docs(spec): navigation.view stops promising a view selection nothing performs - #17796
docs(spec): navigation.view stops promising a view selection nothing performs#17796os-bill wants to merge 1 commit into
navigation.view stops promising a view selection nothing performs#17796Conversation
…g performs `NavigationConfigSchema.view` described itself as "Name of the form view to use for details". Measured against spec source and the `objectui` tree this repo pins in `.objectui-sha`, no reader resolves an authored view name: - Its only read is `useNavigationOverlay`, which binds `navigation?.view` and passes that string as the SECOND argument of `onNavigate` — the slot whose other producers are navigation MODE tokens. - The hook also re-exports it on `NavigationOverlayState.view`, and no consumer reads that member, while its siblings on the same object (`width`, `isOverlay`, `mode`, `selectedRecord`) are read at ~20 sites. - Every `formViews` read in that tree is `formViews?.default`; none is keyed by an authored view name. - One shipped consumer types that argument `'view' | 'edit'` and branches on both with no fallback arm, so an authored name is a dead row click. The description now says that and carries the repo's existing `[EXPERIMENTAL — not enforced]` marker. No accept set moves: `view` is still `z.string().optional()` and every document that parsed before parses now. The enforce-or-remove decision (ADR-0049) is deliberately NOT taken here. Generated reference docs regenerated from the corrected description. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 136 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 d93e47ef990523b6275afdceeb39854ccfdfd9f5 && git checkout d93e47ef990523b6275afdceeb39854ccfdfd9f5
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 8fa3fe63d9e8dbbc507c0735d918c99db41df31d bec4767cc78de82366224351b85042bf546b27f2 && git checkout -B drift-repro 8fa3fe63d9e8dbbc507c0735d918c99db41df31d && git merge --no-ff bec4767cc78de82366224351b85042bf546b27f2
node scripts/docs-audit/affected-docs.mjs --json 8fa3fe63d9e8dbbc507c0735d918c99db41df31d
|
Third instance, and the first where the re-declared line is a
|
| corpus | view: z.string().optional() |
lit control preventNavigation |
dark control |
|---|---|---|---|
origin/main @ 8fa3fe63d9 |
2 | 1 | 0 |
| the PR's branch head | 2 | — | — |
⇒ same count on both sides. On origin/main the two sites are :1146 (a tab schema) and :1599 (NavigationConfigSchema, under its /** Target View Config */ comment). The PR changed only the .describe() string on that second line, which pushed it to :1615 — and the diff therefore re-emits the whole view: … line as an addition.
⭐ This instance sharpens the shape. The two earlier ones re-declared a key while restructuring around it. Here the diff does nothing but correct the prose inside an existing key's .describe() — arguably the most common edit anyone makes to a Zod schema — and T1 reads it as the accept set gaining a spelling. ⇒ the tell fires on a class of change that can never widen anything, because a .describe() string is not an accept set.
⛔ What this seat will not do
The only sanctioned clear is flipping Clause-②: no → yes. ⛔ Refused, for the third time: it would record on a permanent carrier that this PR widened a published accept set, which is false and measurably so. A declaration is a claim about the tree, not a key that opens a gate.
⇒ PR #17796 stays draft and unlanded until this card is fixed. Same disposition as #17157 / PR #17638.
domain:spec execution seat · session_01MkQhmuuJAVDjmeWNixwDDH · readings taken 2026-09-12T05:31Z on origin/main @ 8fa3fe63d9
Generated by Claude Code
Part of #16885 — this round is measure-and-report. Both repairs triage named (honour
view, or retire it under ADR-0049) are out of bounds for it, so the card stays open.What this changes
One
.describe()string onNavigationConfigSchema.view, plus the three generated reference-doc rows that project from it, plus a changeset.⛔ No accept set moves.
viewis stillz.string().optional(). Every document that parsed before parses now, with identical issues and identical output. Nothing is retired, renamed, constrained, or newly resolved.The measurement
Declaration —
packages/spec/src/ui/view.zod.ts,NavigationConfigSchema(unique in non-built source:preventNavigationoccurs exactly once outsidedist/, at that block).Reads — re-measured against source, not the bundle the card quoted. Repo-local: zero (
git grepover tracked files excluding**/dist/**; lit control —navigation.modeoccurs 5×).objectuiat the sha this repo pins in.objectui-sha(53ded82b, read withgit show SHA:PATH;dist/is untracked at that sha, so the reading is reproducible):navigation?.viewreadpackages/react/src/hooks/useNavigationOverlay.ts:245navigation?.mode/preventNavigation/openNewTab: 13 sites.viewwidth/isOverlay/modeon the same returned object: ~20 sitesformViewsread keyed by an authored view nameformViews?.defaultformViewsreads overall: 23 sitesThe one read binds
const view = navigation?.viewand then passes it as the second argument ofonNavigateat two branches (:287no-config,:320page) — the slot whose other producers in the same function are mode tokens (onNavigate(id, 'new_window')at:278and:301).A consumer with a closed vocabulary on that argument exists.
packages/app-shell/src/views/ObjectView.tsx:2540types it(recordId: string | number, mode: 'view' | 'edit')and branches on both values with no fallback arm — an authored name matches neither and the row click does nothing. The sibling consumer at:1957tolerates anything non-new_window, which is why the effect is invisible on some surfaces.Authored instances in this repo — zero, and the space is not vacuous:
ListViewSchema.navigationis set nowhere in-tree (every object-formnavigation: {in tracked files, 21 sites, is an i18n translation map). The scanner was proven on a synthetic fixture that lights for bothviewandmodebefore that zero was accepted.Which exit triage's two the measurement supports
Undetermined on the repair — and that is the finding. Both exits keep live evidence, neither is discharged:
summary_view,edit_form)", under a/** Target View Config */comment. Downstream,useNavigationOverlaypromotesviewto a first-class member ofNavigationOverlayState, which reads as a slot built for renderers and never wired. And a maintainer comment atObjectView.tsx:1968describes the forwarding path in so many words.lint-view-refsresolves app navigationviewName→listViews, a different key on a different surface). The specCHANGELOGnever mentions it, while the siblingsizework is mentioned 3×.objectui'sview-navigation-config-spec-parity.test.ts:139assertssite.navigation?.view === 'summary_view'. It uses{ view: 'summary_view' }only as a convenient mode-less config to pin type parity — it asserts the key is accepted, never that it resolves.⇒ Choosing between them is the seat's act: honouring
viewis new capability, retiring it narrows a published schema. This PR takes neither.Verification
At
bec4767c(the final commit).pnpm --filter @objectstack/spec build→VERDICT command-exit 0(shared verify lock), thenbuild-docs.ts→✅ Generated 222 files.check:authorable-surface·check:docs·check:generated·check:liveness·check:api-surface·check:skill-refs·check:skill-examples·check:llms-txt·check:variant-docs·check:empty-state·check:strictness-ledger·check:objectui-pin-citations·check:export-origins·check:duration-unit-keys·check:exported-any·check:dual-source-exports·check:entry-nameability·check:yaml-examples·check:browser-reachable-entries; repocheck:doc-authoring·check:doc-anchors·check:docs-single-h1·check:docs-spec-enumerations·check:docs-audit-scope·check:docs-redirects·check:docs-transcript-drift·check:nul-bytes·check:quick-reference-counts·check:corpus-claim-drift·check:published-files·check:org-identifier·check:role-word·check:slot-lookup·check:watch-hint-literal·check:spec-parsed-alias·check:page-declaration-shape·check:pm-widening-tells·check:skill-identifier-liveness·check:published-readme-links·check:type-source-resolution·check:test-source-alias·check:cross-package-test-inputs·check-adr-0087-registration --base origin/main·check-changeset-no-major --base origin/main·check-closing-keyword-parity·check-comment-mask-adoption·check-comment-mask-corpus·check-registry-log-declared·check-section-landing-index·check-plugin-teardown-shape·check-platform-object-tenancy-census·check-reference-carrier-shape·check-ci-filter-parity·check-affected-docs·check-undeclared-dep-imports·check-system-context-census.pnpm --filter @objectstack/spec typecheck→ exit 0. Targeted testssrc/ui/view.test.ts+src/ui/interaction-config-retirement.test.ts→ 373 passed.eslint . --no-inline-configover the whole repo → exit 0, no output. ⭐ Not a narrowing: the repo-level scan actually ran at this head, so no ratchet reading is deferred.check:doc-authoringcaught a real defect mid-round: the first draft of the description carried the card id, which that gate forbids inside.describe()prose because the prose projects into published docs where the citation resolves to nothing. The id was moved to the adjacent TSDoc block and the gate went green.Changeset — measured, not assumed. Owed.
@objectstack/spec's publishedfiles[]ships bothdistandsrc/**/*.zod.ts. On the rebuilt artifact the corrected sentence is present in 22 built bundles and in the published source file; the old sentence is absent from all of them. Positive control: a sibling shippeddescribe()(Disable standard navigation entirely) lit the same probe at 22. Negative control: a test-onlyit()title litsrcat 1 anddistat 0.验收备注
noted, not filed— the liveness ledger classifiesview/list/navigationas oneliverow with nochildren, so its six sub-keys (mode,view,preventNavigation,openNewTab,size,width) are classified nowhere andnavigation.viewinheritslivefrom its container. It is also absent fromundrilled-containers.baseline.json, whose own_containersnote claims to record every such gap. This is not a new card: it is exactly the defectcheck-livenessdrills exactly ONE level, so achildrenmap at depth 2 is silently ignored — no evidence resolved, no unclassified report, no warning that any of it is missing #17424 already describes ("check-livenessdrills exactly ONE level"), whose stated fix includes migrating that baseline. 承接者:check-livenessdrills exactly ONE level, so achildrenmap at depth 2 is silently ignored — no evidence resolved, no unclassified report, no warning that any of it is missing #17424 —navigation.viewis a concrete, measured casualty for that round to cite.noted, not filed—ObjectView.tsx:1968(objectui, pinned sha) tells the next reader that a forwardednavigation.viewname is "resolved by RecordDetailView from its own config". RecordDetailView does resolve from its own config, but the forwarded name is dropped before it: the handler navigates torecord/:idcarrying only anoriginState.from. The sentence is therefore true about RecordDetailView and misleading about the name. 承接者: 无 in this repo — it is a comment in the read-only pinned checkout, and it belongs to whichever exit List viewnavigation.viewis declared in spec but resolves no form view — its only read lands it in theonNavigatenavigation-MODE argument #16885 takes.Generated by Claude Code