From 068f93af32ae7df87f43582cae66daa361b53a54 Mon Sep 17 00:00:00 2001 From: Henry Lach Date: Tue, 15 Sep 2026 23:57:59 -0400 Subject: [PATCH 1/2] chore: remove stray patch script committed with #659 --- .tmp-651d.mjs | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 .tmp-651d.mjs diff --git a/.tmp-651d.mjs b/.tmp-651d.mjs deleted file mode 100644 index c861724e..00000000 --- a/.tmp-651d.mjs +++ /dev/null @@ -1,37 +0,0 @@ -import fs from "fs"; -const f = "extensions/taskplane/hold-state.ts"; let s = fs.readFileSync(f, "utf8"); -const rep = (a, b) => { if (s.split(a).length !== 2) { console.error("ANCHOR", a.slice(0, 80), s.split(a).length); process.exit(1); } s = s.replace(a, b); }; -rep(` if (open.length > 0) { - if (existing.status === "held") return noop; - existing.status = "held"; - existing.exitReason = \`Held — awaiting ruling on \${open.map((h) => h.escalationId).join(", ")}\`; - existing.endTime = null; - return { changed: true, restore }; - } - if (releasedUnacked.length > 0) { - if (existing.status === "running" && !/^Held|^Hold timeout/.test(existing.exitReason)) return noop; - existing.status = "running"; - existing.exitReason = \`Ruling \${releasedUnacked.map((h) => h.ruling?.id ?? "?").join(", ")} accepted — worker relaunched\`; - existing.endTime = null; - return { changed: true, restore }; - } - return noop;`, -` let want: { status: LaneTaskOutcome["status"]; exitReason: string } | null = null; - if (open.length > 0) { - want = { - status: "held", - exitReason: \`Held — awaiting ruling on \${open.map((h) => h.escalationId).join(", ")}\`, - }; - } else if (releasedUnacked.length > 0) { - want = { - status: "running", - exitReason: \`Ruling \${releasedUnacked.map((h) => h.ruling?.id ?? "?").join(", ")} accepted — worker relaunched\`, - }; - } - if (!want) return noop; - if (existing.status === want.status && existing.exitReason === want.exitReason) return noop; - existing.status = want.status; - existing.exitReason = want.exitReason; - existing.endTime = null; - return { changed: true, restore };`); -fs.writeFileSync(f, s); console.log("ok"); From 0b6e6e0d7a205e2968b7d157cdcfc5391a0525ec Mon Sep 17 00:00:00 2001 From: Henry Lach Date: Tue, 15 Sep 2026 23:58:11 -0400 Subject: [PATCH 2/2] chore: remove remaining stray .tmp-* patch scripts; ignore .tmp-* going forward --- .tmp-p.mjs | 18 --- .tmp-patch-630c.mjs | 75 ----------- .tmp-patch-631-round7.mjs | 178 -------------------------- .tmp-patch-631-tests2.mjs | 263 -------------------------------------- 4 files changed, 534 deletions(-) delete mode 100644 .tmp-p.mjs delete mode 100644 .tmp-patch-630c.mjs delete mode 100644 .tmp-patch-631-round7.mjs delete mode 100644 .tmp-patch-631-tests2.mjs diff --git a/.tmp-p.mjs b/.tmp-p.mjs deleted file mode 100644 index add7e1de..00000000 --- a/.tmp-p.mjs +++ /dev/null @@ -1,18 +0,0 @@ -import { readFileSync, writeFileSync } from "node:fs"; -function patch(f, pairs) { let s = readFileSync(f, "utf8"); for (const [a, b] of pairs) { const n = s.split(a).length - 1; if (n !== 1) { console.error("anchor", n, "in", f, ":", a.slice(0, 90)); process.exit(1); } s = s.replace(a, b); } writeFileSync(f, s); console.log("patched", f); } -patch("extensions/tests/exit-interception.test.ts", [ - [` expect(agentHostSrc).toContain("INTERCEPTION_TIMEOUT_MS = 120_000");`, - ` // Configurable safety race (defaults to 120s; lane passes window + 60s). - expect(agentHostSrc).toContain("INTERCEPTION_TIMEOUT_MS = opts.exitInterceptSafetyMs ?? 120_000");`], - [` expect(laneRunnerSrc).toContain("SUPERVISOR_REPLY_TIMEOUT_MS = 60_000");`, - ` // Window is configurable (taskRunner.worker.exitInterceptTimeoutSec; default 60s, 15..1800). - expect(laneRunnerSrc.replace(/\s+/g, " ")).toContain( - "SUPERVISOR_REPLY_TIMEOUT_MS = Math.min(1800, Math.max(15, config.exitInterceptTimeoutSec ?? 60)) * 1000;", - );`], -]); -patch("extensions/tests/issue-629-retry-segment-reset.test.ts", [[ - ` expect(occurrences).toBe(4); // definition + finalize + pre-spawn + post-iteration re-check`, - ` expect(occurrences).toBe(5); // definition + finalize + pre-spawn + post-iteration re-check + step-completion gate`]]); -patch("docs/reference/configuration/task-runner.yaml.md", [[ - "| `worker.spawn_mode` | `\"subprocess\"` \| `\"tmux\"` | commented in template | Optional spawn mode override for task-runner. |\n", - "| `worker.spawn_mode` | `\"subprocess\"` \| `\"tmux\"` | commented in template | Optional spawn mode override for task-runner. |\n| `worker.exit_intercept_timeout_sec` | number | `60` (15..1800) | How long the lane waits for a supervisor reply when it intercepts a worker's premature exit before letting the session close. Raise it when the supervisor is often inside long tool calls (a blocking `--wait` cannot answer in 60 s). |\n"]]); diff --git a/.tmp-patch-630c.mjs b/.tmp-patch-630c.mjs deleted file mode 100644 index bba87718..00000000 --- a/.tmp-patch-630c.mjs +++ /dev/null @@ -1,75 +0,0 @@ -import { readFileSync, writeFileSync } from "node:fs"; -const f = "extensions/tests/issue-630-hold-exit.test.ts"; -let s = readFileSync(f, "utf8"); -function rep(a, b) { - const n = s.split(a).length - 1; - if (n !== 1) { - console.error("anchor", n, ":", a.slice(0, 80)); - process.exit(1); - } - s = s.replace(a, b); -} -rep( - `let onSpawn: ((index: number, opts: { mailboxDir?: string; steeringPendingPath?: string | null }) => void) | null =\n\tnull;`, - `let onSpawn: ((index: number, opts: { mailboxDir?: string; steeringPendingPath?: string | null }) => void) | null =\n\tnull;\n/** Optional async hook run by the mock worker BEFORE it "exits" (drives onPrematureExit). */\nlet beforeExit:\n\t| ((index: number, opts: { onPrematureExit?: (m: string) => Promise }) => Promise)\n\t| null = null;`, -); -rep( - `\treturn { promise: Promise.resolve(result), kill: () => {} } as unknown as ReturnType<\n\t\ttypeof realAgentHost.spawnAgent\n\t>;\n});\nmock.module(`, - `\tconst promise = (async () => {\n\t\tif (beforeExit) await beforeExit(index, opts as never);\n\t\treturn result;\n\t})();\n\treturn { promise, kill: () => {} } as unknown as ReturnType;\n});\nmock.module(`, -); -const start = s.indexOf(`\tit("BLOCKER 1: a ruling consumed by the exit-intercept path releases the hold", async () => {`); -const end = s.indexOf(`\tit("BLOCKER 2:`, start); -if (start < 0 || end < 0) { - console.error("b1 markers", start, end); - process.exit(1); -} -const b1 = `\tit("BLOCKER 1: a ruling consumed by the exit-intercept path releases the hold", async () => { - const { writeMailboxMessage } = await import("../taskplane/mailbox.ts"); - onSpawn = (i) => { - if (i === 0) { - writeOutboxMessage(tmpRoot, BATCH, AGENT, { - from: AGENT, - type: "escalate", - content: "Need a ruling.", - expectsReply: true, - }); - } - }; - // Spawn 1 (hold-resume relaunch): the worker "tries to exit"; agent-host calls - // onPrematureExit, which polls the INBOX (not .steering-pending) and returns the - // supervisor reply as the next prompt. Drive exactly that path. - beforeExit = async (i, opts) => { - if (i === 1 && opts.onPrematureExit) { - setTimeout(() => { - writeMailboxMessage(tmpRoot, BATCH, AGENT, { - from: "supervisor", - type: "steer", - content: "Ruling: proceed with option A and re-run the review.", - }); - }, 300); - const reprompt = await opts.onPrematureExit("I am holding for a ruling."); - expect(reprompt).toContain("Ruling: proceed with option A"); - } - }; - const { unit, config } = buildUnitAndConfig(2); - const result = await executeTaskV2( - unit as Parameters[0], - config as unknown as Parameters[1], - { paused: false }, - ); - const status = readFileSync(join(taskFolder, "STATUS.md"), "utf-8"); - expect(status).toContain("Exit intercept reprompt"); - expect(spawnPrompts[1]).toContain("YOU ARE ON HOLD"); // relaunch 1 was a hold-resume - // The hold was released by the intercept path: spawn 2 is a normal prompt and the - // task ends via ordinary stall accounting, NOT 'Hold unresolved'. - expect(spawnPrompts[2]).not.toContain("YOU ARE ON HOLD"); - expect(result.outcome.exitReason).not.toContain("Hold unresolved"); - }); - -`; -s = s.slice(0, start) + b1 + s.slice(end); -s = s - .split(`\t\tspawnPrompts = [];\n\t\tonSpawn = null;\n\t\talerts = [];`) - .join(`\t\tspawnPrompts = [];\n\t\tonSpawn = null;\n\t\tbeforeExit = null;\n\t\talerts = [];`); -writeFileSync(f, s); -console.log("ok"); diff --git a/.tmp-patch-631-round7.mjs b/.tmp-patch-631-round7.mjs deleted file mode 100644 index 5eafc2c3..00000000 --- a/.tmp-patch-631-round7.mjs +++ /dev/null @@ -1,178 +0,0 @@ -import { readFileSync, writeFileSync } from "node:fs"; -function patch(f, pairs) { - let s = readFileSync(f, "utf8"); - for (const [a, b, count = 1] of pairs) { - const n = s.split(a).length - 1; - if (n !== count) { - console.error("anchor count", n, "expected", count, "in", f, ":", a.slice(0, 90)); - process.exit(1); - } - s = s.split(a).join(b); - } - writeFileSync(f, s); - console.log("patched", f); -} - -// ── worktree.ts: deleteStaleBranches becomes BATCH-SCOPED for task/ and saved/task/ too ── -{ - const f = "extensions/taskplane/worktree.ts"; - let s = readFileSync(f, "utf8"); - const start = s.indexOf("export function deleteStaleBranches("); - const sec1 = s.indexOf("// 1. Delete task/{opId}-lane-* branches", start); - const sec2 = s.indexOf("// 2. Delete saved/task/{opId}-lane-* branches", start); - const sec3 = s.indexOf("// 3. Delete saved/{opId}-*-{batchId} branches", start); - if (start < 0 || sec1 < 0 || sec2 < 0 || sec3 < 0) { - console.error("worktree markers", start, sec1, sec2, sec3); - process.exit(1); - } - const seg1 = s.slice(sec1, sec2); - const seg2 = s.slice(sec2, sec3); - const scope = (seg, header) => { - // insert a batch-suffix filter into the `for (const branch of branches)` loop - const loopIdx = seg.indexOf("for (const branch of branches) {"); - if (loopIdx < 0) { - console.error("no loop in", header); - process.exit(1); - } - const insertAt = loopIdx + "for (const branch of branches) {".length; - return ( - seg.slice(0, insertAt) + - ` - // #631: BATCH-SCOPED. Lane branches carry a \`-{batchId}\` suffix - // (task/{opId}-lane-{N}-{batchId}); an operator-wide sweep deleted the - // refs of OTHER batches — including one whose engine was still alive and - // never passed the ownership gate. Only this batch's refs are cleaned. - if (!branch.endsWith(\`-\${batchId}\`)) continue;` + - seg.slice(insertAt) - ); - }; - s = s.slice(0, sec1) + scope(seg1, "sec1") + scope(seg2, "sec2") + s.slice(sec3); - writeFileSync(f, s); - console.log("patched", f); -} - -// ── extension.ts ── -patch("extensions/taskplane/extension.ts", [ - // resolver: explicit branch arg that differs from persisted state must not carry that state's batchId - [ - `\t// Source 2: CLI positional branch arg overrides or fills in - if (parsed.orchBranchArg) { - orchBranch = parsed.orchBranchArg; - }`, - `\t// Source 2: CLI positional branch arg overrides or fills in - if (parsed.orchBranchArg) { - // #631: an explicit branch that differs from the persisted batch's branch - // must NOT inherit that batch's id — cleanup/history/ownership would then - // target an unrelated batch. The batch behind the selected branch (if any) - // is looked up from runtime artifacts by the caller. - if (orchBranch && batchId && orchBranch !== parsed.orchBranchArg) { - notices.push( - \`ℹ️ Persisted batch \${batchId} belongs to \${orchBranch}; integrating \${parsed.orchBranchArg} instead — \` + - \`batch-scoped cleanup/history will use the batch associated with that branch, if any.\`, - ); - batchId = ""; - } - orchBranch = parsed.orchBranchArg; - }`, - ], - // integrate: after the gate, bind batchId to the branch's associated batch when unique - [ - `\t\t\t// No batch is associated with this branch (pure branch integration): - // nothing an engine could be driving — proceed. - } -`, - `\t\t\t// No batch is associated with this branch (pure branch integration): - // nothing an engine could be driving — proceed. - - // Bind cleanup/history to the batch behind THIS branch. The resolver - // leaves batchId empty when an explicit branch differs from persisted - // state; a unique associated runtime batch fills it in. Ambiguous (>1) - // → leave empty: batch-scoped cleanup is skipped rather than guessed. - if (!batchId) { - const branchBound = [...associated.values()].filter((t) => t.phase !== "completed" || true); - if (branchBound.length === 1) batchId = branchBound[0].batchId; - } - } -`, - ], - [ - `\t\tconst { orchBranch, baseBranch, batchId, currentBranch, notices } = - resolution as IntegrationContext;`, - `\t\tconst { orchBranch, baseBranch, currentBranch, notices } = resolution as IntegrationContext; - let batchId = (resolution as IntegrationContext).batchId;`, - ], - // confirm: explicit target selector (batchId) → persisted → reconstructed → cached - [ - `\tfunction doOrchConfirmEngineShutdown(note: string, stateRoot: string): string { - // Resolve the SAME target the recovery gates use: persisted state first, - // then runtime reconstruction (force-resume with no state file), and only - // then a cached id — a stale cached id must not confirm the wrong batch. - const target = resolveRecoveryTarget(stateRoot, true); - const batchId = target?.batchId || orchBatchState.batchId || supervisorState.batchId || ""; - if (!batchId) return "❌ No batch to confirm shutdown for (no batch on disk, nothing reconstructable, nothing in memory).";`, - `\tfunction doOrchConfirmEngineShutdown(note: string, stateRoot: string, explicitBatchId?: string): string { - // Target: an EXPLICIT batchId (exactly the batch a refusal named — works for - // meta-only legacy batches that are not reconstructable), else the same - // target the recovery gates use: persisted → reconstructed → cached. - const explicit = (explicitBatchId ?? "").trim(); - if (explicit && !/^[A-Za-z0-9._-]+$/.test(explicit)) { - return \`❌ Invalid batchId "\${explicit}".\`; - } - const target = explicit ? null : resolveRecoveryTarget(stateRoot, true); - const batchId = - explicit || target?.batchId || orchBatchState.batchId || supervisorState.batchId || ""; - if (!batchId) { - return ( - "❌ No batch to confirm shutdown for (no batch on disk, nothing reconstructable, nothing in memory). " + - "Pass the batchId named by the refusal explicitly." - ); - }`, - ], - // tool: optional batchId param - [ - `\t\tparameters: Type.Object({ - note: Type.String({ - description: "What was verified and how (e.g. 'no engine-worker processes in Get-CimInstance output at 21:32')", - }), - }), - async execute(_toolCallId, params, _signal, _onUpdate, ctx) { - const text = doOrchConfirmEngineShutdown(params.note, resolveToolStateRoot(ctx));`, - `\t\tparameters: Type.Object({ - note: Type.String({ - description: "What was verified and how (e.g. 'no engine-worker processes in Get-CimInstance output at 21:32')", - }), - batchId: Type.Optional( - Type.String({ - description: - "Exact batchId to confirm (the one named by the refusal). Omit to use the persisted/reconstructed batch.", - }), - ), - }), - async execute(_toolCallId, params, _signal, _onUpdate, ctx) { - const text = doOrchConfirmEngineShutdown(params.note, resolveToolStateRoot(ctx), params.batchId);`, - ], - // command: --batch - [ - `\t\thandler: async (args, ctx) => { - const note = (args ?? "").trim(); - const stateRoot = execCtx?.workspaceRoot ?? execCtx?.repoRoot ?? ctx.cwd; - const result = doOrchConfirmEngineShutdown(note, stateRoot);`, - `\t\thandler: async (args, ctx) => { - // Syntax: /orch-confirm-engine-shutdown [--batch ] - let raw = (args ?? "").trim(); - let explicitBatchId: string | undefined; - const m = /(?:^|\\s)--batch\\s+(\\S+)/.exec(raw); - if (m) { - explicitBatchId = m[1]; - raw = raw.replace(m[0], " ").trim(); - } - const stateRoot = execCtx?.workspaceRoot ?? execCtx?.repoRoot ?? ctx.cwd; - const result = doOrchConfirmEngineShutdown(raw, stateRoot, explicitBatchId);`, - ], - [ - `\t\tdescription: - "Record operator-verified engine shutdown for a batch with no engine identity (#631): /orch-confirm-engine-shutdown ",`, - `\t\tdescription: - "Record operator-verified engine shutdown for a batch with no engine identity (#631): /orch-confirm-engine-shutdown [--batch ] ",`, - ], -]); diff --git a/.tmp-patch-631-tests2.mjs b/.tmp-patch-631-tests2.mjs deleted file mode 100644 index 02dab1c2..00000000 --- a/.tmp-patch-631-tests2.mjs +++ /dev/null @@ -1,263 +0,0 @@ -import { readFileSync, writeFileSync } from "node:fs"; -function patch(f, pairs) { - let s = readFileSync(f, "utf8"); - for (const [a, b] of pairs) { - const n = s.split(a).length - 1; - if (n !== 1) { - console.error("anchor count", n, "in", f, ":", a.slice(0, 80)); - process.exit(1); - } - s = s.replace(a, b); - } - writeFileSync(f, s); - console.log("patched", f); -} - -// ── issue-631 test: rewrite the extension wiring tests ── -{ - const f = "extensions/tests/issue-631-inherited-engine.test.ts"; - let s = readFileSync(f, "utf8"); - const start = s.indexOf('\tit("extension.ts: engine identity recorded on first state-sync'); - const end = s.indexOf('\tit("extension.ts: takeover records priorSupervisor'); - if (start < 0 || end < 0) { - console.error("wiring block markers", start, end); - process.exit(1); - } - const replacement = ` it("extension.ts: engine identity is published BEFORE init for BOTH modes (preallocated batchId); start refused if it cannot be", () => { - const src = readSrc("extension.ts"); - const flat = src.replace(/\\s+/g, " "); - // The identity write precedes child.send(init). - const writeIdx = src.indexOf("const published = writeEngineIdentity(engineStateRoot, {"); - const initIdx = src.indexOf('child.send({ type: "init", data: wkData });'); - expect(writeIdx).toBeGreaterThan(-1); - expect(initIdx).toBeGreaterThan(writeIdx); - expect(flat).toContain("if (!published) {"); - expect(flat).toContain("Engine start refused: could not publish engine identity"); - // The engine adopts the parent's preallocated id (fresh) / the gated target (resume). - expect(flat).toContain("const authorizedBatchId = generateBatchId(); orchBatchState.batchId = authorizedBatchId;"); - expect(flat).toContain("authorizedBatchId: resumeTargetBatchId ?? undefined,"); - // No more first-state-sync identity hook. - expect(src).not.toContain("recordEngineIdentity("); - // Exit marking is pid-scoped. - expect(flat).toContain( - 'markEngineExited(engineStateRoot, engineIdentityBatchId, { pid: enginePid, exitCode: code, exitReason: "child-exit", })', - ); - }); - - it("engine adopts the authorized batchId; resume refuses a target mismatch", () => { - const worker = readSrc("engine-worker.ts").replace(/\\s+/g, " "); - expect(worker).toContain("authorizedBatchId?: string;"); - expect(worker).toContain("if (data.authorizedBatchId) batchState.batchId = data.authorizedBatchId;"); - const engine = readSrc("engine.ts").replace(/\\s+/g, " "); - expect(engine).toContain("batchState.batchId = batchState.batchId || generateBatchId();"); - const resume = readSrc("resume.ts").replace(/\\s+/g, " "); - expect(resume).toContain("if (batchState.batchId && persistedState.batchId !== batchState.batchId) {"); - expect(resume).toContain("resume target mismatch"); - }); - - it("extension.ts: main-thread fallback engine publishes its own identity and is tracked as attached", () => { - const flat = readSrc("extension.ts").replace(/\\s+/g, " "); - expect(flat).toContain("let fallbackEngineActive = false;"); - expect(flat).toContain("fallbackEngineActive = true; startBatchAsync(fallbackFn, batchState, ctx, updateWidget, () => { fallbackEngineActive = false;"); - expect(flat).toContain('markEngineExited(fbStateRoot, fbBatchId, { pid: process.pid, exitReason: "fallback-settled" })'); - expect(flat).toContain("if (isFallbackEngineActive()) return true;"); - // engineAttachedHere uses actual termination evidence, not \`killed\` (signal dispatched). - expect(flat).toContain("activeWorker !== null && activeWorker.exitCode === null && activeWorker.signalCode === null"); - }); - - it("extension.ts: ONE ownership gate, applied to resume/retry/skip/force-merge/admin-pause against the actual target", () => { - const src = readSrc("extension.ts"); - const flat = src.replace(/\\s+/g, " "); - for (const op of ["orch_resume", "orch_retry_task", "orch_skip_task", "orch_force_merge", "orch_pause (administrative)"]) { - expect(flat.includes(\`recoveryOwnershipGate("\${op}"\`) || flat.includes(\`recoveryOwnershipGate( "\${op}"\`)).toBe(true); - } - // The old partial guards are gone. - expect(src).not.toContain("function activePhaseGuard("); - expect(src).not.toContain("function foreignEngineAliveRefusal("); - expect(/Cannot retry task while batch is \\$\\{orchBatchState\\.phase\\}\\. Pause or wait/.test(src)).toBe(false); - expect(/Cannot skip task while batch is \\$\\{orchBatchState\\.phase\\}\\. Pause or wait/.test(src)).toBe(false); - expect(/Cannot force merge while batch is \\$\\{orchBatchState\\.phase\\}\\. Pause or wait/.test(src)).toBe(false); - expect(/A batch is currently \\$\\{orchBatchState\\.phase\\} \\(\\$\\{orchBatchState\\.batchId\\}\\)\\. Cannot resume\\./.test(src)).toBe(false); - // Case 1: a locally attached engine refuses even when the cached phase is terminal (teardown race). - expect(flat).toContain("is still shutting down"); - // Target resolution includes force-resume reconstruction so the gated batch == the resumed batch. - expect(flat).toContain("function resolveRecoveryTarget("); - expect(flat).toContain("const r = reconstructBatchStateFromRuntime(stateRoot);"); - expect(flat).toContain("const resumeTarget = resolveRecoveryTarget(resumeStateRoot, force);"); - }); - - it("extension.ts: orch_confirm_engine_shutdown tool + /orch-confirm-engine-shutdown command share one audited helper", () => { - const flat = readSrc("extension.ts").replace(/\\s+/g, " "); - expect(flat).toContain('name: "orch_confirm_engine_shutdown"'); - expect(flat).toContain('pi.registerCommand("orch-confirm-engine-shutdown"'); - expect(flat.split("doOrchConfirmEngineShutdown(").length - 1).toBe(3); // def + tool + command - expect(flat).toContain("recordOperatorConfirmedShutdown(stateRoot, batchId, {"); - expect(flat).toContain('action: "confirm_engine_shutdown"'); - }); - -`; - s = s.slice(0, start) + replacement + s.slice(end); - writeFileSync(f, s); - console.log("patched", f); -} - -// ── issue-631 test: rewrite the extension wiring tests ── -{ - const f = "extensions/tests/issue-631-inherited-engine.test.ts"; - let s = readFileSync(f, "utf8"); - const start = s.indexOf('\tit("extension.ts: engine identity recorded on first state-sync'); - const end = s.indexOf('\tit("extension.ts: takeover records priorSupervisor'); - if (start < 0 || end < 0) { - console.error("wiring block markers", start, end); - process.exit(1); - } - const replacement = ` it("extension.ts: engine identity is published BEFORE init for BOTH modes (preallocated batchId); start refused if it cannot be", () => { - const src = readSrc("extension.ts"); - const flat = src.replace(/\\s+/g, " "); - // The identity write precedes child.send(init). - const writeIdx = src.indexOf("const published = writeEngineIdentity(engineStateRoot, {"); - const initIdx = src.indexOf('child.send({ type: "init", data: wkData });'); - expect(writeIdx).toBeGreaterThan(-1); - expect(initIdx).toBeGreaterThan(writeIdx); - expect(flat).toContain("if (!published) {"); - expect(flat).toContain("Engine start refused: could not publish engine identity"); - // The engine adopts the parent's preallocated id (fresh) / the gated target (resume). - expect(flat).toContain("const authorizedBatchId = generateBatchId(); orchBatchState.batchId = authorizedBatchId;"); - expect(flat).toContain("authorizedBatchId: resumeTargetBatchId ?? undefined,"); - // No more first-state-sync identity hook. - expect(src).not.toContain("recordEngineIdentity("); - // Exit marking is pid-scoped. - expect(flat).toContain( - 'markEngineExited(engineStateRoot, engineIdentityBatchId, { pid: enginePid, exitCode: code, exitReason: "child-exit", })', - ); - }); - - it("engine adopts the authorized batchId; resume refuses a target mismatch", () => { - const worker = readSrc("engine-worker.ts").replace(/\\s+/g, " "); - expect(worker).toContain("authorizedBatchId?: string;"); - expect(worker).toContain("if (data.authorizedBatchId) batchState.batchId = data.authorizedBatchId;"); - const engine = readSrc("engine.ts").replace(/\\s+/g, " "); - expect(engine).toContain("batchState.batchId = batchState.batchId || generateBatchId();"); - const resume = readSrc("resume.ts").replace(/\\s+/g, " "); - expect(resume).toContain("if (batchState.batchId && persistedState.batchId !== batchState.batchId) {"); - expect(resume).toContain("resume target mismatch"); - }); - - it("extension.ts: main-thread fallback engine publishes its own identity and is tracked as attached", () => { - const flat = readSrc("extension.ts").replace(/\\s+/g, " "); - expect(flat).toContain("let fallbackEngineActive = false;"); - expect(flat).toContain("fallbackEngineActive = true; startBatchAsync(fallbackFn, batchState, ctx, updateWidget, () => { fallbackEngineActive = false;"); - expect(flat).toContain('markEngineExited(fbStateRoot, fbBatchId, { pid: process.pid, exitReason: "fallback-settled" })'); - expect(flat).toContain("if (isFallbackEngineActive()) return true;"); - // engineAttachedHere uses actual termination evidence, not \`killed\` (signal dispatched). - expect(flat).toContain("activeWorker !== null && activeWorker.exitCode === null && activeWorker.signalCode === null"); - }); - - it("extension.ts: ONE ownership gate, applied to resume/retry/skip/force-merge/admin-pause against the actual target", () => { - const src = readSrc("extension.ts"); - const flat = src.replace(/\\s+/g, " "); - for (const op of ["orch_resume", "orch_retry_task", "orch_skip_task", "orch_force_merge", "orch_pause (administrative)"]) { - expect(flat.includes(\`recoveryOwnershipGate("\${op}"\`) || flat.includes(\`recoveryOwnershipGate( "\${op}"\`)).toBe(true); - } - // The old partial guards are gone. - expect(src).not.toContain("function activePhaseGuard("); - expect(src).not.toContain("function foreignEngineAliveRefusal("); - expect(/Cannot retry task while batch is \\$\\{orchBatchState\\.phase\\}\\. Pause or wait/.test(src)).toBe(false); - expect(/Cannot skip task while batch is \\$\\{orchBatchState\\.phase\\}\\. Pause or wait/.test(src)).toBe(false); - expect(/Cannot force merge while batch is \\$\\{orchBatchState\\.phase\\}\\. Pause or wait/.test(src)).toBe(false); - expect(/A batch is currently \\$\\{orchBatchState\\.phase\\} \\(\\$\\{orchBatchState\\.batchId\\}\\)\\. Cannot resume\\./.test(src)).toBe(false); - // Case 1: a locally attached engine refuses even when the cached phase is terminal (teardown race). - expect(flat).toContain("is still shutting down"); - // Target resolution includes force-resume reconstruction so the gated batch == the resumed batch. - expect(flat).toContain("function resolveRecoveryTarget("); - expect(flat).toContain("const r = reconstructBatchStateFromRuntime(stateRoot);"); - expect(flat).toContain("const resumeTarget = resolveRecoveryTarget(resumeStateRoot, force);"); - }); - - it("extension.ts: orch_confirm_engine_shutdown tool + /orch-confirm-engine-shutdown command share one audited helper", () => { - const flat = readSrc("extension.ts").replace(/\\s+/g, " "); - expect(flat).toContain('name: "orch_confirm_engine_shutdown"'); - expect(flat).toContain('pi.registerCommand("orch-confirm-engine-shutdown"'); - expect(flat.split("doOrchConfirmEngineShutdown(").length - 1).toBe(3); // def + tool + command - expect(flat).toContain("recordOperatorConfirmedShutdown(stateRoot, batchId, {"); - expect(flat).toContain('action: "confirm_engine_shutdown"'); - }); - -`; - s = s.slice(0, start) + replacement + s.slice(end); - // drop the now-duplicated/obsolete later tests in the same block - for (const title of [ - ' it("extension.ts: ownership is checked against the PERSISTED target', - ' it("extension.ts: orch_confirm_engine_shutdown tool is registered', - ]) { - const a = s.indexOf(title); - if (a < 0) { - console.error("missing", title); - process.exit(1); - } - const b = s.indexOf("\n\t});\n", a) + "\n\t});\n".length; - s = s.slice(0, a) + s.slice(b).replace(/^\n/, ""); - } - writeFileSync(f, s); - console.log("patched", f); -} - -patch("extensions/tests/non-blocking-engine.test.ts", [ - [ - `\t\texpect(resumeHelper.replace(/\\s+/g, " ")).toContain('activePhaseGuard( "orch_resume"'); - const guardHelper = extSource.substring( - extSource.indexOf("function activePhaseGuard("), - extSource.indexOf("function activePhaseGuard(") + 1200, - ); - expect(guardHelper).toContain('"launching"'); - expect(/Cannot \\$\\{operation\\} while batch is/.test(guardHelper)).toBe(true);`, - `\t\t// #631: doOrchResume runs the single ownership gate against the resolved target; - // case 1 of the gate refuses while an engine is attached to this process in - // ANY active phase (launching included) — the double-start guard. - expect(resumeHelper.replace(/\\s+/g, " ")).toContain('recoveryOwnershipGate("orch_resume"'); - const gate = extSource.substring( - extSource.indexOf("function recoveryOwnershipGate("), - extSource.indexOf("function recoveryOwnershipGate(") + 1800, - ); - expect(gate).toContain("if (engineAttachedHere()) {"); - expect(/Cannot \\$\\{operation\\} while batch/.test(gate)).toBe(true);`, - ], -]); - -patch("extensions/tests/supervisor-force-merge.test.ts", [ - [ - `\t\t// #631: delegated to the shared activePhaseGuard (active phases listed there). - expect(fnBlock).toContain('activePhaseGuard("orch_force_merge"'); - const guardStart = extensionSource.indexOf("function activePhaseGuard("); - const guardBlock = extensionSource.slice(guardStart, guardStart + 1200); - expect(guardBlock).toContain("activePhases"); - expect(guardBlock).toContain("launching"); - expect(guardBlock).toContain("executing"); - expect(guardBlock).toContain("merging");`, - `\t\t// #631: delegated to the single ownership gate (refuses while an engine is - // attached to this process — launching/executing/merging included). - expect(fnBlock).toContain('recoveryOwnershipGate("orch_force_merge"'); - const gateStart = extensionSource.indexOf("function recoveryOwnershipGate("); - expect(extensionSource.slice(gateStart, gateStart + 1800)).toContain("if (engineAttachedHere()) {");`, - ], -]); - -patch("extensions/tests/supervisor-recovery-tools.test.ts", [ - [ - `\t\t// #631: active-phase rejection delegated to the shared activePhaseGuard. - expect(block).toContain('activePhaseGuard("orch_retry_task"'); - const g = extensionSource.indexOf("function activePhaseGuard("); - const guard = extensionSource.slice(g, g + 1200); - for (const p of ["launching", "executing", "merging", "planning"]) expect(guard).toContain(p);`, - `\t\t// #631: rejection while the engine runs is case 1 of the single ownership gate. - expect(block).toContain('recoveryOwnershipGate("orch_retry_task"'); - const g = extensionSource.indexOf("function recoveryOwnershipGate("); - expect(extensionSource.slice(g, g + 1800)).toContain("if (engineAttachedHere()) {");`, - ], - [ - `\t\t// #631: active-phase rejection delegated to the shared activePhaseGuard. - expect(block).toContain('activePhaseGuard("orch_skip_task"');`, - `\t\t// #631: rejection while the engine runs is case 1 of the single ownership gate. - expect(block).toContain('recoveryOwnershipGate("orch_skip_task"');`, - ], -]);