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,11 +1,7 @@
1
1
  import * as crypto from "node:crypto";
2
2
  import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
- import type {
5
- AgentConfig,
6
- ResourceSource,
7
- RoutingMetadata,
8
- } from "../agents/agent-config.ts";
4
+ import type { AgentConfig, ResourceSource, RoutingMetadata } from "../agents/agent-config.ts";
9
5
  import { serializeAgent } from "../agents/agent-serializer.ts";
10
6
  import { discoverAgents } from "../agents/discover-agents.ts";
11
7
  import type { PiTeamsConfig } from "../config/config.ts";
@@ -13,21 +9,10 @@ import type { TeamToolParamsValue } from "../schema/team-tool-schema.ts";
13
9
  import { allTeams, discoverTeams } from "../teams/discover-teams.ts";
14
10
  import type { TeamConfig, TeamRole } from "../teams/team-config.ts";
15
11
  import { serializeTeam } from "../teams/team-serializer.ts";
16
- import {
17
- hasOwn,
18
- parseConfigObject,
19
- requireString,
20
- sanitizeName,
21
- } from "../utils/names.ts";
12
+ import { hasOwn, parseConfigObject, requireString, sanitizeName } from "../utils/names.ts";
22
13
  import { projectCrewRoot, userPiRoot } from "../utils/paths.ts";
23
- import {
24
- allWorkflows,
25
- discoverWorkflows,
26
- } from "../workflows/discover-workflows.ts";
27
- import type {
28
- WorkflowConfig,
29
- WorkflowStep,
30
- } from "../workflows/workflow-config.ts";
14
+ import { allWorkflows, discoverWorkflows } from "../workflows/discover-workflows.ts";
15
+ import type { WorkflowConfig, WorkflowStep } from "../workflows/workflow-config.ts";
31
16
  import { serializeWorkflow } from "../workflows/workflow-serializer.ts";
32
17
  import { enforceDestructiveIntent } from "./team-tool/intent-policy.ts";
33
18
  import type { TeamToolDetails } from "./team-tool-types.ts";
@@ -42,19 +27,11 @@ type MutableSource = "user" | "project";
42
27
 
43
28
  type MutableResource = AgentConfig | TeamConfig | WorkflowConfig;
44
29
 
45
- function result(
46
- text: string,
47
- status: TeamToolDetails["status"] = "ok",
48
- isError = false,
49
- ): PiTeamsToolResult {
30
+ function result(text: string, status: TeamToolDetails["status"] = "ok", isError = false): PiTeamsToolResult {
50
31
  return toolResult(text, { action: "management", status }, isError);
51
32
  }
52
33
 
53
- function scopeDir(
54
- ctx: ManagementContext,
55
- resource: "agent" | "team" | "workflow",
56
- scope: MutableSource,
57
- ): string {
34
+ function scopeDir(ctx: ManagementContext, resource: "agent" | "team" | "workflow", scope: MutableSource): string {
58
35
  const base = scope === "user" ? userPiRoot() : projectCrewRoot(ctx.cwd);
59
36
  if (resource === "agent") return path.join(base, "agents");
60
37
  if (resource === "team") return path.join(base, "teams");
@@ -77,16 +54,8 @@ function backupFile(filePath: string): string {
77
54
  return backupPath;
78
55
  }
79
56
 
80
- function targetPath(
81
- ctx: ManagementContext,
82
- resource: "agent" | "team" | "workflow",
83
- scope: MutableSource,
84
- name: string,
85
- ): string {
86
- return path.join(
87
- scopeDir(ctx, resource, scope),
88
- `${name}${extensionFor(resource)}`,
89
- );
57
+ function targetPath(ctx: ManagementContext, resource: "agent" | "team" | "workflow", scope: MutableSource, name: string): string {
58
+ return path.join(scopeDir(ctx, resource, scope), `${name}${extensionFor(resource)}`);
90
59
  }
91
60
 
92
61
  function parseStringArray(value: unknown): string[] | undefined {
@@ -96,58 +65,31 @@ function parseStringArray(value: unknown): string[] | undefined {
96
65
  .map((entry) => entry.trim())
97
66
  .filter(Boolean);
98
67
  if (Array.isArray(value))
99
- return value
100
- .filter(
101
- (entry): entry is string =>
102
- typeof entry === "string" && entry.trim().length > 0,
103
- )
104
- .map((entry) => entry.trim());
68
+ return value.filter((entry): entry is string => typeof entry === "string" && entry.trim().length > 0).map((entry) => entry.trim());
105
69
  return undefined;
106
70
  }
107
71
 
108
- function parseRouting(
109
- value: Record<string, unknown>,
110
- fallback?: RoutingMetadata,
111
- ): RoutingMetadata | undefined {
72
+ function parseRouting(value: Record<string, unknown>, fallback?: RoutingMetadata): RoutingMetadata | undefined {
112
73
  const routing = {
113
- triggers: hasOwn(value, "triggers")
114
- ? parseStringArray(value.triggers)
115
- : fallback?.triggers,
116
- useWhen: hasOwn(value, "useWhen")
117
- ? parseStringArray(value.useWhen)
118
- : fallback?.useWhen,
119
- avoidWhen: hasOwn(value, "avoidWhen")
120
- ? parseStringArray(value.avoidWhen)
121
- : fallback?.avoidWhen,
122
- cost:
123
- value.cost === "free" ||
124
- value.cost === "cheap" ||
125
- value.cost === "expensive"
126
- ? value.cost
127
- : fallback?.cost,
74
+ triggers: hasOwn(value, "triggers") ? parseStringArray(value.triggers) : fallback?.triggers,
75
+ useWhen: hasOwn(value, "useWhen") ? parseStringArray(value.useWhen) : fallback?.useWhen,
76
+ avoidWhen: hasOwn(value, "avoidWhen") ? parseStringArray(value.avoidWhen) : fallback?.avoidWhen,
77
+ cost: value.cost === "free" || value.cost === "cheap" || value.cost === "expensive" ? value.cost : fallback?.cost,
128
78
  category: hasOwn(value, "category")
129
79
  ? typeof value.category === "string" && value.category.trim()
130
80
  ? value.category.trim()
131
81
  : undefined
132
82
  : fallback?.category,
133
83
  };
134
- return routing.triggers ||
135
- routing.useWhen ||
136
- routing.avoidWhen ||
137
- routing.cost ||
138
- routing.category
139
- ? routing
140
- : undefined;
84
+ return routing.triggers || routing.useWhen || routing.avoidWhen || routing.cost || routing.category ? routing : undefined;
141
85
  }
142
86
 
143
87
  function parseRoles(value: unknown): { roles?: TeamRole[]; error?: string } {
144
- if (!Array.isArray(value) || value.length === 0)
145
- return { error: "config.roles must be a non-empty array." };
88
+ if (!Array.isArray(value) || value.length === 0) return { error: "config.roles must be a non-empty array." };
146
89
  const roles: TeamRole[] = [];
147
90
  for (let i = 0; i < value.length; i++) {
148
91
  const item = value[i];
149
- if (!item || typeof item !== "object" || Array.isArray(item))
150
- return { error: `config.roles[${i}] must be an object.` };
92
+ if (!item || typeof item !== "object" || Array.isArray(item)) return { error: `config.roles[${i}] must be an object.` };
151
93
  const obj = item as Record<string, unknown>;
152
94
  const name = requireString(obj.name, `config.roles[${i}].name`);
153
95
  if (name.error) return { error: name.error };
@@ -156,15 +98,10 @@ function parseRoles(value: unknown): { roles?: TeamRole[]; error?: string } {
156
98
  roles.push({
157
99
  name: sanitizeName(name.value!),
158
100
  agent: sanitizeName(agent.value!),
159
- description:
160
- typeof obj.description === "string"
161
- ? obj.description.trim()
162
- : undefined,
101
+ description: typeof obj.description === "string" ? obj.description.trim() : undefined,
163
102
  model: typeof obj.model === "string" ? obj.model.trim() : undefined,
164
103
  maxConcurrency:
165
- typeof obj.maxConcurrency === "number" &&
166
- Number.isInteger(obj.maxConcurrency) &&
167
- obj.maxConcurrency > 0
104
+ typeof obj.maxConcurrency === "number" && Number.isInteger(obj.maxConcurrency) && obj.maxConcurrency > 0
168
105
  ? obj.maxConcurrency
169
106
  : undefined,
170
107
  });
@@ -176,13 +113,11 @@ function parseSteps(value: unknown): {
176
113
  steps?: WorkflowStep[];
177
114
  error?: string;
178
115
  } {
179
- if (!Array.isArray(value) || value.length === 0)
180
- return { error: "config.steps must be a non-empty array." };
116
+ if (!Array.isArray(value) || value.length === 0) return { error: "config.steps must be a non-empty array." };
181
117
  const steps: WorkflowStep[] = [];
182
118
  for (let i = 0; i < value.length; i++) {
183
119
  const item = value[i];
184
- if (!item || typeof item !== "object" || Array.isArray(item))
185
- return { error: `config.steps[${i}] must be an object.` };
120
+ if (!item || typeof item !== "object" || Array.isArray(item)) return { error: `config.steps[${i}] must be an object.` };
186
121
  const obj = item as Record<string, unknown>;
187
122
  const id = requireString(obj.id, `config.steps[${i}].id`);
188
123
  if (id.error) return { error: id.error };
@@ -205,23 +140,13 @@ function parseSteps(value: unknown): {
205
140
  role: sanitizeName(role.value!),
206
141
  task,
207
142
  dependsOn: parseStringArray(obj.dependsOn),
208
- parallelGroup:
209
- typeof obj.parallelGroup === "string"
210
- ? obj.parallelGroup.trim()
211
- : undefined,
212
- output:
213
- obj.output === false
214
- ? false
215
- : typeof obj.output === "string"
216
- ? obj.output.trim()
217
- : undefined,
143
+ parallelGroup: typeof obj.parallelGroup === "string" ? obj.parallelGroup.trim() : undefined,
144
+ output: obj.output === false ? false : typeof obj.output === "string" ? obj.output.trim() : undefined,
218
145
  reads: obj.reads === false ? false : parseStringArray(obj.reads),
219
146
  model: typeof obj.model === "string" ? obj.model.trim() : undefined,
220
147
  skills: obj.skills === false ? false : parseStringArray(obj.skills),
221
- progress:
222
- typeof obj.progress === "boolean" ? obj.progress : undefined,
223
- worktree:
224
- typeof obj.worktree === "boolean" ? obj.worktree : undefined,
148
+ progress: typeof obj.progress === "boolean" ? obj.progress : undefined,
149
+ worktree: typeof obj.worktree === "boolean" ? obj.worktree : undefined,
225
150
  verify: typeof obj.verify === "boolean" ? obj.verify : undefined,
226
151
  });
227
152
  }
@@ -229,75 +154,49 @@ function parseSteps(value: unknown): {
229
154
  }
230
155
 
231
156
  function parseWorkflowMaxConcurrency(value: unknown): number | undefined {
232
- if (typeof value !== "number" || !Number.isInteger(value) || value < 1)
233
- return undefined;
157
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 1) return undefined;
234
158
  return value;
235
159
  }
236
160
 
237
- function findResource(
238
- ctx: ManagementContext,
239
- resource: "agent" | "team" | "workflow",
240
- name: string,
241
- scope?: string,
242
- ): MutableResource[] {
161
+ function findResource(ctx: ManagementContext, resource: "agent" | "team" | "workflow", name: string, scope?: string): MutableResource[] {
243
162
  const normalized = sanitizeName(name);
244
163
  const sourceMatches = (item: { name: string; source: ResourceSource }) =>
245
- (scope === "user" || scope === "project"
246
- ? item.source === scope
247
- : item.source !== "builtin") && item.name === normalized;
164
+ (scope === "user" || scope === "project" ? item.source === scope : item.source !== "builtin") && item.name === normalized;
248
165
  // Search in the correct scope array directly to avoid allAgents shadowing issue.
249
166
  if (resource === "agent") {
250
167
  const discovery = discoverAgents(ctx.cwd);
251
168
  const pool =
252
- scope === "user"
253
- ? discovery.user
254
- : scope === "project"
255
- ? discovery.project
256
- : [...discovery.builtin, ...discovery.user];
169
+ scope === "user" ? discovery.user : scope === "project" ? discovery.project : [...discovery.builtin, ...discovery.user];
257
170
  return pool.filter(sourceMatches);
258
171
  }
259
172
  if (resource === "team") {
260
173
  const discovery = discoverTeams(ctx.cwd);
261
174
  const pool =
262
- scope === "user"
263
- ? discovery.user
264
- : scope === "project"
265
- ? discovery.project
266
- : [...discovery.builtin, ...discovery.user];
175
+ scope === "user" ? discovery.user : scope === "project" ? discovery.project : [...discovery.builtin, ...discovery.user];
267
176
  return pool.filter(sourceMatches);
268
177
  }
269
178
  {
270
179
  const discovery = discoverWorkflows(ctx.cwd);
271
180
  const pool =
272
- scope === "user"
273
- ? discovery.user
274
- : scope === "project"
275
- ? discovery.project
276
- : [...discovery.builtin, ...discovery.user];
181
+ scope === "user" ? discovery.user : scope === "project" ? discovery.project : [...discovery.builtin, ...discovery.user];
277
182
  return pool.filter(sourceMatches);
278
183
  }
279
184
  }
280
185
 
281
186
  // Note: only checks agent→team references and defaultWorkflow. Does not detect
282
187
  // workflow-step→agent/team references or team name in workflow metadata.
283
- function findReferences(
284
- ctx: ManagementContext,
285
- resource: "agent" | "team" | "workflow",
286
- name: string,
287
- ): string[] {
188
+ function findReferences(ctx: ManagementContext, resource: "agent" | "team" | "workflow", name: string): string[] {
288
189
  const refs: string[] = [];
289
190
  if (resource === "agent") {
290
191
  for (const team of allTeams(discoverTeams(ctx.cwd))) {
291
192
  for (const role of team.roles) {
292
- if (role.agent === name)
293
- refs.push(`team '${team.name}' role '${role.name}'`);
193
+ if (role.agent === name) refs.push(`team '${team.name}' role '${role.name}'`);
294
194
  }
295
195
  }
296
196
  }
297
197
  if (resource === "workflow") {
298
198
  for (const team of allTeams(discoverTeams(ctx.cwd))) {
299
- if (team.defaultWorkflow === name)
300
- refs.push(`team '${team.name}' defaultWorkflow`);
199
+ if (team.defaultWorkflow === name) refs.push(`team '${team.name}' defaultWorkflow`);
301
200
  }
302
201
  }
303
202
  return refs;
@@ -332,18 +231,12 @@ function updateReferencesForRename(
332
231
  if (oldName === newName) return [];
333
232
  if (resource !== "agent" && resource !== "workflow") return [];
334
233
  const changed: string[] = [];
335
- for (const team of allTeams(discoverTeams(ctx.cwd)).filter(
336
- (candidate) => candidate.source === scope,
337
- )) {
234
+ for (const team of allTeams(discoverTeams(ctx.cwd)).filter((candidate) => candidate.source === scope)) {
338
235
  let updated = false;
339
236
  let nextTeam = team;
340
237
  if (resource === "agent") {
341
- const roles = team.roles.map((role) =>
342
- role.agent === oldName ? { ...role, agent: newName } : role,
343
- );
344
- updated = roles.some(
345
- (role, index) => role.agent !== team.roles[index]!.agent,
346
- );
238
+ const roles = team.roles.map((role) => (role.agent === oldName ? { ...role, agent: newName } : role));
239
+ updated = roles.some((role, index) => role.agent !== team.roles[index]!.agent);
347
240
  nextTeam = { ...team, roles };
348
241
  }
349
242
  if (resource === "workflow" && team.defaultWorkflow === oldName) {
@@ -359,9 +252,7 @@ function updateReferencesForRename(
359
252
  }
360
253
  // L12 fix: also update workflow step role references when renaming agents.
361
254
  // Workflow files use `role:` to reference agent roles, not agent names.
362
- for (const workflow of allWorkflows(discoverWorkflows(ctx.cwd)).filter(
363
- (w) => w.source === scope,
364
- )) {
255
+ for (const workflow of allWorkflows(discoverWorkflows(ctx.cwd)).filter((w) => w.source === scope)) {
365
256
  let updated = false;
366
257
  const newSteps = workflow.steps.map((step) => {
367
258
  if (step.role === oldName) {
@@ -374,28 +265,16 @@ function updateReferencesForRename(
374
265
  changed.push(workflow.filePath);
375
266
  if (!dryRun) {
376
267
  backupFile(workflow.filePath);
377
- fs.writeFileSync(
378
- workflow.filePath,
379
- serializeWorkflow({ ...workflow, steps: newSteps }),
380
- "utf-8",
381
- );
268
+ fs.writeFileSync(workflow.filePath, serializeWorkflow({ ...workflow, steps: newSteps }), "utf-8");
382
269
  }
383
270
  }
384
271
  // L12 fix: update agent references in test fixtures.
385
- const testDir =
386
- scope === "user"
387
- ? path.join(projectCrewRoot(ctx.cwd), "test")
388
- : path.join(ctx.cwd, "test", "fixtures");
272
+ const testDir = scope === "user" ? path.join(projectCrewRoot(ctx.cwd), "test") : path.join(ctx.cwd, "test", "fixtures");
389
273
  if (fs.existsSync(testDir)) {
390
274
  for (const fixture of walkTsFiles(testDir)) {
391
275
  const content = fs.readFileSync(fixture, "utf-8");
392
276
  if (!content.includes(oldName)) continue;
393
- const agentPattern = new RegExp(
394
- "([\"'\\`]agent[=\"':\\s]*)" +
395
- escapeRegex(oldName) +
396
- "([\"'\\`]|\\s)",
397
- "g",
398
- );
277
+ const agentPattern = new RegExp("([\"'\\`]agent[=\"':\\s]*)" + escapeRegex(oldName) + "([\"'\\`]|\\s)", "g");
399
278
  const newContent = content.replace(agentPattern, `$1${newName}$2`);
400
279
  if (newContent !== content) {
401
280
  changed.push(fixture);
@@ -408,80 +287,42 @@ function updateReferencesForRename(
408
287
  return changed;
409
288
  }
410
289
 
411
- function resolveMutable(
412
- ctx: ManagementContext,
413
- params: TeamToolParamsValue,
414
- ): { resource?: MutableResource; error?: PiTeamsToolResult } {
290
+ function resolveMutable(ctx: ManagementContext, params: TeamToolParamsValue): { resource?: MutableResource; error?: PiTeamsToolResult } {
415
291
  if (!params.resource)
416
292
  return {
417
- error: result(
418
- "resource is required for update/delete.",
419
- "error",
420
- true,
421
- ),
293
+ error: result("resource is required for update/delete.", "error", true),
422
294
  };
423
- const name =
424
- params.resource === "agent"
425
- ? params.agent
426
- : params.resource === "team"
427
- ? params.team
428
- : params.workflow;
295
+ const name = params.resource === "agent" ? params.agent : params.resource === "team" ? params.team : params.workflow;
429
296
  if (!name)
430
297
  return {
431
- error: result(
432
- `${params.resource} name is required.`,
433
- "error",
434
- true,
435
- ),
298
+ error: result(`${params.resource} name is required.`, "error", true),
436
299
  };
437
300
  const matches = findResource(ctx, params.resource, name, params.scope);
438
301
  if (matches.length === 0)
439
302
  return {
440
- error: result(
441
- `${params.resource} '${name}' not found in mutable user/project scopes.`,
442
- "error",
443
- true,
444
- ),
303
+ error: result(`${params.resource} '${name}' not found in mutable user/project scopes.`, "error", true),
445
304
  };
446
305
  if (matches.length > 1)
447
306
  return {
448
- error: result(
449
- `${params.resource} '${name}' exists in multiple scopes. Specify scope: 'user' or 'project'.`,
450
- "error",
451
- true,
452
- ),
307
+ error: result(`${params.resource} '${name}' exists in multiple scopes. Specify scope: 'user' or 'project'.`, "error", true),
453
308
  };
454
309
  return { resource: matches[0] };
455
310
  }
456
311
 
457
- export function handleCreate(
458
- params: TeamToolParamsValue,
459
- ctx: ManagementContext,
460
- ): PiTeamsToolResult {
461
- if (!params.resource)
462
- return result("resource is required for create.", "error", true);
312
+ export function handleCreate(params: TeamToolParamsValue, ctx: ManagementContext): PiTeamsToolResult {
313
+ if (!params.resource) return result("resource is required for create.", "error", true);
463
314
  const parsed = parseConfigObject(params.config);
464
315
  if (parsed.error) return result(parsed.error, "error", true);
465
316
  const cfg = parsed.value!;
466
317
  const nameValue = requireString(cfg.name, "config.name");
467
318
  if (nameValue.error) return result(nameValue.error, "error", true);
468
- const descriptionValue = requireString(
469
- cfg.description,
470
- "config.description",
471
- );
472
- if (descriptionValue.error)
473
- return result(descriptionValue.error, "error", true);
319
+ const descriptionValue = requireString(cfg.description, "config.description");
320
+ if (descriptionValue.error) return result(descriptionValue.error, "error", true);
474
321
  const name = sanitizeName(nameValue.value!);
475
- if (!name)
476
- return result(
477
- "config.name is invalid after sanitization.",
478
- "error",
479
- true,
480
- );
322
+ if (!name) return result("config.name is invalid after sanitization.", "error", true);
481
323
  const scope = cfg.scope === "project" ? "project" : "user";
482
324
  const filePath = targetPath(ctx, params.resource, scope, name);
483
- if (fs.existsSync(filePath))
484
- return result(`File already exists: ${filePath}`, "error", true);
325
+ if (fs.existsSync(filePath)) return result(`File already exists: ${filePath}`, "error", true);
485
326
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
486
327
 
487
328
  let content: string;
@@ -491,19 +332,14 @@ export function handleCreate(
491
332
  description: descriptionValue.value!,
492
333
  source: scope,
493
334
  filePath,
494
- systemPrompt:
495
- typeof cfg.systemPrompt === "string" ? cfg.systemPrompt : "",
335
+ systemPrompt: typeof cfg.systemPrompt === "string" ? cfg.systemPrompt : "",
496
336
  model: typeof cfg.model === "string" ? cfg.model : undefined,
497
337
  fallbackModels: parseStringArray(cfg.fallbackModels),
498
- thinking:
499
- typeof cfg.thinking === "string" ? cfg.thinking : undefined,
338
+ thinking: typeof cfg.thinking === "string" ? cfg.thinking : undefined,
500
339
  tools: parseStringArray(cfg.tools),
501
- extensions: hasOwn(cfg, "extensions")
502
- ? (parseStringArray(cfg.extensions) ?? [])
503
- : undefined,
340
+ extensions: hasOwn(cfg, "extensions") ? (parseStringArray(cfg.extensions) ?? []) : undefined,
504
341
  skills: parseStringArray(cfg.skills),
505
- systemPromptMode:
506
- cfg.systemPromptMode === "append" ? "append" : "replace",
342
+ systemPromptMode: cfg.systemPromptMode === "append" ? "append" : "replace",
507
343
  inheritProjectContext: cfg.inheritProjectContext === true,
508
344
  inheritSkills: cfg.inheritSkills === true,
509
345
  routing: parseRouting(cfg),
@@ -518,16 +354,10 @@ export function handleCreate(
518
354
  source: scope,
519
355
  filePath,
520
356
  roles: parsedRoles.roles!,
521
- defaultWorkflow:
522
- typeof cfg.defaultWorkflow === "string"
523
- ? sanitizeName(cfg.defaultWorkflow)
524
- : undefined,
525
- workspaceMode:
526
- cfg.workspaceMode === "worktree" ? "worktree" : "single",
357
+ defaultWorkflow: typeof cfg.defaultWorkflow === "string" ? sanitizeName(cfg.defaultWorkflow) : undefined,
358
+ workspaceMode: cfg.workspaceMode === "worktree" ? "worktree" : "single",
527
359
  maxConcurrency:
528
- typeof cfg.maxConcurrency === "number" &&
529
- Number.isInteger(cfg.maxConcurrency) &&
530
- cfg.maxConcurrency > 0
360
+ typeof cfg.maxConcurrency === "number" && Number.isInteger(cfg.maxConcurrency) && cfg.maxConcurrency > 0
531
361
  ? cfg.maxConcurrency
532
362
  : undefined,
533
363
  routing: parseRouting(cfg),
@@ -545,10 +375,7 @@ export function handleCreate(
545
375
  });
546
376
  }
547
377
 
548
- if (params.dryRun)
549
- return result(
550
- `[dry-run] Would create ${params.resource} '${name}' at ${filePath}:\n\n${content}`,
551
- );
378
+ if (params.dryRun) return result(`[dry-run] Would create ${params.resource} '${name}' at ${filePath}:\n\n${content}`);
552
379
  try {
553
380
  fs.writeFileSync(filePath, content, "utf-8");
554
381
  } catch (writeError) {
@@ -561,29 +388,18 @@ export function handleCreate(
561
388
  return result(`Created ${params.resource} '${name}' at ${filePath}.`);
562
389
  }
563
390
 
564
- export function handleUpdate(
565
- params: TeamToolParamsValue,
566
- ctx: ManagementContext,
567
- ): PiTeamsToolResult {
391
+ export function handleUpdate(params: TeamToolParamsValue, ctx: ManagementContext): PiTeamsToolResult {
568
392
  const resolved = resolveMutable(ctx, params);
569
393
  if (resolved.error) return resolved.error;
570
394
  const parsed = parseConfigObject(params.config);
571
395
  if (parsed.error) return result(parsed.error, "error", true);
572
396
  const cfg = parsed.value!;
573
397
  const current = resolved.resource!;
574
- const nextName = hasOwn(cfg, "name")
575
- ? sanitizeName(String(cfg.name ?? ""))
576
- : current.name;
577
- if (!nextName)
578
- return result(
579
- "config.name is invalid after sanitization.",
580
- "error",
581
- true,
582
- );
398
+ const nextName = hasOwn(cfg, "name") ? sanitizeName(String(cfg.name ?? "")) : current.name;
399
+ if (!nextName) return result("config.name is invalid after sanitization.", "error", true);
583
400
  const source = current.source === "project" ? "project" : "user";
584
401
  const nextPath = targetPath(ctx, params.resource!, source, nextName);
585
- if (nextPath !== current.filePath && fs.existsSync(nextPath))
586
- return result(`Target file already exists: ${nextPath}`, "error", true);
402
+ if (nextPath !== current.filePath && fs.existsSync(nextPath)) return result(`Target file already exists: ${nextPath}`, "error", true);
587
403
 
588
404
  let content: string;
589
405
  if (params.resource === "agent") {
@@ -592,50 +408,22 @@ export function handleUpdate(
592
408
  ...agent,
593
409
  name: nextName,
594
410
  filePath: nextPath,
595
- description:
596
- typeof cfg.description === "string" && cfg.description.trim()
597
- ? cfg.description.trim()
598
- : agent.description,
599
- systemPrompt:
600
- typeof cfg.systemPrompt === "string"
601
- ? cfg.systemPrompt
602
- : agent.systemPrompt,
603
- model: hasOwn(cfg, "model")
604
- ? typeof cfg.model === "string" && cfg.model.trim()
605
- ? cfg.model.trim()
606
- : undefined
607
- : agent.model,
608
- fallbackModels: hasOwn(cfg, "fallbackModels")
609
- ? parseStringArray(cfg.fallbackModels)
610
- : agent.fallbackModels,
411
+ description: typeof cfg.description === "string" && cfg.description.trim() ? cfg.description.trim() : agent.description,
412
+ systemPrompt: typeof cfg.systemPrompt === "string" ? cfg.systemPrompt : agent.systemPrompt,
413
+ model: hasOwn(cfg, "model") ? (typeof cfg.model === "string" && cfg.model.trim() ? cfg.model.trim() : undefined) : agent.model,
414
+ fallbackModels: hasOwn(cfg, "fallbackModels") ? parseStringArray(cfg.fallbackModels) : agent.fallbackModels,
611
415
  thinking: hasOwn(cfg, "thinking")
612
416
  ? typeof cfg.thinking === "string" && cfg.thinking.trim()
613
417
  ? cfg.thinking.trim()
614
418
  : undefined
615
419
  : agent.thinking,
616
- tools: hasOwn(cfg, "tools")
617
- ? parseStringArray(cfg.tools)
618
- : agent.tools,
619
- extensions: hasOwn(cfg, "extensions")
620
- ? (parseStringArray(cfg.extensions) ?? [])
621
- : agent.extensions,
622
- skills: hasOwn(cfg, "skills")
623
- ? parseStringArray(cfg.skills)
624
- : agent.skills,
420
+ tools: hasOwn(cfg, "tools") ? parseStringArray(cfg.tools) : agent.tools,
421
+ extensions: hasOwn(cfg, "extensions") ? (parseStringArray(cfg.extensions) ?? []) : agent.extensions,
422
+ skills: hasOwn(cfg, "skills") ? parseStringArray(cfg.skills) : agent.skills,
625
423
  systemPromptMode:
626
- cfg.systemPromptMode === "append"
627
- ? "append"
628
- : cfg.systemPromptMode === "replace"
629
- ? "replace"
630
- : agent.systemPromptMode,
631
- inheritProjectContext:
632
- typeof cfg.inheritProjectContext === "boolean"
633
- ? cfg.inheritProjectContext
634
- : agent.inheritProjectContext,
635
- inheritSkills:
636
- typeof cfg.inheritSkills === "boolean"
637
- ? cfg.inheritSkills
638
- : agent.inheritSkills,
424
+ cfg.systemPromptMode === "append" ? "append" : cfg.systemPromptMode === "replace" ? "replace" : agent.systemPromptMode,
425
+ inheritProjectContext: typeof cfg.inheritProjectContext === "boolean" ? cfg.inheritProjectContext : agent.inheritProjectContext,
426
+ inheritSkills: typeof cfg.inheritSkills === "boolean" ? cfg.inheritSkills : agent.inheritSkills,
639
427
  routing: parseRouting(cfg, agent.routing),
640
428
  });
641
429
  } else if (params.resource === "team") {
@@ -643,34 +431,23 @@ export function handleUpdate(
643
431
  let roles = team.roles;
644
432
  if (hasOwn(cfg, "roles")) {
645
433
  const parsedRoles = parseRoles(cfg.roles);
646
- if (parsedRoles.error)
647
- return result(parsedRoles.error, "error", true);
434
+ if (parsedRoles.error) return result(parsedRoles.error, "error", true);
648
435
  roles = parsedRoles.roles!;
649
436
  }
650
437
  content = serializeTeam({
651
438
  ...team,
652
439
  name: nextName,
653
440
  filePath: nextPath,
654
- description:
655
- typeof cfg.description === "string" && cfg.description.trim()
656
- ? cfg.description.trim()
657
- : team.description,
441
+ description: typeof cfg.description === "string" && cfg.description.trim() ? cfg.description.trim() : team.description,
658
442
  roles,
659
443
  defaultWorkflow: hasOwn(cfg, "defaultWorkflow")
660
444
  ? typeof cfg.defaultWorkflow === "string"
661
445
  ? sanitizeName(cfg.defaultWorkflow)
662
446
  : undefined
663
447
  : team.defaultWorkflow,
664
- workspaceMode:
665
- cfg.workspaceMode === "worktree"
666
- ? "worktree"
667
- : cfg.workspaceMode === "single"
668
- ? "single"
669
- : team.workspaceMode,
448
+ workspaceMode: cfg.workspaceMode === "worktree" ? "worktree" : cfg.workspaceMode === "single" ? "single" : team.workspaceMode,
670
449
  maxConcurrency:
671
- typeof cfg.maxConcurrency === "number" &&
672
- Number.isInteger(cfg.maxConcurrency) &&
673
- cfg.maxConcurrency > 0
450
+ typeof cfg.maxConcurrency === "number" && Number.isInteger(cfg.maxConcurrency) && cfg.maxConcurrency > 0
674
451
  ? cfg.maxConcurrency
675
452
  : team.maxConcurrency,
676
453
  routing: parseRouting(cfg, team.routing),
@@ -680,34 +457,21 @@ export function handleUpdate(
680
457
  let steps = workflow.steps;
681
458
  if (hasOwn(cfg, "steps")) {
682
459
  const parsedSteps = parseSteps(cfg.steps);
683
- if (parsedSteps.error)
684
- return result(parsedSteps.error, "error", true);
460
+ if (parsedSteps.error) return result(parsedSteps.error, "error", true);
685
461
  steps = parsedSteps.steps!;
686
462
  }
687
463
  content = serializeWorkflow({
688
464
  ...workflow,
689
465
  name: nextName,
690
466
  filePath: nextPath,
691
- description:
692
- typeof cfg.description === "string" && cfg.description.trim()
693
- ? cfg.description.trim()
694
- : workflow.description,
695
- maxConcurrency: hasOwn(cfg, "maxConcurrency")
696
- ? parseWorkflowMaxConcurrency(cfg.maxConcurrency)
697
- : workflow.maxConcurrency,
467
+ description: typeof cfg.description === "string" && cfg.description.trim() ? cfg.description.trim() : workflow.description,
468
+ maxConcurrency: hasOwn(cfg, "maxConcurrency") ? parseWorkflowMaxConcurrency(cfg.maxConcurrency) : workflow.maxConcurrency,
698
469
  steps,
699
470
  });
700
471
  }
701
472
 
702
473
  const referenceUpdates = params.updateReferences
703
- ? updateReferencesForRename(
704
- ctx,
705
- params.resource!,
706
- current.name,
707
- nextName,
708
- source,
709
- true,
710
- )
474
+ ? updateReferencesForRename(ctx, params.resource!, current.name, nextName, source, true)
711
475
  : [];
712
476
  if (params.dryRun) {
713
477
  return result(
@@ -716,13 +480,7 @@ export function handleUpdate(
716
480
  "",
717
481
  content,
718
482
  ...(referenceUpdates.length
719
- ? [
720
- "",
721
- "Would update references in:",
722
- ...referenceUpdates.map(
723
- (filePath) => `- ${filePath}`,
724
- ),
725
- ]
483
+ ? ["", "Would update references in:", ...referenceUpdates.map((filePath) => `- ${filePath}`)]
726
484
  : []),
727
485
  ].join("\n"),
728
486
  );
@@ -750,36 +508,20 @@ export function handleUpdate(
750
508
  );
751
509
  }
752
510
  const updatedRefs = params.updateReferences
753
- ? updateReferencesForRename(
754
- ctx,
755
- params.resource!,
756
- current.name,
757
- nextName,
758
- source,
759
- false,
760
- )
511
+ ? updateReferencesForRename(ctx, params.resource!, current.name, nextName, source, false)
761
512
  : [];
762
513
  return result(
763
514
  [
764
515
  `Updated ${params.resource} at ${nextPath}. Backup: ${backupPath}.`,
765
- ...(updatedRefs.length
766
- ? [
767
- "Updated references:",
768
- ...updatedRefs.map((filePath) => `- ${filePath}`),
769
- ]
770
- : []),
516
+ ...(updatedRefs.length ? ["Updated references:", ...updatedRefs.map((filePath) => `- ${filePath}`)] : []),
771
517
  ].join("\n"),
772
518
  );
773
519
  }
774
520
 
775
- export function handleDelete(
776
- params: TeamToolParamsValue,
777
- ctx: ManagementContext,
778
- ): PiTeamsToolResult {
521
+ export function handleDelete(params: TeamToolParamsValue, ctx: ManagementContext): PiTeamsToolResult {
779
522
  const intentError = enforceDestructiveIntent("delete", params, ctx.config);
780
523
  if (intentError) return intentError;
781
- if (!params.confirm)
782
- return result("delete requires confirm: true.", "error", true);
524
+ if (!params.confirm) return result("delete requires confirm: true.", "error", true);
783
525
  const resolved = resolveMutable(ctx, params);
784
526
  if (resolved.error) return resolved.error;
785
527
  const refs = findReferences(ctx, params.resource!, resolved.resource!.name);
@@ -804,7 +546,5 @@ export function handleDelete(
804
546
  true,
805
547
  );
806
548
  }
807
- return result(
808
- `Deleted ${params.resource} at ${resolved.resource!.filePath}. Backup: ${backupPath}.`,
809
- );
549
+ return result(`Deleted ${params.resource} at ${resolved.resource!.filePath}. Backup: ${backupPath}.`);
810
550
  }