Skip to content

refactor(service-automation): move the run-context and resume bodies into run-resume.ts (#25222 slice 6) - #25567

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-nirtwt
Oct 24, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-nirtwt

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Sales · project thread

Part of #25222
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6348891160

This is slice 6 of the engine.ts split, and its claim is comment 6377626691. The bodies of fifteen AutomationEngine methods move, unedited, into a new module, packages/services/service-automation/src/run-resume.ts:

  • resolveRunContext, seedRunGrants, resolveDecisionSegmentContext and expandDeclaredLookups, which resolve a run's context, grants and declared lookups;
  • resume, refuseGatedResume, refuseUndeclaredSuspension, loadSuspendedRun, loadSuspendedRunStrict and creditChildRun, which load, gate and resume a suspended run;
  • failSuspendedRun, settleUnresumableSuspension, cancelRun, cloneVariablesAtPause and failAncestors, which fail, settle or cancel a suspended run, along with its ancestors.

The change is move-only, and the card stays open for the later slices. The branch is claude/project-thread-nirtwt, which the harness pins for this session. It was restarted from main at 03243fc6 after slice 5 (#25551) merged. The branch name has no issue number, so the claim comment is the identity record.

Scope

  • The 33-site question. The ruling on the 33 this.FIELD.delete/insert/update( sites in 21 methods is still pending with Sales. This slice moves 0 of those sites, because none of the fifteen bodies holds one. check-tenant-audit-census and check-system-context-census give byte-identical output at base and head (see Readers).
  • Return types. Each of the fifteen methods declares its return type, including the two public ones, resume and cancelRun. So no public body with an inferred return type moves.
  • None of the bodies that must stay moves. The remaining-bodies table (comment 6376268510) marks these as stays:
    • for liveness, retryExecution and getConnectorDescriptors;
    • for private statics, resolveCanonicalDescriptor, resolveResumeAuthority and resolveEffectiveSuspension. refuseGatedResume and refuseUndeclaredSuspension call them through host closures, and they stay in the class;
    • for the startup-registry gate, knownNodeTypes, getUnknownNodeTypeAudit, sealNodeTypeVocabulary and warnUnknownNodeTypes.
  • Two more bodies stay: refuseInvalidScreenInput and buildSubflowResumeSignal.
    • The table put them in this group. But they read ENGINE_BUILT_SIGNAL and engineBuilt, and docs/adr/0019-approval-as-flow-node.md calls that symbol "module-private".
    • Moving them would mean exporting both names from engine.ts. The package's export map is . only and index.ts would re-export neither, so the symbol would stay out of reach outside the package. Even so, the ADR's line would no longer be true.
    • So they stay in the class, as the claim says, and the table's stays are now 11.
  • Size. 1,369 changed lines, under the 3,000-line bar: engine.ts +132 / -546, the new module +689, and the test 1 / 1.

What stays in engine.ts

  • Every moved method keeps its name, docblock, signature and position in the class, because tsup emits each member, private ones included, into the published .d.ts.

The shape (slices 1 to 5)

  • The host interface. RunResumeHost holds the 25 members these bodies read, each typed as the class member itself (AutomationEngine['m']), so a renamed member is a compile error. There is no cast, and no member becomes public or protected.

    • Each moved function types this as the Pick of RunResumeHost over exactly the members its own body reads, read off each body's AST in first-read order.
    • creditChildRun reads no member, so it is called directly, without a host.
  • Methods are passed as late-bound closures, (...a) => this.m(...a), so a spy or test double set on the instance is still the one called. There are 17 of them:

    • seedRunGrants, expandDeclaredLookups, refuseGatedResume, resumeInternal, resolveEffectiveSuspension and resolveSuspendedNodeType;
    • resolveResumeAuthority, resolveDeclaredResumeAuthority, resolveCanonicalDescriptor, loadSuspendedRunStrict and evictConsumedSuspension;
    • journalConsumedSuspension, forgetSuspendedRun, recordLog, claimAdvance, loadSuspendedRun and failSuspendedRun.
  • Four fields go through a getter, in slice 5's store form ([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 cut 1, PR refactor(plugin-security): move SecurityPlugin's leaf readers into security-plugin-object-inputs.ts (#25223 cut 1) #25290), because a method reassigns each. The write sites are engine.ts at this head:

    • store: setSuspendedRunStore (:2769), and the constructor (:2745);
    • userGrantsResolver: setUserGrantsResolver (:3988);
    • recordExpander: setRecordExpander (:3998);
    • nodeTypeVocabularySealed: sealNodeTypeVocabulary (:9424).

    For each one, the stub builds const readX = () => this.X; and the host member get X() { return readX(); }. Each read in the body reads the engine's current value, as it did inside the class.

  • Four fields go by value: logger, suspendedRuns, cacheOnlySuspensions and consumedSuspensions. The seat asked for proof that none is reassigned after construction:

    • The declarations (engine.ts at this head):
      • private logger: Logger;
      • private suspendedRuns = new Map…
      • private cacheOnlySuspensions = new Set…
      • private consumedSuspensions = new Map…
    • git grep -nE "this\.(logger|suspendedRuns|cacheOnlySuspensions|consumedSuspensions)\s*=[^=]" -- packages/services/service-automation/src finds 1 line, in the constructor: this.logger = logger; (:2744).
    • Across the repo, git grep -nE "\.(suspendedRuns|cacheOnlySuspensions|consumedSuspensions)\s*(=[^=>]|\?\?=)" finds nothing. The bracket form, ['logger'] and the other three names followed by = or ??=, finds nothing either. And git grep -nE "\.logger\s*(=[^=>]|\?\?=)" -- packages/services/service-automation finds only that constructor line.
    • The bodies change the three collections' contents in place, on the engine's own Map and Set, and never rebind the fields.
  • Async. The stubs of the twelve async methods drop async and return the moved function's promise, as in slices 3 to 5.

    • The caller gets the very promise the body makes.
    • Dropping async is the only edit to those signature lines, and the .d.ts does not print async.
  • The moved bodies keep saying this., so the moved lines are unedited.

Module-level declarations and imports

  • Nothing is newly exported. Every top-level name the bodies read is already exported from engine.ts: buildRunTrigger, NodeExecutionResult, StepLogEntry and SuspendedRun.
    • The module imports buildRunTrigger by value, and the rest, AutomationEngine included, as types.
    • buildRunTrigger is read only inside function bodies, at call time. A comment above the import says so, as in slices 3 and 5.
  • The module's other imports use the same specifiers as engine.ts's own imports:
    • the types FlowParsed, FlowRunSummary, AutomationContext, AutomationResult and ResumeSignal;
    • the values RESUME_AUTHORITY_SERVICE and describeThrownForLog;
    • the ./runtime-identity.js and ./guard-refusal.js import lines, verbatim. These are moved lines.
  • Two engine.ts import lines change.
    • ./runtime-identity.js keeps runTriggerUserId and type SeededRunContext. runIsUnscopedUserMode, flowTouchesData and runOrgUserIds were read only by moved bodies.
    • import { refuseNode } from './guard-refusal.js'; goes, because only a moved body read refuseNode.
    • engine.ts gains the ./run-resume.js import, after the ./run-history.js one, with a 4-line comment naming its bodies.
  • Two imports stay, for their {@link}s. RESUME_AUTHORITY_SERVICE and SeededRunContext are no longer read in engine.ts code, but engine.ts docblocks still {@link} them: 2 links each. tsc counts a {@link} as a use under noUnusedLocals, so both stay imported and the links still resolve.
    • A control re-added validateScreenInputs and flowTouchesData, which engine.ts neither reads nor links, to its imports. tsc failed with TS6133 on both. So the setting is live for this file.
  • Authored text. The module docblock and the host interface's docblock are new. The host docblock names the method that reassigns each getter field.

Proof of move-only

  • Moved block. This is git diff --color-moved=plain --color-moved-ws=allow-indentation-change 03243fc6 HEAD over engine.ts and run-resume.ts. It detects 534 of the 546 deleted lines and 582 of the 821 added lines as moved.
    • Deleted, not moved (12): the signature heads of the twelve async methods, each of which drops async.
    • Added, not moved (239):
      • the module's docblock, imports and host interface;
      • the fifteen pointer docblocks and rewritten function heads;
      • the ./run-resume.js import and its comment, and the narrowed ./runtime-identity.js import;
      • the twelve heads without async;
      • the fifteen stub bodies;
      • lines git does not pair with a moved block.
  • An independent check. A script compared base and head engine.ts against the new module.
    • Module lines. 579 of the module's 689 lines are in 15 verbatim runs of base engine.ts: the fifteen method texts, de-indented one level. The script names each of the other 110:

      • 76 head lines: the copyright line, the docblock, the imports and their comment, the host docblock and the 25-member host interface;
      • the 15 pointer docblocks;
      • 19 signature lines: fifteen export function heads, and four this parameter lines, each a Pick of the host.
    • Deleted lines. Every line deleted from engine.ts (546 in all, 8 of them blank) is among the module's lines, apart from the 12 async heads above. The two deleted import lines are among them, verbatim.

    • Added lines. Of the 132 lines added to engine.ts, 101 are found nowhere in base. They are:

      • the narrowed ./runtime-identity.js import;
      • the ./run-resume.js import with its comment;
      • the twelve heads without async;
      • the stub lines.

      The other 31, such as logger: this.logger, and };, are lines base already contains elsewhere.

    • Literals. No string or template literal in the fifteen method bodies spans a line, checked on the TypeScript AST of base engine.ts. So de-indenting changed no string value.

  • .d.ts: see the next section.
  • Bundles. The ESM and CJS export lists are identical: 39 names each at base and at head, and ESM equals CJS on each side. The bundle JS bytes differ only because code moved within the bundle.
  • Tests. @objectstack/service-automation's suite passes the same at base and head, 199 of 199 files and 2628 of 2628 tests.

.d.ts reading (ruling 6348891160, item 2)

The merge base is 03243fc6, the head of main, so the merge-base reading and the base reading are one reading.

  • Base is dist/, built at 03243fc6 in this container, in a worktree of that commit.
  • Head is dist/, built at this PR's commit.
  • The package's dependencies were built by turbo run build --filter=@objectstack/service-automation (31 of 31 tasks), and both sides resolve the same built dependencies.

The readings:

  • Raw sha256, index.d.ts and index.d.cts, which are identical to each other on both sides: base 1a5162a4dd929399460a3936e22747a74cf0a8db24d398ffbab5d7ead7bf212e, head 1a5162a4dd929399460a3936e22747a74cf0a8db24d398ffbab5d7ead7bf212e.
  • Normalised sha256, all four files: base 0df32585069f743135440763aabff8c23473231181297c8d164f5f7ee4f10232, head 0df32585069f743135440763aabff8c23473231181297c8d164f5f7ee4f10232.
  • Raw diff, index.d.ts base vs head: 0 lines, with 19,626 lines on each side. This slice reorders no union, so the normalised diff is empty too.
  • The normaliser, the ruling's one-liner, verbatim:
    node -e 'const s=require("fs").readFileSync(process.argv[1],"utf8");process.stdout.write(s.replace(/"[^"\n]*"(?:\s*\|\s*"[^"\n]*")+/g,r=>r.split(/\s*\|\s*/).sort().join(" | ")))' dist/index.d.ts | sha256sum
  • Positive controls, on line 3583 of the head index.d.ts, a private member whose body moved. Each control changes that one line, then runs the same normaliser:
    • private loadSuspendedRunStrict; made public (loadSuspendedRunStrict;) gives 6218e57ef5778f6cd7830065199a40ae791e8f5948ce7ba5b329a19b77ef6aa3.
    • The same member renamed (private loadSuspendedRunStrictRenamed;) gives bc864cef7530af8f0921d14956e47c22a3d20aad6be293d6b494009cb1020c4e.
    • Both differ from 0df32585…, so the normaliser hides neither kind of change.
  • Item 1 holds:
    • (a) the declaration set and visibility are the same;
    • (b) the files are byte-identical, before and after the normalisation;
    • (c) the ESM and CJS export lists are identical;
    • (d) there is no raw-diff line.

Readers

One reader re-pointed. src/flow-activation-ledger.test.ts's ENGINE_SOURCES holds the #10243 grep pins, which are absence checks. It gains ./run-resume.ts, so a moved body is not a place the retired mechanism could come back unseen. That 1-line edit is the PR's third file.

Readers examined. The base for each is 03243fc6, in a worktree of that commit.

  • check-tenant-audit-census (derived): output byte-identical to base.
    • It certifies 238 write call sites (162 decidable; 2 provably without tenant context, 29 more unreadable).
    • It holds 23 prose figures and matches every UNTYPED_RECEIVERS row.
    • Its --self-test output is identical too.
  • check-system-context-census (derived): output byte-identical. It finds 149 elevation read sites in 22 packages across 77 files, in 129 symbols.
  • check:liveness (spec lane, not derived; run by hand as packages/spec's tsx scripts/liveness/check-liveness.mts): output byte-identical at base and head.
    • 753 (entry, cited file) pairs: 752 anchored, 1 exempt.
    • 982 of 982 symbol anchors resolve.
    • No packages/spec/liveness row cites any of the fifteen methods.
  • check:platform-checklist (not derived; run by hand): output identical at base and head. 987 of 997 symbol anchors resolve; the other 10 are the same ones, the named [finding] the platform-checklist corpus resolves symbol anchors with its OWN rule, not the shared resolver — a permissive token match where the ruling says there is to be exactly one implementation #16898 residual.
  • check-adr-symbol-anchors (not derived; run by hand): output identical at base and head. 2384 anchors across 142 records resolve.
  • check:adr-anchors (decision letters; run by hand at the merge base and the head): output identical apart from the scanned-file count, 6691 at base and 6692 at head, the extra file being run-resume.ts.
    • It reads 84 anchored files, 52285 citations and 1947 decision-letter citations, the same at both ends.
    • Neither engine.ts nor run-resume.ts is on the anchored surface.
    • docs/adr/0019-approval-as-flow-node.md is not edited, and its "module-private" line about ENGINE_BUILT_SIGNAL stays true (see Scope).
  • check:startup-registry-verdict (not derived; run by hand at both ends, on the hand-gate list): 46 seams, 40 of them read-only, none recording a verdict, at base and at head.
    • Its --list is the same at both ends apart from line numbers and the scanned-file count.
    • None of its four engine bodies moves.
    • The scanned file count is 3460 at base and 3461 at head; the extra file is run-resume.ts.
  • path:line citations. The only one into this package's engine.ts is service-automation/src/engine.ts:44, in packages/spec/scripts/liveness/evidence.test.ts. It is a realm-attribution fixture that scanEvidence parses without reading the file.
    • Lines of engine.ts from base :68 to :143 move up by 1. Lines after base :143 move down by 20 until the first moved body.
    • Lines after the last moved body move up by 414, since the file goes from 11,108 to 10,694 lines.

Gates

  • Derived. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on this commit derives 60 families from the 3 changed paths: 1,369 changed lines, under the 3,000-line human-merge threshold.
    • All of them ran in this container on this commit, with each exit code captured before any pipe, and all 60 exit 0.
    • The run went in two parts. My own run limit stopped the first part during the 51st family, so that family and the 9 after it ran again in a second run. The 51st family's interrupted run is not counted.
    • dispatch-gates.mjs --ran reconciles: 60 derived, 60 run, 0 NOT-MEASURED, 0 UNRUN.
    • The one family more than slice 5's 59 is node scripts/ci/prune-turbo-cache.mjs --self-test, which ci: prune each Test Core Turbo seed to its own run's tasks before saving it #25523 added to main.
  • By hand, at base and head, not derived: check:liveness, check:platform-checklist, check-adr-symbol-anchors, check:adr-anchors and check:startup-registry-verdict, with the readings in the Readers section above.
  • Package checks.
    • @objectstack/service-automation's vitest run gives 199 of 199 files and 2628 of 2628 tests, the same at base and head.
    • The package's typecheck (tsc --noEmit and check:test-typecheck) passes.
    • ESLint on the three files passes.
  • Open PRs, re-listed just before this PR was opened: 11. I diffed each one's head against its merge base with origin/main. None of them touches service-automation/src, the readers above, their ledgers, or docs/adr/0019-approval-as-flow-node.md.
node scripts/check-ci-filter-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-adoption.mjs :: exit 0
node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-dts-emitted.mjs --self-test :: exit 0
node scripts/check-issue-citations.mjs :: exit 0
node scripts/check-keyed-text-bounds.mjs :: exit 0
node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0
node scripts/check-platform-object-tenancy-census.mjs :: exit 0
node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0
node scripts/check-plugin-teardown-shape.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0
node scripts/check-position-name-fold-loaders.mjs :: exit 0
node scripts/check-position-name-fold-loaders.mjs --self-test :: exit 0
node scripts/check-registry-log-declared.mjs :: exit 0
node scripts/check-registry-log-declared.mjs --self-test :: exit 0
node scripts/check-rest-log-spy-declared.mjs :: exit 0
node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0
node scripts/check-system-context-census.mjs :: exit 0
node scripts/check-system-context-census.mjs --self-test :: exit 0
node scripts/check-tenant-audit-census.mjs :: exit 0
node scripts/check-tenant-audit-census.mjs --self-test :: exit 0
node scripts/check-undeclared-dep-imports.mjs :: exit 0
node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0
node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0
node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0
node scripts/docs-audit/check-affected-docs.mjs :: exit 0
node scripts/docs-audit/check-drift-comment.mjs :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:dts-closure :: exit 0
pnpm check:dual-build-cjs-loads :: exit 0
pnpm check:durability-log-level :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:error-status-conformance :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:issue-citations :: exit 0
pnpm check:lean-entry-closure :: exit 0
pnpm check:logger-receiver-detach :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:objectql-double-limit :: exit 0
pnpm check:org-identifier :: exit 0
pnpm check:page-declaration-shape :: exit 0
pnpm check:published-files :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:slot-lookup :: exit 0
pnpm check:sourcemap-no-sources-content :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0

Acceptance notes

  • The slice is the slice-6 group the remaining-bodies table named, less refuseInvalidScreenInput and buildSubflowResumeSignal. Those two stay so that ADR-0019's "module-private" line about ENGINE_BUILT_SIGNAL stays true. The claim says so.
  • Four host getters, in the slice-5 store form. No get/set pair is needed.
  • No export is added to engine.ts.
  • After this slice, about 815 movable lines in bodies over 3 lines are left for slice 7, and they need no ruling. The 21 site-bearing bodies, and the five startup-registry bodies tied to registerFlow, wait on the 33-site ruling.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Mnj4nkWuhJ18xEdZvb2cjE

…into run-resume.ts

Move-only. The bodies of fifteen AutomationEngine methods move unedited
into a new run-resume.ts: resolveRunContext, seedRunGrants,
resolveDecisionSegmentContext and expandDeclaredLookups, which resolve a
run's context; resume, refuseGatedResume, refuseUndeclaredSuspension,
loadSuspendedRun, loadSuspendedRunStrict and creditChildRun, which load
and gate a suspended run; and failSuspendedRun,
settleUnresumableSuspension, cancelRun, cloneVariablesAtPause and
failAncestors, which fail, settle or cancel one. Each method keeps its
name, docblock, signature and position in the class and calls its body
with a RunResumeHost literal holding exactly the members the body reads;
creditChildRun reads none and is called directly. Each async stub drops
async and returns the promise the moved function makes.

Fields assigned only at their declaration or in the constructor go by
value. store, userGrantsResolver, recordExpander and
nodeTypeVocabularySealed go through getters, because a method reassigns
each. refuseInvalidScreenInput and buildSubflowResumeSignal stay in the
class: they read the module-private ENGINE_BUILT_SIGNAL. The imports only
moved bodies read move with them. The ENGINE_SOURCES grep pins read the
new module too.

Claude-Session: https://claude.ai/code/session_01Mnj4nkWuhJ18xEdZvb2cjE
Co-Authored-By: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/service-automation, touching 63 documentable anchor(s).

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

  • content/docs/ai/actions-as-tools.mdx (via /automation/:name/runs/:runId/resume (route, a path literal in refuseUndeclaredSuspension))
  • content/docs/api/client-sdk.mdx (via automation.resume (sdk, the route ledger binds it to POST /automation/:name/runs/:runId/resume))
  • content/docs/automation/approvals.mdx (via /automation/:name/runs/:runId/resume (route, a path literal in refuseUndeclaredSuspension))
  • content/docs/automation/flows.mdx (via /automation/:name/runs/:runId/resume (route, a path literal in refuseUndeclaredSuspension))

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

  • content/docs/releases/v16.mdx (via AutomationEngine (symbol, a top-level type))
  • content/docs/releases/v17/17-0.mdx (via AutomationEngine (symbol, a top-level type), automation.resume (sdk, the route ledger binds it to POST /automation/:name/runs/:runId/resume))
  • content/docs/releases/v17/17-1.mdx (via /automation/:name/runs/:runId/resume (route, a path literal in refuseUndeclaredSuspension))
  • content/docs/releases/v17/17-6.mdx (via AutomationEngine (symbol, a top-level type))
  • content/docs/releases/v17/17-7.mdx (via RUN_NOT_FOUND (literal, a string literal in settleUnresumableSuspension), STORE_UNAVAILABLE (literal, a string literal in settleUnresumableSuspension), /automation/:name/runs/:runId/resume (route, a path literal in refuseUndeclaredSuspension))

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

What this run could not see
  • 1 anchor(s) matched too much of the corpus to be a work list: PERMISSION_DENIED (literal, 43 pages)
  • 3 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 6 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 9c43e19f659c40bb065601bda50c7e05250169f2 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 646fce712c2f6c84102340726207f7f89e2cc9d8 — the merge of head ad9caf7866d7a4f403b38a890b6a1f21d4334651 into base 9c43e19f659c40bb065601bda50c7e05250169f2, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 646fce712c2f6c84102340726207f7f89e2cc9d8 && git checkout 646fce712c2f6c84102340726207f7f89e2cc9d8
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 9c43e19f659c40bb065601bda50c7e05250169f2 ad9caf7866d7a4f403b38a890b6a1f21d4334651 && git checkout -B drift-repro 9c43e19f659c40bb065601bda50c7e05250169f2 && git merge --no-ff ad9caf7866d7a4f403b38a890b6a1f21d4334651

node scripts/docs-audit/affected-docs.mjs --json 9c43e19f659c40bb065601bda50c7e05250169f2

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

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 9c43e19f659c40bb065601bda50c7e05250169f2 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · 2026-10-24T01:45Z

domain:services seat 1 (seat post #6021) · os-sales · session_016g7nYP9wdNx1GDa5XDr7Uy · card #25222 slice 6 (claim 6377626691; os-dev-report 6378300517) · reviewed head ad9caf7866 · merge base 03243fc637

  • Shape: the bodies of 15 run-context and resume methods move unedited into the new src/run-resume.ts. 3 files, +822 / −547, 1,369 changed lines.
  • Host:
    • store, userGrantsResolver, recordExpander and nodeTypeVocabularySealed are getters. The seat's grep finds each one reassigned outside the constructor: engine.ts:2769, :3988, :3998 and :9424.
    • logger, suspendedRuns, cacheOnlySuspensions and consumedSuspensions go by value. They are written only in the constructor.
    • The host is built on each call.
  • Narrowing, accepted: refuseInvalidScreenInput and buildSubflowResumeSignal stay in the class. They read ENGINE_BUILT_SIGNAL, which ADR-0019 keeps module-private, and moving them would mean exporting it. The claim declared this.
  • Path reader: the flow-activation-ledger.test.ts ENGINE_SOURCES list gains ./run-resume.ts.
  • .d.ts, ruling 6348891160 item 1, re-run by the seat in its own worktree:
    • turbo run build at 03243fc637 and at this head.
    • Raw 1a5162a4dd929399… / normalised 0df32585069f7431… on both index.d.ts and index.d.cts at both ends. The raw diff is 0 lines.
    • The seat's positive control makes head line 1490, private flows;, public. That moves both hashes, to raw 192d82835c6dd986… and normalised 89e8a8fac9607092….
    • CJS exports: 39 at both ends.
  • Gates re-run by the seat, all exit 0 at base and at head:
    • check-adr-symbol-anchors
    • check-tenant-audit-census: byte-identical.
    • check-system-context-census: byte-identical.
    • check-adr-anchors
    • check-dispatcher-error-vocabulary
    • check-platform-checklist
    • spec check-liveness: byte-identical.
    • check-startup-registry-verdict: 46 seams at both ends, and only the file count changes (3,460 → 3,461).
  • Decision-letter count, read by the seat: 1947 at the merge base and 1947 at head.
  • Tests and gates (report): 60 of 60 derived gates exit 0. 199 files / 2,628 tests at both ends.
  • CI: 34 success and 12 expected skips, none failed or pending (46 runs).
  • Mergeable: git merge-tree onto today's main (ce18e73483) is clean.
  • Census sites: this slice moves 0 of the 33, which still wait on their ruling.
  • Landing: not governed (check-governed-merges --pr 25567: 1,369 lines). Ready + auto-merge through the relay. The card stays open and dispatched. Slice 7 is claimed afresh on the merged main.

Generated by Claude Code

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants