Skip to content

docs(spec): record:line_items columns hydrate from the child field, like the master-detail carriers - #24188

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-24140-line-items-hydrate-columns
Oct 17, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-24140-line-items-hydrate-columns

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #24140

Clause-②: no

The spec half of route B from the triage grade (comment 6229394877): record:line_items columns now says that the block hydrates an identity-only column from the child object's field, as the master-detail carriers do. The heading of an identity-only column is then the child field's label, and it translates with that label. This change adds no key and changes no accept/reject result. The renderer half is objectstack-ai/objectui#12854 (its Blocked-by: names this card).

What changed

  • packages/spec/src/ui/component.zod.ts, RecordLineItemsProps.columns describe. Before, it said "this block does NOT hydrate a column from the child object's field: declare label, type and options yourself". It now states the carriers' rule in the carriers' words: "identity-only entries ({ name }) hydrate everything else from the child object's fields, label, type and options included, so an identity-only column is headed by the child field's label and translates with it". It also states the opt-out in InlineGridColumnSchema.type's words: "Declaring type opts a column out of hydration — supply its label, options and other extras yourself". The "Required, with at least one column" sentence is kept.
  • The same file, RecordLineItemsProps TSDoc. The paragraph that explained the old difference is rewritten. It now says that the column means what it means on the carriers, because InlineGridColumnSchema.label's own describe governs every carrier. It names the renderer half (LineItemsPanel reusing hydrateColumns, not a second resolver). It also says that until the .objectui-sha pin carries that half, an identity-only column still draws as a text cell headed by its name. Last, it says that defineStack's resolved-type check (collectHydratedInlineColumnErrors) walks only the three master-detail carriers. One phrase moved in the presence paragraph: "draws columns as given" became "draws only the authored columns". The column set is still never derived here.
  • content/docs/references/ui/component.mdx. Regenerated by gen:docs: one table row changed. check:generated named only this artifact as stale.
  • .changeset/24140-line-items-columns-hydrate.md. @objectstack/spec patch, because the describe text ships in dist and in the JSON Schema.

packages/spec/src/data/field.zod.ts is untouched. InlineGridColumnSchema.label ("defaults to the child field's label via hydration") and type ("Declaring it opts the column out of schema hydration") were false for this one block. After this change they are true for every carrier, so they do not need to name record:line_items.

Measured before editing (origin/main cb8756b)

  • H1, the premise holds. component.zod.ts:2494 carried the "does NOT hydrate" describe, and field.zod.ts:971/:972 carried the hydration describes. On the renderer side, objectui main 26323c4 packages/plugin-form/src/LineItemsPanel.tsx hands applyColumnPermissions(schema.columns, …) to the grid. A grep for hydrate in that file returns zero hits. Control: the same grep finds hydrateColumns in deriveMasterDetail.ts, MasterDetailForm.tsx and their tests.
  • H2, the wording. The carriers' describe (inlineColumns, and columns on an object-master-detail-form detail entry) is "identity-only entries ({ name }) hydrate everything else from the child object's fields". objectui hydrateColumns (deriveMasterDetail.ts, objectui 26323c4) hydrates a column only when it declares no type, and it keeps an authored label. It fills label, type, required, options, the lookup target, the file props, readonlyWhen/requiredWhen and a computed expr. The new describe reuses the carriers' sentence and names the three keys the card names. It adds no narrower or wider rule.
  • H3, the liveness ledger. A case-insensitive grep for line_items in packages/spec/liveness/ hits only page.json:57 and view.json:351. In the page.json row regions, entry [15] cites columns L#gridField (applyColumnPermissions). That is a read point, not a quote of the old describe. No row quotes "does NOT hydrate", so the ledger is unchanged. Control: related_list hits twice each in field.json and page.json. The field.json inline-column rows (inlineColumns, lines 410-423) cite hydrateColumns, which stays true.
  • H5, other statements of the old behaviour. Hand-written content/docs/** (outside references/ and releases/) contains no sentence about line-items hydration. Positive control: the same grep finds record:line_items in content/docs/ui/react-pages.mdx, and layout-dsl.mdx:788 states the carriers' rule for object-master-detail-form. packages/lint has no rule that prescribes or enforces a label on these columns. validate-field-consumers.ts:392 says the block "derives nothing", which is about the column set and stays true. The skills/** and examples/** hits are listed under Acceptance notes and were not edited.

H4: accept/reject unchanged, measured on the built package

  • pnpm --filter @objectstack/spec build ran at the base cb8756b and again at a66b471. The script compares every JSON Schema with description removed and lists the description paths that changed:
    • ui/RecordLineItemsProps.json: structure identical once descriptions are removed; one description path changed, /properties/columns.
    • objectstack.json: structure identical once descriptions are removed; one description path changed, /$defs/ui/RecordLineItemsProps/properties/columns.
    • Every other schema file is byte-identical. The only other file that differs is .build-input-hash-schema.
    • Control for the instrument: comparing RecordHistoryProps.json against RecordLineItemsProps.json reports structure False, so the comparison can fail.
  • packages/spec/authorable-surface/ is byte-identical before and after the build.
  • inline-grid-column-carriers.test.ts passes unchanged, including the line-items section. Its test "CONTROL — defineStack does not judge an identity-only line-items column" still asserts that build() accepts { name: 'amount', scale: 2 } over a currency child field on record:line_items and refuses the same column under object-master-detail-form.

Tests (all at a66b471)

  • 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).
  • pnpm --filter @objectstack/spec test: Test Files 692 passed (692), Tests 20974 passed | 1 todo (20975), exit 0.
  • pnpm --filter @objectstack/spec typecheck: exit 0. This covers tsc --noEmit, check:scripts-typecheck and check:test-typecheck (OK, the debt ledger held).
  • No ablation. No tested behaviour changed: the diff is describe text, TSDoc, a regenerated doc and a changeset.

Gates (local subset, at a66b471)

  • Derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 102 commands over 3 paths, measured against the merge base cb8756b.
  • 101 exit 0. Six of them first refused with exit 3 (PREREQUISITE NOT MET) and were re-run after the prerequisite was met:
    • The closure build pnpm --workspace-concurrency=2 --filter '@objectstack/lint...' --filter '@objectstack/client-react...' --filter '@objectstack/objectql...' --filter '@objectstack/formula...' run build unblocked check:doc-formula-expressions, check:doc-security-posture, check:skill-examples, check:docs-transcript-drift and check:lean-entry-closure.
    • A one-commit fetch of the self-test fixture 621a4876 unblocked check-plugin-teardown-shape --self-test.
  • 1 NOT MEASURED: pnpm check:dual-build-cjs-loads needs every workspace package built. CI runs it in Lint & Repo Gates.
  • --ran reconciliation: "102 derived famil(ies) accounted for — 101 run, 1 NOT-MEASURED".
  • pnpm --filter @objectstack/spec check:generated reported content/docs/references/** stale before regeneration, and only that artifact.

Acceptance notes

  1. defineStack's resolved-type check does not reach record:line_items. collectHydratedInlineColumnErrors (packages/spec/src/stack.zod.ts) judges "inline grid columns whose TYPE comes from the child field" on three carriers. Once the renderer half lands, an identity-only record:line_items column takes its type from the child field too. A { name: 'amount', scale: 2 } column over a currency field will then publish green on this block and be reported only at render time, while object-master-detail-form refuses the same column at publish. Bringing the block into that check changes what publishes, so it is out of this Clause-② no card. It is reported for a separate card that depends on 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. The carriers test's CONTROL title ("the panel draws it unhydrated") describes the pinned renderer, and it flips with that card.
  2. The transition window. Until 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 lands and the .objectui-sha pin carries it, an identity-only record:line_items column still draws as a text cell headed by its field name. The TSDoc and the changeset both say this. The pin bump that carries objectui#12854 should delete the TSDoc sentence that begins "Until the .objectui-sha pin carries it".
  3. Showcase invoice page (held off). The comment above the columns in examples/app-showcase/src/ui/pages/invoice-document.page.ts (around lines 59-66) still states the old behaviour, and so does the docblock of examples/app-showcase/test/invoice-document-line-items.test.ts (lines 12-15). These belong to the showcase invoice card (showcase: the invoice print page's line-items table prints the raw field names description / quantity / unit_price / amount as its headings — its record:line_items columns declare no label, and that block draws a column exactly as declared #23985): its PR decides whether to drop the literal labels.
  4. skills/objectstack-ui/rules/pages.md:112-113 (Tier H, not edited). The print-page example writes identity-only record:line_items columns ({ name: 'product' }, …). That matches the new contract. Before objectui#12854 lands, those columns print raw field names.
  5. main moved while this was open. main gained 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 (the record:json retirement), which edits component.zod.ts at :458 and :2571 and removes the record:json section of component.mdx (lines 1793-1805). Neither touches this diff's hunks, so main was not merged in, per the dispatch's merge-on-conflict-only instruction. The PR's CI and the merge queue validate the merge.

Generated by Claude Code

…carriers

RecordLineItemsProps.columns said the block does not hydrate a column
from the child object's field. The shared InlineGridColumnSchema it takes
by reference says a column's label defaults to the child field's label
via hydration, and the master-detail carriers honour that. The describe
now states the carriers' rule in their words: identity-only entries
hydrate label, type and options from the child field, so the heading
translates with the child field's label; declaring type opts out.

The TSDoc names the renderer half (objectui LineItemsPanel reusing
hydrateColumns) and the defineStack resolved-type check that still walks
only the three master-detail carriers. Describe text only: no key, no
accept/reject change.

Claude-Session: https://claude.ai/code/session_01TyRhWbVbbQpQJTDbW8VahJ
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 143 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 727091c821d7dcaedb4eea547b77933838b471ed → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 64556c2676dbc9ccdaa3775b97db6fd869aee0ed — the merge of head a66b47182e19561578a63d0c3c4c7955dabca68d into base 727091c821d7dcaedb4eea547b77933838b471ed, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 64556c2676dbc9ccdaa3775b97db6fd869aee0ed && git checkout 64556c2676dbc9ccdaa3775b97db6fd869aee0ed
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 727091c821d7dcaedb4eea547b77933838b471ed a66b47182e19561578a63d0c3c4c7955dabca68d && git checkout -B drift-repro 727091c821d7dcaedb4eea547b77933838b471ed && git merge --no-ff a66b47182e19561578a63d0c3c4c7955dabca68d

node scripts/docs-audit/affected-docs.mjs --json 727091c821d7dcaedb4eea547b77933838b471ed

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: a66b47182e19561578a63d0c3c4c7955dabca68d
Local-runs: none
Scope: packages/spec/src/ui/component.zod.ts + packages/spec/src/data/field.zod.ts, packages/spec/src/stack.zod.ts, packages/spec/src/system/i18n-resolver.ts, packages/spec/src/inline-grid-column-carriers.test.ts, packages/spec/liveness/page.json, packages/spec/json-schema.manifest/ui.json, packages/spec/package.json, and in objectui at the pin 5e15928b4 (also objectui 26323c4fc): packages/plugin-form/src/LineItemsPanel.tsx, packages/plugin-form/src/deriveMasterDetail.ts, packages/fields/src/widgets/GridField.tsx. Remainder of the diff (the lane seat's ACCEPT at TIER_DEFAULT): .changeset/24140-line-items-columns-hydrate.md, content/docs/references/ui/component.mdx — both read here too, for ② and ①-2.

Inputs: card #24140 (body, comments 6229394877 / 6234986989 / 6236296173), PR #24188 (body, file list, net diff against main, merge base cb8756b00), the head's check-runs. Code read with git show at a66b47182 and in the objectui checkout; nothing built, run or re-run.

① Derived judgments

  1. Accept set: unchanged — right. The only code line the diff touches is the .describe() string on columns: z.array(InlineGridColumnSchema).min(1); the Zod chain is byte-identical, no key is added or removed, no refinement moves. Consistent with the dev's H4 reading (JSON Schema structurally identical with descriptions stripped; authorable-surface/ byte-identical) and with Type Check · source gates green, which carries check:authorable-surface and check:docs. Clause-②: no is the right declaration.
  2. Public surface: description text only — right. The columns description in the shipped JSON Schema (ui/RecordLineItemsProps.json, the objectstack.json $defs copy) and one regenerated row in content/docs/references/ui/component.mdx (check:docs, green). json-schema.manifest/ui.json records schema names only, so it rightly does not move. Spec property liveness green; no ledger row quotes the old text (page.json:57 entries [15], [16], [109] are read points for record:line_items; view.json and field.json carry no line_items row).
  3. The new describe, claim by claim against the cited code — right.
    • "As on the master-detail carriers, identity-only entries ({ name }) hydrate everything else from the child object's fields": the carriers' sentence verbatim (field.zod.ts:1654 inlineColumns; component.zod.ts:7150 object-master-detail-form detail columns). objectui hydrateColumns (deriveMasterDetail.ts:305 at the pin) hydrates a column with no type: fills type, label (an authored one is kept), required, select options, lookup reference/displayField, file props, readonlyWhen/requiredWhen, computed expr. "label, type and options included" is a true subset.
    • "Declaring type opts a column out of hydration": if (col.type) return col — right, and it is InlineGridColumnSchema.type's own rule (field.zod.ts:972).
    • "headed by the child field's label and translates with it": the hydrated label is the child schema's field label, the same path the master-detail headings take. The page overlay's copy keys (PAGE_COMPONENT_COPY_KEYS, i18n-resolver.ts:2119: title, description, label, placeholder, emptyText on a component's own properties) never reach properties.columns[i].label, so the card's premise holds and hydration is the only translation path that adds no key — the dispatch's "no new key" is honoured.
    • "Required, with at least one column: nothing derives them": .min(1) unchanged; LineItemsPanel derives nothing. Dropping "drawn exactly as declared" was necessary: it contradicted hydration.
  4. The TSDoc (shipped as src/**/*.zod.ts) — right.
    • Transition window ("Until the .objectui-sha pin carries it … an identity-only column draws as a text cell headed by its name"): true at the pin 5e15928b4 (unchanged by this PR) and still at objectui 26323c4fc: LineItemsPanel.tsx:748 is applyColumnPermissions(schema.columns, …), zero hydrat hits in the file; GridField.tsx:1005 heads a column with c.label || c.name and hydrates nothing itself.
    • "collectHydratedInlineColumnErrors walks the three master-detail carriers and not this block": stack.zod.ts:3613 (inlineColumns), :3628 (subforms[].columns), :3639–:3645 (object-master-detail-form details[].columns); no record:line_items arm. "today currency, which refuses scale": HYDRATED_INLINE_COLUMN_TYPE has the one currency row.
    • Holding the gate extension out of this PR is right and correctly sequenced, not only out of scope: that gate judges a column "against the type they will render as" (its own docblock), and at the pinned console a line-items identity-only column renders as text, so judging it as the child field's type before objectui#12854 and the pin bump would refuse what today renders. It is a Clause-②: yes (narrowing) change of its own; the gap is disclosed in the shipped TSDoc rather than advertised closed (Prime Directive chore: version packages #10).
  5. field.zod.ts untouched — right. InlineGridColumnSchema's docblock (:946–:952) and the label/type describes (:971–:972) state the rule for the column, not per carrier; after this PR they are true on every carrier.
  6. Fixes #24140 — right. Triage's grade (6229394877) defines this card as the spec half, with the renderer half on its own card (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 dispatch claim (6234986989) names the dev's branch; The card this PR closes must claim this branch and Part-of PR must not also close its card are green.
  7. Face and tier — right. Three paths, none governed; reviewFace hits = packages/spec/src/ui/component.zod.ts (schema face, CONTRACT_REVIEW_TIER); head repo = base repo; Governed Surface Queue Guard green.

② Semver level

.changeset/24140-line-items-columns-hydrate.md: '@objectstack/spec': patch, Clause-②: no at a line start with no arm, body states before, after and the transition window; the PR body's Clause-②: no matches. @objectstack/spec is published (private unset; files ships dist, json-schema, src/**/*.zod.ts) and the changed text ships in all three, so patch — not skip-changeset — is right (AGENTS.md Post-Task Checklist 3). no with patch is the well-formed pair: nothing widens or narrows the accept set (①-1). No model identifier anywhere in the diff. Check Changeset green. Clause-②: no — agreed.

③ Boundary flags

open_questions: none declared. Dev flags (acceptance notes 1–5, deviations 0–3, out_of_scope_findings 0–4), each answered or escalated:

  • F1 — the defineStack gate does not reach this block (note 1, finding [0], deviation [3]). Answered: right to hold off, see ①-4. Escalated to the dispatching seat: file the card in objectstack at ACCEPT (Blocked-by: objectstack-ai/objectui#12854, back-link 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), naming two sentences this PR leaves behind for that card's PR to rewrite: (i) stack.zod.ts collectHydratedInlineColumnErrors docblock, "All three carriers of the column are walked" — shipped bytes on a non-exported function; once this lands there are four hydrating carriers and three walked, so "All" undercounts. The contract's truth is carried by the new TSDoc in component.zod.ts, so this is a flag, not a FAIL; a text-only rider here would equally do, and keeps Clause-②: no. (ii) inline-grid-column-carriers.test.ts:615–:620 ("pinned on purpose: … no hydration from the child object's field") and the CONTROL title at :740 — not shipped; the CONTROL assertion itself stays true and is the pin on the gate's reach.
  • F2 — the transition window (note 2, finding [1]). Answered: the shipped TSDoc and the changeset both state it; the describe (JSON Schema and docs) does not, which is acceptable under triage's spec-half-first route and Prime Directive Add comprehensive test suite for Zod schema validation #12 (the renderer half is filed with Blocked-by:), and the changeset's last sentence ("keep explicit labels on columns you need headed today") is the author-facing mitigation. Escalated to the pin bump that carries objectui#12854: delete the TSDoc sentence beginning "Until the .objectui-sha pin carries it".
  • F3 — showcase invoice comments (note 3, finding [2]). Answered: held off per the dispatch's hold-offs; non-shipping example comments; showcase: the invoice print page's line-items table prints the raw field names description / quantity / unit_price / amount as its headings — its record:line_items columns declare no label, and that block draws a column exactly as declared #23985's PR owns them.
  • F4 — skills/objectstack-ui/rules/pages.md:112–:113 (note 4, finding [3]). Answered: Tier H, untouched; identity-only columns match the new contract; no change owed.
  • F5 — main moved (note 5, deviation [2]). Answered: not merged, per the dispatch; mergeable per GitHub; main has moved again since (2bcaefba9 at this read) with no overlap on these hunks; the queue rebuilds the merge.
  • F6 — bare -- dropped --maxWorkers (deviation [0]). Answered: a local-run detail; CI's Test Core is the gate verdict.
  • F7 — closure builds and the shallow fixture fetch (deviation [1]). Answered: no bearing on the contract.
  • F8 — H5 rest (finding [4]). Answered: confirmed on the ledger at head (①-2).

Check-runs on a66b47182 as read at 2026-10-17T16:15Z: 27 success (among them Lint & Repo Gates, Build Core, Governed Surface Queue Guard, Type Check · source gates, Check Changeset, Spec property liveness), 5 skipped (the full-battery lanes), 7 in_progress (Test Core 1–6 of 6, Type Check · workspace), none failed. The gate verdicts are theirs; this verdict is on the contract. Landing still waits for every check green (contract-review.md, second pre-landing check).

Implemented-by: claude/issue-24140-line-items-hydrate-columns
Reviewed-by: session_01TyRhWbVbbQpQJTDbW8VahJ

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · PR #24188 @ a66b47182e (#24140) · domain:spec seat 1 · os-project-manager · session session_01TyRhWbVbbQpQJTDbW8VahJ · 2026-10-17T16:39Z

Reviewer of record. Every item below was checked against GitHub and the code, not against the report (6236296173 on #24140).

The PR goes to the merge queue in this act.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 17, 2026 16:40
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 17, 2026 16:40
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 17, 2026
Merged via the queue into main with commit 1489952 Oct 17, 2026
42 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-24140-line-items-hydrate-columns branch October 17, 2026 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/s tooling

Projects

None yet

2 participants