pi-crew 0.9.16 → 0.9.18
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 +130 -0
- package/README.md +19 -0
- package/dist/build-meta.json +21784 -0
- package/dist/index.mjs +83169 -0
- package/dist/index.mjs.map +7 -0
- package/docs/A +358 -0
- package/docs/M-A +357 -0
- package/docs/REVIEW-FINDINGS-2026-06 +357 -0
- package/docs/Y +357 -0
- package/docs/a +357 -0
- package/docs/aA +358 -0
- package/docs/archive/README.md +91 -0
- package/docs/migration/atomic-write-v2-migration.md +297 -0
- package/docs/patterns/command-agent-skill.md +1 -1
- package/docs/perf/performance-review-2026-07.md +287 -0
- package/docs/skills/REFERENCE.md +0 -17
- package/docs//303/242mmaAAA/303/242 +357 -0
- package/index.bundle.ts +25 -0
- package/index.ts +95 -4
- package/package.json +15 -4
- package/skills/iterative-audit/SKILL.md +0 -1
- package/skills/widget-rendering/SKILL.md +17 -0
- package/src/adapters/claude-adapter.ts +1 -3
- package/src/adapters/export-util.ts +16 -16
- package/src/adapters/index.ts +5 -5
- package/src/agents/agent-config.ts +20 -14
- package/src/agents/agent-serializer.ts +1 -1
- package/src/agents/discover-agents.ts +83 -39
- package/src/benchmark/benchmark-runner.ts +51 -51
- package/src/benchmark/feedback-loop.ts +1 -1
- package/src/config/config.ts +303 -591
- package/src/config/defaults.ts +28 -2
- package/src/config/drift-detector.ts +11 -14
- package/src/config/markers.ts +201 -203
- package/src/config/resilient-parser.ts +14 -6
- package/src/config/role-tools.ts +3 -3
- package/src/config/suggestions.ts +5 -12
- package/src/config/types.ts +9 -25
- package/src/errors.ts +151 -157
- package/src/extension/action-suggestions.ts +54 -9
- package/src/extension/async-notifier.ts +43 -13
- package/src/extension/autonomous-policy.ts +77 -37
- package/src/extension/command-completions.ts +9 -8
- package/src/extension/context-status-injection.ts +14 -12
- package/src/extension/crew-autocomplete.ts +8 -16
- package/src/extension/crew-cleanup.ts +2 -1
- package/src/extension/crew-shortcuts.ts +9 -6
- package/src/extension/cross-extension-rpc.ts +136 -42
- package/src/extension/help.ts +1 -1
- package/src/extension/import-index.ts +10 -5
- package/src/extension/knowledge-injection.ts +88 -15
- package/src/extension/management.ts +89 -349
- package/src/extension/message-renderers.ts +3 -4
- package/src/extension/notification-router.ts +22 -5
- package/src/extension/notification-sink.ts +6 -3
- package/src/extension/pi-api.ts +17 -8
- package/src/extension/plan-orchestrate.ts +8 -27
- package/src/extension/project-init.ts +21 -6
- package/src/extension/register.ts +329 -975
- package/src/extension/registration/artifact-cleanup.ts +9 -4
- package/src/extension/registration/command-utils.ts +5 -1
- package/src/extension/registration/commands.ts +806 -314
- package/src/extension/registration/compaction-guard.ts +15 -15
- package/src/extension/registration/lifecycle.ts +259 -0
- package/src/extension/registration/observability.ts +293 -0
- package/src/extension/registration/subagent-helpers.ts +29 -7
- package/src/extension/registration/subagent-tools.ts +253 -44
- package/src/extension/registration/team-tool.ts +19 -84
- package/src/extension/registration/ui.ts +168 -0
- package/src/extension/registration/viewers.ts +64 -24
- package/src/extension/result-watcher.ts +18 -7
- package/src/extension/run-bundle-schema.ts +21 -6
- package/src/extension/run-export.ts +15 -6
- package/src/extension/run-import.ts +64 -29
- package/src/extension/run-index.ts +28 -9
- package/src/extension/run-maintenance.ts +32 -12
- package/src/extension/session-summary.ts +1 -1
- package/src/extension/team-manager-command.ts +64 -7
- package/src/extension/team-onboard.ts +149 -150
- package/src/extension/team-recommendation.ts +121 -21
- package/src/extension/team-tool/anchor.ts +31 -64
- package/src/extension/team-tool/api.ts +929 -141
- package/src/extension/team-tool/auto-summarize.ts +14 -26
- package/src/extension/team-tool/cache-control.ts +1 -5
- package/src/extension/team-tool/cancel.ts +138 -38
- package/src/extension/team-tool/chain-dispatch.ts +5 -13
- package/src/extension/team-tool/chain-executor.ts +29 -51
- package/src/extension/team-tool/config-patch.ts +1 -1
- package/src/extension/team-tool/context.ts +40 -20
- package/src/extension/team-tool/destructive-gate.ts +10 -5
- package/src/extension/team-tool/doctor.ts +170 -51
- package/src/extension/team-tool/explain.ts +228 -214
- package/src/extension/team-tool/failure-patterns.ts +3 -9
- package/src/extension/team-tool/goal-wrap.ts +71 -29
- package/src/extension/team-tool/goal.ts +185 -35
- package/src/extension/team-tool/handle-schedule.ts +34 -15
- package/src/extension/team-tool/handle-settings.ts +94 -56
- package/src/extension/team-tool/health-monitor.ts +27 -108
- package/src/extension/team-tool/inspect.ts +42 -9
- package/src/extension/team-tool/intent-policy.ts +4 -1
- package/src/extension/team-tool/lifecycle-actions.ts +244 -48
- package/src/extension/team-tool/orchestrate.ts +7 -18
- package/src/extension/team-tool/parallel-dispatch.ts +51 -29
- package/src/extension/team-tool/plan.ts +29 -5
- package/src/extension/team-tool/respond.ts +49 -16
- package/src/extension/team-tool/run-not-found.ts +3 -8
- package/src/extension/team-tool/run.ts +80 -317
- package/src/extension/team-tool/status.ts +135 -43
- package/src/extension/team-tool/workflow-manage.ts +92 -25
- package/src/extension/team-tool-types.ts +8 -1
- package/src/extension/team-tool.ts +142 -551
- package/src/extension/validate-resources.ts +39 -8
- package/src/hooks/registry.ts +66 -17
- package/src/hooks/types.ts +1 -1
- package/src/i18n.ts +25 -11
- package/src/observability/correlation.ts +17 -3
- package/src/observability/event-bus.ts +51 -56
- package/src/observability/event-to-metric.ts +117 -15
- package/src/observability/exporters/otlp-exporter.ts +56 -17
- package/src/observability/exporters/prometheus-exporter.ts +1 -1
- package/src/observability/metric-registry.ts +16 -4
- package/src/observability/metric-retention.ts +8 -2
- package/src/observability/metric-sink.ts +11 -3
- package/src/observability/metrics-primitives.ts +42 -9
- package/src/plugins/plugin-define.ts +2 -2
- package/src/plugins/plugin-registry.ts +25 -25
- package/src/plugins/plugins/index.ts +1 -1
- package/src/plugins/plugins/nextjs.ts +16 -16
- package/src/plugins/plugins/vite.ts +7 -11
- package/src/plugins/plugins/vitest.ts +6 -11
- package/src/runtime/adaptive-plan.ts +225 -40
- package/src/runtime/agent-control.ts +58 -15
- package/src/runtime/agent-memory.ts +15 -9
- package/src/runtime/agent-observability.ts +10 -2
- package/src/runtime/anchor-manager.ts +27 -25
- package/src/runtime/async-marker.ts +7 -1
- package/src/runtime/async-runner.ts +39 -24
- package/src/runtime/auto-summarize.ts +7 -13
- package/src/runtime/background-runner.ts +189 -251
- package/src/runtime/batch-barrier.ts +18 -16
- package/src/runtime/cancellation-token.ts +16 -6
- package/src/runtime/cancellation.ts +46 -8
- package/src/runtime/capability-inventory.ts +6 -4
- package/src/runtime/chain-parser.ts +44 -11
- package/src/runtime/chain-runner.ts +63 -69
- package/src/runtime/checkpoint.ts +12 -56
- package/src/runtime/child-pi.ts +344 -79
- package/src/runtime/coalesce-tasks.ts +268 -0
- package/src/runtime/code-summary.ts +71 -26
- package/src/runtime/compact-stages/index.ts +15 -5
- package/src/runtime/compact-stages/tail-capture-stage.ts +7 -2
- package/src/runtime/compact-stages/truncation-stage.ts +4 -1
- package/src/runtime/compaction-summary.ts +17 -10
- package/src/runtime/completion-guard.ts +33 -16
- package/src/runtime/crash-classification.ts +28 -7
- package/src/runtime/crash-recovery.ts +177 -37
- package/src/runtime/crew-agent-records.ts +145 -47
- package/src/runtime/crew-hooks.ts +9 -24
- package/src/runtime/cross-extension-rpc.ts +25 -23
- package/src/runtime/custom-tools/irc-tool.ts +43 -15
- package/src/runtime/custom-tools/submit-result-tool.ts +16 -5
- package/src/runtime/delivery-coordinator.ts +34 -7
- package/src/runtime/delta-conflict.ts +9 -21
- package/src/runtime/deterministic-ast.ts +1 -1
- package/src/runtime/diagnostic-export.ts +53 -20
- package/src/runtime/direct-run.ts +12 -2
- package/src/runtime/dwf-state-store.ts +1 -1
- package/src/runtime/dynamic-workflow-context.ts +187 -59
- package/src/runtime/dynamic-workflow-runner.ts +42 -20
- package/src/runtime/effectiveness.ts +16 -8
- package/src/runtime/errors/crew-errors.ts +7 -11
- package/src/runtime/event-stream-bridge.ts +9 -3
- package/src/runtime/foreground-control.ts +54 -14
- package/src/runtime/foreground-watchdog.ts +9 -6
- package/src/runtime/goal-achievement.ts +27 -10
- package/src/runtime/goal-evaluator.ts +54 -19
- package/src/runtime/goal-loop-runner.ts +280 -99
- package/src/runtime/goal-state-store.ts +27 -17
- package/src/runtime/green-contract.ts +11 -2
- package/src/runtime/group-join.ts +64 -31
- package/src/runtime/handoff-manager.ts +37 -42
- package/src/runtime/heartbeat-gradient.ts +10 -2
- package/src/runtime/heartbeat-watcher.ts +32 -6
- package/src/runtime/hidden-handoff.ts +13 -31
- package/src/runtime/important-line-classifier.ts +12 -2
- package/src/runtime/iteration-hooks.ts +25 -15
- package/src/runtime/live-agent-control.ts +55 -7
- package/src/runtime/live-agent-manager.ts +130 -27
- package/src/runtime/live-control-realtime.ts +23 -3
- package/src/runtime/live-irc.ts +4 -1
- package/src/runtime/live-session-health.ts +12 -4
- package/src/runtime/live-session-runtime.ts +379 -117
- package/src/runtime/manifest-cache.ts +28 -12
- package/src/runtime/mcp-proxy.ts +10 -18
- package/src/runtime/metric-parser.ts +1 -5
- package/src/runtime/model-fallback.ts +55 -18
- package/src/runtime/model-resolver.ts +2 -6
- package/src/runtime/model-scope.ts +19 -3
- package/src/runtime/notebook-helpers.ts +60 -62
- package/src/runtime/orphan-worker-registry.ts +37 -26
- package/src/runtime/output-validator.ts +18 -3
- package/src/runtime/overflow-recovery.ts +5 -4
- package/src/runtime/parallel-research.ts +29 -5
- package/src/runtime/parallel-utils.ts +9 -11
- package/src/runtime/path-overlap.ts +150 -0
- package/src/runtime/peer-dep.ts +12 -17
- package/src/runtime/per-write-validator.ts +1 -3
- package/src/runtime/phase-tracker.ts +342 -330
- package/src/runtime/pi-args.ts +26 -8
- package/src/runtime/pi-json-output.ts +1 -1
- package/src/runtime/pi-spawn.ts +30 -19
- package/src/runtime/pipeline-runner.ts +56 -55
- package/src/runtime/plan-templates.ts +5 -6
- package/src/runtime/policy-engine.ts +43 -7
- package/src/runtime/post-checks.ts +12 -4
- package/src/runtime/post-exit-stdio-guard.ts +2 -2
- package/src/runtime/process-lifecycle.ts +20 -10
- package/src/runtime/process-status.ts +16 -5
- package/src/runtime/progress-event-coalescer.ts +2 -1
- package/src/runtime/progress-tracker.ts +103 -103
- package/src/runtime/prose-compressor.ts +9 -11
- package/src/runtime/recovery-recipes.ts +118 -24
- package/src/runtime/replace.ts +25 -10
- package/src/runtime/resilient-edit.ts +10 -25
- package/src/runtime/result-extractor.ts +2 -6
- package/src/runtime/retry-executor.ts +20 -4
- package/src/runtime/retry-runner.ts +27 -51
- package/src/runtime/role-permission.ts +6 -1
- package/src/runtime/run-coalesced-task-group.ts +256 -0
- package/src/runtime/run-drift.ts +14 -15
- package/src/runtime/run-tracker.ts +6 -28
- package/src/runtime/runtime-policy.ts +1 -6
- package/src/runtime/runtime-resolver.ts +80 -15
- package/src/runtime/scheduler.ts +47 -18
- package/src/runtime/semaphore.ts +5 -7
- package/src/runtime/sensitive-paths.ts +2 -1
- package/src/runtime/session-usage.ts +1 -1
- package/src/runtime/settings-store.ts +16 -12
- package/src/runtime/sidechain-output.ts +6 -2
- package/src/runtime/single-agent-compose.ts +1 -4
- package/src/runtime/skill-effectiveness.ts +29 -97
- package/src/runtime/skill-instructions.ts +40 -83
- package/src/runtime/stale-reconciler.ts +73 -197
- package/src/runtime/stream-preview.ts +1 -1
- package/src/runtime/streaming-output.ts +1 -1
- package/src/runtime/subagent-manager.ts +44 -169
- package/src/runtime/subprocess-tool-registry.ts +4 -1
- package/src/runtime/supervisor-contact.ts +10 -5
- package/src/runtime/task-display.ts +19 -5
- package/src/runtime/task-graph-scheduler.ts +95 -21
- package/src/runtime/task-graph.ts +5 -11
- package/src/runtime/task-health.ts +54 -47
- package/src/runtime/task-id.ts +12 -19
- package/src/runtime/task-output-context.ts +265 -81
- package/src/runtime/task-packet.ts +12 -20
- package/src/runtime/task-quality.ts +6 -14
- package/src/runtime/task-runner/context-retrieval.ts +4 -13
- package/src/runtime/task-runner/live-executor.ts +114 -36
- package/src/runtime/task-runner/output-splitter.ts +152 -0
- package/src/runtime/task-runner/progress.ts +50 -12
- package/src/runtime/task-runner/prompt-builder.ts +31 -7
- package/src/runtime/task-runner/prompt-pipeline.ts +31 -7
- package/src/runtime/task-runner/result-utils.ts +3 -1
- package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
- package/src/runtime/task-runner/run-projection.ts +27 -8
- package/src/runtime/task-runner/state-helpers.ts +50 -14
- package/src/runtime/task-runner/tail-read.ts +2 -6
- package/src/runtime/task-runner.ts +180 -326
- package/src/runtime/team-runner-artifacts.ts +13 -0
- package/src/runtime/team-runner.ts +456 -974
- package/src/runtime/tool-output-pruner.ts +6 -9
- package/src/runtime/tool-progress.ts +11 -21
- package/src/runtime/verification-gates.ts +33 -24
- package/src/runtime/verification-integrity.ts +2 -7
- package/src/runtime/verification-worktree.ts +62 -12
- package/src/runtime/worker-heartbeat.ts +5 -1
- package/src/runtime/worker-startup.ts +29 -5
- package/src/runtime/workflow-state.ts +17 -9
- package/src/runtime/workspace-lock.ts +30 -35
- package/src/runtime/workspace-tree.ts +20 -32
- package/src/runtime/yield-handler.ts +43 -9
- package/src/runtime/zombie-scanner.ts +5 -4
- package/src/schema/config-schema.ts +266 -172
- package/src/schema/team-tool-schema.ts +29 -74
- package/src/schema/validation-types.ts +25 -17
- package/src/skills/discover-skills.ts +35 -10
- package/src/skills/skill-templates.ts +109 -27
- package/src/skills/validate.ts +26 -8
- package/src/state/active-run-registry.ts +87 -28
- package/src/state/artifact-store.ts +9 -5
- package/src/state/atomic-write-v2.ts +85 -63
- package/src/state/atomic-write.ts +106 -27
- package/src/state/blob-store.ts +47 -20
- package/src/state/contracts.ts +20 -5
- package/src/state/crew-init.ts +5 -22
- package/src/state/decision-ledger.ts +19 -73
- package/src/state/event-log-rotation.ts +41 -15
- package/src/state/event-log.ts +168 -53
- package/src/state/event-reconstructor.ts +11 -1
- package/src/state/gitignore-manager.ts +2 -8
- package/src/state/health-store.ts +57 -57
- package/src/state/hook-instinct-bridge.ts +1 -1
- package/src/state/hook-integrations.ts +1 -1
- package/src/state/instinct-store.ts +17 -5
- package/src/state/jsonl-writer.ts +1 -1
- package/src/state/locks.ts +23 -9
- package/src/state/mailbox.ts +151 -28
- package/src/state/observation-store.ts +20 -14
- package/src/state/run-cache.ts +142 -135
- package/src/state/run-graph.ts +6 -15
- package/src/state/run-metrics.ts +5 -18
- package/src/state/schedule.ts +15 -9
- package/src/state/state-store.ts +137 -47
- package/src/state/task-claims.ts +12 -2
- package/src/state/tiered-eval.ts +52 -43
- package/src/state/types-eval.ts +2 -2
- package/src/state/types.ts +24 -20
- package/src/state/usage.ts +20 -4
- package/src/state/worker-atomic-writer.ts +6 -3
- package/src/subagents/index.ts +2 -2
- package/src/teams/discover-teams.ts +21 -6
- package/src/tools/safe-bash-extension.ts +5 -6
- package/src/tools/safe-bash.ts +10 -11
- package/src/types/new-api-types.ts +6 -10
- package/src/ui/agent-management-overlay.ts +52 -40
- package/src/ui/card-colors.ts +13 -4
- package/src/ui/crew-footer.ts +8 -7
- package/src/ui/crew-select-list.ts +1 -1
- package/src/ui/dashboard-panes/agents-pane.ts +41 -25
- package/src/ui/dashboard-panes/cancellation-pane.ts +1 -1
- package/src/ui/dashboard-panes/capability-pane.ts +32 -15
- package/src/ui/dashboard-panes/health-pane.ts +2 -1
- package/src/ui/dashboard-panes/metrics-pane.ts +4 -1
- package/src/ui/dashboard-panes/progress-pane.ts +12 -9
- package/src/ui/heartbeat-aggregator.ts +15 -4
- package/src/ui/keybinding-map.ts +40 -7
- package/src/ui/live-conversation-overlay.ts +36 -20
- package/src/ui/live-duration.ts +1 -4
- package/src/ui/live-run-sidebar.ts +88 -25
- package/src/ui/loaders.ts +2 -8
- package/src/ui/mascot.ts +20 -36
- package/src/ui/overlays/agent-picker-overlay.ts +11 -3
- package/src/ui/overlays/confirm-overlay.ts +4 -2
- package/src/ui/overlays/help-overlay.ts +25 -14
- package/src/ui/overlays/mailbox-compose-overlay.ts +48 -11
- package/src/ui/overlays/mailbox-compose-preview.ts +20 -5
- package/src/ui/overlays/mailbox-detail-overlay.ts +27 -6
- package/src/ui/pi-ui-compat.ts +7 -7
- package/src/ui/powerbar-publisher.ts +120 -42
- package/src/ui/render-diff.ts +10 -3
- package/src/ui/render-scheduler.ts +12 -4
- package/src/ui/run-action-dispatcher.ts +81 -18
- package/src/ui/run-dashboard.ts +172 -76
- package/src/ui/run-event-bus.ts +59 -37
- package/src/ui/run-snapshot-cache.ts +276 -86
- package/src/ui/settings-overlay.ts +361 -74
- package/src/ui/status-colors.ts +12 -1
- package/src/ui/syntax-highlight.ts +1 -1
- package/src/ui/terminal-status.ts +1 -3
- package/src/ui/theme-adapter.ts +16 -14
- package/src/ui/theme-discovery.ts +13 -2
- package/src/ui/tool-progress-formatter.ts +7 -7
- package/src/ui/tool-render.ts +128 -56
- package/src/ui/tool-renderers/brief-mode.ts +45 -27
- package/src/ui/tool-renderers/index.ts +109 -43
- package/src/ui/transcript-cache.ts +32 -6
- package/src/ui/transcript-entries.ts +25 -23
- package/src/ui/transcript-viewer.ts +78 -29
- package/src/ui/widget/index.ts +99 -40
- package/src/ui/widget/widget-formatters.ts +13 -6
- package/src/ui/widget/widget-model.ts +19 -8
- package/src/ui/widget/widget-renderer.ts +23 -13
- package/src/ui/widget/widget-types.ts +1 -1
- package/src/utils/bm25-search.ts +199 -199
- package/src/utils/conflict-detect.ts +22 -21
- package/src/utils/env-filter.ts +14 -7
- package/src/utils/file-coalescer.ts +5 -1
- package/src/utils/fingerprint.ts +3 -6
- package/src/utils/frontmatter.ts +3 -1
- package/src/utils/fs-watch.ts +2 -6
- package/src/utils/gh-protocol.ts +119 -44
- package/src/utils/git.ts +13 -15
- package/src/utils/guards.ts +2 -5
- package/src/utils/ids.ts +9 -2
- package/src/utils/incremental-reader.ts +14 -3
- package/src/utils/internal-error.ts +2 -1
- package/src/utils/names.ts +12 -3
- package/src/utils/paths.ts +49 -5
- package/src/utils/project-detector.ts +2 -2
- package/src/utils/redaction.ts +29 -19
- package/src/utils/resolve-shell.ts +9 -7
- package/src/utils/run-watcher-registry.ts +19 -31
- package/src/utils/safe-paths.ts +46 -29
- package/src/utils/scan-cache.ts +9 -2
- package/src/utils/session-utils.ts +2 -4
- package/src/utils/sleep.ts +12 -5
- package/src/utils/sse-parser.ts +5 -17
- package/src/utils/visual.ts +52 -32
- package/src/workflows/discover-workflows.ts +41 -109
- package/src/workflows/intermediate-store.ts +5 -21
- package/src/workflows/preflight-validator.ts +6 -33
- package/src/workflows/topology-analyzer.ts +5 -21
- package/src/workflows/workflow-config.ts +7 -6
- package/src/worktree/branch-freshness.ts +66 -8
- package/src/worktree/cleanup.ts +130 -20
- package/src/worktree/worktree-manager.ts +212 -69
- package/skills/artifact-analysis-loop/SKILL.md +0 -303
- package/skills/detection-pipeline-design/SKILL.md +0 -286
- package/skills/hunting-investigation-loop/SKILL.md +0 -402
- package/skills/incident-playbook-construction/SKILL.md +0 -384
- package/skills/security-review/SKILL.md +0 -561
- package/skills/threat-hypothesis-framework/SKILL.md +0 -176
- package/skills/ui-render-performance/SKILL.md +0 -58
- /package/docs/{followup-review-round3-2026-05-12.md → archive/followup-review-round3-2026-05-12.md} +0 -0
- /package/docs/{followup-review-round4-2026-05-13.md → archive/followup-review-round4-2026-05-13.md} +0 -0
- /package/docs/{pi-crew-bugs.md → archive/pi-crew-bugs.md} +0 -0
- /package/docs/{pi-crew-test-final.md → archive/pi-crew-test-final.md} +0 -0
- /package/docs/{pi-crew-test-results.md → archive/pi-crew-test-results.md} +0 -0
- /package/docs/{pi-crew-test-round2.md → archive/pi-crew-test-round2.md} +0 -0
- /package/docs/{pi-crew-test-round4.md → archive/pi-crew-test-round4.md} +0 -0
- /package/docs/{pi-crew-test-round5.md → archive/pi-crew-test-round5.md} +0 -0
- /package/docs/{pi-crew-test-round6.md → archive/pi-crew-test-round6.md} +0 -0
- /package/docs/{pi-crew-v0.5.10-audit-fix-plan.md → archive/pi-crew-v0.5.10-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.11-audit-fix-plan.md → archive/pi-crew-v0.5.11-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.12-audit-fix-plan.md → archive/pi-crew-v0.5.12-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.13-audit-fix-plan.md → archive/pi-crew-v0.5.13-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.14-audit-fix-plan.md → archive/pi-crew-v0.5.14-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.16-audit-fix-plan.md → archive/pi-crew-v0.5.16-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.17-audit-fix-plan.md → archive/pi-crew-v0.5.17-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.5-audit-fix-plan.md → archive/pi-crew-v0.5.5-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.9-audit-fix-plan.md → archive/pi-crew-v0.5.9-audit-fix-plan.md} +0 -0
- /package/docs/{pi-mono-opportunities.md → archive/pi-mono-opportunities.md} +0 -0
- /package/docs/{pi-mono-review.md → archive/pi-mono-review.md} +0 -0
- /package/docs/{pi-subagent4-comparison.md → archive/pi-subagent4-comparison.md} +0 -0
- /package/docs/{pi-subagents3-deep-analysis.md → archive/pi-subagents3-deep-analysis.md} +0 -0
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { removeGuidance } from "../../config/markers.ts";
|
|
4
|
+
import { appendHookEvent, executeHook } from "../../hooks/registry.ts";
|
|
2
5
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
3
6
|
import { appendEvent } from "../../state/event-log.ts";
|
|
4
7
|
import { loadRunManifestById } from "../../state/state-store.ts";
|
|
8
|
+
import { projectCrewRoot, userCrewRoot, userPiRoot } from "../../utils/paths.ts";
|
|
9
|
+
import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
|
|
5
10
|
import { cleanupRunWorktrees } from "../../worktree/cleanup.ts";
|
|
6
11
|
import { listImportedRuns } from "../import-index.ts";
|
|
7
12
|
import { exportRunBundle } from "../run-export.ts";
|
|
@@ -9,26 +14,42 @@ import { importRunBundle } from "../run-import.ts";
|
|
|
9
14
|
import { pruneFinishedRuns } from "../run-maintenance.ts";
|
|
10
15
|
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
11
16
|
import { configRecord, result, type TeamContext } from "./context.ts";
|
|
12
|
-
import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
|
|
13
17
|
import { enforceDestructiveIntent, intentFromConfig } from "./intent-policy.ts";
|
|
14
|
-
import {
|
|
15
|
-
import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
|
|
16
|
-
import { projectCrewRoot, userCrewRoot, userPiRoot } from "../../utils/paths.ts";
|
|
17
|
-
import { removeGuidance } from "../../config/markers.ts";
|
|
18
|
-
import * as path from "node:path";
|
|
18
|
+
import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
|
|
19
19
|
|
|
20
20
|
export function handleWorktrees(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
21
21
|
if (!params.runId) return result("Worktrees requires runId.", { action: "worktrees", status: "error" }, true);
|
|
22
22
|
const loaded = loadRunManifestById(ctx.cwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
23
23
|
if (!loaded) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "worktrees", status: "error" }, true);
|
|
24
24
|
const withWorktrees = loaded.tasks.filter((task) => task.worktree);
|
|
25
|
-
const lines = [
|
|
26
|
-
|
|
25
|
+
const lines = [
|
|
26
|
+
`Worktrees for ${loaded.manifest.runId}:`,
|
|
27
|
+
...(withWorktrees.length
|
|
28
|
+
? withWorktrees.map(
|
|
29
|
+
(task) =>
|
|
30
|
+
`- ${task.id}: ${task.worktree!.path} branch=${task.worktree!.branch} reused=${task.worktree!.reused ? "true" : "false"}`,
|
|
31
|
+
)
|
|
32
|
+
: ["- (none)"]),
|
|
33
|
+
];
|
|
34
|
+
return result(lines.join("\n"), {
|
|
35
|
+
action: "worktrees",
|
|
36
|
+
status: "ok",
|
|
37
|
+
runId: loaded.manifest.runId,
|
|
38
|
+
artifactsRoot: loaded.manifest.artifactsRoot,
|
|
39
|
+
});
|
|
27
40
|
}
|
|
28
41
|
|
|
29
42
|
export function handleImports(_params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
30
43
|
const imports = listImportedRuns(ctx.cwd);
|
|
31
|
-
const lines = [
|
|
44
|
+
const lines = [
|
|
45
|
+
"Imported pi-crew runs:",
|
|
46
|
+
...(imports.length
|
|
47
|
+
? imports.map(
|
|
48
|
+
(entry) =>
|
|
49
|
+
`- ${entry.runId} (${entry.scope})${entry.status ? ` [${entry.status}]` : ""} ${entry.team ?? "unknown"}/${entry.workflow ?? "none"}: ${entry.goal ?? ""}\n Bundle: ${entry.bundlePath}\n Summary: ${entry.summaryPath}`,
|
|
50
|
+
)
|
|
51
|
+
: ["- (none)"]),
|
|
52
|
+
];
|
|
32
53
|
return result(lines.join("\n"), { action: "imports", status: "ok" });
|
|
33
54
|
}
|
|
34
55
|
|
|
@@ -39,7 +60,10 @@ export function handleImport(params: TeamToolParamsValue, ctx: TeamContext): PiT
|
|
|
39
60
|
const scope = cfg.scope === "user" ? "user" : "project";
|
|
40
61
|
try {
|
|
41
62
|
const imported = importRunBundle(ctx.cwd, bundlePath, scope);
|
|
42
|
-
return result(
|
|
63
|
+
return result(
|
|
64
|
+
[`Imported run bundle ${imported.runId}.`, `Bundle: ${imported.bundlePath}`, `Summary: ${imported.summaryPath}`].join("\n"),
|
|
65
|
+
{ action: "import", status: "ok" },
|
|
66
|
+
);
|
|
43
67
|
} catch (error) {
|
|
44
68
|
const message = error instanceof Error ? error.message : String(error);
|
|
45
69
|
return result(`Import failed: ${message}`, { action: "import", status: "error" }, true);
|
|
@@ -56,18 +80,41 @@ export async function handleExport(params: TeamToolParamsValue, ctx: TeamContext
|
|
|
56
80
|
// Risk: exported bundles may contain sensitive data from another session's run.
|
|
57
81
|
const foreignRun = typeof loaded.manifest.ownerSessionId === "string" && loaded.manifest.ownerSessionId !== ctx.sessionId;
|
|
58
82
|
if (foreignRun && !params.confirm) {
|
|
59
|
-
return result(
|
|
83
|
+
return result(
|
|
84
|
+
`Run ${loaded.manifest.runId} belongs to another session. Use confirm: true to export anyway.`,
|
|
85
|
+
{ action: "export", status: "error", runId: loaded.manifest.runId },
|
|
86
|
+
true,
|
|
87
|
+
);
|
|
60
88
|
}
|
|
61
89
|
|
|
62
|
-
const hookReport = await executeHook("before_publish", {
|
|
90
|
+
const hookReport = await executeHook("before_publish", {
|
|
91
|
+
runId: loaded.manifest.runId,
|
|
92
|
+
cwd: ctx.cwd,
|
|
93
|
+
});
|
|
63
94
|
appendHookEvent(loaded.manifest, hookReport);
|
|
64
95
|
if (hookReport.outcome === "block") {
|
|
65
|
-
return result(
|
|
96
|
+
return result(
|
|
97
|
+
`Export blocked by hook: ${hookReport.reason ?? "before_publish hook blocked the operation."}`,
|
|
98
|
+
{ action: "export", status: "error", runId: loaded.manifest.runId },
|
|
99
|
+
true,
|
|
100
|
+
);
|
|
66
101
|
}
|
|
67
102
|
|
|
68
103
|
const exported = exportRunBundle(loaded.manifest, loaded.tasks);
|
|
69
|
-
appendEvent(loaded.manifest.eventsPath, {
|
|
70
|
-
|
|
104
|
+
appendEvent(loaded.manifest.eventsPath, {
|
|
105
|
+
type: "run.exported",
|
|
106
|
+
runId: loaded.manifest.runId,
|
|
107
|
+
data: exported,
|
|
108
|
+
});
|
|
109
|
+
return result(
|
|
110
|
+
[`Exported run ${loaded.manifest.runId}.`, `JSON: ${exported.jsonPath}`, `Markdown: ${exported.markdownPath}`].join("\n"),
|
|
111
|
+
{
|
|
112
|
+
action: "export",
|
|
113
|
+
status: "ok",
|
|
114
|
+
runId: loaded.manifest.runId,
|
|
115
|
+
artifactsRoot: loaded.manifest.artifactsRoot,
|
|
116
|
+
},
|
|
117
|
+
);
|
|
71
118
|
}
|
|
72
119
|
|
|
73
120
|
// Note: handlePrune has no ownership check — intentionally cross-session.
|
|
@@ -80,16 +127,35 @@ export async function handlePrune(params: TeamToolParamsValue, ctx: TeamContext)
|
|
|
80
127
|
const keep = params.keep ?? 20;
|
|
81
128
|
if (keep < 0 || !Number.isInteger(keep)) return result("keep must be an integer >= 0.", { action: "prune", status: "error" }, true);
|
|
82
129
|
const intent = intentFromConfig(params.config);
|
|
83
|
-
const pruned = pruneFinishedRuns(ctx.cwd, keep, {
|
|
130
|
+
const pruned = pruneFinishedRuns(ctx.cwd, keep, {
|
|
131
|
+
intent,
|
|
132
|
+
signal: ctx.signal,
|
|
133
|
+
});
|
|
84
134
|
// Fire hook once with all removed run IDs for batch visibility
|
|
85
135
|
if (pruned.removed.length > 0) {
|
|
86
136
|
const sampleManifest = loadRunManifestById(ctx.cwd, pruned.removed[0])?.manifest;
|
|
87
137
|
if (sampleManifest) {
|
|
88
|
-
const hookReport = await executeHook("before_cleanup", {
|
|
138
|
+
const hookReport = await executeHook("before_cleanup", {
|
|
139
|
+
runId: sampleManifest.runId,
|
|
140
|
+
cwd: ctx.cwd,
|
|
141
|
+
data: {
|
|
142
|
+
removedRunIds: pruned.removed,
|
|
143
|
+
keptCount: pruned.kept.length,
|
|
144
|
+
},
|
|
145
|
+
});
|
|
89
146
|
appendHookEvent(sampleManifest, hookReport);
|
|
90
147
|
}
|
|
91
148
|
}
|
|
92
|
-
return result(
|
|
149
|
+
return result(
|
|
150
|
+
[
|
|
151
|
+
`Pruned finished pi-crew runs.`,
|
|
152
|
+
`Kept: ${pruned.kept.length}`,
|
|
153
|
+
`Removed: ${pruned.removed.length}`,
|
|
154
|
+
...(pruned.auditPath ? [`Audit: ${pruned.auditPath}`] : []),
|
|
155
|
+
...(pruned.removed.length ? ["Removed runs:", ...pruned.removed.map((runId) => `- ${runId}`)] : []),
|
|
156
|
+
].join("\n"),
|
|
157
|
+
{ action: "prune", status: "ok", intent },
|
|
158
|
+
);
|
|
93
159
|
}
|
|
94
160
|
|
|
95
161
|
export async function handleForget(params: TeamToolParamsValue, ctx: TeamContext): Promise<PiTeamsToolResult> {
|
|
@@ -102,25 +168,77 @@ export async function handleForget(params: TeamToolParamsValue, ctx: TeamContext
|
|
|
102
168
|
|
|
103
169
|
// Ownership check — prevent cross-session deletion unless force is set
|
|
104
170
|
const foreignRun = typeof loaded.manifest.ownerSessionId === "string" && loaded.manifest.ownerSessionId !== ctx.sessionId;
|
|
105
|
-
if (foreignRun && !params.force)
|
|
171
|
+
if (foreignRun && !params.force)
|
|
172
|
+
return result(
|
|
173
|
+
`Run ${params.runId} belongs to another session. Use force: true to override.`,
|
|
174
|
+
{ action: "forget", status: "error", runId: loaded.manifest.runId },
|
|
175
|
+
true,
|
|
176
|
+
);
|
|
106
177
|
|
|
107
|
-
const hookReport = await executeHook("before_forget", {
|
|
178
|
+
const hookReport = await executeHook("before_forget", {
|
|
179
|
+
runId: loaded.manifest.runId,
|
|
180
|
+
cwd: ctx.cwd,
|
|
181
|
+
});
|
|
108
182
|
appendHookEvent(loaded.manifest, hookReport);
|
|
109
183
|
if (hookReport.outcome === "block") {
|
|
110
|
-
return result(
|
|
184
|
+
return result(
|
|
185
|
+
`Forget blocked by hook: ${hookReport.reason ?? "before_forget hook blocked the operation."}`,
|
|
186
|
+
{ action: "forget", status: "error", runId: loaded.manifest.runId },
|
|
187
|
+
true,
|
|
188
|
+
);
|
|
111
189
|
}
|
|
112
190
|
|
|
113
|
-
const cleanup = cleanupRunWorktrees(loaded.manifest, {
|
|
114
|
-
|
|
191
|
+
const cleanup = cleanupRunWorktrees(loaded.manifest, {
|
|
192
|
+
force: params.force,
|
|
193
|
+
});
|
|
194
|
+
if (cleanup.preserved.length > 0 && !params.force)
|
|
195
|
+
return result(
|
|
196
|
+
[
|
|
197
|
+
`Run '${params.runId}' has preserved worktrees. Use force: true to forget anyway.`,
|
|
198
|
+
...cleanup.preserved.map((item) => `- ${item.path}: ${item.reason}`),
|
|
199
|
+
].join("\n"),
|
|
200
|
+
{
|
|
201
|
+
action: "forget",
|
|
202
|
+
status: "error",
|
|
203
|
+
runId: loaded.manifest.runId,
|
|
204
|
+
artifactsRoot: loaded.manifest.artifactsRoot,
|
|
205
|
+
},
|
|
206
|
+
true,
|
|
207
|
+
);
|
|
115
208
|
const intent = intentFromConfig(params.config);
|
|
116
|
-
appendEvent(loaded.manifest.eventsPath, {
|
|
209
|
+
appendEvent(loaded.manifest.eventsPath, {
|
|
210
|
+
type: "run.forget_requested",
|
|
211
|
+
runId: loaded.manifest.runId,
|
|
212
|
+
message: "Run state and artifacts are being forgotten.",
|
|
213
|
+
data: {
|
|
214
|
+
force: params.force === true,
|
|
215
|
+
removedWorktrees: cleanup.removed,
|
|
216
|
+
preservedWorktrees: cleanup.preserved,
|
|
217
|
+
intent,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
117
220
|
// Determine scope from manifest paths (project vs user-level runs)
|
|
118
|
-
const crewRoot = loaded.manifest.stateRoot.startsWith(userCrewRoot() + path.sep)
|
|
221
|
+
const crewRoot = loaded.manifest.stateRoot.startsWith(userCrewRoot() + path.sep)
|
|
222
|
+
? userCrewRoot()
|
|
223
|
+
: projectCrewRoot(loaded.manifest.cwd);
|
|
119
224
|
const resolvedStateRoot = resolveRealContainedPath(crewRoot, loaded.manifest.stateRoot);
|
|
120
225
|
const resolvedArtifactsRoot = resolveRealContainedPath(crewRoot, loaded.manifest.artifactsRoot);
|
|
121
226
|
fs.rmSync(resolvedStateRoot, { recursive: true, force: true });
|
|
122
227
|
fs.rmSync(resolvedArtifactsRoot, { recursive: true, force: true });
|
|
123
|
-
return result(
|
|
228
|
+
return result(
|
|
229
|
+
[
|
|
230
|
+
`Forgot run ${loaded.manifest.runId}.`,
|
|
231
|
+
`Removed state: ${loaded.manifest.stateRoot}`,
|
|
232
|
+
`Removed artifacts: ${loaded.manifest.artifactsRoot}`,
|
|
233
|
+
...(cleanup.removed.length ? ["Removed worktrees:", ...cleanup.removed.map((item) => `- ${item}`)] : []),
|
|
234
|
+
].join("\n"),
|
|
235
|
+
{
|
|
236
|
+
action: "forget",
|
|
237
|
+
status: "ok",
|
|
238
|
+
runId: loaded.manifest.runId,
|
|
239
|
+
intent,
|
|
240
|
+
},
|
|
241
|
+
);
|
|
124
242
|
}
|
|
125
243
|
|
|
126
244
|
export async function handleCleanup(params: TeamToolParamsValue, ctx: TeamContext): Promise<PiTeamsToolResult> {
|
|
@@ -180,11 +298,18 @@ function handleProjectCleanup(params: TeamToolParamsValue, ctx: TeamContext): Pi
|
|
|
180
298
|
// 1. Remove the AGENTS.md guidance block (marker-delimited → user content preserved).
|
|
181
299
|
const guidancePath = path.join(cwd, "AGENTS.md");
|
|
182
300
|
const guidanceResult = dryRun
|
|
183
|
-
? {
|
|
301
|
+
? {
|
|
302
|
+
path: guidancePath,
|
|
303
|
+
modified: fs.existsSync(guidancePath),
|
|
304
|
+
added: [],
|
|
305
|
+
removed: dryRunRemovedIds(guidancePath),
|
|
306
|
+
}
|
|
184
307
|
: removeGuidance(guidancePath);
|
|
185
308
|
lines.push("AGENTS.md guidance block:");
|
|
186
309
|
if (guidanceResult.modified) {
|
|
187
|
-
lines.push(
|
|
310
|
+
lines.push(
|
|
311
|
+
` - ${dryRun ? "would remove" : "removed"}: ${guidanceResult.removed.length ? guidanceResult.removed.join(", ") : "(marker section)"}`,
|
|
312
|
+
);
|
|
188
313
|
} else {
|
|
189
314
|
lines.push(" - (no pi-crew marker section found — nothing to do)");
|
|
190
315
|
}
|
|
@@ -196,7 +321,9 @@ function handleProjectCleanup(params: TeamToolParamsValue, ctx: TeamContext): Pi
|
|
|
196
321
|
if (!crewExists) {
|
|
197
322
|
lines.push(` - (not present at ${crewRoot} — nothing to do)`);
|
|
198
323
|
} else if (!removeState) {
|
|
199
|
-
lines.push(
|
|
324
|
+
lines.push(
|
|
325
|
+
` - present at ${crewRoot} (preserved — use force: true to remove; contains run history/artifacts/worktrees and is irreversible)`,
|
|
326
|
+
);
|
|
200
327
|
} else {
|
|
201
328
|
// SAFETY: realpath + contain-check before rmSync, so a crafted cwd can't
|
|
202
329
|
// trick us into deleting an arbitrary directory.
|
|
@@ -282,10 +409,15 @@ function handleUserCleanup(params: TeamToolParamsValue, ctx: TeamContext): PiTea
|
|
|
282
409
|
if (fs.existsSync(crewStateDir)) {
|
|
283
410
|
try {
|
|
284
411
|
crewStateBytes = dirSize(crewStateDir);
|
|
285
|
-
} catch {
|
|
412
|
+
} catch {
|
|
413
|
+
/* best-effort size */
|
|
414
|
+
}
|
|
286
415
|
if (!dryRun) {
|
|
287
|
-
try {
|
|
288
|
-
|
|
416
|
+
try {
|
|
417
|
+
fs.rmSync(crewStateDir, { recursive: true, force: true });
|
|
418
|
+
} catch (e) {
|
|
419
|
+
lines.push(` - ERROR removing: ${(e as Error).message}`);
|
|
420
|
+
}
|
|
289
421
|
}
|
|
290
422
|
lines.push(` - ${dryRun ? "would remove" : "removed"}: ${crewStateDir} (${formatBytes(crewStateBytes)})`);
|
|
291
423
|
} else {
|
|
@@ -303,8 +435,11 @@ function handleUserCleanup(params: TeamToolParamsValue, ctx: TeamContext): PiTea
|
|
|
303
435
|
lines.push(` - present at ${userConfigPath} (preserved — use force: true to remove; may hold your customized settings)`);
|
|
304
436
|
} else {
|
|
305
437
|
if (!dryRun) {
|
|
306
|
-
try {
|
|
307
|
-
|
|
438
|
+
try {
|
|
439
|
+
fs.rmSync(userConfigPath, { force: true });
|
|
440
|
+
} catch (e) {
|
|
441
|
+
lines.push(` - ERROR removing: ${(e as Error).message}`);
|
|
442
|
+
}
|
|
308
443
|
}
|
|
309
444
|
lines.push(` - ${dryRun ? "would remove" : "removed"}: ${userConfigPath}`);
|
|
310
445
|
}
|
|
@@ -324,15 +459,20 @@ function handleUserCleanup(params: TeamToolParamsValue, ctx: TeamContext): PiTea
|
|
|
324
459
|
bakJunk.push(path.join(agentsDir, entry));
|
|
325
460
|
}
|
|
326
461
|
}
|
|
327
|
-
} catch {
|
|
462
|
+
} catch {
|
|
463
|
+
/* best-effort scan */
|
|
464
|
+
}
|
|
328
465
|
}
|
|
329
466
|
if (bakJunk.length === 0) {
|
|
330
467
|
lines.push(" - (no `*.md.bak-*` test backups found — nothing to do)");
|
|
331
468
|
} else {
|
|
332
469
|
for (const junk of bakJunk) {
|
|
333
470
|
if (!dryRun) {
|
|
334
|
-
try {
|
|
335
|
-
|
|
471
|
+
try {
|
|
472
|
+
fs.rmSync(junk, { force: true });
|
|
473
|
+
} catch (e) {
|
|
474
|
+
lines.push(` - ERROR removing ${path.basename(junk)}: ${(e as Error).message}`);
|
|
475
|
+
}
|
|
336
476
|
}
|
|
337
477
|
}
|
|
338
478
|
lines.push(` - ${dryRun ? "would remove" : "removed"}: ${bakJunk.length} backup file(s) (pattern *.md.bak-<timestamp>-<hex>)`);
|
|
@@ -354,15 +494,20 @@ function dirSize(dir: string): number {
|
|
|
354
494
|
while (stack.length > 0) {
|
|
355
495
|
const cur = stack.pop()!;
|
|
356
496
|
let entries: string[];
|
|
357
|
-
try {
|
|
358
|
-
|
|
497
|
+
try {
|
|
498
|
+
entries = fs.readdirSync(cur);
|
|
499
|
+
} catch {
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
359
502
|
for (const entry of entries) {
|
|
360
503
|
const full = path.join(cur, entry);
|
|
361
504
|
try {
|
|
362
505
|
const stat = fs.statSync(full);
|
|
363
506
|
if (stat.isDirectory()) stack.push(full);
|
|
364
507
|
else total += stat.size;
|
|
365
|
-
} catch {
|
|
508
|
+
} catch {
|
|
509
|
+
/* skip unreadable */
|
|
510
|
+
}
|
|
366
511
|
}
|
|
367
512
|
}
|
|
368
513
|
return total;
|
|
@@ -378,20 +523,71 @@ function formatBytes(n: number): string {
|
|
|
378
523
|
/** Per-run worktree cleanup (existing behavior, preserved). */
|
|
379
524
|
async function handleRunCleanup(params: TeamToolParamsValue, ctx: TeamContext): Promise<PiTeamsToolResult> {
|
|
380
525
|
const loaded = loadRunManifestById(ctx.cwd, params.runId!); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
381
|
-
if (!loaded)
|
|
526
|
+
if (!loaded)
|
|
527
|
+
return result(
|
|
528
|
+
`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`,
|
|
529
|
+
{ action: "cleanup", status: "error", runId: params.runId },
|
|
530
|
+
true,
|
|
531
|
+
);
|
|
382
532
|
// Ownership check — prevent cross-session worktree cleanup unless force is set
|
|
383
533
|
const foreignRun = typeof loaded.manifest.ownerSessionId === "string" && loaded.manifest.ownerSessionId !== ctx.sessionId;
|
|
384
|
-
if (foreignRun && !params.force)
|
|
534
|
+
if (foreignRun && !params.force)
|
|
535
|
+
return result(
|
|
536
|
+
`Run ${params.runId} belongs to another session. Use force: true to override.`,
|
|
537
|
+
{
|
|
538
|
+
action: "cleanup",
|
|
539
|
+
status: "error",
|
|
540
|
+
runId: loaded.manifest.runId,
|
|
541
|
+
},
|
|
542
|
+
true,
|
|
543
|
+
);
|
|
385
544
|
|
|
386
|
-
const hookReport = await executeHook("before_cleanup", {
|
|
545
|
+
const hookReport = await executeHook("before_cleanup", {
|
|
546
|
+
runId: loaded.manifest.runId,
|
|
547
|
+
cwd: ctx.cwd,
|
|
548
|
+
});
|
|
387
549
|
appendHookEvent(loaded.manifest, hookReport);
|
|
388
550
|
if (hookReport.outcome === "block") {
|
|
389
|
-
return result(
|
|
551
|
+
return result(
|
|
552
|
+
`Cleanup blocked by hook: ${hookReport.reason ?? "before_cleanup hook blocked the operation."}`,
|
|
553
|
+
{
|
|
554
|
+
action: "cleanup",
|
|
555
|
+
status: "error",
|
|
556
|
+
runId: loaded.manifest.runId,
|
|
557
|
+
},
|
|
558
|
+
true,
|
|
559
|
+
);
|
|
390
560
|
}
|
|
391
561
|
|
|
392
|
-
const cleanup = cleanupRunWorktrees(loaded.manifest, {
|
|
562
|
+
const cleanup = cleanupRunWorktrees(loaded.manifest, {
|
|
563
|
+
force: params.force,
|
|
564
|
+
signal: ctx.signal,
|
|
565
|
+
});
|
|
393
566
|
const intent = intentFromConfig(params.config);
|
|
394
|
-
appendEvent(loaded.manifest.eventsPath, {
|
|
395
|
-
|
|
396
|
-
|
|
567
|
+
appendEvent(loaded.manifest.eventsPath, {
|
|
568
|
+
type: "worktree.cleanup",
|
|
569
|
+
runId: loaded.manifest.runId,
|
|
570
|
+
data: {
|
|
571
|
+
removed: cleanup.removed,
|
|
572
|
+
preserved: cleanup.preserved,
|
|
573
|
+
artifacts: cleanup.artifactPaths,
|
|
574
|
+
intent,
|
|
575
|
+
},
|
|
576
|
+
});
|
|
577
|
+
const lines = [
|
|
578
|
+
`Worktree cleanup for ${loaded.manifest.runId}:`,
|
|
579
|
+
"Removed:",
|
|
580
|
+
...(cleanup.removed.length ? cleanup.removed.map((item) => `- ${item}`) : ["- (none)"]),
|
|
581
|
+
"Preserved:",
|
|
582
|
+
...(cleanup.preserved.length ? cleanup.preserved.map((item) => `- ${item.path}: ${item.reason}`) : ["- (none)"]),
|
|
583
|
+
"Artifacts:",
|
|
584
|
+
...(cleanup.artifactPaths.length ? cleanup.artifactPaths.map((item) => `- ${item}`) : ["- (none)"]),
|
|
585
|
+
];
|
|
586
|
+
return result(lines.join("\n"), {
|
|
587
|
+
action: "cleanup",
|
|
588
|
+
status: "ok",
|
|
589
|
+
runId: loaded.manifest.runId,
|
|
590
|
+
artifactsRoot: loaded.manifest.artifactsRoot,
|
|
591
|
+
intent,
|
|
592
|
+
});
|
|
397
593
|
}
|
|
@@ -6,16 +6,16 @@
|
|
|
6
6
|
import * as fs from "node:fs";
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
9
|
-
import
|
|
10
|
-
import { result, type TeamContext } from "./context.ts";
|
|
9
|
+
import { resolveContainedPath } from "../../utils/safe-paths.ts";
|
|
11
10
|
import {
|
|
12
11
|
buildAgentChain,
|
|
13
12
|
formatPlanOverview,
|
|
13
|
+
type OrchestratedStep,
|
|
14
14
|
parsePlanDocument,
|
|
15
15
|
parsePlanDocumentSimple,
|
|
16
|
-
type OrchestratedStep,
|
|
17
16
|
} from "../plan-orchestrate.ts";
|
|
18
|
-
import {
|
|
17
|
+
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
18
|
+
import { result, type TeamContext } from "./context.ts";
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Handle the orchestrate action.
|
|
@@ -25,10 +25,7 @@ import { resolveContainedPath } from "../../utils/safe-paths.ts";
|
|
|
25
25
|
*
|
|
26
26
|
* Usage: `team action='orchestrate' planPath='/path/to/plan.md'`
|
|
27
27
|
*/
|
|
28
|
-
export function handleOrchestrate(
|
|
29
|
-
params: TeamToolParamsValue,
|
|
30
|
-
ctx: TeamContext,
|
|
31
|
-
): PiTeamsToolResult {
|
|
28
|
+
export function handleOrchestrate(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
32
29
|
const planPath = params.planPath as string | undefined;
|
|
33
30
|
|
|
34
31
|
if (!planPath) {
|
|
@@ -44,19 +41,11 @@ export function handleOrchestrate(
|
|
|
44
41
|
try {
|
|
45
42
|
resolvedPath = resolveContainedPath(ctx.cwd, planPath);
|
|
46
43
|
} catch {
|
|
47
|
-
return result(
|
|
48
|
-
`planPath must be within project directory: ${planPath}`,
|
|
49
|
-
{ action: "orchestrate", status: "error" },
|
|
50
|
-
true,
|
|
51
|
-
);
|
|
44
|
+
return result(`planPath must be within project directory: ${planPath}`, { action: "orchestrate", status: "error" }, true);
|
|
52
45
|
}
|
|
53
46
|
|
|
54
47
|
if (!fs.existsSync(resolvedPath)) {
|
|
55
|
-
return result(
|
|
56
|
-
`Plan document not found: ${resolvedPath}`,
|
|
57
|
-
{ action: "orchestrate", status: "error" },
|
|
58
|
-
true,
|
|
59
|
-
);
|
|
48
|
+
return result(`Plan document not found: ${resolvedPath}`, { action: "orchestrate", status: "error" }, true);
|
|
60
49
|
}
|
|
61
50
|
|
|
62
51
|
// Try primary parser
|
|
@@ -8,18 +8,18 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { discoverAgents } from "../../agents/discover-agents.ts";
|
|
10
10
|
import { loadConfig } from "../../config/config.ts";
|
|
11
|
+
import { resolveCrewRuntime } from "../../runtime/runtime-resolver.ts";
|
|
11
12
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
12
|
-
import { createRunManifest } from "../../state/state-store.ts";
|
|
13
13
|
import { appendEvent } from "../../state/event-log.ts";
|
|
14
|
+
import { createRunManifest } from "../../state/state-store.ts";
|
|
14
15
|
import { spawnBackgroundTeamRun } from "../../subagents/async-entry.ts";
|
|
15
|
-
import { resolveCrewRuntime } from "../../runtime/runtime-resolver.ts";
|
|
16
|
-
import { resolveCwdOverride } from "../registration/team-tool.ts";
|
|
17
|
-
import { result, type TeamContext } from "./context.ts";
|
|
18
|
-
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
19
16
|
import { discoverTeams } from "../../teams/discover-teams.ts";
|
|
20
|
-
import { discoverWorkflows } from "../../workflows/discover-workflows.ts";
|
|
21
17
|
import type { TeamConfig } from "../../teams/team-config.ts";
|
|
18
|
+
import { discoverWorkflows } from "../../workflows/discover-workflows.ts";
|
|
22
19
|
import type { WorkflowConfig } from "../../workflows/workflow-config.ts";
|
|
20
|
+
import { resolveCwdOverride } from "../registration/team-tool.ts";
|
|
21
|
+
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
22
|
+
import { result, type TeamContext } from "./context.ts";
|
|
23
23
|
|
|
24
24
|
const MAX_CONCURRENCY = 8;
|
|
25
25
|
const DEFAULT_CONCURRENCY = 4;
|
|
@@ -32,10 +32,7 @@ export async function handleParallel(params: TeamToolParamsValue, ctx: TeamConte
|
|
|
32
32
|
return result("parallel action requires config.tasks: [{goal, agent?}]", { action: "parallel", status: "error" }, true);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
const concurrency = Math.min(
|
|
36
|
-
Math.max(1, Math.floor((params.config?.concurrency as number) ?? DEFAULT_CONCURRENCY)),
|
|
37
|
-
MAX_CONCURRENCY,
|
|
38
|
-
);
|
|
35
|
+
const concurrency = Math.min(Math.max(1, Math.floor((params.config?.concurrency as number) ?? DEFAULT_CONCURRENCY)), MAX_CONCURRENCY);
|
|
39
36
|
|
|
40
37
|
const config = loadConfig(ctx.cwd);
|
|
41
38
|
const agentsResult = discoverAgents(ctx.cwd);
|
|
@@ -44,16 +41,16 @@ export async function handleParallel(params: TeamToolParamsValue, ctx: TeamConte
|
|
|
44
41
|
const workflows = discoverWorkflows(ctx.cwd);
|
|
45
42
|
|
|
46
43
|
const teamName = (params.config?.team as string) ?? DEFAULT_TEAM;
|
|
47
|
-
const team =
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
const team =
|
|
45
|
+
teams.builtin.find((t) => t.name === teamName) ??
|
|
46
|
+
teams.user.find((t) => t.name === teamName) ??
|
|
47
|
+
teams.project.find((t) => t.name === teamName);
|
|
50
48
|
if (!team) {
|
|
51
49
|
return result(`Team '${teamName}' not found`, { action: "parallel", status: "error" }, true);
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
// H2: Use team's defaultWorkflow, fall back to "fast-fix"
|
|
55
|
-
const workflow = workflows.builtin.find((w) => w.name === team.defaultWorkflow)
|
|
56
|
-
?? workflows.builtin.find((w) => w.name === "fast-fix");
|
|
53
|
+
const workflow = workflows.builtin.find((w) => w.name === team.defaultWorkflow) ?? workflows.builtin.find((w) => w.name === "fast-fix");
|
|
57
54
|
if (!workflow) {
|
|
58
55
|
return result("No suitable workflow found for parallel dispatch", { action: "parallel", status: "error" }, true);
|
|
59
56
|
}
|
|
@@ -75,15 +72,15 @@ export async function handleParallel(params: TeamToolParamsValue, ctx: TeamConte
|
|
|
75
72
|
errors.push(res.value.error);
|
|
76
73
|
} else {
|
|
77
74
|
const reason = (res as PromiseRejectedResult).reason;
|
|
78
|
-
errors.push({
|
|
75
|
+
errors.push({
|
|
76
|
+
goal: "(unknown)",
|
|
77
|
+
error: reason instanceof Error ? reason.message : String(reason),
|
|
78
|
+
});
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
const lines: string[] = [
|
|
84
|
-
`Parallel dispatch: ${launched.length}/${tasksParam.length} tasks launched (concurrency: ${concurrency})`,
|
|
85
|
-
"",
|
|
86
|
-
];
|
|
83
|
+
const lines: string[] = [`Parallel dispatch: ${launched.length}/${tasksParam.length} tasks launched (concurrency: ${concurrency})`, ""];
|
|
87
84
|
for (const l of launched) {
|
|
88
85
|
lines.push(` ✅ ${l.runId} — ${l.agent}: ${l.goal.slice(0, 80)}`);
|
|
89
86
|
}
|
|
@@ -91,13 +88,20 @@ export async function handleParallel(params: TeamToolParamsValue, ctx: TeamConte
|
|
|
91
88
|
lines.push(` ❌ ${e.goal.slice(0, 80)}: ${e.error}`);
|
|
92
89
|
}
|
|
93
90
|
|
|
94
|
-
return result(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
return result(
|
|
92
|
+
lines.join("\n"),
|
|
93
|
+
{
|
|
94
|
+
action: "parallel",
|
|
95
|
+
status: errors.length === tasksParam.length ? "error" : "ok",
|
|
96
|
+
},
|
|
97
|
+
errors.length === tasksParam.length,
|
|
98
|
+
);
|
|
98
99
|
}
|
|
99
100
|
|
|
100
|
-
type SpawnOk = {
|
|
101
|
+
type SpawnOk = {
|
|
102
|
+
ok: true;
|
|
103
|
+
value: { runId: string; goal: string; agent: string };
|
|
104
|
+
};
|
|
101
105
|
type SpawnErr = { ok: false; error: { goal: string; error: string } };
|
|
102
106
|
type SpawnResult = SpawnOk | SpawnErr;
|
|
103
107
|
|
|
@@ -116,12 +120,21 @@ async function spawnSingleTask(
|
|
|
116
120
|
const rawCwd = (taskRec.cwd as string) ?? undefined;
|
|
117
121
|
|
|
118
122
|
if (!goal) {
|
|
119
|
-
return {
|
|
123
|
+
return {
|
|
124
|
+
ok: false,
|
|
125
|
+
error: {
|
|
126
|
+
goal: "(missing)",
|
|
127
|
+
error: "Each task must have a 'goal' field",
|
|
128
|
+
},
|
|
129
|
+
};
|
|
120
130
|
}
|
|
121
131
|
|
|
122
132
|
const agent = allAgentsList.find((a) => a.name === agentName);
|
|
123
133
|
if (!agent) {
|
|
124
|
-
return {
|
|
134
|
+
return {
|
|
135
|
+
ok: false,
|
|
136
|
+
error: { goal, error: `Agent '${agentName}' not found` },
|
|
137
|
+
};
|
|
125
138
|
}
|
|
126
139
|
|
|
127
140
|
// H1: Validate taskCwd containment against project root
|
|
@@ -148,9 +161,18 @@ async function spawnSingleTask(
|
|
|
148
161
|
await spawnBackgroundTeamRun(created.manifest);
|
|
149
162
|
}
|
|
150
163
|
|
|
151
|
-
return {
|
|
164
|
+
return {
|
|
165
|
+
ok: true,
|
|
166
|
+
value: { runId: created.manifest.runId, goal, agent: agentName },
|
|
167
|
+
};
|
|
152
168
|
} catch (error) {
|
|
153
169
|
const goal = ((task as Record<string, unknown>).goal as string) ?? "(unknown)";
|
|
154
|
-
return {
|
|
170
|
+
return {
|
|
171
|
+
ok: false,
|
|
172
|
+
error: {
|
|
173
|
+
goal,
|
|
174
|
+
error: error instanceof Error ? error.message : String(error),
|
|
175
|
+
},
|
|
176
|
+
};
|
|
155
177
|
}
|
|
156
178
|
}
|