Skip to content

[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

Open

Description

@objectstack-fleet

Filing gate ③: a task the maintainer dispatched, quoted verbatim below. Filed by domain:services seat 1 (seat post #6021) · os-sales · session session_016g7nYP9wdNx1GDa5XDr7Uy, as the domain:engine half of #24586's restart act. That half was handed over unfiled in 6341834009, and the engine surface is now this project's, folded into domain:server by PR #25247. ⛔ Not a claim.

The maintainer's words, verbatim (#24586, recorded in 6270097840): 「24586 同意A,是否建议这波分拆等 v18 发布之后再处理。」 Triage read the restart condition (npm @objectstack/spec latest ≥ 18.0.0) as true in 6291735609. The ruling's restart act: "one [maintainer] card per file over 10,000 lines into its owning lane … Each card starts with a fresh seam measurement taken at that time, in #23050's shape", and "protocol.ts goes first".

Reader who acts: the domain:server lane, engine surface (packages/metadata-protocol was domain:engine's). One dispatch per slice.

Measured (on origin/main b2c0752900, 2026-10-23)

  • Size and churn:

    • 33,065 lines, up from 22,896 thirty days ago (dabf8d795e, the last commit before 2026-09-23T15:00Z): +10,169, +44.4%.
    • 28 commits in 7 days and 184 in 30 days.
    • git blame --since=2026-09-23T15:00Z attributes 13,445 lines (40.7%) to the last 30 days.
  • Structure:

    • a 6,643-line module preamble: helpers, three error classes, and the query-param and filter vocabulary;
    • one ObjectStackProtocolImplementation class, lines 6644–32941 (26,298 lines, 267 members);
    • a 124-line trailer of package-persist helpers.

    The sections, by contiguous member ranges:

section lines lines from the last 30 days
module preamble (helpers, error classes, query-param and filter vocabulary) 6,643 2,255
class head, flow/SDUI resolvers, registration hooks, authoring gates, mutation pub/sub, overlay index 1,961 707
discovery, types, diagnostics, packaged bases, credential carry-forward 1,578 339
metadata reads (getMetaItems, readFlattenedMetaItems, overlay rows, readMetaItem, layered, audit, getUiView) 2,872 1,696
query validation (assert*FieldsExist, refuseInternal*) 1,643 358
data CRUD (findData … readAsCaller) 1,393 274
searchAll + meta cache 605 160
batch and *Many data 1,067 33
write gates (overlay/code-only/organization/sealed/packaged-base, locks, version tokens, conflict audit) 2,619 1,772
registry hydration, view expansion, write-through, object storage 1,996 1,112
save refusals, saveMetaItem (1,535 lines alone), saveConflict, migrateStoredMetadata 2,960 1,666
history, publish, drafts, publish backfill (publishPackageDrafts 969 lines) 2,600 828
package revert/delete/duplicate/import, orphans, commits, revertCommit, rollback 2,837 1,335
diff, deleteMetaItem, loadMetaFromDb, load reports, findReferencesToMeta 1,831 624
install/update package + module trailer 460 286
  • Shared state a split must pass:
    • The fields are engine (149 refs), getServicesRegistry (16), environmentId (11), the cluster pub/sub trio (clusterPubSub, clusterNodeId, clusterUnsubscribe), the two listener sets, authoringChannel, and about 20 warn-once and cache flags.
    • Coupling is mostly method-to-method: 597 this.X( calls over 206 distinct members. Reads, write gates and saves call one another across the sections above.
  • What reads it by path:
    • The ADR anchor file scripts/adr-anchors/packages__metadata-protocol__src__protocol.ts.json. It holds ADR-0005, 0029, 0087, 0119 and 0126, and its invariant names the two object-hydration seams applyObjectRegistryMutation and loadMetaFromDb. The metadata-plugin.zod.ts anchor file and scripts/symbol-anchors.mjs also name the file.
    • 10 more files under scripts/: check-durability-degradation-log-level.mjs, check-engine-double-contract.mjs (+ .pinned.json, .seams.json), check-filter-alias-parity.mjs, check-nul-bytes.mjs, check-system-context-census.mjs, docs-audit/affected-docs.mjs, objectql-double-limit.baseline.json, query-options-erasure-baseline.json.
    • 22 files under docs/ and content/, 11 of them ADRs.
    • Tests: 180 test files in metadata-protocol import it, and 71 files in other packages name it by path.
  • In flight: none of the 21 open PRs touch the file.

The ask (from #24586's ruling and #23050's shape)

  1. Split along the existing seams, one area per PR. Each slice is move-only: no logic changes.
  2. Shared state stays explicit: moved code reaches the class's shared members through one named context object (the host pattern of [maintainer] refactor(rest): split packages/rest/src/rest-server.ts (13,701 lines, 70 commits in 30 days) along its register*Endpoints seams, one move-only slice per PR, /meta after #22877 stage 2 #23050, [maintainer] refactor(service-automation): split src/engine.ts (13,735 lines, +2,199 in 30 days) along its AutomationEngine seams, one move-only slice per PR #25222, [maintainer] refactor(plugin-security): split src/security-plugin.ts (10,746 lines, +2,803 in 30 days) along its SecurityPlugin seams, one move-only slice per PR #25223 and [maintainer] refactor(plugin-auth): split src/auth-manager.ts (10,338 lines, +1,867 in 30 days) along its AuthManager seams, one move-only slice per PR #25224). ⛔ Not a second copy of a helper, ⛔ not a re-derivation.
  3. Every slice proves it moved nothing:
    • every gate, baseline, ADR anchor and docs anchor that reads the file by path is migrated in the same PR and stays green;
    • the ADR-0029 D9.8/D9.9 invariant's two seams keep a resolving anchor;
    • the package's public .d.ts stays identical.
    • ⛔ A gate whose target moved must not go silently empty.
  4. Serial with the file's in-flight PRs: a slice waits for an open PR on the same region, or that PR merges main after the slice. At 28 commits a week, every slice measures the file's open PRs again at claim.
  5. ⛔ No new gate.

Not in this card

Dedupe

MCP search_issues on this repository, closed included, with two queries:

  • "split protocol.ts metadata-protocol move-only maintainer refactor"
  • "refactor split objectql engine.ts sql-driver.ts large file"

The hits were #24586 (the ruling this card carries out), #25222, #25223 and #25224 (the domain:services files), and #23050 (closed, rest-server.ts). None covers protocol.ts. New.


Generated by Claude Code

Activity

  1. added
    enhancementNew feature or request
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Oct 23, 2026
  2. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: card thread · domain:server (former domain:engine surface) · for domain:services seat 1 (seat post #6021, project run by the Sales account; 由Sales账户的项目负责) · p2 · series card, cut 1 (one PR; cuts strictly serial) · 2026-10-23T15:20Z
    Session: session_01J8pUyVs5eas1AjMdReJM7C
    Account: os-sales (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-uasfag (the harness-pinned branch for this session, cut from origin/main ab510f4c43; it names no issue, so the Duplicate Fix Guard's branch-name hint will not match — this claim is the identity record)
    Worktree: objectstack-wt (a linked worktree in this session's container)
    Domain: domain:server
    Seat: domain:services#1 (seat post #6021; the PR goes back to that seat for ACCEPT)
    Ruling: #24586 letter A (6270097840), restart read in 6291735609. The series' .d.ts bar is ruling 6348891160 (sorted-union identity; raw identity reported when it holds).
    Container & model: M, mode:thread, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card (a [maintainer] refactor card).
    Thread-read: none
    Serial constraints cleared: none of the 21 open PRs touches packages/metadata-protocol/src/protocol.ts (each PR's file list read in this act against origin/main; #25451 touches only protocol.runtime-authoring-gate.test.ts, the Version Packages PR #24876 only CHANGELOG.md / package.json). No pm:dispatched card's claimed file surface names the file. Re-measured again before pr_create; a new open PR on the moved region means this cut yields.

    File surface (read on origin/main ab510f4c43, where protocol.ts is 33,065 lines):

    Cut 1 = the card's "batch and *Many data" section (the seat's suggested first slice: 1,067 lines, 33 of them from the last 30 days). Sixteen ObjectStackProtocolImplementation method bodies move unedited from packages/metadata-protocol/src/protocol.ts into a new module, packages/metadata-protocol/src/protocol-batch-data.ts, in the host shape of #23050 / #25222 / #25223 / #25224:

    • public: batchData :16696, createManyData :17263, insertManyData :17348, updateManyData :17390, deleteManyData :17574;
    • private: runAtomicBatchData :16739, runAtomicBatch :16775, runBatchDataLoop :16850, reconcileStoppedBatch :17108, locateBatchCause :17170, buildBatchDataResponse :17182, buildRolledBackBatchResponse :17219, runUpdateManyLoop :17424, buildUpdateManyResponse :17497, runDeleteManyLoop :17619, buildDeleteManyResponse :17708.
    • triggerAutomation :17527 sits between them but is not batch code; it stays.

    How the host is built:

    • The class keeps every method, with its docblock, signature and position; each body becomes a literal of exactly the members it reads, plus a .call. async is dropped from the stubs, which return the moved function's promise.
    • Members read, measured by AST: engine (field), and the methods assertObjectRegistered, assertRecordExists, probeRecord plus the moved methods' calls to one another. Methods go as late-bound closures, so a spy or double set on the instance is still the one a body reaches. engine goes as a getter.
    • The only outside caller of a moved method is applyPublishBackfill (this.updateManyData(), which keeps calling the class method.

    Module-level declarations the moved bodies read (all stay in protocol.ts; each has readers outside the moved text except mergeDroppedFieldEvents, which stays too, so no declaration moves):

    • export added in place, imported back by value or type from ./protocol.js: byIdUpdateRecord, mergeDroppedFieldEvents, rowOperationFailureFallback, rowRequiredIdError, toRowApiError, type BatchDataRowResult, type BatchDataLoopOutcome. src/index.ts exports from ./protocol.js by name, so none of them is published; the proof measures it (raw .d.ts and ESM/CJS export lists base vs head). Every value import is read only inside function bodies, so the module cycle is evaluation-safe; the PR lists each read site.
    • Imports the new module takes from packages directly (as protocol.ts does): engineCanRollBack, recordNotFoundError (@objectstack/core), omitInternalFieldsFromWriteResponse (./write-response-internal-fields.js), and the @objectstack/spec types the bodies name.

    Path readers migrated in the same PR (each measured base vs head in the PR):

    • scripts/adr-anchors/: the protocol.ts entry's ADR-0119 paragraph describes batchData's atomic path, which moves. Per the series' rule, the new module gets its own entry carrying ADR-0119 and that paragraph verbatim; the protocol.ts entry is unchanged (ADR-0119 is still cited at five sites outside the moved text). check:adr-anchors decision-letter totals reported base and head.
    • protocol.bracketed-refusal-opener-absence.test.ts: the moved text holds 5 new Error( sites, so the new module joins its PRODUCERS list with a measured floor; otherwise those sites would leave the scan silently. protocol.ts keeps its floor of 5.
    • docs/adr/0119-…md anchors protocol.ts#batchData: the method shell stays, so it still resolves; check-adr-symbol-anchors run by hand at both ends.
    • Census and ledgers run base and head: tenant-audit census (the moved bodies hold engine insert/update/delete calls; if they shift class, --write plus the page's prose count, with a per-site base/head comparison), system-context census (0 isSystem reads in the moved text), query-options erasure ratchet (0 counted find/findOne/count/aggregate sites in the moved text), engine-double contract seams (deleteData / updateData rows, which stay), durability log level (scans the whole package).

    ⛔ Nothing else changes: no moved body is edited; the only stay-behind edits are the export keywords above and the stub bodies; no ADR or docs/adr/** text is edited; no new gate. One PR, skip-changeset (no behaviour change), Part of #25467.

    Proof the PR carries: AST leaf-token identity of every moved body (with a one-token negative control), .d.ts block per ruling 6348891160 (raw and normalised sha256 base/head, normaliser, raw diff line count, positive control), ESM/CJS export lists, the metadata-protocol suite at base and head (same counts), dispatch-gates --commands all run with exits, and the hand gates above.

  3. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed cut 1 (batch and *Many data) · domain:services seat 1 (seat post #6021) · os-sales · session_016g7nYP9wdNx1GDa5XDr7Uy · 2026-10-23T17:23Z

    reading value
    PR #25494 MERGED through the queue (the seat's ACCEPT is on the PR), head b55faf2162
    origin/main carries bf5855b5bc

    State: the card stays open and dispatched (Part of). The card thread plans cut 2 on the merged protocol.ts and re-checks the in-flight PRs on the file first (serial rule). It claims cut 2 afresh before it pushes.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: card thread · domain:server (former domain:engine surface) · for domain:services seat 1 (seat post #6021, project run by the Sales account; 由Sales账户的项目负责) · p2 · series card, cut 2 (one PR; cuts strictly serial; cut 1 landed as #25494, bf5855b5bc) · 2026-10-23T17:30Z
    Session: session_01J8pUyVs5eas1AjMdReJM7C
    Account: os-sales (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-uasfag (the harness-pinned branch for this session, restarted from origin/main 5188e7f18f after cut 1 merged; it names no issue, so this claim is the identity record)
    Worktree: objectstack-wt (a linked worktree in this session's container)
    Domain: domain:server
    Seat: domain:services#1 (seat post #6021; scope agreed with the seat before this claim; the PR goes back to that seat for ACCEPT)
    Ruling: #24586 letter A (6270097840), restart read in 6291735609. The series' .d.ts bar is ruling 6348891160 (sorted-union identity; raw identity reported when it holds).
    Container & model: M, mode:thread, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card (a [maintainer] refactor card).
    Thread-read: none
    Serial constraints cleared: none of the 12 open PRs touches packages/metadata-protocol/src/protocol.ts (each PR's file list read in this act, the Version Packages PR #24876 paged through all 395 files: only CHANGELOG.md / package.json in this package). Re-measured again before pr_create; a new open PR on the moved region means this cut yields.

    File surface (read on origin/main 5188e7f18f, where protocol.ts is 32,468 lines):

    Cut 2 = the discovery and diagnostics bodies from the card's "discovery, types, diagnostics, packaged bases, credential carry-forward" section: about 800 lines, 42 of them from the last 30 days (5%, the coldest slice left). Three ObjectStackProtocolImplementation method bodies move unedited into a new module, packages/metadata-protocol/src/protocol-discovery.ts (host DiscoveryHost), in the shape cut 1 used (#23050 shape B):

    • public: getDiscovery :8570, getMetaDiagnostics :9257;
    • private: listLiveMetadataTypes :9059.
    • Members read, measured by AST: engine (field, as a getter), and the methods getServicesRegistry, searchAll, getMetaItems, shippingPackagesOf, artifactLockLayerAt, servedLockState, isArtifactBacked (late-bound closures).

    Stays, deliberately:

    Module-level declarations:

    • SERVICE_CONFIG :5498 is read only by getDiscovery: it moves with it, unedited with its docblocks, unexported.
    • type ShippingPackages :2304 is read by code that stays too: export added in place, imported back as a type. src/index.ts exports from ./protocol.js by name, so it is not published; the proof measures it.
    • The module imports from the same specifiers protocol.ts uses (@objectstack/spec/api, /system, /kernel, @objectstack/core, ./discovery-version.js, ./metadata-diagnostics.js, ./item-lock.js).

    Readers (measured; the PR reports each base vs head):

    • scripts/adr-anchors/ protocol.ts entry: none of its paragraphs (ADR-0029 D9.8/D9.9 hydration seams, ADR-0119 batchData, ADR-0005/0087 view storage, ADR-0126 flow Regime C) describes these bodies, so no new entry. The decision letters inside the moved bodies leave the anchored surface; the exact check:adr-anchors count is reported base → head.
    • docs/qa/platform-checklist/areas/studio-authoring.json anchors protocol.ts#getMetaDiagnostics: the method shell stays, so it still resolves; not edited; check-platform-checklist at both ends.
    • None in the moved text: isSystem reads (system-context census), engine find/findOne/count/aggregate (erasure ratchet), engine update/delete seams (engine-double contract), new Error( (bracketed-refusal PRODUCERS), and none of the package's source-scanning pins' patterns.

    ⛔ Nothing else changes: no moved body is edited; the only stay-behind edits are the one export keyword and the stub bodies; no ADR or docs/** text is edited; no new gate. One PR, skip-changeset, Part of #25467.

    Proof the PR carries, as cut 1: AST leaf-token identity of every moved body (with a negative control), .d.ts block per ruling 6348891160 (raw and normalised sha256 base/head, normaliser, raw diff, positive control), ESM/CJS export lists, the metadata-protocol suite at base and head, dispatch-gates --commands all run with exits and --ran, and the hand gates (check-adr-symbol-anchors, check:adr-anchors with letters, censuses, check-platform-checklist) at both ends.

  5. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim amendment: cut 2 of #25467 (amends claim 6370841668) · domain:services seat 1 (seat post #6021; 由Sales账户的项目负责) · 2026-10-23T17:45Z
    Session: session_01J8pUyVs5eas1AjMdReJM7C
    Branch: claude/project-thread-uasfag (unchanged, base origin/main 5188e7f18f)
    Seat: domain:services#1 (the narrowed scope below agreed with the seat before this amendment)
    Thread-read: 6370841668

    Narrowed scope. Cut 2 is getMetaDiagnostics alone (:9257). Its body moves unedited into packages/metadata-protocol/src/protocol-meta-diagnostics.ts (host MetaDiagnosticsHost, members read: getMetaItems, shippingPackagesOf, artifactLockLayerAt, servedLockState, isArtifactBacked, as late-bound closures). type ShippingPackages gains export in place, as claimed. getDiscovery, listLiveMetadataTypes and SERVICE_CONFIG leave this cut and stay in protocol.ts; nothing else in the claim changes.

    Why getDiscovery cannot move (measured, nothing pushed). It is public and its return type is INFERRED (async getDiscovery() {), so dist/index.d.ts prints the type the compiler infers. With its body moved in this series' shape, the stub's type is inferred from the new module, and the emitted .d.ts changed in two ways that are not union-member order: it dropped a property docblock (@deprecated Use name. Removed in protocol 18 (#4828).), and it spliced about 100 lines of an unrelated protocol.ts docblock (the save door's hook-without-body refusal) into a nested description property. Base raw 8e1a224c…, trial head raw fc33e319…; normalised (ruling 6348891160's normaliser) base 5b98a8e8…, trial head different, normalised diff 111 lines. Under ruling 6348891160 that is a stop, not a pass. The token proof and the package suite were clean on that trial; only the published surface moved. listLiveMetadataTypes' body is barely longer than its stub, and SERVICE_CONFIG is read only by getDiscovery, so both stay with it.

    Carry-forward for later cuts. A public member with an inferred return type stays in protocol.ts in this series: annotating it would be a signature edit, which needs a ruling. Measured on 5188e7f18f, the public members with no declared type: getDiscovery, getMetaTypes, getMetaItems, getMetaItemsForExecution, getMetaItem, getMetaItemForExecution, getUiView, findData, getData, validateData, createData, cloneData, updateData, deleteData, saveMetaItem.

    Decision letters: one leaves the anchored surface with the body (ADR-0110 D3); measured check:adr-anchors 1,979 → 1,978, reported in the PR.

  6. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed cut 2 · domain:services seat 1 (seat post #6021) · os-sales · session_016g7nYP9wdNx1GDa5XDr7Uy · 2026-10-23T19:27Z

    reading value
    PR #25518 MERGED through the queue (ACCEPT 6372365108), head 9f403be528
    origin/main carries b2411c001d

    State: the card stays open and dispatched (Part of). The card thread claims the next cut afresh on the merged protocol.ts. Public members whose return type is inferred stay in the class.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: card thread · domain:server (former domain:engine surface) · for domain:services seat 1 (seat post #6021, project run by the Sales account; 由Sales账户的项目负责) · p2 · series card, cut 3 (one PR; cuts strictly serial; cut 1 landed as #25494 bf5855b5bc, cut 2 as #25518 b2411c001d) · 2026-10-23T19:38Z
    Session: session_01J8pUyVs5eas1AjMdReJM7C
    Account: os-sales (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-uasfag (the harness-pinned branch for this session, restarted from origin/main b2411c001d after cut 2 merged; it names no issue, so this claim is the identity record)
    Worktree: objectstack-wt (a linked worktree in this session's container)
    Domain: domain:server
    Seat: domain:services#1 (seat post #6021; scope A agreed with the seat before this claim, with its conditions carried below; the PR goes back to that seat for ACCEPT)
    Ruling: #24586 letter A (6270097840), restart read in 6291735609. The series' .d.ts bar is ruling 6348891160 (sorted-union identity; raw identity reported when it holds).
    Container & model: M, mode:thread, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card (a [maintainer] refactor card).
    Thread-read: none
    Serial constraints cleared: none of the 9 open PRs touches packages/metadata-protocol/src/protocol.ts (each PR's diff against its merge base read in this act; the Version Packages PR #24876 touches only CHANGELOG.md / package.json in this package). origin/main (f38832be9c) has not touched this package since b2411c001d. Re-measured again before pr_create; a new open PR on the moved region means this cut yields.

    File surface (read on origin/main b2411c001d, where protocol.ts is 32,309 lines):

    Cut 3 = the query validation: the section :12797–:14502 (1,706 lines, 382 of them from the last 30 days). Nineteen PRIVATE ObjectStackProtocolImplementation methods move unedited into a new module, packages/metadata-protocol/src/protocol-query-validation.ts (host QueryValidationHost), in the shape cuts 1–2 used (#23050 shape B):

    • assertObjectRegistered :12861, resolveQueryFields :12933, assertQueryParamsAreFields :12961, assertFilterFieldsExist :13064, assertSortFieldsExist :13358, assertProjectionFieldsExist :13546, assertExpandTargetsExist :13670, assertSearchFieldsAreSearchable :13793, assertGroupByFieldsExist :13988, assertAggregationFieldsExist :14103, assertNoInternalFieldEvaluated :14283, refuseInternalInFilter :14313, refuseUnservedRelationTarget :14346, refuseInternalInExpand :14373, servedExpand :14429, servesExpansionTarget :14454, orderByFieldNames :14460, groupByFieldNames :14469, refuseInternalNames :14478.
    • All private, so the published .d.ts prints no type for any of them: none is on the series' skip list of public inferred-return members.
    • Members read, measured by AST: engine (field, as a getter), and the methods assertFilterFieldsExist, groupByFieldNames, orderByFieldNames, refuseInternalInExpand, refuseInternalInFilter, refuseInternalNames, refuseUnservedRelationTarget, resolveQueryFields, servedExpand, servesExpansionTarget (late-bound closures, so the recursive walks still go through the protocol).

    Module-level declarations, each measured by an AST reader walk over all of protocol.ts (identifier references outside the declaration itself):

    • Move with the bodies, byte-identical, unexported (no reader outside the moved bodies and the other moved declarations): nestedRelationRoute :392, warnedNoRegistryForDataGate :536 (the mutable let: its only reads and its only write are in assertObjectRegistered, so the state moves whole and is never copied), AGGREGATION_FUNCTIONS :4489, DATE_GRANULARITIES :4490, UNMATERIALIZED_SORT_TYPES :4892, invalidQueryError :4988, suggestQueryParam :5131, collectFilterFieldKeys :5217, INTERNAL_FIELD_WALK_DEPTH :5321, EXPANSION_TARGET_OPERATION :5337, RELATION_CONDITION_TARGET_OPERATION :5348. Their initialisers read only package imports or nothing, so module evaluation order is unaffected.
    • Stay and gain export in place (read by code that stays, or by a moved helper and by code that stays): collectFilterReads (← collectStoredMetadataFilterFields), invalidSortError (← normalizeSortNodes, invalidSortDirectionKeyError), isObjectOfDisabledPackage and objectPackageDisabledError (← readMetaItemFace, getMetaItemLayered), isPlainRecord (← storableEqual, soleMovedFrom, buildStorableViewNode), suggestFieldName, FILTER_LOGICAL_KEYS, QUERY_PARAM_NEAR_MISS, nearMissKey, ODATA_SPELLING. src/index.ts exports from ./protocol.js by name, so none is published; the proof measures it.
    • protocol.ts drops the import names that lose every reader (noUnusedLocals); the module imports them from the same specifiers.

    Readers (measured; the PR reports each base vs head):

    • protocol.bracketed-refusal-opener-absence.test.ts PRODUCERS: 17 new Error( sites move (16 in the methods, 1 in invalidQueryError); protocol.ts 104 → 87 against its floor 5, and the new module is listed with its measured floor, 17.
    • scripts/adr-anchors/ protocol.ts entry: none of its paragraphs (ADR-0029 D9.8/D9.9, ADR-0119 batchData, ADR-0005/0087 view storage, ADR-0126 flow Regime C) describes these bodies, so no new entry. check:adr-anchors decision letters are reported exactly base → head.
    • docs/qa/platform-checklist/areas/api-backend.json and search.json anchor protocol.ts# moved methods: the method shells stay, so they still resolve; not edited; check-platform-checklist at both ends.
    • Censuses, the query-options erasure baseline, the engine-double contract seams and the package's source-scanning pins are each run at both ends.
    • Size: under the 3,000-changed-line bar (measured: +1,591 / −1,283 over 3 files).

    ⛔ Nothing else changes: no moved body or declaration is edited; the only stay-behind edits are the ten export keywords, the narrowed import lists and the stub bodies; no ADR or docs/** text is edited; no new gate. One PR, skip-changeset, Part of #25467.

    Proof the PR carries, as cuts 1–2: AST leaf-token identity of every moved body and declaration (with a negative control), the declaration reader table, .d.ts block per ruling 6348891160 (raw and normalised sha256 base/head, normaliser, raw diff, positive control), ESM/CJS export lists, the metadata-protocol suite at base and head compared per test, dispatch-gates --commands all run with exits and --ran, and the hand gates at both ends.

  8. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed cut 3 · domain:services seat 1 (seat post #6021) · os-sales · session_016g7nYP9wdNx1GDa5XDr7Uy · 2026-10-23T22:03Z

    reading value
    PR #25538 MERGED through the queue (ACCEPT 6375081284), head 3b1ae50413
    origin/main carries 798d480269

    State: the card stays open and dispatched (Part of). The card thread claims cut 4 afresh on the merged protocol.ts. #25533 also edits protocol.ts (publishDrafts). Its merge-tree is clean, but its byte offsets have shifted, so its .d.ts is re-read before it lands.


    Generated by Claude Code

  9. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: card thread · domain:server (former domain:engine surface) · for domain:services seat 1 (seat post #6021, project run by the Sales account; 由Sales账户的项目负责) · p2 · series card, cut 4 (one PR; cuts strictly serial; cut 1 landed as #25494 bf5855b5bc, cut 2 as #25518 b2411c001d, cut 3 as #25538 798d480269) · 2026-10-23T22:33Z
    Session: session_01J8pUyVs5eas1AjMdReJM7C
    Account: os-sales (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-uasfag (the harness-pinned branch for this session, restarted from origin/main 798d480269 after cut 3 merged; it names no issue, so this claim is the identity record)
    Worktree: objectstack-wt (a linked worktree in this session's container)
    Domain: domain:server
    Seat: domain:services#1 (seat post #6021; scope C agreed with the seat before this claim, with its five conditions carried below; the PR goes back to that seat for ACCEPT)
    Ruling: #24586 letter A (6270097840), restart read in 6291735609. The series' .d.ts bar is ruling 6348891160 (sorted-union identity; raw identity reported when it holds).
    Container & model: M, mode:thread, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card (a [maintainer] refactor card).
    Thread-read: none
    Serial constraints cleared: of the 9 open PRs, only #25533 (publish-drafts widget probes) touches packages/metadata-protocol/src/protocol.ts; its two hunks sit in publishPackageDrafts (≈ :26263 / :27146 on its own base dc3e5b9d7b), ~11,000 lines past the last line this cut changes (:15284), so the two are disjoint. No open PR touches packages/core/src/security/row-serving-door-exposure.pin.test.ts. origin/main (now 4df174bcc4) has not touched packages/metadata-protocol or that pin since 798d480269. Re-measured again before pr_create (with git merge-tree against main and #25533); a new open PR on the moved region means this cut yields.

    File surface (read on origin/main 798d480269, where protocol.ts is 31,223 lines):

    Cut 4 = the record reads (scope C, narrowed during the trial — see below). Six ObjectStackProtocolImplementation methods move unedited into a new module, packages/metadata-protocol/src/protocol-record-reads.ts (host RecordReadHost), in the shape cuts 1–3 used (#23050 shape B):

    • omitInternalWriteFields :14488 (public, annotated : void), assertRecordExists :14562 (private), assertVersionOf :14624 (private), assertVersionMatch :14675 (private), readAsCaller :14693 (private), searchAll :14811 (public, annotated : Promise<{…}>).
    • None is on the series' skip list of public inferred-return members: four are private, and both public ones declare their return type.
    • Members the bodies read, measured by AST: the fields engine and getServicesRegistry (as getters), and the methods assertVersionOf, getMetaItems, probeRecord, readAsCaller (late-bound closures). RecordReadHost therefore carries no elevation member; each function's this is a Pick of only what it reads.

    Narrowed during the trial, before this claim (a strict subset of the agreed scope C; both members stay in the class exactly as they are):

    • probeRecord stays. Its system-context engine.findOne is one of protocol.ts's 6 sites in scripts/query-options-erasure-baseline.json, which is keyed by file and only shrinks, so the body cannot change files unedited (the query-options/no-any-erasure lint refuses it in the new file). It stays as a host member the moved bodies call through the protocol. This also keeps the cut's one isSystem site where it is: the system-context census reads identically at both ends.
    • getMetaItemCached stays. protocol.read-verb-canonical-fold.test.ts (the Three read-side /meta verbs (history, audit, references) never reach canonicalizeMetaRequestType — they still derive their key from the MANIFEST map #9157 pin) derives the /meta request-boundary verbs from the method bodies in protocol.ts itself and requires each to call canonicalizeMetaRequestType; with the body moved, the stub no longer folds and the pin reds. Re-teaching that pin to follow a stub into another module is a change to the pin, not a move, so the body stays where the pin reads it. With it stay simpleHash and metadataItemNotFoundError (only it reads them), and canonicalizeMetaRequestType needs no export.

    Module-level declarations, each measured by an AST reader walk over all of protocol.ts (identifier references outside the declaration itself; transitive closure over the moved set):

    • Move with the bodies, byte-identical, unexported (no reader outside the moved bodies and the other moved declarations): assertVersionTokenNotMalformed :3175, NormalisedVersion :3207, normaliseVersionToken :3299, versionTokensAgree :3326. Each carries exactly one docblock (its own; leading-trivia blocks checked). None is read during module evaluation.
    • Stays and gains export in place: canonicalVersionInstant :3245 (← assertVersionOf, moved, and auditInstantMs :3349, which stays). src/index.ts exports from ./protocol.js by name, so it is not published; the proof measures it.
    • The classes ConcurrentUpdateError and MalformedVersionTokenError are already exported and are imported as values.
    • protocol.ts drops the import names that lose every reader (canServeApiOperation, ISecurityService, resolveI18nLabel; noUnusedLocals); the module imports them from the same specifiers.

    Readers (measured in the trial; the PR reports each base vs head):

    • packages/core/src/security/row-serving-door-exposure.pin.test.ts (seat condition 1): searchAll's canReadObject call and its canServeApiOperation decision both move, so the CALLERS key and the decisionSite of the cross-object-search row are repointed to protocol-record-reads.ts. The row keeps its door, operation and behaviour pin (protocol.search-api-exposure.test.ts, unchanged). No wiring line of this door stays in protocol.ts: the canReadObject call matcher no longer fires there, so keeping protocol.ts as a key would red the pin's stale-entry check. 7/7 core pin tests pass at both ends (second-object-read-exposure.pin needs no edit this cut).
    • Erasure ratchet (seat condition 2): identical output at both ends — 50 unswept non-test sites in 15 files, no file added. The moved engine reads (readAsCaller's findOne, searchAll's find) are typed and not counted; the counted one stays with probeRecord.
    • System-context census (seat condition 2): identical at both ends (149 elevation read sites in 77 files), no file-count move.
    • Tenant census, check-adr-symbol-anchors, check-platform-checklist (the protocol.ts#searchAll anchors resolve on the method shell, which stays) and spec liveness (object.json cites protocol.ts#searchAll; its key-mention check passes on the stay-behind docblock): identical output at both ends. The blanking check before scope C found no anchor that resolves only inside the moved bodies (seat condition 4).
    • check:adr-anchors decision letters, exact: 1,954 → 1,949 at 798d480269 → head. The 5 that leave are letter citations inside moved code (ADR-0110 D3 ×2, ADR-0079 D3, ADR-0131 D6, ADR-0090 D2); protocol.ts's anchor entry governs ADR-0005/0029/0087/0119/0126 and none of its paragraphs describes these bodies, so the new module gets no entry and those citations leave the anchored surface unedited.
    • protocol.bracketed-refusal-opener-absence.test.ts PRODUCERS: no new Error( site moves (protocol.ts 87 → 87), so no row is added.
    • scripts/adr-anchors/, docs/qa/platform-checklist/**: not edited.
    • Size: +796 / −603 over 3 files (measured in the trial), under the 3,000-changed-line bar.

    ⛔ Nothing else changes: no moved body or declaration is edited; the only stay-behind edits are the one export keyword, the narrowed import lists and the stub bodies, plus the one pin row above; no ADR or docs/** text is edited; no new gate. One PR, skip-changeset, Part of #25467.

    Proof the PR carries, as cuts 1–3: AST leaf-token identity of every moved body and declaration (with a negative control), the declaration reader table, the readAsCaller / searchAll token identity and host Picks (seat condition 3), .d.ts block per ruling 6348891160 measured last on the final layout (raw and normalised sha256 base/head, normaliser, raw diff, positive control), ESM/CJS export lists, the metadata-protocol suite at base and head compared per test, dispatch-gates --commands all run with exits and --ran, and the hand gates at both ends.

  10. objectstack-fleet commented on Oct 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed cut 4 (record reads) · domain:services seat 1 (seat post #6021) · os-sales · session_016g7nYP9wdNx1GDa5XDr7Uy · 2026-10-24T03:39Z

    reading value
    PR #25589 MERGED through the queue (ACCEPT 6379127763), head 034fbb27f8
    origin/main carries ba6912c1ad

    State: the card stays open and dispatched (Part of). On the merged protocol.ts, the card thread either claims the next cut afresh or posts the series' final report. probeRecord (erasure baseline) and getMetaItemCached (the #9157 pin) stay.


    Generated by Claude Code

  11. objectstack-fleet commented on Oct 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: card thread · domain:server (former domain:engine surface) · for domain:services seat 1 (seat post #6021, project run by the Sales account; 由Sales账户的项目负责) · p2 · series card, cut 5 (one PR; cuts strictly serial; cuts 1–4 landed as #25494 bf5855b5bc, #25518 b2411c001d, #25538 798d480269, #25589 ba6912c1ad) · 2026-10-24T04:11Z
    Session: session_01J8pUyVs5eas1AjMdReJM7C
    Account: os-sales (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-uasfag (the harness-pinned branch for this session, restarted from origin/main ba6912c1ad after cut 4 merged; it names no issue, so this claim is the identity record)
    Worktree: objectstack-wt (a linked worktree in this session's container)
    Domain: domain:server
    Seat: domain:services#1 (seat post #6021; scope agreed with the seat before this claim, with its two pre-claim conditions answered below; the PR goes back to that seat for ACCEPT)
    Ruling: #24586 letter A (6270097840), restart read in 6291735609. The series' .d.ts bar is ruling 6348891160 (sorted-union identity; raw identity reported when it holds).
    Container & model: M, mode:thread, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card (a [maintainer] refactor card).
    Thread-read: none
    Serial constraints cleared: none of the 9 open PRs touches packages/metadata-protocol/src/protocol.ts or protocol.bracketed-refusal-opener-absence.test.ts (each PR's diff against its merge base read in this act). origin/main (now a57643d3de) has not touched packages/metadata-protocol since ba6912c1ad. Re-measured again before pr_create with git merge-tree; a new open PR on these files means this cut yields. A release freeze is in force (Sales, 03:57Z): the PR stays a draft and is not readied, armed or queued until the coordinator says merges resume.

    File surface (read on origin/main ba6912c1ad, where protocol.ts is 30,718 lines):

    Cut 5 = the lock gate and the optimistic-concurrency write addresses. Sixteen PRIVATE ObjectStackProtocolImplementation methods move unedited into a new module, packages/metadata-protocol/src/protocol-lock-version-gates.ts (host LockVersionGateHost), in the shape cuts 1–4 used (#23050 shape B). 278 body lines, 122 of them from the last 30 days:

    • getEffectiveLock :17113, readLockGateOverlayLayer :17150, recordMetadataAudit :17259, lockWriteRefusal :17338, assertLockAllowsWrite :17396, assertLockAllowsDelete :17416;
    • storedHashDigest :17520, receiptVersion :17532, storedHeadAt :17559, readVersionToken :17598;
    • packagelessReadAddress :17635, strictDraftReadAddress :17661, packagelessDraftAddress :17798;
    • storedParentForToken :17839, metadataConflictRefusal :17879, recordPendingDenialAudit :17966.
    • Members read, measured by AST: the field engine (a getter) and the methods artifactLockLayerAt, getEffectiveLock, getOverlayRepo, lockWriteRefusal, overlayLockLayerAt, packagelessAddress, packagelessDraftAddress, readLockGateOverlayLayer, receiptVersion, recordMetadataAudit, rethrowUnlessMetadataStoreUnprovisioned, storedHashDigest, storedHeadAt (late-bound closures). No field is assigned; the host carries no elevation member.

    Stay in the class (between or beside the moved methods):

    • recordOptimisticConflictAudit and the static optimisticConflictAuditEntry: the first reads a private static (TS2341 from a module function; ruling 6364006498 precedent).
    • packagelessAddress, narrowed out during the trial: scripts/check-durability-degradation-log-level.mjs's read-seam rule follows its findEnvironmentRows read and the four callers that guard it inside protocol.ts (applyObjectRegistryMutation, deleteMetaItem, deletePackage, loadMetaFromDb). Moved, the census drops from 83 read seams to 79; kept, the seam list is identical at both ends.

    Module-level declarations, each measured by an AST reader walk over all of protocol.ts (transitive closure over the moved set):

    • Move with the bodies, byte-identical, unexported (no reader outside the moved code; one docblock each): ErrorWithPendingAudit :6192 (type) and InboundVersionConflictError :3679 (class; also named in one stub docblock's {@link} prose, which stays).
    • Stay and gain export in place: canonicalMetaType :417 (← canonicalizeMetaRequestType, governServedItem, stripServedSystemColumns, bundleMemberOf) and MetadataAuditEntry :6164 (← withPendingAudit, optimisticConflictAuditEntry). src/index.ts names its exports, so neither is published.

    Seat's pre-claim conditions, measured on the trial build:

    1. .d.ts (ruling 6348891160), base ba6912c1ad (deps built with turbo run build --filter='@objectstack/metadata-protocol^...') vs the trial head: dist/index.d.ts and dist/index.d.cts raw 25da084d43455d12… at both ends (770,690 bytes), normalised ff7d6892b9f1161d… at both ends. Raw identity: the moved class and type print nowhere new, and canonicalMetaType's docblock does not splice onto a neighbour. Re-measured last on the final layout in the PR.
    2. check-governed-merges --branch on the trial file list (3 paths): NOT governed, 968 changed lines (+674 / −294).

    Readers (measured in the trial; the PR reports each base vs head):

    • protocol.bracketed-refusal-opener-absence.test.ts PRODUCERS: 4 new Error( sites move (protocol.ts 87 → 83 against its floor 5); the new module is listed with its measured floor, 'protocol-lock-version-gates.ts': 4, as cut 3 listed its module.
    • check:adr-anchors decision letters, exact: 1,883 → 1,882. The one that leaves is an ADR-0110 D3 comment citation in readLockGateOverlayLayer; no paragraph of protocol.ts's anchor entry describes these bodies, so no new entry.
    • Identical output at both ends: check-adr-symbol-anchors, check-platform-checklist, check-system-context-census, check-tenant-audit-census, check-query-options-erasure-ratchet, spec check-liveness, check-durability-degradation-log-level (with packagelessAddress kept), core row-serving-door-exposure.pin + second-object-read-exposure.pin (7/7). check-engine-double-contract differs only in the line numbers of the updateData/deleteData seams and productionFiles +1 (the new file).
    • metadata-protocol suite: 21,489 tests at both ends, 0 per-test differences. Cross-package path readers (objectql core-boundary.ratchet + protocol-publish-canonical-fold, spec liveness evidence + allow-org-override-absence, client/rest discovery-double-retired-key) pass.

    ⛔ Nothing else changes: no moved body or declaration is edited; the only stay-behind edits are the two export keywords, the stub bodies and the one import of the new module, plus the one PRODUCERS row; no ADR or docs/** text is edited; no new gate. One PR, skip-changeset, Part of #25467.

    Proof the PR carries, as cuts 1–4: AST leaf-token identity of every moved body and declaration (trial: 2,139 tokens, 0 differ, with a negative control), the declaration reader table, the .d.ts block measured last, ESM/CJS export lists, the suite at base and head compared per test, dispatch-gates --commands all run with exits and --ran, and the hand gates at both ends.

  12. objectstack-fleet commented on Oct 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: card thread · domain:server (former domain:engine surface) · for domain:services seat 1 (seat post #6021, project run by the Sales account; 由Sales账户的项目负责) · p2 · series card, cut 6 (one PR; cuts strictly serial; cuts 1–5 landed as #25494 bf5855b5bc, #25518 b2411c001d, #25538 798d480269, #25589 ba6912c1ad, #25601 60d8fd2ea6) · 2026-10-24T10:35Z
    Session: session_01J8pUyVs5eas1AjMdReJM7C
    Account: os-sales (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-uasfag (the harness-pinned branch for this session, restarted from origin/main 60d8fd2ea6 after cut 5 merged; it names no issue, so this claim is the identity record)
    Worktree: objectstack-wt (a linked worktree in this session's container)
    Domain: domain:server
    Seat: domain:services#1 (seat post #6021; scope agreed with the seat before this claim, as in-hand series work under Sales's 08:24Z word that this card continues to merge; the PR goes back to that seat for ACCEPT)
    Ruling: #24586 letter A (6270097840), restart read in 6291735609. The series' .d.ts bar is ruling 6348891160 (sorted-union identity; raw identity reported when it holds).
    Container & model: M, mode:thread, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card (a [maintainer] refactor card).
    Thread-read: none
    Serial constraints cleared: none of the 11 open PRs touches packages/metadata-protocol/src/protocol.ts, the new module or protocol.bracketed-refusal-opener-absence.test.ts (each PR's diff against its merge base read in this act), and git merge-tree of the cut head with each of them and with main 7265b33e77 is clean. origin/main has not touched protocol.ts since 60d8fd2ea6 (the three commits since touch only build-probes.ts and its test in this package). Re-measured again before pr_create; a new open PR on these files means this cut yields.

    File surface (read on origin/main 60d8fd2ea6, where protocol.ts is 30,548 lines):

    Cut 6 = the save door's refusals. Nine PRIVATE ObjectStackProtocolImplementation methods, one contiguous run of the class, move unedited into a new module, packages/metadata-protocol/src/protocol-save-door-refusals.ts (host SaveDoorRefusalHost), in the shape cuts 1–5 used (#23050 shape B):

    • refuseUngrammaticalMetaItemName :19858;
    • defaultRecordPageSaveRefusal :20040;
    • externalBindingSaveRefusal :20155, externalBindingDatasourceDefinition :20197, objectsBoundExternallyTo :20213;
    • anonymousElevatedFlowRefusal :20286;
    • authoredLockFamily :20603, saveWriteBinding :20666, objectNamespacePrefixViolation :20710.
    • Members read, measured by AST: the fields engine and getServicesRegistry (getters; the second is the constructor-supplied function field, passed as cut 4 passed it) and the methods artifactLockLayerAt, externalBindingDatasourceDefinition, getOverlayRepo, objectsBoundExternallyTo, overlayLockLayerAt, readActiveOverlayRows, readMetaItem, rethrowUnlessMetadataStoreUnprovisioned, storedOverlayEntries (late-bound closures). No field is assigned; no moved body names isSystem; the host carries no elevation member.

    Stay in the class (inside the run; narrowed out in the trial, before this claim, with the seat's agreement):

    • refuseUnmintableMetaType and metaTypeNamespaceExists: check-durability-degradation-log-level follows the chain saveMetaItem -> refuseUnmintableMetaType -> metaTypeNamespaceExists -> engine.findOne (its own table rows 3 and 5), and --list carries a metaTypeNamespaceExists read seam — the rule that kept packagelessAddress in cut 5.
    • viewContainerNameCollisionRefusal and its one helper overlaidShippedContainerViewNames: protocol.lookup-artifact-item-call-sites.test.ts reads protocol.ts and records this member's lookupArtifactItem( site.

    Module-level declarations, each measured by an AST reader walk over all of protocol.ts (transitive closure over the moved set):

    • Move with the bodies, byte-identical, unexported (no reader outside the moved code; one docblock each; none a class or a type): LOCK_FAMILY_KEYS, lockFamilyOf, sameLockFamily, withLockFamily, authoredLockFamilyRefusal. (item-lock.ts declares its own, separate LOCK_FAMILY_KEYS, untouched.)
    • Stay and gain export in place: MetadataIssueEntry (← permissionSetOwnerBindingRefusal, protectionBlockRefusal, publishBackfillRefusal, readPublishBackfillRequest), MetadataWriteFace (← specValidationFindings, destructiveChangeRemedy, flowSaveReplaysRetired, saveMetaItem), specValidationFindings (← saveMetaItem). overlaySchemaDeclaredKey is already exported. src/index.ts names its exports, so none is published.
    • Imports narrowed in protocol.ts (lost their last reader): METADATA_ITEM_NAME_PATTERN, defaultRecordPageObject, MetadataProtectionFields, validateObjectNamespacePrefix, and the whole @objectstack/spec/api value import, whose 3-line [ADR-0138 D2b] comment moves with it onto the new module's import.

    Anchor entry (seat note): scripts/adr-anchors/packages__metadata-protocol__src__protocol.ts.json names applyObjectRegistryMutation, loadMetaFromDb, removeObjectOverlay, the OBJECT_OVERLAY_PACKAGE_MISMATCH producer, batchData/transaction(, saveMetaItem/projectStorableViewBody/VIEW_CONSOLE_ROUND_TRIP_KEYS, hydrateOverlayIntoRegistry, readFlattenedMetaItems, isShippedFlowName/isStoredFlowEntryOfShippedName. None appears in the new module (0 hits); both OBJECT_OVERLAY_PACKAGE_MISMATCH producers stay in protocol.ts. No new entry.

    Re-measured on merged main 60d8fd2ea6 (the seat's order: d.ts, then letters, then governed):

    1. .d.ts (ruling 6348891160): deps rebuilt at base with turbo run build --filter='@objectstack/metadata-protocol^...', then dist/index.d.ts and dist/index.d.cts raw 25da084d43455d12… at base 60d8fd2ea6 and at head, both files. Raw identity. ESM and CJS export lists: 78 names, sorted-list hash e47ac7c7… on all four.
    2. check:adr-anchors decision letters, exact: 1,871 → 1,868 (85 → 85 anchored files). The three that leave: ADR-0138 D2b in the moved import comment, ADR-0138 D2b in anonymousElevatedFlowRefusal's body, ADR-0131 D6 in a moved body; none governs protocol.ts's entry (above).
    3. check-governed-merges --branch on the final 3-path list: NOT governed, 872 changed lines (+551 / −321).
    • Also measured at both ends: AST leaf tokens 2,966 compared, 0 differ (negative control fails); class 290 of 299 members byte-identical, 9 stubs keep docblock and signature less async; check-durability-degradation-log-level --list identical modulo line numbers (159 lines); check-adr-symbol-anchors, check-platform-checklist, both censuses, the erasure ratchet, spec liveness and the core pins (7/7) identical; check-engine-double-contract differs only in productionFiles +1; suite 21,490 → 21,491 tests, 0 per-test changes, the one added being the new PRODUCERS row ('protocol-save-door-refusals.ts': 5, 5 new Error( sites move); dispatch-gates --commands --changed 59 derived, 59 exit 0, --ran 59/59, 0 NOT-MEASURED.

    ⛔ Nothing else changes: no moved body or declaration is edited; the only stay-behind edits are the three export keywords, the stub bodies, the narrowed imports and the one import of the new module, plus the one PRODUCERS row; no ADR or docs/** text is edited; no new gate. One PR, skip-changeset, Part of #25467.

  13. objectstack-fleet commented on Oct 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed cut 5 (lock gate and OCC write addresses) · domain:services seat 1 (seat post #6021) · os-sales · session_016g7nYP9wdNx1GDa5XDr7Uy · 2026-10-24T11:08Z

    reading value
    PR #25601 MERGED through the queue at 2026-10-24T10:05Z (ACCEPT 6380213413, held through the 18.1 release freeze, readied and armed after merges resumed), head 11a1c9186b
    origin/main carries 60d8fd2ea6

    State: the card stays open and dispatched (Part of). The card thread claimed cut 6 afresh on the merged protocol.ts (claim 6383176261); it is PR #25623, under seat review.


    Generated by Claude Code

  14. objectstack-fleet commented on Oct 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed cut 6 (save-door refusals) · domain:services seat 1 (seat post #6021) · os-sales · session_016g7nYP9wdNx1GDa5XDr7Uy · 2026-10-24T11:51Z

    reading value
    PR #25623 MERGED through the queue (ACCEPT 6383538346), head 04c063af57
    origin/main carries 9d9a06ea38

    State: the card stays open and dispatched (Part of). On the merged protocol.ts, the card thread either claims the next cut afresh or posts the series' final report. The carry-forward list in #25623 still stands.


    Generated by Claude Code

  15. objectstack-fleet commented on Oct 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: card thread · domain:server (former domain:engine surface) · for domain:services seat 1 (seat post #6021, project run by the Sales account; 由Sales账户的项目负责) · p2 · series card, cut 7 (one PR; cuts strictly serial; cuts 1–6 landed as #25494 bf5855b5bc, #25518 b2411c001d, #25538 798d480269, #25589 ba6912c1ad, #25601 60d8fd2ea6, #25623 9d9a06ea38) · 2026-10-24T12:21Z
    Session: session_01J8pUyVs5eas1AjMdReJM7C
    Account: os-sales (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-uasfag (the harness-pinned branch for this session, restarted from origin/main 9d9a06ea38 after cut 6 merged; it names no issue, so this claim is the identity record)
    Worktree: objectstack-wt (a linked worktree in this session's container)
    Domain: domain:server
    Seat: domain:services#1 (seat post #6021; scope agreed with the seat before this claim, both of its calls answered below; the PR goes back to that seat for ACCEPT)
    Ruling: #24586 letter A (6270097840), restart read in 6291735609. The series' .d.ts bar is ruling 6348891160 (sorted-union identity; raw identity reported when it holds).
    Container & model: M, mode:thread, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card (a [maintainer] refactor card).
    Thread-read: none
    Serial constraints cleared: none of the 14 open PRs touches packages/metadata-protocol/src/protocol.ts, the new module or protocol.bracketed-refusal-opener-absence.test.ts (each PR's diff against its merge base read in this act), and git merge-tree of the cut head with each of them and with main ca80f05ec5 is clean. origin/main has not touched packages/metadata-protocol since 9d9a06ea38. Re-measured again before pr_create; a new open PR on these files means this cut yields.

    File surface (read on origin/main 9d9a06ea38, where protocol.ts is 30,312 lines):

    Cut 7 = package install and update. Four ObjectStackProtocolImplementation members, the tail of the class, move unedited into a new module, packages/metadata-protocol/src/protocol-package-install.ts (host PackageInstallHost), in the shape cuts 1–6 used (#23050 shape B):

    • installPackage :29853 and updatePackage :30106: PUBLIC with ANNOTATED return types, so not on the series' skip list of public members with inferred return types; the class keeps both signatures byte-identical.
    • packagePersistService :30137 and packageInstallUndo :30165: private.
    • Members read, measured by AST: the fields engine and getServicesRegistry (getters) and the methods packagePersistService and packageInstallUndo (late-bound closures). No field is assigned; the host carries no elevation member.

    Module-level declarations, each measured by an AST reader walk over all of protocol.ts:

    • Move with the bodies, byte-identical, unexported (read only by moved code; one docblock each): persistPackageManifest, snapshotPackageRow, restorePackageRow.
    • Stay and gain export in place: packagePersistFailureError (← deletePackage) and the interface PackagePersistService (← the packagePersistService stub's signature, which stays). src/index.ts names its exports, so neither is published.
    • Import moved: the PackageInstallManifestSchema import loses its last reader in protocol.ts; its 2-line [#24086] comment moves with it onto the new module's import.

    Seat's two calls (scope OK, 11:52Z):

    1. .d.ts: raw identity does NOT hold; sorted-union identity does. The only raw change is one union reordered inside getDiscovery's inferred return (environment: "production" | "development" | "sandbox" printed as "sandbox" | "production" | "development"), the offset-dependent printing cut 3 met. The PR reports the raw hashes, the full raw diff and a positive control that moves the normalised hash.
    2. Decision letters: ADR-0087 D1 (the protocol handshake) and ADR-0087 D2 (the authoring door runs no forward conversion) leave with installPackage's body. protocol.ts's entry paragraph for ADR-0087 anchors addendum 2026-08-01b (saveMetaItem's storable view body), not the install handshake, and protocol.ts keeps 26 ADR-0087 citations: no new entry (cut 13 rule, disclosed).

    Re-measured on merged main 9d9a06ea38 (the seat's order: d.ts, then letters, then governed):

    1. .d.ts (ruling 6348891160): deps rebuilt at base with turbo run build --filter='@objectstack/metadata-protocol^...'. Raw dist/index.d.ts and dist/index.d.cts: base 25da084d43455d12…, head 2d66df37f8e4614d… (770,690 bytes both sides). Normalised ff7d6892b9f1161d… at both ends, both files: sorted-union identity holds. The full raw diff is one line, getDiscovery's inferred return at :2407, environment: "production" | "development" | "sandbox"; → environment: "sandbox" | "production" | "development";. Positive control on a copy of the head index.d.ts (line 1361 private engine; made engine;): raw fee7168c…, normalised be016197…, both moved. ESM and CJS export lists: 78 names, e47ac7c7… on all four.
    2. check:adr-anchors decision letters, exact: 1,868 → 1,866 (85 → 85 anchored files): ADR-0087 D1 and ADR-0087 D2 leave with installPackage's body (above).
    3. check-governed-merges --branch on the final 3-path list: NOT governed, 766 changed lines (+427 / −339).
    • Also measured at both ends: AST leaf tokens 1,243 compared, 0 differ (negative control fails); class 295 of 299 members byte-identical, 4 stubs keep docblock and signature less async; check-durability-degradation-log-level --list identical modulo line numbers (159 lines); check-adr-symbol-anchors, check-platform-checklist, both censuses, the erasure ratchet, spec liveness and the core pins (7/7) identical; check-engine-double-contract differs only in productionFiles +1; suite 21,493 → 21,494 tests, 0 per-test changes, the one added being the new PRODUCERS row ('protocol-package-install.ts': 3); out-of-package readers pass (runtime packages domain and integration 190, objectql 61, client 7, rest 2, spec 44, cloud-connection 29); dispatch-gates --commands --changed 59 derived, 59 exit 0, --ran 59/59, 0 NOT-MEASURED.

    ⛔ Nothing else changes: no moved body or declaration is edited; the only stay-behind edits are the two export keywords, the stub bodies, the moved import and the one import of the new module, plus the one PRODUCERS row; no ADR or docs/** text is edited; no new gate. One PR, skip-changeset, Part of #25467.

  16. objectstack-fleet commented on Oct 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat pointer · domain:server seat 1 (seat post #6367) · os-sales · session_01JrXUZYyTV4i588KLZRxSvJ · ⛔ not a claim

    The maintainer voided domain:services seat 1 (#6021) in the Sales account's project and summoned domain:server seat 1 there; #6021 is now an archive of #6367. The reviewing seat for claim 6384152373 (card thread session_01J8pUyVs5eas1AjMdReJM7C) is therefore seat post #6367, same account. The claim, its session, branch and file surface are unchanged. ACCEPT and landing for cut 7 PR #25642 (ACCEPT already on the PR) and the cut 8 scope approved under it come from #6367.


    Generated by Claude Code

  17. objectstack-fleet commented on Oct 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed (cut 7, claim 6384152373) · domain:server seat 1 (seat post #6367) · session session_01JrXUZYyTV4i588KLZRxSvJ · 2026-10-24T15:01Z

    reading result
    PR #25642 object merged: true, merge commit 5aafc8237f, merged 2026-10-24T15:01:15Z through the merge queue
    origin/main 5aafc8237f is an ancestor of origin/main, single parent (squash)
    queue branch no gh-readonly-queue/main/* head for PR 25642 remains

    State: card stays open (Part of #25467). Cut 8, the scope agreed under the same claim, is next from the card thread on a branch from today's main. pm:dispatched stays.


    Generated by Claude Code

  18. objectstack-fleet commented on Oct 24, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: session session_01J8pUyVs5eas1AjMdReJM7C releases #25467 (last live claim 6384152373, cut 7) · because: the owning account (Sales, os-sales) is out of token budget and ordered a handoff · to: pm:queue, no assignee; the next claimant resumes from the branch below
    Provenance: who: Sales (os-sales, card owner) · said: 「那还是让他们尽快结束,然后移交。」 ("wrap it up as soon as possible, then hand it over") · where: the Sales project chat, relayed to this session by the project coordinator
    Resume-from: claude/project-thread-uasfag@65b6d71d38

    Handoff — protocol.ts split under ruling A (6270097840)

    Merged (cuts 1–7), all move-only, one PR per cut, each ACCEPTed by the server seat:

    cut PR new module
    1 #25494 batch
    2 #25518 diagnostics
    3 #25538 query validation
    4 #25589 record reads
    5 #25601 protocol-lock-version-gates.ts
    6 #25623 protocol-save-door-refusals.ts
    7 #25642 protocol-package-install.ts (merge 5aafc8237f)

    Cut 8: built and pushed, NOT claimed, NO PR.

    • Branch claude/project-thread-uasfag @ 65b6d71d38, one commit on main dc6c7ee738. protocol.ts is unchanged between 5aafc8237f and dc6c7ee738.
    • Scope, approved by the seat with option (A): restoredBodyDerivation, restoredBodyWriter, refuseRestoredBodyTheSaveDoorRefuses, runAuthoringGate, assertRuntimeAuthoringRules → new protocol-authoring-gate.ts (shape B host: getters engine, authoringChannel, authoringGates).
    • permissionSetOwnerBindingRefusal and runtimeHookWithoutBodyRefusal are exported in place. Imports in protocol.ts are narrowed.
    • Size: +424/−250 across 3 files; protocol.ts goes 30,010 → 29,821 lines.
    • No PRODUCERS row (the module has no new Error().
    • The only change outside the move is the [#8862] pin in protocol.object-registry-write-through-spelling.test.ts. It now reads protocol.ts plus the new module as one text and keeps the exact "one executable 'objects' literal" assertion.
    • Controls, run on the trial tree (same content):
      • blanked module fails with got +0;
      • an added 'objects' literal fails with got 2;
      • this.applyRegistryWriteThrough( sites in protocol.ts stay at 7.
    • Trial readings on the pre-merge cut 7 head:
      • .d.ts identical to cut 7;
      • durability --list, hand gates, engine-double and core pins are the same;
      • letters 1,866 → 1,865 (ADR-0090 D11, disclosure only, no entry);
      • not governed;
      • lint, rest owd and plugin-security tests pass.
    • Not done:
      • the full re-measure on merged main (.d.ts raw and normalised first, then letters, then governed, then all derived gates);
      • the Claim;
      • pr_create;
      • the os-dev-report.
        The seat's condition stands: re-measure .d.ts raw and normalised on merged main before claiming.

    Stays in the class, and why:

    • Public members whose return type is inferred: getDiscovery, getMetaTypes, getMetaItems(+ForExecution), getMetaItem(+ForExecution), getUiView, findData, getData, validateData, createData, cloneData, updateData, deleteData, saveMetaItem. Annotating them is a signature edit, which needs a ruling.
    • Durability read-seam containers and the in-file this. wrappers the checker follows: packagelessAddress, refuseUnmintableMetaType + metaTypeNamespaceExists. They can only move once the durability checker learns shape B.
    • probeRecord: per-file erasure baseline site.
    • getMetaItemCached and findReferencesToMeta: the Three read-side /meta verbs (history, audit, references) never reach canonicalizeMetaRequestType — they still derive their key from the MANIFEST map #9157 fold pin reads their bodies in protocol.ts.
    • viewContainerNameCollisionRefusal + overlaidShippedContainerViewNames: the lookup-artifact-item-call-sites pin.
    • reportPageRequiresAbsentAtLoad: spec liveness page.json (spec lane).
    • The 7 applyRegistryWriteThrough callers: the spelling pin counts them in protocol.ts.
    • Private-static readers.

    How to pick this up:

    1. Claim with Resume-from above. Re-check open PRs touching protocol.ts; none did at release.
    2. Rebase onto current main if protocol.ts moved, then re-measure in the order .d.ts raw and normalised (normaliser = sort "a" | "b" string-literal unions; ruling 6348891160), then letters, then governed. Then ESM/CJS export tables, the durability --list diff (strip [@:][0-9]+), hand gates, engine-double, and the package suite at both ends.
    3. Open the PR with the pin diff and both controls pasted, and hand it to the server seat for ACCEPT.
    4. Later cuts: the remaining free private members (~100, ~5k lines). Larger groups:
      • publish side effects / drafts / backfill planning;
      • tenant/packaged-base/origin-gated refusals;
      • the carry-forward credential group;
      • classifyObjectContribution;
      • servedLockState/declinesStoredRow;
      • registry materialize/strip.
        Keep each under 3,000 changed lines. Per cut: anchor entry scripts/adr-anchors/packages__metadata-protocol__src__protocol.ts.json (new entry only when a moved body is the mechanism an entry paragraph describes), PRODUCERS rows, and the cross-package pins that read protocol.ts by path.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:serverDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpm:queuepriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions