pi-crew 0.9.41 → 0.9.44
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 +253 -0
- package/README.md +14 -0
- package/dist/build-meta.json +6450 -12419
- package/dist/index.mjs +57998 -68417
- package/dist/index.mjs.map +4 -4
- package/docs/migration/atomic-write-v2-migration.md +2 -0
- package/docs/superpowers/plans/2026-06-09-fallow-patterns-adoption.md +2 -0
- package/package.json +4 -2
- package/scripts/README.md +6 -0
- package/scripts/build-bundle.mjs +2 -1
- package/scripts/check-all-skills.ts +3 -3
- package/scripts/dev-runner.mjs +106 -0
- package/scripts/postinstall.mjs +6 -2
- package/scripts/verify-skill.ts +2 -2
- package/src/agents/agent-config.ts +1 -1
- package/src/config/config.ts +20 -1
- package/src/config/drift-detector.ts +97 -15
- package/src/config/resilient-parser.ts +4 -4
- package/src/config/types.ts +0 -2
- package/src/extension/crew-cleanup.ts +17 -3
- package/src/extension/crew-vibes/config.ts +1 -1
- package/src/extension/crew-vibes/font-detect.ts +16 -3
- package/src/extension/crew-vibes/index.ts +1 -1
- package/src/extension/cross-extension-rpc.ts +26 -9
- package/src/extension/management.ts +6 -5
- package/src/extension/register.ts +58 -1573
- package/src/extension/registration/command-registration.ts +57 -0
- package/src/extension/registration/commands.ts +7 -2
- package/src/extension/registration/context-builder.ts +131 -0
- package/src/extension/registration/crash-recovery-cache.ts +54 -0
- package/src/extension/registration/foreground-run-controller.ts +238 -0
- package/src/extension/registration/hook-registration.ts +119 -0
- package/src/extension/registration/lazy-configurers.ts +124 -0
- package/src/extension/registration/lifecycle-handlers.ts +731 -0
- package/src/extension/registration/observability.ts +33 -4
- package/src/extension/registration/registration-types.ts +149 -0
- package/src/extension/registration/runtime-cleanup.ts +230 -0
- package/src/extension/registration/subagent-manager-setup.ts +211 -0
- package/src/extension/registration/tool-registration.ts +50 -0
- package/src/extension/registration/wire-cross-extension.ts +37 -0
- package/src/extension/rpc-hmac.ts +21 -1
- package/src/extension/run-import.ts +3 -3
- package/src/extension/team-tool/auto-summarize.ts +4 -4
- package/src/extension/team-tool/cancel.ts +5 -5
- package/src/extension/team-tool/chain-executor.ts +5 -4
- package/src/extension/team-tool/context.ts +11 -1
- package/src/extension/team-tool/doctor.ts +2 -1
- package/src/extension/team-tool/goal-wrap.ts +2 -2
- package/src/extension/team-tool/goal.ts +1 -1
- package/src/extension/team-tool/handle-schedule.ts +25 -36
- package/src/extension/team-tool/orchestrate.ts +0 -1
- package/src/extension/team-tool/parallel-dispatch.ts +5 -0
- package/src/extension/team-tool/run.ts +220 -214
- package/src/extension/team-tool/workflow-manage.ts +1 -1
- package/src/extension/team-tool.ts +69 -16
- package/src/hooks/registry.ts +7 -2
- package/src/observability/correlation.ts +4 -3
- package/src/observability/event-bus.ts +10 -1
- package/src/observability/event-to-metric.ts +8 -7
- package/src/observability/exporters/adapter.ts +6 -9
- package/src/observability/exporters/otlp-exporter.ts +81 -0
- package/src/observability/metric-retention.ts +4 -0
- package/src/observability/metric-sink.ts +14 -4
- package/src/prompt/prompt-runtime.ts +15 -0
- package/src/runtime/adaptive-plan.ts +1 -1
- package/src/runtime/async-runner.ts +13 -4
- package/src/runtime/background-runner.ts +32 -23
- package/src/runtime/capability-inventory.ts +1 -1
- package/src/runtime/chain-runner.ts +5 -5
- package/src/runtime/checkpoint.ts +6 -16
- package/src/runtime/child-pi-constants.ts +42 -0
- package/src/runtime/child-pi-kill.ts +180 -0
- package/src/runtime/child-pi-spawn.ts +234 -0
- package/src/runtime/child-pi-steering.ts +128 -0
- package/src/runtime/child-pi-streams.ts +296 -0
- package/src/runtime/child-pi-transcript.ts +169 -0
- package/src/runtime/child-pi.ts +80 -822
- package/src/runtime/coalesce-tasks.ts +1 -1
- package/src/runtime/compact-stages/tail-capture-stage.ts +1 -1
- package/src/runtime/crash-recovery.ts +63 -47
- package/src/runtime/delivery-coordinator.ts +1 -1
- package/src/runtime/deterministic-ast.ts +2 -2
- package/src/runtime/diagnostic-export.ts +2 -1
- package/src/runtime/dwf-state-store.ts +5 -0
- package/src/runtime/dynamic-workflow-context.ts +78 -18
- package/src/runtime/dynamic-workflow-runner.ts +18 -2
- package/src/runtime/foreground-control.ts +3 -2
- package/src/runtime/goal-evaluator.ts +59 -27
- package/src/runtime/goal-loop-runner.ts +46 -13
- package/src/runtime/goal-state-store.ts +1 -1
- package/src/runtime/handoff-manager.ts +0 -2
- package/src/runtime/intercom-bridge.ts +0 -2
- package/src/runtime/live-agent-manager.ts +30 -5
- package/src/runtime/live-extension-bridge.ts +0 -2
- package/src/runtime/live-session-runtime.ts +65 -57
- package/src/runtime/manifest-cache.ts +59 -0
- package/src/runtime/mcp-proxy.ts +1 -1
- package/src/runtime/orphan-worker-registry.ts +3 -3
- package/src/runtime/output-validator.ts +1 -1
- package/src/runtime/path-overlap.ts +1 -1
- package/src/runtime/pi-args.ts +3 -3
- package/src/runtime/pi-json-output.ts +4 -3
- package/src/runtime/pi-spawn.ts +7 -1
- package/src/runtime/pipeline-runner.ts +1 -4
- package/src/runtime/post-checks.ts +0 -1
- package/src/runtime/retry-runner.ts +1 -1
- package/src/runtime/run-coalesced-task-group.ts +18 -23
- package/src/runtime/scheduler.ts +2 -0
- package/src/runtime/session-resources.ts +1 -1
- package/src/runtime/settings-store.ts +31 -1
- package/src/runtime/skill-effectiveness.ts +2 -2
- package/src/runtime/stale-reconciler.ts +23 -53
- package/src/runtime/subagent-manager.ts +19 -3
- package/src/runtime/task-output-context.ts +2 -1
- package/src/runtime/task-runner/prompt-builder.ts +3 -3
- package/src/runtime/task-runner/run-projection.ts +3 -1
- package/src/runtime/task-runner/state-helpers.ts +13 -1
- package/src/runtime/task-runner.ts +31 -6
- package/src/runtime/team-runner.ts +8 -2
- package/src/runtime/verification-gates.ts +54 -5
- package/src/schema/config-schema.ts +19 -1
- package/src/schema/team-tool-schema.ts +2 -0
- package/src/skills/discover-skills.ts +25 -15
- package/src/state/active-run-registry.ts +0 -1
- package/src/state/atomic-write.ts +37 -11
- package/src/state/blob-store.ts +3 -9
- package/src/state/contracts.ts +5 -1
- package/src/state/crew-init.ts +3 -2
- package/src/state/decision-ledger.ts +2 -2
- package/src/state/event-log-rotation.ts +1 -1
- package/src/state/event-log.ts +4 -3
- package/src/state/gitignore-manager.ts +2 -1
- package/src/state/health-store.ts +5 -2
- package/src/state/instinct-store.ts +11 -2
- package/src/state/locks.ts +132 -49
- package/src/state/mailbox.ts +3 -4
- package/src/state/observation-store.ts +1 -13
- package/src/state/run-cache.ts +12 -12
- package/src/state/run-graph.ts +2 -1
- package/src/state/run-metrics.ts +1 -1
- package/src/state/schedule.ts +7 -1
- package/src/state/state-store.ts +9 -3
- package/src/state/tiered-eval.ts +1 -1
- package/src/state/worker-atomic-writer.ts +1 -0
- package/src/ui/dynamic-border.ts +13 -3
- package/src/ui/live-conversation-overlay.ts +7 -27
- package/src/ui/live-duration.ts +2 -2
- package/src/ui/live-run-sidebar.ts +56 -32
- package/src/ui/mascot.ts +19 -13
- package/src/ui/powerbar-publisher.ts +244 -178
- package/src/ui/render-coalescer.ts +44 -3
- package/src/ui/render-diff.ts +2 -2
- package/src/ui/run-dashboard.ts +122 -21
- package/src/ui/run-event-bus.ts +66 -0
- package/src/ui/run-snapshot-cache.ts +84 -81
- package/src/ui/settings-overlay.ts +3 -3
- package/src/ui/status-colors.ts +24 -0
- package/src/ui/tool-progress-formatter.ts +1 -1
- package/src/ui/tool-render.ts +3 -3
- package/src/ui/transcript-cache.ts +5 -10
- package/src/ui/transcript-entries.ts +68 -72
- package/src/ui/transcript-viewer.ts +54 -14
- package/src/ui/widget/index.ts +26 -15
- package/src/ui/widget/widget-model.ts +18 -9
- package/src/ui/widget/widget-renderer.ts +2 -5
- package/src/utils/fingerprint.ts +1 -1
- package/src/utils/paths.ts +1 -1
- package/src/utils/project-detector.ts +1 -1
- package/src/worktree/worktree-manager.ts +47 -19
- package/src/state/atomic-write-v2.ts +0 -108
|
@@ -134,7 +134,11 @@ export function findGitRoot(cwd: string): string {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
export function assertCleanLeader(repoRoot: string): void {
|
|
137
|
-
|
|
137
|
+
// H-7 follow-up: --untracked-files=no so pi-crew's own auto-created .gitignore
|
|
138
|
+
// (and any other untracked files the user hasn't staged) doesn't block worktree mode.
|
|
139
|
+
// The worktree contract is "no tracked changes" — untracked files are safe since
|
|
140
|
+
// they're either in .gitignore or the user can decide later.
|
|
141
|
+
const status = git(repoRoot, ["status", "--porcelain", "--untracked-files=no"]);
|
|
138
142
|
if (status.trim()) {
|
|
139
143
|
throw new Error("Worktree mode requires a clean leader repository. Commit/stash changes or use workspaceMode: 'single'.");
|
|
140
144
|
}
|
|
@@ -168,7 +172,9 @@ export function clearCleanLeaderCache(): void {
|
|
|
168
172
|
|
|
169
173
|
export async function assertCleanLeaderAsync(repoRoot: string): Promise<void> {
|
|
170
174
|
if (_cleanLeaderCache.has(repoRoot)) return;
|
|
171
|
-
|
|
175
|
+
// H-7 follow-up: --untracked-files=no so pi-crew's own auto-created .gitignore
|
|
176
|
+
// (and any other untracked files the user hasn't staged) doesn't block worktree mode.
|
|
177
|
+
const status = await gitAsync(repoRoot, ["status", "--porcelain", "--untracked-files=no"]);
|
|
172
178
|
if (status.trim()) {
|
|
173
179
|
throw new Error("Worktree mode requires a clean leader repository. Commit/stash changes or use workspaceMode: 'single'.");
|
|
174
180
|
}
|
|
@@ -558,7 +564,7 @@ export function overlaySeedPaths(repoRoot: string, worktreePath: string, seedPat
|
|
|
558
564
|
* recovered via `git apply` / manual restore. Best-effort: a snapshot failure
|
|
559
565
|
* only logs (it must not block the clean-slate reuse flow).
|
|
560
566
|
*/
|
|
561
|
-
function snapshotDirtyWorktree(manifest: TeamRunManifest, task: TeamTaskState, worktreePath: string, dirtyStatus: string):
|
|
567
|
+
function snapshotDirtyWorktree(manifest: TeamRunManifest, task: TeamTaskState, worktreePath: string, dirtyStatus: string): boolean {
|
|
562
568
|
try {
|
|
563
569
|
const parts: string[] = [
|
|
564
570
|
`# Worktree recovery snapshot`,
|
|
@@ -596,12 +602,14 @@ function snapshotDirtyWorktree(manifest: TeamRunManifest, task: TeamTaskState, w
|
|
|
596
602
|
producer: "worktree-manager.snapshotDirtyWorktree",
|
|
597
603
|
retention: "run",
|
|
598
604
|
});
|
|
605
|
+
return true;
|
|
599
606
|
} catch (err) {
|
|
600
607
|
logInternalError(
|
|
601
608
|
"worktree.recovery.snapshotFailed",
|
|
602
609
|
err instanceof Error ? err : new Error(String(err)),
|
|
603
610
|
`runId=${manifest.runId}, taskId=${task.id}`,
|
|
604
611
|
);
|
|
612
|
+
return false;
|
|
605
613
|
}
|
|
606
614
|
}
|
|
607
615
|
|
|
@@ -722,14 +730,24 @@ export function prepareTaskWorkspace(manifest: TeamRunManifest, task: TeamTaskSt
|
|
|
722
730
|
if (dirtyStatus.trim()) {
|
|
723
731
|
// Snapshot uncommitted work to a recovery artifact BEFORE discarding, so the
|
|
724
732
|
// previous run's changes are never silently destroyed on reuse.
|
|
725
|
-
snapshotDirtyWorktree(manifest, task, worktreePath, dirtyStatus);
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
+
const snapshotOk = snapshotDirtyWorktree(manifest, task, worktreePath, dirtyStatus);
|
|
734
|
+
if (snapshotOk) {
|
|
735
|
+
logInternalError(
|
|
736
|
+
"worktree.reused.dirty",
|
|
737
|
+
new Error(`Discarding uncommitted changes in reused worktree at ${worktreePath} (snapshot saved to artifacts)`),
|
|
738
|
+
`runId=${manifest.runId}, taskId=${task.id}, dirtyStatus=${dirtyStatus.trim()}`,
|
|
739
|
+
);
|
|
740
|
+
git(worktreePath, ["checkout", "--", "."]);
|
|
741
|
+
git(worktreePath, ["clean", "-fd"]);
|
|
742
|
+
} else {
|
|
743
|
+
logInternalError(
|
|
744
|
+
"worktree.reused.dirtyPreserved",
|
|
745
|
+
new Error(
|
|
746
|
+
`Snapshot failed — preserving dirty worktree at ${worktreePath} (skipping git checkout/clean to prevent data loss)`,
|
|
747
|
+
),
|
|
748
|
+
`runId=${manifest.runId}, taskId=${task.id}, dirtyStatus=${dirtyStatus.trim()}`,
|
|
749
|
+
);
|
|
750
|
+
}
|
|
733
751
|
}
|
|
734
752
|
// Overlay seed paths from config + step-level seedPaths (reused worktree)
|
|
735
753
|
const globalSeedPaths = loadedConfig.config.worktree?.seedPaths ?? [];
|
|
@@ -869,14 +887,24 @@ export async function prepareTaskWorkspaceAsync(
|
|
|
869
887
|
}
|
|
870
888
|
const dirtyStatus = await gitAsync(worktreePath, ["status", "--porcelain"]);
|
|
871
889
|
if (dirtyStatus.trim()) {
|
|
872
|
-
snapshotDirtyWorktree(manifest, task, worktreePath, dirtyStatus);
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
890
|
+
const snapshotOk = snapshotDirtyWorktree(manifest, task, worktreePath, dirtyStatus);
|
|
891
|
+
if (snapshotOk) {
|
|
892
|
+
logInternalError(
|
|
893
|
+
"worktree.reused.dirty",
|
|
894
|
+
new Error(`Discarding uncommitted changes in reused worktree at ${worktreePath} (snapshot saved to artifacts)`),
|
|
895
|
+
`runId=${manifest.runId}, taskId=${task.id}, dirtyStatus=${dirtyStatus.trim()}`,
|
|
896
|
+
);
|
|
897
|
+
await gitAsync(worktreePath, ["checkout", "--", "."]);
|
|
898
|
+
await gitAsync(worktreePath, ["clean", "-fd"]);
|
|
899
|
+
} else {
|
|
900
|
+
logInternalError(
|
|
901
|
+
"worktree.reused.dirtyPreserved",
|
|
902
|
+
new Error(
|
|
903
|
+
`Snapshot failed — preserving dirty worktree at ${worktreePath} (skipping git checkout/clean to prevent data loss)`,
|
|
904
|
+
),
|
|
905
|
+
`runId=${manifest.runId}, taskId=${task.id}, dirtyStatus=${dirtyStatus.trim()}`,
|
|
906
|
+
);
|
|
907
|
+
}
|
|
880
908
|
}
|
|
881
909
|
const globalSeedPaths = loadedConfig.config.worktree?.seedPaths ?? [];
|
|
882
910
|
const mergedReused = normalizeSeedPaths([...globalSeedPaths, ...(stepSeedPaths ?? [])], repoRoot);
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import * as crypto from "node:crypto";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
|
-
import * as path from "node:path";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Fallow-inspired atomic writer: write-to-.tmp → fsync → rename.
|
|
7
|
-
*
|
|
8
|
-
* Key differences from atomic-write.ts:
|
|
9
|
-
* - Uses rename() (POSIX-atomic) instead of link()+unlink()
|
|
10
|
-
* - Calls fsyncSync() on the temp file before rename
|
|
11
|
-
* - Best-effort fsync (failure does not abort)
|
|
12
|
-
* - Writes .gitignore to directory on first use
|
|
13
|
-
* - UUID-based tmp file to prevent collisions under concurrent writes
|
|
14
|
-
*/
|
|
15
|
-
export class AtomicWriter {
|
|
16
|
-
private initializedDirs = new Set<string>();
|
|
17
|
-
private baseDir: string;
|
|
18
|
-
|
|
19
|
-
constructor(baseDir: string) {
|
|
20
|
-
this.baseDir = baseDir;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
writeSync(targetPath: string, content: string): void {
|
|
24
|
-
this.ensureParentDir(targetPath);
|
|
25
|
-
const tmpPath = this.tmpPath(targetPath);
|
|
26
|
-
const fd = fs.openSync(tmpPath, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL, 0o600);
|
|
27
|
-
try {
|
|
28
|
-
fs.writeSync(fd, content, undefined, "utf8");
|
|
29
|
-
try {
|
|
30
|
-
fs.fsyncSync(fd);
|
|
31
|
-
} catch {
|
|
32
|
-
/* best-effort */
|
|
33
|
-
}
|
|
34
|
-
} finally {
|
|
35
|
-
fs.closeSync(fd);
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
fs.renameSync(tmpPath, targetPath);
|
|
39
|
-
} catch (err) {
|
|
40
|
-
try {
|
|
41
|
-
fs.unlinkSync(tmpPath);
|
|
42
|
-
} catch {
|
|
43
|
-
/* best-effort cleanup */
|
|
44
|
-
}
|
|
45
|
-
throw err;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async writeAsync(targetPath: string, content: string): Promise<void> {
|
|
50
|
-
await fs.promises.mkdir(path.dirname(targetPath), { recursive: true });
|
|
51
|
-
const tmpPath = this.tmpPath(targetPath);
|
|
52
|
-
const fd = await fs.promises.open(tmpPath, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL, 0o600);
|
|
53
|
-
try {
|
|
54
|
-
await fd.writeFile(content, "utf8");
|
|
55
|
-
try {
|
|
56
|
-
await fd.sync();
|
|
57
|
-
} catch {
|
|
58
|
-
/* best-effort */
|
|
59
|
-
}
|
|
60
|
-
} finally {
|
|
61
|
-
await fd.close();
|
|
62
|
-
}
|
|
63
|
-
try {
|
|
64
|
-
await fs.promises.rename(tmpPath, targetPath);
|
|
65
|
-
} catch (err) {
|
|
66
|
-
try {
|
|
67
|
-
await fs.promises.unlink(tmpPath);
|
|
68
|
-
} catch {
|
|
69
|
-
/* best-effort cleanup */
|
|
70
|
-
}
|
|
71
|
-
throw err;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
writeJsonSync<T>(targetPath: string, value: T): void {
|
|
76
|
-
this.writeSync(targetPath, JSON.stringify(value, null, 2) + "\n");
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async writeJsonAsync<T>(targetPath: string, value: T): Promise<void> {
|
|
80
|
-
await this.writeAsync(targetPath, JSON.stringify(value, null, 2) + "\n");
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
private tmpPath(targetPath: string): string {
|
|
84
|
-
const uuid = crypto.randomUUID();
|
|
85
|
-
return `${targetPath}.${uuid}.tmp`;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
private ensureParentDir(targetPath: string): void {
|
|
89
|
-
const dir = path.dirname(targetPath);
|
|
90
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
91
|
-
this.ensureGitignore(dir);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
private ensureGitignore(dir: string): void {
|
|
95
|
-
if (this.initializedDirs.has(dir)) return;
|
|
96
|
-
this.initializedDirs.add(dir);
|
|
97
|
-
const gitignorePath = path.join(dir, ".gitignore");
|
|
98
|
-
try {
|
|
99
|
-
fs.accessSync(gitignorePath);
|
|
100
|
-
} catch {
|
|
101
|
-
try {
|
|
102
|
-
fs.writeFileSync(gitignorePath, "*\n", "utf8");
|
|
103
|
-
} catch {
|
|
104
|
-
/* best-effort */
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|