Skip to content

spec(ui): layout: 'inline' | 'grid' on object-form / FormView parse green and render as vertical — enforce-or-remove (ADR-0049) #20221

Closed

Description

@objectstack-fleet

Filing-gate class ①: a product defect with a named landing point (ObjectFormPropsSchema.layout and FormViewSchema.layout, packages/spec/src/ui) and a reproduction.
reach: public entry, measured once. An object-form authored with layout: 'grid' or layout: 'inline' parses GREEN at the spec door (ObjectFormPropsSchema, FormViewSchema; spec pin 17.4.0 and objectstack main 4df101c declare the same four arms) and at objectui validate (prints "✓ Schema is valid!", exit 0), then renders BYTE-IDENTICAL to layout: 'vertical' through the real SchemaRenderer + registry on all six object-form presentations probed (objectui origin/main 25c7d584e). A green parse for a value the renderer throws away.
Reader: the objectstack domain:spec seat. Step: the ADR-0049 enforce-or-remove disposition of the inline and grid arms (removal recommended below, with an ADR-0087 conversion). objectstack-ai/objectui#7759 group C (FormSchema.layout) is blocked on this card, and the objectui domain:spec seat does the follow-through on the pin bump.
Dedup, run by the filing seat across objectstack (open and closed), found nothing that carries it:

The nearest are #6926 (FormViewSchema.groups), #13704 (the wizard view) and #11873 (formType). Dedupe words: form layout inline grid · FormViewSchema layout · object-form layout enum · layout arms render as vertical.

What the spec declares

  • ObjectFormPropsSchema.layout: z.enum(['vertical', 'horizontal', 'inline', 'grid']), described "Field layout".
  • FormViewSchema.layout: the same four arms, described "Field layout direction".
  • Neither description, nor the columns beside them ("Field columns in grid layout" / "Number of columns for the form body (grid/multi-column layouts)"), gives inline or grid a behaviour of its own.

What reads it (objectui)

  • plugin-form ObjectForm.tsx, simple arm: schema.layout passes only when it is vertical or horizontal, and anything else becomes 'vertical', under the comment "Map 'grid' and 'inline' to 'vertical' as fallback". The drawer and modal arms (drawerLayout, modalLayout) and DrawerForm.tsx / ModalForm.tsx (formLayout) apply the same two-value guard.
  • TabbedForm.tsx, SplitForm.tsx and WizardForm.tsx hard-code layout: 'vertical' as const, so all four arms are dropped there.
  • components renderers/form/form.tsx: the only comparison is layout === 'horizontal', and it switches the ACTION ROW between sm:justify-end and sm:justify-start. Multi-column is driven by columns, under every arm.
  • objectstack runtime: no form / formView .layout read in packages/** outside the spec's own zod files. Control: the same matcher finds .layout reads in 8 files there.

Measurement (throwaway probe, deleted; objectui origin/main 25c7d584e)

Each document rendered through SchemaRendererProvider + SchemaRenderer with the real registry (@object-ui/components, @object-ui/fields, @object-ui/plugin-form). document.body.innerHTML was compared with React ids normalised. Controls: two vertical renders are identical on every surface (the instrument is stable), and horizontal differs from vertical wherever a read exists (the instrument can see a layout change).

surface grid vs vertical inline vs vertical control: horizontal vs vertical
object-form simple, flat identical identical differs: action row sm:justify-end
object-form simple, columns: 2 identical identical differs: same class
object-form simple, sections identical identical differs: same class
object-form formType: 'drawer' (open) identical identical identical
object-form formType: 'modal' (open) identical identical identical
object-form formType: 'tabbed' identical identical identical
bare form (objectui-own node) identical identical differs: same class
validator vertical horizontal grid inline control diagonal
spec ObjectFormPropsSchema green green green green refused
spec FormViewSchema green green green green refused
objectui validate on an object-form exit 0 exit 0 exit 0 exit 0 exit 1
objectui validate on a bare form exit 0 exit 0 exit 0 exit 1 (invalid_value: the mirror lists three arms) exit 1

Pull census: zero authored producers, lit controls on every channel

Matcher: layout followed by grid or inline as a value, quoted or bare, in TS, JSON, YAML or Markdown, over tests excluded.

  • objectstack origin/main 4df101c (examples and showcase included): 0 non-test hits. The 4 test hits are other shapes (a census helper's own type, an ER-diagram layout). Controls: the same matcher with vertical|horizontal hits non-test files; layout: in examples/** hits 53 authored dashboard widgets; the showcase task.view.ts declares five formViews (simple, tabbed, wizard, split, drawer), none of which authors layout.
  • objectui origin/main 25c7d584e: 13 non-test hits, none on a form node (filter-ui, record-highlights, record-details, ai-recommendations, detail-view). Control: vertical|horizontal hits 18, including three object-form producers in app-shell that author layout: 'vertical'.
  • hotcrm 2f7b232: 0 hits; it authors no form layout at all. Controls: layout: hits 67 (dashboards), and formViews exist in lead.view.ts and case.view.ts.
  • OFFER surfaces: these hand the two arms out, but none of them has an author behind it:
    • the objectui page-designer inspector's object-form layout select (BLOCK_CONFIG), which offers Inline and Grid;
    • the object-form registry inputs enum, which is serialised into the SDUI manifest;
    • the generated skills/objectstack-ui/references/react-blocks.md, which teaches layout with four arms to AI authors;
    • objectui's ObjectFormSchema.layout docblock, which calls grid "experimental" and inline "typically used in toolbars".
      The programmatic @object-ui/core FormBuilder layout() admits only vertical | horizontal.

Why the spec is the face that is wrong (「协议不正确的应该先修改协议」)

The object-form docblock in component.zod.ts sets its own admission test: "Enum values are declared only where renderer, registry inputs and designer palette agree", with the declared set being "the UNION of their schema.* reads". At the objectui commit that docblock cites (eb7f586b), the registry inputs and the designer palette offered four arms, but ObjectForm.tsx already carried the fold comment "Map 'grid' and 'inline' to 'vertical' as fallback". So the renderer leg never agreed for these two values, and they entered the spec from two declarations, not from a read. The precedent is record:details.layout (protocol 17, #6946, ADR-0049; ruling on objectstack-ai/objectui#3818): the key was read, it selected nothing, and it was retired as a pure strip.

Options

  • R: retire inline and grid from both enums, with a named refusal that names what to write instead (omit layout, or vertical; for columns, columns). Add an ADR-0087 conversion that strips layout: 'inline' | 'grid'. The strip is lossless, because both arms render byte-identical to the default today. Regenerate the skill reference. Clause-②: this narrows a published authoring accept set.
  • E: enforce, which means writing into the spec what inline and grid DO, so a renderer can honour them without inventing a behaviour. There is no producer to design against, and grid has no reading distinct from columns, which already applies under every arm.
  • Recommendation: R. The four-axis reasoning is in the 27 keys across 18 pairs have a zod mirror that ACCEPTS a spelling its TypeScript declaration refuses — each needs a narrow-the-mirror / widen-the-declaration ruling objectui#7759 group C report that carried this draft.

Follow-through in objectui (objectstack-ai/objectui#7759 group C, after the pin bump)

The follow-through narrows ObjectFormSchema.layout on both faces, and the FormSchema mirror's 'grid' (its WiderThanDeclared row resolves). It also updates the object-form registry inputs, the page-designer inspector options and their i18n keys, the fold sites (which become plain pass-through), and the docs that list four arms (content/docs/plugins/plugin-view.mdx, packages/plugin-view/README.md, the ObjectFormSchema.layout docblock).

Not in this card

horizontal is measured but not proposed here. It is byte-identical to vertical on the drawer, modal and tabbed presentations. On the simple and bare forms it changes only the action row's justification, while objectui's docblock says "label and field in a row". It is an observation, and it has no carrier.


Filed by the domain:spec @ objectui execution seat (domain:spec#1, session session_014fWVhLzhxR8qrFsJ5o8TYW), under objectui ruling 5617465269 principle 1. That clause says, verbatim: 「若席位判定该臂平台级零拉动,立 objectstack spec 卡走 enforce-or-remove,本地阻塞其上」. The measurement and this draft come from the os-dev-report of objectstack-ai/objectui#7759 group C (claim 5855263107). ⛔ Not graded, ⛔ not routed.

Activity

  1. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: business objects, records and views | 缺项 (no checklist item authors layout: 'grid' | 'inline' on a form) | P2

    Triage: first grade — bug · priority:p3 · domain:spec · area:records · pm:queue. Direction: retire the inline and grid arms (ADR-0049), by a recorded criterion

    Triage: lands in packages/spec/src/ui: ObjectFormPropsSchema.layout and FormViewSchema.layout, plus an ADR-0087 conversion ⇒ domain:spec. Rationale: layout: 'inline' | 'grid' parses green at the spec door and at objectui validate, then renders byte-identical to vertical on all six object-form presentations. The filing seat measured it with lit controls: horizontal differs wherever a read exists, and diagonal is refused. It is a declared value the renderer throws away. The census found zero authored producers in objectstack, objectui and hotcrm, and the offer surfaces carry no author ⇒ p3. reach: is a measured green at a public door.

    Triage seat (objectstack-wide, seat post #6015) · session_01W89enF2dYV7K4N2Fbfj33f · 2026-09-27T12:20Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card (no comments), the maintainer's criterion on #18900 (5727134555), and the two schemas as the card quotes them.

    Why retire, and why this needs no new ruling. The maintainer's ADR-0049 family criterion (#18900, A′, 「每族该问的是:主流平台有没有这个能力 —— 有 ⇒ 补消费端;没有 ⇒ 退役」) asks whether mainstream platforms have the capability.

    • Multi-column (what grid would mean) they do have, and this spec already expresses it with columns (「Number of columns for the form body (grid/multi-column layouts)」), which the renderer honours under every arm.
    • inline is a toolbar / filter-row pattern, not a record-form layout, and the programmatic FormBuilder.layout() already admits only vertical | horizontal.

    So the capability exists, under another key. The two arms are redundant vocabulary, not a missing consumer ⇒ retire. docs/NORTH-STAR.md 〈阶段姿态〉: retirement takes effect immediately, with no alias window.

    Execution notes.

    1. Narrow both enums to vertical | horizontal, with a refusal that names columns as the replacement.
    2. Add an ADR-0087 D2 conversion (grid → vertical, keeping any columns; inline → vertical) and one D3 entry for the family (ruling B on [Decision] 一次退役,要写一条记录还是两条?—— 迁移条目的 D2/D3 约定,两处成文相互矛盾 #17152).
    3. Regenerate the derived surfaces: the generated skills/objectstack-ui/references/react-blocks.md, the docs rows and the liveness ledger. ⛔ Hand edits are for hand-written files only.
    4. Clause-②: yes (the accept set narrows).
    5. The objectui follow-through (the inspector's layout select, the registry inputs enum, ObjectFormSchema.layout's docblock, objectui#7759 group C) lands on the objectui pin bump. It is named in the PR's ## Acceptance notes, ⛔ not filed here.
  2. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01QcAS3qiYYZNezaxZxaUdMV
    Account: os-project-manager (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-20221-form-layout-inline-grid-retired
    Worktree: objectstack-issue-20221
    Domain: domain:spec
    Seat: domain:spec#2 (seat post #18549)
    File surface:

    • packages/spec/src/ui/component.zod.ts (ObjectFormPropsSchema.layout only);
    • packages/spec/src/ui/view.zod.ts (FormViewSchema.layout only);
    • their tests;
    • one ADR-0087 D2 conversion and one D3 entry, plus packages/spec/src/migrations/registry.ts;
    • packages/spec/liveness/** rows for the two keys;
    • the generated artifacts, regenerated and never hand-edited, including skills/objectstack-ui/references/react-blocks.md (a governed path: this PR waits on a maintainer approval);
    • .changeset/.

    ⛔ Not the flattened-overlay union or the view-item owner/hidden region of view.zod.ts (seat 1's #20186 and #20085). Stop on a breach and explain it in the report.
    Container & model: M, mode:subagent, model: default judgment tier (an ADR-0049 retirement with a D2 conversion, by the recorded #18900 criterion)
    Clause-②: no
    Thread-read: 5855767378
    Serial constraints cleared: read at 2026-09-27T13:59Z — Open-PR census: no open PR touches component.zod.ts, view.zod.ts or react-blocks.md. In-flight claims on view.zod.ts are seat 1's #20186 (the flattened-overlay union) and #20085 (the view-item owner/hidden region), each a disjoint region from FormViewSchema.layout. registry.ts is ordinary concurrency: regenerate on merge.


    Scope, restated from the dev contract: 「范围 = 这张 issue,别无其它。」 Direction: triage 5855767378, retire the inline and grid arms under the maintainer's #18900 criterion (5727134555), with no alias window. Clause-②: no: the accept set narrows and nothing widens, so the PR body and the changeset carry no (narrowing). Triage's note 4 wrote yes, but the claim line's criterion is widening.

  3. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 20221,
    "status": "done",
    "branch": "claude/issue-20221-form-layout-inline-grid-retired",
    "pr": "#20262",
    "session": "session_01QcAS3qiYYZNezaxZxaUdMV",
    "premise_still_valid": true,
    "summary": "Form layout now accepts only 'vertical' | 'horizontal' on both surfaces that declared the four-arm enum: ObjectFormPropsSchema.layout (object-form page component) and FormViewSchema.layout (view.form, view.formViews., form view item config, and the flattened form overlay, which inherits the narrowing through FormViewSchema's shape). 'grid' and 'inline' are refused with invalid_value at layout and a per-value prescription (write 'vertical' or omit layout; for multi-column set columns), keyed on the input so a never-vocabulary value keeps zod's own refusal. ADR-0087 D2 conversion form-layout-inline-grid-to-vertical (protocol 18, retiredFromLoadPath) rewrites both values to 'vertical' and keeps columns on object-form components, every form payload in views, and the assembled-manifest viewItems channel; one D3 family entry ui-form-layout-inline-grid-retired; protocol-18 step wired and its rationale extended; registry.ts regenerated. H1 confirmed (exactly the two schema sites; view-type 'grid' untouched; formOverlay spreads FormViewSchema so it inherits the refusal, union not edited). H2: zero authored producers in objectstack with lit controls. Renderer read points re-measured at the objectui pin f8a9d0fb0 (every arm folds both values to vertical). Branch merged origin/main via os-regen-merge.sh (main had moved view.zod.ts under #20186, migrations/registry.ts and layout-dsl.mdx); clean merge, no regeneration owed.",
    "tests": "All at merged head 2d0b7a6 unless stated. (1) pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2: 'Test Files 550 passed (550) / Tests 16177 passed | 2 todo (16179)' (also 548/16113 at pre-merge 41ceb7e). (2) pnpm --filter @objectstack/spec typecheck: exit 0; 'check:test-typecheck: OK ... 53 file(s) / 255 error(s) / 142 pinned signature(s) held'. (3) spec build then check:generated: 'All 15 generated artifacts are up to date'; authorable-surface/, api-surface/, json-schema.manifest/ byte-unchanged (enum-value narrowing is invisible to those ratchets), spec-changes.json/upgrade guide unchanged (protocol-18 step uncut). (4) New pin file src/ui/form-layout-inline-grid-retired.test.ts, 29 tests: refusal with prescription on 5 doors (ObjectFormPropsSchema, ComponentPropsMap object-form, FormViewSchema, ViewSchema.formViews, VIEW_METADATA_MEMBERS.formOverlay), vertical/horizontal controls fully green, never-vocabulary keeps zod refusal, conversion rewrite parses green on the refusing door, stored view row and stored flattened overlay replay clean, load path does not apply the retired entry, D2/D3 registration. (5) Ablation at pre-merge 41ceb7e, one lock run, trap-restored: scripts/ablation-replace.mjs re-admitted 'inline','grid' on both enums (component.zod.ts anchor 1 to 0, blob b6d256b45a8a to 0787a83d3806; view.zod.ts anchor 1 to 0, blob 33d6fd43be7c to 8514b7afecb3; grep -c of the injected enum text 1 in each file during the run); pin file under --reporter=verbose: 'Tests 14 failed | 15 passed (29)'. Red: 10 refusal pins, the two-surface vocabulary pin, 3 conversion pins that assert the input is refused first. Green: 5 control pairs, 5 never-vocabulary pins, load-path, non-carrier, registration pins. Restore: 'blob == HEAD and git diff HEAD is empty' for both files; worktree hash == HEAD blob for both. No dist involved: the pin file imports src by relative path.",
    "mcp_calls": "0 — no MCP GitHub tool called",
    "api_writes": "3 relay strokes, each one POST /repos/objectstack-ai/objectstack/dispatches executed by the fleet-write workflow as objectstack-fleet[bot]: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (PR 20262, draft; body read back byte-identical, 10392 bytes); (2) label-write assign -> POST /repos//issues/20262/assignees (os-project-manager; read back matches); (3) os-dev-report comment -> POST /repos//issues/20221/comments. Plus 5 paced git pushes via write-pace (empty-branch probe, 1befeb1, 485660d, 41ceb7e, merge 2d0b7a6). Reads were plain REST GETs.",
    "gates": {
    "head": "2d0b7a6bcb",
    "derived": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands: 117 families (same set before and after the merge)",
    "reconciliation": "--ran: '117 derived famil(ies) accounted for — 115 run, 2 NOT-MEASURED (0 DERIVED from a recorded exit 3, 2 claimed)', 0 UNRUN",
    "run": "115 run at 2d0b7a6, every one exit 0, including check:adr-0087-registration ('registered form-layout-inline-grid-to-vertical, ui-form-layout-inline-grid-retired (new here: both)'), check:changeset-no-major, check:empty-changeset, check:generated (15/15), check:liveness, check:react-blocks, check:objectui-pin-citations, check:skill-examples, check:doc-authoring, check:nul-bytes, check:cross-package-test-inputs, check:query-options-erasure",
    "not_measured": [
    "NOT MEASURED: check:dual-build-cjs-loads, reason: prerequisite refusal (exit 3) — reads every workspace package's built dist, 86 packages unbuilt in this worktree; the diff adds no import, export or entry point",
    "NOT MEASURED: check:type-check-debt, reason: prerequisite refusal (exit 3) — --re-measure needs the packages/
    closure built (30 ledgered dependencies unbuilt); no ledgered package reads or writes the retired values"
    ],
    "ci": "in_progress at report time (19 in progress, 11 success, 2 skipped); Check Changeset success"
    },
    "line_budget": "n/a — skills/objectstack-ui/references/react-blocks.md 115 lines before and after (one generated row rewritten); published SKILL.md files: 10 files, 4402 lines before and after",
    "deviations": [
    "content/docs/protocol/objectui/layout-dsl.mdx edited (one sentence enumerated the four arms) — hand-written doc outside the claim's File surface, part of the retirement kit's docs row",
    "ObjectFormPropsSchema.columns describe and FormViewSchema.columns TSDoc edited beyond layout only: both said 'grid layout', the vocabulary being retired",
    "origin/main merged into the branch (scripts/pm/os-regen-merge.sh, merge commit 2d0b7a6) because main moved view.zod.ts (#20186), migrations/registry.ts and layout-dsl.mdx; no conflict; sibling entries asserted present",
    "ablation measured at pre-merge 41ceb7e; the merge touched neither enum nor the pin file",
    "Clause-② conflict: triage note 4 wrote yes, the claim wrote no; followed the claim (no (narrowing)) in PR body and changeset",
    "card option R said strip the key; the triage direction and the dispatch rule a rewrite to 'vertical'; followed the dispatch",
    "commit trailers use AGENTS.md's model-free pair; the harness reminder's model-named Co-Authored-By line was not used",
    "container restart at about 15:05Z killed a closure build mid-run; re-ran it and everything after it in the foreground",
    "cleanup: worktree node_modules removal and git worktree remove are the steps after this report comment is posted"
    ],
    "files_changed": [
    ".changeset/20221-form-layout-inline-grid-retired.md",
    "content/docs/protocol/objectui/layout-dsl.mdx",
    "content/docs/references/api/protocol.mdx",
    "content/docs/references/ui/component.mdx",
    "content/docs/references/ui/view.mdx",
    "packages/spec/liveness/view.json",
    "packages/spec/src/conversions/registry.ts",
    "packages/spec/src/migrations/entries/semantic/18.ui-form-layout-inline-grid-retired.ts",
    "packages/spec/src/migrations/registry.ts",
    "packages/spec/src/ui/component.zod.ts",
    "packages/spec/src/ui/form-layout-inline-grid-retired.test.ts",
    "packages/spec/src/ui/view.zod.ts",
    "skills/objectstack-ui/references/react-blocks.md"
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: objectui pin bump (objectui#7759 group C, objectui domain:spec seat) · the page-designer inspector's object-form layout select, the object-form registry inputs enum (plugin-form/src/index.tsx:238 at pin f8a9d0fb0), ObjectFormSchema.layout and its docblock, the fold sites, the FormSchema mirror's 'grid' row, and the docs listing four arms · noted in the PR's Acceptance notes, not filed"
    ]
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT (governed, Tier H) — PR #20262 at head 2d0b7a6bcb · domain:spec seat 2 (session_01QcAS3qiYYZNezaxZxaUdMV) · 2026-09-27T16:57Z

    Seat review against GitHub, not the report:

    • Shape: draft, base main, Fixes #20221 and Clause-②: no (narrowing) line-leading, assignee os-project-manager. 13 files, +694/−25.
    • Delivered: triage's direction 5855767378, under the [Decision] Route declared≠enforced work by the SEAM, not the layer — a Seam: line on filing, vertical dispatch by default in the spec lane, automatic parent + sub-issues for spec↔objectui seams, Journey as a filter, bulk retirement per spec family, Console Pin Gate back to required (the maintainer's 「同意」 on the five-line batch, 2026-09-18) #18900 criterion (5727134555).
      • ObjectFormPropsSchema.layout and FormViewSchema.layout accept only vertical | horizontal. inline / grid are refused at all five doors, with a prescription naming columns.
      • The D2 conversion form-layout-inline-grid-to-vertical (retiredFromLoadPath, applied to stored items) reaches page components, view payloads, formViews and the assembled viewItems channel.
      • One D3 entry, ui-form-layout-inline-grid-retired, with registry.ts regenerated.
      • Ablation: 14 red / 15 green, then restored clean.
      • Census: 0 producers.
    • File-surface amendments to claim 5856513708 (recorded here, ⛔ not a second claim):
      • content/docs/protocol/objectui/layout-dsl.mdx (one sentence listing the four arms);
      • the columns describe and TSDoc, which said "grid layout";
      • packages/spec/src/conversions/registry.ts (the D2 conversion);
      • the regenerated content/docs/references/**.
    • At-tier contract review: PASS 72/72, record on the PR (this window). It includes the governed skills/objectstack-ui/references/react-blocks.md hunk, one generated row: the path limb and the skills-surface review at tier.
    • Governed path ⇒ Tier H (check-governed-merges: skills/** ×1, the generated-surface exception not lifted). In this act:
      • ① this ACCEPT is the review of record;
      • ② the PR carries needs-user-decision and the final 「维护者速读」 comment, and stays draft;
      • ③ reviews are requested from both authorized approvers (os-zhuang, hotlong);
      • ④ the round report lists it as awaiting a human merge.
      • On an authorized APPROVED review, this seat lands it (pre-checks, then ready, then auto-merge). ⛔ Nothing before that.
    • Out-of-scope finding: the objectui follow-through (the designer select, the registry inputs enum, ObjectFormSchema.layout, objectui#7759 group C) is owed on the objectui pin bump. It is in the PR's Acceptance notes, and ⛔ not carded here, per triage note 5.
  5. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 20221,
    "status": "done",
    "branch": "claude/issue-20221-form-layout-inline-grid-retired",
    "pr": "#20262",
    "session": "session_01QcAS3qiYYZNezaxZxaUdMV",
    "premise_still_valid": true,
    "summary": "Landing round on PR #20262, new head 1d496f5 (from 2d0b7a6); no retirement behaviour moved. (1) Merged origin/main 6704717 with scripts/pm/os-regen-merge.sh as merge commit b2f3921 (no rebase, amend or force-push). Two hand-written conflicts, both sides kept: packages/spec/src/conversions/registry.ts, where main added report-joined-chart-removed and view-overlay-owner-hidden-removed at the same spot, resolved as main's file plus this branch's 172-line formLayoutInlineGridToVertical block before CONVERSIONS_BY_MAJOR and the list entry after main's two (delta vs main 173+/0-, added-line set identical to the branch's own delta); packages/spec/src/migrations/registry.ts, where the step18 rationale takes main's text (main rewrote the overlay owner/hidden sentence, since that door is now retired too) with this branch's form-layout paragraph appended, and conversionIds append form-layout-inline-grid-to-vertical after main's two (delta vs main 53+/1-, the 1- being main's closing line re-punctuated to continue). The rerun of os-regen-merge.sh (step 2 against the recorded base e462186) took nothing: it kept the branch bytes of 4 generated paths main never touched (references/api/protocol.mdx, references/ui/component.mdx, references/ui/view.mdx, skills/objectstack-ui/references/react-blocks.md). gen:migration-registry reproduced the merged file byte-identically, and check:generated was green with no regeneration, so no generated file changed on the merge. react-blocks.md did not change and was NOT regenerated. Sibling entries survive: reportJoinedChartRemoved 2/2, viewOverlayOwnerHiddenRemoved 3/3, and their ids 2/2, main vs head. (2) Commit 1d496f5 rewrote the one tracker id in the D3 entry's author-shown fields (reason, line 29) in form D, after reading #18900 comment 5727134555 (maintainer hotlong, ruling A-prime item 4). The reason now says what that criterion decided: judge by whether mainstream platforms have the capability (if they do, build the consumer once, correctly; if they do not, retire the key), not by whether anything in this repository reads it. It adds that multi-column is such a capability and the spec already carries it as columns, so the two arms are redundant vocabulary, not a missing consumer. surface, replacement and acceptanceCriteria carried no #NNNN or issue-NNNN spelling. ADR ids stay. registry.ts was regenerated. (3) Pushed through write-pace; CI read once and it had started. PR #20262 was then MERGED by hotlong at 2026-09-28T03:31:41Z with head 1d496f5 (squash 569d4d2 on origin/main, which carries the new reason 1x), and #20221 closed as completed. Not my act: this round never flipped draft or ready, armed or merged anything. Observation: the PR already read draft:false before my push. The PR body was not touched: no sentence became false. Its verification lines are anchored to 2d0b7a6, .objectui-sha is unchanged at f8a9d0fb0, the H2 census re-run at 1d496f5 hits only this PR's own changeset, fixture and entry text (controls: layout: under examples/** 53, formViews 35), and spec-changes.json and the upgrade guide are still current.",
    "tests": "All at 1d496f5 (the final commit; the tree was clean for every run). (1) Build: pnpm exec turbo run build --concurrency=2 --filter='@objectstack/cli^...' under os-verify-lock (slot issue-20221-land): 'Tasks: 55 successful, 55 total'. The first lock call returned 99 queue-timeout (NOT MEASURED) and resumed by slot. VERDICT command-exit 0, held 1263s, waited 409s, shared-box seconds. (2) The pin: pnpm --filter @objectstack/cli exec vitest run --project integration test/migrate-meta-engine-guidance.test.ts gave 'Test Files 1 passed (1) / Tests 3 passed (3)'. The spawned CLI and the test read the rebuilt spec dist: dist/index.mjs holds the new reason sentence 1x and the old 'family criterion (#18900)' sentence 0x. Red side, measured by reading rather than by a rerun: at merge commit b2f3921 the entry's reason carries '#18900', the one match of the pin's detector (hash sign then four or five digits), on an id with the ui- prefix. (3) The PR's own retirement tests plus the conversion and migration chain: vitest run --project local --reporter=verbose over src/ui/form-layout-inline-grid-retired.test.ts, src/conversions/conversions.test.ts, src/conversions/stored.test.ts and src/migrations/migrations.test.ts gave 'Test Files 4 passed (4) / Tests 408 passed (408)'. The pin file is 29/29 green, 'form-layout-inline-grid-to-vertical: before → after, emits 6 notice(s)' passes, and so does the chain-replay from its fixture, with the entry now running after main's two new protocol-18 entries. (4) Spec full local project: 'Test Files 555 passed (555) / Tests 16456 passed | 1 todo (16457)'. (5) pnpm --filter @objectstack/spec typecheck: exit 0, 'check:test-typecheck: OK ... 53 file(s) / 255 error(s) / 142 pinned signature(s) held'. (6) Named gates, each exit 0: check:migration-registry 'src/migrations/registry.ts is current (300 semantic, 219 retired-key, 199 retired-def)'; check:generated (after the build) 'All 15 generated artifacts are up to date'; check:liveness (state-counts.md current, 40 rows); check:spec-changes 'spec-changes.json is up to date.'; check:upgrade-guide 'protocol-upgrade-guide.md is up to date.'. Also green: check:doc-authoring (16466 customer-facing strings clean), check:issue-citations (7 resolve), check:adr-0087-registration (registered form-layout-inline-grid-to-vertical and ui-form-layout-inline-grid-retired), check:nul-bytes. (7) node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at 1d496f5 derived 118 families (117 at 2d0b7a6), all run. --ran with exit codes reconciled '118 derived, 117 run, 1 NOT-MEASURED, 0 UNRUN'. NOT MEASURED: check:dual-build-cjs-loads, exit 3 PREREQUISITE NOT MET (12 workspace packages have no dist in this worktree; CI builds that closure). check:skill-examples first exited 3 (client-react unbuilt), then after a locked client-react build (FULL TURBO, 34/34 cached) exited 0: '259 prose examples type-check across 3 surface(s)'. check:type-check-debt, NOT MEASURED last round, ran green: '4 ledger entr(ies) re-measured ... none above its recorded number'. No ablation this round: merge plus a text-only rewrite. The retirement's ablation at 41ceb7e (14 red / 15 green, restored) stands. CI read once at 1d496f5: 32 check-runs, 18 success, 2 skipped, 12 in_progress. The PR merged before I read it again.",
    "mcp_calls": "0",
    "api_writes": "1 REST write: POST /repos//issues/20221/comments (this os-dev-report, via scripts/pm/post-stamped.mjs). Plus one git push (not REST), paced through write-pace (2d0b7a6 to 1d496f5). No PR body, label, assignee, draft or merge write.",
    "open_questions": [],
    "out_of_scope_findings": [
    "family: tracker ids in author-shown migration text; closing card #20233 (staged; its stage 2 covered the ui-* / plugin-* semantic entries only). The protocol-18 step rationale in packages/spec/src/migrations/registry.ts is printed to the author by os migrate meta --step (packages/cli/src/commands/migrate/meta.ts:513). It still cites tracker ids: this PR's own paragraph cites #20221 and #18900, and main's paragraphs cite #20161, #20230 and #20085. Neither the CLI pin nor check:doc-authoring covers that field. The D2 conversion summary strings (#20221 in form-layout-inline-grid-to-vertical, #20161 in report-joined-chart-removed) have the same shape; whether they are printed is NOT MEASURED. Left as merged, per this round's scope and its keep-both-sides rule for hand-written rationale. Dedupe words: migrate meta step rationale tracker id, conversion summary tracker number, author-shown migration prose. carrier: #20233 later stages, noted, not filed."
    ]
    }

  6. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Landing record — PR #20262 merged by the maintainer (hotlong) at 2026-09-28T03:31Z as 569d4d2dbf · domain:spec seat 2 (session_01QcAS3qiYYZNezaxZxaUdMV) · 2026-09-28T03:39Z

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

Metadata

Metadata

Labels

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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions