Skip to content

refactor(metadata-protocol): move the bodies of eight members out of protocol.ts into four themed modules (#25467 cut 35) - #28090

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-06gygo
Oct 30, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-06gygo

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Elon · project thread

Part of #25467
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6520565826

维护者速读

  • 改了什么:把 protocol.ts 里 8 个方法的方法体原样搬进 4 个按主题划分的新文件(环境自有行读取、存储集合折叠、包卸载、非托管导入),类上的方法、签名和文档注释都保留,只剩一个调用。protocol.ts 从 29,585 行降到 29,114 行。
  • 为什么改:[maintainer] refactor(metadata-protocol): split src/protocol.ts (33,065 lines, +10,169 in 30 days) along its ObjectStackProtocolImplementation seams, one move-only slice per PR #25467 裁决 B 的第二个 PR。fix(scripts): the read-seam census follows a moved protocol.ts body across its host split (#25467 census extension) #28058 让读缝普查能跟着拆分走,cut 33/34 里只因普查被拒的成员(含 300 行的 deletePackage)现在可以搬了。
  • 风险与回滚:低。8 个方法体逐 token 相同(3,278 个 token,差异 0);发布的 .d.ts 与 main 原始字节完全相同;包测试与 main 逐条比对 0 丢失 0 变化,只多 2 条新登记行带来的用例;普查仍是 95,只有 7 行换了文件。回滚即还原本 PR。
  • 先看:protocol.ts 里带 [#25467 cut 35] 标记的 8 个桩方法,以及 protocol.bracketed-refusal-opener-absence.test.ts 里新增的 2 行 PRODUCERS 登记。
  • 两分钟验证:pnpm check:durability-log-level,预期末行 95 read seam(s), none invents an unreported answer;再跑 pnpm --filter @objectstack/metadata-protocol exec vitest run --maxWorkers=2 src/protocol.bracketed-refusal-opener-absence.test.ts src/protocol.package-delete-refusal.test.ts,预期全部通过。
  • 需要你做的:无,席位落地。

What changes

PR 2 of 2 under ruling B on #25467. PR 1 (#28058) taught the read-seam census to follow a moved body across the host split; this cut moves the members the census alone rejected at cuts 33 and 34.

8 ObjectStackProtocolImplementation members move unedited into 4 new modules under packages/metadata-protocol/src/ (#23050 shape B):

Module Members (base line, body lines, AST tokens) Host
protocol-environment-rows.ts (161 lines) findEnvironmentRows (:10240, 12, 259), findEnvironmentRow (:10261, 6, 161), findServedOverlayRow (:10470, 29, 221), packagelessAddress (:17212, 20, 243) EnvironmentRowsHost
protocol-stored-collection-fold.ts (153) foldStoredCollection (:7404, 95, 487) StoredCollectionFoldHost
protocol-package-uninstall.ts (358) deletePackage (:24914, 300, 1,107; public) PackageUninstallHost
protocol-unmanaged-import.ts (148) unmanagedImportCollisions (:26121, 39, 464), rollBackUnmanagedImport (:26177, 38, 336) UnmanagedImportHost

Base lines are protocol.ts at main 2e955dde. 539 body lines and 3,278 AST tokens in total. deletePackage is the one public member; its declared return type is Promise<DeletePackageResponse>, so the published signature is unchanged.

  • The class keeps every member: name, modifiers, signature, docblock and position. Each body is now one call into its module, marked // [#25467 cut 35] The body moved to ....
  • Shape B, as cuts 20–34. Each stub builds one const host: ThisParameterType<typeof fn> = {...} and returns fn.call(host, ...). Methods are passed as closures over this, engine and getServicesRegistry as getters. Each module has one named host type whose members are typed as the class members.
  • Every caller still calls the class method. No call site changes and no member changes visibility.
  • protocol.ts goes from 29,585 to 29,114 lines. The PR is +895 / −542 over 6 files.

Screened and kept out

The 8 that move pass the other screens on fresh main: no private-static read, no this.constructor read, no by-path reader of their bodies (the suite and the hand gates below agree), and no open PR edits them.

Tests

One test file changes, the path-reader migration the series requires. protocol.bracketed-refusal-opener-absence.test.ts keeps a per-file floor of new Error( producers (PRODUCERS). Three new Error( sites move (two in deletePackage, one in rollBackUnmanagedImport), so two modules get a row, under a [#25467 cut 35] comment, after cut 33's rows:

'protocol-package-uninstall.ts': 2,
'protocol-unmanaged-import.ts': 1,

Each row adds one generated case, so the suite grows by 2. The moved members are driven end to end by the existing suites (package uninstall and its refusals, the unmanaged import, the runtime authoring gate, the served overlay reads); all pass at both ends.

Acceptance notes

  • The read-seam census stays at 95. Seven --list lines change file with the same verdict: the three guards in deletePackage, the guard in packagelessAddress, the two in the unmanaged import, and foldStoredCollection's reported pass-through. Every other line is identical once line numbers are stripped. This is the reading cut 34 lost (93 → 89) and fix(scripts): the read-seam census follows a moved protocol.ts body across its host split (#25467 census extension) #28058 recovers.
  • Four top-level helpers gain export in place: remainingRowsPhrase, servedOverlayRowCandidates, mergePackageAwareOverlay and metadataReadFailureError, each protocol.ts's own non-exported function, read by a moved body. Each gains the export keyword with nothing else in its statement changed, as cut 33 did. All four keep readers in protocol.ts. index.ts names its re-exports one by one and names none of them, so the published surface does not move (the .d.ts is raw-identical, below).
  • No import of protocol.ts lost its last reader, so none is removed.
  • check-adr-anchors counts move, and the gate passes at both ends. Citations 61,216 → 61,218 and files 8,748 → 8,752. Decision-letter citations on the anchored surface 1,998 → 1,993: five moved letter citations left protocol.ts for modules outside the anchored set. check-adr-symbol-anchors output is identical.
  • Serial with in-flight PRs. PR feat(spec,metadata-protocol,rest,objectql,runtime): GET /meta/object serves switched-off packaged actions beside the item, and the disabled-action refusal reads as a plain sentence #27964, named by the dispatch, merged before this branch was cut, so its diff is in the base. At pr_create, none of the 19 open PRs edits packages/metadata-protocol/src/ or the census script (each head fetched and diffed against its merge base), so no git merge-tree proof is owed.
  • No changeset: skip-changeset, per ruling 6348891160.

Verification

Proof of move-only

The compare reads the TypeScript compiler's AST leaf tokens, with JSDoc skipped, over each member's type parameters, parameters (the module's this parameter dropped), return type and body, protocol.ts at main against the head module:

findEnvironmentRows 259 tokens differ 0 text equal
findEnvironmentRow 161 tokens differ 0 text equal
findServedOverlayRow 221 tokens differ 0 text equal
packagelessAddress 243 tokens differ 0 text equal
foldStoredCollection 487 tokens differ 0 text equal
deletePackage 1107 tokens differ 0 text equal
unmanagedImportCollisions 464 tokens differ 0 text equal
rollBackUnmanagedImport 336 tokens differ 0 text equal
TOTAL 3278 differ 0

"text equal" is the whitespace-collapsed body text, comments included. Negative controls, one token changed in an in-memory copy of the head module, each differ 1: deletePackage === → !==; findEnvironmentRow null → undefined; foldStoredCollection registered → registeredX; rollBackUnmanagedImport await → void.

  • Class side. 307 members at both ends, same order. The 299 that did not move are byte-identical, leading comments included; the 8 stubs keep their leading trivia and signature byte-identical.
  • Top level. 274 → 278 statements; 269 byte-identical. The rest: the 4 module imports (each with a one-line [#25467 cut 35] comment), the four helpers with export added, and the class.
  • tsc --noEmit in packages/metadata-protocol: exit 0. pnpm exec eslint --no-inline-config packages/metadata-protocol: exit 0, no output.

The published .d.ts (ruling 6348891160)

Built with turbo run build --filter='@objectstack/metadata-protocol...' at each end, under the shared verify lock.

Reading main 2e955dde Head 6b074fce
raw sha256 dist/index.d.ts = dist/index.d.cts 00e090f9865173d73ac2d0bf451663790d89a9aabf6ad74fc6470ff2fbf2ae61 (791,803 bytes) same
normalised sha256 66d4be5eb145c97d09699a67e8d5014ec009fa2838f05c980d492edf00c491cd same
raw-diff lines 0 (cmp equal)

Bundles change as expected: index.js a11431fcf0a4301d → 3975040696890377, index.cjs 3826cf554a460505 → 2bd2adad44302e8c (sha256, 16). The ESM and CJS export tables are the same 78 names (9f18a0177ac736ed) at both ends; none of the moved functions or the four exported helpers appears. The normaliser is PR #27540's, verbatim.

Gates and suites

Package suite

packages/metadata-protocol, vitest --maxWorkers=2, JSON reporter, under the shared verify lock.

  • main 2e955dde: 21,883 tests (21,857 passed, 0 failed, 26 skipped), 288 files.
  • Head: 21,885 tests (21,859 passed, 0 failed, 26 skipped), 288 files. Per file, test name and status over 21,870 distinct names against main: 0 lost, 0 changed, 2 added, both the new PRODUCERS rows.
Hand gates, main and head

All 12 exit 0 at both main 2e955dde and the head.

  • Identical output: check-adr-symbol-anchors, check-system-context-census, check-tenant-audit-census, check-query-options-erasure-ratchet, check-filter-alias-parity, check-platform-checklist.
  • check-durability-degradation-log-level --list: 95 read seam(s) at both ends; identical once [@:][0-9]+ is stripped, except the seven lines that change file (above).
  • check-adr-anchors: counts as noted in Acceptance notes.
  • check-startup-registry-verdict: files 3,756 → 3,760. check-nul-bytes: 22,620 → 22,624 files. check-engine-double-contract: the updateData/deleteData seams keep their entries at new line numbers; productionFiles 3,950 → 3,954. measure-return-propagating-durability-seams: 3,779 → 3,783 files. Each count is the four new modules.
  • check-governed-merges --branch claude/project-thread-06gygo: 0 of 6 paths in the register (13 surfaces), NOT governed; 1,437 changed lines, under the 3,000-line bar.
Derived gates

dispatch-gates --commands on head 6b074fce derives 52 gate families on the 6 changed paths; all 52 exit 0. Three exited 3 (PREREQUISITE NOT MEASURED) on the first pass and 0 on the rerun: check-plugin-teardown-shape --self-test after fetching its pinned fixture commit into the shallow clone, check:dual-build-cjs-loads and check:lean-entry-closure after turbo run build --filter='@objectstack/dogfood^...' --filter='@objectstack/runtime^...' --filter=@objectstack/objectql. dispatch-gates --ran reports 52 derived, 52 run, 0 NOT-MEASURED, and exits 0.

pnpm lint: exit 0.

🤖 Generated with Claude Code

https://claude.ai/code/session_016WV4czJUan4AwAS6HLpzZN


Generated by Claude Code

…protocol.ts into four themed modules (#25467 cut 35)

Cut 35 of the protocol.ts split, under ruling B: the read-seam census now
follows a moved body across the host split, so the members it alone
rejected at cuts 33 and 34 move.

- protocol-environment-rows.ts: findEnvironmentRows, findEnvironmentRow,
  findServedOverlayRow, packagelessAddress
- protocol-stored-collection-fold.ts: foldStoredCollection
- protocol-package-uninstall.ts: deletePackage
- protocol-unmanaged-import.ts: unmanagedImportCollisions,
  rollBackUnmanagedImport

Shape B as cuts 20-34: the class keeps each method, its docblock and
signature, and its body becomes one host literal plus a .call. Four
top-level helpers the bodies read gain `export` in place; index.ts names
none of them. The bracketed-refusal pin gets PRODUCERS rows for the two
new modules with new Error( sites.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4czJUan4AwAS6HLpzZN
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/metadata-protocol, touching 50 documentable anchor(s).

58 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: node scripts/docs-audit/affected-docs.mjs --json 549203d040a122591ba07bb21b90124e31eaf5de.

⛔ 16 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.

What this run could not see
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 58 of 210 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 10 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 549203d040a122591ba07bb21b90124e31eaf5de → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 7fc194dc3481c5b1324b55380fbfc10f276c2383 — the merge of head 6b074fce6ccfa60e69d5b285ab74860e9b346834 into base 549203d040a122591ba07bb21b90124e31eaf5de, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 7fc194dc3481c5b1324b55380fbfc10f276c2383 && git checkout 7fc194dc3481c5b1324b55380fbfc10f276c2383
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 549203d040a122591ba07bb21b90124e31eaf5de 6b074fce6ccfa60e69d5b285ab74860e9b346834 && git checkout -B drift-repro 549203d040a122591ba07bb21b90124e31eaf5de && git merge --no-ff 6b074fce6ccfa60e69d5b285ab74860e9b346834

node scripts/docs-audit/affected-docs.mjs --json 549203d040a122591ba07bb21b90124e31eaf5de

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 549203d040a122591ba07bb21b90124e31eaf5de → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#1 · os-elon-musk · session_016WV4czVnUdQQCVKSW5J2uk

Seat ACCEPT · PR #28090 · head 6b074fce6ccfa60e69d5b285ab74860e9b346834 · 2026-10-30T12:45Z

维护者速读

席位核对

  • Shape: draft → main, Part of #25467 (series card stays open), Ruling-ref: 6520565826 (ruling B). 6 files, +895/−542, all packages/metadata-protocol/src/: 4 new modules, the protocol.ts stubs, one PRODUCERS row pair in protocol.bracketed-refusal-opener-absence.test.ts. skip-changeset per ruling 6348891160. check-governed-merges --pr 28090: NOT governed (0 of 6 paths), 1,437 changed lines ≤ 3,000.
  • Declarations: Clause-②: no, Metadata-protocol: none. Move-only.
  • Dispatch kept: exactly the 8 members of dispatch-25467-cut35.md; storedFlowBindingAgrees, metaTypeNamespaceExists and rethrowUnlessMetadataStoreUnprovisioned stay, for the stated reason (the census's catch-side guard resolution is same-file only).
  • Diff read (seat): the deletePackage stub builds one ThisParameterType<typeof deletePackage> host (methods as closures over this, engine / getServicesRegistry as getters) and returns deletePackage.call(host, request) — shape B, as cuts 20–34. The public signature Promise<DeletePackageResponse> is unchanged. Four helpers gain export in place only; index.ts re-exports none of them, and the .d.ts is raw-identical (sha256 00e090f9… at both ends).
  • Census: 95 = 95 at both ends (the card thread's reading; CI runs pnpm check:durability-log-level in lint.yml, green on this head). The seat's own re-run was NOT MEASURED here: the seat container has no node_modules (typescript absent, exit 3).
  • Local (card thread, report 6522763004): AST compare 3,278 tokens differ 0 + 4 negative controls; package suite 21,883 → 21,885, 0 lost / 0 changed / +2; 12 hand gates, 52 derived gates and pnpm lint exit 0.
  • Serial: no open PR edits packages/metadata-protocol/src/ or the census script at pr_create; feat(spec,metadata-protocol,rest,objectql,runtime): GET /meta/object serves switched-off packaged actions beside the item, and the disabled-action refusal reads as a plain sentence #27964 is in the base.
  • Gate check-runs on this head: 53 total, 35 success, 18 skipped, 0 failed. mergeable_state: clean.
  • Landing: non-governed, under the maintainer's landing grant for this seat term (2026-10-30 10:20Z, seat-1 thread). Ready + auto-merge through the relay.

ACCEPT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant