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
|
@@ -2,6 +2,13 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import type { AgentConfig } from "../agents/agent-config.ts";
|
|
4
4
|
import type { CrewLimitsConfig, CrewRuntimeConfig } from "../config/config.ts";
|
|
5
|
+
import { loadConfig } from "../config/config.ts";
|
|
6
|
+
import { errors } from "../errors.ts";
|
|
7
|
+
import { appendHookEvent, executeHook } from "../hooks/registry.ts";
|
|
8
|
+
import { writeArtifact } from "../state/artifact-store.ts";
|
|
9
|
+
import { appendEventAsync, appendEventBuffered, appendEventFireAndForget } from "../state/event-log.ts";
|
|
10
|
+
import { saveRunManifest } from "../state/state-store.ts";
|
|
11
|
+
import { createTaskClaim } from "../state/task-claims.ts";
|
|
5
12
|
import type {
|
|
6
13
|
ArtifactDescriptor,
|
|
7
14
|
OperationTerminalEvidence,
|
|
@@ -12,21 +19,25 @@ import type {
|
|
|
12
19
|
} from "../state/types.ts";
|
|
13
20
|
import { logInternalError } from "../utils/internal-error.ts";
|
|
14
21
|
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
15
|
-
import { errors } from "../errors.ts";
|
|
16
|
-
import { writeArtifact } from "../state/artifact-store.ts";
|
|
17
|
-
import { appendEventAsync, appendEventFireAndForget } from "../state/event-log.ts";
|
|
18
|
-
import { saveRunManifest } from "../state/state-store.ts";
|
|
19
|
-
import { createTaskClaim } from "../state/task-claims.ts";
|
|
20
|
-
import {
|
|
21
|
-
createWorkerHeartbeat,
|
|
22
|
-
touchWorkerHeartbeat,
|
|
23
|
-
} from "./worker-heartbeat.ts";
|
|
24
22
|
import type { WorkflowStep } from "../workflows/workflow-config.ts";
|
|
23
|
+
import { captureWorktreeDiff, captureWorktreeDiffStat, prepareTaskWorkspace } from "../worktree/worktree-manager.ts";
|
|
24
|
+
import { reserveControlChannel } from "./agent-control.ts";
|
|
25
|
+
import { appendTaskAttentionEvent } from "./attention-events.ts";
|
|
26
|
+
import { buildSyntheticTerminalEvidence, cancellationReasonFromSignal } from "./cancellation.ts";
|
|
27
|
+
import { type ChildPiLifecycleEvent, runChildPi } from "./child-pi.ts";
|
|
28
|
+
import { extractCommandTrace } from "./command-trace.ts";
|
|
29
|
+
import { evaluateCompletionMutationGuard } from "./completion-guard.ts";
|
|
25
30
|
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
appendCrewAgentEvent,
|
|
32
|
+
appendCrewAgentOutput,
|
|
33
|
+
emptyCrewAgentProgress,
|
|
34
|
+
recordFromTask,
|
|
35
|
+
upsertCrewAgent,
|
|
36
|
+
} from "./crew-agent-records.ts";
|
|
37
|
+
import type { CrewAgentProgress, CrewRuntimeKind } from "./crew-agent-runtime.ts";
|
|
38
|
+
import { crewHooks } from "./crew-hooks.ts";
|
|
39
|
+
import { bridgeEventFromJsonEvent, registerStreamBridge } from "./event-stream-bridge.ts";
|
|
40
|
+
import { createVerificationEvidence } from "./green-contract.ts";
|
|
30
41
|
import {
|
|
31
42
|
buildConfiguredModelRouting,
|
|
32
43
|
formatModelAttemptNote,
|
|
@@ -34,81 +45,31 @@ import {
|
|
|
34
45
|
type ModelAttemptSummary,
|
|
35
46
|
} from "./model-fallback.ts";
|
|
36
47
|
import { readEnabledModelsPatterns } from "./model-scope.ts";
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
parsePiJsonOutput,
|
|
41
|
-
type ParsedPiJsonOutput,
|
|
42
|
-
} from "./pi-json-output.ts";
|
|
43
|
-
import { runChildPi, type ChildPiLifecycleEvent } from "./child-pi.ts";
|
|
44
|
-
import { awaitRuntimeWarmup } from "./runtime-warmup.ts";
|
|
45
|
-
import { buildTaskPacket } from "./task-packet.ts";
|
|
46
|
-
import { executeHook, appendHookEvent } from "../hooks/registry.ts";
|
|
47
|
-
import { createVerificationEvidence } from "./green-contract.ts";
|
|
48
|
-
import { executeVerificationCommands, computeGreenLevelFromResults } from "./verification-gates.ts";
|
|
49
|
-
import { createStartupEvidence } from "./worker-startup.ts";
|
|
48
|
+
import { type OutputValidationResult, validateWorkerOutput } from "./output-validator.ts";
|
|
49
|
+
import { type ParsedPiJsonOutput, parsePiJsonOutput } from "./pi-json-output.ts";
|
|
50
|
+
import { type ProgressEventSummary, shouldAppendProgressEventUpdate } from "./progress-event-coalescer.ts";
|
|
50
51
|
import { permissionForRole } from "./role-permission.ts";
|
|
51
|
-
import {
|
|
52
|
+
import { awaitRuntimeWarmup } from "./runtime-warmup.ts";
|
|
53
|
+
import { parseSessionUsage } from "./session-usage.ts";
|
|
54
|
+
import { renderSkillInstructions } from "./skill-instructions.ts";
|
|
55
|
+
import { parseSupervisorContactFromLine, recordSupervisorContact } from "./supervisor-contact.ts";
|
|
52
56
|
import {
|
|
53
57
|
collectDependencyOutputContext,
|
|
54
58
|
renderDependencyOutputContext,
|
|
55
59
|
writeTaskInputsArtifact,
|
|
56
60
|
writeTaskSharedOutput,
|
|
57
61
|
} from "./task-output-context.ts";
|
|
58
|
-
import {
|
|
59
|
-
appendCrewAgentEvent,
|
|
60
|
-
appendCrewAgentOutput,
|
|
61
|
-
emptyCrewAgentProgress,
|
|
62
|
-
recordFromTask,
|
|
63
|
-
upsertCrewAgent,
|
|
64
|
-
} from "./crew-agent-records.ts";
|
|
65
|
-
import { reserveControlChannel } from "./agent-control.ts";
|
|
66
|
-
import { parseSessionUsage } from "./session-usage.ts";
|
|
67
|
-
import type {
|
|
68
|
-
CrewAgentProgress,
|
|
69
|
-
CrewRuntimeKind,
|
|
70
|
-
} from "./crew-agent-runtime.ts";
|
|
71
|
-
import {
|
|
72
|
-
shouldAppendProgressEventUpdate,
|
|
73
|
-
type ProgressEventSummary,
|
|
74
|
-
} from "./progress-event-coalescer.ts";
|
|
75
|
-
import {
|
|
76
|
-
coordinationBridgeInstructions,
|
|
77
|
-
renderTaskPrompt,
|
|
78
|
-
} from "./task-runner/prompt-builder.ts";
|
|
79
|
-
import { buildWorkerPromptPipeline } from "./task-runner/prompt-pipeline.ts";
|
|
62
|
+
import { buildTaskPacket } from "./task-packet.ts";
|
|
80
63
|
import { buildWorkerCapabilityInventory } from "./task-runner/capabilities.ts";
|
|
81
|
-
import {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
} from "./task-runner/
|
|
87
|
-
import {
|
|
88
|
-
import {
|
|
89
|
-
|
|
90
|
-
persistSingleTaskUpdate,
|
|
91
|
-
updateTask,
|
|
92
|
-
} from "./task-runner/state-helpers.ts";
|
|
93
|
-
import {
|
|
94
|
-
cleanResultText,
|
|
95
|
-
isFinalChildEvent,
|
|
96
|
-
} from "./task-runner/result-utils.ts";
|
|
97
|
-
import { evaluateCompletionMutationGuard } from "./completion-guard.ts";
|
|
98
|
-
import {
|
|
99
|
-
cancellationReasonFromSignal,
|
|
100
|
-
buildSyntheticTerminalEvidence,
|
|
101
|
-
} from "./cancellation.ts";
|
|
102
|
-
import { appendTaskAttentionEvent } from "./attention-events.ts";
|
|
103
|
-
import {
|
|
104
|
-
parseSupervisorContactFromLine,
|
|
105
|
-
recordSupervisorContact,
|
|
106
|
-
} from "./supervisor-contact.ts";
|
|
107
|
-
import {
|
|
108
|
-
registerStreamBridge,
|
|
109
|
-
bridgeEventFromJsonEvent,
|
|
110
|
-
} from "./event-stream-bridge.ts";
|
|
111
|
-
import { renderSkillInstructions } from "./skill-instructions.ts";
|
|
64
|
+
import { applyAgentProgressEvent, applyUsageToProgress, progressEventSummary, shouldFlushProgressEvent } from "./task-runner/progress.ts";
|
|
65
|
+
import { coordinationBridgeInstructions, renderTaskPrompt } from "./task-runner/prompt-builder.ts";
|
|
66
|
+
import { buildWorkerPromptPipeline } from "./task-runner/prompt-pipeline.ts";
|
|
67
|
+
import { cleanResultText, isFinalChildEvent } from "./task-runner/result-utils.ts";
|
|
68
|
+
import { checkpointTask, persistSingleTaskUpdate, updateTask } from "./task-runner/state-helpers.ts";
|
|
69
|
+
import { tailReadWithLineSnap } from "./task-runner/tail-read.ts";
|
|
70
|
+
import { computeGreenLevelFromResults, executeVerificationCommands } from "./verification-gates.ts";
|
|
71
|
+
import { createWorkerHeartbeat, touchWorkerHeartbeat } from "./worker-heartbeat.ts";
|
|
72
|
+
import { createStartupEvidence } from "./worker-startup.ts";
|
|
112
73
|
import {
|
|
113
74
|
DEFAULT_YIELD_CONFIG,
|
|
114
75
|
extractYieldResult,
|
|
@@ -117,10 +78,6 @@ import {
|
|
|
117
78
|
registerYieldTool,
|
|
118
79
|
type YieldResult,
|
|
119
80
|
} from "./yield-handler.ts";
|
|
120
|
-
import {
|
|
121
|
-
validateWorkerOutput,
|
|
122
|
-
type OutputValidationResult,
|
|
123
|
-
} from "./output-validator.ts";
|
|
124
81
|
|
|
125
82
|
// Register the submit_result tool handler so subprocess events can extract yield data.
|
|
126
83
|
registerYieldTool();
|
|
@@ -155,9 +112,7 @@ export interface TaskRunnerInput {
|
|
|
155
112
|
onJsonEvent?: (taskId: string, runId: string, event: unknown) => void;
|
|
156
113
|
}
|
|
157
114
|
|
|
158
|
-
export async function runTeamTask(
|
|
159
|
-
input: TaskRunnerInput,
|
|
160
|
-
): Promise<{ manifest: TeamRunManifest; tasks: TeamTaskState[] }> {
|
|
115
|
+
export async function runTeamTask(input: TaskRunnerInput): Promise<{ manifest: TeamRunManifest; tasks: TeamTaskState[] }> {
|
|
161
116
|
// Cold-start race fix: ensure the hot module graph is warm before touching
|
|
162
117
|
// any module. Under tsx, concurrent first-imports race module-record
|
|
163
118
|
// instantiation; awaiting the registration-time warmup eliminates the window.
|
|
@@ -183,15 +138,8 @@ export async function runTeamTask(
|
|
|
183
138
|
cwd: workspace.cwd,
|
|
184
139
|
worktreePath: worktree?.path,
|
|
185
140
|
});
|
|
186
|
-
const dependencyContext = collectDependencyOutputContext(
|
|
187
|
-
|
|
188
|
-
input.tasks,
|
|
189
|
-
input.task,
|
|
190
|
-
input.step,
|
|
191
|
-
);
|
|
192
|
-
const dependencyContextText =
|
|
193
|
-
input.dependencyContextText ??
|
|
194
|
-
renderDependencyOutputContext(dependencyContext);
|
|
141
|
+
const dependencyContext = collectDependencyOutputContext(manifest, input.tasks, input.task, input.step);
|
|
142
|
+
const dependencyContextText = input.dependencyContextText ?? renderDependencyOutputContext(dependencyContext);
|
|
195
143
|
let task: TeamTaskState = {
|
|
196
144
|
...input.task,
|
|
197
145
|
cwd: workspace.cwd,
|
|
@@ -206,16 +154,10 @@ export async function runTeamTask(
|
|
|
206
154
|
lifetimeUsage: { input: 0, output: 0, cacheWrite: 0 },
|
|
207
155
|
...(dependencyContextText ? { dependencyContextText } : {}),
|
|
208
156
|
// Reserve control channel before spawn so cancel/steer can target this task immediately
|
|
209
|
-
controlReservation: reserveControlChannel(
|
|
210
|
-
input.task.id,
|
|
211
|
-
manifest.runId,
|
|
212
|
-
),
|
|
157
|
+
controlReservation: reserveControlChannel(input.task.id, manifest.runId),
|
|
213
158
|
} as TeamTaskState;
|
|
214
159
|
let tasks = updateTask(input.tasks, task);
|
|
215
|
-
const runtimeKind =
|
|
216
|
-
input.taskRuntimeOverride ??
|
|
217
|
-
input.runtimeKind ??
|
|
218
|
-
(input.executeWorkers ? "child-process" : "scaffold");
|
|
160
|
+
const runtimeKind = input.taskRuntimeOverride ?? input.runtimeKind ?? (input.executeWorkers ? "child-process" : "scaffold");
|
|
219
161
|
// FIX: Check signal before persisting state — if cancelled, skip the write.
|
|
220
162
|
if (input.signal?.aborted) {
|
|
221
163
|
const cancelReason = cancellationReasonFromSignal(input.signal);
|
|
@@ -231,13 +173,7 @@ export async function runTeamTask(
|
|
|
231
173
|
};
|
|
232
174
|
}
|
|
233
175
|
tasks = persistSingleTaskUpdate(manifest, tasks, task, "started");
|
|
234
|
-
if (runtimeKind === "child-process")
|
|
235
|
-
({ task, tasks } = checkpointTask(
|
|
236
|
-
manifest,
|
|
237
|
-
tasks,
|
|
238
|
-
task,
|
|
239
|
-
"started",
|
|
240
|
-
));
|
|
176
|
+
if (runtimeKind === "child-process") ({ task, tasks } = checkpointTask(manifest, tasks, task, "started"));
|
|
241
177
|
upsertCrewAgent(manifest, recordFromTask(manifest, task, runtimeKind));
|
|
242
178
|
await appendEventAsync(manifest.eventsPath, {
|
|
243
179
|
type: "task.started",
|
|
@@ -271,7 +207,7 @@ export async function runTeamTask(
|
|
|
271
207
|
teamRole: { skills: input.teamRoleSkills },
|
|
272
208
|
step: input.step,
|
|
273
209
|
override: input.skillOverride,
|
|
274
|
-
runId: manifest.runId,
|
|
210
|
+
runId: manifest.runId,
|
|
275
211
|
})
|
|
276
212
|
: undefined;
|
|
277
213
|
const skillBlock = input.skillBlock ?? renderedSkills?.block;
|
|
@@ -289,7 +225,7 @@ export async function runTeamTask(
|
|
|
289
225
|
// follow it and execute a script outside cwd. Throws on escape.
|
|
290
226
|
resolveRealContainedPath(manifest.cwd, input.step.preStepScript);
|
|
291
227
|
try {
|
|
292
|
-
|
|
228
|
+
// LAZY: defer dynamic import of node:child_process to its call site.
|
|
293
229
|
const { execFileSync } = await import("node:child_process");
|
|
294
230
|
preStepOutput = execFileSync(input.step.preStepScript, scriptArgs, {
|
|
295
231
|
timeout: scriptTimeout,
|
|
@@ -307,7 +243,20 @@ export async function runTeamTask(
|
|
|
307
243
|
// pre-step output rather than aborting the task (advisory hooks).
|
|
308
244
|
if (input.step.preStepOptional) {
|
|
309
245
|
const warnMsg = `[preStepOptional] pre-step hook '${input.step.preStepScript}' failed (exit ${exitCode ?? "?"}) but preStepOptional=true; continuing without its output.`;
|
|
310
|
-
try {
|
|
246
|
+
try {
|
|
247
|
+
appendEventFireAndForget(manifest.eventsPath, {
|
|
248
|
+
type: "hook.pre_step_optional_failed",
|
|
249
|
+
runId: manifest.runId,
|
|
250
|
+
taskId: task.id,
|
|
251
|
+
message: warnMsg,
|
|
252
|
+
data: {
|
|
253
|
+
script: input.step.preStepScript,
|
|
254
|
+
exitCode: exitCode ?? null,
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
} catch {
|
|
258
|
+
/* best-effort event log */
|
|
259
|
+
}
|
|
311
260
|
preStepOutput = undefined;
|
|
312
261
|
} else {
|
|
313
262
|
throw errors.preStepFailed(input.step.preStepScript, exitCode, msg);
|
|
@@ -315,18 +264,15 @@ export async function runTeamTask(
|
|
|
315
264
|
}
|
|
316
265
|
}
|
|
317
266
|
|
|
318
|
-
const promptResult = await renderTaskPrompt(
|
|
319
|
-
manifest,
|
|
320
|
-
input.step,
|
|
321
|
-
task,
|
|
322
|
-
input.agent,
|
|
323
|
-
skillBlock,
|
|
324
|
-
);
|
|
267
|
+
const promptResult = await renderTaskPrompt(manifest, input.step, task, input.agent, skillBlock);
|
|
325
268
|
let prompt = promptResult.full;
|
|
326
269
|
|
|
327
270
|
// Inject deterministic pre-step output into prompt
|
|
328
271
|
if (preStepOutput) {
|
|
329
|
-
prompt +=
|
|
272
|
+
prompt +=
|
|
273
|
+
"\n\n---\n## Pre-Step Script Output\n\nThe following data was produced by a pre-step script. Use it as context for your task:\n\n<output>\n" +
|
|
274
|
+
preStepOutput +
|
|
275
|
+
"\n</output>\n";
|
|
330
276
|
}
|
|
331
277
|
const promptArtifact = writeArtifact(manifest.artifactsRoot, {
|
|
332
278
|
kind: "prompt",
|
|
@@ -342,7 +288,7 @@ export async function runTeamTask(
|
|
|
342
288
|
let error: string | undefined;
|
|
343
289
|
let modelAttempts: ModelAttemptSummary[] | undefined;
|
|
344
290
|
let parsedOutput: ParsedPiJsonOutput | undefined;
|
|
345
|
-
|
|
291
|
+
let rawFinalText: string | undefined;
|
|
346
292
|
let intermediateFindings: string | undefined;
|
|
347
293
|
let finalStdout = "";
|
|
348
294
|
let transcriptPath: string | undefined;
|
|
@@ -350,23 +296,14 @@ export async function runTeamTask(
|
|
|
350
296
|
const collectedJsonEvents: Record<string, unknown>[] = [];
|
|
351
297
|
|
|
352
298
|
let startupEvidence = createStartupEvidence({
|
|
353
|
-
command:
|
|
354
|
-
runtimeKind === "child-process"
|
|
355
|
-
? "pi"
|
|
356
|
-
: runtimeKind === "live-session"
|
|
357
|
-
? "live-session"
|
|
358
|
-
: "safe-scaffold",
|
|
299
|
+
command: runtimeKind === "child-process" ? "pi" : runtimeKind === "live-session" ? "live-session" : "safe-scaffold",
|
|
359
300
|
startedAt: new Date(task.startedAt ?? new Date().toISOString()),
|
|
360
301
|
finishedAt: new Date(),
|
|
361
302
|
promptSentAt: new Date(task.startedAt ?? new Date().toISOString()),
|
|
362
303
|
promptAccepted: true,
|
|
363
304
|
exitCode: 0,
|
|
364
305
|
});
|
|
365
|
-
const inputsArtifact = writeTaskInputsArtifact(
|
|
366
|
-
manifest,
|
|
367
|
-
task,
|
|
368
|
-
dependencyContext,
|
|
369
|
-
);
|
|
306
|
+
const inputsArtifact = writeTaskInputsArtifact(manifest, task, dependencyContext);
|
|
370
307
|
const skillArtifact = skillBlock
|
|
371
308
|
? writeArtifact(manifest.artifactsRoot, {
|
|
372
309
|
kind: "metadata",
|
|
@@ -400,8 +337,7 @@ export async function runTeamTask(
|
|
|
400
337
|
scopeModelsPatterns: await resolveTaskScopeModelsPatterns(task.cwd),
|
|
401
338
|
});
|
|
402
339
|
const candidates = modelRoutingPlan.candidates;
|
|
403
|
-
const attemptModels =
|
|
404
|
-
candidates.length > 0 ? candidates : [undefined];
|
|
340
|
+
const attemptModels = candidates.length > 0 ? candidates : [undefined];
|
|
405
341
|
const logs: string[] = [];
|
|
406
342
|
let finalStderr = "";
|
|
407
343
|
modelAttempts = [];
|
|
@@ -431,26 +367,14 @@ export async function runTeamTask(
|
|
|
431
367
|
// Now update in-memory heartbeat so it is always >= persisted state.
|
|
432
368
|
task = {
|
|
433
369
|
...task,
|
|
434
|
-
heartbeat: touchWorkerHeartbeat(
|
|
435
|
-
task.heartbeat ?? createWorkerHeartbeat(task.id),
|
|
436
|
-
),
|
|
370
|
+
heartbeat: touchWorkerHeartbeat(task.heartbeat ?? createWorkerHeartbeat(task.id)),
|
|
437
371
|
};
|
|
438
372
|
lastHeartbeatPersistedAt = now;
|
|
439
373
|
};
|
|
440
|
-
const persistChildProgress = (
|
|
441
|
-
event: unknown,
|
|
442
|
-
force = false,
|
|
443
|
-
): void => {
|
|
374
|
+
const persistChildProgress = (event: unknown, force = false): void => {
|
|
444
375
|
const now = Date.now();
|
|
445
|
-
if (
|
|
446
|
-
|
|
447
|
-
shouldFlushProgressEvent(event) ||
|
|
448
|
-
now - lastAgentRecordPersistedAt >= 500
|
|
449
|
-
) {
|
|
450
|
-
upsertCrewAgent(
|
|
451
|
-
manifest,
|
|
452
|
-
recordFromTask(manifest, task, "child-process"),
|
|
453
|
-
);
|
|
376
|
+
if (force || shouldFlushProgressEvent(event) || now - lastAgentRecordPersistedAt >= 500) {
|
|
377
|
+
upsertCrewAgent(manifest, recordFromTask(manifest, task, "child-process"));
|
|
454
378
|
lastAgentRecordPersistedAt = now;
|
|
455
379
|
}
|
|
456
380
|
const summary = progressEventSummary(task, event);
|
|
@@ -464,9 +388,11 @@ export async function runTeamTask(
|
|
|
464
388
|
});
|
|
465
389
|
if (decision.shouldAppend) {
|
|
466
390
|
// 2.2 caller migration: high-frequency task.progress goes through
|
|
467
|
-
// the buffered path; loss-on-kill is acceptable because progress
|
|
391
|
+
// the buffered path (M7 wire); loss-on-kill is acceptable because progress
|
|
468
392
|
// is informational and re-derivable from per-agent records.
|
|
469
|
-
|
|
393
|
+
// appendEventBuffered coalesces into a single lock acquire after bufferMs,
|
|
394
|
+
// reducing producer p95 from ~13µs (serial) to ~0µs (bench M7).
|
|
395
|
+
void appendEventBuffered(manifest.eventsPath, {
|
|
470
396
|
type: "task.progress",
|
|
471
397
|
runId: manifest.runId,
|
|
472
398
|
taskId: task.id,
|
|
@@ -482,7 +408,9 @@ export async function runTeamTask(
|
|
|
482
408
|
// Ensure transcripts/ subdirectory exists before child-pi appends
|
|
483
409
|
// to it. appendTranscript uses O_APPEND (no mkdir) for security,
|
|
484
410
|
// so the caller must create the directory.
|
|
485
|
-
fs.mkdirSync(path.join(manifest.artifactsRoot, "transcripts"), {
|
|
411
|
+
fs.mkdirSync(path.join(manifest.artifactsRoot, "transcripts"), {
|
|
412
|
+
recursive: true,
|
|
413
|
+
});
|
|
486
414
|
const model = attemptModels[i];
|
|
487
415
|
const attemptStartedAt = new Date();
|
|
488
416
|
const pendingAttempt: ModelAttemptSummary = {
|
|
@@ -494,11 +422,14 @@ export async function runTeamTask(
|
|
|
494
422
|
modelAttempts: [...modelAttempts, pendingAttempt],
|
|
495
423
|
};
|
|
496
424
|
tasks = updateTask(tasks, task);
|
|
497
|
-
crewHooks.emit({
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
425
|
+
crewHooks.emit({
|
|
426
|
+
type: "task_started",
|
|
427
|
+
timestamp: new Date().toISOString(),
|
|
428
|
+
runId: manifest.runId,
|
|
429
|
+
taskId: task.id,
|
|
430
|
+
data: { role: task.role, model: model ?? "default" },
|
|
431
|
+
});
|
|
432
|
+
upsertCrewAgent(manifest, recordFromTask(manifest, task, "child-process"));
|
|
502
433
|
const childResult = await runChildPi({
|
|
503
434
|
cwd: task.cwd,
|
|
504
435
|
task: prompt,
|
|
@@ -520,19 +451,20 @@ export async function runTeamTask(
|
|
|
520
451
|
artifactsRoot: manifest.artifactsRoot,
|
|
521
452
|
onSpawn: (pid) => {
|
|
522
453
|
try {
|
|
523
|
-
({ task, tasks } = checkpointTask(
|
|
524
|
-
manifest,
|
|
525
|
-
tasks,
|
|
526
|
-
task,
|
|
527
|
-
"child-spawned",
|
|
528
|
-
pid,
|
|
529
|
-
));
|
|
454
|
+
({ task, tasks } = checkpointTask(manifest, tasks, task, "child-spawned", pid));
|
|
530
455
|
if (task.pendingSteers?.length) {
|
|
531
456
|
const steeringDir = `${manifest.artifactsRoot}/steering`;
|
|
532
457
|
fs.mkdirSync(steeringDir, { recursive: true });
|
|
533
458
|
const steeringPath = `${steeringDir}/${task.id}.jsonl`;
|
|
534
459
|
for (const msg of task.pendingSteers) {
|
|
535
|
-
fs.appendFileSync(
|
|
460
|
+
fs.appendFileSync(
|
|
461
|
+
steeringPath,
|
|
462
|
+
JSON.stringify({
|
|
463
|
+
type: "steer",
|
|
464
|
+
message: msg,
|
|
465
|
+
ts: new Date().toISOString(),
|
|
466
|
+
}) + "\n",
|
|
467
|
+
);
|
|
536
468
|
}
|
|
537
469
|
task.pendingSteers = [];
|
|
538
470
|
tasks = persistSingleTaskUpdate(manifest, tasks, task);
|
|
@@ -548,7 +480,9 @@ export async function runTeamTask(
|
|
|
548
480
|
taskId: task.id,
|
|
549
481
|
message: `Worker lifecycle: ${event.type}${event.error ? ` error=${event.error}` : ""}${event.exitCode != null ? ` exit=${event.exitCode}` : ""}`,
|
|
550
482
|
data: { ...event },
|
|
551
|
-
}).catch((error) =>
|
|
483
|
+
}).catch((error) =>
|
|
484
|
+
logInternalError("task-runner.lifecycle-event", error, `taskId=${task.id}, type=${event.type}`),
|
|
485
|
+
);
|
|
552
486
|
},
|
|
553
487
|
onStdoutLine: (line) => {
|
|
554
488
|
appendCrewAgentOutput(manifest, task.id, line);
|
|
@@ -567,17 +501,11 @@ export async function runTeamTask(
|
|
|
567
501
|
// Errors are logged but processing continues so subsequent events still update state.
|
|
568
502
|
try {
|
|
569
503
|
appendCrewAgentEvent(manifest, task.id, event);
|
|
570
|
-
if (
|
|
571
|
-
event
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
collectedJsonEvents.push(
|
|
576
|
-
event as Record<string, unknown>,
|
|
577
|
-
);
|
|
578
|
-
if (collectedJsonEvents.length > 1000) {
|
|
579
|
-
collectedJsonEvents.splice(0, collectedJsonEvents.length - 1000);
|
|
580
|
-
}
|
|
504
|
+
if (event && typeof event === "object" && !Array.isArray(event))
|
|
505
|
+
collectedJsonEvents.push(event as Record<string, unknown>);
|
|
506
|
+
if (collectedJsonEvents.length > 1000) {
|
|
507
|
+
collectedJsonEvents.splice(0, collectedJsonEvents.length - 1000);
|
|
508
|
+
}
|
|
581
509
|
// Accumulate lifetime usage via message_end events (survives compaction)
|
|
582
510
|
if (event && typeof event === "object" && (event as Record<string, unknown>).type === "message_end") {
|
|
583
511
|
const msg = (event as Record<string, unknown>).message as Record<string, unknown> | undefined;
|
|
@@ -597,7 +525,8 @@ export async function runTeamTask(
|
|
|
597
525
|
// This supplements the event log so developers can see what the child Pi worker produced.
|
|
598
526
|
if (process.env.PI_CREW_BACKGROUND_MODE === "1" && event) {
|
|
599
527
|
const bgLogPath = `${manifest.stateRoot}/background.log`;
|
|
600
|
-
const eventLine =
|
|
528
|
+
const eventLine =
|
|
529
|
+
typeof event === "object" && !Array.isArray(event) ? JSON.stringify(event) : String(event);
|
|
601
530
|
fs.appendFileSync(bgLogPath, `${eventLine}\n`);
|
|
602
531
|
}
|
|
603
532
|
// Always keep in-memory agentProgress fresh (cheap) so the UI/events see
|
|
@@ -618,31 +547,15 @@ export async function runTeamTask(
|
|
|
618
547
|
lastTaskProgressPersistedAt = progressNow;
|
|
619
548
|
}
|
|
620
549
|
// Bridge event to UI event bus for near-instant updates
|
|
621
|
-
const bridgeEvent = bridgeEventFromJsonEvent(
|
|
622
|
-
manifest.runId,
|
|
623
|
-
task.id,
|
|
624
|
-
event,
|
|
625
|
-
);
|
|
550
|
+
const bridgeEvent = bridgeEventFromJsonEvent(manifest.runId, task.id, event);
|
|
626
551
|
if (bridgeEvent) streamBridge?.handler(bridgeEvent);
|
|
627
552
|
// Feed overflow recovery tracker
|
|
628
553
|
if (input.onJsonEvent) {
|
|
629
|
-
input.onJsonEvent(
|
|
630
|
-
task.id,
|
|
631
|
-
manifest.runId,
|
|
632
|
-
event,
|
|
633
|
-
);
|
|
554
|
+
input.onJsonEvent(task.id, manifest.runId, event);
|
|
634
555
|
}
|
|
635
|
-
if (
|
|
636
|
-
!finalCheckpointWritten &&
|
|
637
|
-
isFinalChildEvent(event)
|
|
638
|
-
) {
|
|
556
|
+
if (!finalCheckpointWritten && isFinalChildEvent(event)) {
|
|
639
557
|
finalCheckpointWritten = true;
|
|
640
|
-
({ task, tasks } = checkpointTask(
|
|
641
|
-
manifest,
|
|
642
|
-
tasks,
|
|
643
|
-
task,
|
|
644
|
-
"child-stdout-final",
|
|
645
|
-
));
|
|
558
|
+
({ task, tasks } = checkpointTask(manifest, tasks, task, "child-stdout-final"));
|
|
646
559
|
}
|
|
647
560
|
persistChildProgress(event);
|
|
648
561
|
} catch (err) {
|
|
@@ -652,8 +565,7 @@ export async function runTeamTask(
|
|
|
652
565
|
});
|
|
653
566
|
const evidenceStatus = childResult.exitStatus?.cancelled
|
|
654
567
|
? "cancelled"
|
|
655
|
-
: childResult.error ||
|
|
656
|
-
(childResult.exitCode && childResult.exitCode !== 0)
|
|
568
|
+
: childResult.error || (childResult.exitCode && childResult.exitCode !== 0)
|
|
657
569
|
? "failed"
|
|
658
570
|
: "completed";
|
|
659
571
|
terminalEvidence = [
|
|
@@ -665,14 +577,10 @@ export async function runTeamTask(
|
|
|
665
577
|
finishedAt: new Date().toISOString(),
|
|
666
578
|
...(input.signal?.aborted
|
|
667
579
|
? {
|
|
668
|
-
reason: cancellationReasonFromSignal(
|
|
669
|
-
input.signal,
|
|
670
|
-
),
|
|
580
|
+
reason: cancellationReasonFromSignal(input.signal),
|
|
671
581
|
}
|
|
672
582
|
: {}),
|
|
673
|
-
...(childResult.exitStatus
|
|
674
|
-
? { exitStatus: childResult.exitStatus }
|
|
675
|
-
: {}),
|
|
583
|
+
...(childResult.exitStatus ? { exitStatus: childResult.exitStatus } : {}),
|
|
676
584
|
},
|
|
677
585
|
];
|
|
678
586
|
if (evidenceStatus === "cancelled") {
|
|
@@ -682,13 +590,7 @@ export async function runTeamTask(
|
|
|
682
590
|
code: "caller_cancelled" as const,
|
|
683
591
|
message: "Worker cancelled.",
|
|
684
592
|
};
|
|
685
|
-
terminalEvidence.push(
|
|
686
|
-
buildSyntheticTerminalEvidence(
|
|
687
|
-
"tool",
|
|
688
|
-
cancelReason,
|
|
689
|
-
attemptStartedAt.toISOString(),
|
|
690
|
-
),
|
|
691
|
-
);
|
|
593
|
+
terminalEvidence.push(buildSyntheticTerminalEvidence("tool", cancelReason, attemptStartedAt.toISOString()));
|
|
692
594
|
await appendEventAsync(manifest.eventsPath, {
|
|
693
595
|
type: "worker.cancelled",
|
|
694
596
|
runId: manifest.runId,
|
|
@@ -702,8 +604,7 @@ export async function runTeamTask(
|
|
|
702
604
|
startedAt: attemptStartedAt,
|
|
703
605
|
finishedAt: new Date(),
|
|
704
606
|
promptSentAt: attemptStartedAt,
|
|
705
|
-
promptAccepted:
|
|
706
|
-
childResult.exitCode === 0 && !childResult.error,
|
|
607
|
+
promptAccepted: childResult.exitCode === 0 && !childResult.error,
|
|
707
608
|
stderr: childResult.stderr,
|
|
708
609
|
error: childResult.error,
|
|
709
610
|
exitCode: childResult.exitCode,
|
|
@@ -713,19 +614,14 @@ export async function runTeamTask(
|
|
|
713
614
|
finalStderr = childResult.stderr;
|
|
714
615
|
// Cap transcript read to MAX_TRANSCRIPT_BYTES to avoid OOM on huge transcripts.
|
|
715
616
|
const MAX_TRANSCRIPT_PARSE_BYTES = 5 * 1024 * 1024;
|
|
716
|
-
const transcriptText = tailReadWithLineSnap(
|
|
717
|
-
transcriptPath,
|
|
718
|
-
MAX_TRANSCRIPT_PARSE_BYTES,
|
|
719
|
-
childResult.stdout,
|
|
720
|
-
);
|
|
617
|
+
const transcriptText = tailReadWithLineSnap(transcriptPath, MAX_TRANSCRIPT_PARSE_BYTES, childResult.stdout);
|
|
721
618
|
parsedOutput = parsePiJsonOutput(transcriptText);
|
|
722
619
|
rawFinalText = childResult.rawFinalText;
|
|
723
620
|
intermediateFindings = childResult.intermediateFindings;
|
|
724
621
|
error =
|
|
725
622
|
childResult.error ||
|
|
726
623
|
(childResult.exitCode && childResult.exitCode !== 0
|
|
727
|
-
? childResult.stderr ||
|
|
728
|
-
`Child Pi exited with ${childResult.exitCode}`
|
|
624
|
+
? childResult.stderr || `Child Pi exited with ${childResult.exitCode}`
|
|
729
625
|
: undefined);
|
|
730
626
|
// E1/E7 (Round 15): when the child timed out, surface a structured
|
|
731
627
|
// CrewError (E007) so users get a code + actionable help hint instead
|
|
@@ -802,31 +698,21 @@ export async function runTeamTask(
|
|
|
802
698
|
if (error && modelAttempts.length > 1) {
|
|
803
699
|
// E2/E1 (Round 15): structured CrewError (E008). Build via the factory so
|
|
804
700
|
// the error carries a code + help hint; keep its .message as the task error.
|
|
805
|
-
error = errors.modelExhausted(
|
|
701
|
+
error = errors.modelExhausted(
|
|
702
|
+
modelAttempts.map((a) => a.model),
|
|
703
|
+
error,
|
|
704
|
+
).message;
|
|
806
705
|
}
|
|
807
706
|
// NEW-8 fix: register all attempt transcripts as artifacts, not just the used one.
|
|
808
707
|
// Earlier failed attempts' transcripts exist on disk but were invisible to the artifact system.
|
|
809
|
-
const successfulAttemptIndex = modelAttempts.findIndex(
|
|
810
|
-
|
|
811
|
-
)
|
|
812
|
-
const usedAttempt =
|
|
813
|
-
successfulAttemptIndex === -1
|
|
814
|
-
? Math.max(0, modelAttempts.length - 1)
|
|
815
|
-
: successfulAttemptIndex;
|
|
816
|
-
for (
|
|
817
|
-
let attemptIdx = 0;
|
|
818
|
-
attemptIdx < modelAttempts.length;
|
|
819
|
-
attemptIdx++
|
|
820
|
-
) {
|
|
708
|
+
const successfulAttemptIndex = modelAttempts.findIndex((attempt) => attempt.success);
|
|
709
|
+
const usedAttempt = successfulAttemptIndex === -1 ? Math.max(0, modelAttempts.length - 1) : successfulAttemptIndex;
|
|
710
|
+
for (let attemptIdx = 0; attemptIdx < modelAttempts.length; attemptIdx++) {
|
|
821
711
|
if (attemptIdx === usedAttempt) continue;
|
|
822
712
|
const tPath = `${manifest.artifactsRoot}/transcripts/${task.id}.attempt-${attemptIdx}.jsonl`;
|
|
823
713
|
if (!fs.existsSync(tPath)) continue;
|
|
824
714
|
const MAX_ATTEMPT_TRANSCRIPT = 5 * 1024 * 1024;
|
|
825
|
-
const tContent = tailReadWithLineSnap(
|
|
826
|
-
tPath,
|
|
827
|
-
MAX_ATTEMPT_TRANSCRIPT,
|
|
828
|
-
"",
|
|
829
|
-
);
|
|
715
|
+
const tContent = tailReadWithLineSnap(tPath, MAX_ATTEMPT_TRANSCRIPT, "");
|
|
830
716
|
if (tContent) {
|
|
831
717
|
writeArtifact(manifest.artifactsRoot, {
|
|
832
718
|
kind: "log",
|
|
@@ -862,9 +748,7 @@ export async function runTeamTask(
|
|
|
862
748
|
...logs,
|
|
863
749
|
`finalExitCode=${exitCode ?? "null"}`,
|
|
864
750
|
`jsonEvents=${parsedOutput?.jsonEvents ?? 0}`,
|
|
865
|
-
parsedOutput?.usage
|
|
866
|
-
? `usage=${JSON.stringify(parsedOutput.usage)}`
|
|
867
|
-
: "",
|
|
751
|
+
parsedOutput?.usage ? `usage=${JSON.stringify(parsedOutput.usage)}` : "",
|
|
868
752
|
"",
|
|
869
753
|
"STDOUT:",
|
|
870
754
|
finalStdout,
|
|
@@ -874,12 +758,8 @@ export async function runTeamTask(
|
|
|
874
758
|
].join("\n"),
|
|
875
759
|
producer: task.id,
|
|
876
760
|
});
|
|
877
|
-
const resolvedModel =
|
|
878
|
-
|
|
879
|
-
const fallbackReason =
|
|
880
|
-
usedAttempt > 0
|
|
881
|
-
? modelAttempts[usedAttempt - 1]?.error
|
|
882
|
-
: undefined;
|
|
761
|
+
const resolvedModel = modelAttempts[usedAttempt]?.model ?? candidates[0] ?? "default";
|
|
762
|
+
const fallbackReason = usedAttempt > 0 ? modelAttempts[usedAttempt - 1]?.error : undefined;
|
|
883
763
|
task = {
|
|
884
764
|
...task,
|
|
885
765
|
modelRouting: {
|
|
@@ -895,9 +775,7 @@ export async function runTeamTask(
|
|
|
895
775
|
// Safety net: transcriptPath may be undefined in edge cases (e.g., early exit before loop).
|
|
896
776
|
// In practice it is always set inside the for loop above.
|
|
897
777
|
const attemptFallback = `${manifest.artifactsRoot}/transcripts/${task.id}.attempt-${usedAttempt}.jsonl`;
|
|
898
|
-
const sessionUsage = parseSessionUsage(
|
|
899
|
-
transcriptPath ?? attemptFallback,
|
|
900
|
-
);
|
|
778
|
+
const sessionUsage = parseSessionUsage(transcriptPath ?? attemptFallback);
|
|
901
779
|
const effectiveUsage = parsedOutput?.usage ?? sessionUsage;
|
|
902
780
|
if (effectiveUsage) {
|
|
903
781
|
parsedOutput = {
|
|
@@ -907,25 +785,15 @@ export async function runTeamTask(
|
|
|
907
785
|
task = {
|
|
908
786
|
...task,
|
|
909
787
|
usage: effectiveUsage,
|
|
910
|
-
agentProgress: applyUsageToProgress(
|
|
911
|
-
task.agentProgress,
|
|
912
|
-
effectiveUsage,
|
|
913
|
-
),
|
|
788
|
+
agentProgress: applyUsageToProgress(task.agentProgress, effectiveUsage),
|
|
914
789
|
};
|
|
915
790
|
tasks = updateTask(tasks, task);
|
|
916
|
-
upsertCrewAgent(
|
|
917
|
-
manifest,
|
|
918
|
-
recordFromTask(manifest, task, "child-process"),
|
|
919
|
-
);
|
|
791
|
+
upsertCrewAgent(manifest, recordFromTask(manifest, task, "child-process"));
|
|
920
792
|
}
|
|
921
793
|
// M2 fix: use attempt-relative path; cap content at MAX_TRANSCRIPT_ARTIFACT_BYTES.
|
|
922
794
|
const MAX_TRANSCRIPT_ARTIFACT_BYTES = 5 * 1024 * 1024; // 5MB cap
|
|
923
795
|
const attemptTranscriptPath = `${manifest.artifactsRoot}/transcripts/${task.id}.attempt-${usedAttempt}.jsonl`;
|
|
924
|
-
const transcriptContent = tailReadWithLineSnap(
|
|
925
|
-
attemptTranscriptPath,
|
|
926
|
-
MAX_TRANSCRIPT_ARTIFACT_BYTES,
|
|
927
|
-
"",
|
|
928
|
-
);
|
|
796
|
+
const transcriptContent = tailReadWithLineSnap(attemptTranscriptPath, MAX_TRANSCRIPT_ARTIFACT_BYTES, "");
|
|
929
797
|
if (transcriptContent) {
|
|
930
798
|
transcriptArtifact = writeArtifact(manifest.artifactsRoot, {
|
|
931
799
|
kind: "log",
|
|
@@ -941,17 +809,10 @@ export async function runTeamTask(
|
|
|
941
809
|
...(transcriptArtifact ? { transcriptArtifact } : {}),
|
|
942
810
|
};
|
|
943
811
|
tasks = updateTask(tasks, task);
|
|
944
|
-
({ task, tasks } = checkpointTask(
|
|
945
|
-
manifest,
|
|
946
|
-
tasks,
|
|
947
|
-
task,
|
|
948
|
-
"artifact-written",
|
|
949
|
-
));
|
|
812
|
+
({ task, tasks } = checkpointTask(manifest, tasks, task, "artifact-written"));
|
|
950
813
|
} else if (runtimeKind === "live-session") {
|
|
951
814
|
// LAZY: live-executor is only needed for live-session runtime branches.
|
|
952
|
-
const { runLiveTask } = await import(
|
|
953
|
-
"./task-runner/live-executor.ts"
|
|
954
|
-
);
|
|
815
|
+
const { runLiveTask } = await import("./task-runner/live-executor.ts");
|
|
955
816
|
const live = await runLiveTask({
|
|
956
817
|
manifest,
|
|
957
818
|
tasks,
|
|
@@ -1016,14 +877,10 @@ export async function runTeamTask(
|
|
|
1016
877
|
// only applies to live-session workers where submit_result is injected by the
|
|
1017
878
|
// runtime. Skipping yield detection for child-process prevents every child
|
|
1018
879
|
// worker from incorrectly being marked needs_attention.
|
|
1019
|
-
const yieldEnabled =
|
|
1020
|
-
runtimeKind !== "child-process" &&
|
|
1021
|
-
(input.runtimeConfig?.yield?.enabled ?? DEFAULT_YIELD_CONFIG.enabled);
|
|
880
|
+
const yieldEnabled = runtimeKind !== "child-process" && (input.runtimeConfig?.yield?.enabled ?? DEFAULT_YIELD_CONFIG.enabled);
|
|
1022
881
|
if (yieldEnabled && collectedJsonEvents.length > 0) {
|
|
1023
882
|
if (hasYieldInOutput(collectedJsonEvents)) {
|
|
1024
|
-
const yieldEvent = collectedJsonEvents.find((e) =>
|
|
1025
|
-
isYieldEvent(e),
|
|
1026
|
-
);
|
|
883
|
+
const yieldEvent = collectedJsonEvents.find((e) => isYieldEvent(e));
|
|
1027
884
|
if (yieldEvent) {
|
|
1028
885
|
_yieldResult = extractYieldResult(yieldEvent);
|
|
1029
886
|
}
|
|
@@ -1033,8 +890,7 @@ export async function runTeamTask(
|
|
|
1033
890
|
type: "task.needs_attention",
|
|
1034
891
|
runId: manifest.runId,
|
|
1035
892
|
taskId: task.id,
|
|
1036
|
-
message:
|
|
1037
|
-
"Worker completed without calling submit_result tool.",
|
|
893
|
+
message: "Worker completed without calling submit_result tool.",
|
|
1038
894
|
data: {
|
|
1039
895
|
activityState: "needs_attention",
|
|
1040
896
|
reason: "no_yield",
|
|
@@ -1072,17 +928,13 @@ export async function runTeamTask(
|
|
|
1072
928
|
})
|
|
1073
929
|
: undefined;
|
|
1074
930
|
|
|
1075
|
-
const mutationGuardMode =
|
|
1076
|
-
input.runtimeConfig?.completionMutationGuard ?? "warn";
|
|
931
|
+
const mutationGuardMode = input.runtimeConfig?.completionMutationGuard ?? "warn";
|
|
1077
932
|
const mutationGuard =
|
|
1078
933
|
!error && mutationGuardMode !== "off"
|
|
1079
934
|
? evaluateCompletionMutationGuard({
|
|
1080
935
|
role: task.role,
|
|
1081
936
|
taskText: `${task.title}\n${input.step.task}`,
|
|
1082
|
-
transcriptPath:
|
|
1083
|
-
runtimeKind === "child-process"
|
|
1084
|
-
? transcriptPath
|
|
1085
|
-
: transcriptArtifact?.path,
|
|
937
|
+
transcriptPath: runtimeKind === "child-process" ? transcriptPath : transcriptArtifact?.path,
|
|
1086
938
|
stdout: finalStdout,
|
|
1087
939
|
})
|
|
1088
940
|
: undefined;
|
|
@@ -1090,8 +942,7 @@ export async function runTeamTask(
|
|
|
1090
942
|
appendTaskAttentionEvent({
|
|
1091
943
|
manifest,
|
|
1092
944
|
taskId: task.id,
|
|
1093
|
-
message:
|
|
1094
|
-
"Implementation-style task completed without an observed mutation tool call.",
|
|
945
|
+
message: "Implementation-style task completed without an observed mutation tool call.",
|
|
1095
946
|
data: {
|
|
1096
947
|
activityState: "needs_attention",
|
|
1097
948
|
reason: "completion_guard",
|
|
@@ -1112,14 +963,11 @@ export async function runTeamTask(
|
|
|
1112
963
|
},
|
|
1113
964
|
};
|
|
1114
965
|
if (mutationGuardMode === "fail") {
|
|
1115
|
-
error =
|
|
1116
|
-
"Completion mutation guard failed: implementation-style task completed without an observed mutation tool call.";
|
|
966
|
+
error = "Completion mutation guard failed: implementation-style task completed without an observed mutation tool call.";
|
|
1117
967
|
exitCode = exitCode === 0 ? 1 : exitCode;
|
|
1118
968
|
if (modelAttempts?.length) {
|
|
1119
969
|
modelAttempts = modelAttempts.map((attempt, index) =>
|
|
1120
|
-
index === modelAttempts!.length - 1
|
|
1121
|
-
? { ...attempt, success: false, exitCode, error }
|
|
1122
|
-
: attempt,
|
|
970
|
+
index === modelAttempts!.length - 1 ? { ...attempt, success: false, exitCode, error } : attempt,
|
|
1123
971
|
);
|
|
1124
972
|
}
|
|
1125
973
|
}
|
|
@@ -1142,8 +990,7 @@ export async function runTeamTask(
|
|
|
1142
990
|
data: {
|
|
1143
991
|
valid: false,
|
|
1144
992
|
formatMatch: outputValidation.formatMatch,
|
|
1145
|
-
structurePreserved:
|
|
1146
|
-
outputValidation.structurePreserved,
|
|
993
|
+
structurePreserved: outputValidation.structurePreserved,
|
|
1147
994
|
issues: outputValidation.issues,
|
|
1148
995
|
},
|
|
1149
996
|
});
|
|
@@ -1188,22 +1035,23 @@ export async function runTeamTask(
|
|
|
1188
1035
|
);
|
|
1189
1036
|
|
|
1190
1037
|
// Compute observed green level from results
|
|
1191
|
-
const observedGreenLevel = computeGreenLevelFromResults(
|
|
1192
|
-
commandResults,
|
|
1193
|
-
taskPacket.verification.requiredGreenLevel,
|
|
1194
|
-
);
|
|
1038
|
+
const observedGreenLevel = computeGreenLevelFromResults(commandResults, taskPacket.verification.requiredGreenLevel);
|
|
1195
1039
|
|
|
1196
1040
|
// Determine satisfaction based on green level
|
|
1197
1041
|
const requiredLevel = taskPacket.verification.requiredGreenLevel;
|
|
1198
1042
|
const satisfied =
|
|
1199
|
-
observedGreenLevel === "none"
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1043
|
+
observedGreenLevel === "none"
|
|
1044
|
+
? false
|
|
1045
|
+
: observedGreenLevel === "targeted"
|
|
1046
|
+
? requiredLevel === "targeted"
|
|
1047
|
+
: observedGreenLevel === "package"
|
|
1048
|
+
? ["targeted", "package"].includes(requiredLevel)
|
|
1049
|
+
: observedGreenLevel === "workspace"
|
|
1050
|
+
? ["targeted", "package", "workspace"].includes(requiredLevel)
|
|
1051
|
+
: observedGreenLevel === "merge_ready";
|
|
1204
1052
|
|
|
1205
|
-
const allPassed = commandResults.every(r => r.status === "passed");
|
|
1206
|
-
const failedCount = commandResults.filter(r => r.status === "failed").length;
|
|
1053
|
+
const allPassed = commandResults.every((r) => r.status === "passed");
|
|
1054
|
+
const failedCount = commandResults.filter((r) => r.status === "failed").length;
|
|
1207
1055
|
|
|
1208
1056
|
verificationEvidence = {
|
|
1209
1057
|
requiredGreenLevel: taskPacket.verification.requiredGreenLevel,
|
|
@@ -1242,14 +1090,9 @@ export async function runTeamTask(
|
|
|
1242
1090
|
verification: verificationEvidence,
|
|
1243
1091
|
resultArtifact,
|
|
1244
1092
|
claim: undefined,
|
|
1245
|
-
heartbeat: touchWorkerHeartbeat(
|
|
1246
|
-
task.heartbeat ?? createWorkerHeartbeat(task.id),
|
|
1247
|
-
{ alive: false },
|
|
1248
|
-
),
|
|
1093
|
+
heartbeat: touchWorkerHeartbeat(task.heartbeat ?? createWorkerHeartbeat(task.id), { alive: false }),
|
|
1249
1094
|
workerExitStatus: terminalEvidence.at(-1)?.exitStatus,
|
|
1250
|
-
terminalEvidence: terminalEvidence.length
|
|
1251
|
-
? [...(task.terminalEvidence ?? []), ...terminalEvidence]
|
|
1252
|
-
: task.terminalEvidence,
|
|
1095
|
+
terminalEvidence: terminalEvidence.length ? [...(task.terminalEvidence ?? []), ...terminalEvidence] : task.terminalEvidence,
|
|
1253
1096
|
...(logArtifact ? { logArtifact } : {}),
|
|
1254
1097
|
...(transcriptArtifact ? { transcriptArtifact } : {}),
|
|
1255
1098
|
};
|
|
@@ -1266,7 +1109,14 @@ export async function runTeamTask(
|
|
|
1266
1109
|
timestamp: task.finishedAt ?? new Date().toISOString(),
|
|
1267
1110
|
runId: manifest.runId,
|
|
1268
1111
|
taskId: task.id,
|
|
1269
|
-
data: {
|
|
1112
|
+
data: {
|
|
1113
|
+
status: task.status,
|
|
1114
|
+
role: task.role,
|
|
1115
|
+
error: task.error,
|
|
1116
|
+
exitCode: task.exitCode,
|
|
1117
|
+
usage: task.usage,
|
|
1118
|
+
commandTrace,
|
|
1119
|
+
},
|
|
1270
1120
|
});
|
|
1271
1121
|
|
|
1272
1122
|
const packetArtifact = writeArtifact(manifest.artifactsRoot, {
|
|
@@ -1281,11 +1131,7 @@ export async function runTeamTask(
|
|
|
1281
1131
|
content: `${JSON.stringify(task.verification, null, 2)}\n`,
|
|
1282
1132
|
producer: task.id,
|
|
1283
1133
|
});
|
|
1284
|
-
const sharedOutputArtifact = writeTaskSharedOutput(
|
|
1285
|
-
manifest,
|
|
1286
|
-
input.step,
|
|
1287
|
-
task,
|
|
1288
|
-
);
|
|
1134
|
+
const sharedOutputArtifact = writeTaskSharedOutput(manifest, input.step, task);
|
|
1289
1135
|
const startupArtifact = writeArtifact(manifest.artifactsRoot, {
|
|
1290
1136
|
kind: "metadata",
|
|
1291
1137
|
relativePath: `metadata/${task.id}.startup-evidence.json`,
|
|
@@ -1361,7 +1207,12 @@ export async function runTeamTask(
|
|
|
1361
1207
|
});
|
|
1362
1208
|
|
|
1363
1209
|
// Execute after_task_complete lifecycle hook (non-blocking)
|
|
1364
|
-
const afterTaskReport = await executeHook("after_task_complete", {
|
|
1210
|
+
const afterTaskReport = await executeHook("after_task_complete", {
|
|
1211
|
+
runId: manifest.runId,
|
|
1212
|
+
taskId: task.id,
|
|
1213
|
+
cwd: manifest.cwd,
|
|
1214
|
+
status: error ? "failed" : noYield ? "needs_attention" : "completed",
|
|
1215
|
+
});
|
|
1365
1216
|
appendHookEvent(manifest, afterTaskReport);
|
|
1366
1217
|
|
|
1367
1218
|
return { manifest, tasks };
|
|
@@ -1443,7 +1294,10 @@ export function detectRetryableModelFailureFromOutput(parsed: ParsedPiJsonOutput
|
|
|
1443
1294
|
if (!eventSource || eventSource.length === 0) return undefined;
|
|
1444
1295
|
for (const candidate of eventSource) {
|
|
1445
1296
|
if (!candidate || typeof candidate !== "object") continue;
|
|
1446
|
-
const event = candidate as {
|
|
1297
|
+
const event = candidate as {
|
|
1298
|
+
stopReason?: unknown;
|
|
1299
|
+
errorMessage?: unknown;
|
|
1300
|
+
};
|
|
1447
1301
|
if (event.stopReason !== "error") continue;
|
|
1448
1302
|
if (typeof event.errorMessage !== "string" || event.errorMessage.length === 0) continue;
|
|
1449
1303
|
if (!isRetryableModelFailure(event.errorMessage)) continue;
|