pi-crew 0.9.15 → 0.9.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +145 -0
- package/README.md +19 -0
- package/dist/build-meta.json +21790 -0
- package/dist/index.mjs +83070 -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/patterns/command-agent-skill.md +1 -1
- 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 +166 -590
- 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 +151 -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 +27 -23
- 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 +343 -78
- 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 +193 -40
- 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 +186 -58
- 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 +12 -30
- 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 +8 -16
- 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 +1 -2
- package/src/runtime/retry-executor.ts +20 -4
- package/src/runtime/retry-runner.ts +26 -50
- 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 +86 -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 +11 -18
- 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 +29 -8
- 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 +1 -4
- 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 +105 -26
- 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 +129 -45
- 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/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 +45 -24
- 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
|
@@ -7,15 +7,7 @@ import { logInternalError } from "../utils/internal-error.ts";
|
|
|
7
7
|
import { projectCrewRoot } from "../utils/paths.ts";
|
|
8
8
|
import { redactSecrets } from "../utils/redaction.ts";
|
|
9
9
|
|
|
10
|
-
export type SubagentStatus =
|
|
11
|
-
| "queued"
|
|
12
|
-
| "running"
|
|
13
|
-
| "completed"
|
|
14
|
-
| "failed"
|
|
15
|
-
| "cancelled"
|
|
16
|
-
| "error"
|
|
17
|
-
| "blocked"
|
|
18
|
-
| "stopped";
|
|
10
|
+
export type SubagentStatus = "queued" | "running" | "completed" | "failed" | "cancelled" | "error" | "blocked" | "stopped";
|
|
19
11
|
|
|
20
12
|
export interface SubagentSpawnOptions {
|
|
21
13
|
cwd: string;
|
|
@@ -61,10 +53,7 @@ export interface SubagentRecord {
|
|
|
61
53
|
lifetimeUsage?: { input: number; output: number; cacheWrite: number };
|
|
62
54
|
}
|
|
63
55
|
|
|
64
|
-
type SpawnRunner = (
|
|
65
|
-
options: SubagentSpawnOptions,
|
|
66
|
-
signal?: AbortSignal,
|
|
67
|
-
) => Promise<PiTeamsToolResult>;
|
|
56
|
+
type SpawnRunner = (options: SubagentSpawnOptions, signal?: AbortSignal) => Promise<PiTeamsToolResult>;
|
|
68
57
|
type Notify = (record: SubagentRecord) => void;
|
|
69
58
|
type NotifyEvent = (type: string, data: Record<string, unknown>) => void;
|
|
70
59
|
|
|
@@ -81,11 +70,7 @@ function isValidSubagentId(id: string): boolean {
|
|
|
81
70
|
|
|
82
71
|
function persistedSubagentPath(cwd: string, id: string): string {
|
|
83
72
|
if (!isValidSubagentId(id)) throw new Error(`Invalid subagent id: ${id}`);
|
|
84
|
-
return path.join(
|
|
85
|
-
projectCrewRoot(cwd),
|
|
86
|
-
DEFAULT_PATHS.state.subagentsSubdir,
|
|
87
|
-
`${id}.json`,
|
|
88
|
-
);
|
|
73
|
+
return path.join(projectCrewRoot(cwd), DEFAULT_PATHS.state.subagentsSubdir, `${id}.json`);
|
|
89
74
|
}
|
|
90
75
|
|
|
91
76
|
function serializableRecord(record: SubagentRecord): SubagentRecord {
|
|
@@ -93,18 +78,11 @@ function serializableRecord(record: SubagentRecord): SubagentRecord {
|
|
|
93
78
|
return rest;
|
|
94
79
|
}
|
|
95
80
|
|
|
96
|
-
export function savePersistedSubagentRecord(
|
|
97
|
-
cwd: string,
|
|
98
|
-
record: SubagentRecord,
|
|
99
|
-
): void {
|
|
81
|
+
export function savePersistedSubagentRecord(cwd: string, record: SubagentRecord): void {
|
|
100
82
|
try {
|
|
101
83
|
const filePath = persistedSubagentPath(cwd, record.id);
|
|
102
84
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
103
|
-
fs.writeFileSync(
|
|
104
|
-
filePath,
|
|
105
|
-
`${JSON.stringify(redactSecrets(serializableRecord(record)), null, 2)}\n`,
|
|
106
|
-
"utf-8",
|
|
107
|
-
);
|
|
85
|
+
fs.writeFileSync(filePath, `${JSON.stringify(redactSecrets(serializableRecord(record)), null, 2)}\n`, "utf-8");
|
|
108
86
|
// SECURITY: Restrict permissions to owner-only (rw-------).
|
|
109
87
|
// On multi-user systems, other users must not read task prompts,
|
|
110
88
|
// agent descriptions, and run IDs from subagent record files.
|
|
@@ -114,6 +92,36 @@ export function savePersistedSubagentRecord(
|
|
|
114
92
|
}
|
|
115
93
|
}
|
|
116
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Delete the persisted subagent record from disk.
|
|
97
|
+
* Used when a subagent is cancelled or terminated — the user wants no trace.
|
|
98
|
+
* Safe-fail: if the file does not exist (already deleted), this is a no-op.
|
|
99
|
+
* Any other I/O error is logged but not propagated.
|
|
100
|
+
*/
|
|
101
|
+
export function removePersistedSubagentRecord(cwd: string, id: string): boolean {
|
|
102
|
+
try {
|
|
103
|
+
const filePath = persistedSubagentPath(cwd, id);
|
|
104
|
+
fs.unlinkSync(filePath);
|
|
105
|
+
return true;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
const code = (error as NodeJS.ErrnoException)?.code;
|
|
108
|
+
if (code === "ENOENT") return false;
|
|
109
|
+
logInternalError("subagent-manager.remove", error, `id=${id}`);
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Predicate: should this record's persisted file be deleted on terminal status?
|
|
116
|
+
* Only abnormal terminations (cancelled / stopped / terminated-flag) are wiped.
|
|
117
|
+
* Successful runs (`completed`) and agent errors (`failed`, `error`) keep their audit trail.
|
|
118
|
+
*/
|
|
119
|
+
export function shouldDeleteOnTerminalStatus(record: SubagentRecord): boolean {
|
|
120
|
+
if (record.terminated === true) return true;
|
|
121
|
+
const s = record.status;
|
|
122
|
+
return s === "cancelled" || s === "stopped";
|
|
123
|
+
}
|
|
124
|
+
|
|
117
125
|
const ALLOWED_RECORD_FIELDS = new Set([
|
|
118
126
|
"id",
|
|
119
127
|
"agentId",
|
|
@@ -156,9 +164,7 @@ function sanitizePersistedRecord(raw: unknown): SubagentRecord | undefined {
|
|
|
156
164
|
for (const key of Object.keys(obj)) {
|
|
157
165
|
if (
|
|
158
166
|
ALLOWED_RECORD_FIELDS.has(key) &&
|
|
159
|
-
(typeof obj[key] === "string" ||
|
|
160
|
-
typeof obj[key] === "number" ||
|
|
161
|
-
typeof obj[key] === "boolean")
|
|
167
|
+
(typeof obj[key] === "string" || typeof obj[key] === "number" || typeof obj[key] === "boolean")
|
|
162
168
|
) {
|
|
163
169
|
clean[key] = obj[key];
|
|
164
170
|
}
|
|
@@ -168,14 +174,9 @@ function sanitizePersistedRecord(raw: unknown): SubagentRecord | undefined {
|
|
|
168
174
|
return clean as unknown as SubagentRecord;
|
|
169
175
|
}
|
|
170
176
|
|
|
171
|
-
export function readPersistedSubagentRecord(
|
|
172
|
-
cwd: string,
|
|
173
|
-
id: string,
|
|
174
|
-
): SubagentRecord | undefined {
|
|
177
|
+
export function readPersistedSubagentRecord(cwd: string, id: string): SubagentRecord | undefined {
|
|
175
178
|
try {
|
|
176
|
-
const raw = JSON.parse(
|
|
177
|
-
fs.readFileSync(persistedSubagentPath(cwd, id), "utf-8"),
|
|
178
|
-
);
|
|
179
|
+
const raw = JSON.parse(fs.readFileSync(persistedSubagentPath(cwd, id), "utf-8"));
|
|
179
180
|
return sanitizePersistedRecord(raw);
|
|
180
181
|
} catch {
|
|
181
182
|
return undefined;
|
|
@@ -196,10 +197,7 @@ function detailsRunId(result: PiTeamsToolResult): string | undefined {
|
|
|
196
197
|
return typeof details?.runId === "string" ? details.runId : undefined;
|
|
197
198
|
}
|
|
198
199
|
|
|
199
|
-
function totalRunTurns(
|
|
200
|
-
cwd: string,
|
|
201
|
-
runId: string | undefined,
|
|
202
|
-
): number | undefined {
|
|
200
|
+
function totalRunTurns(cwd: string, runId: string | undefined): number | undefined {
|
|
203
201
|
if (!runId) return undefined;
|
|
204
202
|
const loaded = loadRunManifestById(cwd, runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
205
203
|
if (!loaded) return undefined;
|
|
@@ -228,33 +226,20 @@ export class SubagentManager {
|
|
|
228
226
|
private readonly onEvent?: NotifyEvent;
|
|
229
227
|
private readonly pollIntervalMs: number;
|
|
230
228
|
|
|
231
|
-
constructor(
|
|
232
|
-
maxConcurrent = 4,
|
|
233
|
-
onComplete?: Notify,
|
|
234
|
-
pollIntervalMs = 1000,
|
|
235
|
-
onEvent?: NotifyEvent,
|
|
236
|
-
) {
|
|
229
|
+
constructor(maxConcurrent = 4, onComplete?: Notify, pollIntervalMs = 1000, onEvent?: NotifyEvent) {
|
|
237
230
|
this.maxConcurrent = maxConcurrent;
|
|
238
231
|
this.onComplete = onComplete;
|
|
239
232
|
this.onEvent = onEvent;
|
|
240
233
|
this.pollIntervalMs = pollIntervalMs;
|
|
241
234
|
}
|
|
242
235
|
|
|
243
|
-
spawn(
|
|
244
|
-
options: SubagentSpawnOptions,
|
|
245
|
-
runner: SpawnRunner,
|
|
246
|
-
signal?: AbortSignal,
|
|
247
|
-
): SubagentRecord {
|
|
236
|
+
spawn(options: SubagentSpawnOptions, runner: SpawnRunner, signal?: AbortSignal): SubagentRecord {
|
|
248
237
|
const record: SubagentRecord = {
|
|
249
238
|
id: `agent_${Date.now().toString(36)}_${(++this.counter).toString(36)}`,
|
|
250
239
|
type: options.type,
|
|
251
240
|
description: options.description,
|
|
252
241
|
prompt: options.prompt,
|
|
253
|
-
status:
|
|
254
|
-
options.background &&
|
|
255
|
-
this.runningBackground >= this.maxConcurrent
|
|
256
|
-
? "queued"
|
|
257
|
-
: "running",
|
|
242
|
+
status: options.background && this.runningBackground >= this.maxConcurrent ? "queued" : "running",
|
|
258
243
|
startedAt: Date.now(),
|
|
259
244
|
model: options.model,
|
|
260
245
|
skill: options.skill,
|
|
@@ -278,9 +263,7 @@ export class SubagentManager {
|
|
|
278
263
|
}
|
|
279
264
|
|
|
280
265
|
listAgents(): SubagentRecord[] {
|
|
281
|
-
return [...this.records.values()].sort(
|
|
282
|
-
(a, b) => b.startedAt - a.startedAt,
|
|
283
|
-
);
|
|
266
|
+
return [...this.records.values()].sort((a, b) => b.startedAt - a.startedAt);
|
|
284
267
|
}
|
|
285
268
|
|
|
286
269
|
abort(id: string, reason?: string): boolean {
|
|
@@ -291,8 +274,7 @@ export class SubagentManager {
|
|
|
291
274
|
this.markStopped(record, reason ?? "Aborted by caller.");
|
|
292
275
|
return true;
|
|
293
276
|
}
|
|
294
|
-
if (record.status !== "running" && record.status !== "blocked")
|
|
295
|
-
return false;
|
|
277
|
+
if (record.status !== "running" && record.status !== "blocked") return false;
|
|
296
278
|
this.controllers.get(id)?.abort();
|
|
297
279
|
this.markStopped(record, reason ?? "Aborted by caller.");
|
|
298
280
|
return true;
|
|
@@ -320,15 +302,9 @@ export class SubagentManager {
|
|
|
320
302
|
while (true) {
|
|
321
303
|
this.drainQueue();
|
|
322
304
|
const pending = this.listAgents()
|
|
323
|
-
.filter(
|
|
324
|
-
(record) =>
|
|
325
|
-
record.status === "running" ||
|
|
326
|
-
record.status === "queued",
|
|
327
|
-
)
|
|
305
|
+
.filter((record) => record.status === "running" || record.status === "queued")
|
|
328
306
|
.map((record) => record.promise)
|
|
329
|
-
.filter((promise): promise is Promise<void> =>
|
|
330
|
-
Boolean(promise),
|
|
331
|
-
);
|
|
307
|
+
.filter((promise): promise is Promise<void> => Boolean(promise));
|
|
332
308
|
if (!pending.length) break;
|
|
333
309
|
await Promise.allSettled(pending);
|
|
334
310
|
}
|
|
@@ -338,15 +314,10 @@ export class SubagentManager {
|
|
|
338
314
|
while (true) {
|
|
339
315
|
const record = this.records.get(id);
|
|
340
316
|
if (!record) return undefined;
|
|
341
|
-
if (record.status !== "running" && record.status !== "queued")
|
|
342
|
-
return record;
|
|
317
|
+
if (record.status !== "running" && record.status !== "queued") return record;
|
|
343
318
|
if (record.promise)
|
|
344
319
|
await record.promise.catch((error) => {
|
|
345
|
-
logInternalError(
|
|
346
|
-
"subagent-manager.waitForRecord",
|
|
347
|
-
error,
|
|
348
|
-
`id=${id}`,
|
|
349
|
-
);
|
|
320
|
+
logInternalError("subagent-manager.waitForRecord", error, `id=${id}`);
|
|
350
321
|
});
|
|
351
322
|
else await new Promise((resolve) => setTimeout(resolve, 100));
|
|
352
323
|
}
|
|
@@ -357,12 +328,7 @@ export class SubagentManager {
|
|
|
357
328
|
this.drainQueue();
|
|
358
329
|
}
|
|
359
330
|
|
|
360
|
-
private start(
|
|
361
|
-
record: SubagentRecord,
|
|
362
|
-
options: SubagentSpawnOptions,
|
|
363
|
-
runner: SpawnRunner,
|
|
364
|
-
signal?: AbortSignal,
|
|
365
|
-
): void {
|
|
331
|
+
private start(record: SubagentRecord, options: SubagentSpawnOptions, runner: SpawnRunner, signal?: AbortSignal): void {
|
|
366
332
|
if (options.background) this.runningBackground++;
|
|
367
333
|
record.status = "running";
|
|
368
334
|
record.startedAt = Date.now();
|
|
@@ -381,8 +347,7 @@ export class SubagentManager {
|
|
|
381
347
|
record.error = record.result;
|
|
382
348
|
throw new Error(record.error);
|
|
383
349
|
}
|
|
384
|
-
if (record.runId)
|
|
385
|
-
await this.pollRunToTerminal(options.cwd, record);
|
|
350
|
+
if (record.runId) await this.pollRunToTerminal(options.cwd, record);
|
|
386
351
|
else record.status = "completed";
|
|
387
352
|
} catch (error) {
|
|
388
353
|
if (record.status === "stopped" || runSignal.aborted) {
|
|
@@ -390,27 +355,16 @@ export class SubagentManager {
|
|
|
390
355
|
? "Signal aborted — agent cancelled by parent (session switch, user cancel, or tool timeout)."
|
|
391
356
|
: undefined;
|
|
392
357
|
record.status = "stopped";
|
|
393
|
-
if (!record.error)
|
|
394
|
-
record.error =
|
|
395
|
-
abortReason ??
|
|
396
|
-
(error instanceof Error
|
|
397
|
-
? error.message
|
|
398
|
-
: String(error));
|
|
358
|
+
if (!record.error) record.error = abortReason ?? (error instanceof Error ? error.message : String(error));
|
|
399
359
|
return;
|
|
400
360
|
}
|
|
401
361
|
record.status = "error";
|
|
402
|
-
record.error =
|
|
403
|
-
error instanceof Error ? error.message : String(error);
|
|
362
|
+
record.error = error instanceof Error ? error.message : String(error);
|
|
404
363
|
throw error; // H4: Propagate rejection so callers awaiting record.promise see the error
|
|
405
364
|
} finally {
|
|
406
365
|
this.cleanupRunSignal(record.id);
|
|
407
|
-
if (options.background)
|
|
408
|
-
|
|
409
|
-
0,
|
|
410
|
-
this.runningBackground - 1,
|
|
411
|
-
);
|
|
412
|
-
if (record.status !== "blocked")
|
|
413
|
-
record.completedAt = record.completedAt ?? Date.now();
|
|
366
|
+
if (options.background) this.runningBackground = Math.max(0, this.runningBackground - 1);
|
|
367
|
+
if (record.status !== "blocked") record.completedAt = record.completedAt ?? Date.now();
|
|
414
368
|
savePersistedSubagentRecord(options.cwd, record);
|
|
415
369
|
if (
|
|
416
370
|
record.status === "completed" ||
|
|
@@ -420,13 +374,15 @@ export class SubagentManager {
|
|
|
420
374
|
record.status === "stopped"
|
|
421
375
|
) {
|
|
422
376
|
// Phase 1.6: Populate telemetry fields
|
|
423
|
-
record.turnCount =
|
|
424
|
-
|
|
425
|
-
totalRunTurns(options.cwd, record.runId);
|
|
426
|
-
record.durationMs = record.completedAt
|
|
427
|
-
? Math.max(0, record.completedAt - record.startedAt)
|
|
428
|
-
: undefined;
|
|
377
|
+
record.turnCount = record.turnCount ?? totalRunTurns(options.cwd, record.runId);
|
|
378
|
+
record.durationMs = record.completedAt ? Math.max(0, record.completedAt - record.startedAt) : undefined;
|
|
429
379
|
savePersistedSubagentRecord(options.cwd, record);
|
|
380
|
+
// User policy (v0.9.16): cancelled / stopped subagents leave NO trace.
|
|
381
|
+
// Successful runs (`completed`) and agent errors (`failed`, `error`)
|
|
382
|
+
// keep their audit trail. See shouldDeleteOnTerminalStatus().
|
|
383
|
+
if (shouldDeleteOnTerminalStatus(record)) {
|
|
384
|
+
removePersistedSubagentRecord(options.cwd, record.id);
|
|
385
|
+
}
|
|
430
386
|
this.onComplete?.(record);
|
|
431
387
|
}
|
|
432
388
|
this.drainQueue();
|
|
@@ -441,20 +397,22 @@ export class SubagentManager {
|
|
|
441
397
|
// DO await (they still see the rejection) while preventing the
|
|
442
398
|
// harness-killing failure mode for callers that don't.
|
|
443
399
|
record.promise.catch((error) => {
|
|
444
|
-
logInternalError(
|
|
445
|
-
"subagent-manager.start.unhandled",
|
|
446
|
-
error,
|
|
447
|
-
`id=${record.id}`,
|
|
448
|
-
);
|
|
400
|
+
logInternalError("subagent-manager.start.unhandled", error, `id=${record.id}`);
|
|
449
401
|
});
|
|
450
402
|
}
|
|
451
403
|
|
|
452
404
|
private markStopped(record: SubagentRecord, reason?: string): void {
|
|
453
405
|
record.status = "stopped";
|
|
406
|
+
record.terminated = true;
|
|
454
407
|
record.completedAt = Date.now();
|
|
455
408
|
if (reason && !record.error) record.error = reason;
|
|
456
409
|
const cwd = this.cwdByRecord.get(record.id);
|
|
410
|
+
// User policy (v0.9.16): stopped subagents leave NO trace on disk.
|
|
411
|
+
// Save first (so any concurrent reader sees the final status), then
|
|
412
|
+
// unlink. The race window is microseconds and the file is gone before
|
|
413
|
+
// the next widget/dashboard tick.
|
|
457
414
|
if (cwd) savePersistedSubagentRecord(cwd, record);
|
|
415
|
+
if (cwd) removePersistedSubagentRecord(cwd, record.id);
|
|
458
416
|
}
|
|
459
417
|
|
|
460
418
|
private createRunSignal(id: string, signal?: AbortSignal): AbortSignal {
|
|
@@ -467,9 +425,7 @@ export class SubagentManager {
|
|
|
467
425
|
if (signal) {
|
|
468
426
|
const abort = (): void => controller.abort();
|
|
469
427
|
signal.addEventListener("abort", abort, { once: true });
|
|
470
|
-
this.controllerCleanup.set(id, () =>
|
|
471
|
-
signal.removeEventListener("abort", abort),
|
|
472
|
-
);
|
|
428
|
+
this.controllerCleanup.set(id, () => signal.removeEventListener("abort", abort));
|
|
473
429
|
}
|
|
474
430
|
return controller.signal;
|
|
475
431
|
}
|
|
@@ -481,48 +437,32 @@ export class SubagentManager {
|
|
|
481
437
|
}
|
|
482
438
|
|
|
483
439
|
private drainQueue(): void {
|
|
484
|
-
while (
|
|
485
|
-
this.queue.length > 0 &&
|
|
486
|
-
this.runningBackground < this.maxConcurrent
|
|
487
|
-
) {
|
|
440
|
+
while (this.queue.length > 0 && this.runningBackground < this.maxConcurrent) {
|
|
488
441
|
const next = this.queue.shift();
|
|
489
442
|
if (!next || next.record.status !== "queued") continue;
|
|
490
443
|
this.start(next.record, next.options, next.runner, next.signal);
|
|
491
444
|
}
|
|
492
445
|
}
|
|
493
446
|
|
|
494
|
-
private async pollRunToTerminal(
|
|
495
|
-
|
|
496
|
-
record: SubagentRecord,
|
|
497
|
-
): Promise<void> {
|
|
498
|
-
while (
|
|
499
|
-
record.runId &&
|
|
500
|
-
(record.status === "running" || record.status === "blocked")
|
|
501
|
-
) {
|
|
447
|
+
private async pollRunToTerminal(cwd: string, record: SubagentRecord): Promise<void> {
|
|
448
|
+
while (record.runId && (record.status === "running" || record.status === "blocked")) {
|
|
502
449
|
const loaded = loadRunManifestById(cwd, record.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
503
450
|
if (!loaded) {
|
|
504
|
-
await new Promise((resolve) =>
|
|
505
|
-
setTimeout(resolve, this.pollIntervalMs),
|
|
506
|
-
);
|
|
451
|
+
await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));
|
|
507
452
|
continue;
|
|
508
453
|
}
|
|
509
454
|
if (loaded.manifest.status === "completed") {
|
|
510
455
|
record.status = "completed";
|
|
511
456
|
record.error = undefined;
|
|
512
|
-
record.turnCount =
|
|
513
|
-
record.turnCount ?? totalRunTurns(cwd, record.runId);
|
|
457
|
+
record.turnCount = record.turnCount ?? totalRunTurns(cwd, record.runId);
|
|
514
458
|
record.completedAt = Date.now();
|
|
515
459
|
savePersistedSubagentRecord(cwd, record);
|
|
516
460
|
return;
|
|
517
461
|
}
|
|
518
|
-
if (
|
|
519
|
-
loaded.manifest.status === "failed" ||
|
|
520
|
-
loaded.manifest.status === "cancelled"
|
|
521
|
-
) {
|
|
462
|
+
if (loaded.manifest.status === "failed" || loaded.manifest.status === "cancelled") {
|
|
522
463
|
record.status = loaded.manifest.status;
|
|
523
464
|
record.error = loaded.manifest.summary;
|
|
524
|
-
record.turnCount =
|
|
525
|
-
record.turnCount ?? totalRunTurns(cwd, record.runId);
|
|
465
|
+
record.turnCount = record.turnCount ?? totalRunTurns(cwd, record.runId);
|
|
526
466
|
record.completedAt = Date.now();
|
|
527
467
|
savePersistedSubagentRecord(cwd, record);
|
|
528
468
|
return;
|
|
@@ -541,20 +481,14 @@ export class SubagentManager {
|
|
|
541
481
|
savePersistedSubagentRecord(cwd, record);
|
|
542
482
|
return;
|
|
543
483
|
}
|
|
544
|
-
await new Promise((resolve) =>
|
|
545
|
-
setTimeout(resolve, this.pollIntervalMs),
|
|
546
|
-
);
|
|
484
|
+
await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));
|
|
547
485
|
}
|
|
548
486
|
}
|
|
549
487
|
|
|
550
|
-
private scheduleBlockedTerminalPoll(
|
|
551
|
-
cwd: string,
|
|
552
|
-
record: SubagentRecord,
|
|
553
|
-
): void {
|
|
488
|
+
private scheduleBlockedTerminalPoll(cwd: string, record: SubagentRecord): void {
|
|
554
489
|
const poll = (): void => {
|
|
555
490
|
const current = this.records.get(record.id);
|
|
556
|
-
if (!current || current.status !== "blocked" || !current.runId)
|
|
557
|
-
return;
|
|
491
|
+
if (!current || current.status !== "blocked" || !current.runId) return;
|
|
558
492
|
const loaded = loadRunManifestById(cwd, current.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
559
493
|
if (
|
|
560
494
|
!loaded ||
|
|
@@ -568,25 +502,17 @@ export class SubagentManager {
|
|
|
568
502
|
return;
|
|
569
503
|
}
|
|
570
504
|
const persisted = readPersistedSubagentRecord(cwd, current.id);
|
|
571
|
-
current.resultConsumed =
|
|
572
|
-
current.resultConsumed || persisted?.resultConsumed;
|
|
505
|
+
current.resultConsumed = current.resultConsumed || persisted?.resultConsumed;
|
|
573
506
|
if (loaded.manifest.status === "completed") {
|
|
574
507
|
current.status = "completed";
|
|
575
508
|
current.error = undefined;
|
|
576
|
-
} else if (
|
|
577
|
-
loaded.manifest.status === "failed" ||
|
|
578
|
-
loaded.manifest.status === "cancelled"
|
|
579
|
-
) {
|
|
509
|
+
} else if (loaded.manifest.status === "failed" || loaded.manifest.status === "cancelled") {
|
|
580
510
|
current.status = loaded.manifest.status;
|
|
581
511
|
current.error = loaded.manifest.summary;
|
|
582
512
|
} else return;
|
|
583
513
|
current.completedAt = Date.now();
|
|
584
|
-
current.turnCount =
|
|
585
|
-
|
|
586
|
-
current.durationMs = Math.max(
|
|
587
|
-
0,
|
|
588
|
-
current.completedAt - current.startedAt,
|
|
589
|
-
);
|
|
514
|
+
current.turnCount = current.turnCount ?? totalRunTurns(cwd, current.runId);
|
|
515
|
+
current.durationMs = Math.max(0, current.completedAt - current.startedAt);
|
|
590
516
|
savePersistedSubagentRecord(cwd, current);
|
|
591
517
|
this.onComplete?.(current);
|
|
592
518
|
};
|
|
@@ -594,20 +520,11 @@ export class SubagentManager {
|
|
|
594
520
|
timer.unref();
|
|
595
521
|
}
|
|
596
522
|
|
|
597
|
-
private scheduleStuckBlockedNotify(
|
|
598
|
-
cwd: string,
|
|
599
|
-
record: SubagentRecord,
|
|
600
|
-
): void {
|
|
523
|
+
private scheduleStuckBlockedNotify(cwd: string, record: SubagentRecord): void {
|
|
601
524
|
const threshold = DEFAULT_SUBAGENT.stuckBlockedNotifyMs;
|
|
602
525
|
const fire = (): void => {
|
|
603
526
|
const current = this.records.get(record.id);
|
|
604
|
-
if (
|
|
605
|
-
!current ||
|
|
606
|
-
current.status !== "blocked" ||
|
|
607
|
-
!current.blockedAt ||
|
|
608
|
-
current.stuckNotified
|
|
609
|
-
)
|
|
610
|
-
return;
|
|
527
|
+
if (!current || current.status !== "blocked" || !current.blockedAt || current.stuckNotified) return;
|
|
611
528
|
current.stuckNotified = true;
|
|
612
529
|
this.onEvent?.("subagent.stuck-blocked", {
|
|
613
530
|
event: "subagent.stuck-blocked",
|
|
@@ -2,7 +2,10 @@ export interface SubprocessToolEvent {
|
|
|
2
2
|
toolName: string;
|
|
3
3
|
toolCallId: string;
|
|
4
4
|
args?: Record<string, unknown>;
|
|
5
|
-
result?: {
|
|
5
|
+
result?: {
|
|
6
|
+
content: Array<{ type: string; text?: string }>;
|
|
7
|
+
details?: unknown;
|
|
8
|
+
};
|
|
6
9
|
isError?: boolean;
|
|
7
10
|
}
|
|
8
11
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { TeamRunManifest } from "../state/types.ts";
|
|
2
1
|
import { appendEvent } from "../state/event-log.ts";
|
|
2
|
+
import type { TeamRunManifest } from "../state/types.ts";
|
|
3
3
|
import { logInternalError } from "../utils/internal-error.ts";
|
|
4
4
|
|
|
5
5
|
export interface SupervisorContactPayload {
|
|
@@ -50,10 +50,15 @@ export function parseSupervisorContactFromLine(line: string): Omit<SupervisorCon
|
|
|
50
50
|
if (record.type !== "supervisor_contact" && record.type !== "crew_supervisor_contact") return undefined;
|
|
51
51
|
return {
|
|
52
52
|
taskId: typeof record.taskId === "string" ? record.taskId : "",
|
|
53
|
-
reason:
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
reason:
|
|
54
|
+
typeof record.reason === "string" &&
|
|
55
|
+
["decision_needed", "clarification", "approval", "error_escalation", "custom"].includes(record.reason)
|
|
56
|
+
? (record.reason as SupervisorContactPayload["reason"])
|
|
57
|
+
: "custom",
|
|
56
58
|
message: typeof record.message === "string" ? record.message : String(record.message ?? ""),
|
|
57
|
-
data:
|
|
59
|
+
data:
|
|
60
|
+
record.data && typeof record.data === "object" && !Array.isArray(record.data)
|
|
61
|
+
? (record.data as Record<string, unknown>)
|
|
62
|
+
: undefined,
|
|
58
63
|
};
|
|
59
64
|
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import type { TeamTaskState } from "../state/types.ts";
|
|
2
|
-
import type { CrewAgentRecord, CrewRuntimeKind } from "./crew-agent-runtime.ts";
|
|
1
|
+
import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
|
|
3
2
|
import { recordFromTask } from "./crew-agent-records.ts";
|
|
4
|
-
import type {
|
|
3
|
+
import type { CrewAgentRecord, CrewRuntimeKind } from "./crew-agent-runtime.ts";
|
|
5
4
|
|
|
6
5
|
export function shouldMaterializeAgent(task: TeamTaskState): boolean {
|
|
7
6
|
return task.status !== "queued" && task.status !== "skipped";
|
|
8
7
|
}
|
|
9
8
|
|
|
10
|
-
export function recordsForMaterializedTasks(
|
|
9
|
+
export function recordsForMaterializedTasks(
|
|
10
|
+
manifest: TeamRunManifest,
|
|
11
|
+
tasks: TeamTaskState[],
|
|
12
|
+
runtime: CrewRuntimeKind,
|
|
13
|
+
): CrewAgentRecord[] {
|
|
11
14
|
return tasks.filter(shouldMaterializeAgent).map((task) => recordFromTask(manifest, task, runtime));
|
|
12
15
|
}
|
|
13
16
|
|
|
@@ -31,7 +34,18 @@ export function waitingReason(task: TeamTaskState, tasks: TeamTaskState[]): stri
|
|
|
31
34
|
export function formatTaskGraphLines(tasks: TeamTaskState[]): string[] {
|
|
32
35
|
if (tasks.length === 0) return ["- (none)"];
|
|
33
36
|
return tasks.map((task) => {
|
|
34
|
-
const icon =
|
|
37
|
+
const icon =
|
|
38
|
+
task.status === "completed"
|
|
39
|
+
? "✓"
|
|
40
|
+
: task.status === "running"
|
|
41
|
+
? "⠋"
|
|
42
|
+
: task.status === "failed"
|
|
43
|
+
? "✗"
|
|
44
|
+
: task.status === "cancelled" || task.status === "skipped"
|
|
45
|
+
? "■"
|
|
46
|
+
: task.status === "needs_attention"
|
|
47
|
+
? "⚠"
|
|
48
|
+
: "◦";
|
|
35
49
|
const wait = waitingReason(task, tasks);
|
|
36
50
|
return `- ${icon} ${task.id} [${task.status}] ${task.role}->${task.agent}${wait && wait !== "ready" ? ` (${wait})` : ""}`;
|
|
37
51
|
});
|