Repository navigation
refactor(metadata-protocol): move the package door save refusal and the origin-gated removal verdict out of protocol.ts into protocol-packaged-base-refusal.ts (#25467 cut 13) - #25972
Conversation
… the origin-gated removal verdict out of protocol.ts (#25467 cut 13) Move-only. The bodies of refusePackagedBaseOverride and originGatedRemovalRefusal move into the new protocol-packaged-base-refusal.ts (host shape B: protocol-bound closures for isSealedManagedItem, isWritablePackage and packagedBaseRefusal). Both members keep their name, docblock and signature in the class as stubs that delegate. refusePackagedBaseRemoval stays in the class: it reads the private static mergesOverlayAtRead. isOriginGatedType leaves protocol.ts' import with its last reader. Nothing re-exports the new module, so the published surface does not move. Claude-Session: https://claude.ai/code/session_016SP1spj613tyGCgxoD1An6 Co-authored-by: Claude <noreply@anthropic.com>
…e door's throw site (#25467 cut 13) refusePackagedBaseOverride's one `new Error(` moved with its body into protocol-packaged-base-refusal.ts, so the scan gains that module's row with its own count as the floor, as cuts 1, 3, 5, 6, 7, 10 and 12 added theirs. Claude-Session: https://claude.ai/code/session_016SP1spj613tyGCgxoD1An6 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 6 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 11 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 f98413274adffe8dd6a30ddab0374165240ee05b && git checkout f98413274adffe8dd6a30ddab0374165240ee05b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 0c3722882633d2941810df0ab542280407958f3f b1ac1d8a942a33cd43cc449823774cc3cbf4288c && git checkout -B drift-repro 0c3722882633d2941810df0ab542280407958f3f && git merge --no-ff b1ac1d8a942a33cd43cc449823774cc3cbf4288c
node scripts/docs-audit/affected-docs.mjs --json 0c3722882633d2941810df0ab542280407958f3f
|
席位核对 · ACCEPT ·
|
| item | reading |
|---|---|
| Shape | draft, base main, Part of #25467, Clause-②: no and Metadata-protocol: none line-initial, skip-changeset. |
| Files (3, +157/−75) | new protocol-packaged-base-refusal.ts, the two delegating stubs plus import in protocol.ts, one PRODUCERS row in protocol.bracketed-refusal-opener-absence.test.ts. No packages/spec/**, no governed path (check-governed-merges --pr 25972), 232 changed lines. |
| Scope narrowed (accepted) | two members moved, refusePackagedBaseOverride and originGatedRemovalRefusal. refusePackagedBaseRemoval stays: the seat re-read it on the head, its body calls the private static mergesOverlayAtRead split across two lines (protocol.ts 16415), so the stay-list ruling keeps it; packagedBaseRefusal stays (public, reads a private static). One PRODUCERS row, not two, follows. |
| Shape B | ThisParameterType host literals with protocol-bound closures (isSealedManagedItem, isWritablePackage; packagedBaseRefusal), .call(host, …); names, docblocks and signatures stay in the class. |
| Evidence | AST 179 tokens, 0 differ; negative control differ = 1; .d.ts raw identity at both ends; 78 export names identical; suite 0 lost / 0 changed / +1 (the new row, whose control reds); 59/59 derived gates exit 0 (report). |
| Landing | ready + auto-merge through the relay once every check on this head is green or an expected skip. Cut 14 (collectBatchPendingDeclarations + applySeedBodies, report's sizing) is the next claim. |
Generated by Claude Code
Requested by Leehom · project thread
Part of #25467
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6270097840
Cut 13 of the
protocol.tssplit (#24586 ruling A, recorded in6270097840). Cuts 1–12 landed as #25494, #25518, #25538, #25589, #25601, #25623, #25642, #25719, #25731, #25740, #25797 and #25939. The claim is6409240079; the scope is the cut 13 proposal of the cut 12 report (6408535757), as the server seat approved it in its dispatch order, narrowed by one member (below).Two
ObjectStackProtocolImplementationmembers move unedited into a new module,packages/metadata-protocol/src/protocol-packaged-base-refusal.ts(#23050 shape B): the package door's save refusalrefusePackagedBaseOverrideand the origin-gated removal verdictoriginGatedRemovalRefusal.protocol.tsloses 61 net lines (29,681 to 29,620). The cut is move-only, and the card stays open for later cuts.The scope narrowed:
refusePackagedBaseRemovalstays in the classThe proposal (my cut 12 report) named three members and said none reads a private-static member. That reading was wrong for one of them: it grepped the one-line spelling
ObjectStackProtocolImplementation.NAME, andrefusePackagedBaseRemovalbreaks that spelling across two lines (ObjectStackProtocolImplementationthen.mergesOverlayAtRead(request.type)).mergesOverlayAtReadisprivate static, and the Release's stay list keeps the private-static readers in the class, which this order's rulings hold. SorefusePackagedBaseRemovalstays, unedited, and the re-measure below walks the AST (a property access on the class identifier), not the text. The two members that move read no static member at all.Does
packagedBaseRefusalride along? No. It is not a small private helper: it is a public member (the/automationdomain of@objectstack/runtimecalls it), it reads the private staticisPackagedBaseRefusal, and it callsrefusePackagedBaseRemoval, which stays. It stays in the class and is handed to the movedoriginGatedRemovalRefusalas a closure.Branch
claude/project-thread-ybjm3his the harness-pinned branch for this thread, restarted frommainafter cut 12 merged. It names no issue, so the claim comment is the identity record. It holds the move commited0ca2d57and the pin commit1c09db420, both onmain7a04ba288d(cut 12's mergeefe35983f8and #25935 are in its history), and the merge ofmain59d9181ed(b1ac1d8a9). That merge brought six commits, none of which touchespackages/metadata-protocol/(the package'ssrc/tree is761912e9at both ends of the range).Serial with the file's in-flight PRs. Measured just before this PR was opened: of the 14 open PRs, one touches
packages/metadata-protocol/src/: #25941 editsmetadata-diagnostics.tsand adds its memo test, disjoint fromprotocol.ts. #25826 is no longer open. The release PR #25640's file list could not be paged through this container's proxy; at cut 11 it touched only the package'sCHANGELOG.mdandpackage.json. No open PR editsprotocol.ts.What moves
refusePackagedBaseOverride:16370originGatedRemovalRefusal:16534(
refusePackagedBaseOverride's 72 body lines are mostly its record comment; comments are not AST tokens, and the comparison below checks them as text.)The shape (#23050 shape B, as cuts 1–12 apply it)
.call, marked[#25467 cut 13].PackagedBaseRefusalHosttypes every member as the class member itself (an indexed access onObjectStackProtocolImplementation). Each moved function types itsthisas thePickof the host over exactly the members its body reads. Each stub annotates its literal asThisParameterTypeoftypeof fn. No cast, no generic member (so the plain.callspelling), and no member changes visibility.refusePackagedBaseOverridereadsisSealedManagedItemandisWritablePackage;originGatedRemovalRefusalreadspackagedBaseRefusal. Each goes as a closure on the protocol. No field is read, so there is no getter.saveMetaItemandpackagedBaseRefusalcallrefusePackagedBaseOverride;deleteMetaItemcallsoriginGatedRemovalRefusal.Module-level declarations, by reader
export, none moves. The bodies read no module-level declaration ofprotocol.ts. They readSysMetadataRepository(its staticreadOnlyBaseOverrideError),managedItemSealedSentenceandisOriginGatedType, which the new module imports from whereprotocol.tsimports them (./sys-metadata-repository.js,./packaged-base-regime.js). The new module's only import fromprotocol.jsis a type import, so it adds no runtime cycle.protocol.ts. One name loses its last reader and is dropped:isOriginGatedTypefrom./packaged-base-regime.js(at base: the import, the body oforiginGatedRemovalRefusal, and a{@link}in its docblock, which stays as prose). The one new statement is the import of the new module.The published
.d.tsThe series bar is ruling
6348891160, sorted-union identity, measured first. Base7a04ba288dand head were built withpnpm --filter @objectstack/metadata-protocol buildagainst one dependency tree (the closure built at head by a fullpnpm build, 119/119, then the package'ssrc/swapped tree-only to base for the base build and restored fromHEADunder a trap;git diff HEADempty,git statusclean and all three touched blobs equal toHEAD's after). Measured twice: on the pre-merge tree (base7a04ba288d, head1c09db420) and after the merge (merged base, headb1ac1d8a9, closure rebuilt by a fullpnpm build, 119/119); the readings below hold for both.08914e65f936a2b031c3f3f215481a97f53d132eefd869e4f42d928947ebe173at base and at head, on bothdist/index.d.tsanddist/index.d.cts, 775,874 bytes each. Raw identity holds, so sorted-union identity holds too. Both members stayprivate NAME;lines.46ccd7e5c4db673652513d1801ec9c9f06bf34a0a7fb6ba97fb2531ef0cc544bat both ends (80 string-literal union runs sorted; this series' cut 12 normaliser).index.jshashes53d93de18be521db…at base and4d3c4c7364445db0…at head; each of the two functions'.call(hostsites occurs 0 times in the base bundles and once in the head bundles (ESM and CJS alike).HEADunder a trap, hash equal toHEAD's after):privatedropped fromoriginGatedRemovalRefusaland the package rebuilt. Both.d.tsfiles move tofec45eed6afc2fff…, so the bar can see a change on these members.9f18a0177ac736ed…on all four. Neither moved function nor the host type appears.No changeset:
skip-changeset, per ruling6348891160.Proof of move-only
this, return type and body): 179 tokens compared, 0 differ. The parameter, return-type and body text, comments included, is also equal with whitespace collapsed, for both. Negative control: one changed token inrefusePackagedBaseOverride's body (namedBase &&tonamedBase ||, on an in-memory copy) makes the check reportdiffer=1on that member and 0 on the other.protocol.ts. 240 of the 241 base statements other than the class are byte-identical, leading comments included. The other one is the./packaged-base-regime.jsimport, which losesisOriginGatedType. Head adds one statement, the new module's import.protocol-packaged-base-refusal.tshas 140 lines.Readers of the moved lines
Every test and script that reads
protocol.tsby path, and every test file inpackages/andscripts/, was grepped for the three proposed member names and the host name; so wasdocs/qa/, which cites methods by name.protocol.packaged-base-refusal.test.ts(lines 9, 225, 231),protocol.package-door-before-gates.test.ts(line 7) and objectqlengine-security-catalog-package-door.test.ts(line 13) namerefusePackagedBaseOverride/refusePackagedBaseRemovalin comments only; none readsprotocol.tsby path or asserts on the bodies' text. Verdict: no edit owed; all three pass at head (see Verification).docs/qa/platform-checklist/areas/access-security.jsoncitespackages/metadata-protocol/src/protocol.ts#refusePackagedBaseOverrideas an anchor (line 1517) and in prose (line 1459). The method keeps its name inprotocol.ts, andcheck-platform-checklist --changed-from origin/mainjudges it: OK, 1 anchored file in the change set, 29 anchors judged, 0 lost.CHANGELOG.mdentries.PRODUCERS):refusePackagedBaseOverride's onenew Error(moves with its body, so the new module gets a row,'protocol-packaged-base-refusal.ts': 1, the module's own count (the order's "two" counted the one inrefusePackagedBaseRemoval, which stays).protocol.tsgoes from 72 to 71 such sites, still above its floor of 5. Control: with that throw changed tonew TypeError((on disk, restored fromHEADunder a trap, hash equal toHEAD's after; on-disk counts read first: 0new Error(, 1new TypeError(), the new row fails with "protocol-packaged-base-refusal.ts no longer constructs errors here — this pin is scanning the wrong file: expected 0 to be greater than or equal to 1" (1 failed, 14 passed); restored, 15/15 pass.check-adr-anchorsexits 0 at both ends: 85 anchored files, 58,860 citations, files 8,259 → 8,260, and 1,847 → 1,843 decision-letter citations. The four that leave the anchored file are comments inrefusePackagedBaseOverride's body: threeADR-0131 D6and oneADR-0070 D1. Theprotocol.tsanchor entry's four paragraphs (ADR-0029 D9.8/D9.9 object hydration, ADR-0119 atomic batches, ADR-0005 appendix (c) view storage, ADR-0126 §2 / §3 flow regime) do not describe the package door, so the new module gets no entry (disclosure only, as cuts 8 and 12 disclosed theirs).ADR-0005, which the moved comments also cite, stays referenced fromprotocol.ts(the gate's "every governing ADR still referenced" holds).check-durability-degradation-log-levelexits 0 at both ends with identical output, and its--listis identical once[@:][0-9]+is stripped (159 lines): the moved bodies hold notry/catch.check-engine-double-contract): exits 0 at both ends. TheupdateData/deleteDataseams keep their entries at new line numbers (14083 → 14085, 14108 → 14110).productionFilesis 3,707 at base and 3,709 at head: +1 is the new file, +1 is the gitignoredpackages/spec/src/migrations/registry.ts, which the spec build writes in the head tree and the clean base tree had not built.check-adr-symbol-anchors,check-system-context-census,check-tenant-audit-census,check-query-options-erasure-ratchet,check-filter-alias-parity.check-nul-bytesdiffers only in the scanned file count, +1. The base-end readings were taken in a clean detached worktree at7a04ba288d.check-governed-merges --branch claude/project-thread-ybjm3h: 0 of 3 paths hit the register, NOT governed; 232 changed lines, under the 3,000-line human-merge bar.Verification
tsc --noEmitinpackages/metadata-protocolexits 0 before and after the merge.pnpm exec eslint --no-inline-config packages/metadata-protocol(the whole touched package; it has nolintscript, these are the rootlintscript's flags) exits 0, no output.packages/metadata-protocolsuite, base and head, compared per test name and status (vitest--maxWorkers=2, JSON reporter, each run under the shared verify lock,VERDICT command-exit 0both legs), on the pre-merge tree (the merge changed no file of the package):7a04ba288d: 21,537 tests (21,518 passed, 0 failed, 19 skipped), 267 files.1c09db420: 21,538 tests (21,519 passed, 0 failed, 19 skipped), 267 files.PRODUCERSrow's case. The base leg is the packagesrc/swapped tree-only from7a04ba288d(the new module removed from the tree) and restored fromHEADunder a trap.engine-security-catalog-package-door.test.tsat headb1ac1d8a9, under the verify lock: 1 file, 18/18 passed,VERDICT command-exit 0. The two metadata-protocol pins named above ran inside the package suite and pass at both ends.dispatch-gates --commands --repo objectstack-ai/objectstackderives 59 gates on 3 changed paths, the same list before and after the merge; all 59 exit 0 on the merged treeb1ac1d8a9, after the fullpnpm buildand with the plugin-teardown fixture commit fetched first.dispatch-gates --ran: 59 derived, 59 run, 0 NOT-MEASURED, 0 UNRUN, exit 0.Acceptance notes
refusePackagedBaseRemovalandrefusePackagedBaseOverridenow live in two files, though their docblocks describe them as twins (one predicate,isSealedManagedItem). The removal twin can follow only once private-static readers can move (the stay list's reason); until then the class docblocks, which did not move, still name each other with{@link}.Carry-forward
Unchanged from cut 12: public members whose return type is inferred, the bodies kept by a reader (
probeRecord,getMetaItemCached,findReferencesToMeta,packagelessAddress,refuseUnmintableMetaType,metaTypeNamespaceExists,viewContainerNameCollisionRefusalwithoverlaidShippedContainerViewNames,reportPageRequiresAbsentAtLoad, the 7applyRegistryWriteThroughcallers,readCodeLayerForCarryForward), and the private-static readers (now named among them:refusePackagedBaseRemovalandpackagedBaseRefusal, besidesrunPublishSideEffects,promoteDraftForPublish,publishPackageDraftsanddiscardPackageDrafts) stay inprotocol.ts.Generated by Claude Code