Repository navigation
Dashboard metric tiles size to their content: a single-number tile is not 135 px tall with an empty lower half #12704
Description
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
- 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: stretchwithin the row only). - A tile with a sparkline or a delta keeps the extra line; a bare number tile is 88–96 px.
- Light and dark unchanged otherwise.
File surface
packages/plugin-dashboard/src/ (the metric tile and the dashboard grid row), tests beside.
Acceptance
- Tests: a bare metric tile renders at or under 96 px; a tile with a delta line renders taller.
- Screenshots of Sales Performance and System Overview at 1024 and 1280 px.
pnpm --filter @object-ui/plugin-dashboard testgreen.
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
objectstack-fleet commentedon Oct 16, 2026
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-dashboardto 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 declarescolumns) gives every row a floor of 5rem and lets each widget span the rows its authoredlayout.hnames.MetricCardfills its box (h-full). The empty lower half is therefore the second authored row, not a CSS height in the tile.Governing text.
packages/spec/src/ui/dashboard.zod.tsonmainfd0e72abc, the widgetlayoutbox: "the dashboard grid sizes bycolumns+gapon 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 (theminW/maxW/minH/maxHguidance lines; control:h: z.number(), 1 hit, same file).DashboardRenderer.tsxonmain80863adea: "minmax(5rem, auto)gives each spanned row a floor (sogridRow: 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).Protocol: no
packages/specchange in A, B or D. A changes how the renderer reads an authored key; B changes shipped metadata only.Premises, with re-check:
packages/platform-objects/src/apps/dashboards/system_overview.dashboard.tsatfd0e72abc: 6type: 'metric'widgets, every oneh: 2; the charts areh: 4.63db83e2d: 29type: 'metric'widgets acrosssrc/sales/dashboards/{sales,executive,crm,activity}.dashboard.ts,shared-widgets.tsandsrc/service/dashboards/service.dashboard.ts. 27 of the 28 with an inline layout areh: 2, and 2 inactivity.dashboard.tsareh: 4.MetricCardish-full:git grep -n 'cn("h-full", METRIC_TILE_CONTAINER_CLASS' 80863adea -- packages/plugin-dashboard/src/MetricCard.tsx→ 1 hit.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.layout.h,按内容定高h: 4想要大卡的domain:ui· 1 张卡,DashboardRenderer按组件类型改跨行规则 · 无先例h: 1h: 2的第三方仪表盘照旧h翻倍业务含义:
四轴(业务立场):
columns和组件的{x, y, w, h}定尺寸。A 给指标卡开一个例外,同一个h在图表上算数、在指标卡上不算数,以后每种组件都可能要一个例外。Salesforce 和 HubSpot 的仪表盘也是作者定格子大小,平台不替作者改。h在指标卡上静默失效。AI 写h: 4想要大卡,得到的是小卡,没有任何报错,正是「声明了但不兑现」。B 下写什么得什么:AI 写错了,渲染出来一眼就能看到。推荐: B;回退: D。 置信缺口:席位没有实时渲染
h: 1的指标卡来确认它落在 88–96 px(带变化值那一行的卡会更高);这一步作为 B 下 objectui 回归测试的第一步实测。席位也没有查到 Studio 仪表盘设计器新建指标卡时默认给几行;如果默认是 2,B 还需要一处默认值修改。自检:只看①选 B;②③④ 是否翻转:否。
os-decision-facets
{x, y, w, h}定尺寸;A 给指标卡开按组件类型的例外。h静默失效(声明不兑现);B 写什么得什么,错了一眼可见。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:
packages/platform-objects, System Overview's 6 metric tiles toh: 1) and one hotcrm card (27 metric tiles toh: 1, the 2 deliberateh: 4tiles 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.hsays, and records thathno longer binds metric tiles.needs-user-decisionin the same write as the ruling record.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
更正 — HotCRM 指标卡计数 · 2026-10-16T19:17Z
上一条决策记录
6222913929里 HotCRM 的数字写错了,更正如下(hotcrm63db83e2d):type: 'metric'共出现 30 次,其中 1 次是shared-widgets.ts里的共享组件定义,不是一张独立的卡。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
objectstack-fleet commentedon Oct 17, 2026
席位意见(增量)· director seat (summon #43 continuation 3,
session_01QJC7i981TSs9L1CGJK59Ax), read as batch #358 item 4, 2026-10-17T01:06ZOn the
domain:uiseat's decision record 6222913929 with its correction 6222939154 (B recommended: fix the authoredlayout.h; A: the renderer ignoreshon metric tiles; C: halve the row unit; D: nothing).Premises re-run in this act — objectstack
origin/mainbe076dad28a0, objectuid0a00d795020, hotcrm4f82b8152805: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.packages/plugin-dashboard/src/DashboardRenderer.tsx:gridAutoRows: 'minmax(5rem, auto)'1 hit;MetricCard.tsxcn("h-full", METRIC_TILE_CONTAINER_CLASS1 hit — a tile fills the rows itshspans, and a one-row tile grows from 80 px to its content. Holds.packages/platform-objects/src/apps/dashboards/system_overview.dashboard.ts: 6type: 'metric'widgets, allh: 2. Holds. hotcrmsrc/**: 30type: 'metric'occurrences, the seat's corrected reading (1 shared definition, 27 inline layouts of which 25h: 2and 2h: 4, the rest through helper parameters). Holds.packages/plugin-designer/src/DashboardEditor.tsx:792—addWidgetgives every new widgetlayout.h: 1. Closed: B needs no designer change.hon 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
hinert 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 HotCRMh: 2metric tile show a half-empty box at 1024 px today · ③ agree — under B a wronghis visible at once; under A a model that writesh: 4for 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:
h: 2→h: 1(platform-objects,Clause-②: no). hotcrm: everyh: 2metric tile, inline or through a helper parameter, →h: 1; the 2 deliberateh: 4tiles inactivity.dashboard.tsstay.premise_still_valid: falsereport (a one-row tile not landing in 88–96 px) comes back to this box, not to A.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 leavesneeds-user-decision→pm:queuewith aRuled:line carrying the re-scope above (domain:ui,area:reports,priority:p2already on it). If A: this cardpm:queueas written, with the record thathno longer binds metric tiles. If D: closesnot_planned.os-decision-facets
h声明了却不兑现,正是 ADR-0078 禁止的「静默失效」,还会按组件类型一个个开例外。h: 2指标卡,1024 px 下今天就是半截空白。h: 4要大卡,得到小卡,没有报错。自检:只看①选 B;②③④ 是否翻转:否。
objectstack-fleet commentedon Oct 17, 2026
Ruling: batch #358 item 4 · letter B · maintainer 「12704 同意」 2026-10-17T01:29Z
Director seat, summon #43 continuation 3,
session_01QJC7i981TSs9L1CGJK59Ax, on thedomain:uiseat's decision record 6222913929 with its correction 6222939154 (recommendation B, fallback D), the director delta 6227753594 and the premise re-run on objectstackorigin/mainbe076dad28a0, objectuid0a00d795020and hotcrm4f82b8152805(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.his corrected):packages/platform-objects/src/apps/dashboards/system_overview.dashboard.ts) goh: 2→h: 1;Clause-②: no.h: 2, inline or through a helper parameter, goes toh: 1; the 2 deliberateh: 4tiles insrc/sales/dashboards/activity.dashboard.tsstay.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) andMetricCardare unchanged; nopackages/specchange. The designer's default (packages/plugin-designer/src/DashboardEditor.tsx:792,h: 1) needs no change.premise_still_valid: falseand comes back to this box (letter D is the recorded fallback); letter A — the renderer ignoringhon metric tiles — is not taken, as ADR-0078's silently-inert class.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; objectuidomain: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 theRuled:line in its body and leavesneeds-user-decisionforpm:queuein the same act (domain:ui,area:reports,priority:p2already on it); its screenshot step waits for the two metadata cards.5 remaining items
objectstack-fleet commentedon Oct 17, 2026
席位意见(增量)· director seat (summon #43 continuation 3,
session_01QJC7i981TSs9L1CGJK59Ax), read as batch #359 item 1, 2026-10-17T03:01ZOn the
domain:uiseat's re-opened record 6228522945 (B′ recommended, D the fallback, E not), after the dev'spremise_still_valid: falsereport 6228515130 fired ruling B's carried fallback (6227971389 item 4).Premises re-run in this act — objectui
origin/main0812a190f69f, objectstackbe076dad28a0, hotcrm4f82b8152805:h: 2control 176 px. The 88–96 px band in the card's Target was the filer's estimate, not a measured ask. Holds as reported.packages/plugin-dashboard/src/DashboardRenderer.tsx:697–:700: a layout-less widget on acolumnsdashboard getsfallbackSpan{ 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:792gives a new widgeth: 1. Two defaults for one thing. Holds.e2e/sidebar-offcanvas-geometry.spec.tsandpackages/plugin-dashboard/src/__tests__/metricTileLayout-12623.test.tsxexist — the two shapes a pin can take. Holds.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:
sidebar-offcanvas-geometry.spec.tsmeasuring the three cases on a stubbed dashboard, or the__tests__shape if the dev shows a layout engine is not needed; apremise_still_valid: falseon the stub cost (a server is unavoidable) falls back to D with no new box visit.fallbackSpanfor a metric on acolumnsdashboard becomesh: 1(DashboardRenderer.tsx:698), matching the designer; the grid rule (minmax(5rem, auto),span h),MetricCardand the tile padding stay as ruling B bound.Clause-②: no(no exported type or prop moves; a patch changeset for@object-ui/plugin-dashboardfor the default).Workload: B′ =
domain:ui· this card, 1 PR (one spec + one line) · precedentsidebar-offcanvas-geometry.spec.ts. D = none. E = 1 PR and a re-ruling.Execution if B′: this card leaves
needs-user-decision→pm:queuewith a secondRuled:line carrying the acceptance above; the ui seat re-dispatches on the existing branch. If D: this card closescompletedwith the two metadata cards as the whole fix. If E: back to the box with a new record.os-decision-facets
自检:只看①选 B′;②③④ 是否翻转:否(④ 嫌贵时回退 D,不翻字母)。
objectstack-fleet commentedon Oct 17, 2026
Ruling: batch #359 item 1 · letter B′ · maintainer 「同意」 2026-10-17T03:25Z
Director seat, summon #43 continuation 3,
session_01QJC7i981TSs9L1CGJK59Ax, on thedomain:uiseat'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 objectuiorigin/main0812a190f69f(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):
e2e/sidebar-offcanvas-geometry.spec.tsmeasuring the three cases on a stubbed dashboard, or thepackages/plugin-dashboard/src/__tests__/shape if the dev shows no layout engine is needed.fallbackSpanfor a layout-less metric on acolumnsdashboard becomesh: 1(DashboardRenderer.tsx:698), the designer's default (DashboardEditor.tsx:792); the grid rule (minmax(5rem, auto),span h),MetricCardand the tile padding stay as ruling B (6227971389) bound.Clause-②: no; apatchchangeset for@object-ui/plugin-dashboard.premise_still_valid: falseon 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) · precedentsidebar-offcanvas-geometry.spec.ts.Execution: this card leaves
needs-user-decision→pm:queuewith a secondRuled:line; thedomain:uiseat re-dispatches onclaude/issue-12704-metric-tile-height-pin.objectstack-fleet commentedon Oct 17, 2026
Claim: PM loop round 3 · re-dispatch under ruling B′ (
priority:p2; the maintainer's 「同意」 on the re-opened decision6228522945, ruling6229016120: the measured acceptance, one geometry pin, the layout-less metric defaulth: 1)Session:
session_01SJn1GEkrbbBQkhGC26wEDwAccount:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-12704-metric-tile-height-pinWorktree:
objectui-issue-12704(in the cloud session's own container)Domain:
domain:uiSeat:
domain:ui#4File surface: one geometry pin, a spec in
e2e/besidesidebar-offcanvas-geometry.spec.ts(or a test underpackages/plugin-dashboard/src/__tests__/if the dev shows no layout engine is needed) and its stubbed fixture;packages/plugin-dashboard/src/DashboardRenderer.tsx(the onefallbackSpandefault, about :698: a layout-less metric on acolumnsdashboard getsh: 1); tests beside it; one.changeset/12704-*.md(@object-ui/plugin-dashboardpatch). ⛔ The grid rule (minmax(5rem, auto),span h),MetricCard.tsx, the tile padding andpackages/plugin-designer/src/DashboardEditor.tsxstay 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/i18nkey moves.Responsibility: n/a — a ruled regression pin and default
Thread-read: 6229016120
Serial constraints cleared: no open objectui PR touches
plugin-dashboardore2e/(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 reportspremise_still_valid: false, and the card closes under letter D with no new decision.objectstack-fleet commentedon Oct 17, 2026
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 returnedpr: null). The seat opened #12857 fromclaude/issue-12704-metric-tile-height-pinata20446aand setprabove. 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
fix(plugin-dashboard): a layout-less metric tile spans one row, and a…
objectstack-fleet commentedon Oct 17, 2026
Landed · PR #12857 merged as
db4417eonmain· read 2026-10-17T04:56Zorigin/maindb4417efallbackSpaninpackages/plugin-dashboard/src/DashboardRenderer.tsxh: isMetricSpan ? 1 : 4(:701)minmax(5rem, auto)MetricCard.tsx,DashboardEditor.tsx,packages/components/src/ui/**4b3d6ede2e/dashboard-metric-tile-height.spec.tsBuild & E2Eran it green on the PR heada20446aDashboardRenderer.metricFallbackSpan-12704.test.tsx.changeset/12704-metric-tile-one-row-default.md@object-ui/plugin-dashboardpatchclaude/issue-12704-evidence-2(e1483b8)State change: the card closed as completed through
Fixes #12704, andpm:dispatchedis removed in this act. The cloud sessionsession_01BxWPtU5qnbTX3RoZJqNSzais archived.Records of this card:
6229016120(B′);6229218246;6229683847;6229688574;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