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
|
@@ -143,12 +143,18 @@ export function classifyProcessCrash(input: CrashClassificationInput): CrashClas
|
|
|
143
143
|
// 1. Timeout takes precedence: the response-timeout guard is the proximate
|
|
144
144
|
// cause of death even if cancellation was also requested.
|
|
145
145
|
if (input.timedOut) {
|
|
146
|
-
return {
|
|
146
|
+
return {
|
|
147
|
+
crashClass: "timeout",
|
|
148
|
+
reason: "process timed out (response timeout guard fired)",
|
|
149
|
+
};
|
|
147
150
|
}
|
|
148
151
|
|
|
149
152
|
// 2. Cooperative cancellation.
|
|
150
153
|
if (input.cancelled) {
|
|
151
|
-
return {
|
|
154
|
+
return {
|
|
155
|
+
crashClass: "cancelled",
|
|
156
|
+
reason: "process was cancelled (abort requested)",
|
|
157
|
+
};
|
|
152
158
|
}
|
|
153
159
|
|
|
154
160
|
// 3. Spawn error: the child never started or emitted a process error.
|
|
@@ -165,13 +171,19 @@ export function classifyProcessCrash(input: CrashClassificationInput): CrashClas
|
|
|
165
171
|
if (abnormalExit) {
|
|
166
172
|
const panic = detectNativePanic(input.stderrSnippet);
|
|
167
173
|
if (panic !== null) {
|
|
168
|
-
return {
|
|
174
|
+
return {
|
|
175
|
+
crashClass: "native_panic",
|
|
176
|
+
reason: `native panic detected: ${panic}`,
|
|
177
|
+
};
|
|
169
178
|
}
|
|
170
179
|
}
|
|
171
180
|
|
|
172
181
|
// 5. Signal exit.
|
|
173
182
|
if (signal !== null) {
|
|
174
|
-
return {
|
|
183
|
+
return {
|
|
184
|
+
crashClass: "signal_exit",
|
|
185
|
+
reason: `process exited after signal ${signal}`,
|
|
186
|
+
};
|
|
175
187
|
}
|
|
176
188
|
|
|
177
189
|
// 6. Clean exit.
|
|
@@ -181,7 +193,10 @@ export function classifyProcessCrash(input: CrashClassificationInput): CrashClas
|
|
|
181
193
|
|
|
182
194
|
// 7. Non-zero exit.
|
|
183
195
|
if (exitCode !== null) {
|
|
184
|
-
return {
|
|
196
|
+
return {
|
|
197
|
+
crashClass: "non_zero_exit",
|
|
198
|
+
reason: `process exited with code ${exitCode}`,
|
|
199
|
+
};
|
|
185
200
|
}
|
|
186
201
|
|
|
187
202
|
// 8. Protocol exit: exitCode is null with no signal — the process stream
|
|
@@ -189,11 +204,17 @@ export function classifyProcessCrash(input: CrashClassificationInput): CrashClas
|
|
|
189
204
|
// If `killed` is true but no signal was recorded, treat as protocol_exit
|
|
190
205
|
// (the kill may not have delivered a signal we could capture).
|
|
191
206
|
if (input.killed) {
|
|
192
|
-
return {
|
|
207
|
+
return {
|
|
208
|
+
crashClass: "protocol_exit",
|
|
209
|
+
reason: "process was killed but no signal/exit code was captured",
|
|
210
|
+
};
|
|
193
211
|
}
|
|
194
212
|
|
|
195
213
|
// 8b. Truly null exitCode with no other context — protocol/stream ended early.
|
|
196
|
-
return {
|
|
214
|
+
return {
|
|
215
|
+
crashClass: "protocol_exit",
|
|
216
|
+
reason: "process exited before protocol completion (exit code unknown)",
|
|
217
|
+
};
|
|
197
218
|
}
|
|
198
219
|
|
|
199
220
|
/** Render an unknown error value to a short message string. */
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
1
|
import * as fs from "node:fs";
|
|
3
2
|
import * as path from "node:path";
|
|
3
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import { appendHookEvent, executeHook } from "../hooks/registry.ts";
|
|
4
5
|
import type { MetricRegistry } from "../observability/metric-registry.ts";
|
|
6
|
+
import { readActiveRunRegistry, unregisterActiveRun } from "../state/active-run-registry.ts";
|
|
5
7
|
import { appendEvent, scanSequence } from "../state/event-log.ts";
|
|
6
|
-
import { recordFromTask, upsertCrewAgent } from "./crew-agent-records.ts";
|
|
7
8
|
import { withRunLockSync } from "../state/locks.ts";
|
|
8
9
|
import { loadRunManifestById, saveRunTasks, updateRunStatus } from "../state/state-store.ts";
|
|
9
10
|
import type { TeamTaskState } from "../state/types.ts";
|
|
10
|
-
import {
|
|
11
|
-
import type { ManifestCache } from "./manifest-cache.ts";
|
|
12
|
-
import { checkProcessLiveness } from "./process-status.ts";
|
|
13
|
-
import { isPlanApprovalPending, reconcileStaleRun, type ReconcileResult } from "./stale-reconciler.ts";
|
|
14
|
-
import { executeHook, appendHookEvent } from "../hooks/registry.ts";
|
|
15
|
-
import { unregisterActiveRun, readActiveRunRegistry } from "../state/active-run-registry.ts";
|
|
16
|
-
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
11
|
+
import { logInternalError } from "../utils/internal-error.ts";
|
|
17
12
|
import { projectCrewRoot, userCrewRoot } from "../utils/paths.ts";
|
|
13
|
+
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
14
|
+
import { recordFromTask, upsertCrewAgent } from "./crew-agent-records.ts";
|
|
18
15
|
import { terminateLiveAgentsForRun } from "./live-agent-manager.ts";
|
|
19
|
-
import {
|
|
16
|
+
import type { ManifestCache } from "./manifest-cache.ts";
|
|
17
|
+
import { checkProcessLiveness } from "./process-status.ts";
|
|
18
|
+
import { isPlanApprovalPending, type ReconcileResult, reconcileStaleRun } from "./stale-reconciler.ts";
|
|
19
|
+
import { isWorkerHeartbeatStale } from "./worker-heartbeat.ts";
|
|
20
20
|
|
|
21
21
|
export interface RecoveryPlan {
|
|
22
22
|
runId: string;
|
|
@@ -26,7 +26,13 @@ export interface RecoveryPlan {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function isTerminalTask(task: TeamTaskState): boolean {
|
|
29
|
-
return
|
|
29
|
+
return (
|
|
30
|
+
task.status === "completed" ||
|
|
31
|
+
task.status === "failed" ||
|
|
32
|
+
task.status === "cancelled" ||
|
|
33
|
+
task.status === "skipped" ||
|
|
34
|
+
task.status === "needs_attention"
|
|
35
|
+
);
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
function shouldRecoverTask(task: TeamTaskState, deadMs: number): boolean {
|
|
@@ -47,7 +53,12 @@ export function detectInterruptedRuns(cwd: string, manifestCache: ManifestCache,
|
|
|
47
53
|
if (!loaded) continue;
|
|
48
54
|
const resumableTasks = loaded.tasks.filter((task) => shouldRecoverTask(task, deadMs)).map((task) => task.id);
|
|
49
55
|
if (!resumableTasks.length) continue;
|
|
50
|
-
plans.push({
|
|
56
|
+
plans.push({
|
|
57
|
+
runId: manifest.runId,
|
|
58
|
+
resumableTasks,
|
|
59
|
+
preservedTasks: loaded.tasks.filter(isTerminalTask).map((task) => task.id),
|
|
60
|
+
lastEventSeq: scanSequence(loaded.manifest.eventsPath),
|
|
61
|
+
});
|
|
51
62
|
}
|
|
52
63
|
return plans;
|
|
53
64
|
}
|
|
@@ -56,17 +67,44 @@ export async function applyRecoveryPlan(plan: RecoveryPlan, ctx: Pick<ExtensionC
|
|
|
56
67
|
const loaded = loadRunManifestById(ctx.cwd, plan.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
57
68
|
if (!loaded) throw new Error(`Run '${plan.runId}' not found.`);
|
|
58
69
|
|
|
59
|
-
const hookReport = await executeHook("run_recovery", {
|
|
70
|
+
const hookReport = await executeHook("run_recovery", {
|
|
71
|
+
runId: plan.runId,
|
|
72
|
+
cwd: ctx.cwd,
|
|
73
|
+
});
|
|
60
74
|
appendHookEvent(loaded.manifest, hookReport);
|
|
61
75
|
if (hookReport.outcome === "block") {
|
|
62
|
-
appendEvent(loaded.manifest.eventsPath, {
|
|
76
|
+
appendEvent(loaded.manifest.eventsPath, {
|
|
77
|
+
type: "crew.run.recovery_blocked",
|
|
78
|
+
runId: plan.runId,
|
|
79
|
+
message: `Recovery blocked by hook: ${hookReport.reason ?? "run_recovery hook blocked the operation."}`,
|
|
80
|
+
data: { hookOutcome: "block", reason: hookReport.reason },
|
|
81
|
+
});
|
|
63
82
|
return;
|
|
64
83
|
}
|
|
65
84
|
|
|
66
85
|
const reset = new Set(plan.resumableTasks);
|
|
67
|
-
const tasks = loaded.tasks.map((task) =>
|
|
86
|
+
const tasks = loaded.tasks.map((task) =>
|
|
87
|
+
reset.has(task.id)
|
|
88
|
+
? {
|
|
89
|
+
...task,
|
|
90
|
+
status: "queued" as const,
|
|
91
|
+
startedAt: undefined,
|
|
92
|
+
finishedAt: undefined,
|
|
93
|
+
error: undefined,
|
|
94
|
+
heartbeat: undefined,
|
|
95
|
+
}
|
|
96
|
+
: task,
|
|
97
|
+
);
|
|
68
98
|
saveRunTasks(loaded.manifest, tasks);
|
|
69
|
-
appendEvent(loaded.manifest.eventsPath, {
|
|
99
|
+
appendEvent(loaded.manifest.eventsPath, {
|
|
100
|
+
type: "crew.run.resumed",
|
|
101
|
+
runId: plan.runId,
|
|
102
|
+
message: `Recovered ${plan.resumableTasks.length} interrupted task(s).`,
|
|
103
|
+
data: {
|
|
104
|
+
recoveredFromSeq: plan.lastEventSeq,
|
|
105
|
+
resumableTasks: plan.resumableTasks,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
70
108
|
registry?.counter("crew.run.count", "Total runs by status").inc({ status: "resumed" });
|
|
71
109
|
}
|
|
72
110
|
|
|
@@ -74,7 +112,12 @@ export function declineRecoveryPlan(plan: RecoveryPlan, ctx: Pick<ExtensionConte
|
|
|
74
112
|
const loaded = loadRunManifestById(ctx.cwd, plan.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
75
113
|
if (!loaded) throw new Error(`Run '${plan.runId}' not found.`);
|
|
76
114
|
// Log the event first — if appendEvent fails, state remains consistent.
|
|
77
|
-
appendEvent(loaded.manifest.eventsPath, {
|
|
115
|
+
appendEvent(loaded.manifest.eventsPath, {
|
|
116
|
+
type: "crew.run.recovery_declined",
|
|
117
|
+
runId: plan.runId,
|
|
118
|
+
message: "Interrupted run was not resumed.",
|
|
119
|
+
data: { recoveredFromSeq: plan.lastEventSeq },
|
|
120
|
+
});
|
|
78
121
|
updateRunStatus(loaded.manifest, "cancelled", "interrupted-not-resumed");
|
|
79
122
|
}
|
|
80
123
|
|
|
@@ -156,26 +199,53 @@ export function cancelOrphanedRuns(
|
|
|
156
199
|
if (!fresh) return;
|
|
157
200
|
if (fresh.manifest.status !== "running" && fresh.manifest.status !== "blocked") {
|
|
158
201
|
// Status changed between initial check (line 109) and acquiring the lock — normal concurrent update, not an orphan
|
|
159
|
-
appendEvent(loaded.manifest.eventsPath, {
|
|
202
|
+
appendEvent(loaded.manifest.eventsPath, {
|
|
203
|
+
type: "crew.run.orphan_skip",
|
|
204
|
+
runId: manifest.runId,
|
|
205
|
+
message: `Skipped orphan cancellation: status is '${fresh.manifest.status}' (was 'running'/'blocked' at initial scan)`,
|
|
206
|
+
data: { currentStatus: fresh.manifest.status },
|
|
207
|
+
});
|
|
160
208
|
return;
|
|
161
209
|
}
|
|
162
210
|
|
|
163
211
|
const now_iso = new Date(now).toISOString();
|
|
164
212
|
const repairedTasks = fresh.tasks.map((task) => {
|
|
165
213
|
if (task.status === "running" || task.status === "queued" || task.status === "waiting") {
|
|
166
|
-
return {
|
|
214
|
+
return {
|
|
215
|
+
...task,
|
|
216
|
+
status: "cancelled" as const,
|
|
217
|
+
finishedAt: now_iso,
|
|
218
|
+
error: `Orphaned run: owner session ${ownerId} no longer exists`,
|
|
219
|
+
};
|
|
167
220
|
}
|
|
168
221
|
return task;
|
|
169
222
|
});
|
|
170
223
|
|
|
171
224
|
saveRunTasks(fresh.manifest, repairedTasks);
|
|
172
|
-
for (const task of repairedTasks) {
|
|
225
|
+
for (const task of repairedTasks) {
|
|
226
|
+
try {
|
|
227
|
+
upsertCrewAgent(fresh.manifest, recordFromTask(fresh.manifest, task, "scaffold"));
|
|
228
|
+
} catch {
|
|
229
|
+
/* non-critical */
|
|
230
|
+
}
|
|
231
|
+
}
|
|
173
232
|
updateRunStatus(fresh.manifest, "cancelled", `Orphaned run: owner session ${ownerId} no longer exists`);
|
|
174
|
-
appendEvent(fresh.manifest.eventsPath, {
|
|
233
|
+
appendEvent(fresh.manifest.eventsPath, {
|
|
234
|
+
type: "crew.run.orphan_cancelled",
|
|
235
|
+
runId: manifest.runId,
|
|
236
|
+
message: `Auto-cancelled orphaned run (owner: ${ownerId})`,
|
|
237
|
+
data: {
|
|
238
|
+
ownerSessionId: ownerId,
|
|
239
|
+
cancelledTasks: repairedTasks.filter((t) => t.status === "cancelled").length,
|
|
240
|
+
},
|
|
241
|
+
});
|
|
175
242
|
cancelled.push(manifest.runId);
|
|
176
243
|
cancelledRun = true;
|
|
177
244
|
});
|
|
178
|
-
if (cancelledRun)
|
|
245
|
+
if (cancelledRun)
|
|
246
|
+
void terminateLiveAgentsForRun(manifest.runId, "cancelled", appendEvent, loaded.manifest.eventsPath).catch((error) =>
|
|
247
|
+
logInternalError("crash-recovery.orphan.terminate", error, `runId=${manifest.runId}`),
|
|
248
|
+
);
|
|
179
249
|
}
|
|
180
250
|
|
|
181
251
|
return { cancelled, skipped };
|
|
@@ -245,7 +315,12 @@ function heartbeatAgeMs(entry: { stateRoot: string }, now: number): number {
|
|
|
245
315
|
* gone, hanging the workflow permanently at the current task with no
|
|
246
316
|
* recoverable state ("Run not found").
|
|
247
317
|
*/
|
|
248
|
-
function hasRecentLifeEvidence(
|
|
318
|
+
function hasRecentLifeEvidence(
|
|
319
|
+
entry: { stateRoot: string },
|
|
320
|
+
manifestUpdatedAt: string | undefined,
|
|
321
|
+
now: number,
|
|
322
|
+
staleThresholdMs: number,
|
|
323
|
+
): boolean {
|
|
249
324
|
const manifestMs = manifestUpdatedAt ? new Date(manifestUpdatedAt).getTime() : NaN;
|
|
250
325
|
if (Number.isFinite(manifestMs) && now - manifestMs <= staleThresholdMs) return true;
|
|
251
326
|
const hbAge = heartbeatAgeMs(entry, now);
|
|
@@ -282,7 +357,14 @@ export function purgeStaleActiveRunIndex(staleThresholdMs = 300_000, now = Date.
|
|
|
282
357
|
}
|
|
283
358
|
|
|
284
359
|
// 3. Read manifest status
|
|
285
|
-
let manifest:
|
|
360
|
+
let manifest:
|
|
361
|
+
| {
|
|
362
|
+
status?: string;
|
|
363
|
+
updatedAt?: string;
|
|
364
|
+
async?: { pid?: number };
|
|
365
|
+
ownerSessionId?: string;
|
|
366
|
+
}
|
|
367
|
+
| undefined;
|
|
286
368
|
try {
|
|
287
369
|
manifest = JSON.parse(fs.readFileSync(entry.manifestPath, "utf-8"));
|
|
288
370
|
} catch {
|
|
@@ -322,14 +404,32 @@ export function purgeStaleActiveRunIndex(staleThresholdMs = 300_000, now = Date.
|
|
|
322
404
|
const now_iso = new Date(now).toISOString();
|
|
323
405
|
const repairedTasks = fullLoaded.tasks.map((task) => {
|
|
324
406
|
if (task.status === "running" || task.status === "queued" || task.status === "waiting") {
|
|
325
|
-
return {
|
|
407
|
+
return {
|
|
408
|
+
...task,
|
|
409
|
+
status: "cancelled" as const,
|
|
410
|
+
finishedAt: now_iso,
|
|
411
|
+
error: "Orphaned run: worker process dead and no recent activity",
|
|
412
|
+
};
|
|
326
413
|
}
|
|
327
414
|
return task;
|
|
328
415
|
});
|
|
329
416
|
saveRunTasks(fullLoaded.manifest, repairedTasks);
|
|
330
|
-
for (const task of repairedTasks) {
|
|
417
|
+
for (const task of repairedTasks) {
|
|
418
|
+
try {
|
|
419
|
+
upsertCrewAgent(fullLoaded.manifest, recordFromTask(fullLoaded.manifest, task, "scaffold"));
|
|
420
|
+
} catch {
|
|
421
|
+
/* non-critical */
|
|
422
|
+
}
|
|
423
|
+
}
|
|
331
424
|
updateRunStatus(fullLoaded.manifest, "cancelled", "Orphaned run: worker process dead and no recent activity");
|
|
332
|
-
void terminateLiveAgentsForRun(
|
|
425
|
+
void terminateLiveAgentsForRun(
|
|
426
|
+
fullLoaded.manifest.runId,
|
|
427
|
+
"cancelled",
|
|
428
|
+
appendEvent,
|
|
429
|
+
fullLoaded.manifest.eventsPath,
|
|
430
|
+
).catch((error) =>
|
|
431
|
+
logInternalError("crash-recovery.pid-dead.terminate", error, `runId=${fullLoaded.manifest.runId}`),
|
|
432
|
+
);
|
|
333
433
|
}
|
|
334
434
|
} catch {
|
|
335
435
|
// Best-effort manifest cleanup
|
|
@@ -352,14 +452,38 @@ export function purgeStaleActiveRunIndex(staleThresholdMs = 300_000, now = Date.
|
|
|
352
452
|
const now_iso = new Date(now).toISOString();
|
|
353
453
|
const repairedTasks = fullLoaded.tasks.map((task) => {
|
|
354
454
|
if (task.status === "running" || task.status === "queued" || task.status === "waiting") {
|
|
355
|
-
return {
|
|
455
|
+
return {
|
|
456
|
+
...task,
|
|
457
|
+
status: "cancelled" as const,
|
|
458
|
+
finishedAt: now_iso,
|
|
459
|
+
error: "Orphaned run: workflow completed but manifest never updated to terminal status",
|
|
460
|
+
};
|
|
356
461
|
}
|
|
357
462
|
return task;
|
|
358
463
|
});
|
|
359
464
|
saveRunTasks(fullLoaded.manifest, repairedTasks);
|
|
360
|
-
for (const task of repairedTasks) {
|
|
361
|
-
|
|
362
|
-
|
|
465
|
+
for (const task of repairedTasks) {
|
|
466
|
+
try {
|
|
467
|
+
upsertCrewAgent(fullLoaded.manifest, recordFromTask(fullLoaded.manifest, task, "scaffold"));
|
|
468
|
+
} catch {
|
|
469
|
+
/* non-critical */
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
updateRunStatus(
|
|
473
|
+
fullLoaded.manifest,
|
|
474
|
+
"cancelled",
|
|
475
|
+
"Orphaned run: no async worker and no manifest update in over " +
|
|
476
|
+
Math.round(staleThresholdMs / 60000) +
|
|
477
|
+
" minutes",
|
|
478
|
+
);
|
|
479
|
+
void terminateLiveAgentsForRun(
|
|
480
|
+
fullLoaded.manifest.runId,
|
|
481
|
+
"cancelled",
|
|
482
|
+
appendEvent,
|
|
483
|
+
fullLoaded.manifest.eventsPath,
|
|
484
|
+
).catch((error) =>
|
|
485
|
+
logInternalError("crash-recovery.pid-dead.terminate", error, `runId=${fullLoaded.manifest.runId}`),
|
|
486
|
+
);
|
|
363
487
|
}
|
|
364
488
|
} catch {
|
|
365
489
|
// Best-effort
|
|
@@ -379,7 +503,10 @@ export function purgeStaleActiveRunIndex(staleThresholdMs = 300_000, now = Date.
|
|
|
379
503
|
export function reconcileAllStaleRuns(cwd: string, manifestCache: ManifestCache, now = Date.now()): ReconcileResult[] {
|
|
380
504
|
const results: ReconcileResult[] = [];
|
|
381
505
|
// Capture runIds to reconcile BEFORE acquiring locks — avoids TOCTOU between cache iteration and lock acquisition.
|
|
382
|
-
const runIds = manifestCache
|
|
506
|
+
const runIds = manifestCache
|
|
507
|
+
.list(50)
|
|
508
|
+
.filter((m) => m.status === "running" || m.status === "blocked")
|
|
509
|
+
.map((m) => m.runId);
|
|
383
510
|
for (const runId of runIds) {
|
|
384
511
|
const cached = manifestCache.get(runId);
|
|
385
512
|
if (!cached) continue;
|
|
@@ -405,12 +532,25 @@ export function reconcileAllStaleRuns(cwd: string, manifestCache: ManifestCache,
|
|
|
405
532
|
const result = reconcileStaleRun(fresh.manifest, fresh.tasks, now);
|
|
406
533
|
if (result.repaired || result.verdict === "result_exists") {
|
|
407
534
|
if (result.repairedTasks) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
535
|
+
saveRunTasks(fresh.manifest, result.repairedTasks);
|
|
536
|
+
for (const task of result.repairedTasks) {
|
|
537
|
+
try {
|
|
538
|
+
upsertCrewAgent(fresh.manifest, recordFromTask(fresh.manifest, task, "scaffold"));
|
|
539
|
+
} catch {
|
|
540
|
+
/* non-critical */
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
411
544
|
updateRunStatus(fresh.manifest, "failed", `Stale run reconciled: ${result.detail}`);
|
|
412
|
-
void terminateLiveAgentsForRun(fresh.manifest.runId, "failed", appendEvent, fresh.manifest.eventsPath).catch((error) =>
|
|
413
|
-
|
|
545
|
+
void terminateLiveAgentsForRun(fresh.manifest.runId, "failed", appendEvent, fresh.manifest.eventsPath).catch((error) =>
|
|
546
|
+
logInternalError("crash-recovery.reconcile.terminate", error, `runId=${fresh.manifest.runId}`),
|
|
547
|
+
);
|
|
548
|
+
appendEvent(fresh.manifest.eventsPath, {
|
|
549
|
+
type: "crew.run.reconciled_stale",
|
|
550
|
+
runId,
|
|
551
|
+
message: result.detail,
|
|
552
|
+
data: { verdict: result.verdict },
|
|
553
|
+
});
|
|
414
554
|
}
|
|
415
555
|
if (result.verdict !== "healthy") {
|
|
416
556
|
results.push(result);
|