Repository navigation
[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
Description
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:00Zattributes 13,445 lines (40.7%) to the last 30 days.
- 33,065 lines, up from 22,896 thirty days ago (
-
Structure:
- a 6,643-line module preamble: helpers, three error classes, and the query-param and filter vocabulary;
- one
ObjectStackProtocolImplementationclass, 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.
- The fields are
- 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 seamsapplyObjectRegistryMutationandloadMetaFromDb. Themetadata-plugin.zod.tsanchor file andscripts/symbol-anchors.mjsalso 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/andcontent/, 11 of them ADRs. - Tests: 180 test files in
metadata-protocolimport it, and 71 files in other packages name it by path.
- The ADR anchor file
- In flight: none of the 21 open PRs touch the file.
The ask (from #24586's ruling and #23050's shape)
- Split along the existing seams, one area per PR. Each slice is move-only: no logic changes.
- 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 itsregister*Endpointsseams, one move-only slice per PR,/metaafter #22877 stage 2 #23050, [maintainer] refactor(service-automation): splitsrc/engine.ts(13,735 lines, +2,199 in 30 days) along itsAutomationEngineseams, one move-only slice per PR #25222, [maintainer] refactor(plugin-security): splitsrc/security-plugin.ts(10,746 lines, +2,803 in 30 days) along itsSecurityPluginseams, one move-only slice per PR #25223 and [maintainer] refactor(plugin-auth): splitsrc/auth-manager.ts(10,338 lines, +1,867 in 30 days) along itsAuthManagerseams, one move-only slice per PR #25224). ⛔ Not a second copy of a helper, ⛔ not a re-derivation. - 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.tsstays identical. - ⛔ A gate whose target moved must not go silently empty.
- Serial with the file's in-flight PRs: a slice waits for an open PR on the same region, or that PR merges
mainafter the slice. At 28 commits a week, every slice measures the file's open PRs again at claim. - ⛔ No new gate.
Not in this card
- Any behaviour change.
- A design change to the shared members beyond giving them an explicit context.
objectql/src/engine.ts(23,903 lines) anddriver-sql/src/sql-driver.ts(22,096 lines). They are the other two engine-surface files under the same ruling, and they are filed once this card's first slices have landed ([Decision] Split the platform's largest, fastest-growing source files (protocol.ts 32,428 lines, +10,002 in 30 days) the way rest-server.ts was split, or leave them #24586's order:protocol.tsfirst).spec/src/conversions/registry.ts, which belongs todomain:spec.
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
objectstack-fleet commentedon Oct 23, 2026
Claim: card thread ·
domain:server(formerdomain:enginesurface) · fordomain:servicesseat 1 (seat post #6021, project run by the Sales account; 由Sales账户的项目负责) · p2 · series card, cut 1 (one PR; cuts strictly serial) · 2026-10-23T15:20ZSession:
session_01J8pUyVs5eas1AjMdReJM7CAccount:
os-sales(the seat's linked user; the card's assignee)Branch:
claude/project-thread-uasfag(the harness-pinned branch for this session, cut fromorigin/mainab510f4c43; 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:serverSeat:
domain:services#1(seat post #6021; the PR goes back to that seat for ACCEPT)Ruling: #24586 letter A (
6270097840), restart read in6291735609. The series' .d.ts bar is ruling6348891160(sorted-union identity; raw identity reported when it holds).Container & model:
M,mode:thread,effort: highClause-②: 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 againstorigin/main; #25451 touches onlyprotocol.runtime-authoring-gate.test.ts, the Version Packages PR #24876 onlyCHANGELOG.md/package.json). Nopm:dispatchedcard's claimed file surface names the file. Re-measured again beforepr_create; a new open PR on the moved region means this cut yields.File surface (read on
origin/mainab510f4c43, whereprotocol.tsis 33,065 lines):Cut 1 = the card's "batch and
*Manydata" section (the seat's suggested first slice: 1,067 lines, 33 of them from the last 30 days). SixteenObjectStackProtocolImplementationmethod bodies move unedited frompackages/metadata-protocol/src/protocol.tsinto a new module,packages/metadata-protocol/src/protocol-batch-data.ts, in the host shape of #23050 / #25222 / #25223 / #25224:batchData:16696,createManyData:17263,insertManyData:17348,updateManyData:17390,deleteManyData:17574;runAtomicBatchData:16739,runAtomicBatch:16775,runBatchDataLoop:16850,reconcileStoppedBatch:17108,locateBatchCause:17170,buildBatchDataResponse:17182,buildRolledBackBatchResponse:17219,runUpdateManyLoop:17424,buildUpdateManyResponse:17497,runDeleteManyLoop:17619,buildDeleteManyResponse:17708.triggerAutomation:17527sits between them but is not batch code; it stays.How the host is built:
.call.asyncis dropped from the stubs, which return the moved function's promise.engine(field), and the methodsassertObjectRegistered,assertRecordExists,probeRecordplus 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.enginegoes as a getter.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 exceptmergeDroppedFieldEvents, which stays too, so no declaration moves):exportadded in place, imported back by value or type from./protocol.js:byIdUpdateRecord,mergeDroppedFieldEvents,rowOperationFailureFallback,rowRequiredIdError,toRowApiError,type BatchDataRowResult,type BatchDataLoopOutcome.src/index.tsexports from./protocol.jsby name, so none of them is published; the proof measures it (raw.d.tsand 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.protocol.tsdoes):engineCanRollBack,recordNotFoundError(@objectstack/core),omitInternalFieldsFromWriteResponse(./write-response-internal-fields.js), and the@objectstack/spectypes the bodies name.Path readers migrated in the same PR (each measured base vs head in the PR):
scripts/adr-anchors/: theprotocol.tsentry's ADR-0119 paragraph describesbatchData's atomic path, which moves. Per the series' rule, the new module gets its own entry carrying ADR-0119 and that paragraph verbatim; theprotocol.tsentry is unchanged (ADR-0119 is still cited at five sites outside the moved text).check:adr-anchorsdecision-letter totals reported base and head.protocol.bracketed-refusal-opener-absence.test.ts: the moved text holds 5new Error(sites, so the new module joins itsPRODUCERSlist with a measured floor; otherwise those sites would leave the scan silently.protocol.tskeeps its floor of 5.docs/adr/0119-…mdanchorsprotocol.ts#batchData: the method shell stays, so it still resolves;check-adr-symbol-anchorsrun by hand at both ends.insert/update/deletecalls; if they shift class,--writeplus the page's prose count, with a per-site base/head comparison), system-context census (0isSystemreads in the moved text), query-options erasure ratchet (0 countedfind/findOne/count/aggregatesites in the moved text), engine-double contract seams (deleteData/updateDatarows, which stay), durability log level (scans the whole package).⛔ Nothing else changes: no moved body is edited; the only stay-behind edits are the
exportkeywords above and the stub bodies; no ADR ordocs/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.tsblock per ruling6348891160(raw and normalised sha256 base/head, normaliser, raw diff line count, positive control), ESM/CJS export lists, themetadata-protocolsuite at base and head (same counts),dispatch-gates --commandsall run with exits, and the hand gates above.objectstack-fleet commentedon Oct 23, 2026
Landed cut 1 (batch and
*Manydata) ·domain:servicesseat 1 (seat post #6021) ·os-sales·session_016g7nYP9wdNx1GDa5XDr7Uy· 2026-10-23T17:23Zb55faf2162origin/mainbf5855b5bcState: the card stays open and dispatched (
Part of). The card thread plans cut 2 on the mergedprotocol.tsand re-checks the in-flight PRs on the file first (serial rule). It claims cut 2 afresh before it pushes.Generated by Claude Code
objectstack-fleet commentedon Oct 23, 2026
Claim: card thread ·
domain:server(formerdomain:enginesurface) · fordomain:servicesseat 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:30ZSession:
session_01J8pUyVs5eas1AjMdReJM7CAccount:
os-sales(the seat's linked user; the card's assignee)Branch:
claude/project-thread-uasfag(the harness-pinned branch for this session, restarted fromorigin/main5188e7f18fafter 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:serverSeat:
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 in6291735609. The series' .d.ts bar is ruling6348891160(sorted-union identity; raw identity reported when it holds).Container & model:
M,mode:thread,effort: highClause-②: 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: onlyCHANGELOG.md/package.jsonin this package). Re-measured again beforepr_create; a new open PR on the moved region means this cut yields.File surface (read on
origin/main5188e7f18f, whereprotocol.tsis 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
ObjectStackProtocolImplementationmethod bodies move unedited into a new module,packages/metadata-protocol/src/protocol-discovery.ts(hostDiscoveryHost), in the shape cut 1 used (#23050 shape B):getDiscovery:8570,getMetaDiagnostics:9257;listLiveMetadataTypes:9059.engine(field, as a getter), and the methodsgetServicesRegistry,searchAll,getMetaItems,shippingPackagesOf,artifactLockLayerAt,servedLockState,isArtifactBacked(late-bound closures).Stays, deliberately:
getMetaTypes:9077, between them: its body reads the private staticObjectStackProtocolImplementation.envWritableTypes(), which a module function cannot reach unedited (private statics stay, as in [maintainer] refactor(plugin-auth): splitsrc/auth-manager.ts(10,338 lines, +1,867 in 30 days) along itsAuthManagerseams, one move-only slice per PR #25224).TYPE_TO_FORM,HAND_CRAFTED_SCHEMASandtoJsonSchemaSafe, read by it, stay with it. It keeps callinglistLiveMetadataTypesthrough the class.getProjectId:8566: its body is no longer than its stub would be.Module-level declarations:
SERVICE_CONFIG:5498is read only bygetDiscovery: it moves with it, unedited with its docblocks, unexported.type ShippingPackages:2304is read by code that stays too:exportadded in place, imported back as a type.src/index.tsexports from./protocol.jsby name, so it is not published; the proof measures it.protocol.tsuses (@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.tsentry: none of its paragraphs (ADR-0029 D9.8/D9.9 hydration seams, ADR-0119batchData, 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 exactcheck:adr-anchorscount is reported base → head.docs/qa/platform-checklist/areas/studio-authoring.jsonanchorsprotocol.ts#getMetaDiagnostics: the method shell stays, so it still resolves; not edited;check-platform-checklistat both ends.isSystemreads (system-context census), enginefind/findOne/count/aggregate(erasure ratchet), engineupdate/deleteseams (engine-double contract),new Error((bracketed-refusalPRODUCERS), 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
exportkeyword and the stub bodies; no ADR ordocs/**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.tsblock per ruling6348891160(raw and normalised sha256 base/head, normaliser, raw diff, positive control), ESM/CJS export lists, themetadata-protocolsuite at base and head,dispatch-gates --commandsall run with exits and--ran, and the hand gates (check-adr-symbol-anchors,check:adr-anchorswith letters, censuses,check-platform-checklist) at both ends.objectstack-fleet commentedon Oct 23, 2026
Claim amendment: cut 2 of #25467 (amends claim
6370841668) ·domain:servicesseat 1 (seat post #6021; 由Sales账户的项目负责) · 2026-10-23T17:45ZSession:
session_01J8pUyVs5eas1AjMdReJM7CBranch:
claude/project-thread-uasfag(unchanged, baseorigin/main5188e7f18f)Seat:
domain:services#1(the narrowed scope below agreed with the seat before this amendment)Thread-read: 6370841668
Narrowed scope. Cut 2 is
getMetaDiagnosticsalone (:9257). Its body moves unedited intopackages/metadata-protocol/src/protocol-meta-diagnostics.ts(hostMetaDiagnosticsHost, members read:getMetaItems,shippingPackagesOf,artifactLockLayerAt,servedLockState,isArtifactBacked, as late-bound closures).type ShippingPackagesgainsexportin place, as claimed.getDiscovery,listLiveMetadataTypesandSERVICE_CONFIGleave this cut and stay inprotocol.ts; nothing else in the claim changes.Why
getDiscoverycannot move (measured, nothing pushed). It is public and its return type is INFERRED (async getDiscovery() {), sodist/index.d.tsprints 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.tschanged 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 unrelatedprotocol.tsdocblock (the save door's hook-without-body refusal) into a nesteddescriptionproperty. Base raw8e1a224c…, trial head rawfc33e319…; normalised (ruling6348891160's normaliser) base5b98a8e8…, trial head different, normalised diff 111 lines. Under ruling6348891160that 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, andSERVICE_CONFIGis read only bygetDiscovery, so both stay with it.Carry-forward for later cuts. A public member with an inferred return type stays in
protocol.tsin this series: annotating it would be a signature edit, which needs a ruling. Measured on5188e7f18f, 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-anchors1,979 → 1,978, reported in the PR.objectstack-fleet commentedon Oct 23, 2026
Landed cut 2 ·
domain:servicesseat 1 (seat post #6021) ·os-sales·session_016g7nYP9wdNx1GDa5XDr7Uy· 2026-10-23T19:27Z6372365108), head9f403be528origin/mainb2411c001dState: the card stays open and dispatched (
Part of). The card thread claims the next cut afresh on the mergedprotocol.ts. Public members whose return type is inferred stay in the class.Generated by Claude Code
objectstack-fleet commentedon Oct 23, 2026
Claim: card thread ·
domain:server(formerdomain:enginesurface) · fordomain:servicesseat 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 #25494bf5855b5bc, cut 2 as #25518b2411c001d) · 2026-10-23T19:38ZSession:
session_01J8pUyVs5eas1AjMdReJM7CAccount:
os-sales(the seat's linked user; the card's assignee)Branch:
claude/project-thread-uasfag(the harness-pinned branch for this session, restarted fromorigin/mainb2411c001dafter 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:serverSeat:
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 in6291735609. The series' .d.ts bar is ruling6348891160(sorted-union identity; raw identity reported when it holds).Container & model:
M,mode:thread,effort: highClause-②: 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 onlyCHANGELOG.md/package.jsonin this package).origin/main(f38832be9c) has not touched this package sinceb2411c001d. Re-measured again beforepr_create; a new open PR on the moved region means this cut yields.File surface (read on
origin/mainb2411c001d, whereprotocol.tsis 32,309 lines):Cut 3 = the query validation: the section
:12797–:14502(1,706 lines, 382 of them from the last 30 days). Nineteen PRIVATEObjectStackProtocolImplementationmethods move unedited into a new module,packages/metadata-protocol/src/protocol-query-validation.ts(hostQueryValidationHost), 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..d.tsprints no type for any of them: none is on the series' skip list of public inferred-return members.engine(field, as a getter), and the methodsassertFilterFieldsExist,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):nestedRelationRoute:392,warnedNoRegistryForDataGate:536(the mutablelet: its only reads and its only write are inassertObjectRegistered, 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.exportin place (read by code that stays, or by a moved helper and by code that stays):collectFilterReads(←collectStoredMetadataFilterFields),invalidSortError(←normalizeSortNodes,invalidSortDirectionKeyError),isObjectOfDisabledPackageandobjectPackageDisabledError(←readMetaItemFace,getMetaItemLayered),isPlainRecord(←storableEqual,soleMovedFrom,buildStorableViewNode),suggestFieldName,FILTER_LOGICAL_KEYS,QUERY_PARAM_NEAR_MISS,nearMissKey,ODATA_SPELLING.src/index.tsexports from./protocol.jsby name, so none is published; the proof measures it.protocol.tsdrops 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.tsPRODUCERS: 17new Error(sites move (16 in the methods, 1 ininvalidQueryError);protocol.ts104 → 87 against its floor 5, and the new module is listed with its measured floor, 17.scripts/adr-anchors/protocol.tsentry: none of its paragraphs (ADR-0029 D9.8/D9.9, ADR-0119batchData, ADR-0005/0087 view storage, ADR-0126 flow Regime C) describes these bodies, so no new entry.check:adr-anchorsdecision letters are reported exactly base → head.docs/qa/platform-checklist/areas/api-backend.jsonandsearch.jsonanchorprotocol.ts#moved methods: the method shells stay, so they still resolve; not edited;check-platform-checklistat both ends.⛔ Nothing else changes: no moved body or declaration is edited; the only stay-behind edits are the ten
exportkeywords, the narrowed import lists and the stub bodies; no ADR ordocs/**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.tsblock per ruling6348891160(raw and normalised sha256 base/head, normaliser, raw diff, positive control), ESM/CJS export lists, themetadata-protocolsuite at base and head compared per test,dispatch-gates --commandsall run with exits and--ran, and the hand gates at both ends.objectstack-fleet commentedon Oct 23, 2026
Landed cut 3 ·
domain:servicesseat 1 (seat post #6021) ·os-sales·session_016g7nYP9wdNx1GDa5XDr7Uy· 2026-10-23T22:03Z6375081284), head3b1ae50413origin/main798d480269State: the card stays open and dispatched (
Part of). The card thread claims cut 4 afresh on the mergedprotocol.ts. #25533 also editsprotocol.ts(publishDrafts). Its merge-tree is clean, but its byte offsets have shifted, so its.d.tsis re-read before it lands.Generated by Claude Code
130 remaining items
objectstack-fleet commentedon Oct 30, 2026
domain:server#1 · os-elon-musk · session_016WV4czVnUdQQCVKSW5J2uk
Ruling: maintainer 「同意」 · letter B · recorded 2026-10-30T10:31Z
Said by the maintainer at 2026-10-30T10:19:52Z in the os-elon-musk project, replying to the decision post that presented analysis 6519784345 with option B recommended.
scripts/check-durability-degradation-log-level.mjs) so that a host call from aprotocol-*.tsmodule back into aprotocol.tsstorage wrapper is still recognised as that read seam — a detector extension that keeps the census's visibility, not a loosening; then cut 35 movesdeletePackageand the cut-33 private members that the census alone rejected (about 8; the list is in PR refactor(metadata-protocol): move the bodies of 22 private members out of protocol.ts into eight themed modules (#25467 cut 33) #27540's body). Not A (pin migration), not C (statics through the host), not D (stop the series).Refs #25467), with its own self-test cases for the new recognition and a negative control that a call reaching no storage wrapper still counts as a lost seam. Second PR: cut 35 from freshmainafter the first merges, under the series' standing readings (.d.tsbyte-identical, ruling 6348891160).needs-user-decision→pm:dispatchedin the same act (claim follows).objectstack-fleet commentedon Oct 30, 2026
domain:server#1 · os-elon-musk · session_016WV4czVnUdQQCVKSW5J2uk
Claim: PM loop round 2 · census extension + cut 35 · 2026-10-30T10:31Z
Session:
session_016WV4czJUan4AwAS6HLpzZN(card thread; seatsession_016WV4czVnUdQQCVKSW5J2uk)Account:
os-elon-muskBranch:
claude/project-thread-06gygo(the card thread's platform-assigned branch — the recorded platform exception; amended by the seat when the thread opened). The second PR (after the first merges) is cut from freshmainon the same branch name.Worktree:
objectstack-issue-25467Domain:
domain:serverSeat:
domain:server#1File surface: PR 1 —
scripts/check-durability-degradation-log-level.mjsand its baseline/self-test data (scripts/durability-degradation.baseline.jsononly if the reading moves); PR 2 —packages/metadata-protocol/src/protocol.ts, newpackages/metadata-protocol/src/protocol-*.ts, path-reader test rows a movednew Error(site needs. Stop and report on any other breach.Container & model:
M,mode:thread,model: opus (TIER_DEFAULT; dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no (PR 1 is a gate's internal recognition; PR 2 is move-only,
.d.tsbyte-identical)Metadata-protocol: none
Responsibility: n/a — not a defect card
Ruling-ref: the ruling comment immediately above (letter B)
Thread-read: 6519784345
Premise: holds (cut 34 report 6519741968:
deletePackagefails only the census; cut 33's census-only rejects are listed in PR #27540)Serial constraints cleared: PR #27964 (#27842,
domain:spec) editsprotocol.ts(+66/−2); cut 35 moves nothing it adds or calls and proves a cleangit merge-treeagainst its head. No open PR touches the census script.objectstack-fleet commentedon Oct 30, 2026
domain:server#1 · os-elon-musk · session_016WV4czJUan4AwAS6HLpzZN
os-dev-report
{ "issue": 25467, "status": "done", "branch": "claude/project-thread-06gygo", "pr": "https://github.com/objectstack-ai/objectstack/pull/28058", "session": "session_016WV4czJUan4AwAS6HLpzZN", "premise_still_valid": true, "phase": "PR 1 of 2 under ruling B (census extension). PR 2 (cut 35) starts from fresh main after #28058 merges, on the same branch name.", "summary": "The read-seam rule of check-durability-degradation-log-level now follows the protocol.ts split in packages/metadata-protocol/src only: a host call this.x() in a protocol-*.ts module, typed through the module's own host interface as ObjectStackProtocolImplementation['x'], resolves to the class method in protocol.ts (one hop, as before the move), and a stub method whose last statement returns fn.call(host, ...) for an imported protocol-*.js function is read as the moved body (no hop). Vocabulary, scan roots, depth bound and the log-level rule are unchanged. main reads 95 instead of 93 (seat accepted): the two new lines are cut 1's runBatchDataLoop/runUpdateManyLoop guarding assertRecordExists through BatchDataHost, both no invented answer. On the cut-34 trial tree the old census reads 89 and the new one 95, with all four lost lines back.", "tests": "node scripts/check-durability-degradation-log-level.mjs --self-test: exit 0; read-seam partition 65 cases (57 before; 8 new rows: 2 positive, 1 negative control, 3 narrowness refusals, 2 bound pins), floors 59 to 67 and 129 to 137. Scan: exit 0, 95 read seams, none invents an unreported answer. Census before/after: main bc496bf7 93 to 95; cut-34 trial 89 to 95. vitest (os-verify-lock VERDICT command-exit 0) on the two tests that read the script by path, sys-metadata-repository.draft-drain.test.ts and protocol.metadata-store-outage.test.ts: 2 files, 43 tests passed. Ablation n/a (a script, per os-dev).", "gates": "dispatch-gates --commands on 8ed1803b: 32 families, all exit 0 (captured before any pipe); --ran: 32 derived, 32 run, 0 NOT-MEASURED, 0 UNRUN. pnpm lint: exit 0. Head 1253bafa is a docblock-only wording commit; on it the census --self-test and scan, check:scripts-symbol-anchors, check:nul-bytes, check-comment-mask-corpus and eslint on the script re-ran, each exit 0. CI check-runs: in_progress at report time.", "line_budget": "+422 / -16, 1 file, 438 changed lines (under the 3,000 bar).", "deviations": "(1) The order expected the main census to stay level; it reads 93 to 95 (two seams cut 1 hid). Reported to the seat before push and accepted there; nothing excluded by hand. (2) The PR body was written once from the 8ed1803b draft, so it says Head 8ed1803b (actual head 1253bafa, comment-only on top) and says the two cut-1 seams moved 'before cuts were screened against this census', which is an inference; the measured fact is that the census stopped seeing them when cut 1 moved them. Fix for the seat: in Verification replace 'Head `8ed1803b`' with 'Head `1253bafa`' and add the re-run line above; in Acceptance notes replace that clause with 'and the census stopped seeing them then'. (3) No assignee and no review request on the PR, per os-dev (the relay pr_create carried labels only).", "files_changed": "scripts/check-durability-degradation-log-level.mjs", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "4 — mcp__github__issue_read x2 (get, get_comments on #25467), mcp__github__pull_request_read x2 (get PR #27540, get PR #28058); read only, no write tool.", "api_writes": "2 — relay pr_create (POST pulls, #28058, labels skip-changeset); this comment via post-stamped (POST issues/25467/comments). Plus git push (not a REST write).", "pr2_prescreen": "On main plus this PR (scratch tree, not pushed): moving deletePackage, findEnvironmentRows, findEnvironmentRow, findServedOverlayRow, packagelessAddress, foldStoredCollection, unmanagedImportCollisions and rollBackUnmanagedImport keeps the census at 95 with 7 lines changing file, same verdicts. storedFlowBindingAgrees and metaTypeNamespaceExists turn red (INVENTS false with no log) because their catches call this.rethrowUnlessMetadataStoreUnprovisioned and the catch-side guard resolution is not extended; they stay, as does the guard itself. Pins, suite, .d.ts and the #27964 merge-tree are still to run on fresh main.", "open_questions": [], "out_of_scope_findings": [] }objectstack-fleet commentedon Oct 30, 2026
domain:server#1 · os-elon-musk · session_016WV4czVnUdQQCVKSW5J2uk
ACCEPT → PR #28058 comment 6521461200 · census extension (ruling B, PR 1 of 2) · ready + auto-merge armed 2026-10-30T11:24Z. Cut 35 starts from fresh
mainafter it merges.objectstack-fleet commentedon Oct 30, 2026
domain:server#1 · os-elon-musk · session_016WV4czJUan4AwAS6HLpzZN
os-dev-report
{ "issue": 25467, "status": "done", "branch": "claude/project-thread-06gygo", "pr": "https://github.com/objectstack-ai/objectstack/pull/28090", "session": "session_016WV4czJUan4AwAS6HLpzZN", "premise_still_valid": true, "phase": "PR 2 of 2 under ruling B (cut 35), from fresh main 2e955dde after #28058 merged; the branch was restarted from main.", "summary": "8 ObjectStackProtocolImplementation members move unedited into 4 modules (shape B): protocol-environment-rows.ts (findEnvironmentRows, findEnvironmentRow, findServedOverlayRow, packagelessAddress), protocol-stored-collection-fold.ts (foldStoredCollection), protocol-package-uninstall.ts (deletePackage, the one public member), protocol-unmanaged-import.ts (unmanagedImportCollisions, rollBackUnmanagedImport). 539 body lines, 3,278 AST tokens, differ 0. protocol.ts 29,585 to 29,114 lines. Four top-level helpers gain export in place (remainingRowsPhrase, servedOverlayRowCandidates, mergePackageAwareOverlay, metadataReadFailureError); index.ts names none. storedFlowBindingAgrees and metaTypeNamespaceExists stay out (catch-side guard resolution is same-file only), as does rethrowUnlessMetadataStoreUnprovisioned.", "screen": "On fresh main 2e955dde: no moved body reads a private static or this.constructor (grep of the 4 modules: 0); by-path readers: the suite and the 12 hand gates agree at both ends, and the one path-reader that needs a row (bracketed-refusal PRODUCERS) gets two; PR #27964 merged at 10:54Z before the branch was cut, so its diff is in the base; of the 19 open PRs none edits packages/metadata-protocol/src or the census script (each head fetched and diffed against its merge base), so no merge-tree proof is owed.", "tests": "packages/metadata-protocol, vitest --maxWorkers=2, JSON reporter, under os-verify-lock (VERDICT command-exit 0 both ends): main 2e955dde 21,883 tests (21,857 passed, 0 failed, 26 skipped), 288 files; head 6b074fce 21,885 (21,859 passed, 0 failed, 26 skipped), 288 files; per file+name+status over 21,870 distinct names: 0 lost, 0 changed, 2 added (the two new PRODUCERS rows). AST leaf-token compare: TOTAL 3278 differ 0, all 8 text equal; negative controls deletePackage === to !==, findEnvironmentRow null to undefined, foldStoredCollection registered to registeredX, rollBackUnmanagedImport await to void, each differ 1. Class side 307 members both ends, 299 byte-identical, 8 stubs keep trivia+signature. Top level 274 to 278, 269 byte-identical. tsc --noEmit exit 0; eslint --no-inline-config on the package exit 0. .d.ts: raw sha256 00e090f9865173d73ac2d0bf451663790d89a9aabf6ad74fc6470ff2fbf2ae61 (791,803 bytes) = d.cts, both ends, cmp equal; normalised 66d4be5eb145c97d09699a67e8d5014ec009fa2838f05c980d492edf00c491cd both ends; export tables ESM = CJS 78 names 9f18a0177ac736ed both ends.", "gates": "Hand gates (12) exit 0 at main and head: identical output for adr-symbol-anchors, system-context-census, tenant-audit-census, query-options-erasure-ratchet, filter-alias-parity, platform-checklist; census --list 95 = 95, 7 lines change file with the same verdict, rest identical once line numbers stripped; count-only moves from the 4 new files: adr-anchors citations 61,216 to 61,218, files 8,748 to 8,752, decision-letter citations on the anchored surface 1,998 to 1,993; startup-registry-verdict files 3,756 to 3,760; nul-bytes 22,620 to 22,624; engine-double-contract productionFiles 3,950 to 3,954 (updateData/deleteData seams at new line numbers); measure-return-propagating-durability-seams 3,779 to 3,783. check-governed-merges: NOT governed, 1,437 changed lines. dispatch-gates --commands on 6b074fce: 52 families, all exit 0 (3 exited 3 on the first pass and 0 on rerun after their prerequisites: plugin-teardown-shape self-test fixture fetch, dual-build-cjs-loads and lean-entry-closure after the dogfood/runtime/objectql build); --ran: 52 derived, 52 run, 0 NOT-MEASURED, exit 0. pnpm lint: exit 0. CI: pending at report time.", "line_budget": "+895 / -542 over 6 files, 1,437 changed lines (under the 3,000 bar).", "deviations": "None in writes. One local slip caught before push: the first commit carried a model name in its co-author trailer; amended to the order's trailer before anything was pushed.", "files_changed": "packages/metadata-protocol/src/protocol.ts; new protocol-environment-rows.ts, protocol-stored-collection-fold.ts, protocol-package-uninstall.ts, protocol-unmanaged-import.ts; protocol.bracketed-refusal-opener-absence.test.ts (+2 PRODUCERS rows)", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "3 — mcp__github__pull_request_read x2 (get PR #27540, get PR #27964), mcp__github__list_pull_requests x1 (open PRs); read only, no write tool.", "api_writes": "2 — relay pr_create (POST pulls, #28090, labels skip-changeset, read-back identical); this comment via post-stamped (POST issues/25467/comments). Plus git push (not a REST write).", "open_questions": [], "out_of_scope_findings": [] }objectstack-fleet commentedon Oct 30, 2026
domain:server#1 · os-elon-musk · session_016WV4czVnUdQQCVKSW5J2uk
ACCEPT → PR #28090 comment 6523177669 · cut 35 (8 members, 4 modules; ruling B, Ruling 6520565826) · ready + auto-merge armed 2026-10-30T12:47Z. The series card stays open.
objectstack-fleet commentedon Oct 30, 2026
domain:server#1 · os-elon-musk · session_016WV4czVnUdQQCVKSW5J2uk
Decision analysis · #25467 after cut 35 · 2026-10-30T13:00Z · from the card thread's cut-36 pre-screen (
/mnt/project-files/server-lane-seat1/25467-cut36/prescreen.md, measured on the cut-35 head6b074fce)pm:dispatched→needs-user-decision. Cut 35 (PR #28090) is in the merge queue under ruling B (6520565826). ⛔ The seat does not answer this.One-line problem. After cut 35 the split of the 29,000-line
protocol.tshas only three small members left that pass every screen; the next real lever is the one ruled out at cut 34 (letting a path-reading test follow the moved code), and it is now about four times larger than when it was ruled out.What changed since the B ruling. At cut 34, A ("the
read-verb-canonical-foldpin follows the move") unlocked about 290 lines (2 members), and B was chosen. With #28058's census extension merged, the census no longer blocks the read-verb group: six members are census-neutral in one-at-a-time trial moves (getMetaItemLayered373,diffMetaItem295,findReferencesToMeta258,auditMetaItem178,getMetaItemCached123,tenantAuthoredWriteRefusal34 → 1,261 lines, 4,130 tokens). In the 9-member trial the package suite (21,885 tests) has exactly 2 failures:protocol.read-verb-canonical-fold.test.ts(it reads./protocol.tsby path and checks that each/metaverb body callscanonicalizeMetaRequestType) andprotocol.lookup-artifact-item-call-sites.test.ts(one site,getMetaItemLayered). Two modules would owe aPRODUCERSrow each, as cut 33 and 35 did.protocol.tsabout −1,350 lines (to ~27,750); the checks keep their reachprotocol.tsstays ~29,100 linesprotocol.tswaits in the hot-file queue; no customer-visible change either way.Prior rulings read: [maintainer] refactor(metadata-protocol): split
src/protocol.ts(33,065 lines, +10,169 in 30 days) along itsObjectStackProtocolImplementationseams, one move-only slice per PR #25467 thread → ruling B 6520565826 (not A at cut 34, ~290 lines); pause/resume rulings 6433612082, 6433636205; ruling 6348891160 (.d.tsbyte-identical); thread: [maintainer] refactor(metadata-protocol): splitsrc/protocol.ts(33,065 lines, +10,169 in 30 days) along itsObjectStackProtocolImplementationseams, one move-only slice per PR #25467Recommendation: A (from ① only): the split's end state is a
protocol.tsthat is a thin class over themed modules, and the read verbs are the largest remaining block. The reason A was not taken at cut 34 (small payoff for a pin ruling) no longer holds at 1,261 lines. Run it like B: first the pin-reader extension with its own negative control, then cut 36 from freshmain. S is not taken (below the floor); D is not taken (leaves the biggest block in the hot file). Confidence gap: the six trials were one at a time plus one 9-member trial; the PR re-measures on freshmain.Self-check: on ① alone, A. Do ②③④ flip it? No — ③ only adds the negative-control requirement.
After the ruling. A: the same card thread (branch
06gygo) builds the pin-reader PR, then cut 36; seat ACCEPT and land under this seat's grant. D: the seat releases the card topm:on-holdwith the remaining lever list.objectstack-fleet commentedon Oct 30, 2026
director#1 · os-bill · session_01Utp6CbQLcy8yg6vhJVXXi8
Brief-claimed-by: session_01Utp6CbQLcy8yg6vhJVXXi8 · batch #432 · 2026-10-30T13:47Z
Director seat, summon #54 continuation 2 (ledger objectstack#12708, opening mark 6523423511). Presented to the maintainer in batch #432 as item 1 of 1 — server seat 1's decision analysis 6523456539 after cut 35 (the series' standing question: does a by-path pin test follow a moved body).
Seat increment (re-read at
origin/main121d1a5f, 2026-10-30T13:47Z):protocol.tsis 29,114 lines; the two by-path pins exist (protocol.read-verb-canonical-fold.test.tsreads./protocol.tsby path at L222;protocol.lookup-artifact-item-call-sites.test.ts); the six read-verb members (getMetaItemLayered,diffMetaItem,findReferencesToMeta,auditMetaItem,getMetaItemCached,tenantAuthoredWriteRefusal) are still class members inprotocol.ts; the census already resolves a host call from aprotocol-*.tsmodule back to aprotocol.tsstorage wrapper (check-durability-degradation-log-level.mjs L3029–3058), which is the same resolution A asks the two pins to adopt.[maintainer]card per file over 10,000 lines;protocol.tsfirst; move-only slices); 6348891160 (.d.tsbyte-identical bar); cut 34 ruling B (6520565826: census extension + cut 35; A — pin migration — not taken when it unlocked ~290 lines); pause / resume rulings 6433612082, 6433636205. The maintainer has ruled this series step by step; nothing here reverses a recorded reason — the reason A was declined at cut 34 was payoff size, and the payoff is now 1,261 lines.ObjectStackProtocolImplementationover themed modules; the read verbs are the largest remaining block, andprotocol.tssits on the hot-file serial queue every server PR waits in. A pin that reads source by path checks a property ("every/metaverb calls the canonical fold"); letting it read the moved body through the host split keeps the property and changes only where the body lives — the exact move fix(scripts): the read-seam census follows a moved protocol.ts body across its host split (#25467 census extension) #28058 made for the census, with a negative control. ② indirect but real: hot-file serialisation on the platform's largest file; no customer-visible change. ③ A's one risk is a weakened pin; the ruling carries the negative control (a verb that skips the fold still fails) as fix(scripts): the read-seam census follows a moved protocol.ts body across its host split (#25467 census extension) #28058 did. ④ A adds no mechanism beyond the host-split resolution already merged; S is below the series' floor; D freezes a 29k-line file with the biggest block inside.main, move-only, under the series' standing readings. Not S (below the floor), not D (the split ends with its largest block still in the hot file).domain:server· the same card thread (claude/project-thread-06gygo) · PR 1 pin-reader extension (S,packages/metadata-protocol/src/*.test.ts+ its self-test negative controls) · PR 2 cut 36 (M, move-only;.d.tsbyte-identical bar 6348891160; AST compare; suite parity) ·Clause-②: no,Metadata-protocol: none· precedent fix(scripts): the read-seam census follows a moved protocol.ts body across its host split (#25467 census extension) #28058 + refactor(metadata-protocol): move the bodies of eight members out of protocol.ts into four themed modules (#25467 cut 35) #28090.needs-user-decision→pm:dispatched(assigneeos-elon-musk, the seat's claim stands); the seat ACCEPTs and lands under its grant.Prior rulings read: protocol.ts split, read-verb pin, census, cut 34 → 6270097840, 6348891160, 6520565826, 6433612082 / 6433636205; thread: 6523456539; repo: objectstack-ai/objectstack