Skip to content

refactor(metadata-protocol): move the single-record data writes through the protocol host (#25467 E2 section 3) - #29788

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/project-thread-x70f27
Nov 3, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/project-thread-x70f27

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Warren · project thread

Part of #25467

Clause-②: no
Metadata-protocol: none

维护者速读

What changes

Step E2, section 3 "data CRUD" of ruling E (6537939895), on the protocol.ts freeze day seat 4 declared (6594835694 on #27737). It is a pure application of the E1 host pattern: no logic changes, and no new rewrite kind.

member moved to rewrite sites (all this.x to host.x)
validateData protocol-data-writes.ts 2
createData protocol-data-writes.ts 3
updateData protocol-data-writes.ts 5
deleteData protocol-data-writes.ts 3

Each method keeps its docblock, modifiers and signature on the class; its body becomes return fn(protocolHost(this), …). ProtocolHost and the class's static block gain 3 entries, all call-time closures: assertObjectRegistered, assertVersionMatch and probeRecord (engine was already on the host). node scripts/host-split.mjs check origin/main MEMBER protocol-data-writes.ts reads ok: true, textIdentical: true for all four, and the tool refused none. Negative control, with deleted === false changed to !== in deleteData's moved body, then restored from HEAD (blob hash equal to the disk hash afterwards):

PROBLEM protocol-data-writes.ts:286: ExclamationEqualsEqualsToken where the base has EqualsEqualsEqualsToken (`===`)
PROBLEM protocol-data-writes.ts: deleteData's body text differs from the base body rewritten and re-indented, first at body line 24

protocol.ts drops one import name only updateData's body read (byIdUpdateRecord; its re-export stays) and gains the import of the four functions beside the 1b imports.

Section 2 has nothing to cut

The order named section 2 (query validation) first. On main c9c68288 its 15 members (assertObjectRegistered through servesExpansionTarget, lines 4881 to 5613) are all stubs of the per-member series' fn.call(host, …) shape, with their bodies in protocol-query-validation.ts since #25538 (cut 3, merged 2026-10-23). No member in that range still carries a body. The seat re-ordered this thread to section 3.

Four bodies of section 3 stay in the class (seat ruling A, 6594932448)

This cut is under ruling E's 1,000-line guide on the seat's ruling. A trial move of all eight bodies measured two gates that read the section by path:

  • findData, getData, cloneData, probeRecord stay. They hold all 6 of the query-options erasure sites scripts/query-options-erasure-baseline.json grandfathers for protocol.ts (findData 3, getData, cloneData, probeRecord 1 each). In a new module they fail pnpm lint and the ratchet, and listing the module is the move that baseline forbids (its key set only shrinks against the merge base). Cut 4 kept probeRecord in the class for the same reason. The seat is filing the card that types those erasures; these four move after it.
  • updateData and deleteData move, and the engine-double-contract ledger follows them. Both are consumer seams the ledger keys by file. scripts/engine-double-contract.seams.json is rewritten by --write (two file values, nothing else), and the self-test's one wiring assertion names the module instead of protocol.ts. The rule judged is unchanged: before the ledger move the run read SEAMS_RETAINED four times and the self-test failed on the old path (exit 1); after it both exit 0, and the moved bodies still pass REFUSES (they throw recordNotFoundError).

Tests

No pin needed an edit. The read-verb pin, the lookup-artifact and hydrate caller-set pins and the system-context census read nothing in the four moved bodies. The query-transport-dialect pin and core's second-object-read-exposure pin read findData and getData, which stay.

The published .d.ts

Built from main 7ba8b11f5 and from this head with the same dependency build. index.d.ts is byte-identical: raw sha256 3a15d153…f48075 on both sides, ESM equal to CJS, so no normaliser is needed.

A measurement worth keeping: on the first base (c9c68288, before #29730), getMetaTypes()'s inferred return type made tsc's declaration emit print a docblock of protocol.ts chosen by character offset (the comment leak 1a met). Any net shift of the text above the class changed index.d.ts, and only a net-zero shift kept it identical (probed at 12 to 28 added characters; only 18, the exact compensation, matched). #29730 gave getMetaTypes() a named return type, and on the merged base the import stands in the import block with index.d.ts byte-identical. The leak no longer constrains later E2 cuts.

Serial

Merged origin/main twice: over #29730 (the getMetaTypes() return type) and over #29753 (seat 4's flow-read docblock lines), both landed during the freeze as the seat's post allowed. git merge was clean both times, and host-split check was re-run against the merged main for all four members. Seat 2's #29673 edits members outside this section and this diff does not touch them.

Verification

On ae528b8277:

  • Package typecheck and test through os-verify-lock: VERDICT command-exit 0; Test Files 310 passed, 4 skipped (314); Tests 22301 passed, 26 skipped (22327).
  • eslint packages/metadata-protocol scripts/check-engine-double-contract.mjs --no-inline-config exits 0; pnpm check:query-options-erasure holds (44 sites in 15 files, none new).
  • node scripts/pm/dispatch-gates.mjs --commands derived 74 commands; --ran reports 74 derived, 73 run, 1 NOT-MEASURED, 0 UNRUN. Each run family exits 0 (check:pm-dispatch-gates 1945 fast-tier cases). The NOT-MEASURED one is check:dual-build-cjs-loads, which needs every package built (exit 3, PREREQUISITE NOT MET), so its reading is CI's.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (untouched)
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; pnpm lint passes (package and changed script locally; CI runs the whole).
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset.
  • 6. packages/spec touched: n/a.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English (the 维护者速读 block is the dispatch template's).

Generated by Claude Code

…gh the protocol host (#25467 E2 section 3)

validateData, createData, updateData and deleteData keep their docblocks and
signatures on ObjectStackProtocolImplementation; their bodies move to
protocol-data-writes.ts, changed only by this. reading host. (host-split check).

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JQwxbY46nuWPvjhNvMiZqA
…and move the two seam ledger rows with the data writes (#25467 E2 section 3)

The protocol-data-writes import stands after the class: tsc's declaration
emit of getMetaTypes() prints a docblock of protocol.ts picked by character
offset, so only a net-zero shift above the class keeps index.d.ts identical.
The engine-double-contract seams ledger and its self-test read updateData and
deleteData where their bodies now stand. Same rule, nothing loosened.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JQwxbY46nuWPvjhNvMiZqA
…block (#25467 E2 section 3)

With getMetaTypes() declaring its return type (#29730), the declaration emit
no longer prints a docblock of protocol.ts by offset; index.d.ts stays
byte-identical to main with the import where the others stand.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JQwxbY46nuWPvjhNvMiZqA
@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tooling labels Nov 3, 2026
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

12 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/api/client-sdk.mdx (via meta.publishItem (sdk, the route ledger binds it to POST /api/v1/meta/:type/:name/publish, selected by route anchor /:type/:name/publish), publishItem (sdk, the bare tail of client method meta.publishItem, bound to POST /api/v1/meta/:type/:name/publish))
  • content/docs/api/metadata-api.mdx (via /:type/:name/publish (route, bridged from symbol createData — its route source's handler names it; bridged from symbol deleteData — its route source's handler names it))
  • content/docs/concepts/metadata-lifecycle.mdx (via /:type/:name/publish (route, bridged from symbol createData — its route source's handler names it; bridged from symbol deleteData — its route source's handler names it))
  • content/docs/data-modeling/currency.mdx (via /:object/import/jobs (route, bridged from symbol createData — its route source's handler names it))
  • content/docs/data-modeling/import-mappings.mdx (via /:object/import/jobs (route, bridged from symbol createData — its route source's handler names it))
  • content/docs/data-modeling/validation.mdx (via validateData (symbol, a method of class ObjectStackProtocolImplementation; a top-level function))
  • content/docs/kernel/contracts/data-engine.mdx (via createData (symbol, a method of class ObjectStackProtocolImplementation; a top-level function), updateData (symbol, a method of class ObjectStackProtocolImplementation; a top-level function))
  • content/docs/kernel/contracts/metadata-service.mdx (via /:type/:name/publish (route, bridged from symbol createData — its route source's handler names it; bridged from symbol deleteData — its route source's handler names it))
  • content/docs/kernel/services-checklist.mdx (via createData (symbol, a method of class ObjectStackProtocolImplementation; a top-level function), deleteData (symbol, a method of class ObjectStackProtocolImplementation; a top-level function), updateData (symbol, a method of class ObjectStackProtocolImplementation; a top-level function))
  • content/docs/permissions/system-context.mdx (via /:object/import/jobs (route, bridged from symbol createData — its route source's handler names it), /import/jobs/:jobId/undo (route, bridged from symbol deleteData — its route source's handler names it))
  • content/docs/protocol/kernel/error-handling.mdx (via /:type/:name/publish (route, bridged from symbol createData — its route source's handler names it; bridged from symbol deleteData — its route source's handler names it))
  • content/docs/protocol/objectql/state-machine.mdx (via /:object/import/jobs (route, bridged from symbol createData — its route source's handler names it), /import/jobs/:jobId/undo (route, bridged from symbol deleteData — its route source's handler names it))

⛔ 5 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17/17-0.mdx (via /:type/:name/publish (route, bridged from symbol createData — its route source's handler names it; bridged from symbol deleteData — its route source's handler names it))
  • content/docs/releases/v17/17-1.mdx (via /:type/:name/publish (route, bridged from symbol createData — its route source's handler names it; bridged from symbol deleteData — its route source's handler names it))
  • content/docs/releases/v17/17-2.mdx (via /:type/:name/publish (route, bridged from symbol createData — its route source's handler names it; bridged from symbol deleteData — its route source's handler names it))
  • content/docs/releases/v17/17-4.mdx (via createData (symbol, a method of class ObjectStackProtocolImplementation; a top-level function), /:type/:name/publish (route, bridged from symbol createData — its route source's handler names it; bridged from symbol deleteData — its route source's handler names it))
  • content/docs/releases/v17/17-6.mdx (via validateData (symbol, a method of class ObjectStackProtocolImplementation; a top-level function))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 1 cross-cutting symbol(s) contributed no route anchor: updateData (4 routes)
  • the SDK route bridge reached 61 of 218 client-bound route-ledger rows — the other 157 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 157: 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; 102 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 601832b1a667992e73d54bf11643849836a6f778 → packageMentionDocs.

Which tree this was computed on

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

node scripts/docs-audit/affected-docs.mjs --json 601832b1a667992e73d54bf11643849836a6f778

⚠️ 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 601832b1a667992e73d54bf11643849836a6f778 → 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#4 · os-warren · session_01JQwxbacSXJQqAztgt4UMrS

席位核对

ACCEPT · domain:server#4 · head ae528b82771c30d29c90b7370417750de2a48d61 · 2026-11-03T05:10Z · seat review of record at TIER_DEFAULT for the whole PR. Clause-②: no and Metadata-protocol: none stand (a move; the published index.d.ts is byte-identical), so no contract review is owed. Not governed: check-governed-merges --pr 29788 0 of 6 paths, +348/−275.

  1. Shape: draft, base main, Part of #25467 (ruling E 6537939895, E2 section 3, scoped by seat ruling A 6594932448). 6 files: the bodies of validateData, createData, updateData and deleteData move to protocol-data-writes.ts and reach the class through protocol-host.ts (three host members added: assertObjectRegistered, assertVersionMatch, probeRecord); the class keeps each docblock and signature as a one-line stub; byIdUpdateRecord leaves the class's import with updateData; the double-contract seams ledger moves two rows to the new file (--write) and its self-test names the new path, the same rule judged; one patch changeset. Inside claim 6594815331 as widened by ruling A.
  2. Premise measured: section 2 had already moved (PR refactor(metadata-protocol): move the query validation out of protocol.ts into protocol-query-validation.ts (#25467 cut 3) #25538), so section 3 is the cut. Of its eight bodies, four move; findData, getData, cloneData and probeRecord stay because their six erasure sites are grandfathered by file in the shrink-only baseline (follow-up metadata-protocol: type the six query-options erasures in protocol.ts data reads (findData, getData, cloneData, probeRecord) so their bodies can leave the class #29764). The host-split check is text-identical for all four, and its negative control bites (dev report 6595748296).
  3. Gates on this head: check-runs pinned to ae528b82: 48 runs, 35 success, 13 skipped, none failed. Dev local on the merged head (over refactor(metadata-protocol): getMetaTypes() declares a named return type, pinned equal to the type it returned #29730 and fix(metadata-protocol): a flow read's _diagnostics and the restore doors judge a stored flow in its D2-converted spelling #29753): metadata-protocol 310 files / 22,301 tests passed; dispatch-gates --ran 74 derived / 73 run / 0 UNRUN / 1 NOT MEASURED (dual-build-cjs-loads, prerequisite; CI covers it); pnpm lint 0; the erasure ratchet holds; index.d.ts byte-identical to main (ESM and CJS).
  4. Accepted deviations: the cut is about 300 lines, under ruling E's 1,000-line guide, on the seat's ruling A; the two gate files are path-only moves.
  5. Out of scope: metadata-protocol: type the six query-options erasures in protocol.ts data reads (findData, getData, cloneData, probeRecord) so their bodies can leave the class #29764 types the six erasures, then the last four bodies move as one more E2 cut.
  6. Landing: not governed, under 3000 lines, no contract review owed ⇒ the seat lands it (pr_ready + automerge_enable). At MERGED: progress record on [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 (stays open), the protocol.ts freeze lift note on seat post [PM seat] domain:server · seat 4 — ⏳ vacant #27737, pm:dispatched → pm:queue with the next step named.

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

Labels

documentation Improvements or additions to documentation size/l tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant