Repository navigation
refactor(service-automation): move executeWithoutRetry and the run-variable seeders into dag-traversal.ts (#25222 slice 4) - #25542
Conversation
…riable seeders into dag-traversal.ts Move-only. The bodies of executeWithoutRetry, seedDeclaredVariables and seedRunVariables move unedited from AutomationEngine into dag-traversal.ts, beside the DAG traversal bodies. Each method keeps its name, docblock, signature and position in the class and calls its body with a DagTraversalHost literal holding exactly the members the body reads; seedDeclaredVariables reads none and is called directly. executeWithoutRetry's stub drops async and returns the promise the moved function makes. DagTraversalHost gains the members these bodies read, each typed as the class member. buildRunTrigger and ExecutionLogEntry, shared with code that stays, are exported in place; index.ts re-exports engine.js by name, so the package entry is unchanged. retryExecution stays in the class: the spec liveness ledger anchors the errorHandling backoff keys on engine.ts, and only its body names them. Claude-Session: https://claude.ai/code/session_01Mnj4nkWuhJ18xEdZvb2cjE Co-Authored-By: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 6 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 6 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin d3d858c53a51c7881138cd48e05cd78f94ff95e9 && git checkout d3d858c53a51c7881138cd48e05cd78f94ff95e9
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 93a6ba41364cf2007c1f8e5e6bfdbb51e5b6bdf9 c89b93d5f33d2555b53b61de5cd1b19f8c0e3745 && git checkout -B drift-repro 93a6ba41364cf2007c1f8e5e6bfdbb51e5b6bdf9 && git merge --no-ff c89b93d5f33d2555b53b61de5cd1b19f8c0e3745
node scripts/docs-audit/affected-docs.mjs --json 93a6ba41364cf2007c1f8e5e6bfdbb51e5b6bdf9
|
席位核对 · ACCEPT · 2026-10-23T22:16Z
Generated by Claude Code |
Requested by Sales · project thread
Part of #25222
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6348891160
Slice 4 of the
engine.tssplit. The claim is 6374967743. The bodies of threeAutomationEnginemethods move, unedited, intopackages/services/service-automation/src/dag-traversal.ts, the module slice 3 (#25531) made:executeWithoutRetry, one attempt of a run;seedDeclaredVariablesandseedRunVariables, which seed a run's variables.The change is move-only, and the card stays open for the later slices. Branch:
claude/project-thread-nirtwt, the harness-pinned branch for this session, restarted frommainat5ea211ccafter slice 3 merged asd7ccdfcd. The branch name has no issue number, so the claim comment is the identity record.Scope
retryExecutionstays in the class. The seat's slice-4 list named it, and this slice narrows that list by one, as the claim states.packages/spec/liveness/flow.jsoncitesengine.tsforflow/errorHandling.backoffMs,.backoffMultiplierand.maxRetryDelayMs. OnlyretryExecution's body names those three keys, in its destructuring oferrorHandling.check:livenesskey-mention goes red: 749 of 753 pairs anchored, those 3 UNANCHORED.getConnectorDescriptorsstayed in slice 2.this.FIELD.delete/insert/update(sites in 21 methods is still pending with Sales. This slice moves 0 of them: none of the three bodies holds one.check-tenant-audit-censusandcheck-system-context-censusgive byte-identical output at base and head (see Readers).What stays in
engine.ts.d.ts.retryExecution, for the reason above, and the section's other members, as slice 3 left them.The shape (slices 1 to 3, one host interface)
DagTraversalHostgains the 11 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. The interface now has 22 members.thisas thePickofDagTraversalHostover exactly the members its own body reads, read off each body's AST in first-read order.seedDeclaredVariablesreads no member, so it is called directly, without a host.(...a) => this.m(...a), so a spy or test double set on the instance is still the one called.logger, as in slice 3, and theflowsmap, assigned once at its declaration and never reassigned anywhere in the repo, tests included. So a host's field is the engine's field, including where the async body reads it after anawait.executeWithoutRetry's stub dropsasyncand returns the moved function's promise, as in slice 3. The caller gets the very promise the body makes. Droppingasyncis the only edit to that signature line, and the.d.tsdoes not printasync.this., so the moved lines are unedited.Module-level declarations and imports
buildRunTriggerand theExecutionLogEntryinterface each gainexport, asFlowSuspendSignaldid in slice 3.index.tsre-exports./engine.jsby name, so the package entry is unchanged; the export lists and the.d.tsbelow prove it../engine.jsit addsbuildRunTrigger, by value, andtype ExecutionLogEntry.buildRunTriggeris read only inside a function body, at call time, so the existing note on the import cycle covers it.AutomationResult,readCarriedRefusal,summarizeRunanddescribeThrownForLog. Each is still read inengine.tstoo, so noengine.tsimport line changes except the./dag-traversal.jsimport, which gains the three names../dag-traversal.jsimport inengine.ts, now name the new bodies.Proof of move-only
git diff --color-moved=plain --color-moved-ws=allow-indentation-change 5ea211cc HEADover the two files): 367 of the 380 deleted lines and 375 of the 446 added lines are detected as moved.engine.ts, the two comment lines above the./dag-traversal.jsimport, the heads ofExecutionLogEntryandbuildRunTrigger, which gainexport, andexecuteWithoutRetry's head, which dropsasync../dag-traversal.jsimport's three names, and the three stub bodies. The rest are lines such as a blank or a closing brace that git does not pair with a moved block.engine.tsand base and headdag-traversal.ts):engine.ts, the three method texts de-indented one level. It names each of the other 31: 6 docblock lines, 6 import lines, 11 host members, 3 pointer docblocks and 5 signature lines (threeexport functionheads and twothisparameter lines, each aPickof the host).engine.tsis among the lines added to the module, apart from the 5 rewritten lines above (372 deleted, 10 of them blank).engine.tsare found nowhere in base: the rewritten comment, the three import names, the twoexportheads, the head withoutasync, and the stub lines. The other 8 are lines such aslogger: this.logger,and};that base already contains elsewhere.engine.ts), so de-indenting changed no string value..d.ts: see the next section.buildRunTriggerandExecutionLogEntrygainexportinside the module graph only, so neither reaches the package entry. The bundle JS bytes differ because code moved within the bundle.@objectstack/service-automation's suite passes the same at base and head, 199 files and 2628 tests..d.tsreading (ruling 6348891160, item 2)Base is
dist/built at5ea211ccin this container, in a worktree of that commit. Head isdist/built at this PR's commit, with the package's dependencies built byturbo run build --filter=@objectstack/service-automation(31 of 31 tasks). Both sides resolve the same built dependencies.index.d.tsandindex.d.cts(identical to each other on both sides): base1a5162a4dd929399460a3936e22747a74cf0a8db24d398ffbab5d7ead7bf212e, head1a5162a4dd929399460a3936e22747a74cf0a8db24d398ffbab5d7ead7bf212e.0df32585069f743135440763aabff8c23473231181297c8d164f5f7ee4f10232, head0df32585069f743135440763aabff8c23473231181297c8d164f5f7ee4f10232.index.d.tsbase vs head: 0 lines (19,626 lines each side). This slice reorders no union, so the normalised diff is empty too.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 | sha256sumindex.d.ts, line 5249, the private member whose body moved, one line each, then the same normaliser:private executeWithoutRetry;made public (executeWithoutRetry;) gives8683c058fc24e16c642af1815c0d43bfd1a2a461f5f3e36ce7b0a9704bbc75c4.private executeWithoutRetryRenamed;) gives81b389461bb213a6c5890a1e129b3c75ddd6d3b6a8054315ee6eda35dcf231bb.0df32585…, so the normaliser hides neither kind of change.Readers
No reader needed re-pointing.
src/flow-activation-ledger.test.ts'sENGINE_SOURCES(the #10243 grep pins) has listed./dag-traversal.tssince slice 3.Readers examined:
check-tenant-audit-census(derived): output byte-identical to base5ea211cc. It certifies 238 write call sites (162 decidable; 2 provably without tenant context, 29 more unreadable), holds 23 prose figures, and matches everyUNTYPED_RECEIVERSrow. Its--self-testoutput is identical too.check-system-context-census(derived): output byte-identical. It finds 149 elevation read sites in 22 packages across 76 files, in 128 symbols.check:liveness(spec lane, not derived, run by hand aspackages/spec'stsx scripts/liveness/check-liveness.mts): output identical at base and head. 753 (entry, cited file) pairs: 752 anchored, 1 exempt. 982 of 982 symbol anchors resolve.flow.json'ssuccessMessagerow citesengine.ts#executeWithoutRetryand quotessuccessMessage: flow.successMessagefrom its body. The method stays as a shell, so the anchor resolves.engine.tsstill namessuccessMessage8 times, so key-mention still holds.retryExecution, which the next row cites, stays (see Scope).check:platform-checklist(not derived, run by hand): output identical at base and head. 987 of 997 symbol anchors resolved; the other 10 are the same ones, on 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. No checklist anchor names a moved method.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): output byte-identical at base and head, with 83 anchored files, 52271 citations across 6676 files, and 1971 decision-letter citations. Neitherengine.tsnordag-traversal.tsis on the anchored surface (the package's one anchored file isflow-precedence.ts).check:startup-registry-verdict(not derived, run by hand): 46 seams, 40 read-only, none recording a verdict, at base and head. The scanned file count is 3448 at base and 3449 at head. The extra file ispackages/spec/src/migrations/registry.ts, a git-ignored build output present only in the head worktree.path:linecitation in the repo points into the moved ranges of baseengine.ts(the bodies:11584to:12025), or intodag-traversal.ts.engine.tsfrom base:125up to the first moved body move down by 3. Lines after base:12025move up by 341.service-automation/src/engine.ts:44string, inpackages/spec/scripts/liveness/evidence.test.ts, is a realm-attribution fixture thatscanEvidenceparses without reading the file.Gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon this commit derives 53 families from the 2 changed paths (826 changed lines, under the 3,000-line human-merge threshold). All 53 ran in this container on this commit, each exit code captured before any pipe, and all 53 exit 0.dispatch-gates.mjs --ranreconciles: 53 derived, 53 run, 0 NOT-MEASURED, 0 UNRUN.check:liveness,check:platform-checklist,check-adr-symbol-anchors,check:adr-anchorsandcheck:startup-registry-verdict, with the readings in the readers section above.@objectstack/service-automation'svitest run: 199 of 199 files, 2628 of 2628 tests, the same at base and head.tsc --noEmitand ESLint on the two files pass.Acceptance notes
retryExecutionstays, for the liveness reason above, stated in the claim before any code was pushed.🤖 Generated with Claude Code
https://claude.ai/code/session_01Mnj4nkWuhJ18xEdZvb2cjE