Skip to content

feat(spec)!: narrow ObjectMasterDetailFormPropsSchema.formType to the measured simple | tabbed - #11963

Merged
os-support-ai merged 3 commits into
mainfrom
claude/issue-11873-masterdetail-formtype
Aug 25, 2026
Merged

os-support-ai merged 3 commits into
mainfrom
claude/issue-11873-masterdetail-formtype

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes #11873

What

ObjectMasterDetailFormPropsSchema.formType narrows from bare z.string() to the measured z.enum(['simple', 'tabbed']) — the spec half of objectui#5939, which already tightened the objectui registry declaration to the same pair on the same measurement. Direction per triage (comment 5403285119): not open; only the retirement mechanics were this card's work.

Census (triage constraint 2 — run BEFORE narrowing)

In-repo authored-value census over every formType on master-detail blocks (fixtures, examples, catalog entries, tests, docs — *.ts/tsx/js/json/md/mdx/yml/yaml, excluding node_modules/dist/.cache): 106 repo-wide formType mentions, all classified; zero out-of-vocabulary values on master-detail blocks. The three authored master-detail values are all 'simple':

  • examples/app-showcase/src/ui/pages/project-workspace.page.ts:45
  • packages/spec/src/ui/component.test.ts (showcase master-detail pin)
  • packages/lint/src/validate-component-props.test.ts (master-detail node)

Positive control: the same sweep resolves real authored out-of-simple|tabbed values on the sibling object-form block — 'wizard' (component.test.ts, validate-component-props.test.ts, new-project-wizard.page.ts) and 'drawer'/'modal' (task-desk / renewals-pipeline JSX pages) — proving it sees authored values, not just declarations. objectui's equivalent census (objectui#5939) also read zero. No premise fork.

Retirement mechanics — why no ADR-0087 conversion entry

Both precedents (#8762, #8010) registered a conversion + migration entry; this narrowing deliberately does not, and the reasoning is recorded in the schema comment:

  1. No gate requires one (PM mechanism assumption, verified): check:authorable-surface tracks keys (the key survives), and no gate diffs enum values against the registries. check-adr-0087-registration requires the question answered in writing — the changeset carries the adr-0087: not-required (no-migration-prescription) disposition, and the gate accepts it (green).
  2. Unlike both precedents — where the dropped values were the schema's own declared vocabulary (and, for chatter, its default) — these four names were never declared for this block: the key was bare z.string(). There is nothing spec-promised to rewrite, and both censuses read zero authored occurrences.
  3. The conversion route would force packages/spec/src/migrations/registry.ts (conversionIds list + semantic entry), which is HELD by a sibling family dispatch this wave — the dispatch constraint forbids touching it. Since (1) and (2) make the entry unnecessary rather than deferred, this is a completed shape, not a debt; if the maintainer wants a belt-and-braces conversion (rewriting the four names → 'simple') it can land as a follow-up once the hold lifts.

Tests

  • Acceptance pins: 'simple' and 'tabbed' parse green on object-master-detail-form.
  • Rejection pins assert the specific zod issue — code: 'invalid_value', path: ['formType'] — for 'wizzard' (plain enum refusal, no prescription) and for each of wizard/split/drawer/modal (per-value prescription naming the honoured pair and object-form).
  • type-alias-convention.pin.test.ts Iso844 (input ≡ infer) verified green without edits — an error-mapped enum with no default/transform stays isomorphic, so the pin file is deliberately not in the diff.

Gates

Full @objectstack/spec build + check:generated (→ gen:docs regenerated content/docs/references/ui/component.mdx, included; re-run green after fix) + full spec test suite: Test Files 424 passed (424) / Tests 11281 passed (11281) (lock verdict command-exit 0, run at 7b3020f; the one later commit 11294ac touches only the .changeset/ marker, no test input) + typecheck incl. the test layer, check:liveness, check:empty-state, check:strictness-ledger, check:variant-docs — all green at final head 11294ac (command-exit 0). check-adr-0087-registration green at 11294ac (disposition accepted). Reverse verification from the committed state: reverting the enum to z.string() (mutation disk-confirmed: injected=1 / removed-remaining=0) turns exactly the 5 rejection pins red (5 failed | 2 passed) with the 2 acceptance pins green, restore disk-confirmed (get-calls=1). Full gate readings quoted in the report comment on #11873. Gate family re-derived from the actual diff with node scripts/pm/dispatch-gates.mjs.

Breaking ships as minor per the launch-window convention (scripts/check-changeset-no-major.mjs); the changeset names the four newly-rejected values and points authors at the two honoured ones.

Generated by Claude Code


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

2 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 45 of 222 client-bound route-ledger rows — the other 177 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run: 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.

Coarse fallback — 126 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 178f90c768155577dfacc04d5cf03aa4c5470e85 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 4a0ff18206cc7e9de5b6e5c1aa40e85187ab1dcc — the merge of head 11294ac5337c698ad7e178f55afa5be20847eb03 into base 178f90c768155577dfacc04d5cf03aa4c5470e85, 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 4a0ff18206cc7e9de5b6e5c1aa40e85187ab1dcc && git checkout 4a0ff18206cc7e9de5b6e5c1aa40e85187ab1dcc
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 178f90c768155577dfacc04d5cf03aa4c5470e85 11294ac5337c698ad7e178f55afa5be20847eb03 && git checkout -B drift-repro 178f90c768155577dfacc04d5cf03aa4c5470e85 && git merge --no-ff 11294ac5337c698ad7e178f55afa5be20847eb03

node scripts/docs-audit/affected-docs.mjs --json 178f90c768155577dfacc04d5cf03aa4c5470e85

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

@github-actions github-actions Bot added documentation Improvements or additions to documentation protocol:ui tests tooling labels Aug 25, 2026
@os-support-ai
os-support-ai marked this pull request as ready for review August 25, 2026 03:39
@os-support-ai
os-support-ai added this pull request to the merge queue Aug 25, 2026
Merged via the queue into main with commit d63b014 Aug 25, 2026
33 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-11873-masterdetail-formtype branch August 25, 2026 03:54
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/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ObjectMasterDetailFormPropsSchema.formType accepts any string — the spec half of objectui#5939, where the renderer honours exactly simple | tabbed

2 participants