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
director#1 · os-bill · session_01Utp6CbQLcy8yg6vhJVXXi8
Ruled: 6537947529 · letter A folded into E (#28142 ruling 6537939895) · 2026-10-31T02:49Z
Ruling-ref: 6537947529
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.
- 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
151 remaining items
objectstack-fleet commentedon Oct 31, 2026
domain:server#4 · os-zhuang · session_01QUs3BtyH9zgxKzYrJiH18J
Claim: PM loop round 1 · step E0 only
Session:
session_01QUs3BtyH9zgxKzYrJiH18JAccount:
os-zhuangBranch:
claude/project-thread-6aibsn(the card thread's platform-assigned push branch, the measured platform exception to the protocol branch shape)Worktree:
objectstack-issue-25467Domain:
domain:serverSeat:
domain:server#4Ruling-ref: 6537939895 (the maintainer's E on #28142, folded here in 6537947529)
File surface:
packages/metadata-protocol/src/protocol.ts(the preamble only, everything aboveexport class ObjectStackProtocolImplementation), new themed modules underpackages/metadata-protocol/src/, the by-path pins and the read-seam census only where they read a preamble symbol, and a new.changeset/25467-e0-*.md(stop on breach; explain in the report)Container & model:
L,mode:thread,model: default judgment tier (dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
metadata-protocol's own source layout | none: a move-only cut has no other producer | every PR touching protocol.ts, which sits on the lane's hot-file serial queueThread-read: 6539885713
Premise: holds; the dev re-measures the preamble on current main before the PR, as the ruling requires
Scope: E0 only, move-only, no host object; the
.d.tsbar of ruling 6348891160 (same export list, identity after sorting union members); tsc, the full package suite, the census and the pins green; move-only shown by tool. E1 and E2 are later dispatches under the same Ruling-ref.Serial constraints cleared: PR #28393 (#28355,
protocol.ts) is in the merge queue; the dev starts from main after it merges and merges main again before the PR. No other in-flight claim of this seat namesprotocol.ts. Size: the PR will pass 3000 lines, so it lands through the maintainer-approval endgame.Taken at 2026-10-31T11:17Z: p2, released to
pm:queuein 6539885713 for the nextdomain:serverseat; the oldest unclaimed p2 by the lane's full order.objectstack-fleet commentedon Oct 31, 2026
domain:server#4 · os-zhuang · session_01QUs3BsJcwnzs3NHfAM4PMV
os-dev-report
{ "issue": 25467, "status": "needs_decision", "branch": "claude/project-thread-6aibsn", "pr": null, "session": "session_01QUs3BsJcwnzs3NHfAM4PMV (card thread, claim 6542693686)", "premise_still_valid": true, "summary": "E0 is built and stopped at the .d.ts bar, as ruling 6348891160 item 1 requires. On base b9b22b9b4 (PR #28393 merged) a tool moved every top-level statement above `export class ObjectStackProtocolImplementation` (180 top-level statements, including the four door request types #28393 added) into 22 themed `protocol-*.ts` modules; protocol.ts goes from 29,255 to 23,237 lines and re-exports what it exported. The published index.d.ts keeps the same declaration set, the same declaration order and the same ESM/CJS export list, but 16 raw lines differ in three kinds the ruling's string-union normaliser does not cover: (a) 10 blank lines, one per rolled-up module boundary among the published declarations (rollup separates modules with a blank line, so any move of a published declaration out of protocol.ts adds at least one); (b) 1 line pair, the `@objectstack/spec/api` import brace list with `MetadataAuthoringSurface, MetadataAuthoringClient` moved to the front (they now arrive through the door-request module, rendered before protocol.ts); (c) 2 line pairs, the mixed number/string literal union `columns?:` inside `getMetaTypes()`'s inferred return type printed in another member order (literal-type creation order, the 6348891160 mechanism, but the union mixes numbers and strings). A trial that kept every published preamble declaration (35, by closure) in protocol.ts still left 1 blank line and (c), so no move-only shape of E0 meets the bar as ruled. Nothing was widened, no changeset was added, no PR was opened. The trial head is pushed for the ruling: 4a35157e.", "tests": "head 4a35157e, worktree objectstack-issue-25467. Move-only by tool: every non-import top-level statement of base protocol.ts (187) appears verbatim, leading comments included, exactly once across head protocol.ts plus the 22 new modules; changed 0, surplus 0; the head adds only import/export-list statements (208) and a 6-line module header comment per module. Negative control: one operator changed in protocol-version-tokens.ts (hash = hash & hash to hash | hash) -> changed 1, surplus 1, exit 1; restored, git diff HEAD empty. tsc: `pnpm --filter @objectstack/metadata-protocol exec tsc --noEmit -p tsconfig.json` exit 0. Package suite under the lock: `vitest run --maxWorkers=2` VERDICT command-exit 1, Test Files 2 failed | 283 passed | 4 skipped (289), Tests 2 failed | 21870 passed | 26 skipped (21898). The 2 failures are the by-path pins E0 owes in the same PR because they read preamble symbols out of protocol.ts: protocol.lookup-artifact-item-call-sites.test.ts (regex for `function envelopePackageId` in protocol.ts) and protocol.read-verb-canonical-fold.test.ts (13 of 17 verbs found). Not migrated yet: stopped at the bar first.", "gates": "NOT MEASURED: dispatch-gates --commands, --ran, pnpm lint, census. reason: E0 stopped at the .d.ts bar before the gate sweep; nothing is proposed for merge. .d.ts block (dist/index.d.ts = dist/index.d.cts, same bytes each side): raw sha256 base 0d87b0e7ab35d799137d419b6b3809ee1af84fcc8e674c25f100c791dc8a65a3, head 9aa11aa4631076420b4ec38089c7277f5bd22af4f136da6c85f9a53039c3dc75; ruling normaliser (verbatim from 6348891160) base 71bb3a6903c316c5ae75d7cd8b66b307f6450c01b4d6674595fe4c3eca17278e, head b750436ab8b4bba6ee98678f4fc18c5fb45640e968964ebfbef0f8ece8782fbb (differ); raw diff 16 changed lines = 10 added blank + 1 import line pair + 2 union line pairs; export list line identical in both formats. Reading for option A, not a gate: a second normaliser (drop blank lines; sort the names inside each `import {...}` brace list; sort the members of each literal-union run, string or number) gives base 8c8c2b3f5bc2100b03de6cff00ec4affc17e1db9b111ad175b5f3c75c9c027e5 = head 8c8c2b3f5bc2100b03de6cff00ec4affc17e1db9b111ad175b5f3c75c9c027e5; positive control (head with the class's first `private engine;` made `engine;`) 3bb6820178f61effade3c3ae407af424700c943aefc016df6d37612562e4dba7, differs.", "dogfood_battery": "n/a: no `!` in a title and no (narrowing) arm; no PR", "mcp_calls": "4, reads only: issue_read x3 (#25467 get, #25467 comments, #28142 comments), pull_request_read x1 (#28393 get)", "api_writes": "1: this report comment (POST issues/25467/comments via the relay, post-stamped). Reads outside MCP: 3 unauthenticated REST GETs of issue comments (6348891160, 6542693686, #25467 comment page).", "open_questions": [ { "question": "E0 cannot keep dist/index.d.ts byte-identical after the ruling's string-union normaliser: moving the preamble adds blank lines between rolled-up modules, reorders one import brace list, and permutes one mixed number/string literal union. Which bar does E0 land under?", "options": [ "A: rule an E0 bar for this one move, report-only like 6348891160: same declaration set, same declaration order, same ESM/CJS export list, and a raw diff made only of (a) blank lines, (b) a permutation inside one import brace list, (c) a permutation of literal-union members, shown by the second normaliser's equal hashes plus its positive control. Then this thread migrates the two pins, runs the gates and lint, adds the dispatch's patch changeset and opens the draft PR (about 12,600 changed lines, maintainer approval). Effort: one more round in this thread.", "B: A, plus the four door request types (`SaveMetaItemRequest`..`DeleteMetaItemRequest`, added by #28393 after E's measurement) stay in protocol.ts, which removes kind (b). Kinds (a) and (c) still need the ruling. Effort: the same as A.", "C: skip E0; keep the preamble in protocol.ts and go on to E1 and E2, whose member stubs keep the published declarations where they are. Effort: none now; protocol.ts keeps its 6,018 preamble lines, and E2's cuts may still meet kind (c) at each cut." ], "recommendation": "A. 1) Long term: the move's evidence is a contract reading (declarations, order, visibility, exports), and A keeps every byte that carries meaning strict while naming three byte classes no consumer can observe. 2) Business pull: protocol.ts sits on the hot-file queue, and A removes 6,018 lines from it in one PR. 3) AI-error prevention: the tool proves the move verbatim (negative control red), and the second normaliser's positive control shows that a visibility change still fails. 4) No sprawl: no gate, no script, report-only. B costs the same and keeps 4 types behind; C defers the largest no-host block for nothing a consumer could observe. Axes: the four os-decision-facets the E and 6348891160 rulings use; the dispatch named none." } ], "out_of_scope_findings": [] }objectstack-fleet commentedon Oct 31, 2026
domain:server#4 · os-zhuang · session_01QUs3BtyH9zgxKzYrJiH18J
needs-user-decision· E0 用哪条.d.ts判据落地 · 2026-10-31T11:48Z · ⛔ 不是裁决一句话问题: 把
protocol.ts前言 6,018 行整体搬到 22 个模块后,对外发布的类型声明在含义上完全不变,但文件字节有 16 行不同(模块之间的空行、一条 import 花括号内的名字顺序、一个数字/字符串混合字面量联合的成员顺序)。按现行判据(6348891160,只容许字符串联合成员换序)这算"变了",开发线程按规定停手。背景: 卡线程报告 6542958324(试验 head
4a35157e,基于b9b22b9b4)。工具证明是纯搬移:187/187 条语句逐字出现一次,反向对照能变红;tsc绿;包测试只红 2 条,正是 E0 本应同 PR 迁移的两条按路径读前言的 pin。声明集合、声明顺序、ESM/CJS 导出名单都相同。保留全部 35 个对外声明不动的试验版仍剩 1 行空行和那个联合,所以任何纯搬移的 E0 都过不了现行判据。Governing text: 裁决 E(6537939895)"Member declarations stay on the class as stubs, so the
.d.tsbar (ruling 6348891160 …) holds";6348891160 的判据"identity after sorting string-literal union members, plus the same export list",其目的写明是"no private member becomes public or protected"。SKILL.md〈升级与决策〉"dev 的needs_decision一律呈人工…⛔ 不代答"。协议声明:Clause-②: no,Metadata-protocol: none,不改packages/spec。前提(带复核命令): 二号归一器(去空行、import 花括号内排序、字面量联合成员排序,字符串和数字都排)下 base 与 head 哈希相同
8c8c2b3f…;阳性对照(把类的第一个private engine;改成公开)哈希不同3bb68201…。复核:在4a35157e与b9b22b9b4各自构建@objectstack/metadata-protocol,对dist/index.d.ts跑报告里的二号归一器后比对 sha256。选项:
protocol.ts,少掉 import 那一类差异protocol.ts继续多背 6,018 行,E2 每刀仍可能遇到联合换序业务含义: A 相当于验收合同时只核条款,不核排版;B 是同样核法但少搬一页;C 是先不整理这一章。
四维(业务立场):
protocol.ts在车道热文件串行队列上,每个 server PR 都在付等待成本;A 一次搬走 6,018 行。只看①选 A;②③④ 是否翻转:否。疑属不升级类(验证策略),但按 SKILL.md 规定仍呈人工。
推荐:A。 B 代价相同却留下 4 个类型;C 拖后最大的一块而换不来任何客户可见的东西。盲区:二号归一器只在这一次构建上实测过,E2 各刀仍需各自报告原始与归一哈希。
裁后执行: 选 A 或 B,本席通知卡线程继续:迁两条 pin、全套门禁、changeset、开 draft PR;本席核对后请你批准合并。选 C,本席关掉 E0 这一步,按 E1 另派。
os-decision-facets
① 长远:证据落在声明/顺序/可见性/导出,排版字节不卡拆分
② 拉动:protocol.ts 热文件队列,每个 server PR 都在付
③ 防错:工具逐条证明+反向对照;阳性对照证明可见性变化仍失败
④ 不扩散:不加门禁不加脚本,只多一个报告读数
Prior rulings read:
.d.ts bar·6348891160·ruling E→ 3 hits (6348891160, 6537939895, 6537947529); ADR none; thread: noneobjectstack-fleet commentedon Oct 31, 2026
director#2 · os-tesla · session_01L9qibxdiybU8ehPKBroYE3
Ruling: batch #432 item 9 · letter A · maintainer 「同意」 2026-10-31T15:15Z
Director seat (decisions thread, 2026-10-31). Presented to the maintainer (his 「同意」 landed at 2026-10-31T15:10Z) as item 9 of batch #432 (the consolidated 待 Tesla 决裁清单 of 2026-10-31T14:40Z, recommendation A from the seat-4 letter 6542973320); the maintainer answered the whole batch, verbatim: 「同意」 = every item at its recommendation, so this card's letter is A.
What the ruling binds (letter A): E0 goes ahead with a new read-only
.d.tscriterion — the same declaration set, order and exports, allowing blank lines, import brace order and literal-union member order — implemented as normaliser 2 with a positive control, then the two pins and the gates migrate to it, and the draft PR (≈12,600 lines) comes to the maintainer for approval as a governed PR. Not taken: B (keeping #28393's four door types in protocol.ts), C (skipping E0 for E1/E2).Workload of the letter: as the seat-4 letter states it —
domain:serverseat 4, one move-only slice PR, Tier H by line count (maintainer approval).Execution: seat 4 (os-zhuang) picks the card up with
Ruling-ref:naming this comment; theRuled:body line and theneeds-user-decision→ working-state stroke are the seat's. Recorded here at 2026-10-31T15:15Z.objectstack-fleet commentedon Nov 1, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Triage: half-state ·
needs-user-decisionandpm:dispatchedtogether · 2026-11-01T17:04Z⛔ Not a claim. A knock to the assignee's seat (
os-zhuang,domain:server#4).pm:dispatchedcomes off. If the work is in flight,needs-user-decisioncomes off and the claim names the question it waits on. Please answer here.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#4 · os-zhuang · session_01QUs3BsJcwnzs3NHfAM4PMV
Release:
session_01QUs3BsJcwnzs3NHfAM4PMV(E0 card thread, claim 6542693686) · the maintainer's order 「你把卡片放回队列就行」 ·pm:queue, for the nextdomain:serverseat to run E0 under the A rulingResume-from: claude/project-thread-6aibsn@4a35157e
.d.tsnormaliser with a positive control (the reading block is in report 6542958324). B and C were not taken.4a35157e(baseb9b22b9b4) carries the move into 22 themed modules. Move-only proof: 187/187 statements verbatim.tscis green. Package suite: 2 red tests, both the by-path pins E0 owes (protocol.lookup-artifact-item-call-sites,protocol.read-verb-canonical-fold). No PR is open.main(the base has moved), then migrate the two pins, run dispatch-gates and lint, add the patch changeset, and open the draft PR. The PR is about 12,600 lines, so it needs maintainer approval.needs-user-decisionwithpm:dispatched): both labels come off,pm:queuegoes on, and the assignee is cleared.