fix(spec,lint,metadata-protocol): correct the view container name ledger note; delete the unreachable list-view tabs walks - #21423
Conversation
…ger note; delete the unreachable list-view tabs walks The liveness row for the view container's body `name` stays `dead`, but its note claimed "a copy nobody reads". Measured, the metadata door stamps the save name into every saved view body (`normalizeViewMetadata`) and its overlay paths key on that copy (`hydrateOverlayIntoRegistry`, `mergePackageAwareOverlay`). The note and the ledger README now say so, and record why the key is kept rather than retired. The list view's own `tabs` is a tombstone on every list-view shape, so the two author-time walks that still read it (the lint list-view field-ref rule, `computeViewReferenceDiagnostics`) could never see it: the lint judges the parsed stack, and every view door refuses or strips the key. Both reads, and their fixtures, are deleted; each keeps its `userFilters.tabs` walk. The stale i18n-resolver comment that still called the list carrier live is corrected. Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
… the deleted tabs walks Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift Check2 anchor(s) derived from 3 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 139 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 28e65c82c6bb56932e3f040e0e35a6b5a66fdd13 && git checkout 28e65c82c6bb56932e3f040e0e35a6b5a66fdd13
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ceb4a939b42f7c91ac8e9d371df34b8663d3f7bc 7ee481ef2d32a880bc533f9f02b0eadaeeea1e92 && git checkout -B drift-repro ceb4a939b42f7c91ac8e9d371df34b8663d3f7bc && git merge --no-ff 7ee481ef2d32a880bc533f9f02b0eadaeeea1e92
node scripts/docs-audit/affected-docs.mjs --json ceb4a939b42f7c91ac8e9d371df34b8663d3f7bc |
Contract reviewServed-tier: Read at 2026-10-02T14:42Z by an isolated subagent of the seat session, against the card (#20301, body and all 24 comments), the PR body and file list (11 files, +88/−59), the net diff against ① Derived judgmentsAccept set at every metadata door: unchanged — right. No
Gate verdicts on the head, read at 2026-10-02T14:40Z: 24 success · 3 skipped ( ② Semver levelRight: three ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #20301
Clause-②: no
Stage 2 of the card, re-scoped by claim amendment
5953063959and its correction5953104466. Stage 1 (PR #20357) retiredlist.tabs. Stage 2 does not retire the view container's bodyname, because the A2 stop fired: the metadata door writes that key itself (os-dev report5953000865). What lands here is the corrected ledger record plus the carried notes from the stage-1 landing record5870707479.⛔ No tombstone, no conversion, no door change, no
view.zod.tskey change. #21412 (the runtime door accepts a contradicting containername) is not addressed here and remains open.What changed
1.
packages/spec/liveness/view.json, thenamerow: the status staysdeadand only the note is rewritten.verifiedAtis now 2026-10-02.liveas "authoring the property changes runtime behaviour". An authored containernameeither restates the key the container already registers under or contradicts it. Soos validate/os lintkeep theirliveness-dead-propertywarning ("drop it"), which is still the right advice.saveMetaItemrunsnormalizeViewMetadataahead of the schema gate, and it stamps the save name onto every view body that has none, containers included. This is pinned byview-container-runtime-expansion.test.ts. The overlay paths then key on the stamped copy:hydrateOverlayIntoRegistryregisters no body without aname, andmergePackageAwareOverlayslots a row by it. The ObjectQL boot loop also mints the derived key onto every stack container it registers.namedisagrees with its derived object key (#14666) #15319) refused direction 3. Triage's guard on this card forbids retiring a key the platform's own writer still sends. The note follows the ledger's "kept deliberately" precedent.viewcell carried the same false sentence and is corrected the same way. Theview.list.tabsrow's note now records that the two walks below are deleted.gen:liveness-countsprinted0 shard(s) rewritten, 0 pruned, and the totals are unchanged:988 live · 3 experimental · 1 live-elsewhere · 109 dead · 10 planned = 1111.2. The carried notes, at their re-measured locations.
packages/spec/src/system/i18n-resolver.ts: a comment still calledListViewSchema.tabsa live carrier. It now names the tombstone and saysUserFiltersSchema.tabsis the one carrier. This is a comment-only change.packages/lint/src/validate-list-view-field-refs.ts: thecheckTabs(listView.tabs, …)call is deleted. This rule isinput: 'parsed'in the authoring-rule registry, and every list-view shape tombstonestabs, so the key could never reach the call. TheuserFilters.tabswalk stays. Header prose that namedtabs[].filter/tabs[].viewas walked positions is updated.packages/metadata-protocol/src/metadata-diagnostics.ts: theview?.tabsread incomputeViewReferenceDiagnosticsis deleted. The write door refuses the key, and stored and artifact bodies have it stripped by the conversion replay (applyConversionsToStoredItem/applyArtifactForwardConversions) before they are served. A body that still carries it is badged bycomputeMetadataDiagnosticswith the tombstone prescription.packages/lint/src/validate-list-view-field-refs.test.tsandpackages/objectql/src/metadata-diagnostics.test.tsare deleted. The objectql case that asserted the deleted read now asserts the survivinguserFilters.tabsread on the same unknown field.HARD_CODED_FILTER_WALKSdropstabs.filter.field. The stage-1 tree-scoped absence pin (view-list-tabs-retirement.test.ts) drops those two files from its self-expiringRESIDUE, as that set's own assertion requires. The CLI i18n entry stays.3. Patch changesets:
@objectstack/spec(liveness/ is in itsfiles[]),@objectstack/lintand@objectstack/metadata-protocol. Each carriesClause-②: no. objectql changes only a test file, and itsfiles[]shipsdistonly, so it gets no changeset.Verification
HEAD
7ee481ef2d(base6d67ad5eca). Everyos-verify-lockrun below reportsVERDICT command-exit 0.pnpm --filter '@objectstack/objectql^...' buildpnpm --filter @objectstack/spec check:generated✓ All 15 generated artifacts are up to datepnpm --filter @objectstack/spec typecheckpnpm --filter @objectstack/spec check:liveness✓ packages/spec/liveness/state-counts/ is currentpnpm --filter @objectstack/spec testTest Files 600 passed (600),Tests 17601 passed / 1 todopnpm --filter @objectstack/lint test && … typecheckTest Files 119 passed,Tests 5574 passed, test-typecheck OKpnpm --filter @objectstack/metadata-protocol exec vitest run --maxWorkers=2 && … typecheckTest Files 201 passed / 3 skipped,Tests 2983 passed / 19 skippedtypecheck,buildmetadata-diagnostics,view-container-divergent-name-registrars,metadata-validation-sweep:Tests 23 passed; typecheck OKDerived gates.
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsprinted 91 commands. Each was run, and its exit code was recorded before any pipe.--ranprinted✓ dispatch-gates --ran: 91 derived famil(ies) accounted for — 90 run, 1 NOT-MEASURED. That includescheck:adr-0087-registration(✓ … no declared-breaking changeset (3 non-breaking changeset(s) seen)),check-changeset-no-major(✓ This diff introduces no major bump),check-empty-changeset,check:changeset-gate-self-tests,check:doc-authoring,check:nul-bytes,check:cross-package-test-inputs, and every@objectstack/speccheck:*the derivation named.Two gates did not measure anything locally:
NOT MEASURED: check:dual-build-cjs-loads. It exited 3 (PREREQUISITE NOT MET) because it needs every package built, which this run did not do.NOT MEASURED: check-engine-split-ratio --days 90. It exited 2 withcannot compute … this clone is shallow. It is an ADR trigger metric over git history, and it is recorded as not measured rather than as a pass.check:lean-entry-closurefirst exited 3 for lack of objectql'sdist. After objectql was built it exited 0 (✓ … Admitted set held exactly).Narrowing, declared: the branch is not merged with
origin/main.ceb4a939b4is 7 commits ahead, andgit diff --stat 6d67ad5eca ceb4a939b4over this PR's 11 paths is empty. CI's merge ref judges the combination.Acceptance notes
tabs?: ListViewSchema['tabs']mirror (typesobjectql.ts) belongs to objectui. It picks up the stage-1 tombstone at its next pin bump, and this PR does not edit it.packages/spec/src/ui/view.zod.ts(theViewSchemaguidance comment, about lines 4720-4728) still says artifact-shipped containers and the validation sweep send the containername. That is the same misattribution the ledger note corrects. The comment is left alone, per this stage's no-view.zod.tsscope. Carrier: the next PR to touch that block, or none.skills/**: no hits for the touched surfaces.Generated by Claude Code