Skip to content

Dashboard metric tiles size to their content: a single-number tile is not 135 px tall with an empty lower half #12704

Closed

Description

@objectstack-fleet

Ruled: 6229016120 · letter B′ · 2026-10-17T03:25Z
Acceptance by the ruling: a one-row metric tile renders at content height with no empty lower half (about 118–125 px for a bare value at 1024–1280 px, taller with a delta line); a two-row tile unchanged (176 px); one geometry pin (beside e2e/sidebar-offcanvas-geometry.spec.ts, or the __tests__ shape if no layout engine is needed); fallbackSpan for a layout-less metric on a columns dashboard becomes h: 1 (DashboardRenderer.tsx:698); the grid rule, MetricCard and the tile padding stay. A stub that needs a running server → premise_still_valid: false → letter D (the two metadata cards are the whole fix).

Ruled: 6227971389 · letter B · 2026-10-17T01:30Z
Re-scoped by the ruling: this card is the objectui regression pin (a one-row metric tile renders at content height, a tile with a delta line taller) plus the live render of a one-row tile as its first step; the metadata corrections are objectstack-ai/objectstack#24126 (System Overview) and objectstack-ai/hotcrm#2135 (HotCRM).

Source

Walked on objectui main efa9cb4fa at 1024 px: Sales Performance (/dashboard/sales_dashboard) draws its four KPI tiles about 135 px tall with the title and the number in the top 60 px and nothing below; Setup › System Overview draws Total Users / Active Sessions / Login Events the same way. After objectui#12623 the title has its own line, which fixed the truncation and left the fixed height.

Target

  1. A metric tile's height follows its content: title line, value line, an optional measure/delta line; min-height 88 px, no fixed height. A dashboard row of tiles aligns on the tallest tile in the row (grid align-items: stretch within the row only).
  2. A tile with a sparkline or a delta keeps the extra line; a bare number tile is 88–96 px.
  3. Light and dark unchanged otherwise.

File surface

packages/plugin-dashboard/src/ (the metric tile and the dashboard grid row), tests beside.

Acceptance

  1. Tests: a bare metric tile renders at or under 96 px; a tile with a delta line renders taller.
  2. Screenshots of Sales Performance and System Overview at 1024 and 1280 px.
  3. pnpm --filter @object-ui/plugin-dashboard test green.

Evidence

Screenshots on the temporary branch claude/console-home-login-design-20261016 of objectstack-ai/objectui (commit 0f4e3f4ee, never merged): r4-sales-performance-tiles.jpg · r4-setup-overview.jpg.

Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff from the 2026-10-16 fourth review: objectui main efa9cb4fa, HotCRM 4f82b815 on platform 18.0.0-next.2, the vite console on :5180 against objectstack dev on :4001, the maintainer's browser pane at 1024 × 768 (dark, en). The maintainer asked for every finding to be filed on the repository it belongs to, verbatim: 「全部立卡,平台问题到 objectui,审计日志核查到 objectstack,HotCRM 转化流程到 hotcrm。」

Activity

  1. added
    enhancementNew feature or request
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:reportsBusiness reporting — dashboards, reports, the numbers a manager reads
    on Oct 16, 2026
  2. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Decision — 指标卡的高度是元数据写的,不是平台写死的 · 2026-10-16T19:16Z

    维护者速读: 本卡要求平台让仪表盘的指标卡(KPI 小卡)按内容自动变矮,去掉下半截空白。席位实测发现:高度不是平台写死的,而是元数据里每张卡都写了 layout.h: 2(占两行网格),平台照做了。HotCRM 的 29 张指标卡里有 27 张写的是 2 行,平台自带的 System Overview 的 6 张也都是 2 行。所以要么平台无视元数据写的行数(A),要么把元数据改成 1 行(B)。席位推荐 B:平台照元数据画,改元数据;1 行的网格本来就会随内容长高,正好落在本卡要的 88–96 px。

    Background. objectui#12704 (filed by the epic PM from the 2026-10-16 fourth review) asks plugin-dashboard to make a metric tile's height follow its content (min 88 px, no fixed height). The seat measured before dispatching. The positioned dashboard grid (a dashboard that declares columns) gives every row a floor of 5rem and lets each widget span the rows its authored layout.h names. MetricCard fills its box (h-full). The empty lower half is therefore the second authored row, not a CSS height in the tile.

    Governing text.

    • objectstack packages/spec/src/ui/dashboard.zod.ts on main fd0e72abc, the widget layout box: "the dashboard grid sizes by columns + gap on the dashboard and this box on the widget", and the box is exactly { x, y, w, h }. Re-check: git grep -n "the dashboard grid sizes by" fd0e72abc -- packages/spec/src/ui/dashboard.zod.ts → 4 hits (the minW/maxW/minH/maxH guidance lines; control: h: z.number(), 1 hit, same file).
    • objectui DashboardRenderer.tsx on main 80863adea: "minmax(5rem, auto) gives each spanned row a floor (so gridRow: span 4 => a real ~20rem box) while still letting taller widgets (tables) grow." Re-check: git grep -n "gridAutoRows: 'minmax(5rem, auto)'" 80863adea -- packages/plugin-dashboard/src/DashboardRenderer.tsx → 1 hit (control: gridRow: \span ${clampedLayout.h}``, 1 hit, same file).
    • AGENTS.md / ADR: none found on metric tile height.

    Protocol: no packages/spec change in A, B or D. A changes how the renderer reads an authored key; B changes shipped metadata only.

    Premises, with re-check:

    • objectstack packages/platform-objects/src/apps/dashboards/system_overview.dashboard.ts at fd0e72abc: 6 type: 'metric' widgets, every one h: 2; the charts are h: 4.
    • hotcrm at 63db83e2d: 29 type: 'metric' widgets across src/sales/dashboards/{sales,executive,crm,activity}.dashboard.ts, shared-widgets.ts and src/service/dashboards/service.dashboard.ts. 27 of the 28 with an inline layout are h: 2, and 2 in activity.dashboard.ts are h: 4.
    • MetricCard is h-full: git grep -n 'cn("h-full", METRIC_TILE_CONTAINER_CLASS' 80863adea -- packages/plugin-dashboard/src/MetricCard.tsx → 1 hit.
    • A 1-row tile is content-sized today: its row is minmax(5rem, auto), so it grows from 80 px to the tile's content (title line, value line, an optional delta line). The seat did not render it live. That is the confidence gap below.
    选项 做什么 用户看到什么 工作量
    A 平台让指标卡无视 layout.h,按内容定高 所有仪表盘的指标卡立刻变矮,包括写了 h: 4 想要大卡的 domain:ui · 1 张卡,DashboardRenderer 按组件类型改跨行规则 · 无先例
    B 平台不动;把内置元数据的指标卡改成 h: 1 System Overview 和 HotCRM 的指标卡变矮;写了 h: 2 的第三方仪表盘照旧 objectstack 1 张卡(platform-objects,6 处)+ hotcrm 1 张卡(27 处);本卡改为在 objectui 加一条「1 行指标卡随内容定高」的回归测试 · 先例:objectui#12623(标题单独一行)
    C 平台把行高单位减半,所有内置元数据的 h 翻倍 视觉不变,但每个第三方仪表盘的图表都会矮一半 三个仓库都要改 · 无先例
    D 维持现状 指标卡下半截空白 无

    业务含义:

    • A 等于不管表格里写了多大的单元格,都按内容挤紧:省事,但写了「这张卡要大」的人会被忽略。
    • B 等于把模板里写错的尺寸改对:平台还是照写的画,写多大就多大。
    • C 等于把整张方格纸换成更细的格子,所有已经画好的图都要重画。

    四轴(业务立场):

    • 项目长远合理性(读数领起): B 守住「元数据写什么,平台就画什么」:协议明确写着网格按仪表盘的 columns 和组件的 {x, y, w, h} 定尺寸。A 给指标卡开一个例外,同一个 h 在图表上算数、在指标卡上不算数,以后每种组件都可能要一个例外。Salesforce 和 HubSpot 的仪表盘也是作者定格子大小,平台不替作者改。
    • 实际业务需求: 有实测拉动。HotCRM 的销售、高管、活动、服务四类仪表盘共 29 张指标卡,System Overview 6 张,1024 px 下都是半截空白。
    • 防 AI 犯错: A 让 AI 写的 h 在指标卡上静默失效。AI 写 h: 4 想要大卡,得到的是小卡,没有任何报错,正是「声明了但不兑现」。B 下写什么得什么:AI 写错了,渲染出来一眼就能看到。
    • 创业阶段不扩散: B 只改元数据,平台零新增;A 加一条按组件类型的渲染规则;C 牵动三个仓库。

    推荐: B;回退: D。 置信缺口:席位没有实时渲染 h: 1 的指标卡来确认它落在 88–96 px(带变化值那一行的卡会更高);这一步作为 B 下 objectui 回归测试的第一步实测。席位也没有查到 Studio 仪表盘设计器新建指标卡时默认给几行;如果默认是 2,B 还需要一处默认值修改。
    自检:只看①选 B;②③④ 是否翻转:否。

    os-decision-facets

    • ① 项目长远合理性:B 守住「平台照元数据画」,协议写明网格按 {x, y, w, h} 定尺寸;A 给指标卡开按组件类型的例外。
    • ② 实际业务拉动:今天就有人看到,HotCRM 29 张、System Overview 6 张指标卡在 1024 px 下半截空白。
    • ③ 防 AI 犯错:A 让 AI 写的 h 静默失效(声明不兑现);B 写什么得什么,错了一眼可见。
    • ④ 创业阶段不扩散:B 只改元数据、平台零新增;A 加一条渲染规则;C 牵动三个仓库。

    Prior rulings read: "metric" + "height" / "layout.h" in objectui docs/adr → 0 hits; objectui#12623 (the title on its own line, landed) is the precedent for fixing tile layout without a spec change; this card has no comments before this record.

    After the ruling:

    • B: the seat files one objectstack card (packages/platform-objects, System Overview's 6 metric tiles to h: 1) and one hotcrm card (27 metric tiles to h: 1, the 2 deliberate h: 4 tiles kept), each through its repo's triage. This card is re-scoped to an objectui regression pin (a 1-row metric tile renders content-height, and a tile with a delta line is taller) plus the designer's default metric height if it is 2. Then it is dispatched when the batch has room.
    • A: the seat dispatches this card as written, with a ruling that a metric tile's row span follows its content whatever h says, and records that h no longer binds metric tiles.
    • D: the seat closes this card as not planned with this record.
    • In every case this card leaves needs-user-decision in the same write as the ruling record.

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    更正 — HotCRM 指标卡计数 · 2026-10-16T19:17Z

    上一条决策记录 6222913929 里 HotCRM 的数字写错了,更正如下(hotcrm 63db83e2d):

    • type: 'metric' 共出现 30 次,其中 1 次是 shared-widgets.ts 里的共享组件定义,不是一张独立的卡。
    • 布局直接写在组件上的有 27 张:25 张 h: 2,2 张 h: 4(都在 activity.dashboard.ts)。
    • 其余的卡通过辅助函数的参数拿布局,例如 avgDealSizeMetricWidget({ x: 9, y: 0, w: 3, h: 2 })。

    推荐不变,仍是 B。B 下 hotcrm 卡的范围相应改为:所有 h: 2 的指标卡(包括通过辅助函数参数传入的)改为 h: 1,2 张 h: 4 保留。


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    席位意见(增量)· director seat (summon #43 continuation 3, session_01QJC7i981TSs9L1CGJK59Ax), read as batch #358 item 4, 2026-10-17T01:06Z

    On the domain:ui seat's decision record 6222913929 with its correction 6222939154 (B recommended: fix the authored layout.h; A: the renderer ignores h on metric tiles; C: halve the row unit; D: nothing).

    Premises re-run in this act — objectstack origin/main be076dad28a0, objectui d0a00d795020, hotcrm 4f82b8152805:

    1. packages/spec/src/ui/dashboard.zod.ts: 「the dashboard grid sizes by」 4 hits — the widget's { x, y, w, h } box is the declared size. Holds.
    2. objectui packages/plugin-dashboard/src/DashboardRenderer.tsx: gridAutoRows: 'minmax(5rem, auto)' 1 hit; MetricCard.tsx cn("h-full", METRIC_TILE_CONTAINER_CLASS 1 hit — a tile fills the rows its h spans, and a one-row tile grows from 80 px to its content. Holds.
    3. packages/platform-objects/src/apps/dashboards/system_overview.dashboard.ts: 6 type: 'metric' widgets, all h: 2. Holds. hotcrm src/**: 30 type: 'metric' occurrences, the seat's corrected reading (1 shared definition, 27 inline layouts of which 25 h: 2 and 2 h: 4, the rest through helper parameters). Holds.
    4. The seat's second gap, the designer default: objectui packages/plugin-designer/src/DashboardEditor.tsx:792 — addWidget gives every new widget layout.h: 1. Closed: B needs no designer change.
    • ADR-0078 (no silently inert metadata) is the governing text the record did not name: under A an authored h on a metric tile would be read and not honoured, with no error — the class ADR-0078 forbids.

    Facets: ① agree with B — the platform draws what the metadata declares; A makes h inert on one widget type (ADR-0078) and invites an exception per type; Salesforce and HubSpot dashboards keep the author's tile size · ② agree — 6 System Overview tiles and every HotCRM h: 2 metric tile show a half-empty box at 1024 px today · ③ agree — under B a wrong h is visible at once; under A a model that writes h: 4 for a big tile gets a small one silently · ④ agree — B is shipped metadata in two repos plus one regression pin; no platform code.

    Recommend B; fallback D. Not A, not C. 口径 for the executors, binding with the letter:

    1. objectstack: System Overview's 6 metric tiles h: 2 → h: 1 (platform-objects, Clause-②: no). hotcrm: every h: 2 metric tile, inline or through a helper parameter, → h: 1; the 2 deliberate h: 4 tiles in activity.dashboard.ts stay.
    2. objectui (this card, re-scoped): one regression pin — a one-row metric tile renders at content height (at or under 96 px for a bare number), a tile with a delta line taller; its first step is the live render the seat did not do; a premise_still_valid: false report (a one-row tile not landing in 88–96 px) comes back to this box, not to A.
    3. Pins: the dashboard grid rule unchanged (minmax(5rem, auto), span h); the acceptance screenshots at 1024 and 1280 px after the two metadata cards land.

    Workload: B = objectstack 1 card (platform-objects, 6 lines) + hotcrm 1 card (metric tiles only) + this card as the pin · precedent objectui#12623. A = domain:ui · 1 card, a per-type renderer rule · no precedent. C = three repos · no precedent. D = none.

    Execution if B: in the ruling act this seat files the objectstack card and the hotcrm card (each to its repo's triage, pm:queue), and this card leaves needs-user-decision → pm:queue with a Ruled: line carrying the re-scope above (domain:ui, area:reports, priority:p2 already on it). If A: this card pm:queue as written, with the record that h no longer binds metric tiles. If D: closes not_planned.

    os-decision-facets

    • ① 项目长远合理性:同意 B —— 平台照元数据画;A 让指标卡上的 h 声明了却不兑现,正是 ADR-0078 禁止的「静默失效」,还会按组件类型一个个开例外。
    • ② 实际业务拉动:同意 —— System Overview 6 张、HotCRM 全部 h: 2 指标卡,1024 px 下今天就是半截空白。
    • ③ 防 AI 犯错:同意 —— B 下写错一眼可见;A 下模型写 h: 4 要大卡,得到小卡,没有报错。
    • ④ 创业阶段不扩散:同意 —— B 只改两个仓库的元数据加一条回归 pin,平台零新增;设计器默认已是 1 行,不用改。

    自检:只看①选 B;②③④ 是否翻转:否。

  5. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #358 item 4 · letter B · maintainer 「12704 同意」 2026-10-17T01:29Z

    Director seat, summon #43 continuation 3, session_01QJC7i981TSs9L1CGJK59Ax, on the domain:ui seat's decision record 6222913929 with its correction 6222939154 (recommendation B, fallback D), the director delta 6227753594 and the premise re-run on objectstack origin/main be076dad28a0, objectui d0a00d795020 and hotcrm 4f82b8152805 (opening marker objectstack-ai/objectstack#12708, comment 6227733044). The maintainer's word in this session's chat: 「12704 同意」 on batch #358.

    What the ruling binds (letter B — the platform draws what the metadata declares; the authored layout.h is corrected):

    1. objectstack: System Overview's 6 metric tiles (packages/platform-objects/src/apps/dashboards/system_overview.dashboard.ts) go h: 2 → h: 1; Clause-②: no.
    2. hotcrm: every metric tile whose layout is h: 2, inline or through a helper parameter, goes to h: 1; the 2 deliberate h: 4 tiles in src/sales/dashboards/activity.dashboard.ts stay.
    3. objectui, this card re-scoped: one regression pin in plugin-dashboard — a one-row metric tile renders at content height (at or under 96 px for a bare number) and a tile with a delta line renders taller; its first step is the live render of a one-row tile that the record did not do. The dashboard grid rule (minmax(5rem, auto), span h) and MetricCard are unchanged; no packages/spec change. The designer's default (packages/plugin-designer/src/DashboardEditor.tsx:792, h: 1) needs no change.
    4. Fallback carried: a one-row tile that does not land in 88–96 px reports premise_still_valid: false and comes back to this box (letter D is the recorded fallback); letter A — the renderer ignoring h on metric tiles — is not taken, as ADR-0078's silently-inert class.
    5. Acceptance after all three land: screenshots of Sales Performance and System Overview at 1024 and 1280 px, as this card's acceptance says.

    Not taken: A (ADR-0078), C (three repos, every third-party chart halved).

    Workload of the letter: objectstack platform-objects · 1 card, 6 lines; hotcrm · 1 card, metric tiles only; objectui domain:ui · this card, one pin · precedent objectui#12623.

    Execution: two execution cards filed in this act — objectstack-ai/objectstack#24126 (domain:engine, p2, pm:queue) and objectstack-ai/hotcrm#2135 (p2, pm:queue). This card is re-scoped by the Ruled: line in its body and leaves needs-user-decision for pm:queue in the same act (domain:ui, area:reports, priority:p2 already on it); its screenshot step waits for the two metadata cards.

  6. 5 remaining items

  7. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    席位意见(增量)· director seat (summon #43 continuation 3, session_01QJC7i981TSs9L1CGJK59Ax), read as batch #359 item 1, 2026-10-17T03:01Z

    On the domain:ui seat's re-opened record 6228522945 (B′ recommended, D the fallback, E not), after the dev's premise_still_valid: false report 6228515130 fired ruling B's carried fallback (6227971389 item 4).

    Premises re-run in this act — objectui origin/main 0812a190f69f, objectstack be076dad28a0, hotcrm 4f82b8152805:

    1. The dev's live render (relayed, not re-run by this seat): a one-row tile is content-sized — 124.38 px at 1280, 117.75 at 1024 for a bare value; 146.38 / 139.88 with a delta line; the h: 2 control 176 px. The 88–96 px band in the card's Target was the filer's estimate, not a measured ask. Holds as reported.
    2. packages/plugin-dashboard/src/DashboardRenderer.tsx:697–:700: a layout-less widget on a columns dashboard gets fallbackSpan { w: 3, h: 2 } when it is a metric, { w: 6, h: 4 } otherwise — the platform's own default is the same half-empty box. packages/plugin-designer/src/DashboardEditor.tsx:792 gives a new widget h: 1. Two defaults for one thing. Holds.
    3. e2e/sidebar-offcanvas-geometry.spec.ts and packages/plugin-dashboard/src/__tests__/metricTileLayout-12623.test.tsx exist — the two shapes a pin can take. Holds.
    4. The metadata halves are filed and queued, not landed: objectstack#24126 (pm:queue), hotcrm#2135 (pm:queue). Holds.

    Facets: ① agree with B′ — what ruling B bound (the platform draws the declared h; the grid rule and the tile chrome unchanged) stands; what fell was a number nobody measured, and the honest correction is to put the measured number in the acceptance, not to bend the renderer to the estimate (E); one default for a layout-less metric (h: 1, the designer's) removes a second answer to the same question · ② agree — the complaint was the empty lower half; one row removes it (176 → 124 px); no user asked for 96 · ③ agree — a geometry pin is what stops a later renderer change from putting the fixed height back silently; D leaves nothing watching · ④ agree, cost named — the pin is one Playwright spec with a stubbed dataset (heavier than the sidebar precedent); the default change is one line; E re-opens ruling B's 「chrome unchanged」 for a number that was never a requirement.

    Recommend B′; fallback D. Not E. 口径 for the executor, binding with the letter:

    1. Acceptance replaces the band: a one-row metric tile renders at content height with no empty lower half (about 118–125 px for a bare value at 1024–1280, taller with a delta line); a two-row tile is unchanged (176 px); rows align on the tallest tile.
    2. The pin: one geometry spec beside sidebar-offcanvas-geometry.spec.ts measuring the three cases on a stubbed dashboard, or the __tests__ shape if the dev shows a layout engine is not needed; a premise_still_valid: false on the stub cost (a server is unavoidable) falls back to D with no new box visit.
    3. fallbackSpan for a metric on a columns dashboard becomes h: 1 (DashboardRenderer.tsx:698), matching the designer; the grid rule (minmax(5rem, auto), span h), MetricCard and the tile padding stay as ruling B bound. Clause-②: no (no exported type or prop moves; a patch changeset for @object-ui/plugin-dashboard for the default).
    4. The screenshot acceptance of Sales Performance and System Overview waits for #24126 and hotcrm#2135, as ruled.

    Workload: B′ = domain:ui · this card, 1 PR (one spec + one line) · precedent sidebar-offcanvas-geometry.spec.ts. D = none. E = 1 PR and a re-ruling.

    Execution if B′: this card leaves needs-user-decision → pm:queue with a second Ruled: line carrying the acceptance above; the ui seat re-dispatches on the existing branch. If D: this card closes completed with the two metadata cards as the whole fix. If E: back to the box with a new record.

    os-decision-facets

    • ① 项目长远合理性:同意 B′ —— 裁决 B 定的「照元数据画、外框不动」不变,改的只是一个没实测过的数字;没写 layout 的指标卡默认改成 1 行,和设计器只剩一个默认。
    • ② 实际业务拉动:同意 —— 抱怨的是半截空白,1 行就去掉了(176 → 124 px);没人要过 96。
    • ③ 防 AI 犯错:同意 —— 量高度的 pin 让以后把死高度改回来的改动立刻报红;D 没人守。
    • ④ 创业阶段不扩散:同意,代价点名 —— 一条带桩的 Playwright 测试加一行默认值;E 为一个估计值动所有卡片外框,还要重裁。

    自检:只看①选 B′;②③④ 是否翻转:否(④ 嫌贵时回退 D,不翻字母)。

  8. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #359 item 1 · letter B′ · maintainer 「同意」 2026-10-17T03:25Z

    Director seat, summon #43 continuation 3, session_01QJC7i981TSs9L1CGJK59Ax, on the domain:ui seat's re-opened record 6228522945 (B′ recommended, D the fallback), the dev's fallback report 6228515130, the director delta 6228803179 and the premise re-run on objectui origin/main 0812a190f69f (opening marker objectstack-ai/objectstack#12708, comment 6227733044). The maintainer's word in this session's chat: 「同意」 on batch #359.

    What the ruling binds (letter B′ — ruling B continues with the measured acceptance; a geometry pin; one default):

    1. Acceptance replaces the 88–96 px band: a one-row metric tile renders at content height with no empty lower half (about 118–125 px for a bare value at 1024–1280 px, taller with a delta line); a two-row tile is unchanged (176 px); rows align on the tallest tile.
    2. The pin: one geometry spec beside e2e/sidebar-offcanvas-geometry.spec.ts measuring the three cases on a stubbed dashboard, or the packages/plugin-dashboard/src/__tests__/ shape if the dev shows no layout engine is needed.
    3. fallbackSpan for a layout-less metric on a columns dashboard becomes h: 1 (DashboardRenderer.tsx:698), the designer's default (DashboardEditor.tsx:792); the grid rule (minmax(5rem, auto), span h), MetricCard and the tile padding stay as ruling B (6227971389) bound. Clause-②: no; a patch changeset for @object-ui/plugin-dashboard.
    4. Fallback carried: if the stub the pin needs costs a running server (a premise_still_valid: false on cost), letter D — this card closes and the two metadata cards (objectstack#24126, hotcrm#2135) are the whole fix — with no new box visit. The screenshot acceptance of Sales Performance and System Overview waits for those two cards, as ruled.

    Not taken: E (the tile chrome changed for an estimated number; re-opens ruling B), D as the first letter (nothing would watch the fixed height).

    Workload of the letter: domain:ui · this card, 1 PR (one spec, one line) · precedent sidebar-offcanvas-geometry.spec.ts.

    Execution: this card leaves needs-user-decision → pm:queue with a second Ruled: line; the domain:ui seat re-dispatches on claude/issue-12704-metric-tile-height-pin.

  9. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 · re-dispatch under ruling B′ (priority:p2; the maintainer's 「同意」 on the re-opened decision 6228522945, ruling 6229016120: the measured acceptance, one geometry pin, the layout-less metric default h: 1)
    Session: session_01SJn1GEkrbbBQkhGC26wEDw
    Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12704-metric-tile-height-pin
    Worktree: objectui-issue-12704 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: one geometry pin, a spec in e2e/ beside sidebar-offcanvas-geometry.spec.ts (or a test under packages/plugin-dashboard/src/__tests__/ if the dev shows no layout engine is needed) and its stubbed fixture; packages/plugin-dashboard/src/DashboardRenderer.tsx (the one fallbackSpan default, about :698: a layout-less metric on a columns dashboard gets h: 1); tests beside it; one .changeset/12704-*.md (@object-ui/plugin-dashboard patch). ⛔ The grid rule (minmax(5rem, auto), span h), MetricCard.tsx, the tile padding and packages/plugin-designer/src/DashboardEditor.tsx stay unchanged, as rulings B and B′ bind. Stop on breach; explain in the report.
    Container & model: M, mode:cloud, model: opus (cloud on the maintainer's stance 「可以的话,ui 后续开发尽量用云 session,并且要求截图给我看」; lane scope on 「你也可以接ui车道的卡」; batch 3 on 「当前任务处理完,后续并发降到3」, this session's chat, 2026-10-16)
    Clause-②: no
    Clause-② reason: a test, its fixture and one renderer default; no exported type, prop or @object-ui/i18n key moves.
    Responsibility: n/a — a ruled regression pin and default
    Thread-read: 6229016120
    Serial constraints cleared: no open objectui PR touches plugin-dashboard or e2e/ (read at dispatch). The metadata halves are objectstack-ai/objectstack#24126 and objectstack-ai/hotcrm#2135; the screenshot acceptance of Sales Performance and System Overview waits for them and is not this PR's. Fallback carried from ruling B′: a stub that needs a running server reports premise_still_valid: false, and the card closes under letter D with no new decision.

  10. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12704,
      "status": "done",
      "branch": "claude/issue-12704-metric-tile-height-pin",
      "pr": 12857,
      "pr_title_draft": "fix(plugin-dashboard): a layout-less metric tile spans one row, and a geometry pin holds one-row tiles at content height (objectui#12704)",
      "pr_body_draft": "(elided here: it is the body of objectstack-ai/objectui#12857, the dev's draft verbatim)",
      "session": "session_01BxWPtU5qnbTX3RoZJqNSza",
      "premise_still_valid": true,
      "summary": "Built under ruling B′.\n- Default: in `DashboardRenderer`, `fallbackSpan` for a layout-less metric on a `columns` dashboard went from `h: 2` to `h: 1`. Non-metric widgets keep `h: 4`. A unit pin and two CONTROLs cover it.\n- Pin: one Playwright geometry spec beside `sidebar-offcanvas-geometry.spec.ts`. It bundles the real `DashboardRenderer` from source with Vite (in memory), mounts it in Chromium with a stub `queryDataset`, and compiles the real theme sheet. No backend is needed, so fallback D does not apply.\n- Readings at 1280: bare h1 = 124.38 px, h1 with delta = 146.38, h2 CONTROL = 176. These equal the previous dev's live console numbers. 1024 gives the same numbers, because the fixture has no sidebar and the tile stays wider than 160 px.\n- All three PM mechanism assumptions held, with one amendment to #3. #1: the `fallbackSpan` line was exactly as quoted. #2: the e2e lane is `pnpm test:e2e --project=chromium` in `Build & E2E`. The lane builds only the console bundle, no workspace `dist/`. #3: `DatasetWidget` fetches in a `useEffect`, so SSR would only show the skeleton. The fixture therefore mounts on the client instead of server-rendering as the precedent does. The data source is still stubbable without a server.\n- Neither metadata card has landed (objectstack `9ffe8af`, hotcrm `4f82b81`: still `h: 2`).",
      "tests": "HEAD a20446a.\n- Pin: CI=1 playwright test, repo config spread, project chromium, executablePath /opt/pw-browsers/chromium; dashboard-metric-tile-height + sidebar-offcanvas-geometry specs. Stats: expected 8, unexpected 0, flaky 0. Readings at both 1280 and 1024: bare 124.38 (slack 25 = chrome 25), delta 146.38 (slack 25 = chrome 25), control 176 (slack 76.63), same-row pair 146.38 / 146.38. Stable over --repeat-each=4 (8 runs, identical).\n- Unit pin DashboardRenderer.metricFallbackSpan-12704.test.tsx: 3 passed.\n- Ablations via objectstack scripts/ablation-replace.mjs; each printed 'ok mutation landed' and 'ok restored: blob == HEAD, git diff HEAD empty':\n  (1) spec: bare case h:1 to h:2. Red, 2 failed (span guard). Re-run on a20446a: red.\n  (2) DashboardRenderer: gridAutoRows 'minmax(5rem, auto)' to 'minmax(12rem, auto)'. Red, 'bare: the one-row box runs 67.63px past its content and padding'. Re-run on a20446a: red.\n  (3) DashboardRenderer: 'h: isMetricSpan ? 1 : 4' to '2 : 4'. Unit pin 1 failed, 2 passed (CONTROLs green): expected 'span 1', received 'span 2'.\n- No dist/ is on either path: the e2e spec bundles src, and vitest aliases src. So no rebuild or dist preflight applied.\n- The first attempt at ablation (1) was VOID: the scratch config could not resolve @playwright/test, so no test ran. I fixed the config and re-ran it. Reported, not counted.",
      "gates": "Local, hand-derived (objectui has no scripts/pm/dispatch-gates.mjs).\n- Verify lock: bash /home/user/objectstack-ai/objectstack/scripts/pm/os-verify-lock.sh, OS_VERIFY_LOCK_SLOT=os-dev-12704.\n- pnpm --filter @object-ui/plugin-dashboard test: VERDICT command-exit 0. 183 files passed, 1814 tests passed, 6 skipped. Ran on b6dfaf0; a20446a changed only the e2e spec (git diff b6dfaf0 HEAD: 1 file).\n- Dependency closure: turbo run build --filter='@object-ui/plugin-dashboard^...' --concurrency=2, 12/12 tasks successful. The lock line read 'batch-last-exit 0' because I joined it with || after a pnpm --filter attempt that failed on build order (data-objectstack). The turbo half is the reading.\n- plugin-dashboard type-check: VERDICT command-exit 0.\n- plugin-dashboard lint: exit 0 (pre-existing warnings, none on changed lines).\n- plugin-dashboard build: VERDICT command-exit 0.\n- pnpm type-check:e2e: exit 0.\n- eslint --no-inline-config on the 3 touched source files: exit 0. The first run caught a no-console error in the spec; fixed in a20446a.\n- vitest scripts/__tests__/e2e-type-check.test.ts: 15/15. It first caught a literal workspace import inside the entry string; fixed in a20446a. check-test-path-roots, select-type-check-scope and dollar-dialect-alias-census tests: passed.\n- pnpm check:test-path-roots: exit 0.\n- pnpm check:new-line-citations: 0 new, exit 0.\n- node scripts/check-changeset-presence.mjs: exit 0.\n- Control-byte scan on the new files: no hits.\n- CI check-runs: NOT MEASURED. No PR is open from this container; the PM opens it.",
      "mcp_calls": "5, all reads, no GitHub write tool: mcp__claude-code-remote__add_repo x2 (objectstack, hotcrm; access read; both answered read_available, nothing attached), ToolSearch x1 to load issue_read, mcp__github__issue_read x2 (get, get_comments) on objectui#12704.",
      "api_writes": "0 REST writes. git push only: claude/issue-12704-metric-tile-height-pin (fast-forward ac5907384 to 4b3d6ed, then b6dfaf0, then a20446a); claude/issue-12704-evidence-2 (e1483b8, new, cut from a20446a, never merged).",
      "screenshots": [
        "https://github.com/objectstack-ai/objectui/blob/e1483b8e5ab88e3c1f019df72f5d04c302bace6f/docs/design/findings/12704/metric-tile-heights-1280-light.png?raw=true",
        "https://github.com/objectstack-ai/objectui/blob/e1483b8e5ab88e3c1f019df72f5d04c302bace6f/docs/design/findings/12704/metric-tile-heights-1024-light.png?raw=true"
      ],
      "files_changed": "Feature branch: e2e/dashboard-metric-tile-height.spec.ts (new); packages/plugin-dashboard/src/DashboardRenderer.tsx (the fallbackSpan default plus its comment); packages/plugin-dashboard/src/__tests__/DashboardRenderer.metricFallbackSpan-12704.test.tsx (new); .changeset/12704-metric-tile-one-row-default.md (patch). All inside the claim's file surface. Evidence branch only: docs/design/findings/12704/metric-tile-heights-{1280,1024}-light.png.",
      "line_budget": "n/a",
      "deviations": [
        "Contract conflict, stated rather than resolved silently. os-dev.md wants a draft PR and an os-dev-report issue comment. This container's write relay is refused (403), as the dispatch's degraded channel says. I followed the dispatch: no PR and no comment. The PR body is in pr_body_draft.",
        "The pin did not run as the literal `pnpm test:e2e --project=chromium`. Playwright 1.62 wants chromium revision 1234; only 1194 is installed at /opt/pw-browsers, and installing is forbidden. I ran a scratch config (scratchpad, not committed) that spreads the repo's playwright.config.ts and keeps the chromium project's Desktop Chrome settings. It adds launchOptions.executablePath and omits the console preview webServer (neither spec uses it). Run with CI=1.",
        "The verify lock came from the read clone at /home/user/objectstack-ai/objectstack/scripts/pm/os-verify-lock.sh. AGENTS.md names /home/user/objectstack.",
        "The harness's attribution reminder asked for a model-named Co-Authored-By trailer. I followed AGENTS.md's model-free pair (Claude-Session plus Co-authored-by: Claude). The scan of git log origin/main..HEAD found no model identifier.",
        "Worktree setup. A local claude/issue-12704-metric-tile-height-pin existed in the shared /home/user/objectui checkout at 4b3d6ed with 0 own commits. I detached that checkout at origin/main and deleted the local branch, then checked out the remote branch (ac5907384) in ../objectui-issue-12704 and fast-forwarded it to origin/main 4b3d6ed. The shared checkout is left at detached HEAD.",
        "The feature worktree ../objectui-issue-12704 is left in place, clean and pushed, because the PR is not opened yet. os-dev.md's cleanup comes after the PR. The evidence worktree is removed. No server or process I started is still running."
      ],
      "open_questions": [
        {
          "question": "The fixture differs from the precedent: client-side mount of a Vite in-memory bundle instead of SSR. DatasetWidget loads in an effect, so SSR shows only the skeleton.",
          "options": [
            "A: keep the client mount (no server, real loading effect).",
            "B: SSR with a prefilled DatasetWidget state, which would need a renderer seam."
          ],
          "recommendation": "A. Recorded as the decision taken, not a blocker. Real need: it measures the tile a metadata dashboard reaches. Long term: no test-only seam in the renderer. AI-error guard: geometry from the real effect path. Startup focus: zero product code added for the test."
        }
      ],
      "out_of_scope_findings": [
        "class: observation (read-only, not reproduced live), noted, not filed · reach: none measured · `defaultWidgetPlacement` in packages/types gives every layout-less widget h:4 in the editable grid (DashboardGridLayout, DashboardWithConfig sliders), metrics included. With this change the read grid gives a layout-less metric 1 row while edit mode gives 4. The renderer comment 'matching the editable DashboardGridLayout's auto-placement' already disagreed on height before this PR (2 vs 4). carrier: none, only in the PR's Acceptance notes · dedupe words: defaultWidgetPlacement h 4 metric, edit-mode layout-less metric height, DashboardGridLayout default placement"
      ]
    }

    Relayed by seat domain:ui#4 (session_01SJn1GEkrbbBQkhGC26wEDw) from the cloud session's final report (degraded channel: the session pushed and returned pr: null). The seat opened #12857 from claude/issue-12704-metric-tile-height-pin at a20446a and set pr above. The open question (a client-side mount instead of the precedent's server render) is ruled in the ACCEPT on the PR.


    Generated by Claude Code

  11. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #12857 merged as db4417e on main · read 2026-10-17T04:56Z

    probe on origin/main db4417e reading control
    fallbackSpan in packages/plugin-dashboard/src/DashboardRenderer.tsx h: isMetricSpan ? 1 : 4 (:701) ruling B′: a layout-less metric spans one row; non-metric widgets keep four
    the grid rule minmax(5rem, auto) unchanged rulings B and B′
    MetricCard.tsx, DashboardEditor.tsx, packages/components/src/ui/** 0 files changed since 4b3d6ed as bound
    e2e/dashboard-metric-tile-height.spec.ts present; Build & E2E ran it green on the PR head a20446a the one geometry pin
    DashboardRenderer.metricFallbackSpan-12704.test.tsx present: the default plus two CONTROLs —
    .changeset/12704-metric-tile-one-row-default.md present: @object-ui/plugin-dashboard patch —
    a model name in the merge commit's message 0 —
    PNG files in the merge's diff 0 the screenshots stay on claude/issue-12704-evidence-2 (e1483b8)

    State change: the card closed as completed through Fixes #12704, and pm:dispatched is removed in this act. The cloud session session_01BxWPtU5qnbTX3RoZJqNSza is archived.

    Records of this card:

    • the maintainer's ruling: 6229016120 (B′);
    • the re-dispatch claim: 6229218246;
    • the report relayed: 6229683847;
    • the ACCEPT: 6229688574;
    • the landing note: 6229739600.

    The metadata halves, objectstack-ai/objectstack#24126 (System Overview) and objectstack-ai/hotcrm#2135 (Sales Performance), stay open and own the screenshot acceptance of those two dashboards, as ruled.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:reportsBusiness reporting — dashboards, reports, the numbers a manager readsdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions