pi-subagents 0.81.0 → 0.82.0
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 +38 -0
- package/bundle/agents.js +3 -3
- package/bundle/child-tool-plan.js +2 -2
- package/bundle/{chunk-LSRUTHT7.js → chunk-43SCHIMD.js} +1 -1
- package/bundle/{chunk-G5DKFLLI.js → chunk-4SDU2BZX.js} +15 -10
- package/bundle/{chunk-V2JWDB5U.js → chunk-52UBALJL.js} +2 -2
- package/bundle/{chunk-3DC5KBVP.js → chunk-5TYMSZX3.js} +1 -1
- package/bundle/{chunk-CEKS3TFO.js → chunk-7IVSUMQQ.js} +6 -6
- package/bundle/{chunk-KSWQVGDW.js → chunk-7PCKZHR5.js} +225 -18
- package/bundle/{chunk-563BHAZ5.js → chunk-7YMXOYEU.js} +33 -25
- package/bundle/{chunk-XMFLCKMQ.js → chunk-B5EKXDHE.js} +336 -130
- package/bundle/{chunk-ZBC44JJ3.js → chunk-CIZQXJ5Q.js} +22 -9
- package/bundle/{chunk-L5ZHE4L4.js → chunk-GC4DSPMH.js} +4 -4
- package/bundle/{chunk-ARRKBB2B.js → chunk-GJECHSAR.js} +2 -2
- package/bundle/{chunk-2ZSNH26H.js → chunk-M2CTFYT3.js} +7 -7
- package/bundle/{chunk-TUWLXTAM.js → chunk-MHZ4G23A.js} +681 -320
- package/bundle/{chunk-WSBNENFS.js → chunk-NGGAFDL6.js} +14 -4
- package/bundle/{chunk-VJHOELQP.js → chunk-NRQ75MGH.js} +160 -78
- package/bundle/{chunk-BJN5LUQY.js → chunk-OYF6AFDY.js} +1 -1
- package/bundle/{chunk-EYNJ6VL6.js → chunk-PLCCBLPY.js} +2 -2
- package/bundle/{chunk-74RT5YQE.js → chunk-RMQFMMAT.js} +123 -33
- package/bundle/{chunk-V6MR5TOQ.js → chunk-SIJ4S3EN.js} +25 -19
- package/bundle/{chunk-NNLASTQE.js → chunk-VH5OAWVG.js} +19 -5
- package/bundle/{chunk-BPS2AGBZ.js → chunk-W2SZ22EM.js} +93 -52
- package/bundle/{chunk-V3BIUPLU.js → chunk-WVD4UEL4.js} +256 -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-ZLINIYTP.js} +497 -272
- package/bundle/{chunk-2XYWN7QJ.js → chunk-ZQGSDHL6.js} +2 -2
- 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 +31 -0
- 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/pi-subagents/references/execution-controls.md +5 -4
- 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/schemas.js +3 -3
- 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 +2 -0
- package/src/runs/background/async-status.js +21 -2
- 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 +1 -0
- package/src/runs/background/terminal-run-index.js +4 -2
- 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 +24 -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
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
checkPidLiveness,
|
|
3
|
+
checkRecordedPidLiveness,
|
|
4
|
+
currentBootId,
|
|
3
5
|
currentPidNamespaceScope,
|
|
4
6
|
isTerminalAsyncState,
|
|
5
7
|
normalizeWorktreeBranchPrefix,
|
|
@@ -9,13 +11,13 @@ import {
|
|
|
9
11
|
validateAuthorityPolicy,
|
|
10
12
|
validateMissionStoreConfig,
|
|
11
13
|
validateModelResponseAliases
|
|
12
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-NRQ75MGH.js";
|
|
13
15
|
import {
|
|
14
16
|
getAgentDir,
|
|
15
17
|
readStatus,
|
|
16
18
|
validatePermissionConfig,
|
|
17
19
|
writePrivateAtomicJson
|
|
18
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-CIZQXJ5Q.js";
|
|
19
21
|
import {
|
|
20
22
|
FLEET_KEYBINDING_ACTIONS,
|
|
21
23
|
RUNNER_LAUNCHER_NAME_PATTERN,
|
|
@@ -252,8 +254,13 @@ function abandonedRunnerReleaseVerdict(status, proofState, options, anyTerminalS
|
|
|
252
254
|
if (thresholdMs === false) return { state: "retained", reason: `${proofReason}; abandoned-timeout policy is disabled` };
|
|
253
255
|
if (anyTerminalState ? !isTerminalAsyncState(status.state) : status.state !== "failed") return { state: "retained", reason: `${proofReason}; abandoned-timeout policy requires a ${anyTerminalState ? "terminal" : "failed"} run, not ${status.state}` };
|
|
254
256
|
if (typeof status.pid !== "number" || !Number.isInteger(status.pid) || status.pid < 1) return { state: "retained", reason: `${proofReason}; runner PID is missing or invalid` };
|
|
255
|
-
|
|
256
|
-
|
|
257
|
+
const observedScope = (options.pidNamespaceScope ?? currentPidNamespaceScope)();
|
|
258
|
+
if (status.pidNamespaceScope !== void 0 && status.pidNamespaceScope !== observedScope) return { state: "retained", reason: `${proofReason}; runner PID namespace differs from this process, so liveness is unknown` };
|
|
259
|
+
const liveness = checkRecordedPidLiveness({ pid: status.pid, pidNamespaceScope: status.pidNamespaceScope, bootId: status.bootId }, {
|
|
260
|
+
observedScope,
|
|
261
|
+
observedBootId: (options.bootId ?? currentBootId)(),
|
|
262
|
+
probe: options.pidLiveness ?? ((pid) => checkPidLiveness(pid))
|
|
263
|
+
});
|
|
257
264
|
if (liveness !== "dead") return { state: "retained", reason: `${proofReason}; runner PID liveness is ${liveness}` };
|
|
258
265
|
const lastActivityAt = status.lastActivityAt ?? status.lastUpdate ?? status.endedAt;
|
|
259
266
|
if (typeof lastActivityAt !== "number" || !Number.isFinite(lastActivityAt)) return { state: "retained", reason: `${proofReason}; last activity timestamp is missing or invalid` };
|
|
@@ -666,6 +673,9 @@ function validateConfig(config) {
|
|
|
666
673
|
if (config.enableSlashCommands !== void 0 && typeof config.enableSlashCommands !== "boolean") {
|
|
667
674
|
throw new Error("config.enableSlashCommands must be a boolean");
|
|
668
675
|
}
|
|
676
|
+
if (config.autoResume !== void 0 && typeof config.autoResume !== "boolean") {
|
|
677
|
+
throw new Error("config.autoResume must be a boolean");
|
|
678
|
+
}
|
|
669
679
|
if (config.toolActivation !== void 0 && config.toolActivation !== "auto" && config.toolActivation !== "dynamic" && config.toolActivation !== "eager") {
|
|
670
680
|
throw new Error('config.toolActivation must be "auto", "dynamic", or "eager"');
|
|
671
681
|
}
|
|
@@ -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,
|
|
@@ -177,8 +177,8 @@ function sessionDirs(asyncDirRoot, sessionId) {
|
|
|
177
177
|
throw error;
|
|
178
178
|
}
|
|
179
179
|
}
|
|
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));
|
|
180
|
+
function recentMarkerFiles(dirs, limit, endedAfter) {
|
|
181
|
+
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
182
|
}
|
|
183
183
|
function readTerminalRunToolCallIndex(asyncDirRoot, toolCallId) {
|
|
184
184
|
const runIds = [];
|
|
@@ -206,7 +206,7 @@ function readTerminalRunToolCallIndex(asyncDirRoot, toolCallId) {
|
|
|
206
206
|
}
|
|
207
207
|
function readRecentTerminalRunIndex(asyncDirRoot, options = {}) {
|
|
208
208
|
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);
|
|
209
|
+
const candidates = recentMarkerFiles(sessionDirs(asyncDirRoot, options.sessionId), limit, options.endedAfter);
|
|
210
210
|
const runIds = [];
|
|
211
211
|
const seen = /* @__PURE__ */ new Set();
|
|
212
212
|
for (const marker of candidates) {
|
|
@@ -742,11 +742,11 @@ function resolveInheritedNestedRoute(route) {
|
|
|
742
742
|
return void 0;
|
|
743
743
|
}
|
|
744
744
|
}
|
|
745
|
-
function inheritedNestedRouteOf(
|
|
746
|
-
return
|
|
745
|
+
function inheritedNestedRouteOf(runtime2) {
|
|
746
|
+
return runtime2?.nestedRoute ? resolveInheritedNestedRoute(runtime2.nestedRoute) : void 0;
|
|
747
747
|
}
|
|
748
|
-
function inheritedNestedParentAddressOf(
|
|
749
|
-
const parent =
|
|
748
|
+
function inheritedNestedParentAddressOf(runtime2) {
|
|
749
|
+
const parent = runtime2?.nestedParent;
|
|
750
750
|
if (!parent || !isSafeNestedId(parent.parentRunId)) return void 0;
|
|
751
751
|
const depth = Math.min(Math.max(1, clampNumber(parent.depth) ?? 1), MAX_DEPTH);
|
|
752
752
|
return {
|
|
@@ -5585,7 +5585,12 @@ function parsePersistedBinding(value, source) {
|
|
|
5585
5585
|
function readMissionBinding(asyncDir) {
|
|
5586
5586
|
const bindingPath = path12.join(asyncDir, MISSION_BINDING_FILE);
|
|
5587
5587
|
if (!fs11.existsSync(bindingPath)) return void 0;
|
|
5588
|
-
|
|
5588
|
+
const raw = fs11.readFileSync(bindingPath, "utf-8");
|
|
5589
|
+
try {
|
|
5590
|
+
return parsePersistedBinding(JSON.parse(raw), bindingPath);
|
|
5591
|
+
} catch (error) {
|
|
5592
|
+
throw new Error(`Invalid mission binding file '${bindingPath}': ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
5593
|
+
}
|
|
5589
5594
|
}
|
|
5590
5595
|
function syncMissionFromAsyncCompletion(value) {
|
|
5591
5596
|
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
@@ -6156,8 +6161,66 @@ function cleanupResultIndexes(resultsDir, now = Date.now(), maxAgeMs = 24 * 60 *
|
|
|
6156
6161
|
return removed;
|
|
6157
6162
|
}
|
|
6158
6163
|
|
|
6164
|
+
// src/shared/completion-owner.ts
|
|
6165
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
6166
|
+
var COMPLETION_OWNER_KEY = /* @__PURE__ */ Symbol.for("pi-subagents.completion-owner-id");
|
|
6167
|
+
var OWNING_SESSION_COMPLETION_OWNER = "owning-session";
|
|
6168
|
+
function currentCompletionOwnerId() {
|
|
6169
|
+
const runtime2 = globalThis;
|
|
6170
|
+
runtime2[COMPLETION_OWNER_KEY] ??= randomUUID6();
|
|
6171
|
+
return runtime2[COMPLETION_OWNER_KEY];
|
|
6172
|
+
}
|
|
6173
|
+
|
|
6174
|
+
// src/runs/background/boot-id.ts
|
|
6175
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
6176
|
+
import * as fs14 from "node:fs";
|
|
6177
|
+
|
|
6178
|
+
// src/runs/background/pid-namespace.ts
|
|
6179
|
+
import * as fs13 from "node:fs";
|
|
6180
|
+
var resolved = false;
|
|
6181
|
+
var cachedScope;
|
|
6182
|
+
function currentPidNamespaceScope() {
|
|
6183
|
+
if (resolved) return cachedScope;
|
|
6184
|
+
resolved = true;
|
|
6185
|
+
if (process.platform !== "linux") return void 0;
|
|
6186
|
+
try {
|
|
6187
|
+
const scope = fs13.readlinkSync("/proc/self/ns/pid", "utf-8").trim();
|
|
6188
|
+
cachedScope = scope || void 0;
|
|
6189
|
+
} catch {
|
|
6190
|
+
cachedScope = void 0;
|
|
6191
|
+
}
|
|
6192
|
+
return cachedScope;
|
|
6193
|
+
}
|
|
6194
|
+
|
|
6195
|
+
// src/runs/background/boot-id.ts
|
|
6196
|
+
function readBootIdFromOs() {
|
|
6197
|
+
try {
|
|
6198
|
+
if (process.platform === "linux") return fs14.readFileSync("/proc/sys/kernel/random/boot_id", "utf-8").trim() || void 0;
|
|
6199
|
+
if (process.platform === "darwin") {
|
|
6200
|
+
return execFileSync2("sysctl", ["-n", "kern.bootsessionuuid"], { encoding: "utf-8", timeout: 1e3, stdio: ["ignore", "pipe", "ignore"] }).trim() || void 0;
|
|
6201
|
+
}
|
|
6202
|
+
} catch {
|
|
6203
|
+
}
|
|
6204
|
+
return void 0;
|
|
6205
|
+
}
|
|
6206
|
+
var BOOT_ID_KEY = /* @__PURE__ */ Symbol.for("pi-subagents.boot-id.v1");
|
|
6207
|
+
var runtime = globalThis;
|
|
6208
|
+
var reader = readBootIdFromOs;
|
|
6209
|
+
function currentBootId() {
|
|
6210
|
+
const cached = runtime[BOOT_ID_KEY];
|
|
6211
|
+
if (cached) return cached.value;
|
|
6212
|
+
const value = reader();
|
|
6213
|
+
runtime[BOOT_ID_KEY] = { value };
|
|
6214
|
+
return value;
|
|
6215
|
+
}
|
|
6216
|
+
function currentRecordedPid() {
|
|
6217
|
+
const pidNamespaceScope = currentPidNamespaceScope();
|
|
6218
|
+
const bootId = currentBootId();
|
|
6219
|
+
return { pid: process.pid, ...pidNamespaceScope ? { pidNamespaceScope } : {}, ...bootId ? { bootId } : {} };
|
|
6220
|
+
}
|
|
6221
|
+
|
|
6159
6222
|
// src/runs/background/stale-run-reconciler.ts
|
|
6160
|
-
import * as
|
|
6223
|
+
import * as fs16 from "node:fs";
|
|
6161
6224
|
import * as path15 from "node:path";
|
|
6162
6225
|
|
|
6163
6226
|
// src/runs/background/parallel-groups.ts
|
|
@@ -6191,25 +6254,15 @@ function flatToLogicalStepIndex(flatIndex, chainStepCount, groups) {
|
|
|
6191
6254
|
return Math.max(0, chainStepCount - 1);
|
|
6192
6255
|
}
|
|
6193
6256
|
|
|
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;
|
|
6257
|
+
// src/workflows/workflow-stop-cause.ts
|
|
6258
|
+
var WORKFLOW_STOP_CAUSE_RUNTIME_REPLACED = "runtime-replaced";
|
|
6259
|
+
var WORKFLOW_STOP_CAUSE_OWNER_EXITED = "owner-exited";
|
|
6260
|
+
function isReusableWorkflowStopCause(cause) {
|
|
6261
|
+
return cause === WORKFLOW_STOP_CAUSE_RUNTIME_REPLACED || cause === WORKFLOW_STOP_CAUSE_OWNER_EXITED;
|
|
6209
6262
|
}
|
|
6210
6263
|
|
|
6211
6264
|
// src/runs/background/workflow-terminal-proof.ts
|
|
6212
|
-
import * as
|
|
6265
|
+
import * as fs15 from "node:fs";
|
|
6213
6266
|
import * as path14 from "node:path";
|
|
6214
6267
|
var TERMINAL_WORKFLOW_STATES = /* @__PURE__ */ new Set(["completed", "failed", "stopped"]);
|
|
6215
6268
|
function isTerminalAsyncState(state) {
|
|
@@ -6247,7 +6300,7 @@ function readWorkflowChildProcessEvidence(workflowAsyncDir, steps) {
|
|
|
6247
6300
|
}
|
|
6248
6301
|
function launchFailedBeforeRunner(step, childDir) {
|
|
6249
6302
|
if (step.status !== "failed" || !step.error) return false;
|
|
6250
|
-
return !childDir || !["process-terminal.json", "runner-startup.json"].some((file) =>
|
|
6303
|
+
return !childDir || !["process-terminal.json", "runner-startup.json"].some((file) => fs15.existsSync(path14.join(childDir, file)));
|
|
6251
6304
|
}
|
|
6252
6305
|
function readWorkflowChildEvidence(workflowAsyncDir, step) {
|
|
6253
6306
|
const label = step.workflowKey ?? step.agent;
|
|
@@ -6255,7 +6308,7 @@ function readWorkflowChildEvidence(workflowAsyncDir, step) {
|
|
|
6255
6308
|
if (!step.async) return void 0;
|
|
6256
6309
|
if (!step.runId || path14.basename(step.runId) !== step.runId) return { state: "unknown", reason: `async workflow child ${label} is missing run id` };
|
|
6257
6310
|
const childDir = path14.join(path14.dirname(workflowAsyncDir), step.runId);
|
|
6258
|
-
if (!
|
|
6311
|
+
if (!fs15.existsSync(childDir)) return launchFailedBeforeRunner(step) ? void 0 : { state: "unknown", reason: `async workflow child ${label} directory is missing` };
|
|
6259
6312
|
const childStatus = readStatus(childDir);
|
|
6260
6313
|
if (!childStatus) return launchFailedBeforeRunner(step, childDir) ? void 0 : { state: "unknown", reason: `async workflow child ${label} status is missing or unreadable` };
|
|
6261
6314
|
if (!isTerminalAsyncState(childStatus.state)) return { state: "pending", reason: `async workflow child ${label} is still ${childStatus.state}` };
|
|
@@ -6302,17 +6355,17 @@ function readRunnerStartupDiagnostics(asyncDir) {
|
|
|
6302
6355
|
const maxBytes = 64 * 1024;
|
|
6303
6356
|
let content;
|
|
6304
6357
|
try {
|
|
6305
|
-
const stat =
|
|
6358
|
+
const stat = fs16.statSync(stderrPath);
|
|
6306
6359
|
if (stat.size <= 0) return void 0;
|
|
6307
|
-
const fd =
|
|
6360
|
+
const fd = fs16.openSync(stderrPath, "r");
|
|
6308
6361
|
try {
|
|
6309
6362
|
const bytesToRead = Math.min(stat.size, maxBytes);
|
|
6310
6363
|
const start = Math.max(0, stat.size - bytesToRead);
|
|
6311
6364
|
const buffer = Buffer.alloc(bytesToRead);
|
|
6312
|
-
|
|
6365
|
+
fs16.readSync(fd, buffer, 0, bytesToRead, start);
|
|
6313
6366
|
content = buffer.toString("utf-8").trim();
|
|
6314
6367
|
} finally {
|
|
6315
|
-
|
|
6368
|
+
fs16.closeSync(fd);
|
|
6316
6369
|
}
|
|
6317
6370
|
} catch {
|
|
6318
6371
|
return void 0;
|
|
@@ -6327,15 +6380,15 @@ function isNotFoundError(error) {
|
|
|
6327
6380
|
}
|
|
6328
6381
|
function appendJsonlBestEffort(filePath, payload) {
|
|
6329
6382
|
try {
|
|
6330
|
-
|
|
6331
|
-
|
|
6383
|
+
fs16.mkdirSync(path15.dirname(filePath), { recursive: true });
|
|
6384
|
+
fs16.appendFileSync(filePath, `${JSON.stringify(payload)}
|
|
6332
6385
|
`, "utf-8");
|
|
6333
6386
|
} catch {
|
|
6334
6387
|
}
|
|
6335
6388
|
}
|
|
6336
6389
|
function regularFileExists(filePath) {
|
|
6337
6390
|
try {
|
|
6338
|
-
return
|
|
6391
|
+
return fs16.statSync(filePath).isFile();
|
|
6339
6392
|
} catch (error) {
|
|
6340
6393
|
if (isNotFoundError(error)) return false;
|
|
6341
6394
|
throw error;
|
|
@@ -6343,7 +6396,7 @@ function regularFileExists(filePath) {
|
|
|
6343
6396
|
}
|
|
6344
6397
|
function readResultRepairData(resultPath) {
|
|
6345
6398
|
try {
|
|
6346
|
-
const data = JSON.parse(
|
|
6399
|
+
const data = JSON.parse(fs16.readFileSync(resultPath, "utf-8"));
|
|
6347
6400
|
if (data.error !== void 0 && typeof data.error !== "string") throw new Error(`Invalid async result file '${resultPath}': error must be a string.`);
|
|
6348
6401
|
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
6402
|
const results = Array.isArray(data.results) ? data.results.map((entry, index) => {
|
|
@@ -6460,13 +6513,15 @@ function settledWorkflowChildStatus(asyncDir, workflowRunId, step, now) {
|
|
|
6460
6513
|
if (settled.stopped === void 0) delete settled.stopped;
|
|
6461
6514
|
return settled;
|
|
6462
6515
|
}
|
|
6463
|
-
function buildFailedRepair(status, asyncDir, now, reason) {
|
|
6516
|
+
function buildFailedRepair(status, asyncDir, now, reason, ownerExited = false, adoptCompletionOwnerId) {
|
|
6464
6517
|
const runId = status.runId || path15.basename(asyncDir);
|
|
6465
6518
|
const pid = typeof status.pid === "number" ? status.pid : "unknown";
|
|
6519
|
+
const exitedWorkflow = ownerExited && status.mode === "workflow" ? status.workflow : void 0;
|
|
6520
|
+
const completionOwnerId = exitedWorkflow ? adoptCompletionOwnerId || OWNING_SESSION_COMPLETION_OWNER : status.completionOwnerId;
|
|
6466
6521
|
const terminal3 = readProcessTerminal(asyncDir, { runId }) ?? status.processTerminal;
|
|
6467
6522
|
const runnerExit = terminal3?.state === "observed" || terminal3?.state === "unknown" ? terminal3.instances?.find((instance) => instance.kind === "runner" && instance.processInstanceId === terminal3.runnerProcessInstanceId) : void 0;
|
|
6468
6523
|
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
|
|
6524
|
+
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
6525
|
const diagnostics = readRunnerStartupDiagnostics(asyncDir);
|
|
6471
6526
|
const message = diagnostics ? `${baseMessage}
|
|
6472
6527
|
|
|
@@ -6502,7 +6557,10 @@ ${diagnostics}` : baseMessage;
|
|
|
6502
6557
|
activityState: void 0,
|
|
6503
6558
|
lastUpdate: now,
|
|
6504
6559
|
endedAt: now,
|
|
6505
|
-
steps: repairedSteps
|
|
6560
|
+
steps: repairedSteps,
|
|
6561
|
+
// Read from the pre-repair status: the repair time would make an old crash look new.
|
|
6562
|
+
...exitedWorkflow ? { workflow: { ...exitedWorkflow, stopCause: WORKFLOW_STOP_CAUSE_OWNER_EXITED, ownerExitedAt: status.lastUpdate ?? status.startedAt } } : {},
|
|
6563
|
+
...completionOwnerId ? { completionOwnerId } : {}
|
|
6506
6564
|
};
|
|
6507
6565
|
const resultAgent = repairedSteps[status.currentStep ?? 0]?.agent ?? repairedSteps[0]?.agent ?? "subagent";
|
|
6508
6566
|
return {
|
|
@@ -6512,7 +6570,9 @@ ${diagnostics}` : baseMessage;
|
|
|
6512
6570
|
id: runId,
|
|
6513
6571
|
agent: resultAgent,
|
|
6514
6572
|
mode: status.mode,
|
|
6515
|
-
...
|
|
6573
|
+
...exitedWorkflow ? { workflow: { stopCause: WORKFLOW_STOP_CAUSE_OWNER_EXITED } } : {},
|
|
6574
|
+
...completionOwnerId ? { completionOwnerId } : {},
|
|
6575
|
+
...status.completionOwnerProcess ? { completionOwnerProcess: status.completionOwnerProcess } : {},
|
|
6516
6576
|
...status.parentWorkflowRunId ? { parentWorkflowRunId: status.parentWorkflowRunId } : {},
|
|
6517
6577
|
...status.workflowKey ? { workflowKey: status.workflowKey } : {},
|
|
6518
6578
|
success: false,
|
|
@@ -6538,8 +6598,8 @@ ${diagnostics}` : baseMessage;
|
|
|
6538
6598
|
}
|
|
6539
6599
|
};
|
|
6540
6600
|
}
|
|
6541
|
-
function writeFailedRepair(asyncDir, status, resultPath, now, reason) {
|
|
6542
|
-
const repair = buildFailedRepair(status, asyncDir, now, reason);
|
|
6601
|
+
function writeFailedRepair(asyncDir, status, resultPath, now, reason, ownerExited = false, adoptCompletionOwnerId) {
|
|
6602
|
+
const repair = buildFailedRepair(status, asyncDir, now, reason, ownerExited, adoptCompletionOwnerId);
|
|
6543
6603
|
if (repair.result.sessionId) writeAsyncResultFile(resultPath, repair.result);
|
|
6544
6604
|
writeAtomicJson(path15.join(asyncDir, "status.json"), repair.status);
|
|
6545
6605
|
updateActiveRunIndex(asyncDir, repair.status.state, repair.status.toolCallId);
|
|
@@ -6599,7 +6659,7 @@ function checkPidLiveness(pid, kill = process.kill, probeZombie = false) {
|
|
|
6599
6659
|
kill(pid, 0);
|
|
6600
6660
|
if (probeZombie && process.platform === "linux") {
|
|
6601
6661
|
try {
|
|
6602
|
-
const stat =
|
|
6662
|
+
const stat = fs16.readFileSync(`/proc/${pid}/stat`, "utf-8");
|
|
6603
6663
|
const closeParen = stat.lastIndexOf(") ");
|
|
6604
6664
|
if (closeParen >= 0 && stat[closeParen + 2] === "Z") return "dead";
|
|
6605
6665
|
} catch {
|
|
@@ -6613,6 +6673,19 @@ function checkPidLiveness(pid, kill = process.kill, probeZombie = false) {
|
|
|
6613
6673
|
return "unknown";
|
|
6614
6674
|
}
|
|
6615
6675
|
}
|
|
6676
|
+
function isRecordedPid(value) {
|
|
6677
|
+
if (!value || typeof value !== "object") return false;
|
|
6678
|
+
const { pid, pidNamespaceScope, bootId } = value;
|
|
6679
|
+
return typeof pid === "number" && Number.isSafeInteger(pid) && pid > 0 && (pidNamespaceScope === void 0 || typeof pidNamespaceScope === "string") && (bootId === void 0 || typeof bootId === "string");
|
|
6680
|
+
}
|
|
6681
|
+
function checkRecordedPidLiveness(recorded, observation = { observedScope: currentPidNamespaceScope(), observedBootId: currentBootId() }) {
|
|
6682
|
+
const { observedScope, observedBootId } = observation;
|
|
6683
|
+
if (recorded.pidNamespaceScope === observedScope && recorded.bootId && observedBootId && recorded.bootId !== observedBootId) return "dead";
|
|
6684
|
+
const scopeMismatch = recorded.pidNamespaceScope !== void 0 && recorded.pidNamespaceScope !== observedScope;
|
|
6685
|
+
const scopeVerified = recorded.pidNamespaceScope !== void 0 && recorded.pidNamespaceScope === observedScope;
|
|
6686
|
+
const liveness = observation.probe ? observation.probe(recorded.pid) : checkPidLiveness(recorded.pid, observation.kill, scopeVerified);
|
|
6687
|
+
return liveness === "dead" && scopeMismatch ? "unknown" : liveness;
|
|
6688
|
+
}
|
|
6616
6689
|
function reconcileAsyncRun(asyncDir, options = {}, observeStatus) {
|
|
6617
6690
|
const now = options.now?.() ?? Date.now();
|
|
6618
6691
|
const status = readStatus(asyncDir);
|
|
@@ -6665,11 +6738,11 @@ function reconcileAsyncRun(asyncDir, options = {}, observeStatus) {
|
|
|
6665
6738
|
return { status: null, repaired: false, resultPath };
|
|
6666
6739
|
}
|
|
6667
6740
|
}
|
|
6668
|
-
const
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6741
|
+
const liveness = checkRecordedPidLiveness({ pid: effectiveStatus.pid, pidNamespaceScope: effectiveStatus.pidNamespaceScope, bootId: effectiveStatus.bootId }, {
|
|
6742
|
+
kill: options.kill,
|
|
6743
|
+
observedScope: options.pidNamespaceScope ? options.pidNamespaceScope() : currentPidNamespaceScope(),
|
|
6744
|
+
observedBootId: options.bootId ? options.bootId() : currentBootId()
|
|
6745
|
+
});
|
|
6673
6746
|
if (liveness !== "dead") {
|
|
6674
6747
|
const staleAfterMs = options.staleAlivePidMs ?? 24 * 60 * 60 * 1e3;
|
|
6675
6748
|
const lastUpdate = effectiveStatus.lastUpdate ?? effectiveStatus.startedAt;
|
|
@@ -6678,7 +6751,7 @@ function reconcileAsyncRun(asyncDir, options = {}, observeStatus) {
|
|
|
6678
6751
|
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
6752
|
return writeFailedRepair(asyncDir, effectiveStatus, resultPath, now, message);
|
|
6680
6753
|
}
|
|
6681
|
-
return writeFailedRepair(asyncDir, effectiveStatus, resultPath, now);
|
|
6754
|
+
return writeFailedRepair(asyncDir, effectiveStatus, resultPath, now, void 0, true, options.adoptCompletionOwnerId);
|
|
6682
6755
|
}
|
|
6683
6756
|
|
|
6684
6757
|
// src/policy/authority.ts
|
|
@@ -6908,7 +6981,7 @@ async function runSetupCommand(command, args, options) {
|
|
|
6908
6981
|
}
|
|
6909
6982
|
|
|
6910
6983
|
// src/runs/shared/worktree.ts
|
|
6911
|
-
import * as
|
|
6984
|
+
import * as fs17 from "node:fs";
|
|
6912
6985
|
import * as os2 from "node:os";
|
|
6913
6986
|
import * as path16 from "node:path";
|
|
6914
6987
|
var DEFAULT_WORKTREE_PROVIDER = "auto";
|
|
@@ -7045,7 +7118,7 @@ function currentWorktreePatch(worktreePath, baseCommit) {
|
|
|
7045
7118
|
assertWorktreeMutationAllowed();
|
|
7046
7119
|
let tempDir;
|
|
7047
7120
|
try {
|
|
7048
|
-
tempDir =
|
|
7121
|
+
tempDir = fs17.mkdtempSync(path16.join(os2.tmpdir(), "pi-worktree-index-"));
|
|
7049
7122
|
} catch (error) {
|
|
7050
7123
|
return { error: error instanceof Error ? error.message : String(error) };
|
|
7051
7124
|
}
|
|
@@ -7060,7 +7133,7 @@ function currentWorktreePatch(worktreePath, baseCommit) {
|
|
|
7060
7133
|
return { patch: diff.stdout };
|
|
7061
7134
|
} finally {
|
|
7062
7135
|
try {
|
|
7063
|
-
|
|
7136
|
+
fs17.rmSync(tempDir, { recursive: true, force: true });
|
|
7064
7137
|
} catch {
|
|
7065
7138
|
}
|
|
7066
7139
|
}
|
|
@@ -7070,7 +7143,7 @@ function validateWorktreePatchRepresentsCurrentWorktree(worktreePath, baseCommit
|
|
|
7070
7143
|
if (validationError) return validationError;
|
|
7071
7144
|
let capturedPatch;
|
|
7072
7145
|
try {
|
|
7073
|
-
capturedPatch =
|
|
7146
|
+
capturedPatch = fs17.readFileSync(patchPath, "utf-8");
|
|
7074
7147
|
} catch (error) {
|
|
7075
7148
|
return error instanceof Error ? error.message : String(error);
|
|
7076
7149
|
}
|
|
@@ -7124,9 +7197,9 @@ function normalizeComparableCwd(cwd) {
|
|
|
7124
7197
|
try {
|
|
7125
7198
|
let realpath;
|
|
7126
7199
|
try {
|
|
7127
|
-
realpath =
|
|
7200
|
+
realpath = fs17.realpathSync.native(existing);
|
|
7128
7201
|
} catch {
|
|
7129
|
-
realpath =
|
|
7202
|
+
realpath = fs17.realpathSync(existing);
|
|
7130
7203
|
}
|
|
7131
7204
|
return path16.join(realpath, ...missingSegments.reverse());
|
|
7132
7205
|
} catch {
|
|
@@ -7326,7 +7399,7 @@ function buildNativeProjectPath(dedicatedRoot, repoRoot) {
|
|
|
7326
7399
|
}
|
|
7327
7400
|
function ensureProjectWorktreeDir(dedicatedRoot, repoRoot) {
|
|
7328
7401
|
try {
|
|
7329
|
-
|
|
7402
|
+
fs17.mkdirSync(buildNativeProjectPath(dedicatedRoot, repoRoot), { recursive: true });
|
|
7330
7403
|
} catch (error) {
|
|
7331
7404
|
const message = error instanceof Error ? error.message : String(error);
|
|
7332
7405
|
throw new Error(`failed to create worktree base directory ${dedicatedRoot}: ${message}`);
|
|
@@ -7386,7 +7459,7 @@ function linkNodeModulesIfPresent(toplevel, worktreePath) {
|
|
|
7386
7459
|
const nodeModulesLinkPath = path16.join(worktreePath, "node_modules");
|
|
7387
7460
|
const hasDirectoryEntry = (candidate) => {
|
|
7388
7461
|
try {
|
|
7389
|
-
|
|
7462
|
+
fs17.lstatSync(candidate);
|
|
7390
7463
|
return true;
|
|
7391
7464
|
} catch (error) {
|
|
7392
7465
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") return false;
|
|
@@ -7397,14 +7470,14 @@ function linkNodeModulesIfPresent(toplevel, worktreePath) {
|
|
|
7397
7470
|
if (hasDirectoryEntry(nodeModulesLinkPath)) return false;
|
|
7398
7471
|
let sourceRealPath;
|
|
7399
7472
|
try {
|
|
7400
|
-
if (!
|
|
7401
|
-
sourceRealPath =
|
|
7473
|
+
if (!fs17.statSync(nodeModulesPath).isDirectory()) throw new Error("source node_modules is not a directory");
|
|
7474
|
+
sourceRealPath = fs17.realpathSync.native(nodeModulesPath);
|
|
7402
7475
|
} catch (error) {
|
|
7403
7476
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") return false;
|
|
7404
7477
|
throw error;
|
|
7405
7478
|
}
|
|
7406
|
-
|
|
7407
|
-
if (!
|
|
7479
|
+
fs17.symlinkSync(nodeModulesPath, nodeModulesLinkPath, process.platform === "win32" ? "junction" : "dir");
|
|
7480
|
+
if (!fs17.lstatSync(nodeModulesLinkPath).isSymbolicLink() || fs17.realpathSync.native(nodeModulesLinkPath) !== sourceRealPath) {
|
|
7408
7481
|
throw new Error("created link does not resolve to the source node_modules");
|
|
7409
7482
|
}
|
|
7410
7483
|
return true;
|
|
@@ -7438,10 +7511,10 @@ function resolveWorktreeSetupHook(repoRoot, config) {
|
|
|
7438
7511
|
} else {
|
|
7439
7512
|
throw new Error("worktree setup hook must be an absolute path or a repo-relative path");
|
|
7440
7513
|
}
|
|
7441
|
-
if (!
|
|
7514
|
+
if (!fs17.existsSync(resolvedPath)) {
|
|
7442
7515
|
throw new Error(`worktree setup hook not found: ${resolvedPath}`);
|
|
7443
7516
|
}
|
|
7444
|
-
if (
|
|
7517
|
+
if (fs17.statSync(resolvedPath).isDirectory()) {
|
|
7445
7518
|
throw new Error(`worktree setup hook must be a file, got directory: ${resolvedPath}`);
|
|
7446
7519
|
}
|
|
7447
7520
|
return {
|
|
@@ -7542,7 +7615,7 @@ async function createNativeWorktree(tx, toplevel, cwdRelative, runId, index, bas
|
|
|
7542
7615
|
const branch = await tx.git(toplevel, ["show-ref", "--verify", "--quiet", `refs/heads/${naming.requestedBranch}`], [0, 1]);
|
|
7543
7616
|
let pathExists = false;
|
|
7544
7617
|
try {
|
|
7545
|
-
|
|
7618
|
+
fs17.lstatSync(worktreePath);
|
|
7546
7619
|
pathExists = true;
|
|
7547
7620
|
} catch (error) {
|
|
7548
7621
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") throw error;
|
|
@@ -7594,7 +7667,7 @@ async function createWorktrunkWorktree(tx, toplevel, cwdRelative, runId, index,
|
|
|
7594
7667
|
const worktreePathCandidate = path16.resolve(output.path);
|
|
7595
7668
|
let stat;
|
|
7596
7669
|
try {
|
|
7597
|
-
stat =
|
|
7670
|
+
stat = fs17.lstatSync(worktreePathCandidate);
|
|
7598
7671
|
} catch (error) {
|
|
7599
7672
|
throw new Error(`Worktrunk provisioning returned a missing worktree path: ${worktreePathCandidate}`, { cause: error instanceof Error ? error : void 0 });
|
|
7600
7673
|
}
|
|
@@ -7637,21 +7710,21 @@ function removeSyntheticPath(worktree, syntheticPath) {
|
|
|
7637
7710
|
}
|
|
7638
7711
|
let stat;
|
|
7639
7712
|
try {
|
|
7640
|
-
stat =
|
|
7713
|
+
stat = fs17.lstatSync(resolved2);
|
|
7641
7714
|
} catch (error) {
|
|
7642
7715
|
const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
|
7643
7716
|
if (code === "ENOENT") return;
|
|
7644
7717
|
throw error;
|
|
7645
7718
|
}
|
|
7646
7719
|
if (stat.isSymbolicLink()) {
|
|
7647
|
-
|
|
7720
|
+
fs17.unlinkSync(resolved2);
|
|
7648
7721
|
return;
|
|
7649
7722
|
}
|
|
7650
7723
|
if (stat.isDirectory()) {
|
|
7651
|
-
|
|
7724
|
+
fs17.rmSync(resolved2, { recursive: true, force: true });
|
|
7652
7725
|
return;
|
|
7653
7726
|
}
|
|
7654
|
-
|
|
7727
|
+
fs17.rmSync(resolved2, { force: true });
|
|
7655
7728
|
}
|
|
7656
7729
|
function removeSyntheticPathsBeforeDiff(worktree) {
|
|
7657
7730
|
if (worktree.syntheticPaths.length === 0) return;
|
|
@@ -7695,7 +7768,7 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
|
|
|
7695
7768
|
const diffStat = runGitChecked(worktree.path, ["diff", "--cached", ...MACHINE_DIFF_OPTIONS, "--stat", setup.baseCommit]).trim();
|
|
7696
7769
|
const patch = runGitChecked(worktree.path, ["diff", "--cached", ...MACHINE_PATCH_OPTIONS, setup.baseCommit]);
|
|
7697
7770
|
const numstat = runGitChecked(worktree.path, ["diff", "--cached", ...MACHINE_DIFF_OPTIONS, "--numstat", setup.baseCommit]);
|
|
7698
|
-
|
|
7771
|
+
fs17.writeFileSync(patchPath, patch, "utf-8");
|
|
7699
7772
|
if (!patch.trim()) {
|
|
7700
7773
|
return emptyDiff(worktree.index, agent, worktree.branch, patchPath);
|
|
7701
7774
|
}
|
|
@@ -7715,14 +7788,14 @@ function captureWorktreeDiff(setup, worktree, agent, patchPath) {
|
|
|
7715
7788
|
}
|
|
7716
7789
|
function writeEmptyPatch(patchPath) {
|
|
7717
7790
|
try {
|
|
7718
|
-
|
|
7791
|
+
fs17.writeFileSync(patchPath, "", "utf-8");
|
|
7719
7792
|
} catch {
|
|
7720
7793
|
}
|
|
7721
7794
|
}
|
|
7722
7795
|
function handoffRecordsPatch(manifestPath, patchPath) {
|
|
7723
|
-
if (!manifestPath || !
|
|
7796
|
+
if (!manifestPath || !fs17.existsSync(manifestPath)) return false;
|
|
7724
7797
|
try {
|
|
7725
|
-
const manifest = JSON.parse(
|
|
7798
|
+
const manifest = JSON.parse(fs17.readFileSync(manifestPath, "utf-8"));
|
|
7726
7799
|
if (manifest.version !== 1 || !Array.isArray(manifest.groups)) return false;
|
|
7727
7800
|
const resolvedPatchPath = path16.resolve(patchPath);
|
|
7728
7801
|
return manifest.groups.some((group) => Array.isArray(group.children) && group.children.some(
|
|
@@ -7779,9 +7852,9 @@ function cleanupSingleWorktree(setup, worktree, intent) {
|
|
|
7779
7852
|
const captured = (intent.capturedDiffs ?? setup.capturedDiffs)?.find((diff) => diff.index === worktree.index);
|
|
7780
7853
|
let patchValidationError;
|
|
7781
7854
|
let patchCaptured = false;
|
|
7782
|
-
if (captured !== void 0 && captured.error === void 0 &&
|
|
7855
|
+
if (captured !== void 0 && captured.error === void 0 && fs17.existsSync(captured.patchPath) && handoffRecordsPatch(intent.handoffManifestPath, captured.patchPath)) {
|
|
7783
7856
|
try {
|
|
7784
|
-
if (
|
|
7857
|
+
if (fs17.statSync(captured.patchPath).size > 0) {
|
|
7785
7858
|
patchValidationError = validateWorktreePatchRepresentsCurrentWorktree(worktree.path, setup.baseCommit, captured.patchPath);
|
|
7786
7859
|
patchCaptured = patchValidationError === void 0;
|
|
7787
7860
|
}
|
|
@@ -7911,7 +7984,7 @@ async function compensateSetup(tx) {
|
|
|
7911
7984
|
throw new Error(tx.progress.unknown);
|
|
7912
7985
|
}
|
|
7913
7986
|
await git(["worktree", "remove", "--force", attempt.path]);
|
|
7914
|
-
} else if (
|
|
7987
|
+
} else if (fs17.existsSync(attempt.path)) {
|
|
7915
7988
|
tx.unknown("Unregistered partial allocation retained");
|
|
7916
7989
|
throw new Error(tx.progress.unknown);
|
|
7917
7990
|
}
|
|
@@ -8031,7 +8104,7 @@ async function createWorktrees(cwd, runId, count, options = {}) {
|
|
|
8031
8104
|
function diffWorktrees(setup, agents, diffsDir) {
|
|
8032
8105
|
assertWorktreeMutationAllowed();
|
|
8033
8106
|
try {
|
|
8034
|
-
|
|
8107
|
+
fs17.mkdirSync(diffsDir, { recursive: true });
|
|
8035
8108
|
} catch {
|
|
8036
8109
|
return [];
|
|
8037
8110
|
}
|
|
@@ -8216,7 +8289,14 @@ export {
|
|
|
8216
8289
|
resultCandidateFilesForToolCall,
|
|
8217
8290
|
missionObserverResultCandidateFiles,
|
|
8218
8291
|
cleanupResultIndexes,
|
|
8292
|
+
OWNING_SESSION_COMPLETION_OWNER,
|
|
8293
|
+
currentCompletionOwnerId,
|
|
8219
8294
|
currentPidNamespaceScope,
|
|
8295
|
+
currentBootId,
|
|
8296
|
+
currentRecordedPid,
|
|
8297
|
+
WORKFLOW_STOP_CAUSE_RUNTIME_REPLACED,
|
|
8298
|
+
WORKFLOW_STOP_CAUSE_OWNER_EXITED,
|
|
8299
|
+
isReusableWorkflowStopCause,
|
|
8220
8300
|
isTerminalAsyncState,
|
|
8221
8301
|
withWorkflowChildRunModel,
|
|
8222
8302
|
readWorkflowChildProcessEvidence,
|
|
@@ -8224,6 +8304,8 @@ export {
|
|
|
8224
8304
|
readWorkflowTerminalProof,
|
|
8225
8305
|
reconcileNestedAsyncDescendants,
|
|
8226
8306
|
checkPidLiveness,
|
|
8307
|
+
isRecordedPid,
|
|
8308
|
+
checkRecordedPidLiveness,
|
|
8227
8309
|
reconcileAsyncRun,
|
|
8228
8310
|
resolveAuthorityDecision,
|
|
8229
8311
|
validateAuthorityPolicy,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getProjectSubagentsDir
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5TYMSZX3.js";
|
|
4
4
|
import {
|
|
5
5
|
discoverAgents,
|
|
6
6
|
formatUnknownAgentError,
|
|
7
7
|
resolveAgentName,
|
|
8
8
|
unknownAgentDiagnosticContext
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-CIZQXJ5Q.js";
|
|
10
10
|
|
|
11
11
|
// src/agents/agent-refinements.ts
|
|
12
12
|
import { createHash, randomUUID } from "node:crypto";
|