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.
Files changed (432) hide show
  1. package/CHANGELOG.md +145 -0
  2. package/README.md +19 -0
  3. package/dist/build-meta.json +21790 -0
  4. package/dist/index.mjs +83070 -0
  5. package/dist/index.mjs.map +7 -0
  6. package/docs/A +358 -0
  7. package/docs/M-A +357 -0
  8. package/docs/REVIEW-FINDINGS-2026-06 +357 -0
  9. package/docs/Y +357 -0
  10. package/docs/a +357 -0
  11. package/docs/aA +358 -0
  12. package/docs/archive/README.md +91 -0
  13. package/docs/patterns/command-agent-skill.md +1 -1
  14. package/docs/skills/REFERENCE.md +0 -17
  15. package/docs//303/242mmaAAA/303/242 +357 -0
  16. package/index.bundle.ts +25 -0
  17. package/index.ts +95 -4
  18. package/package.json +15 -4
  19. package/skills/iterative-audit/SKILL.md +0 -1
  20. package/skills/widget-rendering/SKILL.md +17 -0
  21. package/src/adapters/claude-adapter.ts +1 -3
  22. package/src/adapters/export-util.ts +16 -16
  23. package/src/adapters/index.ts +5 -5
  24. package/src/agents/agent-config.ts +20 -14
  25. package/src/agents/agent-serializer.ts +1 -1
  26. package/src/agents/discover-agents.ts +83 -39
  27. package/src/benchmark/benchmark-runner.ts +51 -51
  28. package/src/benchmark/feedback-loop.ts +1 -1
  29. package/src/config/config.ts +166 -590
  30. package/src/config/defaults.ts +28 -2
  31. package/src/config/drift-detector.ts +11 -14
  32. package/src/config/markers.ts +201 -203
  33. package/src/config/resilient-parser.ts +14 -6
  34. package/src/config/role-tools.ts +3 -3
  35. package/src/config/suggestions.ts +5 -12
  36. package/src/config/types.ts +9 -25
  37. package/src/errors.ts +151 -157
  38. package/src/extension/action-suggestions.ts +54 -9
  39. package/src/extension/async-notifier.ts +43 -13
  40. package/src/extension/autonomous-policy.ts +77 -37
  41. package/src/extension/command-completions.ts +9 -8
  42. package/src/extension/context-status-injection.ts +14 -12
  43. package/src/extension/crew-autocomplete.ts +8 -16
  44. package/src/extension/crew-cleanup.ts +2 -1
  45. package/src/extension/crew-shortcuts.ts +9 -6
  46. package/src/extension/cross-extension-rpc.ts +136 -42
  47. package/src/extension/help.ts +1 -1
  48. package/src/extension/import-index.ts +10 -5
  49. package/src/extension/knowledge-injection.ts +88 -15
  50. package/src/extension/management.ts +89 -349
  51. package/src/extension/message-renderers.ts +3 -4
  52. package/src/extension/notification-router.ts +22 -5
  53. package/src/extension/notification-sink.ts +6 -3
  54. package/src/extension/pi-api.ts +17 -8
  55. package/src/extension/plan-orchestrate.ts +8 -27
  56. package/src/extension/project-init.ts +21 -6
  57. package/src/extension/register.ts +329 -975
  58. package/src/extension/registration/artifact-cleanup.ts +9 -4
  59. package/src/extension/registration/command-utils.ts +5 -1
  60. package/src/extension/registration/commands.ts +806 -314
  61. package/src/extension/registration/compaction-guard.ts +15 -15
  62. package/src/extension/registration/lifecycle.ts +259 -0
  63. package/src/extension/registration/observability.ts +293 -0
  64. package/src/extension/registration/subagent-helpers.ts +29 -7
  65. package/src/extension/registration/subagent-tools.ts +253 -44
  66. package/src/extension/registration/team-tool.ts +19 -84
  67. package/src/extension/registration/ui.ts +168 -0
  68. package/src/extension/registration/viewers.ts +64 -24
  69. package/src/extension/result-watcher.ts +18 -7
  70. package/src/extension/run-bundle-schema.ts +21 -6
  71. package/src/extension/run-export.ts +15 -6
  72. package/src/extension/run-import.ts +64 -29
  73. package/src/extension/run-index.ts +28 -9
  74. package/src/extension/run-maintenance.ts +32 -12
  75. package/src/extension/session-summary.ts +1 -1
  76. package/src/extension/team-manager-command.ts +64 -7
  77. package/src/extension/team-onboard.ts +151 -150
  78. package/src/extension/team-recommendation.ts +121 -21
  79. package/src/extension/team-tool/anchor.ts +31 -64
  80. package/src/extension/team-tool/api.ts +929 -141
  81. package/src/extension/team-tool/auto-summarize.ts +14 -26
  82. package/src/extension/team-tool/cache-control.ts +1 -5
  83. package/src/extension/team-tool/cancel.ts +138 -38
  84. package/src/extension/team-tool/chain-dispatch.ts +5 -13
  85. package/src/extension/team-tool/chain-executor.ts +29 -51
  86. package/src/extension/team-tool/config-patch.ts +1 -1
  87. package/src/extension/team-tool/context.ts +40 -20
  88. package/src/extension/team-tool/destructive-gate.ts +10 -5
  89. package/src/extension/team-tool/doctor.ts +170 -51
  90. package/src/extension/team-tool/explain.ts +228 -214
  91. package/src/extension/team-tool/failure-patterns.ts +3 -9
  92. package/src/extension/team-tool/goal-wrap.ts +71 -29
  93. package/src/extension/team-tool/goal.ts +185 -35
  94. package/src/extension/team-tool/handle-schedule.ts +34 -15
  95. package/src/extension/team-tool/handle-settings.ts +94 -56
  96. package/src/extension/team-tool/health-monitor.ts +27 -108
  97. package/src/extension/team-tool/inspect.ts +42 -9
  98. package/src/extension/team-tool/intent-policy.ts +4 -1
  99. package/src/extension/team-tool/lifecycle-actions.ts +244 -48
  100. package/src/extension/team-tool/orchestrate.ts +7 -18
  101. package/src/extension/team-tool/parallel-dispatch.ts +51 -29
  102. package/src/extension/team-tool/plan.ts +29 -5
  103. package/src/extension/team-tool/respond.ts +49 -16
  104. package/src/extension/team-tool/run-not-found.ts +3 -8
  105. package/src/extension/team-tool/run.ts +80 -317
  106. package/src/extension/team-tool/status.ts +135 -43
  107. package/src/extension/team-tool/workflow-manage.ts +92 -25
  108. package/src/extension/team-tool-types.ts +8 -1
  109. package/src/extension/team-tool.ts +142 -551
  110. package/src/extension/validate-resources.ts +39 -8
  111. package/src/hooks/registry.ts +66 -17
  112. package/src/hooks/types.ts +1 -1
  113. package/src/i18n.ts +25 -11
  114. package/src/observability/correlation.ts +17 -3
  115. package/src/observability/event-bus.ts +51 -56
  116. package/src/observability/event-to-metric.ts +117 -15
  117. package/src/observability/exporters/otlp-exporter.ts +56 -17
  118. package/src/observability/exporters/prometheus-exporter.ts +1 -1
  119. package/src/observability/metric-registry.ts +16 -4
  120. package/src/observability/metric-retention.ts +8 -2
  121. package/src/observability/metric-sink.ts +11 -3
  122. package/src/observability/metrics-primitives.ts +42 -9
  123. package/src/plugins/plugin-define.ts +2 -2
  124. package/src/plugins/plugin-registry.ts +25 -25
  125. package/src/plugins/plugins/index.ts +1 -1
  126. package/src/plugins/plugins/nextjs.ts +16 -16
  127. package/src/plugins/plugins/vite.ts +7 -11
  128. package/src/plugins/plugins/vitest.ts +6 -11
  129. package/src/runtime/adaptive-plan.ts +225 -40
  130. package/src/runtime/agent-control.ts +58 -15
  131. package/src/runtime/agent-memory.ts +15 -9
  132. package/src/runtime/agent-observability.ts +10 -2
  133. package/src/runtime/anchor-manager.ts +27 -25
  134. package/src/runtime/async-marker.ts +7 -1
  135. package/src/runtime/async-runner.ts +27 -23
  136. package/src/runtime/auto-summarize.ts +7 -13
  137. package/src/runtime/background-runner.ts +189 -251
  138. package/src/runtime/batch-barrier.ts +18 -16
  139. package/src/runtime/cancellation-token.ts +16 -6
  140. package/src/runtime/cancellation.ts +46 -8
  141. package/src/runtime/capability-inventory.ts +6 -4
  142. package/src/runtime/chain-parser.ts +44 -11
  143. package/src/runtime/chain-runner.ts +63 -69
  144. package/src/runtime/checkpoint.ts +12 -56
  145. package/src/runtime/child-pi.ts +343 -78
  146. package/src/runtime/coalesce-tasks.ts +268 -0
  147. package/src/runtime/code-summary.ts +71 -26
  148. package/src/runtime/compact-stages/index.ts +15 -5
  149. package/src/runtime/compact-stages/tail-capture-stage.ts +7 -2
  150. package/src/runtime/compact-stages/truncation-stage.ts +4 -1
  151. package/src/runtime/compaction-summary.ts +17 -10
  152. package/src/runtime/completion-guard.ts +33 -16
  153. package/src/runtime/crash-classification.ts +28 -7
  154. package/src/runtime/crash-recovery.ts +177 -37
  155. package/src/runtime/crew-agent-records.ts +193 -40
  156. package/src/runtime/crew-hooks.ts +9 -24
  157. package/src/runtime/cross-extension-rpc.ts +25 -23
  158. package/src/runtime/custom-tools/irc-tool.ts +43 -15
  159. package/src/runtime/custom-tools/submit-result-tool.ts +16 -5
  160. package/src/runtime/delivery-coordinator.ts +34 -7
  161. package/src/runtime/delta-conflict.ts +9 -21
  162. package/src/runtime/deterministic-ast.ts +1 -1
  163. package/src/runtime/diagnostic-export.ts +53 -20
  164. package/src/runtime/direct-run.ts +12 -2
  165. package/src/runtime/dwf-state-store.ts +1 -1
  166. package/src/runtime/dynamic-workflow-context.ts +186 -58
  167. package/src/runtime/dynamic-workflow-runner.ts +42 -20
  168. package/src/runtime/effectiveness.ts +16 -8
  169. package/src/runtime/errors/crew-errors.ts +7 -11
  170. package/src/runtime/event-stream-bridge.ts +9 -3
  171. package/src/runtime/foreground-control.ts +54 -14
  172. package/src/runtime/foreground-watchdog.ts +9 -6
  173. package/src/runtime/goal-achievement.ts +27 -10
  174. package/src/runtime/goal-evaluator.ts +54 -19
  175. package/src/runtime/goal-loop-runner.ts +280 -99
  176. package/src/runtime/goal-state-store.ts +27 -17
  177. package/src/runtime/green-contract.ts +11 -2
  178. package/src/runtime/group-join.ts +64 -31
  179. package/src/runtime/handoff-manager.ts +37 -42
  180. package/src/runtime/heartbeat-gradient.ts +10 -2
  181. package/src/runtime/heartbeat-watcher.ts +32 -6
  182. package/src/runtime/hidden-handoff.ts +12 -30
  183. package/src/runtime/important-line-classifier.ts +12 -2
  184. package/src/runtime/iteration-hooks.ts +25 -15
  185. package/src/runtime/live-agent-control.ts +55 -7
  186. package/src/runtime/live-agent-manager.ts +130 -27
  187. package/src/runtime/live-control-realtime.ts +23 -3
  188. package/src/runtime/live-irc.ts +4 -1
  189. package/src/runtime/live-session-health.ts +12 -4
  190. package/src/runtime/live-session-runtime.ts +379 -117
  191. package/src/runtime/manifest-cache.ts +28 -12
  192. package/src/runtime/mcp-proxy.ts +8 -16
  193. package/src/runtime/metric-parser.ts +1 -5
  194. package/src/runtime/model-fallback.ts +55 -18
  195. package/src/runtime/model-resolver.ts +2 -6
  196. package/src/runtime/model-scope.ts +19 -3
  197. package/src/runtime/notebook-helpers.ts +60 -62
  198. package/src/runtime/orphan-worker-registry.ts +37 -26
  199. package/src/runtime/output-validator.ts +18 -3
  200. package/src/runtime/overflow-recovery.ts +5 -4
  201. package/src/runtime/parallel-research.ts +29 -5
  202. package/src/runtime/parallel-utils.ts +9 -11
  203. package/src/runtime/path-overlap.ts +150 -0
  204. package/src/runtime/peer-dep.ts +12 -17
  205. package/src/runtime/per-write-validator.ts +1 -3
  206. package/src/runtime/phase-tracker.ts +342 -330
  207. package/src/runtime/pi-args.ts +26 -8
  208. package/src/runtime/pi-json-output.ts +1 -1
  209. package/src/runtime/pi-spawn.ts +30 -19
  210. package/src/runtime/pipeline-runner.ts +56 -55
  211. package/src/runtime/plan-templates.ts +5 -6
  212. package/src/runtime/policy-engine.ts +43 -7
  213. package/src/runtime/post-checks.ts +12 -4
  214. package/src/runtime/post-exit-stdio-guard.ts +2 -2
  215. package/src/runtime/process-lifecycle.ts +20 -10
  216. package/src/runtime/process-status.ts +16 -5
  217. package/src/runtime/progress-event-coalescer.ts +2 -1
  218. package/src/runtime/progress-tracker.ts +103 -103
  219. package/src/runtime/prose-compressor.ts +9 -11
  220. package/src/runtime/recovery-recipes.ts +118 -24
  221. package/src/runtime/replace.ts +25 -10
  222. package/src/runtime/resilient-edit.ts +10 -25
  223. package/src/runtime/result-extractor.ts +1 -2
  224. package/src/runtime/retry-executor.ts +20 -4
  225. package/src/runtime/retry-runner.ts +26 -50
  226. package/src/runtime/role-permission.ts +6 -1
  227. package/src/runtime/run-coalesced-task-group.ts +256 -0
  228. package/src/runtime/run-drift.ts +14 -15
  229. package/src/runtime/run-tracker.ts +6 -28
  230. package/src/runtime/runtime-policy.ts +1 -6
  231. package/src/runtime/runtime-resolver.ts +80 -15
  232. package/src/runtime/scheduler.ts +47 -18
  233. package/src/runtime/semaphore.ts +5 -7
  234. package/src/runtime/sensitive-paths.ts +2 -1
  235. package/src/runtime/session-usage.ts +1 -1
  236. package/src/runtime/settings-store.ts +16 -12
  237. package/src/runtime/sidechain-output.ts +6 -2
  238. package/src/runtime/single-agent-compose.ts +1 -4
  239. package/src/runtime/skill-effectiveness.ts +29 -97
  240. package/src/runtime/skill-instructions.ts +40 -83
  241. package/src/runtime/stale-reconciler.ts +73 -197
  242. package/src/runtime/stream-preview.ts +1 -1
  243. package/src/runtime/streaming-output.ts +1 -1
  244. package/src/runtime/subagent-manager.ts +86 -169
  245. package/src/runtime/subprocess-tool-registry.ts +4 -1
  246. package/src/runtime/supervisor-contact.ts +10 -5
  247. package/src/runtime/task-display.ts +19 -5
  248. package/src/runtime/task-graph-scheduler.ts +95 -21
  249. package/src/runtime/task-graph.ts +5 -11
  250. package/src/runtime/task-health.ts +54 -47
  251. package/src/runtime/task-id.ts +11 -18
  252. package/src/runtime/task-output-context.ts +265 -81
  253. package/src/runtime/task-packet.ts +12 -20
  254. package/src/runtime/task-quality.ts +6 -14
  255. package/src/runtime/task-runner/context-retrieval.ts +4 -13
  256. package/src/runtime/task-runner/live-executor.ts +114 -36
  257. package/src/runtime/task-runner/output-splitter.ts +152 -0
  258. package/src/runtime/task-runner/progress.ts +50 -12
  259. package/src/runtime/task-runner/prompt-builder.ts +31 -7
  260. package/src/runtime/task-runner/prompt-pipeline.ts +31 -7
  261. package/src/runtime/task-runner/result-utils.ts +3 -1
  262. package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
  263. package/src/runtime/task-runner/run-projection.ts +27 -8
  264. package/src/runtime/task-runner/state-helpers.ts +29 -8
  265. package/src/runtime/task-runner/tail-read.ts +2 -6
  266. package/src/runtime/task-runner.ts +180 -326
  267. package/src/runtime/team-runner-artifacts.ts +13 -0
  268. package/src/runtime/team-runner.ts +456 -974
  269. package/src/runtime/tool-output-pruner.ts +6 -9
  270. package/src/runtime/tool-progress.ts +11 -21
  271. package/src/runtime/verification-gates.ts +33 -24
  272. package/src/runtime/verification-integrity.ts +1 -4
  273. package/src/runtime/verification-worktree.ts +62 -12
  274. package/src/runtime/worker-heartbeat.ts +5 -1
  275. package/src/runtime/worker-startup.ts +29 -5
  276. package/src/runtime/workflow-state.ts +17 -9
  277. package/src/runtime/workspace-lock.ts +30 -35
  278. package/src/runtime/workspace-tree.ts +20 -32
  279. package/src/runtime/yield-handler.ts +43 -9
  280. package/src/runtime/zombie-scanner.ts +5 -4
  281. package/src/schema/config-schema.ts +266 -172
  282. package/src/schema/team-tool-schema.ts +29 -74
  283. package/src/schema/validation-types.ts +25 -17
  284. package/src/skills/discover-skills.ts +35 -10
  285. package/src/skills/skill-templates.ts +109 -27
  286. package/src/skills/validate.ts +26 -8
  287. package/src/state/active-run-registry.ts +87 -28
  288. package/src/state/artifact-store.ts +9 -5
  289. package/src/state/atomic-write-v2.ts +85 -63
  290. package/src/state/atomic-write.ts +105 -26
  291. package/src/state/blob-store.ts +47 -20
  292. package/src/state/contracts.ts +20 -5
  293. package/src/state/crew-init.ts +5 -22
  294. package/src/state/decision-ledger.ts +19 -73
  295. package/src/state/event-log-rotation.ts +41 -15
  296. package/src/state/event-log.ts +168 -53
  297. package/src/state/event-reconstructor.ts +11 -1
  298. package/src/state/gitignore-manager.ts +2 -8
  299. package/src/state/health-store.ts +57 -57
  300. package/src/state/hook-instinct-bridge.ts +1 -1
  301. package/src/state/hook-integrations.ts +1 -1
  302. package/src/state/instinct-store.ts +17 -5
  303. package/src/state/jsonl-writer.ts +1 -1
  304. package/src/state/locks.ts +23 -9
  305. package/src/state/mailbox.ts +151 -28
  306. package/src/state/observation-store.ts +20 -14
  307. package/src/state/run-cache.ts +142 -135
  308. package/src/state/run-graph.ts +6 -15
  309. package/src/state/run-metrics.ts +5 -18
  310. package/src/state/schedule.ts +15 -9
  311. package/src/state/state-store.ts +129 -45
  312. package/src/state/task-claims.ts +12 -2
  313. package/src/state/tiered-eval.ts +52 -43
  314. package/src/state/types-eval.ts +2 -2
  315. package/src/state/types.ts +24 -20
  316. package/src/state/usage.ts +20 -4
  317. package/src/state/worker-atomic-writer.ts +6 -3
  318. package/src/subagents/index.ts +2 -2
  319. package/src/teams/discover-teams.ts +21 -6
  320. package/src/tools/safe-bash-extension.ts +5 -6
  321. package/src/tools/safe-bash.ts +10 -11
  322. package/src/types/new-api-types.ts +6 -10
  323. package/src/ui/agent-management-overlay.ts +52 -40
  324. package/src/ui/card-colors.ts +13 -4
  325. package/src/ui/crew-footer.ts +8 -7
  326. package/src/ui/crew-select-list.ts +1 -1
  327. package/src/ui/dashboard-panes/agents-pane.ts +41 -25
  328. package/src/ui/dashboard-panes/cancellation-pane.ts +1 -1
  329. package/src/ui/dashboard-panes/capability-pane.ts +32 -15
  330. package/src/ui/dashboard-panes/health-pane.ts +2 -1
  331. package/src/ui/dashboard-panes/metrics-pane.ts +4 -1
  332. package/src/ui/dashboard-panes/progress-pane.ts +12 -9
  333. package/src/ui/heartbeat-aggregator.ts +15 -4
  334. package/src/ui/keybinding-map.ts +40 -7
  335. package/src/ui/live-conversation-overlay.ts +36 -20
  336. package/src/ui/live-duration.ts +1 -4
  337. package/src/ui/live-run-sidebar.ts +88 -25
  338. package/src/ui/loaders.ts +2 -8
  339. package/src/ui/mascot.ts +20 -36
  340. package/src/ui/overlays/agent-picker-overlay.ts +11 -3
  341. package/src/ui/overlays/confirm-overlay.ts +4 -2
  342. package/src/ui/overlays/help-overlay.ts +25 -14
  343. package/src/ui/overlays/mailbox-compose-overlay.ts +48 -11
  344. package/src/ui/overlays/mailbox-compose-preview.ts +20 -5
  345. package/src/ui/overlays/mailbox-detail-overlay.ts +27 -6
  346. package/src/ui/pi-ui-compat.ts +7 -7
  347. package/src/ui/powerbar-publisher.ts +120 -42
  348. package/src/ui/render-diff.ts +10 -3
  349. package/src/ui/render-scheduler.ts +12 -4
  350. package/src/ui/run-action-dispatcher.ts +81 -18
  351. package/src/ui/run-dashboard.ts +172 -76
  352. package/src/ui/run-event-bus.ts +59 -37
  353. package/src/ui/run-snapshot-cache.ts +276 -86
  354. package/src/ui/settings-overlay.ts +361 -74
  355. package/src/ui/status-colors.ts +12 -1
  356. package/src/ui/syntax-highlight.ts +1 -1
  357. package/src/ui/theme-adapter.ts +16 -14
  358. package/src/ui/theme-discovery.ts +13 -2
  359. package/src/ui/tool-progress-formatter.ts +7 -7
  360. package/src/ui/tool-render.ts +128 -56
  361. package/src/ui/tool-renderers/brief-mode.ts +45 -27
  362. package/src/ui/tool-renderers/index.ts +109 -43
  363. package/src/ui/transcript-cache.ts +32 -6
  364. package/src/ui/transcript-entries.ts +25 -23
  365. package/src/ui/transcript-viewer.ts +78 -29
  366. package/src/ui/widget/index.ts +99 -40
  367. package/src/ui/widget/widget-formatters.ts +13 -6
  368. package/src/ui/widget/widget-model.ts +19 -8
  369. package/src/ui/widget/widget-renderer.ts +23 -13
  370. package/src/ui/widget/widget-types.ts +1 -1
  371. package/src/utils/bm25-search.ts +199 -199
  372. package/src/utils/conflict-detect.ts +22 -21
  373. package/src/utils/env-filter.ts +14 -7
  374. package/src/utils/file-coalescer.ts +5 -1
  375. package/src/utils/fingerprint.ts +3 -6
  376. package/src/utils/frontmatter.ts +3 -1
  377. package/src/utils/fs-watch.ts +2 -6
  378. package/src/utils/gh-protocol.ts +119 -44
  379. package/src/utils/git.ts +13 -15
  380. package/src/utils/guards.ts +2 -5
  381. package/src/utils/ids.ts +9 -2
  382. package/src/utils/incremental-reader.ts +14 -3
  383. package/src/utils/internal-error.ts +2 -1
  384. package/src/utils/names.ts +12 -3
  385. package/src/utils/paths.ts +49 -5
  386. package/src/utils/project-detector.ts +2 -2
  387. package/src/utils/redaction.ts +29 -19
  388. package/src/utils/resolve-shell.ts +9 -7
  389. package/src/utils/run-watcher-registry.ts +19 -31
  390. package/src/utils/safe-paths.ts +45 -24
  391. package/src/utils/scan-cache.ts +9 -2
  392. package/src/utils/session-utils.ts +2 -4
  393. package/src/utils/sleep.ts +12 -5
  394. package/src/utils/sse-parser.ts +5 -17
  395. package/src/utils/visual.ts +52 -32
  396. package/src/workflows/discover-workflows.ts +41 -109
  397. package/src/workflows/intermediate-store.ts +5 -21
  398. package/src/workflows/preflight-validator.ts +6 -33
  399. package/src/workflows/topology-analyzer.ts +5 -21
  400. package/src/workflows/workflow-config.ts +7 -6
  401. package/src/worktree/branch-freshness.ts +66 -8
  402. package/src/worktree/cleanup.ts +130 -20
  403. package/src/worktree/worktree-manager.ts +212 -69
  404. package/skills/artifact-analysis-loop/SKILL.md +0 -303
  405. package/skills/detection-pipeline-design/SKILL.md +0 -286
  406. package/skills/hunting-investigation-loop/SKILL.md +0 -402
  407. package/skills/incident-playbook-construction/SKILL.md +0 -384
  408. package/skills/security-review/SKILL.md +0 -561
  409. package/skills/threat-hypothesis-framework/SKILL.md +0 -176
  410. package/skills/ui-render-performance/SKILL.md +0 -58
  411. /package/docs/{followup-review-round3-2026-05-12.md → archive/followup-review-round3-2026-05-12.md} +0 -0
  412. /package/docs/{followup-review-round4-2026-05-13.md → archive/followup-review-round4-2026-05-13.md} +0 -0
  413. /package/docs/{pi-crew-bugs.md → archive/pi-crew-bugs.md} +0 -0
  414. /package/docs/{pi-crew-test-final.md → archive/pi-crew-test-final.md} +0 -0
  415. /package/docs/{pi-crew-test-results.md → archive/pi-crew-test-results.md} +0 -0
  416. /package/docs/{pi-crew-test-round2.md → archive/pi-crew-test-round2.md} +0 -0
  417. /package/docs/{pi-crew-test-round4.md → archive/pi-crew-test-round4.md} +0 -0
  418. /package/docs/{pi-crew-test-round5.md → archive/pi-crew-test-round5.md} +0 -0
  419. /package/docs/{pi-crew-test-round6.md → archive/pi-crew-test-round6.md} +0 -0
  420. /package/docs/{pi-crew-v0.5.10-audit-fix-plan.md → archive/pi-crew-v0.5.10-audit-fix-plan.md} +0 -0
  421. /package/docs/{pi-crew-v0.5.11-audit-fix-plan.md → archive/pi-crew-v0.5.11-audit-fix-plan.md} +0 -0
  422. /package/docs/{pi-crew-v0.5.12-audit-fix-plan.md → archive/pi-crew-v0.5.12-audit-fix-plan.md} +0 -0
  423. /package/docs/{pi-crew-v0.5.13-audit-fix-plan.md → archive/pi-crew-v0.5.13-audit-fix-plan.md} +0 -0
  424. /package/docs/{pi-crew-v0.5.14-audit-fix-plan.md → archive/pi-crew-v0.5.14-audit-fix-plan.md} +0 -0
  425. /package/docs/{pi-crew-v0.5.16-audit-fix-plan.md → archive/pi-crew-v0.5.16-audit-fix-plan.md} +0 -0
  426. /package/docs/{pi-crew-v0.5.17-audit-fix-plan.md → archive/pi-crew-v0.5.17-audit-fix-plan.md} +0 -0
  427. /package/docs/{pi-crew-v0.5.5-audit-fix-plan.md → archive/pi-crew-v0.5.5-audit-fix-plan.md} +0 -0
  428. /package/docs/{pi-crew-v0.5.9-audit-fix-plan.md → archive/pi-crew-v0.5.9-audit-fix-plan.md} +0 -0
  429. /package/docs/{pi-mono-opportunities.md → archive/pi-mono-opportunities.md} +0 -0
  430. /package/docs/{pi-mono-review.md → archive/pi-mono-review.md} +0 -0
  431. /package/docs/{pi-subagent4-comparison.md → archive/pi-subagent4-comparison.md} +0 -0
  432. /package/docs/{pi-subagents3-deep-analysis.md → archive/pi-subagents3-deep-analysis.md} +0 -0
@@ -1,268 +1,282 @@
1
1
  import * as fs from "node:fs";
2
- import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
3
2
  import * as path from "node:path";
4
3
  import { loadRunManifestById } from "../../state/state-store.ts";
5
4
  import type { TeamRunManifest, TeamTaskState } from "../../state/types.ts";
5
+ import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
6
6
 
7
7
  /**
8
8
  * Local wrapper matching the planned `result` API used by handleExplain.
9
9
  */
10
10
  function result(text: string, details: Record<string, unknown>, isError: boolean): { isError: boolean; text: string } {
11
- return { isError, text };
11
+ return { isError, text };
12
12
  }
13
13
 
14
14
  export interface TaskExplainContext {
15
- taskId: string;
16
- role: string;
17
- status: string;
18
- phase?: string;
19
- why: string;
20
- what: string;
21
- filesTouched: string[];
22
- connectedTasks: Array<{ taskId: string; status: string; relation: string }>;
23
- layer: string;
24
- complexity: "simple" | "moderate" | "complex";
25
- usage?: { inputTokens?: number; outputTokens?: number };
26
- duration?: number;
15
+ taskId: string;
16
+ role: string;
17
+ status: string;
18
+ phase?: string;
19
+ why: string;
20
+ what: string;
21
+ filesTouched: string[];
22
+ connectedTasks: Array<{ taskId: string; status: string; relation: string }>;
23
+ layer: string;
24
+ complexity: "simple" | "moderate" | "complex";
25
+ usage?: { inputTokens?: number; outputTokens?: number };
26
+ duration?: number;
27
27
  }
28
28
 
29
29
  /**
30
30
  * Build explain context for a specific task in a run.
31
31
  */
32
- export function buildTaskExplainContext(
33
- manifest: TeamRunManifest,
34
- tasks: TeamTaskState[],
35
- taskId: string,
36
- ): TaskExplainContext {
37
- const task = tasks.find((t) => t.id === taskId);
38
- if (!task) {
39
- throw new Error(`Task ${taskId} not found in run ${manifest.runId}`);
40
- }
32
+ export function buildTaskExplainContext(manifest: TeamRunManifest, tasks: TeamTaskState[], taskId: string): TaskExplainContext {
33
+ const task = tasks.find((t) => t.id === taskId);
34
+ if (!task) {
35
+ throw new Error(`Task ${taskId} not found in run ${manifest.runId}`);
36
+ }
41
37
 
42
- const dependsOn = task.dependsOn ?? [];
43
- const dependents = tasks.filter((t) => (t.dependsOn ?? []).includes(taskId));
38
+ const dependsOn = task.dependsOn ?? [];
39
+ const dependents = tasks.filter((t) => (t.dependsOn ?? []).includes(taskId));
44
40
 
45
- // Layer from phase
46
- const layerMap: Record<string, string> = {
47
- explore: "exploration",
48
- plan: "planning",
49
- assess: "assessment",
50
- execute: "execution",
51
- verify: "verification",
52
- analyze: "analysis",
53
- write: "documentation",
54
- "": "unknown",
55
- };
56
- const layer = layerMap[task.adaptive?.phase ?? ""] ?? "unknown";
41
+ // Layer from phase
42
+ const layerMap: Record<string, string> = {
43
+ explore: "exploration",
44
+ plan: "planning",
45
+ assess: "assessment",
46
+ execute: "execution",
47
+ verify: "verification",
48
+ analyze: "analysis",
49
+ write: "documentation",
50
+ "": "unknown",
51
+ };
52
+ const layer = layerMap[task.adaptive?.phase ?? ""] ?? "unknown";
57
53
 
58
- // Why it exists
59
- let why = `Part of ${manifest.team ?? "unknown"} team workflow.`;
60
- if (dependsOn.length > 0) {
61
- const depTasks = dependsOn.map((d) => {
62
- const dep = tasks.find((t) => t.id === d);
63
- return dep ? `\`${d}\` (${dep.status})` : `\`${d}\``;
64
- }).join(", ");
65
- why += ` Depends on ${depTasks}.`;
66
- }
67
- if (dependents.length > 0) {
68
- why += ` ${dependents.length} task(s) depend on this.`;
69
- }
54
+ // Why it exists
55
+ let why = `Part of ${manifest.team ?? "unknown"} team workflow.`;
56
+ if (dependsOn.length > 0) {
57
+ const depTasks = dependsOn
58
+ .map((d) => {
59
+ const dep = tasks.find((t) => t.id === d);
60
+ return dep ? `\`${d}\` (${dep.status})` : `\`${d}\``;
61
+ })
62
+ .join(", ");
63
+ why += ` Depends on ${depTasks}.`;
64
+ }
65
+ if (dependents.length > 0) {
66
+ why += ` ${dependents.length} task(s) depend on this.`;
67
+ }
70
68
 
71
- // What it did
72
- let what = `Ran agent: ${task.role}`;
73
- if (task.model) {
74
- what += ` (${task.model})`;
75
- }
76
- if (task.usage) {
77
- const inputTokens = task.usage.input ?? 0;
78
- const outputTokens = task.usage.output ?? 0;
79
- what += `. Usage: input=${inputTokens}, output=${outputTokens}`;
80
- }
81
- if (task.status === "failed") {
82
- what += `. Status: FAILED`;
83
- if (task.error) {
84
- what += ` — ${task.error}`;
85
- }
86
- }
69
+ // What it did
70
+ let what = `Ran agent: ${task.role}`;
71
+ if (task.model) {
72
+ what += ` (${task.model})`;
73
+ }
74
+ if (task.usage) {
75
+ const inputTokens = task.usage.input ?? 0;
76
+ const outputTokens = task.usage.output ?? 0;
77
+ what += `. Usage: input=${inputTokens}, output=${outputTokens}`;
78
+ }
79
+ if (task.status === "failed") {
80
+ what += `. Status: FAILED`;
81
+ if (task.error) {
82
+ what += ` — ${task.error}`;
83
+ }
84
+ }
87
85
 
88
- // Files from artifacts
89
- const artifactsPath = manifest.artifactsRoot;
90
- const filesTouched: string[] = [];
91
- if (fs.existsSync(artifactsPath)) {
92
- try {
93
- const entries = fs.readdirSync(artifactsPath);
94
- for (const entry of entries) {
95
- const fullPath = path.join(artifactsPath, entry);
96
- try {
97
- if (fs.statSync(fullPath).isFile()) {
98
- filesTouched.push(entry);
99
- }
100
- } catch { /* ignore */ }
101
- }
102
- } catch { /* ignore */ }
103
- }
86
+ // Files from artifacts
87
+ const artifactsPath = manifest.artifactsRoot;
88
+ const filesTouched: string[] = [];
89
+ if (fs.existsSync(artifactsPath)) {
90
+ try {
91
+ const entries = fs.readdirSync(artifactsPath);
92
+ for (const entry of entries) {
93
+ const fullPath = path.join(artifactsPath, entry);
94
+ try {
95
+ if (fs.statSync(fullPath).isFile()) {
96
+ filesTouched.push(entry);
97
+ }
98
+ } catch {
99
+ /* ignore */
100
+ }
101
+ }
102
+ } catch {
103
+ /* ignore */
104
+ }
105
+ }
104
106
 
105
- // Duration
106
- let duration: number | undefined;
107
- if (task.startedAt && task.finishedAt) {
108
- duration = (new Date(task.finishedAt).getTime() - new Date(task.startedAt).getTime()) / 1000;
109
- }
107
+ // Duration
108
+ let duration: number | undefined;
109
+ if (task.startedAt && task.finishedAt) {
110
+ duration = (new Date(task.finishedAt).getTime() - new Date(task.startedAt).getTime()) / 1000;
111
+ }
110
112
 
111
- // Complexity
112
- const complexity = tasks.length <= 3 ? "simple" : tasks.length <= 8 ? "moderate" : "complex";
113
+ // Complexity
114
+ const complexity = tasks.length <= 3 ? "simple" : tasks.length <= 8 ? "moderate" : "complex";
113
115
 
114
- return {
115
- taskId,
116
- role: task.role,
117
- status: task.status,
118
- phase: task.adaptive?.phase,
119
- why,
120
- what,
121
- filesTouched,
122
- connectedTasks: [
123
- ...dependsOn.map((d) => {
124
- const dep = tasks.find((t) => t.id === d);
125
- return {
126
- taskId: d,
127
- status: dep?.status ?? "unknown",
128
- relation: "depends on",
129
- };
130
- }),
131
- ...dependents.map((d) => ({
132
- taskId: d.id,
133
- status: d.status,
134
- relation: "depended on by",
135
- })),
136
- ],
137
- layer,
138
- complexity,
139
- usage: task.usage ? { inputTokens: task.usage.input, outputTokens: task.usage.output } : undefined,
140
- duration,
141
- };
116
+ return {
117
+ taskId,
118
+ role: task.role,
119
+ status: task.status,
120
+ phase: task.adaptive?.phase,
121
+ why,
122
+ what,
123
+ filesTouched,
124
+ connectedTasks: [
125
+ ...dependsOn.map((d) => {
126
+ const dep = tasks.find((t) => t.id === d);
127
+ return {
128
+ taskId: d,
129
+ status: dep?.status ?? "unknown",
130
+ relation: "depends on",
131
+ };
132
+ }),
133
+ ...dependents.map((d) => ({
134
+ taskId: d.id,
135
+ status: d.status,
136
+ relation: "depended on by",
137
+ })),
138
+ ],
139
+ layer,
140
+ complexity,
141
+ usage: task.usage ? { inputTokens: task.usage.input, outputTokens: task.usage.output } : undefined,
142
+ duration,
143
+ };
142
144
  }
143
145
 
144
146
  /**
145
147
  * Format task explain context as markdown.
146
148
  */
147
149
  export function formatTaskExplain(ctx: TaskExplainContext): string {
148
- const lines: string[] = [];
150
+ const lines: string[] = [];
149
151
 
150
- lines.push(`# Task: ${ctx.taskId} (${ctx.role})`);
151
- lines.push("");
152
- lines.push(`| | |`);
153
- lines.push(`|---|---|`);
154
- lines.push(`| **Status** | ${ctx.status} |`);
155
- if (ctx.phase) lines.push(`| **Phase** | ${ctx.phase} |`);
156
- lines.push(`| **Layer** | ${ctx.layer} |`);
157
- lines.push(`| **Complexity** | ${ctx.complexity} |`);
152
+ lines.push(`# Task: ${ctx.taskId} (${ctx.role})`);
153
+ lines.push("");
154
+ lines.push(`| | |`);
155
+ lines.push(`|---|---|`);
156
+ lines.push(`| **Status** | ${ctx.status} |`);
157
+ if (ctx.phase) lines.push(`| **Phase** | ${ctx.phase} |`);
158
+ lines.push(`| **Layer** | ${ctx.layer} |`);
159
+ lines.push(`| **Complexity** | ${ctx.complexity} |`);
158
160
 
159
- if (ctx.duration) {
160
- const minutes = Math.round(ctx.duration / 60);
161
- lines.push(`| **Duration** | ${minutes} min |`);
162
- }
161
+ if (ctx.duration) {
162
+ const minutes = Math.round(ctx.duration / 60);
163
+ lines.push(`| **Duration** | ${minutes} min |`);
164
+ }
163
165
 
164
- if (ctx.usage) {
165
- const input = ctx.usage.inputTokens ?? 0;
166
- const output = ctx.usage.outputTokens ?? 0;
167
- lines.push(`| **Usage** | ↑${input} ↓${output} tokens |`);
168
- }
166
+ if (ctx.usage) {
167
+ const input = ctx.usage.inputTokens ?? 0;
168
+ const output = ctx.usage.outputTokens ?? 0;
169
+ lines.push(`| **Usage** | ↑${input} ↓${output} tokens |`);
170
+ }
169
171
 
170
- lines.push("");
171
- lines.push(`## Why it exists`);
172
- lines.push("");
173
- lines.push(ctx.why);
174
- lines.push("");
175
- lines.push(`## What it did`);
176
- lines.push("");
177
- lines.push(ctx.what);
178
- lines.push("");
172
+ lines.push("");
173
+ lines.push(`## Why it exists`);
174
+ lines.push("");
175
+ lines.push(ctx.why);
176
+ lines.push("");
177
+ lines.push(`## What it did`);
178
+ lines.push("");
179
+ lines.push(ctx.what);
180
+ lines.push("");
179
181
 
180
- if (ctx.filesTouched.length > 0) {
181
- lines.push("## Files produced");
182
- lines.push("");
183
- for (const file of ctx.filesTouched) {
184
- lines.push(`- \`${file}\``);
185
- }
186
- lines.push("");
187
- }
182
+ if (ctx.filesTouched.length > 0) {
183
+ lines.push("## Files produced");
184
+ lines.push("");
185
+ for (const file of ctx.filesTouched) {
186
+ lines.push(`- \`${file}\``);
187
+ }
188
+ lines.push("");
189
+ }
188
190
 
189
- if (ctx.connectedTasks.length > 0) {
190
- lines.push("## Connected tasks");
191
- lines.push("");
192
- for (const conn of ctx.connectedTasks) {
193
- lines.push(`- ${conn.relation} \`${conn.taskId}\` (${conn.status})`);
194
- }
195
- lines.push("");
196
- }
191
+ if (ctx.connectedTasks.length > 0) {
192
+ lines.push("## Connected tasks");
193
+ lines.push("");
194
+ for (const conn of ctx.connectedTasks) {
195
+ lines.push(`- ${conn.relation} \`${conn.taskId}\` (${conn.status})`);
196
+ }
197
+ lines.push("");
198
+ }
197
199
 
198
- return lines.join("\n");
200
+ return lines.join("\n");
199
201
  }
200
202
 
201
203
  /**
202
204
  * Handle team action='explain'.
203
205
  */
204
- export function handleExplain(params: {
205
- runId?: string;
206
- taskId?: string;
207
- cwd?: string;
208
- }, cwd: string): { isError: boolean; text: string } {
209
- if (!params.runId) {
210
- return result("explain requires runId", { action: "explain", status: "error" }, true);
211
- }
206
+ export function handleExplain(
207
+ params: {
208
+ runId?: string;
209
+ taskId?: string;
210
+ cwd?: string;
211
+ },
212
+ cwd: string,
213
+ ): { isError: boolean; text: string } {
214
+ if (!params.runId) {
215
+ return result("explain requires runId", { action: "explain", status: "error" }, true);
216
+ }
212
217
 
213
- const loaded = loadRunManifestById(cwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
214
- if (!loaded) {
215
- return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "explain", status: "error" }, true);
216
- }
218
+ const loaded = loadRunManifestById(cwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
219
+ if (!loaded) {
220
+ return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "explain", status: "error" }, true);
221
+ }
217
222
 
218
- const { manifest, tasks } = loaded;
223
+ const { manifest, tasks } = loaded;
219
224
 
220
- if (params.taskId) {
221
- try {
222
- const ctx = buildTaskExplainContext(manifest, tasks, params.taskId);
223
- const output = formatTaskExplain(ctx);
224
- return result(output, { action: "explain", runId: params.runId }, false);
225
- } catch (err) {
226
- return result(`Task '${params.taskId}' not found: ${err instanceof Error ? err.message : String(err)}`, { action: "explain", status: "error" }, true);
227
- }
228
- }
225
+ if (params.taskId) {
226
+ try {
227
+ const ctx = buildTaskExplainContext(manifest, tasks, params.taskId);
228
+ const output = formatTaskExplain(ctx);
229
+ return result(output, { action: "explain", runId: params.runId }, false);
230
+ } catch (err) {
231
+ return result(
232
+ `Task '${params.taskId}' not found: ${err instanceof Error ? err.message : String(err)}`,
233
+ { action: "explain", status: "error" },
234
+ true,
235
+ );
236
+ }
237
+ }
229
238
 
230
- // Explain entire run
231
- const lines: string[] = [];
232
- lines.push(`# Run: ${params.runId}`);
233
- lines.push("");
234
- lines.push(`| | |`);
235
- lines.push(`|---|---|`);
239
+ // Explain entire run
240
+ const lines: string[] = [];
241
+ lines.push(`# Run: ${params.runId}`);
242
+ lines.push("");
243
+ lines.push(`| | |`);
244
+ lines.push(`|---|---|`);
236
245
 
237
- const start = new Date(manifest.createdAt).getTime();
238
- const end = manifest.updatedAt ? new Date(manifest.updatedAt).getTime() : Date.now();
239
- const duration = Math.round((end - start) / 1000 / 60);
246
+ const start = new Date(manifest.createdAt).getTime();
247
+ const end = manifest.updatedAt ? new Date(manifest.updatedAt).getTime() : Date.now();
248
+ const duration = Math.round((end - start) / 1000 / 60);
240
249
 
241
- lines.push(`| **Team** | ${manifest.team} |`);
242
- lines.push(`| **Workflow** | ${manifest.workflow ?? "default"} |`);
243
- lines.push(`| **Status** | ${manifest.status} |`);
244
- lines.push(`| **Duration** | ${duration} min |`);
245
- lines.push(`| **Tasks** | ${tasks.length} |`);
246
- lines.push("");
250
+ lines.push(`| **Team** | ${manifest.team} |`);
251
+ lines.push(`| **Workflow** | ${manifest.workflow ?? "default"} |`);
252
+ lines.push(`| **Status** | ${manifest.status} |`);
253
+ lines.push(`| **Duration** | ${duration} min |`);
254
+ lines.push(`| **Tasks** | ${tasks.length} |`);
255
+ lines.push("");
247
256
 
248
- lines.push("## Tasks");
249
- lines.push("");
250
- lines.push("| Task | Role | Status | Layer |");
251
- lines.push("|------|------|--------|-------|");
257
+ lines.push("## Tasks");
258
+ lines.push("");
259
+ lines.push("| Task | Role | Status | Layer |");
260
+ lines.push("|------|------|--------|-------|");
252
261
 
253
- for (const task of tasks) {
254
- const layerMap: Record<string, string> = {
255
- explore: "exploration", plan: "planning", assess: "assessment",
256
- execute: "execution", verify: "verification", analyze: "analysis", write: "documentation",
257
- };
258
- const layer = layerMap[task.adaptive?.phase ?? ""] ?? "unknown";
259
- const statusIcon = task.status === "completed" ? "✅" : task.status === "failed" ? "❌" : "⏳";
260
- lines.push(`| \`${task.id}\` | ${task.role} | ${statusIcon} ${task.status} | ${layer} |`);
261
- }
262
- lines.push("");
262
+ for (const task of tasks) {
263
+ const layerMap: Record<string, string> = {
264
+ explore: "exploration",
265
+ plan: "planning",
266
+ assess: "assessment",
267
+ execute: "execution",
268
+ verify: "verification",
269
+ analyze: "analysis",
270
+ write: "documentation",
271
+ };
272
+ const layer = layerMap[task.adaptive?.phase ?? ""] ?? "unknown";
273
+ const statusIcon = task.status === "completed" ? "✅" : task.status === "failed" ? "❌" : "⏳";
274
+ lines.push(`| \`${task.id}\` | ${task.role} | ${statusIcon} ${task.status} | ${layer} |`);
275
+ }
276
+ lines.push("");
263
277
 
264
- lines.push("---");
265
- lines.push(`*Use \`team action='explain' runId=${params.runId} taskId=<taskId>\` for task detail.*`);
278
+ lines.push("---");
279
+ lines.push(`*Use \`team action='explain' runId=${params.runId} taskId=<taskId>\` for task detail.*`);
266
280
 
267
- return result(lines.join("\n"), { action: "explain", runId: params.runId }, false);
281
+ return result(lines.join("\n"), { action: "explain", runId: params.runId }, false);
268
282
  }
@@ -61,9 +61,7 @@ export function normalizeErrorSignature(error: string | undefined): string {
61
61
  * considered failures for aggregation purposes).
62
62
  */
63
63
  export function aggregateFailurePatterns(tasks: FailurePatternInput[]): FailurePattern[] {
64
- const failed = tasks.filter(
65
- (t) => t.status === "failed" || t.status === "cancelled",
66
- );
64
+ const failed = tasks.filter((t) => t.status === "failed" || t.status === "cancelled");
67
65
  if (failed.length === 0) return [];
68
66
  const buckets = new Map<string, FailurePattern>();
69
67
  for (const t of failed) {
@@ -86,9 +84,7 @@ export function aggregateFailurePatterns(tasks: FailurePatternInput[]): FailureP
86
84
  }
87
85
  }
88
86
  // Only patterns with >=2 members (repeated root causes).
89
- return [...buckets.values()]
90
- .filter((b) => b.count >= 2)
91
- .sort((a, b) => b.count - a.count);
87
+ return [...buckets.values()].filter((b) => b.count >= 2).sort((a, b) => b.count - a.count);
92
88
  }
93
89
 
94
90
  /**
@@ -106,9 +102,7 @@ export function aggregateFailurePatterns(tasks: FailurePatternInput[]): FailureP
106
102
  export function formatFailurePatterns(tasks: FailurePatternInput[]): string[] {
107
103
  const patterns = aggregateFailurePatterns(tasks);
108
104
  if (patterns.length === 0) return [];
109
- const failedCount = tasks.filter(
110
- (t) => t.status === "failed" || t.status === "cancelled",
111
- ).length;
105
+ const failedCount = tasks.filter((t) => t.status === "failed" || t.status === "cancelled").length;
112
106
  const groupedCount = patterns.reduce((sum, p) => sum + p.count, 0);
113
107
  const lines = [
114
108
  `Common failure patterns (${groupedCount} of ${failedCount} failures share ${patterns.length} root cause${patterns.length === 1 ? "" : "s"}):`,