pi-crew 0.9.39 → 0.9.40
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 +14 -0
- package/dist/build-meta.json +11 -11
- package/dist/index.mjs +56 -7
- package/dist/index.mjs.map +2 -2
- package/package.json +1 -1
- package/src/runtime/run-coalesced-task-group.ts +6 -6
- package/src/runtime/stale-reconciler.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.9.40] — stale-reconciler fix + async dispatch + gitignore cleanup (2026-07-16)
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
- **Stale-reconciler `needs_attention` status inference** — `src/runtime/stale-reconciler.ts`. When all tasks end in `needs_attention` (no explicit failure), `reconcileStaleRun` previously marked the run `completed`. This contradicted the codebase convention in `chain-executor.ts:147` (treating `needs_attention` as a non-clean terminal). Now includes `needs_attention` in the `hasFailed` predicate, marking the run `failed` instead. Tests cover: all-`needs_attention` → failed; mix `needs_attention`+completed → failed.
|
|
8
|
+
|
|
9
|
+
### Performance
|
|
10
|
+
|
|
11
|
+
- **Async `saveRunTasks` in `runCoalescedTaskGroup`** — `src/runtime/run-coalesced-task-group.ts`. Replaced 4 synchronous `saveRunTasks` calls with `await saveRunTasksAsync` (from `state-store.ts:493`). The heartbeat `setInterval` callback was promoted to `async () =>` to support the await. With many coalesced groups running in parallel these sync writes blocked the event loop briefly; the async version uses `withRunLock` (non-blocking). No behavioral change.
|
|
12
|
+
|
|
13
|
+
### Cleanup
|
|
14
|
+
|
|
15
|
+
- **`src/**/*.js` gitignored** — `.gitignore`. 290 strip-types companion files in `src/` were untracked noise in `git status`. Added `src/**/*.js` rule. No runtime impact.
|
|
16
|
+
|
|
3
17
|
## [0.9.39] — foreground abort fix + security hardening (2026-07-15)
|
|
4
18
|
|
|
5
19
|
### Fixes
|
package/dist/build-meta.json
CHANGED
|
@@ -6175,7 +6175,7 @@
|
|
|
6175
6175
|
"format": "esm"
|
|
6176
6176
|
},
|
|
6177
6177
|
"src/state/locks.ts": {
|
|
6178
|
-
"bytes":
|
|
6178
|
+
"bytes": 17045,
|
|
6179
6179
|
"imports": [
|
|
6180
6180
|
{
|
|
6181
6181
|
"path": "node:crypto",
|
|
@@ -6598,7 +6598,7 @@
|
|
|
6598
6598
|
"format": "esm"
|
|
6599
6599
|
},
|
|
6600
6600
|
"src/state/state-store.ts": {
|
|
6601
|
-
"bytes":
|
|
6601
|
+
"bytes": 40424,
|
|
6602
6602
|
"imports": [
|
|
6603
6603
|
{
|
|
6604
6604
|
"path": "node:fs",
|
|
@@ -6794,7 +6794,7 @@
|
|
|
6794
6794
|
"format": "esm"
|
|
6795
6795
|
},
|
|
6796
6796
|
"src/runtime/stale-reconciler.ts": {
|
|
6797
|
-
"bytes":
|
|
6797
|
+
"bytes": 28694,
|
|
6798
6798
|
"imports": [
|
|
6799
6799
|
{
|
|
6800
6800
|
"path": "node:fs",
|
|
@@ -14343,7 +14343,7 @@
|
|
|
14343
14343
|
"format": "esm"
|
|
14344
14344
|
},
|
|
14345
14345
|
"src/runtime/run-coalesced-task-group.ts": {
|
|
14346
|
-
"bytes":
|
|
14346
|
+
"bytes": 9281,
|
|
14347
14347
|
"imports": [
|
|
14348
14348
|
{
|
|
14349
14349
|
"path": "node:fs/promises",
|
|
@@ -18003,7 +18003,7 @@
|
|
|
18003
18003
|
"format": "esm"
|
|
18004
18004
|
},
|
|
18005
18005
|
"src/extension/register.ts": {
|
|
18006
|
-
"bytes":
|
|
18006
|
+
"bytes": 70731,
|
|
18007
18007
|
"imports": [
|
|
18008
18008
|
{
|
|
18009
18009
|
"path": "node:fs",
|
|
@@ -18425,7 +18425,7 @@
|
|
|
18425
18425
|
"imports": [],
|
|
18426
18426
|
"exports": [],
|
|
18427
18427
|
"inputs": {},
|
|
18428
|
-
"bytes":
|
|
18428
|
+
"bytes": 6709812
|
|
18429
18429
|
},
|
|
18430
18430
|
"dist/index.mjs": {
|
|
18431
18431
|
"imports": [
|
|
@@ -20704,7 +20704,7 @@
|
|
|
20704
20704
|
"bytesInOutput": 1803
|
|
20705
20705
|
},
|
|
20706
20706
|
"src/state/state-store.ts": {
|
|
20707
|
-
"bytesInOutput":
|
|
20707
|
+
"bytesInOutput": 20475
|
|
20708
20708
|
},
|
|
20709
20709
|
"src/utils/file-coalescer.ts": {
|
|
20710
20710
|
"bytesInOutput": 1204
|
|
@@ -20725,7 +20725,7 @@
|
|
|
20725
20725
|
"bytesInOutput": 4162
|
|
20726
20726
|
},
|
|
20727
20727
|
"src/runtime/stale-reconciler.ts": {
|
|
20728
|
-
"bytesInOutput":
|
|
20728
|
+
"bytesInOutput": 16532
|
|
20729
20729
|
},
|
|
20730
20730
|
"src/runtime/worker-heartbeat.ts": {
|
|
20731
20731
|
"bytesInOutput": 580
|
|
@@ -21733,7 +21733,7 @@
|
|
|
21733
21733
|
"bytesInOutput": 7286
|
|
21734
21734
|
},
|
|
21735
21735
|
"src/runtime/run-coalesced-task-group.ts": {
|
|
21736
|
-
"bytesInOutput":
|
|
21736
|
+
"bytesInOutput": 6363
|
|
21737
21737
|
},
|
|
21738
21738
|
"src/runtime/runtime-policy.ts": {
|
|
21739
21739
|
"bytesInOutput": 575
|
|
@@ -22030,7 +22030,7 @@
|
|
|
22030
22030
|
"bytesInOutput": 3150
|
|
22031
22031
|
},
|
|
22032
22032
|
"src/extension/register.ts": {
|
|
22033
|
-
"bytesInOutput":
|
|
22033
|
+
"bytesInOutput": 47211
|
|
22034
22034
|
},
|
|
22035
22035
|
"src/runtime/batch-barrier.ts": {
|
|
22036
22036
|
"bytesInOutput": 3060
|
|
@@ -22135,7 +22135,7 @@
|
|
|
22135
22135
|
"bytesInOutput": 81
|
|
22136
22136
|
}
|
|
22137
22137
|
},
|
|
22138
|
-
"bytes":
|
|
22138
|
+
"bytes": 3177730
|
|
22139
22139
|
}
|
|
22140
22140
|
}
|
|
22141
22141
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -13483,6 +13483,9 @@ function validateRunManifestPaths(cwd, runId, manifest, stateRoot, tasksPath) {
|
|
|
13483
13483
|
return true;
|
|
13484
13484
|
}
|
|
13485
13485
|
function createRunPaths(cwd, runId = createRunId()) {
|
|
13486
|
+
if (!cwd || typeof cwd !== "string") {
|
|
13487
|
+
throw new Error(`Invalid cwd: ${cwd}`);
|
|
13488
|
+
}
|
|
13486
13489
|
assertSafePathId("runId", runId);
|
|
13487
13490
|
const baseRoot = scopeBaseRoot(cwd);
|
|
13488
13491
|
const stateRoot = resolveContainedRelativePath(path11.join(baseRoot, DEFAULT_PATHS.state.runsSubdir), runId, "runId");
|
|
@@ -14998,7 +15001,7 @@ function checkResultFile(manifest, tasks) {
|
|
|
14998
15001
|
(t2) => t2.status === "completed" || t2.status === "failed" || t2.status === "cancelled" || t2.status === "skipped" || t2.status === "needs_attention"
|
|
14999
15002
|
);
|
|
15000
15003
|
if (allTerminal) {
|
|
15001
|
-
const hasFailed = tasks.some((t2) => t2.status === "failed");
|
|
15004
|
+
const hasFailed = tasks.some((t2) => t2.status === "failed" || t2.status === "needs_attention");
|
|
15002
15005
|
const onlyCancelledOrSkipped = tasks.every((t2) => t2.status === "cancelled" || t2.status === "skipped");
|
|
15003
15006
|
manifest.status = hasFailed ? "failed" : onlyCancelledOrSkipped ? "cancelled" : "completed";
|
|
15004
15007
|
saveRunManifest(manifest);
|
|
@@ -55557,7 +55560,7 @@ async function runCoalescedTaskGroup(input) {
|
|
|
55557
55560
|
}
|
|
55558
55561
|
return t2;
|
|
55559
55562
|
});
|
|
55560
|
-
|
|
55563
|
+
await saveRunTasksAsync(manifest, updatedTasks);
|
|
55561
55564
|
await appendEventAsync(manifest.eventsPath, {
|
|
55562
55565
|
type: "task.coalesced_dispatch_start",
|
|
55563
55566
|
runId: manifest.runId,
|
|
@@ -55572,14 +55575,14 @@ async function runCoalescedTaskGroup(input) {
|
|
|
55572
55575
|
heartbeat: t2.heartbeat ?? createWorkerHeartbeat(t2.id)
|
|
55573
55576
|
};
|
|
55574
55577
|
});
|
|
55575
|
-
|
|
55578
|
+
await saveRunTasksAsync(manifest, updatedTasks);
|
|
55576
55579
|
let rawOutput = "";
|
|
55577
55580
|
let success = false;
|
|
55578
55581
|
if (!executeWorkers) {
|
|
55579
55582
|
rawOutput = buildScaffoldOutput(groupTasks);
|
|
55580
55583
|
success = true;
|
|
55581
55584
|
} else {
|
|
55582
|
-
const heartbeatTimer = setInterval(() => {
|
|
55585
|
+
const heartbeatTimer = setInterval(async () => {
|
|
55583
55586
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
55584
55587
|
updatedTasks = updatedTasks.map((t2) => {
|
|
55585
55588
|
if (!taskIds.includes(t2.id)) return t2;
|
|
@@ -55589,7 +55592,7 @@ async function runCoalescedTaskGroup(input) {
|
|
|
55589
55592
|
};
|
|
55590
55593
|
});
|
|
55591
55594
|
try {
|
|
55592
|
-
|
|
55595
|
+
await saveRunTasksAsync(manifest, updatedTasks);
|
|
55593
55596
|
} catch {
|
|
55594
55597
|
}
|
|
55595
55598
|
}, 15e3);
|
|
@@ -55639,7 +55642,7 @@ async function runCoalescedTaskGroup(input) {
|
|
|
55639
55642
|
resultArtifact
|
|
55640
55643
|
};
|
|
55641
55644
|
});
|
|
55642
|
-
|
|
55645
|
+
await saveRunTasksAsync(manifest, updatedTasks);
|
|
55643
55646
|
let updatedManifest = {
|
|
55644
55647
|
...manifest,
|
|
55645
55648
|
artifacts: mergeArtifacts([...manifest.artifacts, ...newArtifacts])
|
|
@@ -85061,6 +85064,45 @@ Subagent may need manual intervention.`
|
|
|
85061
85064
|
return loaded.tasks.some((t2) => t2.status === "running" || t2.status === "queued");
|
|
85062
85065
|
};
|
|
85063
85066
|
});
|
|
85067
|
+
const cleanupSessionResourcesOnly = () => {
|
|
85068
|
+
if (cleanedUp) return;
|
|
85069
|
+
cleanedUp = true;
|
|
85070
|
+
if (preloadTimer) {
|
|
85071
|
+
clearTimeout(preloadTimer);
|
|
85072
|
+
preloadTimer = void 0;
|
|
85073
|
+
}
|
|
85074
|
+
crewRunWatchers?.closeAll();
|
|
85075
|
+
crewRunWatchers = void 0;
|
|
85076
|
+
userCrewWatchers?.closeAll();
|
|
85077
|
+
userCrewWatchers = void 0;
|
|
85078
|
+
stopSessionBoundSubagents();
|
|
85079
|
+
crewScheduler?.stop();
|
|
85080
|
+
stopAsyncRunNotifier(notifierState);
|
|
85081
|
+
purgeStaleActiveRunIndexSyncIfLoaded();
|
|
85082
|
+
stopCrewWidget(currentCtx, widgetState, currentCtx ? loadConfig(currentCtx.cwd).config.ui : void 0);
|
|
85083
|
+
clearPiCrewPowerbar(pi.events);
|
|
85084
|
+
disposePowerbarCoalescer();
|
|
85085
|
+
disposeObservability(observabilityState, cleanedUp);
|
|
85086
|
+
lifecycleState.deliveryCoordinator?.dispose();
|
|
85087
|
+
clearHooksScoped();
|
|
85088
|
+
uninstallCrewGlobalRegistry();
|
|
85089
|
+
lifecycleState.overflowTracker?.dispose();
|
|
85090
|
+
lifecycleState.deliveryCoordinator = void 0;
|
|
85091
|
+
lifecycleState.overflowTracker = void 0;
|
|
85092
|
+
manifestCache2.dispose();
|
|
85093
|
+
runSnapshotCache.dispose?.();
|
|
85094
|
+
clearProjectRootCache();
|
|
85095
|
+
renderScheduler?.dispose();
|
|
85096
|
+
renderScheduler = void 0;
|
|
85097
|
+
autoRecoveryLast.clear();
|
|
85098
|
+
disposeNotifications(lifecycleState);
|
|
85099
|
+
rpcHandle?.unsubscribe();
|
|
85100
|
+
rpcHandle = void 0;
|
|
85101
|
+
disposeI18n();
|
|
85102
|
+
sessionGeneration += 1;
|
|
85103
|
+
currentCtx = void 0;
|
|
85104
|
+
if (globalStore[runtimeCleanupStoreKey] === cleanupSessionResourcesOnly) delete globalStore[runtimeCleanupStoreKey];
|
|
85105
|
+
};
|
|
85064
85106
|
const cleanupRuntime = () => {
|
|
85065
85107
|
if (cleanedUp) return;
|
|
85066
85108
|
cleanedUp = true;
|
|
@@ -85103,6 +85145,14 @@ Subagent may need manual intervention.`
|
|
|
85103
85145
|
if (globalStore[runtimeCleanupStoreKey] === cleanupRuntime) delete globalStore[runtimeCleanupStoreKey];
|
|
85104
85146
|
};
|
|
85105
85147
|
globalStore[runtimeCleanupStoreKey] = cleanupRuntime;
|
|
85148
|
+
pi.on("session_shutdown", (event) => {
|
|
85149
|
+
const reason = typeof event === "object" && event !== null && "reason" in event ? event.reason : void 0;
|
|
85150
|
+
if (reason === "quit" || reason === "reload") {
|
|
85151
|
+
cleanupRuntime();
|
|
85152
|
+
} else {
|
|
85153
|
+
cleanupSessionResourcesOnly();
|
|
85154
|
+
}
|
|
85155
|
+
});
|
|
85106
85156
|
pi.on("session_start", (_event, ctx) => {
|
|
85107
85157
|
runArtifactCleanup(ctx.cwd);
|
|
85108
85158
|
try {
|
|
@@ -85583,7 +85633,6 @@ Subagent may need manual intervention.`
|
|
|
85583
85633
|
stopAsyncRunNotifier(notifierState);
|
|
85584
85634
|
stopSessionBoundSubagents();
|
|
85585
85635
|
});
|
|
85586
|
-
pi.on("session_shutdown", () => cleanupRuntime());
|
|
85587
85636
|
try {
|
|
85588
85637
|
pi.on("resources_discover", () => {
|
|
85589
85638
|
const sessionCwd = currentCtx?.cwd ?? process.cwd();
|