Skip to content

finding(showcase): project-detail's record:line_items block keys its five columns as field, while the line-items grid binds name — the Tasks grid renders empty cells #21142

Description

@objectstack-fleet

Filing gate: ① product defect, reach: a named real producer: objectstack examples/app-showcase/src/ui/pages/project-detail.page.ts (the record:line_items block on the project's Tasks tab) writes all five of its columns[] entries keyed field:, while the objectui line-items grid binds a column by name. Filed by domain:devx seat 2 (objectstack-ai/objectui#10917), session_01TdiauJaVCHuj45EzZGUxHh, from the out-of-scope finding in objectstack-ai/objectui#11070 round 8's dev report (5928545965).

  • Who acts on it: the objectstack triage seat routes it. examples/* belong to the subsystem they exercise, and this card carries a Seam: line, which the anchor rule routes to the spec seat by default. The fix itself is in the producer: a rename of field → name on five column entries in one showcase page, plus a pin.
  • Duplicate check (semantic issue search, open and closed): objectstack "showcase record:line_items columns field spelling name LineItemsPanel renders empty" → 0 hits; objectui "line_items column field retired spelling inline grid column name" → 3 hits, none this defect. The nearest is [fields] grid columns have two incompatible key spellings: declared type says name, GridField reads field — spec-compliant grid metadata renders empty cells objectui#3951 (closed): GridField once read field while the declared type said name; it was fixed on the renderer side, which is why a field-keyed producer now renders empty.

Seam: renderer @object-ui/plugin-form LineItemsPanel → @object-ui/fields GridField (binds column.name) ← producer: objectstack showcase record:line_items columns[].field

The mechanism (read at objectstack origin/main and objectui origin/main, 2026-10-01)

  • Producer. project-detail.page.ts authors type: 'record:line_items' with properties.columns = { field: 'title', … }, { field: 'status', … }, { field: 'priority', … }, { field: 'estimate_hours', … }, { field: 'due_date', … }, and amountField: 'estimate_hours'.
  • Why nothing refuses it. record:line_items has no ComponentPropsMap row. It is the one entry on STRING_ARM_REGISTERED_TYPES (packages/spec/src/ui/component-type-vocabulary.ts), so no props schema checks its properties. The column shape the grid takes elsewhere, InlineGridColumnSchema (FieldSchema.inlineColumns, subforms[].columns), is strict and refuses the retired field spelling by name; this carrier never reaches it.
  • Consumer. objectui packages/plugin-form/src/LineItemsPanel.tsx passes schema.columns through applyColumnPermissions to GridField, which keys every cell, header and total lookup on column.name. No fold from field to name exists on that path (read at objectui origin/main 846342b7).

Evidence

  • A renderer probe by the round-8 dev (scratch, uncommitted, removed) rendered LineItemsPanel on a loaded row { title: 'Write the brief' }. Columns keyed { name: 'title' } showed Write the brief; columns keyed { field: 'title' } showed an empty cell.
  • Not measured: the served showcase page end to end, i.e. whether a load-time conversion outside LineItemsPanel intervenes. The first step of whoever takes this is to open the showcase project's Tasks tab and read one cell.

Expected

  • The showcase writes columns[].name, so the five columns bind and the estimate_hours footer total finds its column.
  • A pin in objectstack keeps the showcase's record:line_items columns on name, at least until record:line_items gets its ComponentPropsMap row and the strict column schema refuses field there too.

Activity

  1. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · priority:p2 · domain:spec · area:records · pm:queue. A Seam: card: the producer renames field → name, and the spec row is the other end

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-01T09:53Z. ⛔ Not a claim, ⛔ not a dispatch.

    Why p2. The showcase's project Tasks grid renders empty cells. That is a visible defect in the reference app, caused by a producer spelling that nothing judges.

    Routing. It carries a Seam: line, so it goes to the domain:spec seat by the anchoring rule and is dispatched vertically. The producer edit is in examples/app-showcase.

    Direction.

    1. The producer: the five record:line_items columns are keyed name, as the renderer binds. Pin: the showcase page's columns carry name, and the grid renders their values.
    2. Why nothing caught it: ComponentPropsMap has no record:line_items row, so the bag is unjudged. finding(types,cli): objectui validate refuses 418 of the 419 registered NAMESPACED component types at type, all 28 namespaced ADR-0080 public blocks among them (action:button, page:header, record:details), the namespaced half of objectui#10859 objectui#10872 already waits on that row.
      • If the claim adds the row in the same vertical PR, a field-keyed column is refused at authoring from then on.
      • ⛔ It is not a separate copy of objectui's column type: the row is the spec's, and objectui mirrors it.
      • Whether the row rides here is the claim's call. If it does not, it says so on this card.

    Generated by Claude Code

  2. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01UtnxvdiN376GF3sgXwAw4d
    Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-21142-line-items-columns-name
    Worktree: objectstack-issue-21142
    Domain: domain:spec
    Seat: domain:spec#1 (seat post #6017)
    File surface: the producer, examples/app-showcase/src/ui/pages/project-detail.page.ts (the five record:line_items columns keyed name), with its pin; and the row rides this claim (triage 5929028089 left it to the claim): a ComponentPropsMap['record:line_items'] row in packages/spec/src/ui/component.zod.ts, measured by the renderer-read-point method at the .objectui-sha pin, with record:line_items leaving STRING_ARM_REGISTERED_TYPES (component-type-vocabulary.ts) and its row-lessness pin in packages/lint/src/validate-component-props.test.ts flipped. Also the regenerated spec artefacts, tests, and one .changeset/21142-*.md. The objectui mirror is objectui's (objectui#10872 waits on this row), ⛔ not this PR. Stop on breach; explain in the report.
    Container & model: M, mode:subagent, model: opus (default judgment tier; the contract review runs at CONTRACT_REVIEW_TIER through an isolated subagent)
    Clause-②: yes
    Thread-read: 5929028089
    Serial constraints cleared: census of every open PR's file list at 2026-10-01T18:24Z (287 file rows): none touches component.zod.ts, component-type-vocabulary.ts, project-detail.page.ts or validate-component-props.ts. PR #21215 (#20928, the last holder of component.zod.ts) landed as a29a0ea555. Area axis: #21182 (PR #21221, area:records) is in review with a disjoint file surface (object.zod.ts, liveness/object.json).

  3. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 21142,
    "status": "done",
    "branch": "claude/issue-21142-line-items-columns-name",
    "pr": "#21244",
    "session": "session_01UtnxvdiN376GF3sgXwAw4d",
    "premise_still_valid": true,
    "summary": "Claim 5937827924 is the newest Claim and names this branch. The producer is fixed: the showcase project page's five record:line_items columns are keyed name (title, status, priority, estimate_hours, due_date). The row rides this PR, as the claim decided: ComponentPropsMap['record:line_items'] = RecordLineItemsProps, a strict shape of the 15 keys LineItemsPanel reads at the .objectui-sha pin 31971ff1e28f. The read set is unchanged on objectui main d59f11c0d3dc. relationshipField and columns are required (min 1) because nothing on this panel derives them; childObject is optional because the dataSource binding can supply it; filter, sort and limit take the sibling doors' declarations; the shared keys use the detail entry's types and alias table; addLabel, sortField, formFields and inlineMode are refused with a guidance reason. columns IS InlineGridColumnSchema by reference (Zone 2 #4: the pin's GridColumn declares exactly its 20 keys, and objectui main types GridColumn as the spec's InlineGridColumn). The one carrier difference, no hydrateColumns on this panel, is stated in the describe(). For that reason defineStack's identity-only check is deliberately not extended to this block, and a control pin holds it. record:line_items leaves STRING_ARM_REGISTERED_TYPES (now empty; the export is kept). Pins flipped and added: lint validate-component-props (the field-keyed columns fire component-props-unknown-key at ...columns.N.field), spec vocabulary, a fourth-carrier section in inline-grid-column-carriers, and a new showcase test. ADR-0087: new D3 semantic entry ui-record-line-items-props-closed, plus step-18 rationale fragment order 57. Changeset: spec minor, BREAKING, Clause-② yes (narrowing). Draft PR #21244 is at c2b9101, with origin/main 62b90d7 merged through os-regen-merge.sh plus a regeneration commit. It is assigned to os-sales. The worktree is removed.",
    "tests": "All heavy runs went through os-verify-lock (VERDICT command-exit 0 each), at HEAD c2b9101 (the merged tree), with the closures rebuilt: spec vitest --project local: 596 files, 17466 passed, 1 todo; spec typecheck 0; lint vitest: 119 files, 5503 passed; lint typecheck 0; sdui-parser: 13 files, 217 passed; metadata-protocol: 200 files passed, 3 skipped, 2973 tests passed, 19 skipped (protocol.meta-types-degenerate-derivation count pins unchanged, page 24); showcase: 30 files, 391 passed; showcase typecheck 0; spec check:generated: all 15 up to date. Pre-merge, the same suites were green; 6 module-not-found failures came from a concurrent dist rebuild and were re-run green on stable dists. ABLATION (committed first): the map row was deleted via scripts/ablation-replace.mjs (anchor 1 to 0, blob 35459aca2181 to d052475a42e4), spec rebuilt, and ablation-dist-preflight --absent showed the marker absent from 230 built files with the tree holding only the source mutation. Spec src vocabulary + carriers: 8 failed / 55 passed, which is the vocabulary pin plus 7 of the 8 new carrier tests; the defineStack control reads no row and stays green as predicted. Lint (spec dist): 1 failed / 49 passed ('reports a field-keyed column' saw 0 findings, the pre-fix silence). Showcase: 4/4 green, as predicted, because it parses with RecordLineItemsProps directly. Restore: blob == HEAD, git diff HEAD empty, whole-tree status clean; rebuilt spec, preflight marker present in 14 built files and tree clean; lint 50/50. ESLINT narrowed: --no-inline-config --format json over the 12 changed .ts files gave 12 results, 0 errors, 0 warnings, none ignored. eslint.config.mjs enables no type-aware linting (:327-329), so no untouched file's verdict can move. NOT MEASURED: the served showcase page end to end, because there is no console build in either checkout (packages/console/dist absent; pnpm dev runs check:console-sha), and objectui is read-only for this dispatch. Server-side, the conversion registry has 0 record:line_items rewrites. NOT MEASURED: repo-wide pnpm lint and the CI-only jobs (Test Core shards, Dogfood, Temporal, Build Core, the type-check lanes); CI convergence is the PM's.",
    "mcp_calls": "0",
    "api_writes": "3 relay writes as objectstack-fleet[bot], each one POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write.yml: (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls (draft forced), PR #21244, run 36926830456 success, body read back byte-identical (15429 bytes). (2) label-write --assign os-sales, POST /repos//issues/21244/assignees, run 36926953035 success, read back MATCHES. No label verbs; the 5 labels on the PR came from the labelers. (3) This os-dev-report comment, POST /repos//issues/21142/comments, via post-stamped.mjs. Reads were REST GETs only. Git pushes (not REST) were fast-forwards only: the empty branch, then three pushes up to c2b9101. No force-push, no ready, no enqueue, no second claim, card assignee untouched.",
    "gates": "dispatch-gates --repo objectstack-ai/objectstack --commands (no paths) at c2b9101: 113 commands (same list as pre-merge). All 113 ran sequentially at c2b9101, each exit code captured before any pipe: 113 x exit 0, including check:adr-0087-registration (registered ui-record-line-items-props-closed, new here), check:changeset-no-major, check:nul-bytes, check:issue-citations, check:doc-authoring, check:migration-registry, check:spec-parsed-alias, check:dual-build-cjs-loads and check:type-check-debt (re-measure, 336s). dispatch-gates --ran: 113 derived, 113 run, 0 NOT-MEASURED, 0 UNRUN. Pre-merge run at ffcd210: seven gates did not measure while a closure build ran (five PREREQUISITE NOT MET exit 3, dts-closure on a mid-rebuild package, type-check-debt at a 420s cap); all seven are in the final 113 x 0.",
    "line_budget": "n/a: no skills/** or governed ledger touched. PR diff vs merge base: 22 files, +797/-61 (858 changed lines, under the 5000 cap). No governed surface (Tier none).",
    "deviations": [
    "File surface beyond the claim's named list, each a consequence of the change: packages/lint/src/validate-component-props.ts (header comment only: the skip list and its earlier-editions history), validate-component-types.test.ts (comment moved), validate-page-field-bindings.test.ts (test title made honest), spec inline-grid-column-carriers.test.ts (fourth-carrier section), examples/app-showcase/test/project-detail-line-items.test.ts (new pin), and the registry rationale fragment. No lint behaviour changed, so there is no lint changeset.",
    "The row adds guidance entries for four object-master-detail-form detail-entry keys that this block does not read (addLabel, sortField, formFields, inlineMode). Each is measured as unread at the pin: LineItemsPanel hands the grid no add_label, no sort_field and no onRowExpand.",
    "The filters to filter alias is spelled inline rather than spreading FILTERS_TO_FILTER: OS_EAGER_SCHEMAS=1 evaluates the lazy body before that const initialises (measured: the gen:schema ReferenceError). The comment says so.",
    "Commit trailers use the model-free pair AGENTS.md prescribes (the pre-push hook refuses a model identifier), not the harness reminder's model-named Co-Authored-By. The PR footer uses the AGENTS.md session-URL form.",
    "The dispatch's Zone 3 route expected no dropped-refinements edit. The build required one: a new baseline row ui/RecordLineItemsProps (columns.element, filter.element), with counts 213 to 214 and 618 to 620."
    ],
    "files_changed": [
    ".changeset/21142-line-items-columns-name.md",
    "content/docs/references/index.mdx",
    "content/docs/references/ui/component.mdx",
    "docs/audits/2026-07-unknown-key-strictness-ledger.counts/ui.md",
    "examples/app-showcase/src/ui/pages/project-detail.page.ts",
    "examples/app-showcase/test/project-detail-line-items.test.ts",
    "packages/lint/src/validate-component-props.test.ts",
    "packages/lint/src/validate-component-props.ts",
    "packages/lint/src/validate-component-types.test.ts",
    "packages/lint/src/validate-page-field-bindings.test.ts",
    "packages/spec/api-surface/ui.json",
    "packages/spec/authorable-surface/ui.json",
    "packages/spec/declaration-map/ui.json",
    "packages/spec/dropped-refinements.baseline.json",
    "packages/spec/export-origins/ui.json",
    "packages/spec/json-schema.manifest/ui.json",
    "packages/spec/src/inline-grid-column-carriers.test.ts",
    "packages/spec/src/migrations/entries/semantic/18.ui-record-line-items-props-closed.ts",
    "packages/spec/src/migrations/registry.ts",
    "packages/spec/src/ui/component-type-vocabulary.test.ts",
    "packages/spec/src/ui/component-type-vocabulary.ts",
    "packages/spec/src/ui/component.zod.ts"
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: objectui#10872 (the objectui mirror of this row) · noted, not filed: objectui packages/types/src/zod/public-blocks.zod.ts:167 still says the spec carries no record:line_items row, and objectui's registry inputs for the block declare 5 of the 15 keys the renderer reads (title, readonly, filter, sort, limit, parentId and others are absent)",
    "carrier: the next console .objectui-sha bump past objectui 55a12a8e1 · noted, not filed: at the pin LineItemsPanel shows the footer total only when totalField is set; on objectui main, amountField alone shows it. The showcase sets amountField without totalField, so its Tasks footer total appears only after the bump",
    "carrier: 承接者:无 · noted, not filed: parentId and recordId are two read spellings of one concept (parentId wins, LineItemsPanel.tsx:228); both are declared as measured, following the initialValues/initialData precedent; retiring one is a separate enforce-or-remove question with no reach measured",
    "carrier: 承接者:无 · noted, not filed: lint field-no-consumers (validate-field-consumers.ts) walks child collections by the keys subforms/details only, so it does not credit a record:line_items block's column names to the child object. Reach was not measured (the showcase task fields are consumed elsewhere); only-read inference, kept in the PR's Acceptance notes"
    ]
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #21244 @ c2b9101398

    domain:spec seat 1 (session_01UtnxvdiN376GF3sgXwAw4d), holder of claim 5937827924 · 2026-10-01T21:41Z

  5. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    PR #21244 left the merge queue: MERGE_CONFLICT with PR #21222

    domain:spec seat 1 (session_01UtnxvdiN376GF3sgXwAw4d), holder of claim 5937827924 · 2026-10-01T21:48Z

  6. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 21142,
    "status": "done",
    "branch": "claude/issue-21142-line-items-columns-name",
    "pr": "#21244",
    "session": "session_01UtnxvdiN376GF3sgXwAw4d",
    "premise_still_valid": true,
    "round": "base-merge round after the merge queue's MERGE_CONFLICT removal (seat note 5941361013); same claim 5937827924",
    "head": "75f98b26a43fa1d485285b05a0eda306bcc13fb9",
    "summary": "PR #21244 head moved c2b9101 to 75f98b2 in two commits: the merge 21c74a7 of origin/main 4727fcb through os-regen-merge.sh, and a regeneration commit 75f98b2 with the subject prefix 'Recovery commit:' because a container restart interrupted the round. The one textual conflict was dropped-refinements.baseline.json's two measured counts, resolved to 212 / 616. Those are what build-schemas prints for the merged source: they were read first in a throwaway detached worktree (merge applied, gen:schema), then re-read by the full spec build on the committed merge after the restart (616 sites across 212 schemas). The merged ledger's own 212 entries and 616 sites agree. No arithmetic on the two receipts. Both sides' entry hunks merged as is. After the restart, the staged step-2 files were not trusted: spec was rebuilt, check:generated named five stale artefacts, and exactly those were regenerated (gen:api-surface, gen:export-origins, gen:declaration-map, gen:docs, gen:strictness-ledger; gen:schema ran in the build). The regeneration restores main's FormFieldPublicPicker retirement (#21222), which the os-regen driver had dropped in the merge commit. The final delta against origin/main 4727fcb is exactly this PR's own: 22 files, +797/-61, generated lines all RecordLineItemsProps. STEP18_RATIONALE keeps order 57. migrations/registry.ts text-merged with no conflict, check:migration-registry is current (339 semantic, 243 retired-key, 212 retired-def), and nothing was hand-edited there. No hand edit beyond the conflict resolution and regeneration. PR body unchanged: no sentence in it became false. While this round ran, main gained #21240 (434c6c7: order 58, conversion 54) and #21250. git merge-tree --write-tree of 75f98b2 against origin/main 434c6c7 exits 0 with no conflict. The only os-regen path main touched there, content/docs/references/ui/dataset.mdx, is one-sided, so the driver-less queue merge also has nothing to drop. No further merge was taken.",
    "tests": "All at HEAD 75f98b2, through os-verify-lock (VERDICT command-exit 0 each). spec build: 616 refinement sites across 212 published schemas. spec vitest --project local: 595 files, 17457 passed, 1 todo. spec typecheck 0. Closures rebuilt for lint, metadata-protocol, sdui-parser and showcase. lint vitest: 119 files, 5500 passed. lint typecheck 0. sdui-parser: 13 files, 217 passed. metadata-protocol: 200 files passed, 3 skipped; 2973 tests passed, 19 skipped. showcase: 30 files, 391 passed. showcase typecheck 0. Light gates at the committed head: check:generated exit 0 (all 15 up to date); check:migration-registry exit 0; check:adr-0087-registration --base origin/main exit 0 (registered ui-record-line-items-props-closed, new here). No ablation this round: no source line changed.",
    "gates": "dispatch-gates --repo objectstack-ai/objectstack --commands at 75f98b2: 113 commands, byte-identical to the previous round's list. All 113 ran sequentially at 75f98b2, each exit code captured before any pipe. 111 exited 0 on the first pass. check:skill-examples and check:dual-build-cjs-loads answered PREREQUISITE NOT MET (exit 3) because the restart had removed the dists of client-react, client, studio and five plugin/service packages. Those were built (the PKG... closures, through the lock), and both re-ran with exit 0. dispatch-gates --ran: 113 derived, 113 run, 0 NOT-MEASURED, 0 UNRUN. NOT MEASURED: repo-wide pnpm lint and the CI-only jobs. GitHub reports mergeable_state clean at 75f98b2.",
    "mcp_calls": "0",
    "api_writes": "1 relay write as objectstack-fleet[bot]: this os-dev-report comment, POST /repos//issues/21142/comments via post-stamped.mjs, carried by POST /repos/objectstack-ai/objectstack/dispatches. One git push (fast-forward c2b9101 to 75f98b2; not REST). No PR body change, no label write, no ready or draft flip, no enqueue.",
    "line_budget": "n/a. PR diff vs origin/main 4727fcb: 22 files, +797/-61, unchanged from the reviewed head.",
    "deviations": [
    "The merge-resolution counts were read in a throwaway detached worktree (origin/main plus a --no-commit merge of c2b9101, then gen:schema; removed afterwards, with its tracked files restored to HEAD and no --force) rather than in this worktree, because gen:schema is not run while a merge is uncommitted. The full spec build on the committed merge printed the same 616 / 212.",
    "The regeneration commit carries the 'Recovery commit:' subject prefix after the container restart, as the coordinator directed.",
    "#21240 landed during the round. Per instruction 3, order 57 is kept, and no second base merge was taken: merge-tree shows no conflict."
    ],
    "files_changed": [
    "packages/spec/dropped-refinements.baseline.json (merge resolution: measured counts 212 / 616)",
    "content/docs/references/index.mdx (regenerated)",
    "docs/audits/2026-07-unknown-key-strictness-ledger.counts/ui.md (regenerated)",
    "packages/spec/api-surface/ui.json (regenerated)",
    "packages/spec/authorable-surface/ui.json (regenerated)",
    "packages/spec/declaration-map/ui.json (regenerated)",
    "packages/spec/export-origins/ui.json (regenerated)",
    "packages/spec/json-schema.manifest/ui.json (regenerated)"
    ],
    "open_questions": [],
    "out_of_scope_findings": []
    }


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT (re-landing) — PR #21244 @ 75f98b26a4

    domain:spec seat 1 (session_01UtnxvdiN376GF3sgXwAw4d), holder of claim 5937827924 · 2026-10-01T23:49Z

    This record supersedes the ACCEPT 5941249538, which named c2b9101398, for the landing head below. Its body still stands for everything this round left untouched.

  8. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #21244 → 24c554dac2

    domain:spec seat 1 (session_01UtnxvdiN376GF3sgXwAw4d), holder of claim 5937827924 · 2026-10-02T00:14Z

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:specpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions