pi-subagents 0.81.0 → 0.82.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/README.md +1 -1
- package/bundle/agents.js +3 -3
- package/bundle/child-tool-plan.js +2 -2
- package/bundle/{chunk-L5ZHE4L4.js → chunk-3JCDWF4V.js} +4 -4
- package/bundle/{chunk-LSRUTHT7.js → chunk-43SCHIMD.js} +1 -1
- package/bundle/{chunk-VJHOELQP.js → chunk-46XKCPJR.js} +193 -81
- package/bundle/{chunk-G5DKFLLI.js → chunk-4SDU2BZX.js} +15 -10
- package/bundle/{chunk-2ZSNH26H.js → chunk-4Y2ROR7L.js} +7 -7
- package/bundle/{chunk-V2JWDB5U.js → chunk-52UBALJL.js} +2 -2
- package/bundle/{chunk-3DC5KBVP.js → chunk-5TYMSZX3.js} +1 -1
- package/bundle/{chunk-NNLASTQE.js → chunk-6XJB7PIX.js} +20 -6
- package/bundle/{chunk-ZBC44JJ3.js → chunk-CIZQXJ5Q.js} +22 -9
- package/bundle/{chunk-KSWQVGDW.js → chunk-FXUXCX2K.js} +225 -18
- package/bundle/{chunk-563BHAZ5.js → chunk-G4GZD3OJ.js} +35 -26
- package/bundle/{chunk-ARRKBB2B.js → chunk-GJECHSAR.js} +2 -2
- package/bundle/{chunk-V3BIUPLU.js → chunk-IVAE5Z6Q.js} +256 -52
- package/bundle/{chunk-V6MR5TOQ.js → chunk-JYUKW2SY.js} +25 -19
- package/bundle/{chunk-BJN5LUQY.js → chunk-OYF6AFDY.js} +1 -1
- package/bundle/{chunk-CEKS3TFO.js → chunk-PBK2I7WY.js} +6 -6
- package/bundle/{chunk-TUWLXTAM.js → chunk-PDZWJCHD.js} +681 -320
- package/bundle/{chunk-EYNJ6VL6.js → chunk-PLCCBLPY.js} +2 -2
- package/bundle/{chunk-XMFLCKMQ.js → chunk-QE4AGIMG.js} +339 -132
- package/bundle/{chunk-74RT5YQE.js → chunk-RMQFMMAT.js} +123 -33
- package/bundle/{chunk-WSBNENFS.js → chunk-UCPP4GNU.js} +14 -4
- package/bundle/{chunk-2XYWN7QJ.js → chunk-UTT254JE.js} +2 -2
- package/bundle/{chunk-BPS2AGBZ.js → chunk-VSUSLDNW.js} +93 -52
- package/bundle/{chunk-ZP3HODFH.js → chunk-XSWOTIA3.js} +1 -1
- package/bundle/{chunk-3IF2PGW7.js → chunk-YKEWIB4M.js} +1 -1
- package/bundle/{chunk-26C3WLYQ.js → chunk-ZIV4J4HG.js} +498 -274
- package/bundle/control-channel.js +2 -2
- package/bundle/index.js +1 -1
- package/bundle/intercom-bridge.js +2 -2
- package/bundle/preflight.js +8 -8
- package/bundle/project-panes.js +3 -3
- package/docs/agents.md +37 -7
- package/docs/configuration.md +9 -1
- package/docs/tool-reference.md +3 -1
- package/docs/workflows.md +16 -0
- package/package.json +2 -2
- package/skills/council-mode/SKILL.md +1 -4
- package/skills/pi-subagents/SKILL.md +130 -107
- package/skills/pi-subagents/references/orchestration.md +124 -0
- package/skills/pi-subagents/references/prompting-and-roles.md +96 -295
- package/src/agents/agent-management.js +3 -3
- package/src/agents/agent-memory.js +3 -1
- package/src/agents/agents.js +6 -6
- package/src/agents/frontmatter.d.ts +2 -0
- package/src/agents/frontmatter.js +15 -1
- package/src/agents/skills.js +2 -1
- package/src/extension/config.js +3 -0
- package/src/extension/herdr-pi-bridge.js +17 -10
- package/src/extension/index.js +82 -2
- package/src/extension/reply-workflow-script.js +5 -2
- package/src/extension/schemas.js +3 -3
- package/src/extension/subagent-guide.js +1 -2
- package/src/intercom/native-supervisor-channel.js +20 -0
- package/src/missions/lifecycle.js +7 -1
- package/src/runs/background/active-async-capacity.d.ts +1 -0
- package/src/runs/background/active-async-capacity.js +9 -3
- package/src/runs/background/async-execution.js +20 -10
- package/src/runs/background/async-job-tracker.d.ts +6 -1
- package/src/runs/background/async-job-tracker.js +9 -4
- package/src/runs/background/async-status.d.ts +4 -0
- package/src/runs/background/async-status.js +22 -3
- package/src/runs/background/await-async-run.js +3 -7
- package/src/runs/background/boot-id.d.ts +12 -0
- package/src/runs/background/boot-id.js +47 -0
- package/src/runs/background/interrupted-elsewhere.d.ts +22 -0
- package/src/runs/background/interrupted-elsewhere.js +68 -0
- package/src/runs/background/notify.d.ts +2 -0
- package/src/runs/background/notify.js +13 -0
- package/src/runs/background/result-delivery-ownership.d.ts +6 -0
- package/src/runs/background/result-delivery-ownership.js +19 -1
- package/src/runs/background/result-watcher.d.ts +3 -1
- package/src/runs/background/result-watcher.js +24 -8
- package/src/runs/background/run-child-session.d.ts +1 -6
- package/src/runs/background/run-child-session.js +1 -1
- package/src/runs/background/run-status.js +2 -1
- package/src/runs/background/stale-run-reconciler.d.ts +25 -0
- package/src/runs/background/stale-run-reconciler.js +52 -13
- package/src/runs/background/subagent-runner-bootstrap.js +3 -0
- package/src/runs/background/subagent-runner.d.ts +4 -0
- package/src/runs/background/subagent-runner.js +13 -5
- package/src/runs/background/subagent-wait.d.ts +1 -1
- package/src/runs/background/subagent-wait.js +6 -1
- package/src/runs/background/terminal-run-index.d.ts +2 -0
- package/src/runs/background/terminal-run-index.js +44 -3
- package/src/runs/foreground/async-stop-action.js +3 -1
- package/src/runs/foreground/execution.js +6 -3
- package/src/runs/foreground/foreground-history.d.ts +16 -2
- package/src/runs/foreground/foreground-history.js +133 -31
- package/src/runs/foreground/subagent-executor.d.ts +11 -0
- package/src/runs/foreground/subagent-executor.js +277 -74
- package/src/runs/shared/child-launch.d.ts +2 -2
- package/src/runs/shared/child-session.d.ts +3 -2
- package/src/runs/shared/child-session.js +51 -8
- package/src/runs/shared/child-tool-plan.d.ts +7 -0
- package/src/runs/shared/child-tool-plan.js +21 -6
- package/src/runs/shared/herdr-connection.d.ts +17 -8
- package/src/runs/shared/herdr-connection.js +19 -7
- package/src/runs/shared/herdr-external-adapters.d.ts +3 -2
- package/src/runs/shared/herdr-external-adapters.js +1 -1
- package/src/runs/shared/herdr-machine.d.ts +12 -2
- package/src/runs/shared/herdr-machine.js +55 -9
- package/src/runs/shared/herdr-pane-host.d.ts +88 -0
- package/src/runs/shared/herdr-pane-host.js +155 -0
- package/src/runs/shared/herdr-placed-run.d.ts +27 -150
- package/src/runs/shared/herdr-placed-run.js +48 -395
- package/src/runs/shared/local-machine-access.d.ts +5 -0
- package/src/runs/shared/local-machine-access.js +28 -0
- package/src/runs/shared/orca-progress-tabs.d.ts +0 -1
- package/src/runs/shared/orca-progress-tabs.js +1 -24
- package/src/runs/shared/parallel-utils.d.ts +1 -1
- package/src/runs/shared/placed-run-owner.d.ts +49 -0
- package/src/runs/shared/placed-run-owner.js +93 -0
- package/src/runs/shared/placement-host.d.ts +99 -0
- package/src/runs/shared/placement-host.js +157 -0
- package/src/runs/shared/rex-machine.d.ts +25 -0
- package/src/runs/shared/rex-machine.js +83 -0
- package/src/runs/shared/rex-pane-host.d.ts +62 -0
- package/src/runs/shared/rex-pane-host.js +327 -0
- package/src/shared/completion-owner.d.ts +5 -0
- package/src/shared/completion-owner.js +5 -0
- package/src/shared/session-identity.d.ts +2 -0
- package/src/shared/session-identity.js +26 -0
- package/src/shared/types.d.ts +45 -6
- package/src/tui/fleet.d.ts +1 -0
- package/src/tui/fleet.js +25 -15
- package/src/tui/render.d.ts +6 -0
- package/src/tui/render.js +3 -3
- package/src/tui/subagent-messages.js +1 -0
- package/src/workflows/scripted-workflow.d.ts +1 -1
- package/src/workflows/workflow-auto-resume.d.ts +32 -0
- package/src/workflows/workflow-auto-resume.js +102 -0
- package/src/workflows/workflow-launch-record.d.ts +27 -0
- package/src/workflows/workflow-launch-record.js +48 -0
- package/src/workflows/workflow-resume-claim.d.ts +82 -0
- package/src/workflows/workflow-resume-claim.js +210 -0
- package/src/workflows/workflow-resume.d.ts +56 -0
- package/src/workflows/workflow-resume.js +106 -0
- package/src/workflows/workflow-reuse.d.ts +15 -9
- package/src/workflows/workflow-reuse.js +77 -14
- package/src/workflows/workflow-revival.d.ts +2 -0
- package/src/workflows/workflow-revival.js +2 -1
- package/src/workflows/workflow-stop-cause.d.ts +6 -0
- package/src/workflows/workflow-stop-cause.js +8 -0
- package/skills/pi-subagents/references/constraints-and-recipes.md +0 -74
- package/skills/pi-subagents/references/execution-controls.md +0 -563
- package/skills/pi-subagents/references/management-authoring-rpc.md +0 -165
- package/skills/pi-subagents/references/multi-lane-orchestration.md +0 -61
- package/skills/pi-subagents/references/review-and-validation.md +0 -73
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PROJECT_SUBAGENTS_RELATIVE_DIR
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5TYMSZX3.js";
|
|
4
4
|
import {
|
|
5
5
|
DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS,
|
|
6
6
|
DEFAULT_GLOBAL_CONCURRENCY_LIMIT,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
withFileLease,
|
|
23
23
|
writeAtomicJson,
|
|
24
24
|
writePrivateAtomicJson
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-CIZQXJ5Q.js";
|
|
26
26
|
import {
|
|
27
27
|
DIRS,
|
|
28
28
|
SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
|
|
@@ -109,6 +109,28 @@ var TOOL_CALL_INDEX_DIR = "@tool-calls";
|
|
|
109
109
|
function isTerminalState(state) {
|
|
110
110
|
return state === "complete" || state === "failed" || state === "partial" || state === "paused" || state === "stopped" || state === "rejected";
|
|
111
111
|
}
|
|
112
|
+
function isCorruptStatusError(error, statusPath) {
|
|
113
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
114
|
+
return message.startsWith(`Failed to parse async status file '${statusPath}'`) || message.startsWith(`Failed to validate async status file '${statusPath}'`);
|
|
115
|
+
}
|
|
116
|
+
var reportedCorruptTerminalStatus = /* @__PURE__ */ new Map();
|
|
117
|
+
function warnCorruptTerminalStatus(runId, statusPath, error, onCorruptStatus) {
|
|
118
|
+
let fileSignature = "unavailable";
|
|
119
|
+
try {
|
|
120
|
+
const stat = fs.statSync(statusPath);
|
|
121
|
+
fileSignature = `${stat.size}:${stat.mtimeMs}:${stat.ctimeMs}:${stat.ino}`;
|
|
122
|
+
} catch (statError) {
|
|
123
|
+
if (statError.code !== "ENOENT") throw statError;
|
|
124
|
+
}
|
|
125
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
126
|
+
const signature = `${fileSignature}
|
|
127
|
+
${message}`;
|
|
128
|
+
if (reportedCorruptTerminalStatus.get(statusPath) === signature) return;
|
|
129
|
+
reportedCorruptTerminalStatus.set(statusPath, signature);
|
|
130
|
+
const warning = `Skipping indexed terminal run '${runId}' with corrupt status at '${statusPath}': ${message}`;
|
|
131
|
+
if (onCorruptStatus) onCorruptStatus(warning);
|
|
132
|
+
else console.error(`[pi-subagents] ${warning}`);
|
|
133
|
+
}
|
|
112
134
|
function indexRoot(asyncDirRoot) {
|
|
113
135
|
return path2.join(asyncDirRoot, TERMINAL_RUN_INDEX_DIR);
|
|
114
136
|
}
|
|
@@ -177,8 +199,8 @@ function sessionDirs(asyncDirRoot, sessionId) {
|
|
|
177
199
|
throw error;
|
|
178
200
|
}
|
|
179
201
|
}
|
|
180
|
-
function recentMarkerFiles(dirs, limit) {
|
|
181
|
-
return dirs.flatMap(markerFiles).sort((left, right) => right.name.localeCompare(left.name)).slice(0, limit).map((marker) => path2.join(marker.dir, marker.name));
|
|
202
|
+
function recentMarkerFiles(dirs, limit, endedAfter) {
|
|
203
|
+
return dirs.flatMap(markerFiles).filter((marker) => endedAfter === void 0 || !(Number(marker.name.slice(0, TIMESTAMP_WIDTH)) < endedAfter)).sort((left, right) => right.name.localeCompare(left.name)).slice(0, limit).map((marker) => path2.join(marker.dir, marker.name));
|
|
182
204
|
}
|
|
183
205
|
function readTerminalRunToolCallIndex(asyncDirRoot, toolCallId) {
|
|
184
206
|
const runIds = [];
|
|
@@ -206,7 +228,7 @@ function readTerminalRunToolCallIndex(asyncDirRoot, toolCallId) {
|
|
|
206
228
|
}
|
|
207
229
|
function readRecentTerminalRunIndex(asyncDirRoot, options = {}) {
|
|
208
230
|
const limit = options.limit === void 0 ? Number.POSITIVE_INFINITY : Math.max(0, Math.floor(options.limit));
|
|
209
|
-
const candidates = recentMarkerFiles(sessionDirs(asyncDirRoot, options.sessionId), limit);
|
|
231
|
+
const candidates = recentMarkerFiles(sessionDirs(asyncDirRoot, options.sessionId), limit, options.endedAfter);
|
|
210
232
|
const runIds = [];
|
|
211
233
|
const seen = /* @__PURE__ */ new Set();
|
|
212
234
|
for (const marker of candidates) {
|
|
@@ -221,7 +243,15 @@ function readRecentTerminalRunIndex(asyncDirRoot, options = {}) {
|
|
|
221
243
|
continue;
|
|
222
244
|
}
|
|
223
245
|
const asyncDir = path2.join(asyncDirRoot, entry.runId);
|
|
224
|
-
const
|
|
246
|
+
const statusPath = path2.join(asyncDir, "status.json");
|
|
247
|
+
let status;
|
|
248
|
+
try {
|
|
249
|
+
status = readStatus(asyncDir);
|
|
250
|
+
} catch (error) {
|
|
251
|
+
if (!isCorruptStatusError(error, statusPath)) throw error;
|
|
252
|
+
warnCorruptTerminalStatus(entry.runId, statusPath, error, options.onCorruptStatus);
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
225
255
|
if (!status || !isTerminalState(status.state) || status.sessionId !== entry.sessionId || status.runId && status.runId !== entry.runId) {
|
|
226
256
|
removeInvalidMarker(marker);
|
|
227
257
|
continue;
|
|
@@ -742,11 +772,11 @@ function resolveInheritedNestedRoute(route) {
|
|
|
742
772
|
return void 0;
|
|
743
773
|
}
|
|
744
774
|
}
|
|
745
|
-
function inheritedNestedRouteOf(
|
|
746
|
-
return
|
|
775
|
+
function inheritedNestedRouteOf(runtime2) {
|
|
776
|
+
return runtime2?.nestedRoute ? resolveInheritedNestedRoute(runtime2.nestedRoute) : void 0;
|
|
747
777
|
}
|
|
748
|
-
function inheritedNestedParentAddressOf(
|
|
749
|
-
const parent =
|
|
778
|
+
function inheritedNestedParentAddressOf(runtime2) {
|
|
779
|
+
const parent = runtime2?.nestedParent;
|
|
750
780
|
if (!parent || !isSafeNestedId(parent.parentRunId)) return void 0;
|
|
751
781
|
const depth = Math.min(Math.max(1, clampNumber(parent.depth) ?? 1), MAX_DEPTH);
|
|
752
782
|
return {
|
|
@@ -1936,7 +1966,7 @@ async function executeWorkflowHostCommand(input) {
|
|
|
1936
1966
|
}
|
|
1937
1967
|
|
|
1938
1968
|
// src/workflows/scripted-workflow.ts
|
|
1939
|
-
import { accessSync, constants as constants2, readFileSync as readFileSync6, realpathSync as realpathSync3, statSync as
|
|
1969
|
+
import { accessSync, constants as constants2, readFileSync as readFileSync6, realpathSync as realpathSync3, statSync as statSync4 } from "node:fs";
|
|
1940
1970
|
import { createRequire } from "node:module";
|
|
1941
1971
|
import { dirname as dirname6, resolve as resolvePath } from "node:path";
|
|
1942
1972
|
import { Worker } from "node:worker_threads";
|
|
@@ -3703,7 +3733,7 @@ async function runWorkflowScript(options) {
|
|
|
3703
3733
|
if (staleCwd) process.chdir(options.processCwd);
|
|
3704
3734
|
else {
|
|
3705
3735
|
const target = realpathSync3(options.processCwd);
|
|
3706
|
-
if (!
|
|
3736
|
+
if (!statSync4(target).isDirectory()) {
|
|
3707
3737
|
const error = new Error(`ENOTDIR: not a directory, access '${target}'`);
|
|
3708
3738
|
error.code = "ENOTDIR";
|
|
3709
3739
|
throw error;
|
|
@@ -5585,7 +5615,12 @@ function parsePersistedBinding(value, source) {
|
|
|
5585
5615
|
function readMissionBinding(asyncDir) {
|
|
5586
5616
|
const bindingPath = path12.join(asyncDir, MISSION_BINDING_FILE);
|
|
5587
5617
|
if (!fs11.existsSync(bindingPath)) return void 0;
|
|
5588
|
-
|
|
5618
|
+
const raw = fs11.readFileSync(bindingPath, "utf-8");
|
|
5619
|
+
try {
|
|
5620
|
+
return parsePersistedBinding(JSON.parse(raw), bindingPath);
|
|
5621
|
+
} catch (error) {
|
|
5622
|
+
throw new Error(`Invalid mission binding file '${bindingPath}': ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
5623
|
+
}
|
|
5589
5624
|
}
|
|
5590
5625
|
function syncMissionFromAsyncCompletion(value) {
|
|
5591
5626
|
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
@@ -6156,8 +6191,66 @@ function cleanupResultIndexes(resultsDir, now = Date.now(), maxAgeMs = 24 * 60 *
|
|
|
6156
6191
|
return removed;
|
|
6157
6192
|
}
|
|
6158
6193
|
|
|
6194
|
+
// src/shared/completion-owner.ts
|
|
6195
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
6196
|
+
var COMPLETION_OWNER_KEY = /* @__PURE__ */ Symbol.for("pi-subagents.completion-owner-id");
|
|
6197
|
+
var OWNING_SESSION_COMPLETION_OWNER = "owning-session";
|
|
6198
|
+
function currentCompletionOwnerId() {
|
|
6199
|
+
const runtime2 = globalThis;
|
|
6200
|
+
runtime2[COMPLETION_OWNER_KEY] ??= randomUUID6();
|
|
6201
|
+
return runtime2[COMPLETION_OWNER_KEY];
|
|
6202
|
+
}
|
|
6203
|
+
|
|
6204
|
+
// src/runs/background/boot-id.ts
|
|
6205
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
6206
|
+
import * as fs14 from "node:fs";
|
|
6207
|
+
|
|
6208
|
+
// src/runs/background/pid-namespace.ts
|
|
6209
|
+
import * as fs13 from "node:fs";
|
|
6210
|
+
var resolved = false;
|
|
6211
|
+
var cachedScope;
|
|
6212
|
+
function currentPidNamespaceScope() {
|
|
6213
|
+
if (resolved) return cachedScope;
|
|
6214
|
+
resolved = true;
|
|
6215
|
+
if (process.platform !== "linux") return void 0;
|
|
6216
|
+
try {
|
|
6217
|
+
const scope = fs13.readlinkSync("/proc/self/ns/pid", "utf-8").trim();
|
|
6218
|
+
cachedScope = scope || void 0;
|
|
6219
|
+
} catch {
|
|
6220
|
+
cachedScope = void 0;
|
|
6221
|
+
}
|
|
6222
|
+
return cachedScope;
|
|
6223
|
+
}
|
|
6224
|
+
|
|
6225
|
+
// src/runs/background/boot-id.ts
|
|
6226
|
+
function readBootIdFromOs() {
|
|
6227
|
+
try {
|
|
6228
|
+
if (process.platform === "linux") return fs14.readFileSync("/proc/sys/kernel/random/boot_id", "utf-8").trim() || void 0;
|
|
6229
|
+
if (process.platform === "darwin") {
|
|
6230
|
+
return execFileSync2("sysctl", ["-n", "kern.bootsessionuuid"], { encoding: "utf-8", timeout: 1e3, stdio: ["ignore", "pipe", "ignore"] }).trim() || void 0;
|
|
6231
|
+
}
|
|
6232
|
+
} catch {
|
|
6233
|
+
}
|
|
6234
|
+
return void 0;
|
|
6235
|
+
}
|
|
6236
|
+
var BOOT_ID_KEY = /* @__PURE__ */ Symbol.for("pi-subagents.boot-id.v1");
|
|
6237
|
+
var runtime = globalThis;
|
|
6238
|
+
var reader = readBootIdFromOs;
|
|
6239
|
+
function currentBootId() {
|
|
6240
|
+
const cached = runtime[BOOT_ID_KEY];
|
|
6241
|
+
if (cached) return cached.value;
|
|
6242
|
+
const value = reader();
|
|
6243
|
+
runtime[BOOT_ID_KEY] = { value };
|
|
6244
|
+
return value;
|
|
6245
|
+
}
|
|
6246
|
+
function currentRecordedPid() {
|
|
6247
|
+
const pidNamespaceScope = currentPidNamespaceScope();
|
|
6248
|
+
const bootId = currentBootId();
|
|
6249
|
+
return { pid: process.pid, ...pidNamespaceScope ? { pidNamespaceScope } : {}, ...bootId ? { bootId } : {} };
|
|
6250
|
+
}
|
|
6251
|
+
|
|
6159
6252
|
// src/runs/background/stale-run-reconciler.ts
|
|
6160
|
-
import * as
|
|
6253
|
+
import * as fs16 from "node:fs";
|
|
6161
6254
|
import * as path15 from "node:path";
|
|
6162
6255
|
|
|
6163
6256
|
// src/runs/background/parallel-groups.ts
|
|
@@ -6191,25 +6284,15 @@ function flatToLogicalStepIndex(flatIndex, chainStepCount, groups) {
|
|
|
6191
6284
|
return Math.max(0, chainStepCount - 1);
|
|
6192
6285
|
}
|
|
6193
6286
|
|
|
6194
|
-
// src/
|
|
6195
|
-
|
|
6196
|
-
var
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
if (resolved) return cachedScope;
|
|
6200
|
-
resolved = true;
|
|
6201
|
-
if (process.platform !== "linux") return void 0;
|
|
6202
|
-
try {
|
|
6203
|
-
const scope = fs13.readlinkSync("/proc/self/ns/pid", "utf-8").trim();
|
|
6204
|
-
cachedScope = scope || void 0;
|
|
6205
|
-
} catch {
|
|
6206
|
-
cachedScope = void 0;
|
|
6207
|
-
}
|
|
6208
|
-
return cachedScope;
|
|
6287
|
+
// src/workflows/workflow-stop-cause.ts
|
|
6288
|
+
var WORKFLOW_STOP_CAUSE_RUNTIME_REPLACED = "runtime-replaced";
|
|
6289
|
+
var WORKFLOW_STOP_CAUSE_OWNER_EXITED = "owner-exited";
|
|
6290
|
+
function isReusableWorkflowStopCause(cause) {
|
|
6291
|
+
return cause === WORKFLOW_STOP_CAUSE_RUNTIME_REPLACED || cause === WORKFLOW_STOP_CAUSE_OWNER_EXITED;
|
|
6209
6292
|
}
|
|
6210
6293
|
|
|
6211
6294
|
// src/runs/background/workflow-terminal-proof.ts
|
|
6212
|
-
import * as
|
|
6295
|
+
import * as fs15 from "node:fs";
|
|
6213
6296
|
import * as path14 from "node:path";
|
|
6214
6297
|
var TERMINAL_WORKFLOW_STATES = /* @__PURE__ */ new Set(["completed", "failed", "stopped"]);
|
|
6215
6298
|
function isTerminalAsyncState(state) {
|
|
@@ -6247,7 +6330,7 @@ function readWorkflowChildProcessEvidence(workflowAsyncDir, steps) {
|
|
|
6247
6330
|
}
|
|
6248
6331
|
function launchFailedBeforeRunner(step, childDir) {
|
|
6249
6332
|
if (step.status !== "failed" || !step.error) return false;
|
|
6250
|
-
return !childDir || !["process-terminal.json", "runner-startup.json"].some((file) =>
|
|
6333
|
+
return !childDir || !["process-terminal.json", "runner-startup.json"].some((file) => fs15.existsSync(path14.join(childDir, file)));
|
|
6251
6334
|
}
|
|
6252
6335
|
function readWorkflowChildEvidence(workflowAsyncDir, step) {
|
|
6253
6336
|
const label = step.workflowKey ?? step.agent;
|
|
@@ -6255,7 +6338,7 @@ function readWorkflowChildEvidence(workflowAsyncDir, step) {
|
|
|
6255
6338
|
if (!step.async) return void 0;
|
|
6256
6339
|
if (!step.runId || path14.basename(step.runId) !== step.runId) return { state: "unknown", reason: `async workflow child ${label} is missing run id` };
|
|
6257
6340
|
const childDir = path14.join(path14.dirname(workflowAsyncDir), step.runId);
|
|
6258
|
-
if (!
|
|
6341
|
+
if (!fs15.existsSync(childDir)) return launchFailedBeforeRunner(step) ? void 0 : { state: "unknown", reason: `async workflow child ${label} directory is missing` };
|
|
6259
6342
|
const childStatus = readStatus(childDir);
|
|
6260
6343
|
if (!childStatus) return launchFailedBeforeRunner(step, childDir) ? void 0 : { state: "unknown", reason: `async workflow child ${label} status is missing or unreadable` };
|
|
6261
6344
|
if (!isTerminalAsyncState(childStatus.state)) return { state: "pending", reason: `async workflow child ${label} is still ${childStatus.state}` };
|
|
@@ -6302,17 +6385,17 @@ function readRunnerStartupDiagnostics(asyncDir) {
|
|
|
6302
6385
|
const maxBytes = 64 * 1024;
|
|
6303
6386
|
let content;
|
|
6304
6387
|
try {
|
|
6305
|
-
const stat =
|
|
6388
|
+
const stat = fs16.statSync(stderrPath);
|
|
6306
6389
|
if (stat.size <= 0) return void 0;
|
|
6307
|
-
const fd =
|
|
6390
|
+
const fd = fs16.openSync(stderrPath, "r");
|
|
6308
6391
|
try {
|
|
6309
6392
|
const bytesToRead = Math.min(stat.size, maxBytes);
|
|
6310
6393
|
const start = Math.max(0, stat.size - bytesToRead);
|
|
6311
6394
|
const buffer = Buffer.alloc(bytesToRead);
|
|
6312
|
-
|
|
6395
|
+
fs16.readSync(fd, buffer, 0, bytesToRead, start);
|
|
6313
6396
|
content = buffer.toString("utf-8").trim();
|
|
6314
6397
|
} finally {
|
|
6315
|
-
|
|
6398
|
+
fs16.closeSync(fd);
|
|
6316
6399
|
}
|
|
6317
6400
|
} catch {
|
|
6318
6401
|
return void 0;
|
|
@@ -6327,15 +6410,15 @@ function isNotFoundError(error) {
|
|
|
6327
6410
|
}
|
|
6328
6411
|
function appendJsonlBestEffort(filePath, payload) {
|
|
6329
6412
|
try {
|
|
6330
|
-
|
|
6331
|
-
|
|
6413
|
+
fs16.mkdirSync(path15.dirname(filePath), { recursive: true });
|
|
6414
|
+
fs16.appendFileSync(filePath, `${JSON.stringify(payload)}
|
|
6332
6415
|
`, "utf-8");
|
|
6333
6416
|
} catch {
|
|
6334
6417
|
}
|
|
6335
6418
|
}
|
|
6336
6419
|
function regularFileExists(filePath) {
|
|
6337
6420
|
try {
|
|
6338
|
-
return
|
|
6421
|
+
return fs16.statSync(filePath).isFile();
|
|
6339
6422
|
} catch (error) {
|
|
6340
6423
|
if (isNotFoundError(error)) return false;
|
|
6341
6424
|
throw error;
|
|
@@ -6343,7 +6426,7 @@ function regularFileExists(filePath) {
|
|
|
6343
6426
|
}
|
|
6344
6427
|
function readResultRepairData(resultPath) {
|
|
6345
6428
|
try {
|
|
6346
|
-
const data = JSON.parse(
|
|
6429
|
+
const data = JSON.parse(fs16.readFileSync(resultPath, "utf-8"));
|
|
6347
6430
|
if (data.error !== void 0 && typeof data.error !== "string") throw new Error(`Invalid async result file '${resultPath}': error must be a string.`);
|
|
6348
6431
|
const state = data.success ? "complete" : data.state === "stopped" ? "stopped" : data.state === "rejected" ? "rejected" : data.state === "partial" ? "partial" : data.state === "paused" || data.exitCode === 0 ? "paused" : "failed";
|
|
6349
6432
|
const results = Array.isArray(data.results) ? data.results.map((entry, index) => {
|
|
@@ -6460,13 +6543,15 @@ function settledWorkflowChildStatus(asyncDir, workflowRunId, step, now) {
|
|
|
6460
6543
|
if (settled.stopped === void 0) delete settled.stopped;
|
|
6461
6544
|
return settled;
|
|
6462
6545
|
}
|
|
6463
|
-
function buildFailedRepair(status, asyncDir, now, reason) {
|
|
6546
|
+
function buildFailedRepair(status, asyncDir, now, reason, ownerExited = false, adoptCompletionOwnerId) {
|
|
6464
6547
|
const runId = status.runId || path15.basename(asyncDir);
|
|
6465
6548
|
const pid = typeof status.pid === "number" ? status.pid : "unknown";
|
|
6549
|
+
const exitedWorkflow = ownerExited && status.mode === "workflow" ? status.workflow : void 0;
|
|
6550
|
+
const completionOwnerId = exitedWorkflow ? adoptCompletionOwnerId || OWNING_SESSION_COMPLETION_OWNER : status.completionOwnerId;
|
|
6466
6551
|
const terminal3 = readProcessTerminal(asyncDir, { runId }) ?? status.processTerminal;
|
|
6467
6552
|
const runnerExit = terminal3?.state === "observed" || terminal3?.state === "unknown" ? terminal3.instances?.find((instance) => instance.kind === "runner" && instance.processInstanceId === terminal3.runnerProcessInstanceId) : void 0;
|
|
6468
6553
|
const exitText = runnerExit?.kind === "runner" ? `exited with code ${runnerExit.exitCode ?? "none"}${runnerExit.signal ? ` (signal ${runnerExit.signal})` : ""}` : "exited or disappeared";
|
|
6469
|
-
const baseMessage = reason ?? `Async runner process ${pid} ${exitText} before writing a result. Marked run failed by stale-run reconciliation
|
|
6554
|
+
const baseMessage = reason ?? (exitedWorkflow ? `The Pi process (PID ${pid}) that ran workflow ${runId} exited before the workflow finished. Marked run failed by stale-run reconciliation. Its finished children are kept.` : `Async runner process ${pid} ${exitText} before writing a result. Marked run failed by stale-run reconciliation.`);
|
|
6470
6555
|
const diagnostics = readRunnerStartupDiagnostics(asyncDir);
|
|
6471
6556
|
const message = diagnostics ? `${baseMessage}
|
|
6472
6557
|
|
|
@@ -6502,7 +6587,10 @@ ${diagnostics}` : baseMessage;
|
|
|
6502
6587
|
activityState: void 0,
|
|
6503
6588
|
lastUpdate: now,
|
|
6504
6589
|
endedAt: now,
|
|
6505
|
-
steps: repairedSteps
|
|
6590
|
+
steps: repairedSteps,
|
|
6591
|
+
// Read from the pre-repair status: the repair time would make an old crash look new.
|
|
6592
|
+
...exitedWorkflow ? { workflow: { ...exitedWorkflow, stopCause: WORKFLOW_STOP_CAUSE_OWNER_EXITED, ownerExitedAt: status.lastUpdate ?? status.startedAt } } : {},
|
|
6593
|
+
...completionOwnerId ? { completionOwnerId } : {}
|
|
6506
6594
|
};
|
|
6507
6595
|
const resultAgent = repairedSteps[status.currentStep ?? 0]?.agent ?? repairedSteps[0]?.agent ?? "subagent";
|
|
6508
6596
|
return {
|
|
@@ -6512,7 +6600,9 @@ ${diagnostics}` : baseMessage;
|
|
|
6512
6600
|
id: runId,
|
|
6513
6601
|
agent: resultAgent,
|
|
6514
6602
|
mode: status.mode,
|
|
6515
|
-
...
|
|
6603
|
+
...exitedWorkflow ? { workflow: { stopCause: WORKFLOW_STOP_CAUSE_OWNER_EXITED } } : {},
|
|
6604
|
+
...completionOwnerId ? { completionOwnerId } : {},
|
|
6605
|
+
...status.completionOwnerProcess ? { completionOwnerProcess: status.completionOwnerProcess } : {},
|
|
6516
6606
|
...status.parentWorkflowRunId ? { parentWorkflowRunId: status.parentWorkflowRunId } : {},
|
|
6517
6607
|
...status.workflowKey ? { workflowKey: status.workflowKey } : {},
|
|
6518
6608
|
success: false,
|
|
@@ -6538,8 +6628,8 @@ ${diagnostics}` : baseMessage;
|
|
|
6538
6628
|
}
|
|
6539
6629
|
};
|
|
6540
6630
|
}
|
|
6541
|
-
function writeFailedRepair(asyncDir, status, resultPath, now, reason) {
|
|
6542
|
-
const repair = buildFailedRepair(status, asyncDir, now, reason);
|
|
6631
|
+
function writeFailedRepair(asyncDir, status, resultPath, now, reason, ownerExited = false, adoptCompletionOwnerId) {
|
|
6632
|
+
const repair = buildFailedRepair(status, asyncDir, now, reason, ownerExited, adoptCompletionOwnerId);
|
|
6543
6633
|
if (repair.result.sessionId) writeAsyncResultFile(resultPath, repair.result);
|
|
6544
6634
|
writeAtomicJson(path15.join(asyncDir, "status.json"), repair.status);
|
|
6545
6635
|
updateActiveRunIndex(asyncDir, repair.status.state, repair.status.toolCallId);
|
|
@@ -6599,7 +6689,7 @@ function checkPidLiveness(pid, kill = process.kill, probeZombie = false) {
|
|
|
6599
6689
|
kill(pid, 0);
|
|
6600
6690
|
if (probeZombie && process.platform === "linux") {
|
|
6601
6691
|
try {
|
|
6602
|
-
const stat =
|
|
6692
|
+
const stat = fs16.readFileSync(`/proc/${pid}/stat`, "utf-8");
|
|
6603
6693
|
const closeParen = stat.lastIndexOf(") ");
|
|
6604
6694
|
if (closeParen >= 0 && stat[closeParen + 2] === "Z") return "dead";
|
|
6605
6695
|
} catch {
|
|
@@ -6613,6 +6703,19 @@ function checkPidLiveness(pid, kill = process.kill, probeZombie = false) {
|
|
|
6613
6703
|
return "unknown";
|
|
6614
6704
|
}
|
|
6615
6705
|
}
|
|
6706
|
+
function isRecordedPid(value) {
|
|
6707
|
+
if (!value || typeof value !== "object") return false;
|
|
6708
|
+
const { pid, pidNamespaceScope, bootId } = value;
|
|
6709
|
+
return typeof pid === "number" && Number.isSafeInteger(pid) && pid > 0 && (pidNamespaceScope === void 0 || typeof pidNamespaceScope === "string") && (bootId === void 0 || typeof bootId === "string");
|
|
6710
|
+
}
|
|
6711
|
+
function checkRecordedPidLiveness(recorded, observation = { observedScope: currentPidNamespaceScope(), observedBootId: currentBootId() }) {
|
|
6712
|
+
const { observedScope, observedBootId } = observation;
|
|
6713
|
+
if (recorded.pidNamespaceScope === observedScope && recorded.bootId && observedBootId && recorded.bootId !== observedBootId) return "dead";
|
|
6714
|
+
const scopeMismatch = recorded.pidNamespaceScope !== void 0 && recorded.pidNamespaceScope !== observedScope;
|
|
6715
|
+
const scopeVerified = recorded.pidNamespaceScope !== void 0 && recorded.pidNamespaceScope === observedScope;
|
|
6716
|
+
const liveness = observation.probe ? observation.probe(recorded.pid) : checkPidLiveness(recorded.pid, observation.kill, scopeVerified);
|
|
6717
|
+
return liveness === "dead" && scopeMismatch ? "unknown" : liveness;
|
|
6718
|
+
}
|
|
6616
6719
|
function reconcileAsyncRun(asyncDir, options = {}, observeStatus) {
|
|
6617
6720
|
const now = options.now?.() ?? Date.now();
|
|
6618
6721
|
const status = readStatus(asyncDir);
|
|
@@ -6665,11 +6768,11 @@ function reconcileAsyncRun(asyncDir, options = {}, observeStatus) {
|
|
|
6665
6768
|
return { status: null, repaired: false, resultPath };
|
|
6666
6769
|
}
|
|
6667
6770
|
}
|
|
6668
|
-
const
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6771
|
+
const liveness = checkRecordedPidLiveness({ pid: effectiveStatus.pid, pidNamespaceScope: effectiveStatus.pidNamespaceScope, bootId: effectiveStatus.bootId }, {
|
|
6772
|
+
kill: options.kill,
|
|
6773
|
+
observedScope: options.pidNamespaceScope ? options.pidNamespaceScope() : currentPidNamespaceScope(),
|
|
6774
|
+
observedBootId: options.bootId ? options.bootId() : currentBootId()
|
|
6775
|
+
});
|
|
6673
6776
|
if (liveness !== "dead") {
|
|
6674
6777
|
const staleAfterMs = options.staleAlivePidMs ?? 24 * 60 * 60 * 1e3;
|
|
6675
6778
|
const lastUpdate = effectiveStatus.lastUpdate ?? effectiveStatus.startedAt;
|
|
@@ -6678,7 +6781,7 @@ function reconcileAsyncRun(asyncDir, options = {}, observeStatus) {
|
|
|
6678
6781
|
const message = `Async runner PID ${effectiveStatus.pid} ${probe}; status has not updated for ${now - lastUpdate}ms, so stale-run reconciliation marked the run failed because PID ownership is unverified.`;
|
|
6679
6782
|
return writeFailedRepair(asyncDir, effectiveStatus, resultPath, now, message);
|
|
6680
6783
|
}
|
|
6681
|
-
return writeFailedRepair(asyncDir, effectiveStatus, resultPath, now);
|
|
6784
|
+
return writeFailedRepair(asyncDir, effectiveStatus, resultPath, now, void 0, true, options.adoptCompletionOwnerId);
|
|
6682
6785
|
}
|
|
6683
6786
|
|
|
6684
6787
|
// src/policy/authority.ts
|
|
@@ -6908,7 +7011,7 @@ async function runSetupCommand(command, args, options) {
|
|
|
6908
7011
|
}
|
|
6909
7012
|
|
|
6910
7013
|
// src/runs/shared/worktree.ts
|
|
6911
|
-
import * as
|
|
7014
|
+
import * as fs17 from "node:fs";
|
|
6912
7015
|
import * as os2 from "node:os";
|
|
6913
7016
|
import * as path16 from "node:path";
|
|
6914
7017
|
var DEFAULT_WORKTREE_PROVIDER = "auto";
|
|
@@ -7045,7 +7148,7 @@ function currentWorktreePatch(worktreePath, baseCommit) {
|
|
|
7045
7148
|
assertWorktreeMutationAllowed();
|
|
7046
7149
|
let tempDir;
|
|
7047
7150
|
try {
|
|
7048
|
-
tempDir =
|
|
7151
|
+
tempDir = fs17.mkdtempSync(path16.join(os2.tmpdir(), "pi-worktree-index-"));
|
|
7049
7152
|
} catch (error) {
|
|
7050
7153
|
return { error: error instanceof Error ? error.message : String(error) };
|
|
7051
7154
|
}
|
|
@@ -7060,7 +7163,7 @@ function currentWorktreePatch(worktreePath, baseCommit) {
|
|
|
7060
7163
|
return { patch: diff.stdout };
|
|
7061
7164
|
} finally {
|
|
7062
7165
|
try {
|
|
7063
|
-
|
|
7166
|
+
fs17.rmSync(tempDir, { recursive: true, force: true });
|
|
7064
7167
|
} catch {
|
|
7065
7168
|
}
|
|
7066
7169
|
}
|
|
@@ -7070,7 +7173,7 @@ function validateWorktreePatchRepresentsCurrentWorktree(worktreePath, baseCommit
|
|
|
7070
7173
|
if (validationError) return validationError;
|
|
7071
7174
|
let capturedPatch;
|
|
7072
7175
|
try {
|
|
7073
|
-
capturedPatch =
|
|
7176
|
+
capturedPatch = fs17.readFileSync(patchPath, "utf-8");
|
|
7074
7177
|
} catch (error) {
|
|
7075
7178
|
return error instanceof Error ? error.message : String(error);
|
|
7076
7179
|
}
|
|
@@ -7124,9 +7227,9 @@ function normalizeComparableCwd(cwd) {
|
|
|
7124
7227
|
try {
|
|
7125
7228
|
let realpath;
|
|
7126
7229
|
try {
|
|
7127
|
-
realpath =
|
|
7230
|
+
realpath = fs17.realpathSync.native(existing);
|
|
7128
7231
|
} catch {
|
|
7129
|
-
realpath =
|
|
7232
|
+
realpath = fs17.realpathSync(existing);
|
|
7130
7233
|
}
|
|
7131
7234
|
return path16.join(realpath, ...missingSegments.reverse());
|
|
7132
7235
|
} catch {
|
|
@@ -7326,7 +7429,7 @@ function buildNativeProjectPath(dedicatedRoot, repoRoot) {
|
|
|
7326
7429
|
}
|
|
7327
7430
|
function ensureProjectWorktreeDir(dedicatedRoot, repoRoot) {
|
|
7328
7431
|
try {
|
|
7329
|
-
|
|
7432
|
+
fs17.mkdirSync(buildNativeProjectPath(dedicatedRoot, repoRoot), { recursive: true });
|
|
7330
7433
|
} catch (error) {
|
|
7331
7434
|
const message = error instanceof Error ? error.message : String(error);
|
|
7332
7435
|
throw new Error(`failed to create worktree base directory ${dedicatedRoot}: ${message}`);
|
|
@@ -7386,7 +7489,7 @@ function linkNodeModulesIfPresent(toplevel, worktreePath) {
|
|
|
7386
7489
|
const nodeModulesLinkPath = path16.join(worktreePath, "node_modules");
|
|
7387
7490
|
const hasDirectoryEntry = (candidate) => {
|
|
7388
7491
|
try {
|
|
7389
|
-
|
|
7492
|
+
fs17.lstatSync(candidate);
|
|
7390
7493
|
return true;
|
|
7391
7494
|
} catch (error) {
|
|
7392
7495
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") return false;
|
|
@@ -7397,14 +7500,14 @@ function linkNodeModulesIfPresent(toplevel, worktreePath) {
|
|
|
7397
7500
|
if (hasDirectoryEntry(nodeModulesLinkPath)) return false;
|
|
7398
7501
|
let sourceRealPath;
|
|
7399
7502
|
try {
|
|
7400
|
-
if (!
|
|
7401
|
-
sourceRealPath =
|
|
7503
|
+
if (!fs17.statSync(nodeModulesPath).isDirectory()) throw new Error("source node_modules is not a directory");
|
|
7504
|
+
sourceRealPath = fs17.realpathSync.native(nodeModulesPath);
|
|
7402
7505
|
} catch (error) {
|
|
7403
7506
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") return false;
|
|
7404
7507
|
throw error;
|
|
7405
7508
|
}
|
|
7406
|
-
|
|
7407
|
-
if (!
|
|
7509
|
+
fs17.symlinkSync(nodeModulesPath, nodeModulesLinkPath, process.platform === "win32" ? "junction" : "dir");
|
|
7510
|
+
if (!fs17.lstatSync(nodeModulesLinkPath).isSymbolicLink() || fs17.realpathSync.native(nodeModulesLinkPath) !== sourceRealPath) {
|
|
7408
7511
|
throw new Error("created link does not resolve to the source node_modules");
|
|
7409
7512
|
}
|
|
7410
7513
|
return true;
|
|
@@ -7438,10 +7541,10 @@ function resolveWorktreeSetupHook(repoRoot, config) {
|
|
|
7438
7541
|
} else {
|
|
7439
7542
|
throw new Error("worktree setup hook must be an absolute path or a repo-relative path");
|
|
7440
7543
|
}
|
|
7441
|
-
if (!
|
|
7544
|
+
if (!fs17.existsSync(resolvedPath)) {
|
|
7442
7545
|
throw new Error(`worktree setup hook not found: ${resolvedPath}`);
|
|
7443
7546
|
}
|
|
7444
|
-
if (
|
|
7547
|
+
if (fs17.statSync(resolvedPath).isDirectory()) {
|
|
7445
7548
|
throw new Error(`worktree setup hook must be a file, got directory: ${resolvedPath}`);
|
|
7446
7549
|
}
|
|
7447
7550
|
return {
|
|
@@ -7542,7 +7645,7 @@ async function createNativeWorktree(tx, toplevel, cwdRelative, runId, index, bas
|
|
|
7542
7645
|
const branch = await tx.git(toplevel, ["show-ref", "--verify", "--quiet", `refs/heads/${naming.requestedBranch}`], [0, 1]);
|
|
7543
7646
|
let pathExists = false;
|
|
7544
7647
|
try {
|
|
7545
|
-
|
|
7648
|
+
fs17.lstatSync(worktreePath);
|
|
7546
7649
|
pathExists = true;
|
|
7547
7650
|
} catch (error) {
|
|
7548
7651
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") throw error;
|
|
@@ -7594,7 +7697,7 @@ async function createWorktrunkWorktree(tx, toplevel, cwdRelative, runId, index,
|
|
|
7594
7697
|
const worktreePathCandidate = path16.resolve(output.path);
|
|
7595
7698
|
let stat;
|
|
7596
7699
|
try {
|
|
7597
|
-
stat =
|
|
7700
|
+
stat = fs17.lstatSync(worktreePathCandidate);
|
|
7598
7701
|
} catch (error) {
|
|
7599
7702
|
throw new Error(`Worktrunk provisioning returned a missing worktree path: ${worktreePathCandidate}`, { cause: error instanceof Error ? error : void 0 });
|
|
7600
7703
|
}
|
|
@@ -7637,21 +7740,21 @@ function removeSyntheticPath(worktree, syntheticPath) {
|
|
|
7637
7740
|
}
|
|
7638
7741
|
let stat;
|
|
7639
7742
|
try {
|
|
7640
|
-
stat =
|
|
7743
|
+
stat = fs17.lstatSync(resolved2);
|
|
7641
7744
|
} catch (error) {
|
|
7642
7745
|
const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
|
7643
7746
|
if (code === "ENOENT") return;
|
|
7644
7747
|
throw error;
|
|
7645
7748
|
}
|
|
7646
7749
|
if (stat.isSymbolicLink()) {
|
|
7647
|
-
|
|
7750
|
+
fs17.unlinkSync(resolved2);
|
|
7648
7751
|
return;
|
|
7649
7752
|
}
|
|
7650
7753
|
if (stat.isDirectory()) {
|
|
7651
|
-
|
|
7754
|
+
fs17.rmSync(resolved2, { recursive: true, force: true });
|
|
7652
7755
|
return;
|
|
7653
7756
|
}
|
|
7654
|
-
|
|
7757
|
+
fs17.rmSync(resolved2, { force: true });
|
|
7655
7758
|
}
|
|
7656
7759
|
function removeSyntheticPathsBeforeDiff(worktree) {
|
|
7657
7760
|
if (worktree.syntheticPaths.length === 0) return;
|
|
@@ -7695,7 +7798,7 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
|
|
|
7695
7798
|
const diffStat = runGitChecked(worktree.path, ["diff", "--cached", ...MACHINE_DIFF_OPTIONS, "--stat", setup.baseCommit]).trim();
|
|
7696
7799
|
const patch = runGitChecked(worktree.path, ["diff", "--cached", ...MACHINE_PATCH_OPTIONS, setup.baseCommit]);
|
|
7697
7800
|
const numstat = runGitChecked(worktree.path, ["diff", "--cached", ...MACHINE_DIFF_OPTIONS, "--numstat", setup.baseCommit]);
|
|
7698
|
-
|
|
7801
|
+
fs17.writeFileSync(patchPath, patch, "utf-8");
|
|
7699
7802
|
if (!patch.trim()) {
|
|
7700
7803
|
return emptyDiff(worktree.index, agent, worktree.branch, patchPath);
|
|
7701
7804
|
}
|
|
@@ -7715,14 +7818,14 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
|
|
|
7715
7818
|
}
|
|
7716
7819
|
function writeEmptyPatch(patchPath) {
|
|
7717
7820
|
try {
|
|
7718
|
-
|
|
7821
|
+
fs17.writeFileSync(patchPath, "", "utf-8");
|
|
7719
7822
|
} catch {
|
|
7720
7823
|
}
|
|
7721
7824
|
}
|
|
7722
7825
|
function handoffRecordsPatch(manifestPath, patchPath) {
|
|
7723
|
-
if (!manifestPath || !
|
|
7826
|
+
if (!manifestPath || !fs17.existsSync(manifestPath)) return false;
|
|
7724
7827
|
try {
|
|
7725
|
-
const manifest = JSON.parse(
|
|
7828
|
+
const manifest = JSON.parse(fs17.readFileSync(manifestPath, "utf-8"));
|
|
7726
7829
|
if (manifest.version !== 1 || !Array.isArray(manifest.groups)) return false;
|
|
7727
7830
|
const resolvedPatchPath = path16.resolve(patchPath);
|
|
7728
7831
|
return manifest.groups.some((group) => Array.isArray(group.children) && group.children.some(
|
|
@@ -7779,9 +7882,9 @@ function cleanupSingleWorktree(setup, worktree, intent) {
|
|
|
7779
7882
|
const captured = (intent.capturedDiffs ?? setup.capturedDiffs)?.find((diff) => diff.index === worktree.index);
|
|
7780
7883
|
let patchValidationError;
|
|
7781
7884
|
let patchCaptured = false;
|
|
7782
|
-
if (captured !== void 0 && captured.error === void 0 &&
|
|
7885
|
+
if (captured !== void 0 && captured.error === void 0 && fs17.existsSync(captured.patchPath) && handoffRecordsPatch(intent.handoffManifestPath, captured.patchPath)) {
|
|
7783
7886
|
try {
|
|
7784
|
-
if (
|
|
7887
|
+
if (fs17.statSync(captured.patchPath).size > 0) {
|
|
7785
7888
|
patchValidationError = validateWorktreePatchRepresentsCurrentWorktree(worktree.path, setup.baseCommit, captured.patchPath);
|
|
7786
7889
|
patchCaptured = patchValidationError === void 0;
|
|
7787
7890
|
}
|
|
@@ -7911,7 +8014,7 @@ async function compensateSetup(tx) {
|
|
|
7911
8014
|
throw new Error(tx.progress.unknown);
|
|
7912
8015
|
}
|
|
7913
8016
|
await git(["worktree", "remove", "--force", attempt.path]);
|
|
7914
|
-
} else if (
|
|
8017
|
+
} else if (fs17.existsSync(attempt.path)) {
|
|
7915
8018
|
tx.unknown("Unregistered partial allocation retained");
|
|
7916
8019
|
throw new Error(tx.progress.unknown);
|
|
7917
8020
|
}
|
|
@@ -8031,7 +8134,7 @@ async function createWorktrees(cwd, runId, count, options = {}) {
|
|
|
8031
8134
|
function diffWorktrees(setup, agents, diffsDir) {
|
|
8032
8135
|
assertWorktreeMutationAllowed();
|
|
8033
8136
|
try {
|
|
8034
|
-
|
|
8137
|
+
fs17.mkdirSync(diffsDir, { recursive: true });
|
|
8035
8138
|
} catch {
|
|
8036
8139
|
return [];
|
|
8037
8140
|
}
|
|
@@ -8216,7 +8319,14 @@ export {
|
|
|
8216
8319
|
resultCandidateFilesForToolCall,
|
|
8217
8320
|
missionObserverResultCandidateFiles,
|
|
8218
8321
|
cleanupResultIndexes,
|
|
8322
|
+
OWNING_SESSION_COMPLETION_OWNER,
|
|
8323
|
+
currentCompletionOwnerId,
|
|
8219
8324
|
currentPidNamespaceScope,
|
|
8325
|
+
currentBootId,
|
|
8326
|
+
currentRecordedPid,
|
|
8327
|
+
WORKFLOW_STOP_CAUSE_RUNTIME_REPLACED,
|
|
8328
|
+
WORKFLOW_STOP_CAUSE_OWNER_EXITED,
|
|
8329
|
+
isReusableWorkflowStopCause,
|
|
8220
8330
|
isTerminalAsyncState,
|
|
8221
8331
|
withWorkflowChildRunModel,
|
|
8222
8332
|
readWorkflowChildProcessEvidence,
|
|
@@ -8224,6 +8334,8 @@ export {
|
|
|
8224
8334
|
readWorkflowTerminalProof,
|
|
8225
8335
|
reconcileNestedAsyncDescendants,
|
|
8226
8336
|
checkPidLiveness,
|
|
8337
|
+
isRecordedPid,
|
|
8338
|
+
checkRecordedPidLiveness,
|
|
8227
8339
|
reconcileAsyncRun,
|
|
8228
8340
|
resolveAuthorityDecision,
|
|
8229
8341
|
validateAuthorityPolicy,
|