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.
Files changed (435) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +19 -0
  3. package/dist/build-meta.json +21784 -0
  4. package/dist/index.mjs +83169 -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/migration/atomic-write-v2-migration.md +297 -0
  14. package/docs/patterns/command-agent-skill.md +1 -1
  15. package/docs/perf/performance-review-2026-07.md +287 -0
  16. package/docs/skills/REFERENCE.md +0 -17
  17. package/docs//303/242mmaAAA/303/242 +357 -0
  18. package/index.bundle.ts +25 -0
  19. package/index.ts +95 -4
  20. package/package.json +15 -4
  21. package/skills/iterative-audit/SKILL.md +0 -1
  22. package/skills/widget-rendering/SKILL.md +17 -0
  23. package/src/adapters/claude-adapter.ts +1 -3
  24. package/src/adapters/export-util.ts +16 -16
  25. package/src/adapters/index.ts +5 -5
  26. package/src/agents/agent-config.ts +20 -14
  27. package/src/agents/agent-serializer.ts +1 -1
  28. package/src/agents/discover-agents.ts +83 -39
  29. package/src/benchmark/benchmark-runner.ts +51 -51
  30. package/src/benchmark/feedback-loop.ts +1 -1
  31. package/src/config/config.ts +303 -591
  32. package/src/config/defaults.ts +28 -2
  33. package/src/config/drift-detector.ts +11 -14
  34. package/src/config/markers.ts +201 -203
  35. package/src/config/resilient-parser.ts +14 -6
  36. package/src/config/role-tools.ts +3 -3
  37. package/src/config/suggestions.ts +5 -12
  38. package/src/config/types.ts +9 -25
  39. package/src/errors.ts +151 -157
  40. package/src/extension/action-suggestions.ts +54 -9
  41. package/src/extension/async-notifier.ts +43 -13
  42. package/src/extension/autonomous-policy.ts +77 -37
  43. package/src/extension/command-completions.ts +9 -8
  44. package/src/extension/context-status-injection.ts +14 -12
  45. package/src/extension/crew-autocomplete.ts +8 -16
  46. package/src/extension/crew-cleanup.ts +2 -1
  47. package/src/extension/crew-shortcuts.ts +9 -6
  48. package/src/extension/cross-extension-rpc.ts +136 -42
  49. package/src/extension/help.ts +1 -1
  50. package/src/extension/import-index.ts +10 -5
  51. package/src/extension/knowledge-injection.ts +88 -15
  52. package/src/extension/management.ts +89 -349
  53. package/src/extension/message-renderers.ts +3 -4
  54. package/src/extension/notification-router.ts +22 -5
  55. package/src/extension/notification-sink.ts +6 -3
  56. package/src/extension/pi-api.ts +17 -8
  57. package/src/extension/plan-orchestrate.ts +8 -27
  58. package/src/extension/project-init.ts +21 -6
  59. package/src/extension/register.ts +329 -975
  60. package/src/extension/registration/artifact-cleanup.ts +9 -4
  61. package/src/extension/registration/command-utils.ts +5 -1
  62. package/src/extension/registration/commands.ts +806 -314
  63. package/src/extension/registration/compaction-guard.ts +15 -15
  64. package/src/extension/registration/lifecycle.ts +259 -0
  65. package/src/extension/registration/observability.ts +293 -0
  66. package/src/extension/registration/subagent-helpers.ts +29 -7
  67. package/src/extension/registration/subagent-tools.ts +253 -44
  68. package/src/extension/registration/team-tool.ts +19 -84
  69. package/src/extension/registration/ui.ts +168 -0
  70. package/src/extension/registration/viewers.ts +64 -24
  71. package/src/extension/result-watcher.ts +18 -7
  72. package/src/extension/run-bundle-schema.ts +21 -6
  73. package/src/extension/run-export.ts +15 -6
  74. package/src/extension/run-import.ts +64 -29
  75. package/src/extension/run-index.ts +28 -9
  76. package/src/extension/run-maintenance.ts +32 -12
  77. package/src/extension/session-summary.ts +1 -1
  78. package/src/extension/team-manager-command.ts +64 -7
  79. package/src/extension/team-onboard.ts +149 -150
  80. package/src/extension/team-recommendation.ts +121 -21
  81. package/src/extension/team-tool/anchor.ts +31 -64
  82. package/src/extension/team-tool/api.ts +929 -141
  83. package/src/extension/team-tool/auto-summarize.ts +14 -26
  84. package/src/extension/team-tool/cache-control.ts +1 -5
  85. package/src/extension/team-tool/cancel.ts +138 -38
  86. package/src/extension/team-tool/chain-dispatch.ts +5 -13
  87. package/src/extension/team-tool/chain-executor.ts +29 -51
  88. package/src/extension/team-tool/config-patch.ts +1 -1
  89. package/src/extension/team-tool/context.ts +40 -20
  90. package/src/extension/team-tool/destructive-gate.ts +10 -5
  91. package/src/extension/team-tool/doctor.ts +170 -51
  92. package/src/extension/team-tool/explain.ts +228 -214
  93. package/src/extension/team-tool/failure-patterns.ts +3 -9
  94. package/src/extension/team-tool/goal-wrap.ts +71 -29
  95. package/src/extension/team-tool/goal.ts +185 -35
  96. package/src/extension/team-tool/handle-schedule.ts +34 -15
  97. package/src/extension/team-tool/handle-settings.ts +94 -56
  98. package/src/extension/team-tool/health-monitor.ts +27 -108
  99. package/src/extension/team-tool/inspect.ts +42 -9
  100. package/src/extension/team-tool/intent-policy.ts +4 -1
  101. package/src/extension/team-tool/lifecycle-actions.ts +244 -48
  102. package/src/extension/team-tool/orchestrate.ts +7 -18
  103. package/src/extension/team-tool/parallel-dispatch.ts +51 -29
  104. package/src/extension/team-tool/plan.ts +29 -5
  105. package/src/extension/team-tool/respond.ts +49 -16
  106. package/src/extension/team-tool/run-not-found.ts +3 -8
  107. package/src/extension/team-tool/run.ts +80 -317
  108. package/src/extension/team-tool/status.ts +135 -43
  109. package/src/extension/team-tool/workflow-manage.ts +92 -25
  110. package/src/extension/team-tool-types.ts +8 -1
  111. package/src/extension/team-tool.ts +142 -551
  112. package/src/extension/validate-resources.ts +39 -8
  113. package/src/hooks/registry.ts +66 -17
  114. package/src/hooks/types.ts +1 -1
  115. package/src/i18n.ts +25 -11
  116. package/src/observability/correlation.ts +17 -3
  117. package/src/observability/event-bus.ts +51 -56
  118. package/src/observability/event-to-metric.ts +117 -15
  119. package/src/observability/exporters/otlp-exporter.ts +56 -17
  120. package/src/observability/exporters/prometheus-exporter.ts +1 -1
  121. package/src/observability/metric-registry.ts +16 -4
  122. package/src/observability/metric-retention.ts +8 -2
  123. package/src/observability/metric-sink.ts +11 -3
  124. package/src/observability/metrics-primitives.ts +42 -9
  125. package/src/plugins/plugin-define.ts +2 -2
  126. package/src/plugins/plugin-registry.ts +25 -25
  127. package/src/plugins/plugins/index.ts +1 -1
  128. package/src/plugins/plugins/nextjs.ts +16 -16
  129. package/src/plugins/plugins/vite.ts +7 -11
  130. package/src/plugins/plugins/vitest.ts +6 -11
  131. package/src/runtime/adaptive-plan.ts +225 -40
  132. package/src/runtime/agent-control.ts +58 -15
  133. package/src/runtime/agent-memory.ts +15 -9
  134. package/src/runtime/agent-observability.ts +10 -2
  135. package/src/runtime/anchor-manager.ts +27 -25
  136. package/src/runtime/async-marker.ts +7 -1
  137. package/src/runtime/async-runner.ts +39 -24
  138. package/src/runtime/auto-summarize.ts +7 -13
  139. package/src/runtime/background-runner.ts +189 -251
  140. package/src/runtime/batch-barrier.ts +18 -16
  141. package/src/runtime/cancellation-token.ts +16 -6
  142. package/src/runtime/cancellation.ts +46 -8
  143. package/src/runtime/capability-inventory.ts +6 -4
  144. package/src/runtime/chain-parser.ts +44 -11
  145. package/src/runtime/chain-runner.ts +63 -69
  146. package/src/runtime/checkpoint.ts +12 -56
  147. package/src/runtime/child-pi.ts +344 -79
  148. package/src/runtime/coalesce-tasks.ts +268 -0
  149. package/src/runtime/code-summary.ts +71 -26
  150. package/src/runtime/compact-stages/index.ts +15 -5
  151. package/src/runtime/compact-stages/tail-capture-stage.ts +7 -2
  152. package/src/runtime/compact-stages/truncation-stage.ts +4 -1
  153. package/src/runtime/compaction-summary.ts +17 -10
  154. package/src/runtime/completion-guard.ts +33 -16
  155. package/src/runtime/crash-classification.ts +28 -7
  156. package/src/runtime/crash-recovery.ts +177 -37
  157. package/src/runtime/crew-agent-records.ts +145 -47
  158. package/src/runtime/crew-hooks.ts +9 -24
  159. package/src/runtime/cross-extension-rpc.ts +25 -23
  160. package/src/runtime/custom-tools/irc-tool.ts +43 -15
  161. package/src/runtime/custom-tools/submit-result-tool.ts +16 -5
  162. package/src/runtime/delivery-coordinator.ts +34 -7
  163. package/src/runtime/delta-conflict.ts +9 -21
  164. package/src/runtime/deterministic-ast.ts +1 -1
  165. package/src/runtime/diagnostic-export.ts +53 -20
  166. package/src/runtime/direct-run.ts +12 -2
  167. package/src/runtime/dwf-state-store.ts +1 -1
  168. package/src/runtime/dynamic-workflow-context.ts +187 -59
  169. package/src/runtime/dynamic-workflow-runner.ts +42 -20
  170. package/src/runtime/effectiveness.ts +16 -8
  171. package/src/runtime/errors/crew-errors.ts +7 -11
  172. package/src/runtime/event-stream-bridge.ts +9 -3
  173. package/src/runtime/foreground-control.ts +54 -14
  174. package/src/runtime/foreground-watchdog.ts +9 -6
  175. package/src/runtime/goal-achievement.ts +27 -10
  176. package/src/runtime/goal-evaluator.ts +54 -19
  177. package/src/runtime/goal-loop-runner.ts +280 -99
  178. package/src/runtime/goal-state-store.ts +27 -17
  179. package/src/runtime/green-contract.ts +11 -2
  180. package/src/runtime/group-join.ts +64 -31
  181. package/src/runtime/handoff-manager.ts +37 -42
  182. package/src/runtime/heartbeat-gradient.ts +10 -2
  183. package/src/runtime/heartbeat-watcher.ts +32 -6
  184. package/src/runtime/hidden-handoff.ts +13 -31
  185. package/src/runtime/important-line-classifier.ts +12 -2
  186. package/src/runtime/iteration-hooks.ts +25 -15
  187. package/src/runtime/live-agent-control.ts +55 -7
  188. package/src/runtime/live-agent-manager.ts +130 -27
  189. package/src/runtime/live-control-realtime.ts +23 -3
  190. package/src/runtime/live-irc.ts +4 -1
  191. package/src/runtime/live-session-health.ts +12 -4
  192. package/src/runtime/live-session-runtime.ts +379 -117
  193. package/src/runtime/manifest-cache.ts +28 -12
  194. package/src/runtime/mcp-proxy.ts +10 -18
  195. package/src/runtime/metric-parser.ts +1 -5
  196. package/src/runtime/model-fallback.ts +55 -18
  197. package/src/runtime/model-resolver.ts +2 -6
  198. package/src/runtime/model-scope.ts +19 -3
  199. package/src/runtime/notebook-helpers.ts +60 -62
  200. package/src/runtime/orphan-worker-registry.ts +37 -26
  201. package/src/runtime/output-validator.ts +18 -3
  202. package/src/runtime/overflow-recovery.ts +5 -4
  203. package/src/runtime/parallel-research.ts +29 -5
  204. package/src/runtime/parallel-utils.ts +9 -11
  205. package/src/runtime/path-overlap.ts +150 -0
  206. package/src/runtime/peer-dep.ts +12 -17
  207. package/src/runtime/per-write-validator.ts +1 -3
  208. package/src/runtime/phase-tracker.ts +342 -330
  209. package/src/runtime/pi-args.ts +26 -8
  210. package/src/runtime/pi-json-output.ts +1 -1
  211. package/src/runtime/pi-spawn.ts +30 -19
  212. package/src/runtime/pipeline-runner.ts +56 -55
  213. package/src/runtime/plan-templates.ts +5 -6
  214. package/src/runtime/policy-engine.ts +43 -7
  215. package/src/runtime/post-checks.ts +12 -4
  216. package/src/runtime/post-exit-stdio-guard.ts +2 -2
  217. package/src/runtime/process-lifecycle.ts +20 -10
  218. package/src/runtime/process-status.ts +16 -5
  219. package/src/runtime/progress-event-coalescer.ts +2 -1
  220. package/src/runtime/progress-tracker.ts +103 -103
  221. package/src/runtime/prose-compressor.ts +9 -11
  222. package/src/runtime/recovery-recipes.ts +118 -24
  223. package/src/runtime/replace.ts +25 -10
  224. package/src/runtime/resilient-edit.ts +10 -25
  225. package/src/runtime/result-extractor.ts +2 -6
  226. package/src/runtime/retry-executor.ts +20 -4
  227. package/src/runtime/retry-runner.ts +27 -51
  228. package/src/runtime/role-permission.ts +6 -1
  229. package/src/runtime/run-coalesced-task-group.ts +256 -0
  230. package/src/runtime/run-drift.ts +14 -15
  231. package/src/runtime/run-tracker.ts +6 -28
  232. package/src/runtime/runtime-policy.ts +1 -6
  233. package/src/runtime/runtime-resolver.ts +80 -15
  234. package/src/runtime/scheduler.ts +47 -18
  235. package/src/runtime/semaphore.ts +5 -7
  236. package/src/runtime/sensitive-paths.ts +2 -1
  237. package/src/runtime/session-usage.ts +1 -1
  238. package/src/runtime/settings-store.ts +16 -12
  239. package/src/runtime/sidechain-output.ts +6 -2
  240. package/src/runtime/single-agent-compose.ts +1 -4
  241. package/src/runtime/skill-effectiveness.ts +29 -97
  242. package/src/runtime/skill-instructions.ts +40 -83
  243. package/src/runtime/stale-reconciler.ts +73 -197
  244. package/src/runtime/stream-preview.ts +1 -1
  245. package/src/runtime/streaming-output.ts +1 -1
  246. package/src/runtime/subagent-manager.ts +44 -169
  247. package/src/runtime/subprocess-tool-registry.ts +4 -1
  248. package/src/runtime/supervisor-contact.ts +10 -5
  249. package/src/runtime/task-display.ts +19 -5
  250. package/src/runtime/task-graph-scheduler.ts +95 -21
  251. package/src/runtime/task-graph.ts +5 -11
  252. package/src/runtime/task-health.ts +54 -47
  253. package/src/runtime/task-id.ts +12 -19
  254. package/src/runtime/task-output-context.ts +265 -81
  255. package/src/runtime/task-packet.ts +12 -20
  256. package/src/runtime/task-quality.ts +6 -14
  257. package/src/runtime/task-runner/context-retrieval.ts +4 -13
  258. package/src/runtime/task-runner/live-executor.ts +114 -36
  259. package/src/runtime/task-runner/output-splitter.ts +152 -0
  260. package/src/runtime/task-runner/progress.ts +50 -12
  261. package/src/runtime/task-runner/prompt-builder.ts +31 -7
  262. package/src/runtime/task-runner/prompt-pipeline.ts +31 -7
  263. package/src/runtime/task-runner/result-utils.ts +3 -1
  264. package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
  265. package/src/runtime/task-runner/run-projection.ts +27 -8
  266. package/src/runtime/task-runner/state-helpers.ts +50 -14
  267. package/src/runtime/task-runner/tail-read.ts +2 -6
  268. package/src/runtime/task-runner.ts +180 -326
  269. package/src/runtime/team-runner-artifacts.ts +13 -0
  270. package/src/runtime/team-runner.ts +456 -974
  271. package/src/runtime/tool-output-pruner.ts +6 -9
  272. package/src/runtime/tool-progress.ts +11 -21
  273. package/src/runtime/verification-gates.ts +33 -24
  274. package/src/runtime/verification-integrity.ts +2 -7
  275. package/src/runtime/verification-worktree.ts +62 -12
  276. package/src/runtime/worker-heartbeat.ts +5 -1
  277. package/src/runtime/worker-startup.ts +29 -5
  278. package/src/runtime/workflow-state.ts +17 -9
  279. package/src/runtime/workspace-lock.ts +30 -35
  280. package/src/runtime/workspace-tree.ts +20 -32
  281. package/src/runtime/yield-handler.ts +43 -9
  282. package/src/runtime/zombie-scanner.ts +5 -4
  283. package/src/schema/config-schema.ts +266 -172
  284. package/src/schema/team-tool-schema.ts +29 -74
  285. package/src/schema/validation-types.ts +25 -17
  286. package/src/skills/discover-skills.ts +35 -10
  287. package/src/skills/skill-templates.ts +109 -27
  288. package/src/skills/validate.ts +26 -8
  289. package/src/state/active-run-registry.ts +87 -28
  290. package/src/state/artifact-store.ts +9 -5
  291. package/src/state/atomic-write-v2.ts +85 -63
  292. package/src/state/atomic-write.ts +106 -27
  293. package/src/state/blob-store.ts +47 -20
  294. package/src/state/contracts.ts +20 -5
  295. package/src/state/crew-init.ts +5 -22
  296. package/src/state/decision-ledger.ts +19 -73
  297. package/src/state/event-log-rotation.ts +41 -15
  298. package/src/state/event-log.ts +168 -53
  299. package/src/state/event-reconstructor.ts +11 -1
  300. package/src/state/gitignore-manager.ts +2 -8
  301. package/src/state/health-store.ts +57 -57
  302. package/src/state/hook-instinct-bridge.ts +1 -1
  303. package/src/state/hook-integrations.ts +1 -1
  304. package/src/state/instinct-store.ts +17 -5
  305. package/src/state/jsonl-writer.ts +1 -1
  306. package/src/state/locks.ts +23 -9
  307. package/src/state/mailbox.ts +151 -28
  308. package/src/state/observation-store.ts +20 -14
  309. package/src/state/run-cache.ts +142 -135
  310. package/src/state/run-graph.ts +6 -15
  311. package/src/state/run-metrics.ts +5 -18
  312. package/src/state/schedule.ts +15 -9
  313. package/src/state/state-store.ts +137 -47
  314. package/src/state/task-claims.ts +12 -2
  315. package/src/state/tiered-eval.ts +52 -43
  316. package/src/state/types-eval.ts +2 -2
  317. package/src/state/types.ts +24 -20
  318. package/src/state/usage.ts +20 -4
  319. package/src/state/worker-atomic-writer.ts +6 -3
  320. package/src/subagents/index.ts +2 -2
  321. package/src/teams/discover-teams.ts +21 -6
  322. package/src/tools/safe-bash-extension.ts +5 -6
  323. package/src/tools/safe-bash.ts +10 -11
  324. package/src/types/new-api-types.ts +6 -10
  325. package/src/ui/agent-management-overlay.ts +52 -40
  326. package/src/ui/card-colors.ts +13 -4
  327. package/src/ui/crew-footer.ts +8 -7
  328. package/src/ui/crew-select-list.ts +1 -1
  329. package/src/ui/dashboard-panes/agents-pane.ts +41 -25
  330. package/src/ui/dashboard-panes/cancellation-pane.ts +1 -1
  331. package/src/ui/dashboard-panes/capability-pane.ts +32 -15
  332. package/src/ui/dashboard-panes/health-pane.ts +2 -1
  333. package/src/ui/dashboard-panes/metrics-pane.ts +4 -1
  334. package/src/ui/dashboard-panes/progress-pane.ts +12 -9
  335. package/src/ui/heartbeat-aggregator.ts +15 -4
  336. package/src/ui/keybinding-map.ts +40 -7
  337. package/src/ui/live-conversation-overlay.ts +36 -20
  338. package/src/ui/live-duration.ts +1 -4
  339. package/src/ui/live-run-sidebar.ts +88 -25
  340. package/src/ui/loaders.ts +2 -8
  341. package/src/ui/mascot.ts +20 -36
  342. package/src/ui/overlays/agent-picker-overlay.ts +11 -3
  343. package/src/ui/overlays/confirm-overlay.ts +4 -2
  344. package/src/ui/overlays/help-overlay.ts +25 -14
  345. package/src/ui/overlays/mailbox-compose-overlay.ts +48 -11
  346. package/src/ui/overlays/mailbox-compose-preview.ts +20 -5
  347. package/src/ui/overlays/mailbox-detail-overlay.ts +27 -6
  348. package/src/ui/pi-ui-compat.ts +7 -7
  349. package/src/ui/powerbar-publisher.ts +120 -42
  350. package/src/ui/render-diff.ts +10 -3
  351. package/src/ui/render-scheduler.ts +12 -4
  352. package/src/ui/run-action-dispatcher.ts +81 -18
  353. package/src/ui/run-dashboard.ts +172 -76
  354. package/src/ui/run-event-bus.ts +59 -37
  355. package/src/ui/run-snapshot-cache.ts +276 -86
  356. package/src/ui/settings-overlay.ts +361 -74
  357. package/src/ui/status-colors.ts +12 -1
  358. package/src/ui/syntax-highlight.ts +1 -1
  359. package/src/ui/terminal-status.ts +1 -3
  360. package/src/ui/theme-adapter.ts +16 -14
  361. package/src/ui/theme-discovery.ts +13 -2
  362. package/src/ui/tool-progress-formatter.ts +7 -7
  363. package/src/ui/tool-render.ts +128 -56
  364. package/src/ui/tool-renderers/brief-mode.ts +45 -27
  365. package/src/ui/tool-renderers/index.ts +109 -43
  366. package/src/ui/transcript-cache.ts +32 -6
  367. package/src/ui/transcript-entries.ts +25 -23
  368. package/src/ui/transcript-viewer.ts +78 -29
  369. package/src/ui/widget/index.ts +99 -40
  370. package/src/ui/widget/widget-formatters.ts +13 -6
  371. package/src/ui/widget/widget-model.ts +19 -8
  372. package/src/ui/widget/widget-renderer.ts +23 -13
  373. package/src/ui/widget/widget-types.ts +1 -1
  374. package/src/utils/bm25-search.ts +199 -199
  375. package/src/utils/conflict-detect.ts +22 -21
  376. package/src/utils/env-filter.ts +14 -7
  377. package/src/utils/file-coalescer.ts +5 -1
  378. package/src/utils/fingerprint.ts +3 -6
  379. package/src/utils/frontmatter.ts +3 -1
  380. package/src/utils/fs-watch.ts +2 -6
  381. package/src/utils/gh-protocol.ts +119 -44
  382. package/src/utils/git.ts +13 -15
  383. package/src/utils/guards.ts +2 -5
  384. package/src/utils/ids.ts +9 -2
  385. package/src/utils/incremental-reader.ts +14 -3
  386. package/src/utils/internal-error.ts +2 -1
  387. package/src/utils/names.ts +12 -3
  388. package/src/utils/paths.ts +49 -5
  389. package/src/utils/project-detector.ts +2 -2
  390. package/src/utils/redaction.ts +29 -19
  391. package/src/utils/resolve-shell.ts +9 -7
  392. package/src/utils/run-watcher-registry.ts +19 -31
  393. package/src/utils/safe-paths.ts +46 -29
  394. package/src/utils/scan-cache.ts +9 -2
  395. package/src/utils/session-utils.ts +2 -4
  396. package/src/utils/sleep.ts +12 -5
  397. package/src/utils/sse-parser.ts +5 -17
  398. package/src/utils/visual.ts +52 -32
  399. package/src/workflows/discover-workflows.ts +41 -109
  400. package/src/workflows/intermediate-store.ts +5 -21
  401. package/src/workflows/preflight-validator.ts +6 -33
  402. package/src/workflows/topology-analyzer.ts +5 -21
  403. package/src/workflows/workflow-config.ts +7 -6
  404. package/src/worktree/branch-freshness.ts +66 -8
  405. package/src/worktree/cleanup.ts +130 -20
  406. package/src/worktree/worktree-manager.ts +212 -69
  407. package/skills/artifact-analysis-loop/SKILL.md +0 -303
  408. package/skills/detection-pipeline-design/SKILL.md +0 -286
  409. package/skills/hunting-investigation-loop/SKILL.md +0 -402
  410. package/skills/incident-playbook-construction/SKILL.md +0 -384
  411. package/skills/security-review/SKILL.md +0 -561
  412. package/skills/threat-hypothesis-framework/SKILL.md +0 -176
  413. package/skills/ui-render-performance/SKILL.md +0 -58
  414. /package/docs/{followup-review-round3-2026-05-12.md → archive/followup-review-round3-2026-05-12.md} +0 -0
  415. /package/docs/{followup-review-round4-2026-05-13.md → archive/followup-review-round4-2026-05-13.md} +0 -0
  416. /package/docs/{pi-crew-bugs.md → archive/pi-crew-bugs.md} +0 -0
  417. /package/docs/{pi-crew-test-final.md → archive/pi-crew-test-final.md} +0 -0
  418. /package/docs/{pi-crew-test-results.md → archive/pi-crew-test-results.md} +0 -0
  419. /package/docs/{pi-crew-test-round2.md → archive/pi-crew-test-round2.md} +0 -0
  420. /package/docs/{pi-crew-test-round4.md → archive/pi-crew-test-round4.md} +0 -0
  421. /package/docs/{pi-crew-test-round5.md → archive/pi-crew-test-round5.md} +0 -0
  422. /package/docs/{pi-crew-test-round6.md → archive/pi-crew-test-round6.md} +0 -0
  423. /package/docs/{pi-crew-v0.5.10-audit-fix-plan.md → archive/pi-crew-v0.5.10-audit-fix-plan.md} +0 -0
  424. /package/docs/{pi-crew-v0.5.11-audit-fix-plan.md → archive/pi-crew-v0.5.11-audit-fix-plan.md} +0 -0
  425. /package/docs/{pi-crew-v0.5.12-audit-fix-plan.md → archive/pi-crew-v0.5.12-audit-fix-plan.md} +0 -0
  426. /package/docs/{pi-crew-v0.5.13-audit-fix-plan.md → archive/pi-crew-v0.5.13-audit-fix-plan.md} +0 -0
  427. /package/docs/{pi-crew-v0.5.14-audit-fix-plan.md → archive/pi-crew-v0.5.14-audit-fix-plan.md} +0 -0
  428. /package/docs/{pi-crew-v0.5.16-audit-fix-plan.md → archive/pi-crew-v0.5.16-audit-fix-plan.md} +0 -0
  429. /package/docs/{pi-crew-v0.5.17-audit-fix-plan.md → archive/pi-crew-v0.5.17-audit-fix-plan.md} +0 -0
  430. /package/docs/{pi-crew-v0.5.5-audit-fix-plan.md → archive/pi-crew-v0.5.5-audit-fix-plan.md} +0 -0
  431. /package/docs/{pi-crew-v0.5.9-audit-fix-plan.md → archive/pi-crew-v0.5.9-audit-fix-plan.md} +0 -0
  432. /package/docs/{pi-mono-opportunities.md → archive/pi-mono-opportunities.md} +0 -0
  433. /package/docs/{pi-mono-review.md → archive/pi-mono-review.md} +0 -0
  434. /package/docs/{pi-subagent4-comparison.md → archive/pi-subagent4-comparison.md} +0 -0
  435. /package/docs/{pi-subagents3-deep-analysis.md → archive/pi-subagents3-deep-analysis.md} +0 -0
@@ -1,77 +1,76 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
- import { projectCrewRoot } from "../utils/paths.ts";
4
- import { allTeams, discoverTeams } from "../teams/discover-teams.ts";
5
3
  import type { TeamRunManifest } from "../state/types.ts";
4
+ import { allTeams, discoverTeams } from "../teams/discover-teams.ts";
5
+ import { projectCrewRoot } from "../utils/paths.ts";
6
6
 
7
7
  export interface OnboardingOptions {
8
- team?: string;
9
- limit?: number;
10
- cwd?: string;
8
+ team?: string;
9
+ limit?: number;
10
+ cwd?: string;
11
11
  }
12
12
 
13
13
  interface RunSummary {
14
- runId: string;
15
- status: string;
16
- goal: string;
17
- team: string;
18
- createdAt: string;
19
- completedAt?: string;
20
- taskCount: number;
14
+ runId: string;
15
+ status: string;
16
+ goal: string;
17
+ team: string;
18
+ createdAt: string;
19
+ completedAt?: string;
20
+ taskCount: number;
21
21
  }
22
22
 
23
23
  /**
24
24
  * Load run summaries from the state directory.
25
25
  */
26
26
  function loadRunSummaries(cwd: string, options: OnboardingOptions = {}): RunSummary[] {
27
- const crewRoot = projectCrewRoot(cwd);
28
- const runsRoot = path.join(crewRoot, "state", "runs");
29
-
30
- if (!fs.existsSync(runsRoot)) return [];
31
-
32
- const limit = options.limit ?? 5;
33
- const teamFilter = options.team;
34
-
35
- const entries = fs.readdirSync(runsRoot)
36
- .filter((e) => {
37
- try {
38
- return fs.statSync(path.join(runsRoot, e)).isDirectory();
39
- } catch {
40
- return false;
41
- }
42
- })
43
- .sort()
44
- .reverse()
45
- .slice(0, 100);
46
-
47
- const summaries: RunSummary[] = [];
48
-
49
- for (const runId of entries) {
50
- if (summaries.length >= limit) break;
51
-
52
- const manifestPath = path.join(runsRoot, runId, "manifest.json");
53
- if (!fs.existsSync(manifestPath)) continue;
54
-
55
- try {
56
- const raw = JSON.parse(fs.readFileSync(manifestPath, "utf-8")) as TeamRunManifest & { completedAt?: string };
57
-
58
- if (teamFilter && raw.team !== teamFilter) continue;
59
-
60
- summaries.push({
61
- runId,
62
- status: raw.status,
63
- goal: raw.goal ?? "",
64
- team: raw.team,
65
- createdAt: raw.createdAt,
66
- completedAt: raw.completedAt ?? raw.updatedAt,
67
- taskCount: 0, // tasks stored separately, not in manifest
68
- });
69
- } catch {
70
- continue;
71
- }
72
- }
73
-
74
- return summaries;
27
+ const crewRoot = projectCrewRoot(cwd);
28
+ const runsRoot = path.join(crewRoot, "state", "runs");
29
+
30
+ if (!fs.existsSync(runsRoot)) return [];
31
+
32
+ const limit = options.limit ?? 5;
33
+ const teamFilter = options.team;
34
+
35
+ const entries = fs
36
+ .readdirSync(runsRoot)
37
+ .filter((e) => {
38
+ try {
39
+ return fs.statSync(path.join(runsRoot, e)).isDirectory();
40
+ } catch {
41
+ return false;
42
+ }
43
+ })
44
+ .sort()
45
+ .reverse()
46
+ .slice(0, 100);
47
+
48
+ const summaries: RunSummary[] = [];
49
+
50
+ for (const runId of entries) {
51
+ if (summaries.length >= limit) break;
52
+
53
+ const manifestPath = path.join(runsRoot, runId, "manifest.json");
54
+ if (!fs.existsSync(manifestPath)) continue;
55
+
56
+ try {
57
+ const raw = JSON.parse(fs.readFileSync(manifestPath, "utf-8")) as TeamRunManifest & { completedAt?: string };
58
+
59
+ if (teamFilter && raw.team !== teamFilter) continue;
60
+
61
+ summaries.push({
62
+ runId,
63
+ status: raw.status,
64
+ goal: raw.goal ?? "",
65
+ team: raw.team,
66
+ createdAt: raw.createdAt,
67
+ completedAt: raw.completedAt ?? raw.updatedAt,
68
+ taskCount: 0, // tasks stored separately, not in manifest
69
+ });
70
+ } catch {}
71
+ }
72
+
73
+ return summaries;
75
74
  }
76
75
 
77
76
  /**
@@ -79,100 +78,100 @@ function loadRunSummaries(cwd: string, options: OnboardingOptions = {}): RunSumm
79
78
  * (e.g. legacy test runs) — returns "?" instead of "NaNm".
80
79
  */
81
80
  export function formatDuration(createdAt: string, completedAt?: string): string {
82
- const start = new Date(createdAt).getTime();
83
- const end = completedAt ? new Date(completedAt).getTime() : Date.now();
84
- if (!Number.isFinite(start) || !Number.isFinite(end) || end < start) return "?";
85
- const minutes = Math.round((end - start) / 1000 / 60);
86
- if (minutes < 1) return "<1m";
87
- if (minutes >= 60) return `${Math.round(minutes / 60)}h`;
88
- return `${minutes}m`;
81
+ const start = new Date(createdAt).getTime();
82
+ const end = completedAt ? new Date(completedAt).getTime() : Date.now();
83
+ if (!Number.isFinite(start) || !Number.isFinite(end) || end < start) return "?";
84
+ const minutes = Math.round((end - start) / 1000 / 60);
85
+ if (minutes < 1) return "<1m";
86
+ if (minutes >= 60) return `${Math.round(minutes / 60)}h`;
87
+ return `${minutes}m`;
89
88
  }
90
89
 
91
90
  /**
92
91
  * Build markdown onboarding guide for a team.
93
92
  */
94
93
  export function buildTeamOnboarding(team: string, cwd: string, options: OnboardingOptions = {}): string {
95
- const runs = loadRunSummaries(cwd, { ...options, team });
96
-
97
- const lines: string[] = [];
98
-
99
- // Header
100
- lines.push(`# Team: ${team}`);
101
- lines.push("");
102
- lines.push(`> Multi-agent ${team} team for pi-crew.`);
103
- lines.push("");
104
-
105
- // Overview stats
106
- const completed = runs.filter((r) => r.status === "completed");
107
- const failed = runs.filter((r) => r.status === "failed" || r.status === "cancelled");
108
-
109
- let avgDuration = 0;
110
- if (completed.length > 0) {
111
- const totalMs = completed.reduce((sum, r) => {
112
- const start = new Date(r.createdAt).getTime();
113
- const end = r.completedAt ? new Date(r.completedAt).getTime() : Date.now();
114
- return sum + (end - start);
115
- }, 0);
116
- avgDuration = totalMs / completed.length / 1000 / 60;
117
- }
118
-
119
- lines.push("## Overview");
120
- lines.push("");
121
- lines.push(`| Metric | Value |`);
122
- lines.push(`|--------|-------|`);
123
- lines.push(`| Total runs | ${runs.length} |`);
124
- lines.push(`| Completed | ${completed.length} |`);
125
- lines.push(`| Failed/Cancelled | ${failed.length} |`);
126
- if (avgDuration > 0) {
127
- lines.push(`| Avg duration | ${avgDuration.toFixed(1)} min |`);
128
- }
129
- lines.push("");
130
-
131
- // Past runs table
132
- if (runs.length > 0) {
133
- lines.push("## Past Runs");
134
- lines.push("");
135
- lines.push("| Run | Goal | Duration | Status |");
136
- lines.push("|-----|------|----------|--------|");
137
-
138
- for (const run of runs) {
139
- const duration = formatDuration(run.createdAt, run.completedAt);
140
- const goalPreview = run.goal ? run.goal.slice(0, 40) : "N/A";
141
- const goalSuffix = run.goal && run.goal.length > 40 ? "..." : "";
142
- const status = run.status ?? "unknown";
143
- const statusIcon = status === "completed" ? "✅" : status === "failed" ? "❌" : status === "cancelled" ? "⏹️" : "⚠️";
144
- lines.push(`| \`${run.runId.slice(-8)}\` | ${goalPreview}${goalSuffix} | ${duration} | ${statusIcon} ${status} |`);
145
- }
146
- lines.push("");
147
- }
148
-
149
- // How to run
150
- lines.push("## How to Run");
151
- lines.push("");
152
- lines.push("```bash");
153
- lines.push(`team action='run' team='${team}' goal="<your goal>"`);
154
- lines.push("```");
155
- lines.push("");
156
- lines.push("See `team action='help'` for more options.");
157
- lines.push("");
158
-
159
- // Teams
160
- lines.push("## Available Teams");
161
- lines.push("");
162
- try {
163
- const discovery = discoverTeams(cwd);
164
- const teams = allTeams(discovery);
165
- for (const t of teams) {
166
- lines.push(`- \`${t.name}\` — ${t.description ?? "No description"}`);
167
- }
168
- } catch {
169
- lines.push("- *(team discovery unavailable)*");
170
- }
171
- lines.push("");
172
-
173
- // Footer
174
- lines.push("---");
175
- lines.push("*Generated by pi-crew. For up-to-date info, check recent run history.*");
176
-
177
- return lines.join("\n");
94
+ const runs = loadRunSummaries(cwd, { ...options, team });
95
+
96
+ const lines: string[] = [];
97
+
98
+ // Header
99
+ lines.push(`# Team: ${team}`);
100
+ lines.push("");
101
+ lines.push(`> Multi-agent ${team} team for pi-crew.`);
102
+ lines.push("");
103
+
104
+ // Overview stats
105
+ const completed = runs.filter((r) => r.status === "completed");
106
+ const failed = runs.filter((r) => r.status === "failed" || r.status === "cancelled");
107
+
108
+ let avgDuration = 0;
109
+ if (completed.length > 0) {
110
+ const totalMs = completed.reduce((sum, r) => {
111
+ const start = new Date(r.createdAt).getTime();
112
+ const end = r.completedAt ? new Date(r.completedAt).getTime() : Date.now();
113
+ return sum + (end - start);
114
+ }, 0);
115
+ avgDuration = totalMs / completed.length / 1000 / 60;
116
+ }
117
+
118
+ lines.push("## Overview");
119
+ lines.push("");
120
+ lines.push(`| Metric | Value |`);
121
+ lines.push(`|--------|-------|`);
122
+ lines.push(`| Total runs | ${runs.length} |`);
123
+ lines.push(`| Completed | ${completed.length} |`);
124
+ lines.push(`| Failed/Cancelled | ${failed.length} |`);
125
+ if (avgDuration > 0) {
126
+ lines.push(`| Avg duration | ${avgDuration.toFixed(1)} min |`);
127
+ }
128
+ lines.push("");
129
+
130
+ // Past runs table
131
+ if (runs.length > 0) {
132
+ lines.push("## Past Runs");
133
+ lines.push("");
134
+ lines.push("| Run | Goal | Duration | Status |");
135
+ lines.push("|-----|------|----------|--------|");
136
+
137
+ for (const run of runs) {
138
+ const duration = formatDuration(run.createdAt, run.completedAt);
139
+ const goalPreview = run.goal ? run.goal.slice(0, 40) : "N/A";
140
+ const goalSuffix = run.goal && run.goal.length > 40 ? "..." : "";
141
+ const status = run.status ?? "unknown";
142
+ const statusIcon = status === "completed" ? "✅" : status === "failed" ? "❌" : status === "cancelled" ? "⏹️" : "⚠️";
143
+ lines.push(`| \`${run.runId.slice(-8)}\` | ${goalPreview}${goalSuffix} | ${duration} | ${statusIcon} ${status} |`);
144
+ }
145
+ lines.push("");
146
+ }
147
+
148
+ // How to run
149
+ lines.push("## How to Run");
150
+ lines.push("");
151
+ lines.push("```bash");
152
+ lines.push(`team action='run' team='${team}' goal="<your goal>"`);
153
+ lines.push("```");
154
+ lines.push("");
155
+ lines.push("See `team action='help'` for more options.");
156
+ lines.push("");
157
+
158
+ // Teams
159
+ lines.push("## Available Teams");
160
+ lines.push("");
161
+ try {
162
+ const discovery = discoverTeams(cwd);
163
+ const teams = allTeams(discovery);
164
+ for (const t of teams) {
165
+ lines.push(`- \`${t.name}\` — ${t.description ?? "No description"}`);
166
+ }
167
+ } catch {
168
+ lines.push("- *(team discovery unavailable)*");
169
+ }
170
+ lines.push("");
171
+
172
+ // Footer
173
+ lines.push("---");
174
+ lines.push("*Generated by pi-crew. For up-to-date info, check recent run history.*");
175
+
176
+ return lines.join("\n");
178
177
  }
@@ -1,7 +1,7 @@
1
- import { detectTeamIntent } from "./autonomous-policy.ts";
2
1
  import type { AgentConfig } from "../agents/agent-config.ts";
3
- import type { TeamConfig } from "../teams/team-config.ts";
4
2
  import type { PiTeamsAutonomousConfig } from "../config/config.ts";
3
+ import type { TeamConfig } from "../teams/team-config.ts";
4
+ import { detectTeamIntent } from "./autonomous-policy.ts";
5
5
 
6
6
  export type DecompositionStrategy = "numbered" | "bulleted" | "conjunction" | "atomic";
7
7
 
@@ -18,16 +18,61 @@ export interface TeamRecommendation {
18
18
  async: boolean;
19
19
  workspaceMode: "single" | "worktree";
20
20
  confidence: "low" | "medium" | "high";
21
- decomposition: { strategy: DecompositionStrategy; subtasks: RecommendedSubtask[]; fanout: number };
21
+ decomposition: {
22
+ strategy: DecompositionStrategy;
23
+ subtasks: RecommendedSubtask[];
24
+ fanout: number;
25
+ };
22
26
  reasons: string[];
23
27
  }
24
28
 
25
29
  const REVIEW_TERMS = ["review", "audit", "security", "vulnerability", "diff", "pr", "pull request"];
26
- const RESEARCH_TERMS = ["research", "investigate", "compare", "analyze", "document", "docs", "explain", "architecture", "đọc sâu", "source", "projects"];
30
+ const RESEARCH_TERMS = [
31
+ "research",
32
+ "investigate",
33
+ "compare",
34
+ "analyze",
35
+ "document",
36
+ "docs",
37
+ "explain",
38
+ "architecture",
39
+ "đọc sâu",
40
+ "source",
41
+ "projects",
42
+ ];
27
43
  const PARALLEL_RESEARCH_RE = /(?:đọc sâu|deep read|deep research|source audit|multiple projects|các project|pi-\*|source\/|@source)/i;
28
44
  const FAST_FIX_TERMS = ["quick fix", "fast-fix", "small bug", "typo", "one-line", "minor", "lint"];
29
- const IMPLEMENTATION_TERMS = ["implement", "refactor", "migrate", "feature", "tests", "test", "integration", "upgrade", "build", "create", "add", "fix", "update", "sửa", "thêm", "cập nhật", "kiểm thử"];
30
- const RISKY_TERMS = ["migration", "refactor", "large", "multiple", "parallel", "concurrent", "risky", "critical", "nhiều file", "nhiều task"];
45
+ const IMPLEMENTATION_TERMS = [
46
+ "implement",
47
+ "refactor",
48
+ "migrate",
49
+ "feature",
50
+ "tests",
51
+ "test",
52
+ "integration",
53
+ "upgrade",
54
+ "build",
55
+ "create",
56
+ "add",
57
+ "fix",
58
+ "update",
59
+ "sửa",
60
+ "thêm",
61
+ "cập nhật",
62
+ "kiểm thử",
63
+ ];
64
+ const RISKY_TERMS = [
65
+ "migration",
66
+ "refactor",
67
+ "large",
68
+ "multiple",
69
+ "parallel",
70
+ "concurrent",
71
+ "risky",
72
+ "critical",
73
+ "nhiều file",
74
+ "nhiều task",
75
+ ];
31
76
  const NUMBERED_LINE_RE = /^\s*\d+[.)]\s+(.+)$/;
32
77
  const BULLETED_LINE_RE = /^\s*[-*•]\s+(.+)$/;
33
78
  const CONJUNCTION_SPLIT_RE = /\s+(?:and|,\s*and|,)\s+/i;
@@ -58,8 +103,15 @@ function makeSubtask(text: string): RecommendedSubtask {
58
103
  return { subject, description: text.trim(), role: recommendRole(text) };
59
104
  }
60
105
 
61
- export function decomposeGoal(goal: string): { strategy: DecompositionStrategy; subtasks: RecommendedSubtask[]; fanout: number } {
62
- const lines = goal.split("\n").map((line) => line.trim()).filter(Boolean);
106
+ export function decomposeGoal(goal: string): {
107
+ strategy: DecompositionStrategy;
108
+ subtasks: RecommendedSubtask[];
109
+ fanout: number;
110
+ } {
111
+ const lines = goal
112
+ .split("\n")
113
+ .map((line) => line.trim())
114
+ .filter(Boolean);
63
115
  const fileRefs = goal.match(FILE_REF_RE)?.length ?? 0;
64
116
  const codeSymbols = goal.match(CODE_SYMBOL_RE)?.length ?? 0;
65
117
  const hasParallelKeyword = /\b(?:parallel|concurrently|simultaneously|independently)\b/i.test(goal);
@@ -78,10 +130,17 @@ export function decomposeGoal(goal: string): { strategy: DecompositionStrategy;
78
130
  return { strategy: "bulleted", subtasks, fanout: subtasks.length };
79
131
  }
80
132
  if (lines.length === 1) {
81
- const parts = lines[0].split(CONJUNCTION_SPLIT_RE).map((part) => part.trim()).filter(Boolean);
133
+ const parts = lines[0]
134
+ .split(CONJUNCTION_SPLIT_RE)
135
+ .map((part) => part.trim())
136
+ .filter(Boolean);
82
137
  if (parts.length >= 2) {
83
138
  const subtasks = parts.map((part) => makeSubtask(part));
84
- return { strategy: "conjunction", subtasks, fanout: subtasks.length };
139
+ return {
140
+ strategy: "conjunction",
141
+ subtasks,
142
+ fanout: subtasks.length,
143
+ };
85
144
  }
86
145
  }
87
146
  const subtask = makeSubtask(goal);
@@ -93,7 +152,11 @@ function metadataMatches(goal: string, values: string[] | undefined): string[] {
93
152
  return (values ?? []).filter((value) => lower.includes(value.toLowerCase()));
94
153
  }
95
154
 
96
- export function recommendTeam(goal: string, config: PiTeamsAutonomousConfig = {}, resources?: { teams?: TeamConfig[]; agents?: AgentConfig[] }): TeamRecommendation {
155
+ export function recommendTeam(
156
+ goal: string,
157
+ config: PiTeamsAutonomousConfig = {},
158
+ resources?: { teams?: TeamConfig[]; agents?: AgentConfig[] },
159
+ ): TeamRecommendation {
97
160
  const normalized = goal.toLowerCase();
98
161
  const intents = detectTeamIntent(goal, config);
99
162
  const decomposition = decomposeGoal(goal);
@@ -106,7 +169,10 @@ export function recommendTeam(goal: string, config: PiTeamsAutonomousConfig = {}
106
169
  if (intents.length > 0) reasons.push(`Matched explicit intent keyword(s): ${intents.join(", ")}.`);
107
170
 
108
171
  const metadataTeamMatches = (resources?.teams ?? [])
109
- .map((candidate) => ({ team: candidate, matches: [...metadataMatches(goal, candidate.routing?.triggers), ...metadataMatches(goal, candidate.routing?.useWhen)] }))
172
+ .map((candidate) => ({
173
+ team: candidate,
174
+ matches: [...metadataMatches(goal, candidate.routing?.triggers), ...metadataMatches(goal, candidate.routing?.useWhen)],
175
+ }))
110
176
  .filter((candidate) => candidate.matches.length > 0)
111
177
  .sort((a, b) => b.matches.length - a.matches.length);
112
178
 
@@ -120,13 +186,22 @@ export function recommendTeam(goal: string, config: PiTeamsAutonomousConfig = {}
120
186
  team = metadataTeamMatches[0].team.name as TeamRecommendation["team"];
121
187
  workflow = (metadataTeamMatches[0].team.defaultWorkflow ?? metadataTeamMatches[0].team.name) as TeamRecommendation["workflow"];
122
188
  confidence = "high";
123
- reasons.push(`Matched team routing metadata for '${metadataTeamMatches[0].team.name}': ${metadataTeamMatches[0].matches.join(", ")}.`);
189
+ reasons.push(
190
+ `Matched team routing metadata for '${metadataTeamMatches[0].team.name}': ${metadataTeamMatches[0].matches.join(", ")}.`,
191
+ );
124
192
  } else if (intents.includes("review") || reviewMatches.length >= 2 || normalized.includes("security review")) {
125
193
  team = "review";
126
194
  workflow = "review";
127
195
  confidence = "high";
128
196
  reasons.push(`Review/audit terms detected: ${reviewMatches.join(", ") || "explicit review intent"}.`);
129
- } else if (PARALLEL_RESEARCH_RE.test(goal) || (researchMatches.length >= 2 && (normalized.includes("multiple") || normalized.includes("source") || normalized.includes("project") || normalized.includes("pi-")))) {
197
+ } else if (
198
+ PARALLEL_RESEARCH_RE.test(goal) ||
199
+ (researchMatches.length >= 2 &&
200
+ (normalized.includes("multiple") ||
201
+ normalized.includes("source") ||
202
+ normalized.includes("project") ||
203
+ normalized.includes("pi-")))
204
+ ) {
130
205
  team = "parallel-research";
131
206
  workflow = "parallel-research";
132
207
  confidence = "high";
@@ -145,7 +220,9 @@ export function recommendTeam(goal: string, config: PiTeamsAutonomousConfig = {}
145
220
  team = "implementation";
146
221
  workflow = "implementation";
147
222
  confidence = "high";
148
- reasons.push(`Actionable multi-item task list detected (${decomposition.fanout} bullet${decomposition.fanout === 1 ? "" : "s"}); use coordinated implementation planning.`);
223
+ reasons.push(
224
+ `Actionable multi-item task list detected (${decomposition.fanout} bullet${decomposition.fanout === 1 ? "" : "s"}); use coordinated implementation planning.`,
225
+ );
149
226
  } else if (intents.includes("implementation") || implementationMatches.length > 0) {
150
227
  team = "implementation";
151
228
  workflow = "implementation";
@@ -157,14 +234,26 @@ export function recommendTeam(goal: string, config: PiTeamsAutonomousConfig = {}
157
234
  reasons.push("No strong team-specific intent detected; start with planning/default discovery.");
158
235
  }
159
236
 
160
-
161
- if (decomposition.strategy !== "atomic") reasons.push(`Goal decomposes into ${decomposition.subtasks.length} subtasks using ${decomposition.strategy} parsing.`);
162
- const async = config.preferAsyncForLongTasks === true && (wordCount(goal) > 24 || riskyMatches.length > 0 || implementationMatches.length >= 2 || decomposition.fanout >= 3);
163
- const workspaceMode = config.allowWorktreeSuggestion === false ? "single" : (riskyMatches.length > 0 && team === "implementation" ? "worktree" : "single");
237
+ if (decomposition.strategy !== "atomic")
238
+ reasons.push(`Goal decomposes into ${decomposition.subtasks.length} subtasks using ${decomposition.strategy} parsing.`);
239
+ const async =
240
+ config.preferAsyncForLongTasks === true &&
241
+ (wordCount(goal) > 24 || riskyMatches.length > 0 || implementationMatches.length >= 2 || decomposition.fanout >= 3);
242
+ const workspaceMode =
243
+ config.allowWorktreeSuggestion === false ? "single" : riskyMatches.length > 0 && team === "implementation" ? "worktree" : "single";
164
244
  if (async) reasons.push("Task appears long/risky and config prefers async for long tasks.");
165
245
  if (workspaceMode === "worktree") reasons.push(`Risk/isolation terms detected: ${riskyMatches.join(", ")}.`);
166
246
 
167
- return { team, workflow, action, async, workspaceMode, confidence, decomposition, reasons };
247
+ return {
248
+ team,
249
+ workflow,
250
+ action,
251
+ async,
252
+ workspaceMode,
253
+ confidence,
254
+ decomposition,
255
+ reasons,
256
+ };
168
257
  }
169
258
 
170
259
  export function formatRecommendation(goal: string, recommendation: TeamRecommendation): string {
@@ -183,6 +272,17 @@ export function formatRecommendation(goal: string, recommendation: TeamRecommend
183
272
  "Reasons:",
184
273
  ...recommendation.reasons.map((reason) => `- ${reason}`),
185
274
  "Suggested tool call:",
186
- JSON.stringify({ action: recommendation.action, team: recommendation.team, workflow: recommendation.workflow, goal, async: recommendation.async, workspaceMode: recommendation.workspaceMode }, null, 2),
275
+ JSON.stringify(
276
+ {
277
+ action: recommendation.action,
278
+ team: recommendation.team,
279
+ workflow: recommendation.workflow,
280
+ goal,
281
+ async: recommendation.async,
282
+ workspaceMode: recommendation.workspaceMode,
283
+ },
284
+ null,
285
+ 2,
286
+ ),
187
287
  ].join("\n");
188
288
  }