Repository navigation
Commit 673ebfd
<!-- claude-projects-attribution: {"github_login":"os-sales"} -->
_Requested by **Sales** · [project
thread](https://claude.ai/code/project/chan_01D5bWFY3rFzgJcytD5gD4Uu?thread=cmsg_01D5bWFY3rFzgJcytD5gD4UuCEzLkAB12FfRHL9ipwfKPd)_
Part of #25222
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6348891160
Slice 4 of the `engine.ts` split. The claim is 6374967743. The bodies of
three `AutomationEngine` methods move, unedited, into
`packages/services/service-automation/src/dag-traversal.ts`, the module
slice 3 (#25531) made:
- `executeWithoutRetry`, one attempt of a run;
- `seedDeclaredVariables` and `seedRunVariables`, 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 from `main` at `5ea211cc` after slice 3 merged
as `d7ccdfcd`. The branch name has no issue number, so the claim comment
is the identity record.
## Scope
- **`retryExecution` stays 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.json` cites `engine.ts` for
`flow/errorHandling.backoffMs`, `.backoffMultiplier` and
`.maxRetryDelayMs`. Only `retryExecution`'s body names those three keys,
in its destructuring of `errorHandling`.
- Measured on a draft that moved it, `check:liveness` key-mention goes
red: 749 of 753 pairs anchored, those 3 UNANCHORED.
- The ledger is the spec lane's file, so this slice does not re-point
it. The body stays, as `getConnectorDescriptors` stayed in slice 2.
- **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 them: none of the three bodies
holds one. `check-tenant-audit-census` and `check-system-context-census`
give byte-identical output at base and head (see Readers).
- **Return types.** The three methods are private, and each declares its
return type.
- **Size.** 826 changed lines, under the 3,000-line bar.
## 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`.
- `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)
- `DagTraversalHost` gains 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.
- Each moved function types `this` as the `Pick` of `DagTraversalHost`
over exactly the members its own body reads, read off each body's AST in
first-read order. `seedDeclaredVariables` 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.
- Fields are passed by value. There are two: `logger`, as in slice 3,
and the `flows` map, 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 an
`await`.
- **Async.** `executeWithoutRetry`'s stub drops `async` and returns the
moved function's promise, as in slice 3. The caller gets the very
promise the body makes. Dropping `async` is the only edit to that
signature line, 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
- **Shared with code that stays, exported in place.** `buildRunTrigger`
and the `ExecutionLogEntry` interface each gain `export`, as
`FlowSuspendSignal` did in slice 3. `index.ts` re-exports `./engine.js`
by name, so the package entry is unchanged; the export lists and the
`.d.ts` below prove it.
- **The module's imports.**
- From `./engine.js` it adds `buildRunTrigger`, by value, and `type
ExecutionLogEntry`. `buildRunTrigger` is read only inside a function
body, at call time, so the existing note on the import cycle covers it.
- It adds `AutomationResult`, `readCarriedRefusal`, `summarizeRun` and
`describeThrownForLog`. Each is still read in `engine.ts` too, so no
`engine.ts` import line changes except the `./dag-traversal.js` import,
which gains the three names.
- **Authored text.** Two sentences of the module docblock, and the
comment above the `./dag-traversal.js` import in `engine.ts`, now name
the new bodies.
## Proof of move-only
- **Moved block** (`git diff --color-moved=plain
--color-moved-ws=allow-indentation-change 5ea211c HEAD` over the two
files): 367 of the 380 deleted lines and 375 of the 446 added lines are
detected as moved.
- Deleted, not moved (13): in the module, the six docblock lines and two
import lines that are rewritten; in `engine.ts`, the two comment lines
above the `./dag-traversal.js` import, the heads of `ExecutionLogEntry`
and `buildRunTrigger`, which gain `export`, and `executeWithoutRetry`'s
head, which drops `async`.
- Added, not moved (71): their replacements, the module's new import
lines, the 11 host members, the three pointer docblocks and rewritten
signature heads, the `./dag-traversal.js` import'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.
- **An independent check** (a script over base and head `engine.ts` and
base and head `dag-traversal.ts`):
- 384 of the 415 lines added to the module are in 4 verbatim runs of
base `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 (three `export function` heads
and two `this` parameter lines, each a `Pick` of the host).
- Every line deleted from `engine.ts` is among the lines added to the
module, apart from the 5 rewritten lines above (372 deleted, 10 of them
blank).
- 23 of the 31 lines added to `engine.ts` are found nowhere in base: the
rewritten comment, the three import names, the two `export` heads, the
head without `async`, and the stub lines. The other 8 are lines such as
`logger: this.logger,` and `};` that base already contains elsewhere.
- The 8 lines deleted from the module are the docblock and import lines
it rewrites; no slice-3 body line changes.
- No string or template literal in the three 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 head, and ESM equals CJS on each side. `buildRunTrigger` and
`ExecutionLogEntry` gain `export` inside the module graph only, so
neither reaches the package entry. The bundle JS bytes differ because
code moved within the bundle.
- **Tests**: `@objectstack/service-automation`'s suite passes the same
at base and head, 199 files and 2628 tests.
## `.d.ts` reading (ruling 6348891160, item 2)
Base is `dist/` built at `5ea211cc` in this container, in a worktree of
that commit. Head is `dist/` built at this PR's commit, with the
package's dependencies built by `turbo run build
--filter=@objectstack/service-automation` (31 of 31 tasks). Both sides
resolve the same built dependencies.
- raw sha256, `index.d.ts` and `index.d.cts` (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** (19,626 lines 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 the head `index.d.ts`, line 5249, the private
member whose body moved, one line each, then the same normaliser:
- `private executeWithoutRetry;` made public (`executeWithoutRetry;`)
gives
`8683c058fc24e16c642af1815c0d43bfd1a2a461f5f3e36ce7b0a9704bbc75c4`.
- the same member renamed (`private executeWithoutRetryRenamed;`) gives
`81b389461bb213a6c5890a1e129b3c75ddd6d3b6a8054315ee6eda35dcf231bb`.
- 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
No reader needed re-pointing. `src/flow-activation-ledger.test.ts`'s
`ENGINE_SOURCES` (the #10243 grep pins) has listed `./dag-traversal.ts`
since slice 3.
**Readers examined:**
- `check-tenant-audit-census` (derived): output byte-identical to base
`5ea211cc`. It certifies 238 write call sites (162 decidable; 2 provably
without tenant context, 29 more unreadable), 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 76 files, in 128
symbols.
- `check:liveness` (spec lane, not derived, run by hand as
`packages/spec`'s `tsx 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`'s `successMessage` row cites
`engine.ts#executeWithoutRetry` and quotes `successMessage:
flow.successMessage` from its body. The method stays as a shell, so the
anchor resolves. `engine.ts` still names `successMessage` 8 times, so
key-mention still holds.
- The quoted line is now in the module, which the spec lane may re-point
to at its own pace. `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 #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. Neither
`engine.ts` nor `dag-traversal.ts` is on the anchored surface (the
package's one anchored file is `flow-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 is
`packages/spec/src/migrations/registry.ts`, a git-ignored build output
present only in the head worktree.
- No `path:line` citation in the repo points into the moved ranges of
base `engine.ts` (the bodies `:11584` to `:12025`), or into
`dag-traversal.ts`.
- Lines of `engine.ts` from base `:125` up to the first moved body move
down by 3. Lines after base `:12025` move up by 341.
- The one live `service-automation/src/engine.ts:44` string, in
`packages/spec/scripts/liveness/evidence.test.ts`, is a
realm-attribution fixture that `scanEvidence` parses without reading the
file.
## Gates
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` on 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 --ran`
reconciles: 53 derived, 53 run, 0 NOT-MEASURED, 0 UNRUN.
- Run 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.
- `@objectstack/service-automation`'s `vitest run`: 199 of 199 files,
2628 of 2628 tests, the same at base and head. `tsc --noEmit` and ESLint
on the two files pass.
```text
node scripts/check-ci-filter-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0
node scripts/check-comment-mask-adoption.mjs :: 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 --self-test :: exit 0
node scripts/check-keyed-text-bounds.mjs :: exit 0
node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0
node scripts/check-platform-object-tenancy-census.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0
node scripts/check-plugin-teardown-shape.mjs :: exit 0
node scripts/check-position-name-fold-loaders.mjs --self-test :: exit 0
node scripts/check-position-name-fold-loaders.mjs :: exit 0
node scripts/check-registry-log-declared.mjs --self-test :: exit 0
node scripts/check-registry-log-declared.mjs :: exit 0
node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0
node scripts/check-rest-log-spy-declared.mjs :: exit 0
node scripts/check-system-context-census.mjs --self-test :: exit 0
node scripts/check-system-context-census.mjs :: exit 0
node scripts/check-tenant-audit-census.mjs --self-test :: exit 0
node scripts/check-tenant-audit-census.mjs :: exit 0
node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0
node scripts/check-undeclared-dep-imports.mjs :: exit 0
node scripts/ci/assert-turbo-remote-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: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:org-identifier :: exit 0
pnpm check:page-declaration-shape :: exit 0
pnpm check:published-files :: 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:watch-hint-literal :: exit 0
```
## Acceptance notes
- One judgement call is outside the seat's slice-4 list:
`retryExecution` stays, for the liveness reason above, stated in the
claim before any code was pushed.
- The 33-site ruling decides the slices after this one.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01Mnj4nkWuhJ18xEdZvb2cjE
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 35d942e commit 673ebfd
2 files changed
Lines changed: 446 additions & 380 deletions
0 commit comments