Repository navigation
refactor(service-automation): move AutomationEngine.resumeInternal's body into run-resume.ts (#25222 slice 8b) - #25734
Conversation
…body into run-resume.ts Move-only. The class keeps the private method, its docblock and its signature, and calls the body with a RunResumeHost literal holding the 25 members the body reads (logger, flows, resuming and consumedSuspensions by value; the rest as late-bound closures, so the two recursive call sites still route through the class method). ChildRunRefusal, isRetryableResumeRefusal, carriesSubflowChildOutput and applyResumeSignal gain `export` in place so run-resume.ts can read them; ENGINE_BUILT_SIGNAL stays unexported. Claude-Session: https://claude.ai/code/session_01Rg1PtyxbtSpabeP7j6fq8Y Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 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 cf347edb1cc30b6c3d9387be6944dc708480dd0d && git checkout cf347edb1cc30b6c3d9387be6944dc708480dd0d
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin f3fea0a03df3f4859dd389899df5a4ea036d1545 d8bf1026ad037e4812ccb96908d71a2796cdc7ec && git checkout -B drift-repro f3fea0a03df3f4859dd389899df5a4ea036d1545 && git merge --no-ff d8bf1026ad037e4812ccb96908d71a2796cdc7ec
node scripts/docs-audit/affected-docs.mjs --json f3fea0a03df3f4859dd389899df5a4ea036d1545
|
席位核对 · ACCEPT ·
|
| item | reading |
|---|---|
| Shape | draft, base main, Part of #25222 (no closing keyword), skip-changeset label, Clause-②: no line-initial. |
| Files (2, +985/−913) | engine.ts and run-resume.ts: exactly the claim's surface; no test file needed an edit; no packages/spec/**, no docs/adr/**. Not governed (check-governed-merges --pr 25734), 1,898 changed lines. |
| Move-only | report's AST proof: body, parameters, return type and async token-identical; one-token negative control reads DIFFERENT. Seat's own read on the diff: the class keeps a private resumeInternal stub whose host literal has 25 members, 21 callbacks (the recursive resumeInternal among them, so both recursive calls go through the class) and 4 by value (logger, flows, resuming, consumedSuspensions), none of which the class reassigns after the constructor (flows, resuming, consumedSuspensions are field initialisers; logger is set once in the constructor). |
| Exports | exactly the four the Release names gain export in place (ChildRunRefusal, isRetryableResumeRefusal, carriesSubflowChildOutput, applyResumeSignal); ENGINE_BUILT_SIGNAL stays unexported. |
.d.ts |
raw byte-identical at base and head (a5cbe3bb…), the hazard the Release named did not occur. Ruling 6348891160 holds. |
| Gates | dev 54 derived, 54/54 exit 0, --ran 0 NOT-MEASURED; check:startup-registry-verdict (46 seams) and the tenant-audit census byte-identical at both ends; vitest 201 files / 2,636 tests. CI at this act: in progress. Lint & Repo Gates and Type Check owed success before ready. |
| Landing | ready + auto-merge through the relay once every check on this head is green or an expected skip. This completes slice 8; the seat decides the card's close at landing (report: no slice 9 needed). |
Generated by Claude Code
…s the fixed group, @objectstack/console builds from ui/apps/console, the objectui pin is deleted (#25711) (#25745) <!-- claude-projects-attribution: {"github_login":"os-tesla"} --> _Requested by **Tesla** · [project thread](https://claude.ai/code/project/chan_01AXsQkLFKRdQCqQ3RTr6JaoKAHLK79xmvJyPStopRpPQ2)_ Part of objectstack#25677 Fixes #25711 Blocked-by: sub-issue 5 of #25677 (the subtree PR that adds `ui/`; not filed yet) Clause-②: no Metadata-protocol: none **Maintainer rulings (Tesla, 2026-10-25 09:06Z, director thread):** 17a — the release npm token has publish rights on `@object-ui`. 17b, ruling B — the private VS Code extension `object-ui` stays in the one fixed group. 17c, ruling B — the QUICK_REFERENCE release-sync rows retire; decision B (17c) carried here. > ⛔ **Tier H, cutover sitting.** The cutover #25825 is on `main` (`fd40831416`, with #25833). This PR merged `main` and applies its `ui/` half as tree edits on that tree. Local verdict on `fb110c2323`: comment 6404553650, every step and gate exit 0. It merges per ruling 30 = B once that sweep is clean and the four fast lanes are green. > Body refreshed 2026-10-25T22:55Z on head `fb110c2323` (the merge of `main` `fd40831416` is `e2db258a24`). Comments read through 6404553650. ## What changes **1. One fixed group** (`.changeset/config.json`). The 38 public `@object-ui/*` packages and the private VS Code extension `object-ui` (17b) join the `@objectstack/*` fixed group; `@object-ui/example-*`, `@object-ui/site`, `@object-ui/runner` and `@object-ui/test-support` are ignored, as in objectui. (objectui#13506 made `@object-ui/runner` private before the freeze at `9e1fe03286`.) `ui/.changeset/config.json` is deleted by the ui-side patch (changesets reads one config per repository), and objectui's 65 pending `ui/.changeset/*.md` stay under `ui/` for aftercare #25831. Measured on cutover head `c04b36dcb9`, moving them as they stand reds `check-empty-changeset` (3 empty frontmatters) and `check-adr-0087-registration` (41 breaking changesets with no disposition). Root `check-changeset-fixed` accepts a private name in the group only when `PRIVATE_FIXED_MEMBERS` declares it (`object-ui` alone, with its reason), the package is private, and `privatePackages.version` is true; it reds if that member leaves the group. `check:lockstep-package-count` subtracts the declared private members, so the published count is 111. `check-changeset-no-major` now reads `packages/console/build-dist.sh` as the Console's packed-copy build script, and `check-empty-changeset`'s frontmatter-parser family loses the deleted objectui digest. **2. `@objectstack/console` builds in this workspace.** `packages/console/build-dist.sh` copies `ui/apps/console/dist` (built by turbo through `@object-ui/console#build`) into `packages/console/dist`, ships the tracked `sdui.manifest.json` (ADR-0080), and runs the single-zod canary over the bytes it ships. Root task `@objectstack/console#build:dist` (`turbo.json`) depends on `@object-ui/console#build`; `pnpm console:build` runs it, and `pnpm release` / `cut-rc.yml` run it after `pnpm run build`. `files` and `prepublishOnly` are unchanged. `scripts/build-console.sh` is deleted. The CLI's remedy for a missing Console dist names `pnpm console:build`. **3. The objectstack-side pin is deleted.** `.objectui-sha`, `scripts/bump-objectui.sh` (+ selftest), `scripts/objectui-changeset-digest.mjs`, `scripts/objectui-range.mjs`, `scripts/check-prerelease-pin-watch.mjs`, `scripts/check-console-sha.mjs`, `scripts/check-console-injection.mjs`, `scripts/assert-console-spec-injection.mjs`, `scripts/console-spec-probes.mjs`, `packages/spec/scripts/build-console-objectstack-root.test.ts`; the pin reads in `cut-rc.yml` ("THE objectui PIN IS AN INPUT HERE" and `Read the committed objectui pin`), `release.yml`, `lint.yml`, `showcase-smoke.yml` and the root `package.json` scripts (`objectui:*`, `check:console-sha`, `check:console-injection`, `check:objectui-*`, `check:prerelease-pins`; `pnpm dev*` no longer runs `check:console-sha`). `scripts/check-console-intercept-disarm.mjs` stays. Release notes (`collect-release-notes.sh`) say "no objectui pin" when the new ref has none. Gate self-tests and rosters that named the deleted scripts follow (`dispatch-gates`, `pnpm-filter-targets`, `check-pnpm-filter-targets` (tree-aware: foreign `@object-ui/` targets must be 0 without `ui/`, >0 with it), `bare-root-worklist`, `check-type-check-coverage`). The lockstep count in `content/docs/protocol/backward-compatibility.mdx` and `scripts/publish-smoke-pack.mjs` reads 112, both scopes (`check:lockstep-package-count --fix`), and `packages/spec/vitest.repo-tests.json` drops the deleted test. **4. The objectui-side pin is deleted, in `ui/`.** Until `ui/` was on `main`, this half was carried as `scripts/ui-import/4a-ui-side.patch`. After the cutover landed, `fb110c2323` applied it under `ui/` with README step 2's deletions, then deleted the patch file. `scripts/ui-import/README.md` now records what was applied. It deletes `.objectstack-sha`, `.objectstack-pin/`, `bump-objectstack.sh`, `objectstack-pin.mjs`, `objectstack-floor.mjs`, `check-spec-range-floors.mjs`, `check-installed-spec-pin-claims.mjs`, the dist-pin Vite probes `vite-objectstack-spec-dist.ts` / `vite-objectstack-client-dist.ts`, `changeset-release.yml`, `spec-range-floors.yml`, `release-github-releases.mjs` and their tests, plus (17c) `sync-quick-reference-release.mjs`, its test and the `quick-reference-current-release-4143` pin, with `QUICK_REFERENCE.md`'s version rows. The single-zod guard moves to `ui/scripts/vite-single-zod.ts` (it runs in every console build); `apps/console/vite.config.ts` drops both injections. Every reader of the Changesets config goes through a new `changesetConfigPath()` (own root standalone, monorepo root when nested); objectui's `check-changeset-fixed` and `check-unused-dependencies` otherwise keep their extension rules (17b). The patch was written against verify head `9e37acd126` and checked with `git apply --check` on cutover heads `1c0d02eda4` and `c04b36dcb9` and on `main` at `fd40831416`. It also deletes the nested `ui/.github/pull_request_template.md`, which never renders and whose only markdown-test-inputs reader was the claims test. **6. SDUI manifest.** Carries the sdui manifest regeneration for the merged tree (107 → 106 components; objectui#13449 retired html): `sdui.manifest.json` and `scripts/sdui-manifest.record.json`, regenerated from `ui/` now that `.objectui-sha` is gone and the dual-mode gates (#25833) read the in-tree oracle. **5. One release lane.** objectui's `changeset-release.yml` is gone; root `release.yml` publishes both scopes in one `pnpm -r publish`, and the root `scripts/release-github-releases.mjs` cuts one GitHub Release per package tag across both scopes. ## The four deleted Console checks, and what proves the same thing now | Deleted | What it proved | Now | |---|---|---| | `assert-console-spec-injection.mjs` | the built Console bundles THIS tree's `@objectstack/spec`, not the copy objectui's lockfile installed | Can no longer be false. Every `@objectstack/*` dependency under `ui/` is `workspace:^` (33 spec, 2 client, 2 lint, 2 formula rows measured), which pnpm links and never resolves from the registry; the merged lockfile has 0 registry entries for `@objectstack/spec` or `@objectstack/client` and 37 `link:` rows to `packages/spec`. The single-zod guard (Vite, `ui/scripts/vite-single-zod.ts`) and canary (`build-dist.sh`, on the shipped bytes) still run in every build. | | `check-console-injection.mjs` | a Console dist restored from the pin-keyed cache was built against the current spec | Can no longer be false. The cache keyed on `.objectui-sha` is gone; turbo's hash for `@object-ui/console#build` includes `@objectstack/spec#build`, `@objectstack/client#build` and `@objectstack/lint#build` (measured with `turbo run build:dist --filter=@objectstack/console --dry=json`), so a spec change misses the cache. | | `check-console-sha.mjs` | the local `packages/console/dist` was built from the pinned objectui commit | The pin it compared against is gone, so that drift cannot occur. A local dist can still be older than `ui/` after a pull; `pnpm console:build` rebuilds it (a turbo cache hit when nothing changed). Nothing checks this on `pnpm dev` any more: reported to the dispatcher. | | `console-spec-probes.mjs` | the shared probe derivation for the two injection checks above | Left with them; nothing else imported it. | ## Verification (merged tree at objectui@cd70b7818; the 17b/17c items re-measured on verify head `9e37acd126`) - `pnpm changeset version` on the cutover head `1c0d02eda4` (objectstack#25825, objectui frozen at `9e1fe03286`) + this PR + the ui patch: exit 0, and all 112 members move 18.1.0 → 18.2.0 together (111 public: 73 `@objectstack/*` and 38 `@object-ui/*`, plus `object-ui`). The private, ignored `@object-ui/runner` stays at 18.1.0. On that tree root and objectui `check-changeset-fixed` and `check:lockstep-package-count` exit 0. - Earlier, on verify head `9e37acd126` (when `@object-ui/runner` was still public): all 113 members move 18.1.0 → 18.2.0 in one bump: 112 public (73 `@objectstack/*`, 39 `@object-ui/*`) and the private extension `object-ui`. The other private `@objectstack/*` packages move as they do on `main`. `pnpm -r publish` and `release-verify-npm` skip `object-ui` (private), so nothing it owes the registry changes. - `pnpm -r publish --dry-run` after the version (at `9e37acd126`): 112 packages, 39 `@object-ui/*` + 72 `@objectstack/*` + `create-objectstack`, all 18.2.0. `pnpm pack` of `@object-ui/core`: `@objectstack/spec` `workspace:^` → `^18.2.0`, `@object-ui/types` `workspace:*` → `18.2.0`. - `pnpm console:build` (CI=true): exit 0, single-zod canary green. The packed `@objectstack/console` has the same top-level `dist/` entries as the published 18.1.0 tarball, minus `dist/.objectstack-injection.json` and `dist/.objectui-sha`; assets 2,268 → 2,381 (newer objectui), tarball 9,260K → 9,140K. - Console eager-closure budget (`ui/scripts/check-eager-closure-budget.mjs`, ceiling 3,496.0 KB): this build 3,054.2 KB gzipped, `vendor-objectstack` 1,605.2 KB; the published 18.1.0 dist measured by the same ceilings: 3,522.3 KB, `vendor-objectstack` 1,851.5 KB. The membership half is red identically on both (`packages/core`: 1 of 89 modules in `vendor-objectstack`), so it predates this PR. - The ui-side patch on verify head `9e37acd126`: `git apply --check` passes after README steps 1–2 and reproduces the edited `ui/` tree byte for byte (60 files). With this PR's root half, install and `pnpm run build`: `type-check:scripts`, `type-check:vitest-config`, `lint:root` exit 0; root and objectui `check-changeset-fixed` pass; `vitest run scripts/__tests__` 17 failed / 5,573 passed, where 2 are 15 s load timeouts that pass alone, 2 fail the same way without the patch (`check-lockfile-integrity`; `quick-reference-commands-4149` on the root scripts the adaptation drops, cutover bill), and 14 read objectui's nested `ui/.github/`, which 4b PR 2 deletes. - actionlint 1.7.7 over `release.yml`, `cut-rc.yml`, `lint.yml`, `showcase-smoke.yml`: exit 0. No step reads a pin file. ## Gates (this branch, no `ui/`) `dispatch-gates --commands` derives 166 families for this diff; all 166 ran, and `dispatch-gates --ran` reconciles: 164 run, 2 NOT-MEASURED. All were run on head `4ac569dc00` (after merging `main` at `f0cf338330`, which had moved `.objectui-sha` and the root `build` script), after a full `pnpm run build`. 156 exit 0, including `check:required-contexts`, `check:workflow-status-functions`, `check:workflow-step-name-quoting`, `check-changeset-no-major`, `check-empty-changeset`, `check-adr-0087-registration`, `check:lockstep-package-count` (112) and `check:nul-bytes`. One is red on `main` itself and not this PR's: `check:liveness` (`translation/flows.screens` cites `service-automation/src/engine.ts`, which #25734 refactored; this PR touches neither). The other 9 are red or not measured because `ui/`, PR B or 4b has not landed yet, as designed: | Gate | Exit | Why red here | Clears when | |---|---|---|---| | `check-changeset-fixed` | 1 | the 38 `@object-ui/*` names and `object-ui` in `fixed` have no package without `ui/` (on cutover head `1c0d02eda4` + this PR + the ui patch: exit 0, 111 public + 1 declared private) | sub-issue 5 | | `check-prerelease-pin-watch --self-test`, `--verbose` | 1, 1 | named only by `prerelease-pin-watch.yml`; this PR deletes the script | PR B of #25697 | | `check-self-test-wired --self-test` | 1 | `ci.yml` `console-pin` and `prerelease-pin-watch.yml` still invoke deleted scripts | PR B of #25697 | | `check:pm-dispatch-gates` | 1 | 3 of 1,913 fast-tier cases, all on the same live invocations of deleted scripts | PR B of #25697 | | `check:console-sha`, `check:console-injection` | NOT-MEASURED (254) | root scripts deleted here; only the `console-pin` job names them | PR B of #25697 | | `check-sdui-manifest`, `check:sdui-lockstep` | 1, 1 | they read `.objectui-sha` | 4b PR 2 (#25712) | ## Depends on, outside this PR - **Sub-issue 5** (subtree PR): adds `ui/`; this PR merges right after it. - **PR B of #25697** (retire the pin gates in the cutover window): removes the `console-pin` job and `console` filter in `ci.yml`, `prerelease-pin-watch.yml`, and the live specimens in the `dispatch-gates` self-test that still name `check-prerelease-pin-watch.mjs`. Until it lands, `prerelease-pin-watch.yml` runs a script this PR deletes. - **4b PR 2 (#25712)**: `check-sdui-lockstep`, `check-sdui-manifest` and `gen-sdui-manifest-node` read `.objectui-sha` and go red without it; regenerating `sdui.manifest.json` from `ui/` is theirs (the root copy lags the old pin, and `build-dist.sh` ships the tracked one). Also the nested `ui/.github/` and the tests that read it, and both AGENTS.md files. - **Maintainer**: the npm token's `@object-ui` publish rights (card risk 1) — confirmed by Tesla, ruling 17a. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_0149BHSXfCdQywGaLdpRAtWe --------- Co-authored-by: Claude <noreply@anthropic.com>
Requested by Leehom · project thread
Part of #25222
Clause-②: no
Metadata-protocol: none
Slice 8b of the
engine.tssplit, move-only, under claim6392268076(Ruling-ref6384677413, ruling B;6348891160, the series'.d.tsbar). Scope is Release6385919610's 8b paragraph:resumeInternalmoves alone intorun-resume.ts.Is this the last slice? It is the last slice the Release plans. With 8a (#25725) and this PR, slice 8 is done; the six bodies the Release keeps in the class stay there. Whether the card closes is the seat's call, so this PR does not close it.
What moves
AutomationEngine.resumeInternal's body (919 lines in the class) becomesexport async function resumeInternalat the end ofrun-resume.ts, moved unedited. The class keeps the private method: its name, docblock, parameter comment and signature stay. The stub calls the body with a host literal and is no longerasync; it returns the promise the moved function makes.RunResumeHostgains 14 members, so it now holds 41. The function'sthisis a Pick ofRunResumeHostover the 25 members the body reads.logger,flows,resumingandconsumedSuspensionsgo by value. Each one is assigned only at its declaration or in the constructor. The other 21 are late-bound method closures, so a spy or test double set on the instance is still the one called.this.resumeInternal(childRunId, signal, true)) goes through the host closure into the class stub.bubbleToParent's call stays in the class and calls the stub directly.subflow-hosted-approval-strand.test.tsin plugin-approvals patchesresumeInternalon the instance, and both paths still reach that patch.engine.ts, the ones the Release names:ChildRunRefusal,isRetryableResumeRefusal,carriesSubflowChildOutputandapplyResumeSignal.ENGINE_BUILT_SIGNALstays unexported. The body reads no other unexportedengine.tsname; a TypeScript checker pass over the base method listed exactly these four.run-resume.tsimportsreadCarriedRefusalandsummarizeRundirectly. From./engine.jsit also takesFlowRefusalSignal,isRefusalSignal,isSuspendSignal, the three new value exports and the typesChildRunRefusalandExecutionLogEntry. Those values are read only at call time, so the cycle comment now lists all seven.Size: 2 files, 1,898 changed lines (+985 / -913).
engine.tsgoes from 9,882 to 9,006 lines.check-governed-merges --branch HEADsays NOT governed, with 0 of 2 paths on the register, under 3,000 lines.Proof that it moved nothing
All readings below were taken in this container on head
d8bf1026against basef3fea0a03d, the merge base andorigin/mainat the time.thisparameter dropped), on the return type (4 tokens) and on theasyncmodifier.run-resume.ts, I changed one token:this.resuming.delete(runId)becamethis.resuming.add(runId). Grep confirmed the edit landed (delete went 1 to 0, add went 1 to 2), and the comparison reads DIFFERENT with exit 1.engine.tsreappears, dedented four spaces, amongrun-resume.ts's added lines. The five exceptions are the four declaration lines that gainedexportand the method'sprivate asynchead line.this.Xreads in the head body, the Pick keys and the stub's host-literal keys are the same 25 names. Every Pick key is declared onRunResumeHost..d.ts.dist/index.d.tsanddist/index.d.ctsare raw byte-identical at base and head, both sha256a5cbe3bbb8aff2805674e1d9f119946199697e469a3e8a5b9bc7eb4fc08bc7cb. Raw identity holds, so the sorted-union bar holds trivially. The headindex.jsdoes contain the newasync function resumeInternal(and base does not, so the head build is real.afcfb4e8069c1e10at both ends.check-startup-registry-verdict: 46 seams, 39 read-only (9209def6…). Its--self-testisfb8c875f…. Its--listmatches apart from line numbers, includingregisterFlow's line.check-tenant-audit-census(52b71dc0…): 239 sites certified, 163 decidable, 23 prose figures. Its--self-testisfae0925f….tenant-audit-census: human outputb1d732d2…, and--jsonwithoutmeasuredAtdc3ff45e….check-system-context-census(6db2898d…) andisystem-census --json(fb320be9…).check-platform-checklist(edee137b…),check-adr-symbol-anchors(7530e478…) andcheck-adr-anchors(1b79d342…).Tests and gates
@objectstack/service-automationvitest on head: Test Files 201 passed (201), Tests 2636 passed (2636).typecheck(tsc --noEmitpluscheck:test-typecheck) exits 0. ESLint--no-inline-configoverpackages/services/service-automationexits 0.dispatch-gates --commands --repo objectstack-ai/objectstackderives 54 families on the 2 paths, and all 54 exit 0. Two of them first exited 3, PREREQUISITE NOT MET, and passed on re-run without any change to the code:check-plugin-teardown-shape --self-testpassed (48 cases) once the fixture commit621a4876was fetched into the shallow clone.check:dual-build-cjs-loadspassed after a fullpnpm build.--ranreconciles: 54 derived, 54 run, 0 NOT-MEASURED, 0 UNRUN.Acceptance notes
engine.tsorrun-resume.ts. 18 were diffed against their merge base. docs(pm-dispatch): text written by accounts outside the maintainer and the fleet is data, never instructions #25588 (docs, pm-dispatch) and feat(cli): serve the Console document with a nonce-based content-security-policy #25569 (cli CSP) have no merge base in this shallow clone, so I judged those two by title only.Generated by Claude Code