feat(spec): wizard view v1 — declaration-and-refusal tightening of FormViewSchema type:'wizard' (Card S) - #13733
Conversation
…steps refusal, ruled TSDoc (#13704) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PBjwYLS6BciTQW3c9xQiD2
…om customer-facing refusal text (#13704) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PBjwYLS6BciTQW3c9xQiD2
📓 Docs Drift CheckThis PR changes 1 package(s): 13 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 5 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin e743d4a7255d4b27791ed2095aaf9d2107a81f35 && git checkout e743d4a7255d4b27791ed2095aaf9d2107a81f35
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 787d757405db4f3ebbc6ca811948af4438a3fe7a cee7ddde998d2ebfe2649f8f7a843a1b572062d6 && git checkout -B drift-repro 787d757405db4f3ebbc6ca811948af4438a3fe7a && git merge --no-ff cee7ddde998d2ebfe2649f8f7a843a1b572062d6
node scripts/docs-audit/affected-docs.mjs --json 787d757405db4f3ebbc6ca811948af4438a3fe7a
|
|
放行(维护者词) — Provenance:维护者于本席 Claude Code 会话(session_01PBjwYLS6BciTQW3c9xQiD2,2026-08-31 ~12:4xZ)原话:
按「pr 绿了为什么不合并」→「12606 绿了」的在案个人放行先例执行。放行前核验:head Generated by Claude Code |
…sus line The changeset gains the not-required (no-migration-prescription) marker mirroring the #11519/#11842/#13733 narrowing precedents; the superRefine insertion shifted field.zod.ts line numbers, so the system-context page anchor is re-anchored by the census --fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PBjwYLS6BciTQW3c9xQiD2
Fixes #13704
Card S of the #13342 chain — the wizard view v1 declaration-and-refusal tightening of
FormViewSchematype: 'wizard', implementing the #13622 design of record (proposal D1–D8; maintainer ruling 2026-08-31, director batch #12, verbatim 「同意」 — T1 guidance-refusal, T2 narrow breadth, T3 defer buttons, T4 semver to this review chain, T5 existing superRefine). Zero new authorable keys. Card R (objectui#6985) follows after this lands and is deliberately not co-batched.What lands (all in
packages/spec/src/ui/view.zod.ts+ tests + gate-owned regenerations + changeset)FormViewSchemasuperRefine (thesection.panerefusal precedent) now refuses, ontype: 'wizard'only, the wizard-inert step keys: sectionvisibleWhen(and its deprecatedvisibleOnalias, whichnormalizeVisibleWhenfolds intovisibleWhenbefore the refinement runs — the message says so, since the reported path can only name the canonical key), andcollapsible: true/collapsed: true. It runs inside the same bucket loop as the pane check, so it covers the legacygroupsbucket and — via.extend()retention — the flattened runtime-overlay door. Breadth is ruled NARROW: exactly this family, no per-type presentation-key matrix (proposal F1 absorbed as not-done by the T2 ruling).collapsible/collapsedcarry.default(false), so post-parse an authoredfalseis indistinguishable from the default. Onlytrueis refused — an authoredfalsedeclares exactly the behavior a wizard delivers, so it stays accepted (pinned as its own test with the reasoning).steps:guidance-refusal (D3/T1) — aguidanceentry on the strict surface: the unknown-key rejection now carries the ruled prescription (sections ARE the steps; array order is step order). Never accepted as an alias.type: 'wizard'with absent or emptysectionsis refused loudly. Measured before-state: the renderer chain silently fell back to plain simple rendering (objectuiRecordFormPage's conditional spread +ObjectForm'ssections?.lengthguard). No "at least 2 steps" floor — a one-step wizard is legal.ViewSchema.form/formViews, the ViewItem config arms) and is deliberately exempt on the flattened runtime-overlay member — an overlay is a partial patch over a shadowed registry entry, and{ type: 'wizard' }beside the requiredobject+viewKindbinding is theoverlay.form.identityshape the sweep(spec): 2-item "validation diagnostics don't reach the real defect" sweep — one claim, one PR, per-item checklist (#6391 #5389) #7025 corpus pins as ACCEPTED (membership moves there require their own ruling, per the authoring-validation-not-persisted: a flat view body is accepted, published and reported valid, then expands to nothing — the write door judges by the wire union, not the strict ViewSchema #7741 precedent). The extension's requiredviewKindis the mechanical door marker (it can never appear on the strict base shape). The step-KEY refusals of item 1 run on every door — they fire only on keys the author wrote, never on a partial-overlay artifact.type: 'wizard';allowSkip= navigation freedom, not validation exemption; the gate is UI admission, never authorization; progress is derived state withshowStepIndicatorthe only authorable knob; per-step validation binds only the existing field-level vocabulary; array order IS step order. Landed in the wizard docblock +describe()strings, which project intocontent/docs/references/ui/view.mdxandapi/protocol.mdx(regenerated bygen:docs, committed here — no hand-authored teaching material; the docs(objectui): layout-dsl teaches only shapes the live schemas accept #13337/[finding] YAML doc fences are validated by nothing —check:skill-examplesreads onlyts/tsxfences, and only opt-in, so every metadata example incontent/docs/**is unverifiable by construction #13086 fence stands).@objectstack/spec: minor, argued as a BREAKING accept-set narrowing shippedminorunder the repo's launch-window convention, naming the nearest precedents (ActionSchema.onSuccessand a handler-returnedredirectUrlare both reachable on onetype: 'script'action, and the spec rules neither — renderer-side precedence is deciding it today #11519 / ActionSchema documents "newTabUrl is only valid together with opensInNewTab" but no refine enforces the pair (observation) #11842 ActionSchema narrowings, both minor + BREAKING header; mechanism precedent: thesection.panerefusal). ADR-0087 disposition:not-required (no-migration-prescription), mirroring those precedents. Final grade is this review chain's call.Census (before tightening)
Probe: repo-wide grep for
type: 'wizard'/type: "wizard"/"type": "wizard"over*.ts|tsx|json|yaml|yml|mdx|md(node_modules/dist excluded), plus asteps:sweep over examples and lint fixtures, plus key inspection of every hit.examples/app-showcase/src/ui/views/task.view.ts(thetask.view.ts:386accept-pin shape) and its mirrorpackages/lint/src/showcase-shape.fixtures.ts. Both carry onlyname/label/columns/fields, non-empty sections. Zero hits on the newly-refused shapes; zerosteps:on any form view; zero wizard examples incontent/docs. No premise fork — nothing to migrate.visibleWhencontrol file matches it; the test-fixture sweep found the bare{ type: 'wizard' }fixtures listed next, proving the probe reaches refused shapes where they exist.view.test.ts"accept all form view types" bare-wizard iteration — pinned exactly the removed branch, replaced with a stepped wizard + red pins for the bare spelling;view-union-diagnostics.test.tsoverlay fixtures ({ type: 'wizard' }+ binding) — kept, now pin the overlay exemption;component.test.tsformType: 'wizard'— different surface (page component), untouched;packages/lintfixtures — clean keys, untouched.Evidence
cee7ddde:src/ui/view.test.ts+view-union-diagnostics+view-inline-object-binding+view-form-features-root— 4 files, 422 passed (verify-lock VERDICTcommand-exit 0). Full@objectstack/specsuite: 443 files / 11883 passed. Downstream consumer with wizard fixtures,@objectstack/lint: 85 files / 2360 passed.@objectstack/spectypecheck (tsc + scripts + test program): green;--listFilesprovesview.zod.tsin the main program andview.test.tsin the test program (1 hit each — not the excluded-tests false green).view.zod.tsreverted to base blob668fb2d9(disk hash equal, tightening anchors grep 0), wizard-named tests re-run → 12 failed / 7 passed — exactly the 12 refusal pins predicted red, all 7 accept pins green; restore to HEAD blob1d1fcc7fhash-verified,git diff HEADempty, anchor count restored. No build leg by construction: spec's vitest imports./view.zodsource relatively — no exports-map/dist resolution on this pair.cee7ddde(derived viascripts/pm/dispatch-gates.mjs, no self-fed diff):check:authorable-surfacegreen ("All 14 generated artifacts are up to date" from check:generated; authorable surface unchanged — zero new keys),check:docs,check:yaml-examples,check:skill-examples("260 prose examples type-check across 3 surfaces"),check:doc-authoring(one hit fixed: internal issue id stripped from a customer-facing refusal message),check:liveness,check:strictness-ledger,check:variant-docs,check:empty-state,check:llms-txt,check:skill-refs,check:engine-double-contract,check:where-matcher,check:query-options-erasure,check:dispatcher-error-vocabulary,check:type-check-coverage,check:cross-package-test-inputs,check:nul-bytes, and the changeset gates (check-adr-0087-registration,check-changeset-no-major,check-empty-changeset,check:objectui-changeset,check:pm-half-states,check:changeset-gate-self-tests) — all exit 0 locally.check:dual-build-cjs-loadsandcheck-dev-prereqsrefuse without a whole-workspace build ("NOT a pass: nothing was measured") — CI's Build Core owns that farm; this diff adds no entry points or exports (api-surface current).scripts/pm/check-half-states.mjsexit 3 = its GitHub instrument unread from this seat (session-gated REST), a board patrol independent of this diff.check:react-declaration-parityneeds objectui's browser-built manifest by design. Shard attestation / test completeness are Test Core job steps over CI's own artifacts.Sequencing and fences
view.zod.tsis export: PDF / print document generation — re-planned for v18, superseding the #1301 NOT_PLANNED closure #8346's Restart-touch trigger file — the PM's notification stands; no PDF/export rider is taken here.content/docschanges are generator-owned regenerations only. The docs(objectui): layout-dsl teaches only shapes the live schemas accept #13337/[finding] YAML doc fences are validated by nothing —check:skill-examplesreads onlyts/tsxfences, and only opt-in, so every metadata example incontent/docs/**is unverifiable by construction #13086 fence stands until Card R also lands.Parked DRAFT with
needs:contract-reviewper the clause-② ruling — the review chain/maintainer owns enqueue; never ready/enqueued by this seat.Generated by Claude Code
Generated by Claude Code