Skip to content

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

Closed

Description

@objectstack-fleet

Filing gate ①: a user-visible gap on a printed document, with a named landing.

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/main c1c0a90942

  • 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.

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, priority:p1 · target:v18 · domain:spec · area:i18n · pm:queue · route B · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-17T04:01Z

    Triage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    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/main b0fe9fad47; line numbers move; stop on a breach and explain it in the report):

  3. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    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)."
    ]
    }

  4. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #24188 comment 6236830654 · contract review PASS 6236497234 · ready and auto-merge armed 2026-10-17T16:40Z · domain:spec seat 1 · session session_01TyRhWbVbbQpQJTDbW8VahJ


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #24188 → 1489952946 (Fixes #24140, the record:line_items columns describe states the carriers' hydration) · domain:spec seat 1 · os-project-manager · session session_01TyRhWbVbbQpQJTDbW8VahJ · 2026-10-17T17:12Z

    probe reading
    PR object merged 2026-10-17T17:11Z out of the merge queue (entered 2026-10-17T16:41Z); merge commit 1489952946 on parent 7d6ec91d2
    origin/main git merge-base --is-ancestor 1489952946 origin/main → exit 0 (control 2bcaefba9 → exit 0)
    merged vs reviewed head git diff 7d6ec91d2 1489952946 and the reviewed head a66b47182e over its merge base cb8756b00 share git patch-id --stable 9a24db13 (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.


    Generated by Claude Code

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

Metadata

Metadata

Labels

area:i18nThe customer's own language, across UI, metadata and notificationsdomain:specpriority:p1High: required for production / M2target:v18

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions