pi-crew 0.5.14 → 0.5.17
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 +171 -0
- package/README.md +1 -1
- package/docs/pi-crew-v0.5.16-audit-fix-plan.md +35 -0
- package/docs/pi-crew-v0.5.17-audit-fix-plan.md +80 -0
- package/docs/skills/REFERENCE.md +11 -0
- package/package.json +1 -1
- package/skills/artifact-analysis-loop/SKILL.md +1 -0
- package/skills/async-worker-recovery/SKILL.md +1 -0
- package/skills/child-pi-spawning/SKILL.md +1 -0
- package/skills/context-artifact-hygiene/SKILL.md +1 -0
- package/skills/delegation-patterns/SKILL.md +1 -0
- package/skills/detection-pipeline-design/SKILL.md +2 -1
- package/skills/event-log-tracing/SKILL.md +1 -0
- package/skills/git-master/SKILL.md +1 -0
- package/skills/hunting-investigation-loop/SKILL.md +1 -0
- package/skills/incident-playbook-construction/SKILL.md +1 -0
- package/skills/iterative-audit/SKILL.md +331 -0
- package/skills/live-agent-lifecycle/SKILL.md +1 -0
- package/skills/mailbox-interactive/SKILL.md +1 -0
- package/skills/model-routing-context/SKILL.md +2 -1
- package/skills/multi-perspective-review/SKILL.md +1 -0
- package/skills/observability-reliability/SKILL.md +1 -0
- package/skills/orchestration/SKILL.md +2 -1
- package/skills/ownership-session-security/SKILL.md +1 -0
- package/skills/pi-extension-lifecycle/SKILL.md +3 -2
- package/skills/post-mortem/SKILL.md +1 -0
- package/skills/read-only-explorer/SKILL.md +1 -0
- package/skills/requirements-to-task-packet/SKILL.md +1 -0
- package/skills/resource-discovery-config/SKILL.md +2 -1
- package/skills/runtime-state-reader/SKILL.md +1 -0
- package/skills/safe-bash/SKILL.md +1 -0
- package/skills/scrutinize/SKILL.md +1 -0
- package/skills/secure-agent-orchestration-review/SKILL.md +1 -0
- package/skills/security-review/SKILL.md +1 -0
- package/skills/state-mutation-locking/SKILL.md +1 -0
- package/skills/systematic-debugging/SKILL.md +1 -0
- package/skills/threat-hypothesis-framework/SKILL.md +1 -0
- package/skills/ui-render-performance/SKILL.md +2 -1
- package/skills/verification-before-done/SKILL.md +1 -0
- package/skills/widget-rendering/SKILL.md +2 -1
- package/skills/workspace-isolation/SKILL.md +1 -0
- package/skills/worktree-isolation/SKILL.md +1 -0
- package/src/config/types.ts +1 -0
- package/src/extension/management.ts +1 -1
- package/src/extension/plan-orchestrate.ts +0 -1
- package/src/extension/register.ts +16 -7
- package/src/extension/registration/viewers.ts +1 -1
- package/src/extension/run-index.ts +1 -1
- package/src/extension/team-tool/explain.ts +0 -1
- package/src/extension/team-tool/handle-schedule.ts +0 -1
- package/src/extension/team-tool/health-monitor.ts +0 -1
- package/src/extension/team-tool/orchestrate.ts +12 -4
- package/src/extension/team-tool/run.ts +2 -2
- package/src/extension/team-tool/status.ts +1 -1
- package/src/extension/team-tool.ts +2 -30
- package/src/observability/exporters/otlp-exporter.ts +11 -1
- package/src/runtime/adaptive-plan.ts +18 -2
- package/src/runtime/child-pi.ts +18 -6
- package/src/runtime/crash-recovery.ts +1 -1
- package/src/runtime/crew-agent-records.ts +23 -3
- package/src/runtime/crew-hooks.ts +1 -1
- package/src/runtime/dynamic-script-runner.ts +14 -1
- package/src/runtime/handoff-manager.ts +0 -1
- package/src/runtime/heartbeat-watcher.ts +1 -1
- package/src/runtime/live-session-runtime.ts +0 -1
- package/src/runtime/loop-gates.ts +0 -1
- package/src/runtime/mcp-proxy.ts +2 -2
- package/src/runtime/pipeline-runner.ts +1 -2
- package/src/runtime/sandbox.ts +8 -0
- package/src/runtime/task-packet.ts +124 -0
- package/src/runtime/task-runner/live-executor.ts +1 -2
- package/src/runtime/task-runner/prompt-builder.ts +4 -1
- package/src/runtime/task-runner.ts +2 -2
- package/src/schema/config-schema.ts +1 -0
- package/src/state/event-log.ts +7 -0
- package/src/state/jsonl-writer.ts +24 -0
- package/src/state/locks.ts +66 -35
- package/src/state/run-metrics.ts +1 -2
- package/src/state/schedule.ts +13 -5
- package/src/state/state-store.ts +1 -1
- package/src/tools/safe-bash-extension.ts +1 -1
- package/src/tools/safe-bash.ts +10 -1
- package/src/ui/crew-widget.ts +2 -2
- package/src/ui/render-diff.ts +1 -1
- package/src/ui/run-dashboard.ts +1 -2
- package/src/ui/tool-render.ts +20 -3
- package/src/utils/conflict-detect.ts +0 -1
- package/src/utils/gh-protocol.ts +0 -2
- package/src/workflows/workflow-config.ts +3 -0
- package/src/worktree/worktree-manager.ts +75 -1
|
@@ -116,6 +116,11 @@ function runSetupHook(manifest: TeamRunManifest, task: TeamTaskState, repoRoot:
|
|
|
116
116
|
logInternalError("worktree.setupHook.rejected", new Error("hook path not allowed: " + rawHookPath), `cwd=${manifest.cwd}`);
|
|
117
117
|
return [];
|
|
118
118
|
}
|
|
119
|
+
// SECURITY WARNING: Home directory hooks (~/.pi/hooks/) are user-writable and not project-scoped.
|
|
120
|
+
// A rogue npm postinstall script could place malicious hooks there. Log for visibility.
|
|
121
|
+
if (path.isAbsolute(rawHookPath)) {
|
|
122
|
+
logInternalError("worktree.setupHook.homeHook", new Error("Home directory hook used — ensure ~/.pi/hooks/ is trusted"), `hookPath=${rawHookPath}`);
|
|
123
|
+
}
|
|
119
124
|
const hookPath = path.isAbsolute(rawHookPath) ? rawHookPath : path.resolve(repoRoot, rawHookPath);
|
|
120
125
|
// SECURITY: Verify the resolved hook path is contained within the real repoRoot.
|
|
121
126
|
// This prevents symlink-based escape where repoRoot is a symlink.
|
|
@@ -201,7 +206,64 @@ function pruneStaleWorktrees(repoRoot: string): void {
|
|
|
201
206
|
catch { /* best-effort */ }
|
|
202
207
|
}
|
|
203
208
|
|
|
204
|
-
|
|
209
|
+
/**
|
|
210
|
+
* Normalize and validate seed paths — ensure all paths stay within repoRoot.
|
|
211
|
+
* Rejects path traversal (../) and absolute paths.
|
|
212
|
+
*/
|
|
213
|
+
export function normalizeSeedPaths(seedPaths: string[], repoRoot: string): string[] {
|
|
214
|
+
const resolvedRepoRoot = path.resolve(repoRoot);
|
|
215
|
+
const entries = Array.isArray(seedPaths) ? seedPaths : [];
|
|
216
|
+
const seen = new Set<string>();
|
|
217
|
+
const normalized: string[] = [];
|
|
218
|
+
|
|
219
|
+
for (const entry of entries) {
|
|
220
|
+
if (typeof entry !== "string" || entry.trim().length === 0) continue;
|
|
221
|
+
|
|
222
|
+
const absolutePath = path.resolve(resolvedRepoRoot, entry);
|
|
223
|
+
const relativePath = path.relative(resolvedRepoRoot, absolutePath);
|
|
224
|
+
|
|
225
|
+
if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) {
|
|
226
|
+
throw new Error(`seedPaths entries must stay inside repoRoot: ${entry}`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const normalizedPath = relativePath.split(path.sep).join("/");
|
|
230
|
+
if (seen.has(normalizedPath)) continue;
|
|
231
|
+
seen.add(normalizedPath);
|
|
232
|
+
normalized.push(normalizedPath);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return normalized;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Overlay seed paths from repoRoot into worktreePath.
|
|
240
|
+
* Copies files and directories, creating parent dirs as needed.
|
|
241
|
+
* Skips non-existent sources with logInternalError (non-fatal).
|
|
242
|
+
*/
|
|
243
|
+
export function overlaySeedPaths(repoRoot: string, worktreePath: string, seedPaths: string[]): void {
|
|
244
|
+
const normalized = normalizeSeedPaths(seedPaths, repoRoot);
|
|
245
|
+
|
|
246
|
+
for (const seedPath of normalized) {
|
|
247
|
+
const sourcePath = path.join(repoRoot, seedPath);
|
|
248
|
+
const destinationPath = path.join(worktreePath, seedPath);
|
|
249
|
+
|
|
250
|
+
if (!fs.existsSync(sourcePath)) {
|
|
251
|
+
logInternalError("worktree.seedPaths.missing", new Error(`Seed path does not exist: ${seedPath}`));
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
fs.mkdirSync(path.dirname(destinationPath), { recursive: true });
|
|
256
|
+
fs.rmSync(destinationPath, { force: true, recursive: true });
|
|
257
|
+
fs.cpSync(sourcePath, destinationPath, {
|
|
258
|
+
dereference: false,
|
|
259
|
+
force: true,
|
|
260
|
+
preserveTimestamps: true,
|
|
261
|
+
recursive: true,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function prepareTaskWorkspace(manifest: TeamRunManifest, task: TeamTaskState, stepSeedPaths?: string[]): PreparedTaskWorkspace {
|
|
205
267
|
if (manifest.workspaceMode !== "worktree") return { cwd: task.cwd };
|
|
206
268
|
const repoRoot = findGitRoot(manifest.cwd);
|
|
207
269
|
const loadedConfig = loadConfig(manifest.cwd);
|
|
@@ -220,6 +282,12 @@ export function prepareTaskWorkspace(manifest: TeamRunManifest, task: TeamTaskSt
|
|
|
220
282
|
if (currentBranch !== branch) {
|
|
221
283
|
throw new Error(`Existing worktree branch mismatch at ${worktreePath}: expected '${branch}', got '${currentBranch}'.`);
|
|
222
284
|
}
|
|
285
|
+
// Overlay seed paths from config + step-level seedPaths (reused worktree)
|
|
286
|
+
const globalSeedPaths = loadedConfig.config.worktree?.seedPaths ?? [];
|
|
287
|
+
const mergedReused = normalizeSeedPaths([...globalSeedPaths, ...(stepSeedPaths ?? [])], repoRoot);
|
|
288
|
+
if (mergedReused.length > 0) {
|
|
289
|
+
overlaySeedPaths(repoRoot, worktreePath, mergedReused);
|
|
290
|
+
}
|
|
223
291
|
return { cwd: worktreePath, worktreePath, branch, reused: true };
|
|
224
292
|
}
|
|
225
293
|
pruneStaleWorktrees(repoRoot);
|
|
@@ -242,6 +310,12 @@ export function prepareTaskWorkspace(manifest: TeamRunManifest, task: TeamTaskSt
|
|
|
242
310
|
}
|
|
243
311
|
const syntheticPaths = runSetupHook(manifest, task, repoRoot, worktreePath, branch);
|
|
244
312
|
const nodeModulesLinked = loadedConfig.config.worktree?.linkNodeModules === true ? linkNodeModulesIfPresent(repoRoot, worktreePath) : false;
|
|
313
|
+
// Overlay seed paths from config + step-level seedPaths
|
|
314
|
+
const globalSeedPaths = loadedConfig.config.worktree?.seedPaths ?? [];
|
|
315
|
+
const merged = normalizeSeedPaths([...globalSeedPaths, ...(stepSeedPaths ?? [])], repoRoot);
|
|
316
|
+
if (merged.length > 0) {
|
|
317
|
+
overlaySeedPaths(repoRoot, worktreePath, merged);
|
|
318
|
+
}
|
|
245
319
|
return { cwd: worktreePath, worktreePath, branch, reused: false, nodeModulesLinked, syntheticPaths };
|
|
246
320
|
}
|
|
247
321
|
|