feat(spec): register the fourteen remaining door:'none' error codes that ship in dist - #16879
Conversation
…hat ship in dist Under the #16404 ruling (option D) the ledger is the published face: every code shipped in dist is registered, door or no door. #16449 took the nine measured on its tree; the fourteen boot-refusal rows that remained in dispatcher-error-vocabulary.ts — nine @objectstack/core refusals, MIXED_ARTIFACT_COLLECTION_SHAPE (runtime), DUPLICATE_ARTIFACT_OBJECT_NAME (objectql), the two drivers' *_MULTI_TENANT_UNSUPPORTED refusals and WALLED_MEMBERSHIP_POLICY_UNDECLARED (organizations) — gain ledger rows under their stamping packages, each measured present in that package's built dist/index.js. @objectstack/driver-mongodb returns as an owner key (the #8035 removal reversed on the record) and @objectstack/organizations is new. The fourteen vocabulary rows ratchet out as the gate's stale-row rule requires; the test that pinned MONGODB_MULTI_TENANT_UNSUPPORTED's absence now pins its presence, with OVERLAY_PERSISTENCE_FAILED as the retired-class witness and MULTI_TENANT_UNSUPPORTED as the still-refused control. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016N6xmWt5hYm94ffVEwGH8x
…usal-codes Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016N6xmWt5hYm94ffVEwGH8x
…prose-id baseline for the fourteen registrations
check:docs proved content/docs/references/api/{contract,error-code-ledger}.mdx
stale against the widened ledger (the ErrorCode union grows by fourteen, the
ledger page lists the fourteen rows); check:generated --fix regenerated only
that one artifact. check:doc-authoring's prose-id baseline over-pinned the
vocabulary module for two ids whose only carriers were the fourteen
boot-refusal rows that ratcheted out; the shrink-only census re-derives it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016N6xmWt5hYm94ffVEwGH8x
📓 Docs Drift CheckThis PR changes 2 package(s): 6 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
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 45cc42d5af1804dac68f93c2b8e9298c1e46414a && git checkout 45cc42d5af1804dac68f93c2b8e9298c1e46414a
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 4cfc93b80270b12854fc31f7a4837f1f8bcf5513 6738c993e35cf03fcfe1f6b7f142ad379eef04d7 && git checkout -B drift-repro 4cfc93b80270b12854fc31f7a4837f1f8bcf5513 && git merge --no-ff 6738c993e35cf03fcfe1f6b7f142ad379eef04d7
node scripts/docs-audit/affected-docs.mjs --json 4cfc93b80270b12854fc31f7a4837f1f8bcf5513
|
Seat answers both open questions, and owns a stale number of its own — 2026-09-08T13:28Z, head
|
Contract review — VERDICT: PASS WITH FINDINGS, BINDING: none. Enqueuing.Read 2026-09-08T13:28:06Z → 13:49:47Z, bound to head ⭐ Row 1 — the authority claim, which is why this review existedThe PR reverses #8035, which unregistered
⇒ "Door or no door" is the direct negation of "no envelope path ⇒ unregister." The newer ruling reaches the older one's ground, so the reversal is authorised.
The other rows
⭐ The runtime-bump question this seat asked, answered by measurementThe PR declares no Findings — all non-blocking, and this seat takes the reviewer's rating
Disposition
Generated by Claude Code |
Contract review (
|
Part of #16649 — the ledger half of the card: the fourteen
door: 'none'(boot-refusal) codes gain theirERROR_CODE_LEDGERrows. The card's second bullet — widen the gate'spackages/spec/src/refusal to every published package'ssrc/and retire theboot-refusalverdict — is deliberately NOT in this PR (section "What stays open" below), so #16649 remains open after this merges.Clause-②: yes
Ruling executed: #16404 (decision batch #62, 2026-09-07, option D, maintainer 「同意」), verbatim from the ruling comment: "Every
codethat ships indistmust be registered there; registering a code isClause-②: yes, door or no door, because it widens the published face." The first nine landed in #16449; this is the rest of that class.What changed
packages/spec/src/api/error-code-ledger.zod.ts— fourteen new rows, each under the package whosedist/index.jscarries the literal (measured, table below), each with the reachability reading its vocabulary row recorded. Two owner keys move:@objectstack/driver-mongodbreturns (its only row came out with [finding]MONGODB_MULTI_TENANT_UNSUPPORTEDmay be registered-but-unemittable in the error-code ledger — a boot refusal never reaches a wire envelope #8035),@objectstack/organizationsis new (the package's first row).packages/spec/src/api/error-code-ledger.test.ts— the pin that assertedMONGODB_MULTI_TENANT_UNSUPPORTED's ABSENCE now asserts the fourteen's presence under their owners (withstandardSynonymOfempty for each, andMULTI_TENANT_UNSUPPORTED— the drivers' shared constant NAME, never a stamped code — as the still-refused control);OVERLAY_PERSISTENCE_FAILEDbecomes the witness of the one retirement ground that survives [Decision] Clause ② on an UNREGISTERED error code carried by a thrown value: #14552 landedno, #15963 landsyes, and they are the same class #16404 (no producer left inpackages/**).packages/runtime/src/dispatcher-error-vocabulary.ts— the fourteenboot-refusalrows ratchet out. This is forced, not chosen:check:dispatcher-error-vocabularyderives a site only for a code the registered vocabulary lacks, so a registration makes the site vanish from the scan and the row that classified it reds asstale-row. The verdict itself stays declared (0 rows carry it on this tree); the running-log comment records the cycle. The module is not exported frompackages/runtime/src/index.tsandUNREGISTERED_CODE_SITEShas 0 hits inpackages/runtime/dist/index.js, so nothing published in@objectstack/runtimemoves.content/docs/references/api/{contract,error-code-ledger}.mdx— regenerated bycheck:generated --fix(the one artifact it proved stale): theErrorCodeunion count moves +308 → +322, the ledger page lists the fourteen.scripts/doc-authoring-prose-id.baseline.json— shrink-only census: the vocabulary module's#3724(1) and#8035(6) prose-id pins had the deleted rows as their only carriers..changeset/register-remaining-boot-refusal-codes.md—@objectstack/spec: minor(additive widening of a published face, finding(changeset): two independent contract reviews read the repo's own history to opposite bumps for "add an exported symbol to a published index" #15294's floor). Spec-only on purpose: no stamping package's source ordistchanges.The count, settled: fourteen, not two
The dispatch flagged that the card says fourteen while
node scripts/check-dispatcher-error-vocabulary.mjs --reportsays "2 awaiting a ledger entry". Both readings taken onorigin/mainc930f8597(a puregit archiveof that tree, no worktree state), exit captured before any pipe:--reportexit 0: "66 unregistered code-stamping site(s), all classified; 2 awaiting a ledger entry (spec: register the dispatcher conformance gate's reported error codes in ERROR_CODE_LEDGER (spec half of the #8087 ruling) #8846)". Its derivation lists the fourteen codes, each with verdictboot-refusal, and the two with verdictpending-registration(AMBIGUOUS_METADATA_STEM,owd_widening_forbidden).declared.filter(d => d.verdict === 'pending-registration')— it counts ONE verdict. The scan itself reports "only codes the registered vocabulary does NOT contain" (header bounds), so every one of the 66 derived sites is an unregistered code; the fourteenboot-refusalsites are unregistered by the same construction, they just sit under a different verdict label than the line counts.origin/main: 0 row hits for each of the fourteen (positive controlsUNIQUE_VIOLATION2,PLUGIN_REGISTER_FAILED1);StandardErrorCodeinerrors.zod.ts: 0 for each (controlPERMISSION_DENIED2).--reportexit 0, "51 unregistered code-stamping site(s), all classified; 2 awaiting a ledger entry", 279 ledger codes (265 + 14); the same twopending-registrationrows remain — the triage's item 2 says they are not this card's, and they are untouched.So the card's predicate ("
boot-refusalrows = shipped codes with no ledger row") is the one the #16404 ruling reaches, and the gate's "2 awaiting" is the older #8846 predicate (codes with a DOOR awaiting registration). Fourteen is right; the diff registers exactly those fourteen.Each of the fourteen ships in its package's
dist(word-boundary grep,dist/index.jsbuilt on this container)INVALID_ARTIFACT_PACKAGES·INVALID_ARTIFACT_PACKAGE_ENTRY·DUPLICATE_ARTIFACT_PACKAGE·NO_SUCH_RUN·PLAN_CHANGED·PREFLIGHT_FAILED·NOT_COMPENSABLE·SERVICE_NOT_REGISTERED·PLUGIN_CONTRACT_VIOLATION@objectstack/coreMIXED_ARTIFACT_COLLECTION_SHAPE@objectstack/runtimeDUPLICATE_ARTIFACT_OBJECT_NAME@objectstack/objectqlMEMORY_MULTI_TENANT_UNSUPPORTED@objectstack/driver-memoryMONGODB_MULTI_TENANT_UNSUPPORTED@objectstack/driver-mongodbWALLED_MEMBERSHIP_POLICY_UNDECLARED@objectstack/organizations(verified inpackages/plugins/organizations/package.json, not the card's@objectstack/plugins/organizationsguess)Controls:
UNIQUE_VIOLATIONin driver-memory dist 1 (positive); bareMULTI_TENANT_UNSUPPORTED0 and retiredOVERLAY_PERSISTENCE_FAILEDin core dist 0 (negatives). None of the six packages isprivate; each publishesfiles: ["dist", …].MONGODB_MULTI_TENANT_UNSUPPORTEDis a deliberate reversal of #8035, on the record#8035 unregistered it on the ground "host boot matching is not wire vocabulary"; #16404 supersedes exactly that ground. The ledger header's "Retiring a code" section now carries both halves, the row comment names the reversal, and the old absence pin is replaced by a presence pin — this is not an accidental revert.
Verification (tree
6738c993e=origin/mainc930f8597merged in; exit codes captured before any pipe)Heavy runs went through
scripts/pm/os-verify-lock.sh; itsVERDICTline is quoted where it applies. Each;-joined batch ends in the conjunction of its parts, so the wrapper's last-exit covers every part, and each part's own exit is echoed beside it.pnpm --filter @objectstack/spec buildVERDICT command-exit 0 · held the lock 145spnpm --workspace-concurrency=2 --filter '[BASE]' build(the packages main moved since the branch base; the root package was in the set, so its script ran turbo over the tree)VERDICT command-exit 0 · held the lock 389spnpm --filter @objectstack/spec testspec-test-exit=0— 465 files, 12967 tests passed (384.9s)pnpm --filter @objectstack/spec typecheck(tsc --noEmit+ scripts +check:test-typecheck, which compiles the test layer undertsconfig.test.json— the ledger test is in that program,tsconfig.jsonitself excludes**/*.test.ts)spec-typecheck-exit=0; wrapperVERDICT batch-last-exit 0 · held the lock 441spnpm --filter @objectstack/runtime typecheckruntime-typecheck-exit=0error-envelope.conformance,package-door-error-parity,http-dispatcher.error-leak,domains/actions-validation-envelope)runtime-targeted-exit=0— 4 files, 70 testsmeta-object-owd-gate,package-door-declared-code)rest-targeted-exit=0— 2 files, 47 testsdashboard-widget-options)sdui-targeted-exit=0— 1 file, 21 tests; wrapperVERDICT batch-last-exit 0 · held the lock 52snode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack→ 78 commandspnpm check:dispatcher-error-vocabulary(the family this card lives in)pnpm check:error-code-casing·check:nul-bytes·check:published-files·check:pm-widening-tells· speccheck:error-code-provenance·check:api-surface·check:export-origins·check:liveness·check:strictness-ledgerpnpm check:doc-authoring#37241,#80356) → baseline re-derived with the shrink-only census → rerun exit 0check:docs/check:generatedcontract.mdx,error-code-ledger.mdxstale) →check:generated --fixregenerated only that artifact → committed;check:generatedreports 14/15 up to date and the docs artifact regeneratedpnpm check:dual-build-cjs-loadsdistfor 37 packages) → after the tree build, exit 0: "104 published require entry point(s) across 67 package(s) load"pnpm check:type-check-debt--re-measureout of heap, once under a 4 GB override, once under the gate's own pinned 6 GB); a whole-tree family CI runscheck-changeset-fixed, speccheck:meta-url-spelling,check:spec-changes,check:authz-resolver,check:filter-alias-parity,check:partof-closing-keyword,check:error-status-conformance)check:partof-closing-keywordRULE 2 on the three commit messages, via the gate's owncommitRelationsextractor[]for each — no card-relation trailer in any commitAblation — the pin can fail, from the committed state
Subject resolves through source (
error-code-ledger.test.tsimports./error-code-ledger.zod), so nodistrebuild is in the loop. HEAD blob of the ledgera6912719a2cf3e6fc2c6cf80d44c95c3cb26f6ba; restore undertrap … EXIT INT TERMasgit checkout HEAD -- ABSOLUTE_PATH.'WALLED_MEMBERSHIP_POLICY_UNDECLARED',— anchor count 1 → 0 on disk; mutated blob809dde94771c…differs from HEAD.check:dispatcher-error-vocabulary→ exit 1:[unclassified-site] packages/plugins/organizations/src/membership-policy-gate.ts stamps unregistered code 'WALLED_MEMBERSHIP_POLICY_UNDECLARED' (classconst) and packages/runtime/src/dispatcher-error-vocabulary.ts does not classify it.× accepts the #16649 batch — the fourteen remaining door:none codes …, 1 failed | 19 passed.git diff HEAD --statempty,git status --porcelainempty, restored blob equals the HEAD blob, anchor count back to 1.What stays open on #16649 (the second half, not in this PR)
The card's second bullet — widen
SPEC_SOURCE_FACEinscripts/check-dispatcher-error-vocabulary.mjsfrompackages/spec/src/to every published package'ssrc/, and retire theboot-refusalverdict — is not here, for two reasons that the PM should weigh rather than this seat:pending-registrationtoo, and the twopending-registrationrows (AMBIGUOUS_METADATA_STEMunderpackages/metadata,owd_widening_forbiddenunderpackages/plugins/plugin-security) sit in published packages. Applied verbatim, "spec-face rule for every published package" reds both — and the triage's item 2 says those two are not this card's. Whether the widened rule keeps apending-registrationallowance outside spec until spec: register the dispatcher conformance gate's reported error codes in ERROR_CODE_LEDGER (spec half of the #8087 ruling) #8846 lands, or refuses only the retiredboot-refusalverdict, is a contract-shape question for the follow-up.Retiring the verdict now would also be premature by the gate's own design: the vocabulary's comment says a future pre-HTTP producer the scan finds lands as
unclassified-site, takesboot-refusal, then a registration, then comes out again — the verdict is the declared holding state for that cycle until the widened rule replaces it.验收备注
分诊席的验收口径逐条对照:
stale-row棘轮退出,本树上boot-refusal行数 = 0。✅pending-registration行(AMBIGUOUS_METADATA_STEM、owd_widening_forbidden)未动。✅boot-refusal判词:⛔ 不在本 PR(见上节 "What stays open"),本 PR 用Part of,卡片保持打开,由 PM 决定是拆卡还是同一认领续做。check:dispatcher-error-vocabulary与台账 pin 同时转红(见 Ablation)。packages/plugins/organizations/package.json的name是@objectstack/organizations。✅@objectstack/spec: minor。六个戳出包的源码与dist均未变(stamp 站点在origin/main与分支之间零 diff),@objectstack/runtime的 vocabulary 模块不在其发布入口内(dist/index.js零命中),故不欠各包 changeset。content/docs/releases/未碰。✅MONGODB_MULTI_TENANT_UNSUPPORTEDmay be registered-but-unemittable in the error-code ledger — a boot refusal never reaches a wire envelope #8035 反转已在台账头部、行注释、测试与 changeset 四处点名为依 [Decision] Clause ② on an UNREGISTERED error code carried by a thrown value: #14552 landedno, #15963 landsyes, and they are the same class #16404 的有意反转。✅Container & model:
M,mode:cloud(resumption),model: claude-fable-5-1(CONTRACT_REVIEW_TIER, passed explicitly on this dispatch). dispatch-gates--tierfor this dispatch printed a "Clause ② SUSPECT surface" block namingpackages/spec/src/api/error-code-ledger.zod.tsand…error-code-ledger.test.tsunderpackages/spec/src/**— *"the contract surface (error-code ledger, .zod.ts contract schemas) — the normal landing zone of a clause-② card", plus "whichever tier is dispatched, the PR's actual diff passes the clause-② enqueue gate before the card may enqueue." Card content widens the published error-code ledger ⇒ 强制条款② ⇒ fable.noted, not filed:
pnpm check:type-check-debt(--re-measure) ran out of heap on this container twice — once under a 4 GB override, once under the gate's own pinned 6 GB ceiling — and exited 3 (PREREQUISITE NOT MET, nothing measured). A whole-tree family CI owns; not a defect in the tree. 承接者:无(CI)。stale-rowrule makes the vocabulary write the mechanical consequence of the ledger write. Process note for the PM's file-surface template on this class. 承接者:PM。Generated by Claude Code