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,14 +1,10 @@
|
|
|
1
|
-
import type { TeamContext } from "../team-tool/context.ts";
|
|
2
1
|
import { loadConfig, updateConfig } from "../../config/config.ts";
|
|
2
|
+
import { suggestConfigKey } from "../../config/suggestions.ts";
|
|
3
|
+
import { discoverPiThemes, formatThemesListing, setPiTheme } from "../../ui/theme-discovery.ts";
|
|
3
4
|
import { configPatchFromConfig } from "../team-tool/config-patch.ts";
|
|
5
|
+
import type { TeamContext } from "../team-tool/context.ts";
|
|
4
6
|
import { result } from "../team-tool/context.ts";
|
|
5
7
|
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
6
|
-
import { suggestConfigKey } from "../../config/suggestions.ts";
|
|
7
|
-
import {
|
|
8
|
-
formatThemesListing,
|
|
9
|
-
discoverPiThemes,
|
|
10
|
-
setPiTheme,
|
|
11
|
-
} from "../../ui/theme-discovery.ts";
|
|
12
8
|
|
|
13
9
|
// ---------------------------------------------------------------------------
|
|
14
10
|
// Effective defaults — values used when config key is not set
|
|
@@ -40,9 +36,9 @@ const EFFECTIVE_DEFAULTS: Record<string, unknown> = {
|
|
|
40
36
|
"autonomous.injectPolicy": true,
|
|
41
37
|
"autonomous.preferAsyncForLongTasks": false,
|
|
42
38
|
"autonomous.allowWorktreeSuggestion": true,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
executeWorkers: true,
|
|
40
|
+
asyncByDefault: false,
|
|
41
|
+
notifierIntervalMs: 5000,
|
|
46
42
|
"reliability.autoRetry": false,
|
|
47
43
|
"reliability.autoRecover": false,
|
|
48
44
|
"reliability.cleanupOrphanedTempDirs": true,
|
|
@@ -88,7 +84,11 @@ function formatValue(value: unknown, key?: string): string {
|
|
|
88
84
|
|
|
89
85
|
function parseValue(raw: string): unknown {
|
|
90
86
|
// JSON handles strings (quoted), numbers, booleans, null, arrays, objects.
|
|
91
|
-
try {
|
|
87
|
+
try {
|
|
88
|
+
return JSON.parse(raw);
|
|
89
|
+
} catch {
|
|
90
|
+
/* keep as string */
|
|
91
|
+
}
|
|
92
92
|
return raw;
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -107,9 +107,7 @@ function flattenConfig(obj: unknown, prefix: string = ""): string[] {
|
|
|
107
107
|
// Check if it's a "leaf object" — a value-type record like agent overrides
|
|
108
108
|
// where keys are agent names and values are { model, thinking, ... }
|
|
109
109
|
const entries = Object.entries(value as Record<string, unknown>);
|
|
110
|
-
const allLeafValues = entries.every(([, v]) =>
|
|
111
|
-
v === undefined || v === null || typeof v !== "object" || Array.isArray(v)
|
|
112
|
-
);
|
|
110
|
+
const allLeafValues = entries.every(([, v]) => v === undefined || v === null || typeof v !== "object" || Array.isArray(v));
|
|
113
111
|
if (allLeafValues && entries.length > 0) {
|
|
114
112
|
// It's a flat record like { explorer: { model: "...", thinking: "..." } }
|
|
115
113
|
// Check if nested values are objects (agent overrides pattern)
|
|
@@ -285,7 +283,10 @@ export function handleSettings(params: { config?: Record<string, unknown> }, ctx
|
|
|
285
283
|
for (const w of loaded.warnings) lines.push(` ${w}`);
|
|
286
284
|
}
|
|
287
285
|
lines.push("", USAGE);
|
|
288
|
-
return result(lines.join("\n"), {
|
|
286
|
+
return result(lines.join("\n"), {
|
|
287
|
+
...OK,
|
|
288
|
+
count: flatLines.length,
|
|
289
|
+
} as never);
|
|
289
290
|
}
|
|
290
291
|
|
|
291
292
|
// team-settings json — full JSON dump
|
|
@@ -294,7 +295,7 @@ export function handleSettings(params: { config?: Record<string, unknown> }, ctx
|
|
|
294
295
|
`// pi-crew effective config (merged from all sources)`,
|
|
295
296
|
`// Config file: ${loaded.path}`,
|
|
296
297
|
`// Sources: ${loaded.paths?.join(", ") ?? loaded.path}`,
|
|
297
|
-
...loaded.warnings?.map(w => `// WARNING: ${w}`) ?? [],
|
|
298
|
+
...(loaded.warnings?.map((w) => `// WARNING: ${w}`) ?? []),
|
|
298
299
|
"",
|
|
299
300
|
JSON.stringify(effective, null, 2),
|
|
300
301
|
];
|
|
@@ -310,15 +311,15 @@ export function handleSettings(params: { config?: Record<string, unknown> }, ctx
|
|
|
310
311
|
lines.push(` ${key}${marker}`);
|
|
311
312
|
}
|
|
312
313
|
lines.push("", "✓ = currently set in config. Keys without ✓ use defaults.", "", USAGE);
|
|
313
|
-
return result(lines.join("\n"), {
|
|
314
|
+
return result(lines.join("\n"), {
|
|
315
|
+
...OK,
|
|
316
|
+
count: KNOWN_KEYS.size,
|
|
317
|
+
} as never);
|
|
314
318
|
}
|
|
315
319
|
|
|
316
320
|
// team-settings paths — show all config file paths
|
|
317
321
|
if (args === "path" || args === "paths") {
|
|
318
|
-
const lines = [
|
|
319
|
-
"pi-crew config paths:",
|
|
320
|
-
` User config: ${loaded.path}`,
|
|
321
|
-
];
|
|
322
|
+
const lines = ["pi-crew config paths:", ` User config: ${loaded.path}`];
|
|
322
323
|
if (ctx.cwd && loaded.paths) {
|
|
323
324
|
for (const p of loaded.paths) {
|
|
324
325
|
if (p !== loaded.path) lines.push(` Additional: ${p}`);
|
|
@@ -337,7 +338,9 @@ export function handleSettings(params: { config?: Record<string, unknown> }, ctx
|
|
|
337
338
|
if (args === "theme" || args.startsWith("theme ")) {
|
|
338
339
|
const name = args === "theme" ? "" : args.slice(6).trim();
|
|
339
340
|
if (!name) {
|
|
340
|
-
const available = discoverPiThemes()
|
|
341
|
+
const available = discoverPiThemes()
|
|
342
|
+
.map((t) => t.name)
|
|
343
|
+
.join(", ");
|
|
341
344
|
return result(
|
|
342
345
|
`Usage: team-settings theme <name>\n\nAvailable Pi themes: ${available}\n\nBrowse all: team-settings themes`,
|
|
343
346
|
{ ...ERR },
|
|
@@ -356,14 +359,10 @@ export function handleSettings(params: { config?: Record<string, unknown> }, ctx
|
|
|
356
359
|
}
|
|
357
360
|
try {
|
|
358
361
|
const savedTo = setPiTheme(name);
|
|
359
|
-
return result(
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
` Applied live — no restart needed.`,
|
|
364
|
-
].join("\n"),
|
|
365
|
-
{ ...OK, theme: name } as never,
|
|
366
|
-
);
|
|
362
|
+
return result([`✓ Pi theme set to '${name}'`, ` Written to: ${savedTo}`, ` Applied live — no restart needed.`].join("\n"), {
|
|
363
|
+
...OK,
|
|
364
|
+
theme: name,
|
|
365
|
+
} as never);
|
|
367
366
|
} catch (error) {
|
|
368
367
|
return result(error instanceof Error ? error.message : String(error), { ...ERR }, true);
|
|
369
368
|
}
|
|
@@ -382,23 +381,29 @@ export function handleSettings(params: { config?: Record<string, unknown> }, ctx
|
|
|
382
381
|
if (args === "scope" || args.startsWith("scope ")) {
|
|
383
382
|
const scopeArg = args === "scope" ? "" : args.slice(6).trim();
|
|
384
383
|
if (!scopeArg) {
|
|
385
|
-
return result(
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
384
|
+
return result(
|
|
385
|
+
[
|
|
386
|
+
`Current write scope: ${scope}`,
|
|
387
|
+
` user → writes to ${loaded.path}`,
|
|
388
|
+
` project → writes to ${projectConfigPath(ctx.cwd)}`,
|
|
389
|
+
"Usage: team-settings scope [user|project]",
|
|
390
|
+
].join("\n"),
|
|
391
|
+
{ ...OK, scope } as never,
|
|
392
|
+
);
|
|
391
393
|
}
|
|
392
394
|
if (scopeArg !== "user" && scopeArg !== "project") {
|
|
393
395
|
return result("Scope must be 'user' or 'project'.", { ...ERR }, true);
|
|
394
396
|
}
|
|
395
|
-
return result(
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
397
|
+
return result(
|
|
398
|
+
[
|
|
399
|
+
`Write scope is a per-command option. Use:`,
|
|
400
|
+
` team-settings set <key> <value> (writes to ${scopeArg === "project" ? "project" : "user"} config)`,
|
|
401
|
+
``,
|
|
402
|
+
`To change scope for a single command, pass scope in the team tool:`,
|
|
403
|
+
` team(action="settings", config={ args: "set <key> <value>", scope: "${scopeArg}" })`,
|
|
404
|
+
].join("\n"),
|
|
405
|
+
{ ...OK } as never,
|
|
406
|
+
);
|
|
402
407
|
}
|
|
403
408
|
|
|
404
409
|
// team-settings get <key>
|
|
@@ -413,7 +418,11 @@ export function handleSettings(params: { config?: Record<string, unknown> }, ctx
|
|
|
413
418
|
if (suggestion) note = `\n(did you mean '${suggestion}'?)`;
|
|
414
419
|
else note = "\n(unknown key — may not take effect)";
|
|
415
420
|
}
|
|
416
|
-
return result(`${key} = ${formatValue(value, key)}${note}`, {
|
|
421
|
+
return result(`${key} = ${formatValue(value, key)}${note}`, {
|
|
422
|
+
...OK,
|
|
423
|
+
key,
|
|
424
|
+
value,
|
|
425
|
+
} as never);
|
|
417
426
|
}
|
|
418
427
|
|
|
419
428
|
// team-settings unset <key>
|
|
@@ -422,7 +431,10 @@ export function handleSettings(params: { config?: Record<string, unknown> }, ctx
|
|
|
422
431
|
if (!key) return result("Usage: team-settings unset <key>", { ...ERR }, true);
|
|
423
432
|
try {
|
|
424
433
|
const saved = updateConfig({}, { cwd: ctx.cwd, scope, unsetPaths: [key] });
|
|
425
|
-
return result(`Unset ${key}\nSaved to: ${saved.path}`, {
|
|
434
|
+
return result(`Unset ${key}\nSaved to: ${saved.path}`, {
|
|
435
|
+
...OK,
|
|
436
|
+
key,
|
|
437
|
+
} as never);
|
|
426
438
|
} catch (error) {
|
|
427
439
|
return result(error instanceof Error ? error.message : String(error), { ...ERR }, true);
|
|
428
440
|
}
|
|
@@ -432,7 +444,12 @@ export function handleSettings(params: { config?: Record<string, unknown> }, ctx
|
|
|
432
444
|
if (args.startsWith("set ")) {
|
|
433
445
|
const rest = args.slice(4).trim();
|
|
434
446
|
const spaceIdx = rest.indexOf(" ");
|
|
435
|
-
if (spaceIdx === -1)
|
|
447
|
+
if (spaceIdx === -1)
|
|
448
|
+
return result(
|
|
449
|
+
"Usage: team-settings set <key> <value>\nExample: team-settings set runtime.mode child-process",
|
|
450
|
+
{ ...ERR },
|
|
451
|
+
true,
|
|
452
|
+
);
|
|
436
453
|
const key = rest.slice(0, spaceIdx);
|
|
437
454
|
const rawValue = rest.slice(spaceIdx + 1).trim();
|
|
438
455
|
if (!key) return result("Usage: team-settings set <key> <value>", { ...ERR }, true);
|
|
@@ -450,23 +467,44 @@ export function handleSettings(params: { config?: Record<string, unknown> }, ctx
|
|
|
450
467
|
let warning = "";
|
|
451
468
|
if (!KNOWN_KEYS.has(key) && !key.startsWith("agents.overrides.") && !key.startsWith("ui.")) {
|
|
452
469
|
const suggestion = suggestConfigKey(key, KNOWN_SORTED);
|
|
453
|
-
warning = suggestion
|
|
470
|
+
warning = suggestion
|
|
471
|
+
? `\nWarning: unknown key. Did you mean '${suggestion}'?`
|
|
472
|
+
: "\nWarning: unknown key — verify it exists in config schema.";
|
|
454
473
|
}
|
|
455
474
|
|
|
456
475
|
// Check if project config would sanitize this key
|
|
457
476
|
if (scope === "project") {
|
|
458
|
-
const sensitiveKeys = [
|
|
459
|
-
|
|
460
|
-
|
|
477
|
+
const sensitiveKeys = [
|
|
478
|
+
"executeWorkers",
|
|
479
|
+
"asyncByDefault",
|
|
480
|
+
"runtime.mode",
|
|
481
|
+
"runtime.preferLiveSession",
|
|
482
|
+
"runtime.allowChildProcessFallback",
|
|
483
|
+
"runtime.inheritContext",
|
|
484
|
+
"runtime.isolationPolicy",
|
|
485
|
+
"autonomous.profile",
|
|
486
|
+
"autonomous.enabled",
|
|
487
|
+
"autonomous.injectPolicy",
|
|
488
|
+
"agents.overrides",
|
|
489
|
+
"agents.disableBuiltins",
|
|
490
|
+
];
|
|
491
|
+
if (sensitiveKeys.some((k) => key === k || key.startsWith(k + "."))) {
|
|
492
|
+
warning +=
|
|
493
|
+
"\nNote: this key is sensitive and will be ignored in project-level config for security. Set it in user scope instead.";
|
|
461
494
|
}
|
|
462
495
|
}
|
|
463
496
|
|
|
464
|
-
return result(
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
497
|
+
return result(
|
|
498
|
+
[
|
|
499
|
+
`Set ${key} = ${formatValue(value, key)}`,
|
|
500
|
+
`Effective: ${formatValue(effectiveValue, key)}`,
|
|
501
|
+
`Saved to: ${saved.path}`,
|
|
502
|
+
warning,
|
|
503
|
+
]
|
|
504
|
+
.filter(Boolean)
|
|
505
|
+
.join("\n"),
|
|
506
|
+
{ ...OK, key, value } as never,
|
|
507
|
+
);
|
|
470
508
|
} catch (error) {
|
|
471
509
|
return result(error instanceof Error ? error.message : String(error), { ...ERR }, true);
|
|
472
510
|
}
|
|
@@ -4,17 +4,13 @@
|
|
|
4
4
|
import * as fs from "node:fs";
|
|
5
5
|
import * as os from "node:os";
|
|
6
6
|
import * as path from "node:path";
|
|
7
|
-
import { listRuns } from "../run-index.ts";
|
|
8
7
|
import { readCrewAgents } from "../../runtime/crew-agent-records.ts";
|
|
9
|
-
import {
|
|
10
|
-
isActiveRunStatus,
|
|
11
|
-
hasStaleAsyncProcess,
|
|
12
|
-
isLikelyOrphanedActiveRun,
|
|
13
|
-
} from "../../runtime/process-status.ts";
|
|
14
|
-
import { result, type TeamContext } from "./context.ts";
|
|
8
|
+
import { hasStaleAsyncProcess, isActiveRunStatus, isLikelyOrphanedActiveRun } from "../../runtime/process-status.ts";
|
|
15
9
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
16
|
-
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
17
10
|
import type { TeamRunManifest, TeamTaskState } from "../../state/types.ts";
|
|
11
|
+
import { listRuns } from "../run-index.ts";
|
|
12
|
+
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
13
|
+
import { result, type TeamContext } from "./context.ts";
|
|
18
14
|
|
|
19
15
|
// ── Types ────────────────────────────────────────────────────────────
|
|
20
16
|
|
|
@@ -69,9 +65,7 @@ export const STUCK_TASK_THRESHOLD_MS = 5 * 60 * 1000; // 5 minutes
|
|
|
69
65
|
function readRunTasks(stateRoot: string): TeamTaskState[] {
|
|
70
66
|
const tasksPath = path.join(stateRoot, "tasks.json");
|
|
71
67
|
try {
|
|
72
|
-
return JSON.parse(
|
|
73
|
-
fs.readFileSync(tasksPath, "utf-8"),
|
|
74
|
-
) as TeamTaskState[];
|
|
68
|
+
return JSON.parse(fs.readFileSync(tasksPath, "utf-8")) as TeamTaskState[];
|
|
75
69
|
} catch {
|
|
76
70
|
return [];
|
|
77
71
|
}
|
|
@@ -81,10 +75,7 @@ function readRunTasks(stateRoot: string): TeamTaskState[] {
|
|
|
81
75
|
* Detect "stuck" tasks: tasks with status "running" whose last heartbeat or
|
|
82
76
|
* activity timestamp is older than STUCK_TASK_THRESHOLD_MS.
|
|
83
77
|
*/
|
|
84
|
-
export function detectStuckTasks(
|
|
85
|
-
run: { runId: string; stateRoot: string },
|
|
86
|
-
now: number,
|
|
87
|
-
): StuckTask[] {
|
|
78
|
+
export function detectStuckTasks(run: { runId: string; stateRoot: string }, now: number): StuckTask[] {
|
|
88
79
|
const tasks = readRunTasks(run.stateRoot);
|
|
89
80
|
const stuck: StuckTask[] = [];
|
|
90
81
|
|
|
@@ -92,23 +83,14 @@ export function detectStuckTasks(
|
|
|
92
83
|
if (task.status !== "running") continue;
|
|
93
84
|
|
|
94
85
|
// Check agentProgress.lastActivityAt first, then heartbeat.lastSeenAt, then startedAt
|
|
95
|
-
const activityAt = task.agentProgress?.lastActivityAt
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const heartbeatAt = task.heartbeat?.lastSeenAt
|
|
99
|
-
? new Date(task.heartbeat.lastSeenAt).getTime()
|
|
100
|
-
: Number.NaN;
|
|
101
|
-
const startedAt = task.startedAt
|
|
102
|
-
? new Date(task.startedAt).getTime()
|
|
103
|
-
: Number.NaN;
|
|
86
|
+
const activityAt = task.agentProgress?.lastActivityAt ? new Date(task.agentProgress.lastActivityAt).getTime() : Number.NaN;
|
|
87
|
+
const heartbeatAt = task.heartbeat?.lastSeenAt ? new Date(task.heartbeat.lastSeenAt).getTime() : Number.NaN;
|
|
88
|
+
const startedAt = task.startedAt ? new Date(task.startedAt).getTime() : Number.NaN;
|
|
104
89
|
|
|
105
90
|
// Use the most recent valid timestamp
|
|
106
91
|
let latest = Number.NaN;
|
|
107
92
|
for (const ts of [activityAt, heartbeatAt, startedAt]) {
|
|
108
|
-
if (
|
|
109
|
-
Number.isFinite(ts) &&
|
|
110
|
-
(!Number.isFinite(latest) || ts > latest)
|
|
111
|
-
) {
|
|
93
|
+
if (Number.isFinite(ts) && (!Number.isFinite(latest) || ts > latest)) {
|
|
112
94
|
latest = ts;
|
|
113
95
|
}
|
|
114
96
|
}
|
|
@@ -135,40 +117,25 @@ export function detectStuckTasks(
|
|
|
135
117
|
* Read-only — does NOT mutate anything.
|
|
136
118
|
* Pattern adapted from stale-reconciler.ts:reconcileOrphanedTempWorkspaces().
|
|
137
119
|
*/
|
|
138
|
-
export function scanZombieTempWorkspaces(
|
|
139
|
-
tmpDir: string,
|
|
140
|
-
now: number,
|
|
141
|
-
): ZombieWorkspace[] {
|
|
120
|
+
export function scanZombieTempWorkspaces(tmpDir: string, now: number): ZombieWorkspace[] {
|
|
142
121
|
if (!tmpDir || !fs.existsSync(tmpDir)) return [];
|
|
143
122
|
const zombies: ZombieWorkspace[] = [];
|
|
144
123
|
|
|
145
124
|
try {
|
|
146
125
|
const entries = fs.readdirSync(tmpDir, { withFileTypes: true });
|
|
147
126
|
for (const entry of entries) {
|
|
148
|
-
if (!entry.isDirectory() || !entry.name.startsWith("pi-crew-"))
|
|
149
|
-
continue;
|
|
127
|
+
if (!entry.isDirectory() || !entry.name.startsWith("pi-crew-")) continue;
|
|
150
128
|
const workspaceDir = path.join(tmpDir, entry.name);
|
|
151
|
-
const stateRunsDir = path.join(
|
|
152
|
-
workspaceDir,
|
|
153
|
-
".crew",
|
|
154
|
-
"state",
|
|
155
|
-
"runs",
|
|
156
|
-
);
|
|
129
|
+
const stateRunsDir = path.join(workspaceDir, ".crew", "state", "runs");
|
|
157
130
|
if (!fs.existsSync(stateRunsDir)) continue;
|
|
158
131
|
|
|
159
132
|
let runCount = 0;
|
|
160
133
|
try {
|
|
161
134
|
for (const runDir of fs.readdirSync(stateRunsDir)) {
|
|
162
|
-
const manifestPath = path.join(
|
|
163
|
-
stateRunsDir,
|
|
164
|
-
runDir,
|
|
165
|
-
"manifest.json",
|
|
166
|
-
);
|
|
135
|
+
const manifestPath = path.join(stateRunsDir, runDir, "manifest.json");
|
|
167
136
|
if (fs.existsSync(manifestPath)) {
|
|
168
137
|
try {
|
|
169
|
-
const manifest = JSON.parse(
|
|
170
|
-
fs.readFileSync(manifestPath, "utf-8"),
|
|
171
|
-
) as { runId?: string; status?: string };
|
|
138
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8")) as { runId?: string; status?: string };
|
|
172
139
|
if (manifest.runId) runCount++;
|
|
173
140
|
} catch {
|
|
174
141
|
/* skip corrupt manifest */
|
|
@@ -224,29 +191,16 @@ export function collectTempWorkspaceRuns(
|
|
|
224
191
|
try {
|
|
225
192
|
const entries = fs.readdirSync(tmpDir, { withFileTypes: true });
|
|
226
193
|
for (const entry of entries) {
|
|
227
|
-
if (!entry.isDirectory() || !entry.name.startsWith("pi-crew-"))
|
|
228
|
-
|
|
229
|
-
const stateRunsDir = path.join(
|
|
230
|
-
tmpDir,
|
|
231
|
-
entry.name,
|
|
232
|
-
".crew",
|
|
233
|
-
"state",
|
|
234
|
-
"runs",
|
|
235
|
-
);
|
|
194
|
+
if (!entry.isDirectory() || !entry.name.startsWith("pi-crew-")) continue;
|
|
195
|
+
const stateRunsDir = path.join(tmpDir, entry.name, ".crew", "state", "runs");
|
|
236
196
|
if (!fs.existsSync(stateRunsDir)) continue;
|
|
237
197
|
|
|
238
198
|
try {
|
|
239
199
|
for (const runDir of fs.readdirSync(stateRunsDir)) {
|
|
240
|
-
const manifestPath = path.join(
|
|
241
|
-
stateRunsDir,
|
|
242
|
-
runDir,
|
|
243
|
-
"manifest.json",
|
|
244
|
-
);
|
|
200
|
+
const manifestPath = path.join(stateRunsDir, runDir, "manifest.json");
|
|
245
201
|
if (!fs.existsSync(manifestPath)) continue;
|
|
246
202
|
try {
|
|
247
|
-
const manifest = JSON.parse(
|
|
248
|
-
fs.readFileSync(manifestPath, "utf-8"),
|
|
249
|
-
) as {
|
|
203
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8")) as {
|
|
250
204
|
runId?: string;
|
|
251
205
|
status?: string;
|
|
252
206
|
cwd?: string;
|
|
@@ -256,15 +210,8 @@ export function collectTempWorkspaceRuns(
|
|
|
256
210
|
updatedAt?: string;
|
|
257
211
|
summary?: string;
|
|
258
212
|
};
|
|
259
|
-
if (!manifest.runId || primaryIds.has(manifest.runId))
|
|
260
|
-
|
|
261
|
-
if (
|
|
262
|
-
manifest.status &&
|
|
263
|
-
manifest.cwd &&
|
|
264
|
-
manifest.stateRoot &&
|
|
265
|
-
manifest.artifactsRoot &&
|
|
266
|
-
manifest.updatedAt
|
|
267
|
-
) {
|
|
213
|
+
if (!manifest.runId || primaryIds.has(manifest.runId)) continue;
|
|
214
|
+
if (manifest.status && manifest.cwd && manifest.stateRoot && manifest.artifactsRoot && manifest.updatedAt) {
|
|
268
215
|
runs.push({
|
|
269
216
|
runId: manifest.runId!,
|
|
270
217
|
status: manifest.status,
|
|
@@ -296,18 +243,7 @@ export function collectTempWorkspaceRuns(
|
|
|
296
243
|
*/
|
|
297
244
|
export function countStatuses(
|
|
298
245
|
runs: Array<{ status: string }>,
|
|
299
|
-
): Pick<
|
|
300
|
-
HealthCounts,
|
|
301
|
-
| "total"
|
|
302
|
-
| "running"
|
|
303
|
-
| "completed"
|
|
304
|
-
| "failed"
|
|
305
|
-
| "cancelled"
|
|
306
|
-
| "blocked"
|
|
307
|
-
| "queued"
|
|
308
|
-
| "planning"
|
|
309
|
-
| "waiting"
|
|
310
|
-
> {
|
|
246
|
+
): Pick<HealthCounts, "total" | "running" | "completed" | "failed" | "cancelled" | "blocked" | "queued" | "planning" | "waiting"> {
|
|
311
247
|
const counts = {
|
|
312
248
|
total: runs.length,
|
|
313
249
|
running: 0,
|
|
@@ -392,11 +328,7 @@ export function buildHealthReport(
|
|
|
392
328
|
|
|
393
329
|
for (const run of allRuns) {
|
|
394
330
|
// 1. Ghost: active status but cwd no longer exists
|
|
395
|
-
if (
|
|
396
|
-
isActiveRunStatus(run.status) &&
|
|
397
|
-
run.cwd &&
|
|
398
|
-
!fs.existsSync(run.cwd)
|
|
399
|
-
) {
|
|
331
|
+
if (isActiveRunStatus(run.status) && run.cwd && !fs.existsSync(run.cwd)) {
|
|
400
332
|
ghost.push({
|
|
401
333
|
runId: run.runId,
|
|
402
334
|
reason: "dead-cwd",
|
|
@@ -406,10 +338,7 @@ export function buildHealthReport(
|
|
|
406
338
|
}
|
|
407
339
|
|
|
408
340
|
// 2. Corrupted: state root or artifacts root missing
|
|
409
|
-
if (
|
|
410
|
-
!fs.existsSync(run.stateRoot) ||
|
|
411
|
-
!fs.existsSync(run.artifactsRoot)
|
|
412
|
-
) {
|
|
341
|
+
if (!fs.existsSync(run.stateRoot) || !fs.existsSync(run.artifactsRoot)) {
|
|
413
342
|
corrupted.push({
|
|
414
343
|
runId: run.runId,
|
|
415
344
|
reason: "missing-state-or-artifacts",
|
|
@@ -514,19 +443,12 @@ export function buildHealthReport(
|
|
|
514
443
|
if (zombieWorkspaces.length > 0) {
|
|
515
444
|
lines.push("Zombie /tmp/ workspaces:");
|
|
516
445
|
for (const z of zombieWorkspaces) {
|
|
517
|
-
lines.push(
|
|
518
|
-
` - ${z.dir} (${z.runCount} run${z.runCount !== 1 ? "s" : ""})`,
|
|
519
|
-
);
|
|
446
|
+
lines.push(` - ${z.dir} (${z.runCount} run${z.runCount !== 1 ? "s" : ""})`);
|
|
520
447
|
}
|
|
521
448
|
lines.push("");
|
|
522
449
|
}
|
|
523
450
|
|
|
524
|
-
const hasIssues =
|
|
525
|
-
ghost.length > 0 ||
|
|
526
|
-
orphaned.length > 0 ||
|
|
527
|
-
corrupted.length > 0 ||
|
|
528
|
-
allStuck.length > 0 ||
|
|
529
|
-
zombieWorkspaces.length > 0;
|
|
451
|
+
const hasIssues = ghost.length > 0 || orphaned.length > 0 || corrupted.length > 0 || allStuck.length > 0 || zombieWorkspaces.length > 0;
|
|
530
452
|
|
|
531
453
|
if (!hasIssues) {
|
|
532
454
|
lines.push("All runs healthy.");
|
|
@@ -544,10 +466,7 @@ export function buildHealthReport(
|
|
|
544
466
|
|
|
545
467
|
// ── Main handler ─────────────────────────────────────────────────────
|
|
546
468
|
|
|
547
|
-
export function handleHealthMonitor(
|
|
548
|
-
ctx: TeamContext,
|
|
549
|
-
params: TeamToolParamsValue,
|
|
550
|
-
): PiTeamsToolResult {
|
|
469
|
+
export function handleHealthMonitor(ctx: TeamContext, params: TeamToolParamsValue): PiTeamsToolResult {
|
|
551
470
|
const { text, counts, hasIssues } = buildHealthReport(ctx, params);
|
|
552
471
|
|
|
553
472
|
return result(
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
2
2
|
import { readEvents } from "../../state/event-log.ts";
|
|
3
3
|
import { loadRunManifestById } from "../../state/state-store.ts";
|
|
4
|
-
import { aggregateUsage,
|
|
5
|
-
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
4
|
+
import { aggregateUsage, formatCostReport, formatUsage } from "../../state/usage.ts";
|
|
6
5
|
import { locateRunCwd } from "../team-tool.ts";
|
|
6
|
+
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
7
7
|
import { result, type TeamContext } from "./context.ts";
|
|
8
|
-
import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
|
|
9
8
|
import { formatFailurePatterns } from "./failure-patterns.ts";
|
|
9
|
+
import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
|
|
10
10
|
|
|
11
11
|
export function handleEvents(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
12
12
|
if (!params.runId) return result("Events requires runId.", { action: "events", status: "error" }, true);
|
|
@@ -15,8 +15,21 @@ export function handleEvents(params: TeamToolParamsValue, ctx: TeamContext): PiT
|
|
|
15
15
|
const loaded = loadRunManifestById(runCwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
16
16
|
if (!loaded) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "events", status: "error" }, true);
|
|
17
17
|
const events = readEvents(loaded.manifest.eventsPath);
|
|
18
|
-
const lines = [
|
|
19
|
-
|
|
18
|
+
const lines = [
|
|
19
|
+
`Events for ${loaded.manifest.runId}:`,
|
|
20
|
+
...(events.length
|
|
21
|
+
? events.map(
|
|
22
|
+
(event) =>
|
|
23
|
+
`${event.time} ${event.type}${event.taskId ? ` ${event.taskId}` : ""}${event.message ? `: ${event.message}` : ""}${event.data ? ` ${JSON.stringify(event.data)}` : ""}`,
|
|
24
|
+
)
|
|
25
|
+
: ["(none)"]),
|
|
26
|
+
];
|
|
27
|
+
return result(lines.join("\n"), {
|
|
28
|
+
action: "events",
|
|
29
|
+
status: "ok",
|
|
30
|
+
runId: loaded.manifest.runId,
|
|
31
|
+
artifactsRoot: loaded.manifest.artifactsRoot,
|
|
32
|
+
});
|
|
20
33
|
}
|
|
21
34
|
|
|
22
35
|
export function handleArtifacts(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
@@ -25,8 +38,21 @@ export function handleArtifacts(params: TeamToolParamsValue, ctx: TeamContext):
|
|
|
25
38
|
if (!runCwd) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "artifacts", status: "error" }, true);
|
|
26
39
|
const loaded = loadRunManifestById(runCwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
27
40
|
if (!loaded) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "artifacts", status: "error" }, true);
|
|
28
|
-
const lines = [
|
|
29
|
-
|
|
41
|
+
const lines = [
|
|
42
|
+
`Artifacts for ${loaded.manifest.runId}:`,
|
|
43
|
+
...(loaded.manifest.artifacts.length
|
|
44
|
+
? loaded.manifest.artifacts.map(
|
|
45
|
+
(artifact) =>
|
|
46
|
+
`- ${artifact.kind}: ${artifact.path}${artifact.sizeBytes !== undefined ? ` (${artifact.sizeBytes} bytes)` : ""}${artifact.contentHash ? ` sha256=${artifact.contentHash.slice(0, 12)}` : ""}`,
|
|
47
|
+
)
|
|
48
|
+
: ["- (none)"]),
|
|
49
|
+
];
|
|
50
|
+
return result(lines.join("\n"), {
|
|
51
|
+
action: "artifacts",
|
|
52
|
+
status: "ok",
|
|
53
|
+
runId: loaded.manifest.runId,
|
|
54
|
+
artifactsRoot: loaded.manifest.artifactsRoot,
|
|
55
|
+
});
|
|
30
56
|
}
|
|
31
57
|
|
|
32
58
|
export function handleSummary(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
@@ -49,7 +75,14 @@ export function handleSummary(params: TeamToolParamsValue, ctx: TeamContext): Pi
|
|
|
49
75
|
...(failurePatternLines.length > 0 ? ["", ...failurePatternLines] : []),
|
|
50
76
|
"",
|
|
51
77
|
"Tasks:",
|
|
52
|
-
...loaded.tasks.map(
|
|
78
|
+
...loaded.tasks.map(
|
|
79
|
+
(task) => `- ${task.id}: ${task.status} (${task.role} -> ${task.agent})${task.error ? ` - ${task.error}` : ""}`,
|
|
80
|
+
),
|
|
53
81
|
];
|
|
54
|
-
return result(lines.join("\n"), {
|
|
82
|
+
return result(lines.join("\n"), {
|
|
83
|
+
action: "summary",
|
|
84
|
+
status: "ok",
|
|
85
|
+
runId: loaded.manifest.runId,
|
|
86
|
+
artifactsRoot: loaded.manifest.artifactsRoot,
|
|
87
|
+
});
|
|
55
88
|
}
|
|
@@ -36,7 +36,10 @@ export function enforceDestructiveIntent(
|
|
|
36
36
|
const label = DESTRUCTIVE_ACTION_LABELS[action];
|
|
37
37
|
return result(
|
|
38
38
|
`Destructive action '${label}' requires config.intent when policy.requireIntentForDestructiveActions is enabled.`,
|
|
39
|
-
{
|
|
39
|
+
{
|
|
40
|
+
action: action === "delete" ? "management" : action,
|
|
41
|
+
status: "error",
|
|
42
|
+
},
|
|
40
43
|
true,
|
|
41
44
|
);
|
|
42
45
|
}
|