Skip to content

refactor(metadata-protocol): move the commit plan items parse out of protocol.ts into protocol-commit-items.ts (#25467 cut 32) - #27406

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-xbievt
Oct 29, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-xbievt

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Sales · project thread

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

维护者速读

  • 改了什么:把 protocol.ts 里一个只有 10 行的私有方法 parseCommitItems(把提交记录的 items 列读回成回滚计划)原样搬进新文件 protocol-commit-items.ts,类上的方法保留并直接调用它。
  • 为什么改:[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 拆分超大文件 protocol.ts 的第 32 刀,按裁决只搬不改,让这个文件继续变小、好读。
  • 风险与回滚:极低。逻辑逐 token 相同,发布的 .d.ts 原始字节两端完全相同,包测试 21,800 条逐条一致;回滚就是还原这一个 PR。
  • 先看:packages/metadata-protocol/src/protocol.ts 的 parseCommitItems 方法体(现在只剩一行调用)与 CommitPlanItem 前新增的 export;再看新文件 protocol-commit-items.ts。
  • 两分钟验证:pnpm --filter @objectstack/metadata-protocol exec vitest run --maxWorkers=2 src/protocol.recovery-doors-emit-mutation.test.ts,预期全部通过(它经 revertCommit 读回提交计划)。
  • 需要你做的:无,席位落地。

What changes

Cut 32 of the protocol.ts split (#24586 ruling A, recorded in 6270097840). Cuts 1–31 landed; cut 31 is #27181. The claim is 6487683544. It takes the cut 32 proposal of the cut 31 report (6465513012): one member on its own. It passed the AST screen and the read-seam census and moved unedited.

One ObjectStackProtocolImplementation member moves unedited into a new module, packages/metadata-protocol/src/protocol-commit-items.ts (#23050 shape B): parseCommitItems, which reads a stored sys_metadata_commit row's items column back as its revert plan. An array is the plan as stored; a string is parsed as JSON; anything else, or a string that is not a JSON array, reads as no items.

Member Base line Visibility Body lines AST tokens (params + return + body) Reads
parseCommitItems :26479 private, return type declared (CommitPlanItem[]) 10 73 no class member; module-level type CommitPlanItem
  • The class keeps the member: name, signature and position. It has no docblock. Its body is now one call, return parseCommitItems(raw);, marked [#25467 cut 32].
  • No host. The body reads no class member (no this), so the stub calls the plain function directly, as cut 26 did for orgWallEnforced.
  • Every caller still calls the class method: listCommits (this.parseCommitItems(r.items), base :26577) and revertCommit (this.parseCommitItems(row.items), base :26693). Neither changes.
  • No member changes visibility.
  • protocol.ts goes from 29,514 to 29,508 lines. protocol-commit-items.ts has 44 lines. The cut is move-only, and the card stays open for later cuts.

Branch claude/project-thread-xbievt is the harness-pinned branch for this thread; it names no issue, so the claim comment is the identity record. It holds the move commit dda5102340 on main c4c515ad3c, one merge of main 9b33088b78 (4 commits up to 7e200b4a68, none in packages/metadata-protocol/), and a09398108f, a comment-only fix to the new module's header (it named the caller listPackageCommits; the method is listCommits).

One top-level edit beyond the move: CommitPlanItem gains export

The dispatch's correction holds: CommitPlanItem is not an import. It is protocol.ts's own non-exported module-level type alias (base :2751). The moved function's signature and body name it, so it gains the export keyword in place, with nothing else in its statement changed, and the new module imports it with import type. This follows addressPackages (cut 16), withDeclaredPageTypeDefault (cut 23) and noPendingDraftError (cut 31).

  • packages/metadata-protocol/src/index.ts names its re-exports from ./protocol.js one by one and does not name it, so the published surface does not move: the .d.ts and export-table readings below are identical at both ends.
  • It keeps its other readers in protocol.ts (the commitItems plan built at publish, the commit-write argument type, both callers' results) and stays there.

Tests

Nothing is added or changed under test; the cut is move-only. The package suite is compared per test at both ends (see Verification). The member is driven end to end through revertCommit by the recovery-door suites (protocol.recovery-doors-*.test.ts, protocol.object-registry-write-through-spelling.test.ts), which serve sys_metadata_commit rows from a fake driver, and through listCommits by the commit-timeline suites (protocol-14038-list-commits-created-at-iso.test.ts, protocol.commit-timeline-instant-order.test.ts); all pass at both ends.

Acceptance notes

  • The order's screen. No private-static read and no this.constructor read (the body has no this at all). No new Error(, so no PRODUCERS row is owed. The body's try/catch guards JSON.parse, not a storage read, so it is outside the read-seam rule's vocabulary; the census does not move (below).
  • The cut 25 docblock-offset trap did not fire. The raw .d.ts is byte-identical at both ends after the final byte layout, measured again after the comment-only commit.
  • Readers of the moved lines: none by path. Grepped parseCommitItems and CommitPlanItem across the repository at HEAD (outside the two touched files): 0 hits. Of the 32 files that name protocol.ts and call readFileSync, none names the member or its body text; three name sys_metadata_commit only as behavioural fixtures run through the protocol. No @objectstack/spec liveness row and no docs/qa/platform-checklist anchor names the member.
  • Liveness ledger follow-up, carried forward (packages/spec/**, outside this card): manifest.json's dependencies row → protocol.ts#resolveWritePackageScope (cut 19) and seed.json → protocol.ts#applySeedBodies (cut 14). No row points at this cut's member.
  • Serial with in-flight PRs. At pr_create, of the 23 open PRs none edits protocol.ts or names the member. The only one touching packages/metadata-protocol/ is chore: version packages #26517 (Version Packages: CHANGELOG.md, package.json). Probed in a throwaway bare clone with no merge driver, it conflicts with this head in exactly the 4 ui/packages/*/package.json files it already conflicts with on main ad2c2869bb; none is in this package. main moved one commit after the merge (ad2c2869bb, plugin-grid); git merge-tree of this head with it is clean, so main was not merged again.
  • 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 the parameters, the return type and the body, base protocol.ts at c4c515ad3c against the head module:

parseCommitItems: base tokens 73, head tokens 73, differ 0, text-equal(ws-collapsed, comments incl.) true
CLASS members base=304 head=304 order-same=true byte-identical=303 stub-leading+signature-identical=true other=[]
TOP base=266 head=267 byte-identical=264 (class statement excluded)
TOP base-only: ["type CommitPlanItem = { type: string; name: string; existedBefore: boolean; prevVersion: number | null; member?: string };"]
TOP head-only: ["import { parseCommitItems } from './protocol-commit-items.js';","export type CommitPlanItem = { type: string; name: string; existedBefore: boolean; prevVersion: number | null; member?: string };"]

Negative controls, one token changed in an in-memory copy of the head module:

"typeof raw === 'string'"  -> "typeof raw === 'object'"   differ 1
"Array.isArray(p) ? p"     -> "Array.isArray(raw) ? p"    differ 1
  • Class side. 304 members at both ends, same order; the 303 that did not move are byte-identical to base, leading comments included; the stub keeps its leading trivia and signature byte-identical.
  • Top level. Of the 265 non-class base statements, 264 are byte-identical; the other is CommitPlanItem, whose only change is the added export. Head adds the module import (with its one-line [#25467 cut 32] comment).
  • Size. +49 / −11 over 2 files, 60 changed lines (the cut 31 report's estimate was 40–70).

The published .d.ts (ruling 6348891160)

Base c4c515ad3c and head were built with pnpm --filter @objectstack/metadata-protocol build against one dependency tree (the closure built by a full turbo run build, 115/115). For the base build the package src/ was swapped tree-only to base (the new module removed) and restored from HEAD under a trap; afterwards git status --porcelain was empty and both touched blobs hashed equal to HEAD's.

Reading Base c4c515ad3c Head a09398108f
raw sha256 dist/index.d.ts = dist/index.d.cts 4cb92b2e20135dd78d07fd2800b1d2a050a432b923cd511d5b50f3ed6de29a58 (784,960 bytes) same
normalised sha256 a4dcc2306638c29983bceaf7258df71a29a3020a3ec26904c9830a0cecd0c70e same
raw-diff lines 0
index.js / index.cjs sha256 (16) 20239680cb0cf515 / f3ac1e9bdd5b9e96 e5abe0490663649f / 1c36338d33aa16a5
function parseCommitItems( in each bundle 0 1
export tables, ESM and CJS (sorted names + newline) 78 names, e47ac7c753bcb8be same; neither parseCommitItems nor CommitPlanItem

Both identities hold: raw and sorted-union. The head reading was taken on the move commit, on the merged tree and again on a09398108f; all give the same hashes.

Normaliser, verbatim:

node -e 'const s=require("fs").readFileSync(process.argv[1],"utf8");process.stdout.write(s.replace(/"[^"\n]*"(?:\s*\|\s*"[^"\n]*")+/g,r=>r.split(/\s*\|\s*/).sort().join(" | ")))' dist/index.d.ts | sha256sum

Positive control on the head tree: private dropped from parseCommitItems on disk (restored from HEAD under a trap) and the package rebuilt. Both .d.ts files move to raw ca90763579860f2c… (785,652 bytes), normalised b7639852d59f8343… (differs from the bar's a4dcc230…), printing parseCommitItems(raw: unknown): CommitPlanItem[];. So the bar can see a change on this member.

Gates and suites

Package suite, tsc, eslint
  • packages/metadata-protocol suite, vitest --maxWorkers=2, JSON reporter, under the shared verify lock. Base c4c515ad3c (src swapped tree-only, restored from HEAD under a trap), the move commit dda5102340 and the final head a09398108f: all three 21,800 tests (21,774 passed, 0 failed, 26 skipped), 283 files. Per test name and status over 21,787 distinct names: 0 lost, 0 added, 0 changed.
  • tsc --noEmit in packages/metadata-protocol: exit 0.
  • pnpm exec eslint --no-inline-config packages/metadata-protocol: exit 0, no output.
Hand gates, base and head

Base readings in a clean detached worktree at c4c515ad3c; head in the branch checkout.

  • check-durability-degradation-log-level: exit 0 at both ends, output identical, 89 read seam(s). --list identical once [@:][0-9]+ is stripped (165 lines); no entry changes file. 89 is the claim's base.
  • Identical output, exit 0 at both ends: check-adr-anchors, check-adr-symbol-anchors, check-system-context-census, check-tenant-audit-census, check-query-options-erasure-ratchet (50 unswept non-test sites in 15 files), check-filter-alias-parity.
  • check-nul-bytes: exit 0 at both ends; scanned files +1 (the new module).
  • check-engine-double-contract: exit 0 at both ends; the updateData/deleteData seams keep their entries at new line numbers (13997 → 13999 and 14022 → 14024: the import's two lines sit above them, and the move's eight removed lines below); productionFiles 3,876 → 3,878 (the new file and the gitignored spec registry.ts the build writes in the head tree, as in cuts 20–31).
  • check-platform-checklist --changed-from origin/main: OK, 32 anchors judged, 0 lost.
  • check-governed-merges --branch claude/project-thread-xbievt: 0 of 2 paths in the register (13 surfaces), NOT governed; 60 changed lines, under the 3,000-line bar.
Derived gates

dispatch-gates --commands --repo objectstack-ai/objectstack on a09398108f derives 46 gates on 2 changed paths (merge base 7e200b4a6). All 46 exit 0 after a full turbo run build (115/115). dispatch-gates --ran reports 46 derived, 46 run, 0 NOT-MEASURED, 0 UNRUN, and exits 0.

On the final head the hand gates were re-read: check-adr-anchors output is identical to main 7e200b4a68's (60,467 citations, 1,900 decision letters; the +1 citation and file against c4c515ad3c come from the merged main commits), and check-durability-degradation-log-level is identical to base, --list included.

🤖 Generated with Claude Code

https://claude.ai/code/session_01L6bhgVaAsaDVwT6XfwB5yk


Generated by Claude Code

… into protocol-commit-items.ts

Move-only cut 32 of the protocol.ts split. The body of the private
parseCommitItems member moves unedited into a new module as a plain
function; it reads no class member, so the class method's body calls it
directly. CommitPlanItem gains `export` in place so the new module can
import it as a type; index.ts does not re-export it.

Claude-Session: https://claude.ai/code/session_01L6bhgVaAsaDVwT6XfwB5yk
Co-authored-by: Claude <noreply@anthropic.com>
… in the moved module's header

Claude-Session: https://claude.ai/code/session_01L6bhgVaAsaDVwT6XfwB5yk
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 29, 2026
@objectstack-fleet
objectstack-fleet Bot requested a review from os-sales October 29, 2026 05:22
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

2 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see
  • 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 ad2c2869bb67fe24750021aa5b94c99c1ac7c957 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 8dd5fe91f4ae4460cf6643225a45c1c3d09868eb — the merge of head a09398108fec88c52087aad000b5158de8109539 into base ad2c2869bb67fe24750021aa5b94c99c1ac7c957, 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 8dd5fe91f4ae4460cf6643225a45c1c3d09868eb && git checkout 8dd5fe91f4ae4460cf6643225a45c1c3d09868eb
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ad2c2869bb67fe24750021aa5b94c99c1ac7c957 a09398108fec88c52087aad000b5158de8109539 && git checkout -B drift-repro ad2c2869bb67fe24750021aa5b94c99c1ac7c957 && git merge --no-ff a09398108fec88c52087aad000b5158de8109539

node scripts/docs-audit/affected-docs.mjs --json ad2c2869bb67fe24750021aa5b94c99c1ac7c957

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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#1 · os-sales · session_01L6bhgXcN9HaZYSEUdJWEjw

维护者速读(席位终稿)

  • 改了什么:把 protocol.ts 里一个只有 10 行的私有方法 parseCommitItems 原样搬进新文件 protocol-commit-items.ts。这个方法把提交记录的 items 列读回成回滚计划。类上的方法保留,改为直接调用新文件里的函数。它用到的类型 CommitPlanItem 在原地加了 export,供新文件按类型导入。
  • 为什么改:这是 [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 拆分超大文件 protocol.ts 的第 32 刀。按裁决只搬不改,让文件继续变小、好读。
  • 风险与回滚:极低。逻辑逐 token 相同,发布的 .d.ts 两端字节完全相同,导出表 78 个名字不变,新加的 export 不进包入口。包测试 21,800 条逐条一致。回滚即 revert 本 PR。
  • 先看:protocol.ts 的 parseCommitItems 方法体(现在只剩一行调用)与 CommitPlanItem 前新增的 export;新文件 protocol-commit-items.ts。
  • 两分钟验证:pnpm --filter @objectstack/metadata-protocol exec vitest run --maxWorkers=2 src/protocol.recovery-doors-emit-mutation.test.ts,预期全部通过(它经 revertCommit 读回提交计划)。
  • 需要你做的:无,席位落地(非受管面,60 行)。
  • 席位意见:收下。席位读过 diff,搬移体与基线逐行相同。

席位核对 — ACCEPT · domain:server#1 · head a0939810 · 2026-10-29T05:41Z

  • Shape: 2 files, +49/−11 (60 lines).
    • New packages/metadata-protocol/src/protocol-commit-items.ts (+44).
    • protocol.ts (+5/−11): one import, export on CommitPlanItem, and the stub return parseCommitItems(raw);.
    • check-governed-merges --pr 27406: 0 of 2 paths governed, under the 3,000-line bar. skip-changeset fits a move-only change with byte-identical .d.ts.
  • Premise, measured by the seat: I read the diff. The moved body's 10 lines match the removed lines text for text, one indent level out. It reads no member (no this at all), so there is no host, as cut 26 had none. The method keeps its private modifier, signature and position. Both callers, listCommits and revertCommit, stay on the class method. The claim premise named the first caller listPackageCommits; the dev measured it as listCommits and fixed the header comment in a0939810.
  • Public surface: index.ts exports from ./protocol.js by name only, never with export * (read at origin/main), and it does not name CommitPlanItem. So the in-place export does not reach the package surface. The dev's export tables match: 78 names at both ends. The raw .d.ts hash 4cb92b2e… is identical at both ends (bar 6348891160 item 1). The positive control (private dropped) changes it.
  • Gates:
    • On a0939810: 34 success and 19 skipped, none other. check-expected-skips --pr 27406 (roster pinned to main): OK, all 19 skips are in main's roster. mergeable_state: clean.
    • The dev's derived gates at the head: 46 of 46 exit 0. --ran: 0 NOT-MEASURED. The suite of 21,800 tests matches per test name at base, the move commit and the head.
  • Accepted deviations:
    • CommitPlanItem gains export in place rather than moving. This follows the precedent of cuts 16, 23 and 31, and it is disclosed in the PR.
    • A comment-only commit came after the merge. Every head reading was re-taken on it.
  • Out of scope + Skills-docs:
  • Landing: ready, then auto-merge through the queue. After the merge, [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 (Part of) goes back to pm:queue with a delivered/remaining note.

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 29, 2026 05:42
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 29, 2026
Merged via the queue into main with commit 9f57dcc Oct 29, 2026
54 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-xbievt branch October 29, 2026 06:02
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#1 · os-sales · session_01L6bhgXcN9HaZYSEUdJWEjw

Landed · domain:server#1 · 2026-10-29T06:03Z

Reading Value
PR #27406 merged at 2026-10-29T06:02Z, merge commit 9f57dcc6d8, head a0939810 (the ACCEPTed head)
Card #25467 open (Part of), released to pm:queue with a delivered/remaining note

State change: #25467 pm:dispatched → pm:queue, assignee cleared. No card was closed by this PR's body.


Generated by Claude Code

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants