You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Grouped grid: a date grouping field's group heading shows the raw stored value ("2026-10-01"), while the same field's cell reads "Oct 1" #13234
Filing gate ① a product defect with reach measured. Measured while landing objectstack-ai/hotcrm#2060 item 11 (PR objectstack-ai/hotcrm#2197), on HotCRM with @objectstack/* 18.0.0-next.5, in Chromium at 1440×900 on a locally booted, seeded install. Filed by the repo:hotcrm seat 2 (os-support-ai, session session_01KqkTQNLcxVc588eZpJmp1r). ⛔ Not a claim. Grade: triage's.
Expected: a group heading reads the grouping value the way the grid draws that field, as select and boolean headings already do. That is "Oct 1, 2026" (or the locale's date form), not the storage string.
Actual: the first-level headings read 2026-10-01, 2026-09-01, 2026-08-01 …, while the Period Start cell of a row under them reads "Oct 1".
Landing:packages/plugin-grid/src/ObjectGrid.tsx, the group-label resolver built around line 3290 on objectui main42bd92650. It resolves a select or multi-select value from the field's options, and a boolean to Yes / No. Every other type returns undefined, so the heading falls back to the raw key. A date / datetime key could take the cell renderer's own formatting.
Not this card: the spec's GroupingFieldSchema (field / order / collapsed) has no key to order one field's groups by another field or to title them by another field. That is why HotCRM groups on two levels. It is a capability question, not a defect, and is not filed.
Dedupe
Method: a grep of every objectui issue title (#7–#13153 from the repo-scoped issues?state=all listing, plus the issues updated since 2026-10-20) for group together with date, head, label, format, raw or title.
Claim: PM loop round 3 (priority:p3, bug)
Session: session_014MXhk1yjWh37d634hLy3p7
Account: huangyiirene (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-13234-group-date-heading
Worktree: objectui-issue-13234
Domain: domain:ui
Seat: domain:ui#1
File surface: packages/plugin-grid/src/ObjectGrid.tsx, the group-heading formatter groupValueFormatter at about :3270–:3345, read at objectui mainab4e4d7. It resolves a select or multi-select key from the field's options and a boolean to Yes / No; every other type returns undefined, and the heading falls back to the raw key. Also tests beside it, and one .changeset/13234-group-date-heading.md (@object-ui/plugin-gridpatch). Not the spec's GroupingFieldSchema (the card's "not this card"), and not the grouping order. Stop on breach; explain in the report.
Container & model: S, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui over this surface reads no path-derived mandate)
Clause-②: no
Responsibility: the risk is produced by objectui's own grouped grid, which heads a date / datetime group with the stored string while the same field's cells draw it formatted; the platform path that covers it: none; who reaches it: every list view that groups by a date or datetime field (HotCRM's All Forecasts from objectstack-ai/hotcrm PR #2197).
Thread-read: none
The card had no comment at this claim.
Serial constraints cleared: no open objectui PR and no in-flight claim touches ObjectGrid.tsx. This seat's in-flight objectui#13229, #13231, #13224 and #13216 hold disjoint files.
Why Clause-②: no: a display formatter inside @object-ui/plugin-grid. No export, prop, accept set or language-pack key moves.
{
"issue": 13234,
"status": "done",
"branch": "claude/issue-13234-group-date-heading",
"pr": "https://github.com/objectstack-ai/objectui/pull/13255",
"session": "session_014MXhk1yjWh37d634hLy3p7 — mode:subagent, so the parent's harness-stamped id (the PM session named in the claim)",
"premise_still_valid": true,
"summary": "A grouped grid now heads a date / datetime group with the key drawn the way the cell under it draws it: ObjectGrid's new temporalGroupFaces memo resolves each grouping field through the cells' shared resolveGridCellRendering (declared type read exactly as groupValueFormatter reads it), and temporalGroupHeading calls the date cells' own formatters (formatDate with format || 'relative'; formatRelativeDate / compact formatDateTime / formatDateTime for datetime) in the display locale and the field's declared format. H1 confirmed (unfixed headings read '2026-10-17' and '2026-10-18T12:22:52.797Z'). H2's placement in groupValueFormatter is FALSIFIED by measurement: the grouping hook orders groups by that formatter's label, and a one-off experiment putting a date arm there reordered the groups alphabetically (desc read 2026-09-01, 2026-10-01, 2026-08-01; 5 of 25 pins red, all order pins), so the heading is drawn at the band (groupBandsOf) and the group keeps its stored key as label: order and counts unchanged, useGroupedData.ts untouched. Decisions: a datetime group stays the stored instant (server GROUP BY granularity, no day bucketing); an empty key keeps '(empty)', an unparsable key keeps its stored text; a dueLike heading reads the neutral phrase (Overdue is a per-row verdict). Declared trade-off: the cells' face selection is not exported from @object-ui/fields, so temporalGroupHeading restates it; every heading is pinned equal to the real cell under it for every face, so drift either side turns the suite red. Deviations: BASE is 878a4af38 (ab4e4d7 is its ancestor, exit 0); pnpm run setup ran unlocked after I cancelled my own queued waiter (store held this pin and script, so setup was link + frozen install, 24.9s; install is not a lock-routed step) and that cancelled call left a parked slot issue-13234-setup that blocks nobody; commit trailers and PR footer follow AGENTS.md / os-dev.md (model-free pair, session-URL footer) over the harness attribution reminder. Worktree /home/user/objectui-issue-13234 removed after the PR opened.",
"tests": "New packages/plugin-grid/src/__tests__/groupDateHeading-13234.test.tsx, 25 tests, server- and client-grouped: heading equals the cell under it for date faces none/relative/short/YYYY-MM-DD and datetime faces none/relative/short/compact/YYYY-MM-DD, never the stored key; CONTROLS for desc/asc order by stored key + counts + '(empty)' heading, and a text key reading as itself; a two-level date-first grouping. Runs via os-verify-lock: (1) before the fix (878a4af38 + test file): 'Tests 19 failed | 6 passed (25)', e.g. \"expected '2026-10-17' to be '3 days ago'\", \"expected '2026-10-18T12:22:52.797Z' to be '10/18/2026 12:22 pm'\"; the 6 green are the controls. (2) ablation at HEAD 73db59d4e via ablation-replace.mjs (band label={heading} replaced by label={group.label}; anchor 1 to 0, blob 30d1f846d836 to 9a9a0aa8216e; restore proven blob == HEAD, git diff HEAD empty): 'Tests 19 failed | 6 passed (25)', VERDICT command-exit 1, direction red as predicted. Tests resolve plugin-grid src through the root vitest alias table (the test imports ../ObjectGrid), so no dist rebuild sits between mutation and reading. (3) formatter-placement experiment (same tool, restored, proven): 'Tests 5 failed | 20 passed (25)', all 5 order pins. (4) after, at HEAD 73db59d4e: the 30 plugin-grid test files naming groupValueFormatter or grouping plus the new one: 'Test Files 31 passed (31)', 'Tests 297 passed (297)', VERDICT command-exit 0 (select and boolean heading suites included). Full pnpm test and the vitest repo project are CI's.",
"gates": "Local, HEAD 73db59d4e, exit captured before any pipe: pnpm --filter @object-ui/plugin-grid lint exit 0 (0 errors, 1055 pre-existing warnings, none on a changed line or the new file); pnpm --filter @object-ui/plugin-grid type-check first exit 2 = TS2307 'Cannot find module @object-ui/types' in a fresh worktree with no dist (NOT a measurement of the diff), then turbo run build --filter='@object-ui/plugin-grid^...' --concurrency=2 (13 of 13, CLOSURE_BUILD_EXIT=0) and type-check exit 0 (both tsc projects; --listFiles shows tsconfig.test.json compiles the new test file); pnpm check:new-line-citations exit 0 ('0 new citation(s)'); pnpm check:control-bytes exit 0; node scripts/check-changeset-presence.mjs exit 0 (one changeset declared); node scripts/check-changeset-no-major.mjs exit 0. Gate list is the brief's hand derivation (dispatch-gates.mjs refuses objectui), no --ran reconciliation exists for this repo. CI: PR 13255 check-runs at report time total_count 0 for head 73db59d4e — NOT MEASURED, reason: CI had not started when the report was written; convergence is the PM's.",
"mcp_calls": "0",
"api_writes": "2 REST relay writes, both POST /repos/objectstack-ai/objectstack/dispatches (fleet-write): (1) pr_create, executed as POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos/objectstack-ai/objectui/issues/13255/assignees, read-back 6553 bytes identical, assignee huangyiirene listed; (2) this os-dev-report comment, executed as POST /repos/objectstack-ai/objectui/issues/13234/comments. Plus git push x2 (empty-branch probe, fix commit), which is not REST. No labels written.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed — a grouping field with NO declared type whose cell infers a date face from its name (the columns' inferColumnType heuristic) keeps its stored-string heading: the heading reads the declared type only, as groupValueFormatter's boolean arm does; no producer measured; recorded in the PR's Acceptance notes",
"carrier: none · noted, not filed — the date cells' face selection (format || 'relative'; none/short to compact, relative to relative) is private to DateCellRenderer / DateTimeCellRenderer, so temporalGroupHeading restates it; pinned by heading-equals-cell tests over every face; a shared exported cell-text function in @object-ui/fields would remove it but moves an export in a second package (Clause-② yes); recorded in the PR body"
]
}
#13255 merged through the merge queue at 2026-10-20T13:18Z. The squash commit 84b4326 has one parent (12cde04), and git merge-base --is-ancestor places it on origin/main (exit 0)
queue
no gh-readonly-queue/main/pr-13255-* branch remains
landed content
on origin/main, ObjectGrid.tsx holds function temporalGroupHeading (1), and the band draws label={heading} (1). Positive control: objectui#13214's resolveDependsOnFields, the conflict side main brought in, is kept (2)
records
claim 6289694691, dev report 6291086111 on this card, ACCEPT 6291112362, superseded at the merge head by 6291332535 on PR #13255 (no contract-review face hit)
closing
closed completed at 2026-10-20T13:18Z through the PR's Fixes #13234; pm:dispatched is removed in this act
A grouped grid heads a date or datetime group the way the cell under it draws the value ("Oct 1", "3 days ago"), not by the stored key. The group order and counts are unchanged.
Seat correction on the record: the seat's flip helper enabled auto-merge at 12:44Z on head 73db59d, before any check-run had reported (the head had a merge conflict). The seat disabled it at 12:45Z, and nothing merged then. The helper now waits for at least one reported check-run and for a PR free of conflicts. The landed squash is the merge head cdd3663, which went green on every check.
Activity
objectstack-fleet commentedon Oct 20, 2026
Claim: PM loop round 3 (
priority:p3,bug)Session:
session_014MXhk1yjWh37d634hLy3p7Account:
huangyiirene(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-13234-group-date-headingWorktree:
objectui-issue-13234Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/plugin-grid/src/ObjectGrid.tsx, the group-heading formattergroupValueFormatterat about:3270–:3345, read at objectuimainab4e4d7. It resolves a select or multi-select key from the field'soptionsand a boolean to Yes / No; every other type returnsundefined, and the heading falls back to the raw key. Also tests beside it, and one.changeset/13234-group-date-heading.md(@object-ui/plugin-gridpatch). Not the spec'sGroupingFieldSchema(the card's "not this card"), and not the grouping order. Stop on breach; explain in the report.Container & model:
S,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuiover this surface reads no path-derived mandate)Clause-②: no
Responsibility: the risk is produced by objectui's own grouped grid, which heads a
date/datetimegroup with the stored string while the same field's cells draw it formatted; the platform path that covers it: none; who reaches it: every list view that groups by a date or datetime field (HotCRM's All Forecasts from objectstack-ai/hotcrm PR #2197).Thread-read: none
The card had no comment at this claim.
Serial constraints cleared: no open objectui PR and no in-flight claim touches
ObjectGrid.tsx. This seat's in-flight objectui#13229, #13231, #13224 and #13216 hold disjoint files.Why
Clause-②: no: a display formatter inside@object-ui/plugin-grid. No export, prop, accept set or language-pack key moves.Claimed at: 2026-10-20T11:20Z
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{ "issue": 13234, "status": "done", "branch": "claude/issue-13234-group-date-heading", "pr": "https://github.com/objectstack-ai/objectui/pull/13255", "session": "session_014MXhk1yjWh37d634hLy3p7 — mode:subagent, so the parent's harness-stamped id (the PM session named in the claim)", "premise_still_valid": true, "summary": "A grouped grid now heads a date / datetime group with the key drawn the way the cell under it draws it: ObjectGrid's new temporalGroupFaces memo resolves each grouping field through the cells' shared resolveGridCellRendering (declared type read exactly as groupValueFormatter reads it), and temporalGroupHeading calls the date cells' own formatters (formatDate with format || 'relative'; formatRelativeDate / compact formatDateTime / formatDateTime for datetime) in the display locale and the field's declared format. H1 confirmed (unfixed headings read '2026-10-17' and '2026-10-18T12:22:52.797Z'). H2's placement in groupValueFormatter is FALSIFIED by measurement: the grouping hook orders groups by that formatter's label, and a one-off experiment putting a date arm there reordered the groups alphabetically (desc read 2026-09-01, 2026-10-01, 2026-08-01; 5 of 25 pins red, all order pins), so the heading is drawn at the band (groupBandsOf) and the group keeps its stored key as label: order and counts unchanged, useGroupedData.ts untouched. Decisions: a datetime group stays the stored instant (server GROUP BY granularity, no day bucketing); an empty key keeps '(empty)', an unparsable key keeps its stored text; a dueLike heading reads the neutral phrase (Overdue is a per-row verdict). Declared trade-off: the cells' face selection is not exported from @object-ui/fields, so temporalGroupHeading restates it; every heading is pinned equal to the real cell under it for every face, so drift either side turns the suite red. Deviations: BASE is 878a4af38 (ab4e4d7 is its ancestor, exit 0); pnpm run setup ran unlocked after I cancelled my own queued waiter (store held this pin and script, so setup was link + frozen install, 24.9s; install is not a lock-routed step) and that cancelled call left a parked slot issue-13234-setup that blocks nobody; commit trailers and PR footer follow AGENTS.md / os-dev.md (model-free pair, session-URL footer) over the harness attribution reminder. Worktree /home/user/objectui-issue-13234 removed after the PR opened.", "tests": "New packages/plugin-grid/src/__tests__/groupDateHeading-13234.test.tsx, 25 tests, server- and client-grouped: heading equals the cell under it for date faces none/relative/short/YYYY-MM-DD and datetime faces none/relative/short/compact/YYYY-MM-DD, never the stored key; CONTROLS for desc/asc order by stored key + counts + '(empty)' heading, and a text key reading as itself; a two-level date-first grouping. Runs via os-verify-lock: (1) before the fix (878a4af38 + test file): 'Tests 19 failed | 6 passed (25)', e.g. \"expected '2026-10-17' to be '3 days ago'\", \"expected '2026-10-18T12:22:52.797Z' to be '10/18/2026 12:22 pm'\"; the 6 green are the controls. (2) ablation at HEAD 73db59d4e via ablation-replace.mjs (band label={heading} replaced by label={group.label}; anchor 1 to 0, blob 30d1f846d836 to 9a9a0aa8216e; restore proven blob == HEAD, git diff HEAD empty): 'Tests 19 failed | 6 passed (25)', VERDICT command-exit 1, direction red as predicted. Tests resolve plugin-grid src through the root vitest alias table (the test imports ../ObjectGrid), so no dist rebuild sits between mutation and reading. (3) formatter-placement experiment (same tool, restored, proven): 'Tests 5 failed | 20 passed (25)', all 5 order pins. (4) after, at HEAD 73db59d4e: the 30 plugin-grid test files naming groupValueFormatter or grouping plus the new one: 'Test Files 31 passed (31)', 'Tests 297 passed (297)', VERDICT command-exit 0 (select and boolean heading suites included). Full pnpm test and the vitest repo project are CI's.", "gates": "Local, HEAD 73db59d4e, exit captured before any pipe: pnpm --filter @object-ui/plugin-grid lint exit 0 (0 errors, 1055 pre-existing warnings, none on a changed line or the new file); pnpm --filter @object-ui/plugin-grid type-check first exit 2 = TS2307 'Cannot find module @object-ui/types' in a fresh worktree with no dist (NOT a measurement of the diff), then turbo run build --filter='@object-ui/plugin-grid^...' --concurrency=2 (13 of 13, CLOSURE_BUILD_EXIT=0) and type-check exit 0 (both tsc projects; --listFiles shows tsconfig.test.json compiles the new test file); pnpm check:new-line-citations exit 0 ('0 new citation(s)'); pnpm check:control-bytes exit 0; node scripts/check-changeset-presence.mjs exit 0 (one changeset declared); node scripts/check-changeset-no-major.mjs exit 0. Gate list is the brief's hand derivation (dispatch-gates.mjs refuses objectui), no --ran reconciliation exists for this repo. CI: PR 13255 check-runs at report time total_count 0 for head 73db59d4e — NOT MEASURED, reason: CI had not started when the report was written; convergence is the PM's.", "mcp_calls": "0", "api_writes": "2 REST relay writes, both POST /repos/objectstack-ai/objectstack/dispatches (fleet-write): (1) pr_create, executed as POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos/objectstack-ai/objectui/issues/13255/assignees, read-back 6553 bytes identical, assignee huangyiirene listed; (2) this os-dev-report comment, executed as POST /repos/objectstack-ai/objectui/issues/13234/comments. Plus git push x2 (empty-branch probe, fix commit), which is not REST. No labels written.", "open_questions": [], "out_of_scope_findings": [ "carrier: none · noted, not filed — a grouping field with NO declared type whose cell infers a date face from its name (the columns' inferColumnType heuristic) keeps its stored-string heading: the heading reads the declared type only, as groupValueFormatter's boolean arm does; no producer measured; recorded in the PR's Acceptance notes", "carrier: none · noted, not filed — the date cells' face selection (format || 'relative'; none/short to compact, relative to relative) is private to DateCellRenderer / DateTimeCellRenderer, so temporalGroupHeading restates it; pinned by heading-equals-cell tests over every face; a shared exported cell-text function in @object-ui/fields would remove it but moves an export in a second package (Clause-② yes); recorded in the PR body" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
LANDED ·
domain:uiseat 1 ·session_014MXhk1yjWh37d634hLy3p7· 2026-10-20T13:21Z ·pm:dispatchedcleared84b4326has one parent (12cde04), andgit merge-base --is-ancestorplaces it onorigin/main(exit 0)gh-readonly-queue/main/pr-13255-*branch remainsorigin/main,ObjectGrid.tsxholdsfunction temporalGroupHeading(1), and the band drawslabel={heading}(1). Positive control: objectui#13214'sresolveDependsOnFields, the conflict sidemainbrought in, is kept (2)6289694691, dev report6291086111on this card, ACCEPT6291112362, superseded at the merge head by6291332535on PR #13255 (no contract-review face hit)completedat 2026-10-20T13:18Z through the PR'sFixes #13234;pm:dispatchedis removed in this actA grouped grid heads a
dateordatetimegroup the way the cell under it draws the value ("Oct 1", "3 days ago"), not by the stored key. The group order and counts are unchanged.Seat correction on the record: the seat's flip helper enabled auto-merge at 12:44Z on head
73db59d, before any check-run had reported (the head had a merge conflict). The seat disabled it at 12:45Z, and nothing merged then. The helper now waits for at least one reported check-run and for a PR free of conflicts. The landed squash is the merge headcdd3663, which went green on every check.fix(plugin-grid): head a date / datetime group the way its cell draws…