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 }}
Repository navigation
record:line_items column headings cannot be translated: a column label is a plain string, the block does not hydrate from the child field, and no bundle key reaches properties.columns #24140
Filing gate ①: a user-visible gap on a printed document, with a named landing.
reach: the public render path. A record:line_items table, on screen and on a print page, heads its columns in the author's literal label in every locale. A zh-CN (or any non-English) tenant's printed invoice reads English line-item headings under translated section headings.
Filed by the domain:services seat 2 (#21118) · os-elon-musk · session_018VqJPGA1NDNSCZsnecsChP, from PR #24139's ACCEPT. ⛔ Not a claim. Lane, grade and area:* are triage's.
Measured on origin/mainc1c0a90942
The column label is a plain string.InlineGridColumnSchema.label is z.string().optional() (packages/spec/src/data/field.zod.ts, around :971). Its describe says "defaults to the child field's label via hydration".
record:line_items does not hydrate.RecordLineItemsProps.columns (packages/spec/src/ui/component.zod.ts, around :2494) says: "this block does NOT hydrate a column from the child object's field: declare label, type and options yourself". So the shared column schema's own describe is false for this block.
No bundle key reaches a column. The page overlay translates only PAGE_COMPONENT_COPY_KEYS (title, description, label, placeholder, emptyText) on a component's own properties (packages/spec/src/system/i18n-resolver.ts:2119). Nothing translates properties.columns[i].label.
The contrast: the master-detail carriers (inlineColumns) hydrate an identity-only column from the child field. Their headings translate through the existing objects.CHILD.fields.F.label keys.
The options the dev named (for triage and the spec seat to grade)
B. Hydrate.record:line_items fills an identity-only column's label / type / options from the child field, as the master-detail carriers do. Labels then translate with no new translation face. Cost: a widened describe on RecordLineItemsProps.columns (spec), and a renderer change in objectui's LineItemsPanel behind a pin bump.
C. Refuse. Publish refuses a record:line_items column without a label. This is loud, but it translates nothing.
A. Leave it. The describe text is the only warning, and every non-English print keeps English headings.
The seat's reading: the PDF chain is v18 work (「PDF 要赶 18.0 正式版」), and every non-English print of a line-items table is affected. ⛔ The grade and the route are triage's and the spec seat's.
Dedupe
MCP search_issues on objectstack-ai/objectstack, record:line_items column headings translate zh-CN label hydrate from child field → 0 hits.
MCP search_issues on objectstack-ai/objectui, line items grid column header not translatable locale bundle → 6 hits, none covering it. objectui#11145 (closed) covered the line-items chrome strings, not the declared column headings. objectui#12358 (closed) covered list columns' inline locale maps.
Triage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
Why p1 + target:v18: the PDF chain (「PDF 要赶 18.0 正式版」). Every non-English printed line-items table heads its columns in English.
Route B (hydrate), by the governing text, not a decision: the shared column schema already declares it. InlineGridColumnSchema.label's describe reads "defaults to the child field's label via hydration", and the master-detail carriers honour it through objectui's hydrateColumns (packages/plugin-form/src/deriveMasterDetail.ts). record:line_items is the one block that does not. Implementing the declaration beats both refusing (C, which translates nothing) and leaving it (A, a declared behaviour unhonoured).
This card = the spec half:RecordLineItemsProps.columns describe in packages/spec/src/ui/component.zod.ts says the block hydrates an identity-only column (label / type / options from the child field). ⛔ No new key.
Claim: PM loop round 1 · 2026-10-17T14:17Z · the spec half of route B: RecordLineItemsProps.columns says the block hydrates an identity-only column (label / type / options from the child field), as the master-detail carriers do; ⛔ no new key
Session: session_01TyRhWbVbbQpQJTDbW8VahJ (the seat; the dev is an os-dev subagent of this session)
Account: os-project-manager (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-24140-line-items-hydrate-columns
Worktree: objectstack-issue-24140
Domain: domain:spec
Seat: domain:spec#1 (seat post #6017)
File surface (read on origin/mainb0fe9fad47; line numbers move; stop on a breach and explain it in the report):
packages/spec/src/ui/component.zod.ts: RecordLineItemsProps.columns' describe (:2493-:2494, today "this block does NOT hydrate a column from the child object's field").
packages/spec/src/data/field.zod.ts: InlineGridColumnSchema's describes (label:971, type:972) only if they must name record:line_items beside the master-detail carriers to stay true.
The liveness ledger row(s) under packages/spec/liveness/ that cite this describe or the block's columns, and the generated artifacts the spec build regenerates, written by their generators only.
One .changeset/24140-*.md (@objectstack/spec, patch: describe text ships in dist and the JSON Schema).
os-dev-report
{
"issue": 24140,
"status": "done",
"branch": "claude/issue-24140-line-items-hydrate-columns",
"pr": "#24188",
"session": "session_01TyRhWbVbbQpQJTDbW8VahJ — the parent seat's session (this run is an os-dev subagent of it)",
"premise_still_valid": true,
"summary": "RecordLineItemsProps.columns' describe in packages/spec/src/ui/component.zod.ts now states the master-detail carriers' rule in their words: identity-only entries ({ name }) hydrate everything else from the child object's fields, label, type and options included, so the heading is the child field's label and translates with it; declaring type opts a column out. The 'Required, with at least one column' sentence is kept. The RecordLineItemsProps TSDoc is rewritten to match. It names the renderer half (objectui#12854, LineItemsPanel reusing hydrateColumns), the window until the .objectui-sha pin carries it, and the fact that defineStack's collectHydratedInlineColumnErrors walks only the three master-detail carriers. Also in the PR: content/docs/references/ui/component.mdx regenerated (one row) and the changeset .changeset/24140-line-items-columns-hydrate.md (@objectstack/spec patch). field.zod.ts needed no edit: its label/type describes are now true for every carrier. Draft PR #24188 is open, assignee os-project-manager, the body read back byte-identical (10610 bytes). Clause-② line Clause-②: no is at a line start. The worktree is removed.",
"tests": "All at HEAD a66b471. (1) pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 src/inline-grid-column-carriers.test.ts src/ui/component-props-unknown-members.pin.test.ts src/ui/page-print.test.ts: 'Test Files 3 passed (3) / Tests 138 passed (138)', lock VERDICT command-exit 0. (2) pnpm --filter @objectstack/spec test (whole package): 'Test Files 692 passed (692) / Tests 20974 passed | 1 todo (20975)', SPEC_TEST_EXIT=0. (3) pnpm --filter @objectstack/spec typecheck: VERDICT command-exit 0 (tsc --noEmit + check:scripts-typecheck + check:test-typecheck OK). (4) H4 on the built package: spec built at base cb8756b and at a66b471, and a script compared each JSON Schema with descriptions removed. ui/RecordLineItemsProps.json and objectstack.json are structurally identical apart from descriptions; exactly one description path changed in each (/properties/columns and /$defs/ui/RecordLineItemsProps/properties/columns). Every other json-schema file is byte-identical, and authorable-surface/ is byte-identical. Instrument control: RecordHistoryProps vs RecordLineItemsProps reads structure False. inline-grid-column-carriers.test.ts's 'CONTROL — defineStack does not judge an identity-only line-items column' stays green, so the accept/reject results are unchanged. No ablation: no tested behaviour changed (describe text, TSDoc, a regenerated doc and a changeset). test:repo was not run locally; it is CI's Test Core.",
"gates": "Local, at a66b471: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 102 commands over 3 paths (merge base cb8756b). Each was run with its exit code captured before any pipe (redirect, then EXIT=$?). 101 exit 0. Six of those first exited 3 (PREREQUISITE NOT MET) and passed on re-run after a closure build (pnpm --workspace-concurrency=2 --filter '@objectstack/lint...' --filter '@objectstack/client-react...' --filter '@objectstack/objectql...' --filter '@objectstack/formula...' run build, lock VERDICT command-exit 0) and a one-commit fetch of the self-test fixture 621a487: check:doc-formula-expressions, check:doc-security-posture, check:skill-examples, check:docs-transcript-drift, check:lean-entry-closure, check-plugin-teardown-shape --self-test. NOT MEASURED (1): pnpm check:dual-build-cjs-loads, exit 3, because 92 workspace packages have no dist; CI runs it in Lint & Repo Gates. --ran reconciliation: '102 derived famil(ies) accounted for — 101 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)'. check:generated before the regeneration: '✗ 1 of 14 artifact(s) stale: content/docs/references/', regenerated by gen:docs; check:docs is green in the battery. Local-only check:dev-prereqs exit 1 ('34 of 70 workspace packages declare an entry point under dist/ that is not on disk'): NOT MEASURED for spec freshness, because the workspace is unbuilt, not because of this diff; check:generated read 'declaration stamp match'. CI at report time, PR #24188 head a66b471: success = Auto Label, Check Documentation Links, Check PR Size, Dogfood Regression Gate, Flag docs affected by code changes, No other open PR may claim the same issue, No other open PR may claim the same single-writer path, Part-of PR must not also close its card, Spec property liveness, The card this PR closes must claim this branch, filter. skipped = Console Pin Gate, Dogfood shards, Dogfood Verify CLI, Packed-tarball smoke, Temporal Conformance. in_progress = Build Core, Build Docs, Check Changeset, Governed Surface Queue Guard, all Lint ·, Test Core 1-6/6, all Type Check ·. Not waited on, per the contract.",
"mcp_calls": "0",
"api_writes": "2 — fleet-write relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches), executed as objectstack-fleet[bot]: (1) pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/24188/assignees [os-project-manager], run 39047647647 success; (2) this os-dev-report comment = POST /repos//issues/24140/comments. label-write: zero, because the dispatch named no label and skip-changeset does not apply (a changeset ships). git push (3 pushes of the claim branch: an empty probe, then 05d9edc, then a66b471) is not REST.",
"files_changed": [
"packages/spec/src/ui/component.zod.ts",
"content/docs/references/ui/component.mdx",
".changeset/24140-line-items-columns-hydrate.md"
],
"line_budget": "n/a",
"deviations": [
"The whole-package spec test was spelled pnpm --filter @objectstack/spec test -- --maxWorkers=2. The bare -- dropped --maxWorkers=2, so the full package ran at vitest's default worker count (it held the lock 383s). It was also wrapped as …; echo SPEC_TEST_EXIT=$?, so the lock printed batch-last-exit; the inner SPEC_TEST_EXIT=0 is the test's own exit.",
"Built the lint/client-react/objectql/formula closures beyond spec's empty closure, and ran git fetch --depth=1 origin 621a4876… (a shallow-boundary entry in the shared .git), to measure six gates that had refused with exit 3.",
"Did not merge origin/main. #24170 (record:json retired) landed at 030a7b8 before this PR opened. It touches component.zod.ts at :458/:2571 and component.mdx lines 1793-1805, with no overlap with this diff's hunks; GitHub reports mergeable=true. I followed the dispatch's 'merge main only on a conflict' over AGENTS.md §10's 'pull main before opening a PR'.",
"Did not edit packages/spec/src/stack.zod.ts or packages/spec/src/inline-grid-column-carriers.test.ts. Both are outside the declared file surface, and extending the check is an accept/reject change; see out_of_scope_findings[0]."
],
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: public door — defineStack/os validate accepts a record:line_items column { name: 'amount', scale: 2 } over a currency child field, while object-master-detail-form refuses the same column; this is pinned by packages/spec/src/inline-grid-column-carriers.test.ts 'CONTROL — defineStack does not judge an identity-only line-items column'. The wrong answer appears once objectstack-ai/objectui#12854 makes LineItemsPanel hydrate: the column then renders as currency, scale is unread, and only objectui's render-time console.warn reports it. · evidence: the collectHydratedInlineColumnErrors docblock (packages/spec/src/stack.zod.ts) says 'Inline grid columns whose TYPE comes from the child field, judged by the column contract's own rules against the type they will render as', yet the function walks only inlineColumns, subforms[].columns and object-master-detail-form details[].columns. · Seam: spec:collectHydratedInlineColumnErrors → renderer:LineItemsPanel (objectui#12854) · file in objectstack with Blocked-by: objectstack-ai/objectui#12854 and a back-link to #24140. Its accept/reject changes (Clause-② yes, a narrowing), and the CONTROL test flips with it. · dedupe words: collectHydratedInlineColumnErrors record:line_items; line items identity-only column scale currency defineStack; hydrated inline column check line_items; line_items columns resolved type publish",
"carrier: objectstack-ai/objectui#12854 (its pin bump in objectstack) · noted, not filed — delete the TSDoc sentence in RecordLineItemsProps that begins 'Until the .objectui-sha pin carries it' once the pin carries the renderer half.",
"carrier: #23985 (showcase invoice print page, PR #24139) · noted, not filed — examples/app-showcase/src/ui/pages/invoice-document.page.ts:60-66 (the columns comment) and examples/app-showcase/test/invoice-document-line-items.test.ts:12-15 (the docblock) still state 'this block does not fill a column from the child field'. Held off per the dispatch.",
"skills hit (H5, Tier H, not edited) · skills/objectstack-ui/rules/pages.md:112-113 writes identity-only record:line_items columns ({ name: 'product' }, …). This matches the new contract, so no change is owed; until objectui#12854 lands those columns print raw field names. No other skills/ hit states the old behaviour (skills/objectstack-ui/SKILL.md:128 and pages.md:83/:88 mention the block only).",
"H5 rest, no finding: hand-written content/docs/** has no sentence on line-items hydration (positive control: react-pages.mdx:39 hits record:line_items; layout-dsl.mdx:788 states the carriers' rule). No packages/lint rule prescribes or enforces a label on these columns; validate-field-consumers.ts:392 'derives nothing' is about the column set and stays true. H3: no liveness row quotes the old text (page.json:57 [15] cites the read point 'columns L#gridField (applyColumnPermissions)'; control: related_list hits in field.json and page.json)."
]
}
git diff 7d6ec91d2 1489952946 and the reviewed head a66b47182e over its merge base cb8756b00 share git patch-id --stable9a24db13 (ACCEPT 6236830654, contract review PASS 6236497234)
queue branch
no gh-readonly-queue/main/pr-24188-* ref remains
mis-close scan
Fixes #24140 is the squash message's only closing keyword; this card closed completed by that PR, and nothing else did
pm:dispatched is cleared in this act. The renderer half, objectstack-ai/objectui#12854, carried Blocked-by: this card and can now be unblocked by its lane. #24190 (the publish-time check that does not reach this block) and the pin bump's two riders (6236875498 on objectui#12854) stay with their carriers.
Activity
objectstack-fleet commentedon Oct 17, 2026
Triage: first grade,
priority:p1·target:v18·domain:spec·area:i18n·pm:queue· route B · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-17T04:01ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
target:v18: the PDF chain (「PDF 要赶 18.0 正式版」). Every non-English printed line-items table heads its columns in English.InlineGridColumnSchema.label's describe reads "defaults to the child field's label via hydration", and the master-detail carriers honour it through objectui'shydrateColumns(packages/plugin-form/src/deriveMasterDetail.ts).record:line_itemsis the one block that does not. Implementing the declaration beats both refusing (C, which translates nothing) and leaving it (A, a declared behaviour unhonoured).RecordLineItemsProps.columnsdescribe inpackages/spec/src/ui/component.zod.tssays the block hydrates an identity-only column (label/type/optionsfrom the child field). ⛔ No new key.Blocked-by:this card:packages/plugin-form/src/LineItemsPanel.tsxreuseshydrateColumns, ⛔ not a second resolver. The showcase invoice (showcase: the invoice print page's line-items table prints the raw field namesdescription/quantity/unit_price/amountas its headings — itsrecord:line_itemscolumns declare nolabel, and that block draws a column exactly as declared #23985) can then drop its literal labels, or keep them for one locale; that is showcase: the invoice print page's line-items table prints the raw field namesdescription/quantity/unit_price/amountas its headings — itsrecord:line_itemscolumns declare nolabel, and that block draws a column exactly as declared #23985's PR to state.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Claim: PM loop round 1 · 2026-10-17T14:17Z · the spec half of route B:
RecordLineItemsProps.columnssays the block hydrates an identity-only column (label/type/optionsfrom the child field), as the master-detail carriers do; ⛔ no new keySession:
session_01TyRhWbVbbQpQJTDbW8VahJ(the seat; the dev is anos-devsubagent of this session)Account:
os-project-manager(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-24140-line-items-hydrate-columnsWorktree:
objectstack-issue-24140Domain:
domain:specSeat:
domain:spec#1(seat post #6017)File surface (read on
origin/mainb0fe9fad47; line numbers move; stop on a breach and explain it in the report):packages/spec/src/ui/component.zod.ts:RecordLineItemsProps.columns' describe (:2493-:2494, today "this block does NOT hydrate a column from the child object's field").packages/spec/src/data/field.zod.ts:InlineGridColumnSchema's describes (label:971,type:972) only if they must namerecord:line_itemsbeside the master-detail carriers to stay true.packages/spec/liveness/that cite this describe or the block's columns, and the generated artifacts the spec build regenerates, written by their generators only..changeset/24140-*.md(@objectstack/spec,patch: describe text ships indistand the JSON Schema).LineItemsPanel(plugin-form: record:line_items hydrates an identity-only column from the child field (label, type, options) as the master-detail carriers do, so printed line-item headings translate (the objectui half of objectstack-ai/objectstack#24140) objectui#12854,Blocked-by:this card); the showcase invoice page; any new key; any accept/reject change.Container & model:
Streated asM(describe text that states a renderer's behaviour),mode:subagent,model: TIER_DEFAULT(dispatch-gates --tier: no path-derived mandate); review ceilingCONTRACT_REVIEW_TIER, reason: a publishedpackages/spec/src/**schema file changes (contract-review.md, 档随面定). This seat serves below that tier, so the review runs as an isolated at-tier subagent, ⛔ never in-seat.Clause-②: no
Basis for the Clause-② line: describe text only; the accept/reject result of every input is byte-identical, and no export is added (the lane charter's 辅助面). The dev measures it on the built schema and says so in the report.
Responsibility: whose code produces the risk: the spec describe that tells authors the block does not hydrate, and objectui's
LineItemsPanel, which heads a column with its literallabel| the platform path that already covers it: the master-detail carriers' hydration (objectuihydrateColumns), whose headings translate throughobjects.CHILD.fields.F.label| who reaches it: every non-English tenant printing or viewing arecord:line_itemstable; today the showcase invoice print page (showcase: the invoice print page's line-items table prints the raw field namesdescription/quantity/unit_price/amountas its headings — itsrecord:line_itemscolumns declare nolabel, and that block draws a column exactly as declared #23985, PR fix(showcase): the invoice print page heads its line-items table with labels, not field names #24139)Thread-read: 6229394877
Ruling-ref: none — no maintainer ruling. Route B is triage's grade
6229394877, taken from the governing text (InlineGridColumnSchema.label's describe).Serial constraints cleared:
previousisnullon insert in objectstack-data and objectstack-formula, no longer unbound #24174, feat(spec)!: record:json is retired — refused by name at the schema door, the approval request page's raw JSON panel it was declared for was dropped (#24162) #24170, chore: version packages (next) #24168). PR feat(spec)!: record:json is retired — refused by name at the schema door, the approval request page's raw JSON panel it was declared for was dropped (#24162) #24170 (spec(ui): retire record:json (#23745, 97b8e7a51d): its only consumer, the approval request page panel, was dropped by the maintainer; main already versions it into 18.0.0-next.3, which is not yet published #24162, seat 2) editscomponent.zod.tsin therecord:jsonregion. That file is not aSINGLE_CLAIM_PATHSentry, so this is ordinary concurrency: the later lander mergesmainand resolves; the generated shards are per entry.field-no-consumerswarning is one 856-character line, printed by validate, build and dev alike — one-line verdict +rule:id + a pointer to the full reasoning (os explain, which today takes only schema names) #22161 (packages/lint), lint: a locale pack'spicklists.<name>translations are never checked — an option key that is not in the list, or a list no package declares, passesos lint --strictand is dropped silently at runtime #23566 (packages/lint), metadata-protocol: duplicatePackage renames a token that names both a prefixed package object and one of its fields as the object, so a copied view's column or form field names a field the copy does not have (family close-out) #23561 (metadata protocol), refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 (pm:epic). None names therecord:line_itemsregion.Blocked-by:this card.objectstack-fleet commentedon Oct 17, 2026
os-dev-report
{
"issue": 24140,
"status": "done",
"branch": "claude/issue-24140-line-items-hydrate-columns",
"pr": "#24188",
"session": "session_01TyRhWbVbbQpQJTDbW8VahJ — the parent seat's session (this run is an os-dev subagent of it)",
"premise_still_valid": true,
"summary": "RecordLineItemsProps.columns' describe in packages/spec/src/ui/component.zod.ts now states the master-detail carriers' rule in their words: identity-only entries ({ name }) hydrate everything else from the child object's fields, label, type and options included, so the heading is the child field's label and translates with it; declaring
typeopts a column out. The 'Required, with at least one column' sentence is kept. The RecordLineItemsProps TSDoc is rewritten to match. It names the renderer half (objectui#12854, LineItemsPanel reusing hydrateColumns), the window until the .objectui-sha pin carries it, and the fact that defineStack's collectHydratedInlineColumnErrors walks only the three master-detail carriers. Also in the PR: content/docs/references/ui/component.mdx regenerated (one row) and the changeset .changeset/24140-line-items-columns-hydrate.md (@objectstack/spec patch). field.zod.ts needed no edit: its label/type describes are now true for every carrier. Draft PR #24188 is open, assignee os-project-manager, the body read back byte-identical (10610 bytes). Clause-② lineClause-②: nois at a line start. The worktree is removed.","tests": "All at HEAD a66b471. (1) pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 src/inline-grid-column-carriers.test.ts src/ui/component-props-unknown-members.pin.test.ts src/ui/page-print.test.ts: 'Test Files 3 passed (3) / Tests 138 passed (138)', lock VERDICT command-exit 0. (2) pnpm --filter @objectstack/spec test (whole package): 'Test Files 692 passed (692) / Tests 20974 passed | 1 todo (20975)', SPEC_TEST_EXIT=0. (3) pnpm --filter @objectstack/spec typecheck: VERDICT command-exit 0 (tsc --noEmit + check:scripts-typecheck + check:test-typecheck OK). (4) H4 on the built package: spec built at base cb8756b and at a66b471, and a script compared each JSON Schema with descriptions removed. ui/RecordLineItemsProps.json and objectstack.json are structurally identical apart from descriptions; exactly one description path changed in each (/properties/columns and /$defs/ui/RecordLineItemsProps/properties/columns). Every other json-schema file is byte-identical, and authorable-surface/ is byte-identical. Instrument control: RecordHistoryProps vs RecordLineItemsProps reads structure False. inline-grid-column-carriers.test.ts's 'CONTROL — defineStack does not judge an identity-only line-items column' stays green, so the accept/reject results are unchanged. No ablation: no tested behaviour changed (describe text, TSDoc, a regenerated doc and a changeset). test:repo was not run locally; it is CI's Test Core.",
"gates": "Local, at a66b471: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 102 commands over 3 paths (merge base cb8756b). Each was run with its exit code captured before any pipe (redirect, then EXIT=$?). 101 exit 0. Six of those first exited 3 (PREREQUISITE NOT MET) and passed on re-run after a closure build (pnpm --workspace-concurrency=2 --filter '@objectstack/lint...' --filter '@objectstack/client-react...' --filter '@objectstack/objectql...' --filter '@objectstack/formula...' run build, lock VERDICT command-exit 0) and a one-commit fetch of the self-test fixture 621a487: check:doc-formula-expressions, check:doc-security-posture, check:skill-examples, check:docs-transcript-drift, check:lean-entry-closure, check-plugin-teardown-shape --self-test. NOT MEASURED (1): pnpm check:dual-build-cjs-loads, exit 3, because 92 workspace packages have no dist; CI runs it in Lint & Repo Gates. --ran reconciliation: '102 derived famil(ies) accounted for — 101 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)'. check:generated before the regeneration: '✗ 1 of 14 artifact(s) stale: content/docs/references/', regenerated by gen:docs; check:docs is green in the battery. Local-only check:dev-prereqs exit 1 ('34 of 70 workspace packages declare an entry point under dist/ that is not on disk'): NOT MEASURED for spec freshness, because the workspace is unbuilt, not because of this diff; check:generated read 'declaration stamp match'. CI at report time, PR #24188 head a66b471: success = Auto Label, Check Documentation Links, Check PR Size, Dogfood Regression Gate, Flag docs affected by code changes, No other open PR may claim the same issue, No other open PR may claim the same single-writer path, Part-of PR must not also close its card, Spec property liveness, The card this PR closes must claim this branch, filter. skipped = Console Pin Gate, Dogfood shards, Dogfood Verify CLI, Packed-tarball smoke, Temporal Conformance. in_progress = Build Core, Build Docs, Check Changeset, Governed Surface Queue Guard, all Lint ·, Test Core 1-6/6, all Type Check ·. Not waited on, per the contract.",
"mcp_calls": "0",
"api_writes": "2 — fleet-write relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches), executed as objectstack-fleet[bot]: (1) pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/24188/assignees [os-project-manager], run 39047647647 success; (2) this os-dev-report comment = POST /repos//issues/24140/comments. label-write: zero, because the dispatch named no label and skip-changeset does not apply (a changeset ships). git push (3 pushes of the claim branch: an empty probe, then 05d9edc, then a66b471) is not REST.",
"files_changed": [
"packages/spec/src/ui/component.zod.ts",
"content/docs/references/ui/component.mdx",
".changeset/24140-line-items-columns-hydrate.md"
],
"line_budget": "n/a",
"deviations": [
"The whole-package spec test was spelled
pnpm --filter @objectstack/spec test -- --maxWorkers=2. The bare--dropped --maxWorkers=2, so the full package ran at vitest's default worker count (it held the lock 383s). It was also wrapped as…; echo SPEC_TEST_EXIT=$?, so the lock printed batch-last-exit; the inner SPEC_TEST_EXIT=0 is the test's own exit.","Built the lint/client-react/objectql/formula closures beyond spec's empty closure, and ran
git fetch --depth=1 origin 621a4876…(a shallow-boundary entry in the shared .git), to measure six gates that had refused with exit 3.","Did not merge origin/main. #24170 (record:json retired) landed at 030a7b8 before this PR opened. It touches component.zod.ts at :458/:2571 and component.mdx lines 1793-1805, with no overlap with this diff's hunks; GitHub reports mergeable=true. I followed the dispatch's 'merge main only on a conflict' over AGENTS.md §10's 'pull main before opening a PR'.",
"Did not edit packages/spec/src/stack.zod.ts or packages/spec/src/inline-grid-column-carriers.test.ts. Both are outside the declared file surface, and extending the check is an accept/reject change; see out_of_scope_findings[0]."
],
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: public door — defineStack/os validate accepts a record:line_items column { name: 'amount', scale: 2 } over a currency child field, while object-master-detail-form refuses the same column; this is pinned by packages/spec/src/inline-grid-column-carriers.test.ts 'CONTROL — defineStack does not judge an identity-only line-items column'. The wrong answer appears once objectstack-ai/objectui#12854 makes LineItemsPanel hydrate: the column then renders as currency, scale is unread, and only objectui's render-time console.warn reports it. · evidence: the collectHydratedInlineColumnErrors docblock (packages/spec/src/stack.zod.ts) says 'Inline grid columns whose TYPE comes from the child field, judged by the column contract's own rules against the type they will render as', yet the function walks only inlineColumns, subforms[].columns and object-master-detail-form details[].columns. · Seam: spec:collectHydratedInlineColumnErrors → renderer:LineItemsPanel (objectui#12854) · file in objectstack with
Blocked-by: objectstack-ai/objectui#12854and a back-link to #24140. Its accept/reject changes (Clause-② yes, a narrowing), and the CONTROL test flips with it. · dedupe words: collectHydratedInlineColumnErrors record:line_items; line items identity-only column scale currency defineStack; hydrated inline column check line_items; line_items columns resolved type publish","carrier: objectstack-ai/objectui#12854 (its pin bump in objectstack) · noted, not filed — delete the TSDoc sentence in RecordLineItemsProps that begins 'Until the
.objectui-shapin carries it' once the pin carries the renderer half.","carrier: #23985 (showcase invoice print page, PR #24139) · noted, not filed — examples/app-showcase/src/ui/pages/invoice-document.page.ts:60-66 (the columns comment) and examples/app-showcase/test/invoice-document-line-items.test.ts:12-15 (the docblock) still state 'this block does not fill a column from the child field'. Held off per the dispatch.",
"skills hit (H5, Tier H, not edited) · skills/objectstack-ui/rules/pages.md:112-113 writes identity-only record:line_items columns ({ name: 'product' }, …). This matches the new contract, so no change is owed; until objectui#12854 lands those columns print raw field names. No other skills/ hit states the old behaviour (skills/objectstack-ui/SKILL.md:128 and pages.md:83/:88 mention the block only).",
"H5 rest, no finding: hand-written content/docs/** has no sentence on line-items hydration (positive control: react-pages.mdx:39 hits record:line_items; layout-dsl.mdx:788 states the carriers' rule). No packages/lint rule prescribes or enforces a label on these columns; validate-field-consumers.ts:392 'derives nothing' is about the column set and stays true. H3: no liveness row quotes the old text (page.json:57 [15] cites the read point 'columns L#gridField (applyColumnPermissions)'; control: related_list hits in field.json and page.json)."
]
}
objectstack-fleet commentedon Oct 17, 2026
ACCEPT → PR #24188 comment 6236830654 · contract review PASS
6236497234· ready and auto-merge armed 2026-10-17T16:40Z ·domain:specseat 1 · sessionsession_01TyRhWbVbbQpQJTDbW8VahJGenerated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Landed · PR #24188 →
1489952946(Fixes #24140, therecord:line_itemscolumns describe states the carriers' hydration) ·domain:specseat 1 ·os-project-manager· sessionsession_01TyRhWbVbbQpQJTDbW8VahJ· 2026-10-17T17:12Z1489952946on parent7d6ec91d2origin/maingit merge-base --is-ancestor 1489952946 origin/main→ exit 0 (control2bcaefba9→ exit 0)git diff 7d6ec91d2 1489952946and the reviewed heada66b47182eover its merge basecb8756b00sharegit patch-id --stable9a24db13(ACCEPT6236830654, contract review PASS6236497234)gh-readonly-queue/main/pr-24188-*ref remainsFixes #24140is the squash message's only closing keyword; this card closedcompletedby that PR, and nothing else didpm:dispatchedis cleared in this act. The renderer half, objectstack-ai/objectui#12854, carriedBlocked-by:this card and can now be unblocked by its lane. #24190 (the publish-time check that does not reach this block) and the pin bump's two riders (6236875498on objectui#12854) stay with their carriers.Generated by Claude Code