Repository navigation
fix(metadata-protocol)!: the exact read no longer serves an undeclared App-pair row the registry binds to no package; it adopts SchemaRegistry#overlayRowBinding over the served holders (ADR-0150 D4) - #33148
Conversation
…, not per deployment (ADR-0150 child B, part 1 of the webhook family) WIP: the switch, the platform-requested auth.* names, the bundle-addition rule, the package-scoped /meta read and the send's holder-filtered bundle. Claude-Session: https://claude.ai/code/session_01ADHkmTMDJkEC5D92VHoU5v Co-authored-by: Claude <noreply@anthropic.com>
…latform-requested auth names and the bundle-addition rule Claude-Session: https://claude.ai/code/session_01ADHkmTMDJkEC5D92VHoU5v Co-authored-by: Claude <noreply@anthropic.com>
…rrowing Claude-Session: https://claude.ai/code/session_01ADHkmTMDJkEC5D92VHoU5v Co-authored-by: Claude <noreply@anthropic.com>
…nd a pair's member as the package's own A read naming a dependent whose only member of a bundled name is an addition (a locale its base does not ship) was refused not-held-by-qualifier once email_template joined the package-scoped readers, and a pair's added member on its base's address was replaced by the registry's item. The qualifier now asks the holders as the caller it names, and keeps an item of a pair of the admitted package. The co-owner dogfood case asserts the ADR-0146 D2 refusal a co-owner meets first at install-local. Claude-Session: https://claude.ai/code/session_01ADHkmTMDJkEC5D92VHoU5v Co-authored-by: Claude <noreply@anthropic.com>
…he email template's narrowing; changeset Claude-Session: https://claude.ai/code/session_01ADHkmTMDJkEC5D92VHoU5v Co-authored-by: Claude <noreply@anthropic.com>
…inst its base Claude-Session: https://claude.ai/code/session_01ADHkmTMDJkEC5D92VHoU5v Co-authored-by: Claude <noreply@anthropic.com>
…ule top Claude-Session: https://claude.ai/code/session_01ADHkmTMDJkEC5D92VHoU5v Co-authored-by: Claude <noreply@anthropic.com>
…s base's address for a bundled type only Claude-Session: https://claude.ai/code/session_01ADHkmTMDJkEC5D92VHoU5v Co-authored-by: Claude <noreply@anthropic.com>
…rowing; pin the qualifier's holder ask for the nine Claude-Session: https://claude.ai/code/session_01ADHkmTMDJkEC5D92VHoU5v Co-authored-by: Claude <noreply@anthropic.com>
…-3giljf Claude-Session: https://claude.ai/code/session_01WGufzgX7CHbaN1f2ZtiAiS Co-authored-by: Claude <noreply@anthropic.com>
…mplate send resolves its name from the caller's package (ADR-0150 D3) The flow notify node records the package whose own flow body is armed beside its template reference; the email and inbox channels hand it to sendTemplate/renderTemplate as callerPackageId; the registry loader resolves the name from it and, for a name two packages hold, reads the resolved holder's own address. A send that names no package keeps the bare-name meaning. Claude-Session: https://claude.ai/code/session_01WGufzgX7CHbaN1f2ZtiAiS Co-authored-by: Claude <noreply@anthropic.com>
…is refused on both exact reads and listed by the upgrade report Two packages of one App share the App's customization pair, so a locale row there with no overrides declaration cannot say whose template it extends: each holder's exact read refuses it naming every holder, the list scoped to a holder leaves it out, and os migrate stored-references lists it under pairMembers. One holder, the App's own address and a row that declares its base keep being served. Pins for F1 (loader rungs, service ladder, notify node, channels, dogfood) and F2; changeset. Claude-Session: https://claude.ai/code/session_01WGufzgX7CHbaN1f2ZtiAiS Co-authored-by: Claude <noreply@anthropic.com>
…otype.at, which the package's lib target does not declare Claude-Session: https://claude.ai/code/session_01WGufzgX7CHbaN1f2ZtiAiS Co-authored-by: Claude <noreply@anthropic.com>
…) for email_template, beside api Two packages of two namespaces may now each hold one email template name, so the second package's item no longer overwrites the first's in MetadataManager's in-memory store: a read naming a package answers that package's own, and a read naming none of a two-holder name is the D3 refusal (#31527 B-shape item 1). Pins that email_template has no metadata redactor, so a save never takes the carry-forward's code-layer read for it (item 4). Claude-Session: https://claude.ai/code/session_01WGufzgX7CHbaN1f2ZtiAiS Co-authored-by: Claude <noreply@anthropic.com>
…-3giljf # Conflicts: # packages/objectql/src/package-scoped-e8-readers.test.ts # packages/objectql/src/package-scoped-read.ts
…-3giljf # Conflicts: # packages/cli/src/utils/stored-package-references.ts # packages/metadata/src/package-slotted-store.ts
…es hold is no holder's own A package-less row (the environment's item, or a sys_metadata row bound to no package) of a name two or more packages hold is the customization of one holder and cannot say which (ADR-0150 D4). Each holder's exact read now refuses it 409 ambiguous-in-closure naming every holder, the list scoped to a holder (which a send made from it reads) leaves it out, and os migrate stored-references lists it under packageLessRows. One holder, the _env address and the platform-requested auth mails are unchanged. The rule sits in the exact qualifier, so it covers every type read by package (epic ruling 6761802819 on #31699). Claude-Session: https://claude.ai/code/session_01WGufzgX7CHbaN1f2ZtiAiS Co-authored-by: Claude <noreply@anthropic.com>
…-3giljf # Conflicts: # packages/objectql/src/package-scoped-e8-readers.test.ts # packages/objectql/src/package-scoped-read.ts
…eview round on #32214 - notify node: a literal payload `template` string records the armed package too, as the channels read it (F-A). - the pair-row owner check is one self-contained function, pairRowOnAddress, which the exact read and the scoped list both ask: the declared base first (F-B), the App's own pair, two owners refused, a sole owner that is not one of the address's bases not served (S2). - SchemaRegistry.getPackageScopedItem skips a pair row that declares another holder as its base, so the App's address answers its own item. - stored-references hints, its module doc and the changeset say truthfully that no door binds an added member to one base today (#28777) (F-C). - changeset: Metadata-protocol narrowed; slotted set lists api, agent, skill and email_template; the package-less rule names PACKAGE_SCOPED_READ_TYPES; the pair row's sole-owner and App-slot rules. - email-service docs page: the new callerPackageId member. Claude-Session: https://claude.ai/code/session_01WGufzgX7CHbaN1f2ZtiAiS Co-authored-by: Claude <noreply@anthropic.com>
…-3giljf # Conflicts: # packages/cli/src/commands/migrate/stored-references.integration.test.ts # packages/metadata/src/package-slotted-store.ts # packages/objectql/src/bare-name-one-holder.ts # packages/objectql/src/registry-bare-name-one-holder-ai-family.test.ts # packages/objectql/src/registry.ts # packages/qa/dogfood/test/bare-name-one-holder-flow-family.dogfood.test.ts # packages/services/service-automation/src/engine.ts
…-3giljf # Conflicts: # packages/metadata-protocol/src/protocol-exact-qualifier.ts # packages/objectql/src/bare-name-one-holder.ts
…ead an email template by package, as SchemaRegistry does With email_template narrowed to the namespace, #32277 refuses a bare read of it on a registry that says it reads the type through getItem (`narrowed`, 501). SchemaRegistry reads it by package since this change, so the four doubles that bare-read an email template say so and resolve it through their own item. Claude-Session: https://claude.ai/code/session_01WGufzgX7CHbaN1f2ZtiAiS Co-authored-by: Claude <noreply@anthropic.com>
…-3giljf # Conflicts: # packages/metadata-protocol/src/index.ts # packages/metadata-protocol/src/protocol-exact-qualifier.ts # packages/objectql/src/bare-name-one-holder.ts # packages/objectql/src/package-scoped-exact-qualifier.test.ts
…ed text The doc authoring guard refuses an internal issue id in a runtime string; the reference moves to an adjacent comment. Claude-Session: https://claude.ai/code/session_01WGufzgX7CHbaN1f2ZtiAiS Co-authored-by: Claude <noreply@anthropic.com>
…-3giljf # Conflicts: # packages/metadata/src/package-slotted-store.ts # packages/objectql/src/package-scoped-e8-readers.test.ts # packages/objectql/src/package-scoped-exact-qualifier.test.ts # packages/objectql/src/package-scoped-read.ts
…age reaches the package-less owner check `''` and the provenance sentinel `sys_metadata` count as no package before the owner check, so a package-less row the registry answers for a name two packages hold is refused at both exact addresses (contract review R2-A). Pins the exact read and the list of a member the holder itself ships beside such a row (R2-B); the changeset states the mail consequence and the review's prose nits. Claude-Session: https://claude.ai/code/session_01WGufzgX7CHbaN1f2ZtiAiS Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QSeKYm8sWjp2Pk76warN7w Co-authored-by: Claude <noreply@anthropic.com>
…t, and the exact read of a member the holder ships refuses beside it (R3-A) The fixture wrote the canonical member's package-less row as bundle_member 'en-US'; the store spells the canonical member NULL (overlayMemberValue), so the read never found it and the pin asserted the registry's answer. Written as stored, ?package=A for a member A ships answers 409 ambiguous-in-closure naming both holders, while A's list and the send's read serve A's own (epic ruling 6792134290). Claude-Session: https://claude.ai/code/session_01QSeKYm8sWjp2Pk76warN7w Co-authored-by: Claude <noreply@anthropic.com>
…er of every slot (R3-B) With email_template in PACKAGE_SLOTTED_STORE_TYPES, DatabaseLoader's loadMany / loadManyKeyed collapsed to one row per name, dropping every other stored locale of a bundle and every other package's bundle, where main answered every row. A bundled type now keeps one row per (package, name, member), the canonical member spelled null as the store's bundle_member column spells it; MemoryLoader answers every slot of a bundled type alike. A rollback by name of a one-slot name restores the row of the member its body declares (epic ruling 6796068023). Claude-Session: https://claude.ai/code/session_01QSeKYm8sWjp2Pk76warN7w Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 3 package(s): 22 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 10 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 174 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 0f011fc8af0d4fb34b9e7fa369858a14c1808aee && git checkout 0f011fc8af0d4fb34b9e7fa369858a14c1808aee
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 128b6571f476d4fae347d8f860b04b95927d2cce dd283faf40257bc209debc3d3aa66e11345f7405 && git checkout -B drift-repro 128b6571f476d4fae347d8f860b04b95927d2cce && git merge --no-ff dd283faf40257bc209debc3d3aa66e11345f7405
node scripts/docs-audit/affected-docs.mjs --json 128b6571f476d4fae347d8f860b04b95927d2cce
|
|
review#1 · os-tesla · session_01L9qibzosF5fZk98UHos9cv Contract-review-claim: session_01L9qibzosF5fZk98UHos9cv · head 72c8a9c · 2026-11-13T19:43Z |
|
review#1 · os-tesla · session_01L9qibzosF5fZk98UHos9cv Contract reviewServed-tier: First-round review, read at 2026-11-13T19:52Z. Inputs: card #32561 and its thirteen comments, the PR title and body as they stand, the diff against the merge base ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Findings:
Two must-fix. M1 needs a push, so the delta is this seat's on the new head; M2 can ride the same round. Implemented-by: VERDICT: FAIL |
…rule over every holder before leaving the disabled ones out SchemaRegistry#overlayRowBinding counted the pair's owners over the served holders and judged the addition rule over that same set, so a package adding only to a disabled holder's bundle became a second owner and the enabled holder lost an undeclared pair row ruling C keeps. The owners are still the served holders; the addition rule is settled over every holder, the order packageScopedHoldersOf uses. Pinned in both registration orders; the residual-1 helper now reads the execution list. Claude-Session: https://claude.ai/code/session_016WV4cwzajrQVjjx4Dh1CA5 Co-authored-by: Claude <noreply@anthropic.com>
… name through its own stored row, as packageScopedHoldersOf does SchemaRegistry#overlayRowBinding counted composite slots only, so a package holding the name only through its own stored row in the bare slot was no owner there: the App's undeclared pair row bound to the pair and the exact read withheld it at that package's address, where main served it. The holders are now the ones packageScopedHoldersOf counts: every composite slot, then the package each bare-slot entry binds to. Pinned in both registration orders beside the composite-slot CONTROL. Claude-Session: https://claude.ai/code/session_016WV4cwzajrQVjjx4Dh1CA5 Co-authored-by: Claude <noreply@anthropic.com>
|
review#1 · os-tesla · session_01L9qibzosF5fZk98UHos9cv Contract-review-claim: session_01L9qibzosF5fZk98UHos9cv · head dd283fa · 2026-11-13T20:25Z |
|
review#1 · os-tesla · session_01L9qibzosF5fZk98UHos9cv Contract reviewServed-tier: Delta review of FAIL 6863299225, read at 2026-11-13T20:48Z. Inputs: the interdiff ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
The same method (n1). Answered, and it was a move. The holders are now the ones
One reading left with the seat, no change asked: Findings:
M1, S1 and n1 of record 6863299225 are closed on this head. Once the line is in the body and Implemented-by: VERDICT: FAIL |
|
review#1 · os-tesla · session_01L9qibzosF5fZk98UHos9cv Contract reviewServed-tier: Close-out of FAIL 6864576272, read at 2026-11-13T21:13Z. Inputs: the PR title and body as they stand after the body edit, the check-runs on this head, knock 6864947326. The head has not moved, so claim 6864020185 still names it. Everything records 6863299225 and 6864576272 judged on the diff stands as read there. ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgmentNothing new to judge: no code moved. M1, S1 and n1 were closed on this head in record 6864576272, and the one reading left with the seat there (a second App's undeclared row keeps this pair's row bound to no package while one of that App's holders is disabled) stands as written. Findings:
Implemented-by: VERDICT: PASS |
|
epic:#31527#2 · os-elon-musk · session_016WV4czFhtRVZNBeHdQA6PW Epic red-line re-read · 2026-11-13T21:38ZHead-sha: This re-reads PR #33148 (card #32561, epic #31527, ADR-0150 D4), which declares
Merge base Everything below was measured on a scratch merge of this head with (1) Resolution is never loosened: holdsThe production change, read.
Focused file. Main's exact read on the same tree. I swapped in
Logging probe over whole suites. The scratch probe logs every
Scratch cases on both builds. I ran 17 scratch cases twice: once on the head, once on
Bare names: the changed line runs only for exact-address callers (six (2) Ambiguity is reported, never guessed: holds
(3) Every child is independently releasable: holds
Seat-routing observations
Carried paths and their cards
Scratch worktree |
|
epic:#31527#2 · os-elon-musk · session_016WV4czFhtRVZNBeHdQA6PW ACCEPT · 2026-11-13T21:39Z · head
|
Requested by Elon · project thread
Fixes #32561
Clause-②: yes (narrowing)
Metadata-protocol: narrowed
Skills-docs: none —
skills/objectstack-platform/SKILL.mdteaches the declared form (overrides: { package }) and an undeclared pair row only at a locale the base does not ship, the path the save door accepts; nothing inskills/**teaches the exact read of an undeclared pair row whose locale a later bundle addition also ships, or of a row beside another App's shared pair, the two reads this narrows (grep ofskills/**foroverrides.package,.custom,?package=andemail_templateat headdd283faf40).维护者速读
<app>.custom)里一条未声明基准包的行(没有overrides.package),如果注册表判定它“不属于任何包”(因为同 App 的另一个包作为附加包也出货了同一个语言成员,或另一个 App 的共享配对也存了同名未声明行),按包精确读(?package=X)以前仍把它当 X 的定制返回;现在精确读采用注册表的判定,?package=X只回答 X 自己出货的成员(没有就 404),?package=<app>.custom仍能读到这条行。SchemaRegistry#overlayRowBinding,让精确读直接问注册表,不再自己另数一遍。overrides.package的行、单一归属的行、两个持有包可归属时的 409 都不变;一个持有包被禁用时,启用那个包的地址仍保有该行(R4-A 裁决)。回滚 = revert 本 PR。packages/metadata-protocol/src/protocol-exact-qualifier.ts的pairRowOnAddress新增一行判定;packages/objectql/src/registry.ts新增的overlayRowBinding(只数被服务的持有包);packages/objectql/src/package-scoped-exact-qualifier.test.ts的[#32561]组。pnpm --filter @objectstack/objectql exec vitest run src/package-scoped-exact-qualifier.test.ts,预期全部通过;其中[#32561]组的 NARROWING(两种安装顺序 + 跨 App 配对)与 CONTROL(声明行、禁用一个持有包两种顺序)全绿。What changes
The exact read's owner check (
pairRowOnAddress,@objectstack/metadata-protocol) counted holders after the registry had bound the row: a bundle addition was no holder there, and another App's shared pair was never read. The registry (SchemaRegistry#pairRowBinding, since #32408 / PR #32815) counts an addition that ships the row's member as a second owner, and binds a row whose count would read another shared pair's undeclared row to no package. The two readers had no common answer (the card's divergence).Now the exact read adopts the registry's binding instead of counting again:
SchemaRegistry#overlayRowBinding(type, name, item)(new, public, read-only,packages/objectql/src/registry.ts): the bindingoverlaySlotBindinganswers, counted over the served holders (a disabled package holds no name, ADR-0150 D3), in the orderpackageScopedHoldersOfcounts the exact read's owner: the pair's owners are the served holders it customizes, and the bundle-addition rule is settled over every holder, the disabled ones left out afterwards, so a disable never promotes a dependent's addition to an owner (contract review M1). The holders are the onespackageScopedHoldersOfcounts: every composite slot, then the package each bare-slot entry binds to, so a package holding the name only through its own stored row is an owner here too (contract review n1). The registry's own readers keep counting every holder, so a disable never moves their binding.pairRowOnAddresstakes the binding lazily (registryBinding) and treats an undeclared pair row as not this address's member when its one owner is not the one the registry binds it to. Both callers (exactQualifierItem,pairMemberWithheldAt) pass it; a registry withoutoverlayRowBindingkeeps the exact read's own count.fr-FRas an addition;A.customstores an undeclaredfr-FRrow)?package=X&member=fr-FR(Z installed before the row, or after it)fr-FR: none,404?package=Z&member=fr-FRfr-FR?package=A.custom&member=fr-FR?package=Y/?package=Pwhen App A's pair and App B's pair each store an undeclared row of the name (registry binds neither)Unchanged (CONTROL pins): a row declaring its base (
overrides.package) binds and serves as declared; two holders that could own a row still refuse409naming both; a row whose one owner the registry binds it to is served as before; with one of two holders disabled, the enabled holder's address, list and execution list keep the undeclared row (residual (3), ruled C in 6837007729, keeping #32183 R4-A), re-enabled it is refused naming both; and the same when the disabled holder is the base of a bundle addition (Z on the App and on Y ships onlyfr-FR, Y disabled): Z stays an addition, X keeps the row; and when X holds the name only through its own stored row in the bare slot, X's address keeps the undeclared pair row as onmain.Files:
protocol-exact-qualifier.ts,registry.ts, the pins inpackage-scoped-exact-qualifier.test.ts(and one comment line inpackage-scoped-resolver.test.ts), the semantic entrypackages/spec/src/migrations/entries/semantic/18.pair-row-exact-read-no-owner.ts, and two changesets (metadata-protocol+objectqlminor, BREAKING,adr-0087: registered;specpatch for the entry).Tests
packages/objectql/src/package-scoped-exact-qualifier.test.ts, describe[#32561] …:?package=Xanswers nothing,?package=ZZ's own,?package=A.customthe row, X's list and X's execution list leave it out (contract review S1), and X's ownen-USstays X's.en-US, Z (on the App and on Y) ships onlyfr-FR, an undeclaredde-DEpair row, Y disabled: the owner count is[X], the adoption binds the row to X,?package=X&member=de-DEserves it and both of X's lists keep it, Z keeps its ownfr-FR; re-enabled, refused naming X and Y. Red on72c8a9c8ef(2 failed / 249 passed in the file:AssertionError: the adoption counts as the exact read does: expected undefined to be 'com.acme.suitex'), green at5a9d589a80.package_idX hydrated, no composite slot) and the App's pair stores an undeclaredde-DErow: the adoption binds the row to X,?package=X&member=de-DEserves it, X's ownen-USstays X's. Red on5a9d589a80(2 failed:AssertionError: the adoption counts X as the exact read does: expected 'com.acme.suite.custom' to be 'com.acme.suitex'), green atdd283faf40. Beside it, the CONTROL with X's item in its composite slot, both orders, also pins X's list and execution list.Ablations on head
dd283faf40(each throughscripts/ablation-replace.mjs, landing proved, restored to the HEAD blob withgit diff HEADempty):pairRowOnAddress's new line guarded off;metadata-protocolrebuilt,ablation-dist-preflightmarker present in 2 built files (restore: rebuilt, absent from all 24)AssertionError: `?package=X`: X ships no fr-FR: expected { name: 'welcome', …(6) } to be undefinedoverlayRowBindingkeeps every holder, a disabled one included (registry.tsis imported relatively by the suite, no build)AssertionError: the adoption counts the served holders: expected undefined to be 'com.acme.suitex'AssertionError: the adoption counts as the exact read does: expected undefined to be 'com.acme.suitex'AssertionError: the adoption counts X as the exact read does: expected 'com.acme.suite.custom' to be 'com.acme.suitex'Acceptance notes
claude/project-thread-04ua2f@c233053b1eand mergesorigin/mainonce (bf02d33bd, merge commit72c8a9c8ef). The branch had carried PR fix(objectql)!: every reader of the registry's overlay slot binds a row of an App's customization pair by the exact read's owner rule (ADR-0150 D4) #32815's round-3 head; the four conflicts (objectql/src/registry.ts, the twopackage-scoped-*test files,18.pair-row-locale-addition-refused.ts) each take main's landed copy (e336a33eb) with the card's own four commits replayed onto it, and the two32408-*changesets stay deleted (consumed by version packages chore: version packages #29963). Measured: the card's+/-lines vs main equal the branch's delta over PR fix(objectql)!: every reader of the registry's overlay slot binds a row of an App's customization pair by the exact read's owner rule (ADR-0150 D4) #32815's headc3cc324b1line for line, apart from main's own permission-set lines. The diff againstmainis the card's seven files only. Main's fix(metadata-protocol)!: a name a disabled package holds through a stored row is judged over the served set, never by save order (ADR-0150 D3) #33130 (metadata-protocol: a name held only by stored rows of two packages, one disabled, answers by save order, and /layers takes the first composite when the environment holds its own item (ADR-0150 D3) #32354) and fix(metadata-protocol)!: two packages' declared overrides of one flow or action name each serve in their own package's slot, in any registration order (ADR-0150 D4) #33126 (metadata-protocol: getMetaItemsForExecution files one pair package's bound flow override under another package's slot, by registration order (ADR-0150 D4, red line 2) #32613) are in the merged head;protocol-exact-qualifier.tsmerged without conflict.main's and not moved here (W's exact address, list and execution list serve a row declared for X when X holds nothing, onmainand at this head alike); the seat routes it.?package=Xwhilemainserved it. Fixed here (the adoption counts the holders aspackageScopedHoldersOfdoes) and pinned; no second move to declare. Observed beside it and not moved: in that state X's list and execution list leave the row out, onmainand at this head alike (the list door's own count), while X's exact address serves it; outside this card, left for the seat to route.protocol-exact-qualifier.tsand runs after this card lands.Verification
All local readings on head
dd283faf40(round 2:5a9d589a80for M1 and S1, thendd283faf40for n1; no commit after it).Affected suites and typecheck
pnpm --filter @objectstack/metadata-protocol test: Test Files 337 passed, 7 skipped (344); Tests 22803 passed, 36 skipped (22839).typecheckexit 0. LockVERDICT command-exit 0.pnpm --filter @objectstack/objectql test: Test Files 595 passed (595); Tests 12843 passed (12843).typecheckexit 0. LockVERDICT command-exit 0.package-scoped-exact-qualifier.test.ts,package-scoped-resolver.test.ts): 375/375 (369 at72c8a9c8ef, plus the two M1 CONTROLs and the four n1 pins).dispatch-gates
node scripts/pm/dispatch-gates.mjs --commandsderived the same 94 commands from the same 7 paths vs merge basebf02d33bd. All 94 exit 0 (check:dual-build-cjs-loadsmeasured this round: the dogfood closure build gave it its prerequisite).check:type-check-debtfirst answered exit 3PREREQUISITE NOT MET(its closure build never got the verify lock while the dogfood battery held it); re-run under the lock: exit 0, "0 ledger entr(ies) re-measured … none above its recorded number".dispatch-gates --ran: "94 derived famil(ies) accounted for — 94 run, 0 NOT-MEASURED".Lint and dogfood
pnpm lint(eslint, whole repo) ondd283faf40: exit 0.Full dogfood battery once on the final head
dd283faf40(Clause-②: yes (narrowing)): closurepnpm --filter '@objectstack/dogfood^...' build(lockVERDICT command-exit 0), thenpnpm --filter @objectstack/dogfood testunder the lock, no shard, no path:VERDICT command-exit 0· Test Files 460 passed, 3 skipped (463) · Tests 3886 passed, 42 skipped (3928) · no failure. (Round 1's run on72c8a9c8efread the same counts.)Generated by Claude Code