pi-crew 0.9.16 → 0.9.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (432) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/README.md +19 -0
  3. package/dist/build-meta.json +21790 -0
  4. package/dist/index.mjs +83070 -0
  5. package/dist/index.mjs.map +7 -0
  6. package/docs/A +358 -0
  7. package/docs/M-A +357 -0
  8. package/docs/REVIEW-FINDINGS-2026-06 +357 -0
  9. package/docs/Y +357 -0
  10. package/docs/a +357 -0
  11. package/docs/aA +358 -0
  12. package/docs/archive/README.md +91 -0
  13. package/docs/patterns/command-agent-skill.md +1 -1
  14. package/docs/skills/REFERENCE.md +0 -17
  15. package/docs//303/242mmaAAA/303/242 +357 -0
  16. package/index.bundle.ts +25 -0
  17. package/index.ts +95 -4
  18. package/package.json +15 -4
  19. package/skills/iterative-audit/SKILL.md +0 -1
  20. package/skills/widget-rendering/SKILL.md +17 -0
  21. package/src/adapters/claude-adapter.ts +1 -3
  22. package/src/adapters/export-util.ts +16 -16
  23. package/src/adapters/index.ts +5 -5
  24. package/src/agents/agent-config.ts +20 -14
  25. package/src/agents/agent-serializer.ts +1 -1
  26. package/src/agents/discover-agents.ts +83 -39
  27. package/src/benchmark/benchmark-runner.ts +51 -51
  28. package/src/benchmark/feedback-loop.ts +1 -1
  29. package/src/config/config.ts +166 -590
  30. package/src/config/defaults.ts +28 -2
  31. package/src/config/drift-detector.ts +11 -14
  32. package/src/config/markers.ts +201 -203
  33. package/src/config/resilient-parser.ts +14 -6
  34. package/src/config/role-tools.ts +3 -3
  35. package/src/config/suggestions.ts +5 -12
  36. package/src/config/types.ts +9 -25
  37. package/src/errors.ts +151 -157
  38. package/src/extension/action-suggestions.ts +54 -9
  39. package/src/extension/async-notifier.ts +43 -13
  40. package/src/extension/autonomous-policy.ts +77 -37
  41. package/src/extension/command-completions.ts +9 -8
  42. package/src/extension/context-status-injection.ts +14 -12
  43. package/src/extension/crew-autocomplete.ts +8 -16
  44. package/src/extension/crew-cleanup.ts +2 -1
  45. package/src/extension/crew-shortcuts.ts +9 -6
  46. package/src/extension/cross-extension-rpc.ts +136 -42
  47. package/src/extension/help.ts +1 -1
  48. package/src/extension/import-index.ts +10 -5
  49. package/src/extension/knowledge-injection.ts +88 -15
  50. package/src/extension/management.ts +89 -349
  51. package/src/extension/message-renderers.ts +3 -4
  52. package/src/extension/notification-router.ts +22 -5
  53. package/src/extension/notification-sink.ts +6 -3
  54. package/src/extension/pi-api.ts +17 -8
  55. package/src/extension/plan-orchestrate.ts +8 -27
  56. package/src/extension/project-init.ts +21 -6
  57. package/src/extension/register.ts +329 -975
  58. package/src/extension/registration/artifact-cleanup.ts +9 -4
  59. package/src/extension/registration/command-utils.ts +5 -1
  60. package/src/extension/registration/commands.ts +806 -314
  61. package/src/extension/registration/compaction-guard.ts +15 -15
  62. package/src/extension/registration/lifecycle.ts +259 -0
  63. package/src/extension/registration/observability.ts +293 -0
  64. package/src/extension/registration/subagent-helpers.ts +29 -7
  65. package/src/extension/registration/subagent-tools.ts +253 -44
  66. package/src/extension/registration/team-tool.ts +19 -84
  67. package/src/extension/registration/ui.ts +168 -0
  68. package/src/extension/registration/viewers.ts +64 -24
  69. package/src/extension/result-watcher.ts +18 -7
  70. package/src/extension/run-bundle-schema.ts +21 -6
  71. package/src/extension/run-export.ts +15 -6
  72. package/src/extension/run-import.ts +64 -29
  73. package/src/extension/run-index.ts +28 -9
  74. package/src/extension/run-maintenance.ts +32 -12
  75. package/src/extension/session-summary.ts +1 -1
  76. package/src/extension/team-manager-command.ts +64 -7
  77. package/src/extension/team-onboard.ts +151 -150
  78. package/src/extension/team-recommendation.ts +121 -21
  79. package/src/extension/team-tool/anchor.ts +31 -64
  80. package/src/extension/team-tool/api.ts +929 -141
  81. package/src/extension/team-tool/auto-summarize.ts +14 -26
  82. package/src/extension/team-tool/cache-control.ts +1 -5
  83. package/src/extension/team-tool/cancel.ts +138 -38
  84. package/src/extension/team-tool/chain-dispatch.ts +5 -13
  85. package/src/extension/team-tool/chain-executor.ts +29 -51
  86. package/src/extension/team-tool/config-patch.ts +1 -1
  87. package/src/extension/team-tool/context.ts +40 -20
  88. package/src/extension/team-tool/destructive-gate.ts +10 -5
  89. package/src/extension/team-tool/doctor.ts +170 -51
  90. package/src/extension/team-tool/explain.ts +228 -214
  91. package/src/extension/team-tool/failure-patterns.ts +3 -9
  92. package/src/extension/team-tool/goal-wrap.ts +71 -29
  93. package/src/extension/team-tool/goal.ts +185 -35
  94. package/src/extension/team-tool/handle-schedule.ts +34 -15
  95. package/src/extension/team-tool/handle-settings.ts +94 -56
  96. package/src/extension/team-tool/health-monitor.ts +27 -108
  97. package/src/extension/team-tool/inspect.ts +42 -9
  98. package/src/extension/team-tool/intent-policy.ts +4 -1
  99. package/src/extension/team-tool/lifecycle-actions.ts +244 -48
  100. package/src/extension/team-tool/orchestrate.ts +7 -18
  101. package/src/extension/team-tool/parallel-dispatch.ts +51 -29
  102. package/src/extension/team-tool/plan.ts +29 -5
  103. package/src/extension/team-tool/respond.ts +49 -16
  104. package/src/extension/team-tool/run-not-found.ts +3 -8
  105. package/src/extension/team-tool/run.ts +80 -317
  106. package/src/extension/team-tool/status.ts +135 -43
  107. package/src/extension/team-tool/workflow-manage.ts +92 -25
  108. package/src/extension/team-tool-types.ts +8 -1
  109. package/src/extension/team-tool.ts +142 -551
  110. package/src/extension/validate-resources.ts +39 -8
  111. package/src/hooks/registry.ts +66 -17
  112. package/src/hooks/types.ts +1 -1
  113. package/src/i18n.ts +25 -11
  114. package/src/observability/correlation.ts +17 -3
  115. package/src/observability/event-bus.ts +51 -56
  116. package/src/observability/event-to-metric.ts +117 -15
  117. package/src/observability/exporters/otlp-exporter.ts +56 -17
  118. package/src/observability/exporters/prometheus-exporter.ts +1 -1
  119. package/src/observability/metric-registry.ts +16 -4
  120. package/src/observability/metric-retention.ts +8 -2
  121. package/src/observability/metric-sink.ts +11 -3
  122. package/src/observability/metrics-primitives.ts +42 -9
  123. package/src/plugins/plugin-define.ts +2 -2
  124. package/src/plugins/plugin-registry.ts +25 -25
  125. package/src/plugins/plugins/index.ts +1 -1
  126. package/src/plugins/plugins/nextjs.ts +16 -16
  127. package/src/plugins/plugins/vite.ts +7 -11
  128. package/src/plugins/plugins/vitest.ts +6 -11
  129. package/src/runtime/adaptive-plan.ts +225 -40
  130. package/src/runtime/agent-control.ts +58 -15
  131. package/src/runtime/agent-memory.ts +15 -9
  132. package/src/runtime/agent-observability.ts +10 -2
  133. package/src/runtime/anchor-manager.ts +27 -25
  134. package/src/runtime/async-marker.ts +7 -1
  135. package/src/runtime/async-runner.ts +27 -23
  136. package/src/runtime/auto-summarize.ts +7 -13
  137. package/src/runtime/background-runner.ts +189 -251
  138. package/src/runtime/batch-barrier.ts +18 -16
  139. package/src/runtime/cancellation-token.ts +16 -6
  140. package/src/runtime/cancellation.ts +46 -8
  141. package/src/runtime/capability-inventory.ts +6 -4
  142. package/src/runtime/chain-parser.ts +44 -11
  143. package/src/runtime/chain-runner.ts +63 -69
  144. package/src/runtime/checkpoint.ts +12 -56
  145. package/src/runtime/child-pi.ts +343 -78
  146. package/src/runtime/coalesce-tasks.ts +268 -0
  147. package/src/runtime/code-summary.ts +71 -26
  148. package/src/runtime/compact-stages/index.ts +15 -5
  149. package/src/runtime/compact-stages/tail-capture-stage.ts +7 -2
  150. package/src/runtime/compact-stages/truncation-stage.ts +4 -1
  151. package/src/runtime/compaction-summary.ts +17 -10
  152. package/src/runtime/completion-guard.ts +33 -16
  153. package/src/runtime/crash-classification.ts +28 -7
  154. package/src/runtime/crash-recovery.ts +177 -37
  155. package/src/runtime/crew-agent-records.ts +145 -47
  156. package/src/runtime/crew-hooks.ts +9 -24
  157. package/src/runtime/cross-extension-rpc.ts +25 -23
  158. package/src/runtime/custom-tools/irc-tool.ts +43 -15
  159. package/src/runtime/custom-tools/submit-result-tool.ts +16 -5
  160. package/src/runtime/delivery-coordinator.ts +34 -7
  161. package/src/runtime/delta-conflict.ts +9 -21
  162. package/src/runtime/deterministic-ast.ts +1 -1
  163. package/src/runtime/diagnostic-export.ts +53 -20
  164. package/src/runtime/direct-run.ts +12 -2
  165. package/src/runtime/dwf-state-store.ts +1 -1
  166. package/src/runtime/dynamic-workflow-context.ts +186 -58
  167. package/src/runtime/dynamic-workflow-runner.ts +42 -20
  168. package/src/runtime/effectiveness.ts +16 -8
  169. package/src/runtime/errors/crew-errors.ts +7 -11
  170. package/src/runtime/event-stream-bridge.ts +9 -3
  171. package/src/runtime/foreground-control.ts +54 -14
  172. package/src/runtime/foreground-watchdog.ts +9 -6
  173. package/src/runtime/goal-achievement.ts +27 -10
  174. package/src/runtime/goal-evaluator.ts +54 -19
  175. package/src/runtime/goal-loop-runner.ts +280 -99
  176. package/src/runtime/goal-state-store.ts +27 -17
  177. package/src/runtime/green-contract.ts +11 -2
  178. package/src/runtime/group-join.ts +64 -31
  179. package/src/runtime/handoff-manager.ts +37 -42
  180. package/src/runtime/heartbeat-gradient.ts +10 -2
  181. package/src/runtime/heartbeat-watcher.ts +32 -6
  182. package/src/runtime/hidden-handoff.ts +12 -30
  183. package/src/runtime/important-line-classifier.ts +12 -2
  184. package/src/runtime/iteration-hooks.ts +25 -15
  185. package/src/runtime/live-agent-control.ts +55 -7
  186. package/src/runtime/live-agent-manager.ts +130 -27
  187. package/src/runtime/live-control-realtime.ts +23 -3
  188. package/src/runtime/live-irc.ts +4 -1
  189. package/src/runtime/live-session-health.ts +12 -4
  190. package/src/runtime/live-session-runtime.ts +379 -117
  191. package/src/runtime/manifest-cache.ts +28 -12
  192. package/src/runtime/mcp-proxy.ts +8 -16
  193. package/src/runtime/metric-parser.ts +1 -5
  194. package/src/runtime/model-fallback.ts +55 -18
  195. package/src/runtime/model-resolver.ts +2 -6
  196. package/src/runtime/model-scope.ts +19 -3
  197. package/src/runtime/notebook-helpers.ts +60 -62
  198. package/src/runtime/orphan-worker-registry.ts +37 -26
  199. package/src/runtime/output-validator.ts +18 -3
  200. package/src/runtime/overflow-recovery.ts +5 -4
  201. package/src/runtime/parallel-research.ts +29 -5
  202. package/src/runtime/parallel-utils.ts +9 -11
  203. package/src/runtime/path-overlap.ts +150 -0
  204. package/src/runtime/peer-dep.ts +12 -17
  205. package/src/runtime/per-write-validator.ts +1 -3
  206. package/src/runtime/phase-tracker.ts +342 -330
  207. package/src/runtime/pi-args.ts +26 -8
  208. package/src/runtime/pi-json-output.ts +1 -1
  209. package/src/runtime/pi-spawn.ts +30 -19
  210. package/src/runtime/pipeline-runner.ts +56 -55
  211. package/src/runtime/plan-templates.ts +5 -6
  212. package/src/runtime/policy-engine.ts +43 -7
  213. package/src/runtime/post-checks.ts +12 -4
  214. package/src/runtime/post-exit-stdio-guard.ts +2 -2
  215. package/src/runtime/process-lifecycle.ts +20 -10
  216. package/src/runtime/process-status.ts +16 -5
  217. package/src/runtime/progress-event-coalescer.ts +2 -1
  218. package/src/runtime/progress-tracker.ts +103 -103
  219. package/src/runtime/prose-compressor.ts +9 -11
  220. package/src/runtime/recovery-recipes.ts +118 -24
  221. package/src/runtime/replace.ts +25 -10
  222. package/src/runtime/resilient-edit.ts +10 -25
  223. package/src/runtime/result-extractor.ts +1 -2
  224. package/src/runtime/retry-executor.ts +20 -4
  225. package/src/runtime/retry-runner.ts +26 -50
  226. package/src/runtime/role-permission.ts +6 -1
  227. package/src/runtime/run-coalesced-task-group.ts +256 -0
  228. package/src/runtime/run-drift.ts +14 -15
  229. package/src/runtime/run-tracker.ts +6 -28
  230. package/src/runtime/runtime-policy.ts +1 -6
  231. package/src/runtime/runtime-resolver.ts +80 -15
  232. package/src/runtime/scheduler.ts +47 -18
  233. package/src/runtime/semaphore.ts +5 -7
  234. package/src/runtime/sensitive-paths.ts +2 -1
  235. package/src/runtime/session-usage.ts +1 -1
  236. package/src/runtime/settings-store.ts +16 -12
  237. package/src/runtime/sidechain-output.ts +6 -2
  238. package/src/runtime/single-agent-compose.ts +1 -4
  239. package/src/runtime/skill-effectiveness.ts +29 -97
  240. package/src/runtime/skill-instructions.ts +40 -83
  241. package/src/runtime/stale-reconciler.ts +73 -197
  242. package/src/runtime/stream-preview.ts +1 -1
  243. package/src/runtime/streaming-output.ts +1 -1
  244. package/src/runtime/subagent-manager.ts +44 -169
  245. package/src/runtime/subprocess-tool-registry.ts +4 -1
  246. package/src/runtime/supervisor-contact.ts +10 -5
  247. package/src/runtime/task-display.ts +19 -5
  248. package/src/runtime/task-graph-scheduler.ts +95 -21
  249. package/src/runtime/task-graph.ts +5 -11
  250. package/src/runtime/task-health.ts +54 -47
  251. package/src/runtime/task-id.ts +11 -18
  252. package/src/runtime/task-output-context.ts +265 -81
  253. package/src/runtime/task-packet.ts +12 -20
  254. package/src/runtime/task-quality.ts +6 -14
  255. package/src/runtime/task-runner/context-retrieval.ts +4 -13
  256. package/src/runtime/task-runner/live-executor.ts +114 -36
  257. package/src/runtime/task-runner/output-splitter.ts +152 -0
  258. package/src/runtime/task-runner/progress.ts +50 -12
  259. package/src/runtime/task-runner/prompt-builder.ts +31 -7
  260. package/src/runtime/task-runner/prompt-pipeline.ts +31 -7
  261. package/src/runtime/task-runner/result-utils.ts +3 -1
  262. package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
  263. package/src/runtime/task-runner/run-projection.ts +27 -8
  264. package/src/runtime/task-runner/state-helpers.ts +29 -8
  265. package/src/runtime/task-runner/tail-read.ts +2 -6
  266. package/src/runtime/task-runner.ts +180 -326
  267. package/src/runtime/team-runner-artifacts.ts +13 -0
  268. package/src/runtime/team-runner.ts +456 -974
  269. package/src/runtime/tool-output-pruner.ts +6 -9
  270. package/src/runtime/tool-progress.ts +11 -21
  271. package/src/runtime/verification-gates.ts +33 -24
  272. package/src/runtime/verification-integrity.ts +1 -4
  273. package/src/runtime/verification-worktree.ts +62 -12
  274. package/src/runtime/worker-heartbeat.ts +5 -1
  275. package/src/runtime/worker-startup.ts +29 -5
  276. package/src/runtime/workflow-state.ts +17 -9
  277. package/src/runtime/workspace-lock.ts +30 -35
  278. package/src/runtime/workspace-tree.ts +20 -32
  279. package/src/runtime/yield-handler.ts +43 -9
  280. package/src/runtime/zombie-scanner.ts +5 -4
  281. package/src/schema/config-schema.ts +266 -172
  282. package/src/schema/team-tool-schema.ts +29 -74
  283. package/src/schema/validation-types.ts +25 -17
  284. package/src/skills/discover-skills.ts +35 -10
  285. package/src/skills/skill-templates.ts +109 -27
  286. package/src/skills/validate.ts +26 -8
  287. package/src/state/active-run-registry.ts +87 -28
  288. package/src/state/artifact-store.ts +9 -5
  289. package/src/state/atomic-write-v2.ts +85 -63
  290. package/src/state/atomic-write.ts +105 -26
  291. package/src/state/blob-store.ts +47 -20
  292. package/src/state/contracts.ts +20 -5
  293. package/src/state/crew-init.ts +5 -22
  294. package/src/state/decision-ledger.ts +19 -73
  295. package/src/state/event-log-rotation.ts +41 -15
  296. package/src/state/event-log.ts +168 -53
  297. package/src/state/event-reconstructor.ts +11 -1
  298. package/src/state/gitignore-manager.ts +2 -8
  299. package/src/state/health-store.ts +57 -57
  300. package/src/state/hook-instinct-bridge.ts +1 -1
  301. package/src/state/hook-integrations.ts +1 -1
  302. package/src/state/instinct-store.ts +17 -5
  303. package/src/state/jsonl-writer.ts +1 -1
  304. package/src/state/locks.ts +23 -9
  305. package/src/state/mailbox.ts +151 -28
  306. package/src/state/observation-store.ts +20 -14
  307. package/src/state/run-cache.ts +142 -135
  308. package/src/state/run-graph.ts +6 -15
  309. package/src/state/run-metrics.ts +5 -18
  310. package/src/state/schedule.ts +15 -9
  311. package/src/state/state-store.ts +129 -45
  312. package/src/state/task-claims.ts +12 -2
  313. package/src/state/tiered-eval.ts +52 -43
  314. package/src/state/types-eval.ts +2 -2
  315. package/src/state/types.ts +24 -20
  316. package/src/state/usage.ts +20 -4
  317. package/src/state/worker-atomic-writer.ts +6 -3
  318. package/src/subagents/index.ts +2 -2
  319. package/src/teams/discover-teams.ts +21 -6
  320. package/src/tools/safe-bash-extension.ts +5 -6
  321. package/src/tools/safe-bash.ts +10 -11
  322. package/src/types/new-api-types.ts +6 -10
  323. package/src/ui/agent-management-overlay.ts +52 -40
  324. package/src/ui/card-colors.ts +13 -4
  325. package/src/ui/crew-footer.ts +8 -7
  326. package/src/ui/crew-select-list.ts +1 -1
  327. package/src/ui/dashboard-panes/agents-pane.ts +41 -25
  328. package/src/ui/dashboard-panes/cancellation-pane.ts +1 -1
  329. package/src/ui/dashboard-panes/capability-pane.ts +32 -15
  330. package/src/ui/dashboard-panes/health-pane.ts +2 -1
  331. package/src/ui/dashboard-panes/metrics-pane.ts +4 -1
  332. package/src/ui/dashboard-panes/progress-pane.ts +12 -9
  333. package/src/ui/heartbeat-aggregator.ts +15 -4
  334. package/src/ui/keybinding-map.ts +40 -7
  335. package/src/ui/live-conversation-overlay.ts +36 -20
  336. package/src/ui/live-duration.ts +1 -4
  337. package/src/ui/live-run-sidebar.ts +88 -25
  338. package/src/ui/loaders.ts +2 -8
  339. package/src/ui/mascot.ts +20 -36
  340. package/src/ui/overlays/agent-picker-overlay.ts +11 -3
  341. package/src/ui/overlays/confirm-overlay.ts +4 -2
  342. package/src/ui/overlays/help-overlay.ts +25 -14
  343. package/src/ui/overlays/mailbox-compose-overlay.ts +48 -11
  344. package/src/ui/overlays/mailbox-compose-preview.ts +20 -5
  345. package/src/ui/overlays/mailbox-detail-overlay.ts +27 -6
  346. package/src/ui/pi-ui-compat.ts +7 -7
  347. package/src/ui/powerbar-publisher.ts +120 -42
  348. package/src/ui/render-diff.ts +10 -3
  349. package/src/ui/render-scheduler.ts +12 -4
  350. package/src/ui/run-action-dispatcher.ts +81 -18
  351. package/src/ui/run-dashboard.ts +172 -76
  352. package/src/ui/run-event-bus.ts +59 -37
  353. package/src/ui/run-snapshot-cache.ts +276 -86
  354. package/src/ui/settings-overlay.ts +361 -74
  355. package/src/ui/status-colors.ts +12 -1
  356. package/src/ui/syntax-highlight.ts +1 -1
  357. package/src/ui/theme-adapter.ts +16 -14
  358. package/src/ui/theme-discovery.ts +13 -2
  359. package/src/ui/tool-progress-formatter.ts +7 -7
  360. package/src/ui/tool-render.ts +128 -56
  361. package/src/ui/tool-renderers/brief-mode.ts +45 -27
  362. package/src/ui/tool-renderers/index.ts +109 -43
  363. package/src/ui/transcript-cache.ts +32 -6
  364. package/src/ui/transcript-entries.ts +25 -23
  365. package/src/ui/transcript-viewer.ts +78 -29
  366. package/src/ui/widget/index.ts +99 -40
  367. package/src/ui/widget/widget-formatters.ts +13 -6
  368. package/src/ui/widget/widget-model.ts +19 -8
  369. package/src/ui/widget/widget-renderer.ts +23 -13
  370. package/src/ui/widget/widget-types.ts +1 -1
  371. package/src/utils/bm25-search.ts +199 -199
  372. package/src/utils/conflict-detect.ts +22 -21
  373. package/src/utils/env-filter.ts +14 -7
  374. package/src/utils/file-coalescer.ts +5 -1
  375. package/src/utils/fingerprint.ts +3 -6
  376. package/src/utils/frontmatter.ts +3 -1
  377. package/src/utils/fs-watch.ts +2 -6
  378. package/src/utils/gh-protocol.ts +119 -44
  379. package/src/utils/git.ts +13 -15
  380. package/src/utils/guards.ts +2 -5
  381. package/src/utils/ids.ts +9 -2
  382. package/src/utils/incremental-reader.ts +14 -3
  383. package/src/utils/internal-error.ts +2 -1
  384. package/src/utils/names.ts +12 -3
  385. package/src/utils/paths.ts +49 -5
  386. package/src/utils/project-detector.ts +2 -2
  387. package/src/utils/redaction.ts +29 -19
  388. package/src/utils/resolve-shell.ts +9 -7
  389. package/src/utils/run-watcher-registry.ts +19 -31
  390. package/src/utils/safe-paths.ts +45 -24
  391. package/src/utils/scan-cache.ts +9 -2
  392. package/src/utils/session-utils.ts +2 -4
  393. package/src/utils/sleep.ts +12 -5
  394. package/src/utils/sse-parser.ts +5 -17
  395. package/src/utils/visual.ts +52 -32
  396. package/src/workflows/discover-workflows.ts +41 -109
  397. package/src/workflows/intermediate-store.ts +5 -21
  398. package/src/workflows/preflight-validator.ts +6 -33
  399. package/src/workflows/topology-analyzer.ts +5 -21
  400. package/src/workflows/workflow-config.ts +7 -6
  401. package/src/worktree/branch-freshness.ts +66 -8
  402. package/src/worktree/cleanup.ts +130 -20
  403. package/src/worktree/worktree-manager.ts +212 -69
  404. package/skills/artifact-analysis-loop/SKILL.md +0 -303
  405. package/skills/detection-pipeline-design/SKILL.md +0 -286
  406. package/skills/hunting-investigation-loop/SKILL.md +0 -402
  407. package/skills/incident-playbook-construction/SKILL.md +0 -384
  408. package/skills/security-review/SKILL.md +0 -561
  409. package/skills/threat-hypothesis-framework/SKILL.md +0 -176
  410. package/skills/ui-render-performance/SKILL.md +0 -58
  411. /package/docs/{followup-review-round3-2026-05-12.md → archive/followup-review-round3-2026-05-12.md} +0 -0
  412. /package/docs/{followup-review-round4-2026-05-13.md → archive/followup-review-round4-2026-05-13.md} +0 -0
  413. /package/docs/{pi-crew-bugs.md → archive/pi-crew-bugs.md} +0 -0
  414. /package/docs/{pi-crew-test-final.md → archive/pi-crew-test-final.md} +0 -0
  415. /package/docs/{pi-crew-test-results.md → archive/pi-crew-test-results.md} +0 -0
  416. /package/docs/{pi-crew-test-round2.md → archive/pi-crew-test-round2.md} +0 -0
  417. /package/docs/{pi-crew-test-round4.md → archive/pi-crew-test-round4.md} +0 -0
  418. /package/docs/{pi-crew-test-round5.md → archive/pi-crew-test-round5.md} +0 -0
  419. /package/docs/{pi-crew-test-round6.md → archive/pi-crew-test-round6.md} +0 -0
  420. /package/docs/{pi-crew-v0.5.10-audit-fix-plan.md → archive/pi-crew-v0.5.10-audit-fix-plan.md} +0 -0
  421. /package/docs/{pi-crew-v0.5.11-audit-fix-plan.md → archive/pi-crew-v0.5.11-audit-fix-plan.md} +0 -0
  422. /package/docs/{pi-crew-v0.5.12-audit-fix-plan.md → archive/pi-crew-v0.5.12-audit-fix-plan.md} +0 -0
  423. /package/docs/{pi-crew-v0.5.13-audit-fix-plan.md → archive/pi-crew-v0.5.13-audit-fix-plan.md} +0 -0
  424. /package/docs/{pi-crew-v0.5.14-audit-fix-plan.md → archive/pi-crew-v0.5.14-audit-fix-plan.md} +0 -0
  425. /package/docs/{pi-crew-v0.5.16-audit-fix-plan.md → archive/pi-crew-v0.5.16-audit-fix-plan.md} +0 -0
  426. /package/docs/{pi-crew-v0.5.17-audit-fix-plan.md → archive/pi-crew-v0.5.17-audit-fix-plan.md} +0 -0
  427. /package/docs/{pi-crew-v0.5.5-audit-fix-plan.md → archive/pi-crew-v0.5.5-audit-fix-plan.md} +0 -0
  428. /package/docs/{pi-crew-v0.5.9-audit-fix-plan.md → archive/pi-crew-v0.5.9-audit-fix-plan.md} +0 -0
  429. /package/docs/{pi-mono-opportunities.md → archive/pi-mono-opportunities.md} +0 -0
  430. /package/docs/{pi-mono-review.md → archive/pi-mono-review.md} +0 -0
  431. /package/docs/{pi-subagent4-comparison.md → archive/pi-subagent4-comparison.md} +0 -0
  432. /package/docs/{pi-subagents3-deep-analysis.md → archive/pi-subagents3-deep-analysis.md} +0 -0
@@ -2,153 +2,153 @@ import type { AgentConfig } from "../agents/agent-config.ts";
2
2
  import type { TeamConfig } from "../teams/team-config.ts";
3
3
 
4
4
  interface SearchDocument {
5
- id: string;
6
- fields: Record<string, string>;
5
+ id: string;
6
+ fields: Record<string, string>;
7
7
  }
8
8
 
9
9
  interface SearchResult<T> {
10
- item: T;
11
- score: number;
12
- matchedOn: string[];
10
+ item: T;
11
+ score: number;
12
+ matchedOn: string[];
13
13
  }
14
14
 
15
15
  interface BM25Config {
16
- k1?: number;
17
- b?: number;
16
+ k1?: number;
17
+ b?: number;
18
18
  }
19
19
 
20
20
  export class BM25Search<T extends SearchDocument> {
21
- private readonly documents: T[];
22
- private readonly fieldWeights: Record<string, number>;
23
- private readonly avgDocLen: number;
24
- private readonly k1: number;
25
- private readonly b: number;
26
- private readonly docLenMap: Map<string, number>;
27
- private readonly N: number;
28
- /**
29
- * Precomputed document frequency per term. Cached at construction time
30
- * to avoid O(N) recomputation on every search() call. The cache is
31
- * immutable for a given document corpus, so it's safe to share across
32
- * search() invocations.
33
- */
34
- private readonly dfCache: Map<string, number>;
35
-
36
- constructor(documents: T[], fieldWeights: Record<string, number> = {}, config: BM25Config = {}) {
37
- this.documents = documents;
38
- this.fieldWeights = fieldWeights;
39
- this.k1 = config.k1 ?? 1.5;
40
- this.b = config.b ?? 0.75;
41
- this.N = documents.length;
42
-
43
- this.docLenMap = new Map();
44
- this.dfCache = new Map();
45
-
46
- for (const doc of documents) {
47
- const fieldValues = Object.values(doc.fields).join(" ");
48
- const len = fieldValues.split(/\s+/).filter(Boolean).length;
49
- this.docLenMap.set(doc.id, len);
50
- }
51
-
52
- const totalLen = [...this.docLenMap.values()].reduce((a, b) => a + b, 0);
53
- this.avgDocLen = totalLen / this.N || 1;
54
-
55
- // Precompute df for all terms in the corpus. We do this once instead
56
- // of on-demand to avoid the O(Q * N * field_count) cost per search call.
57
- this.precomputeDocumentFrequencies();
58
- }
59
-
60
- /**
61
- * Build a map of term -> document frequency. O(N * avg_terms * field_count).
62
- * Called once in the constructor.
63
- */
64
- private precomputeDocumentFrequencies(): void {
65
- for (const doc of this.documents) {
66
- for (const field of Object.keys(this.fieldWeights)) {
67
- const text = (doc.fields[field] ?? "").toLowerCase();
68
- // Extract unique terms via split on whitespace
69
- const terms = new Set(text.split(/\s+/).filter(Boolean));
70
- for (const term of terms) {
71
- if (term.length === 0) continue;
72
- this.dfCache.set(term, (this.dfCache.get(term) ?? 0) + 1);
73
- }
74
- }
75
- }
76
- }
77
-
78
- /**
79
- * Get document frequency for a term. Returns the precomputed value.
80
- * O(1) lookup.
81
- */
82
- private df(term: string): number {
83
- return this.dfCache.get(term.toLowerCase()) ?? 0;
84
- }
85
-
86
- search(query: string, options?: { limit?: number; minScore?: number }): SearchResult<T>[] {
87
- const queryTerms = query.toLowerCase().split(/\s+/).filter(Boolean);
88
- if (queryTerms.length === 0) return [];
89
-
90
- const results: SearchResult<T>[] = [];
91
-
92
- for (const doc of this.documents) {
93
- let totalScore = 0;
94
- const matchedOn: string[] = [];
95
-
96
- for (const [field, weight] of Object.entries(this.fieldWeights)) {
97
- const text = doc.fields[field] ?? "";
98
- const textLower = text.toLowerCase();
99
- let fieldScore = 0;
100
-
101
- for (const term of queryTerms) {
102
- // Use indexOf for linear-time substring counting instead of regex
103
- const termLower = term.toLowerCase();
104
- let tf = 0;
105
- let pos = 0;
106
- while ((pos = textLower.indexOf(termLower, pos)) !== -1) {
107
- tf++;
108
- pos += termLower.length;
109
- // Cap tf to prevent runaway on repeated patterns
110
- if (tf > 100) break;
111
- }
112
- if (tf === 0) continue;
113
-
114
- const df = this.df(termLower);
115
- if (df === 0) continue;
116
-
117
- const idf = Math.log((this.N - df + 0.5) / (df + 0.5) + 1);
118
- const docLen = this.docLenMap.get(doc.id) ?? this.avgDocLen;
119
- const numerator = tf * (this.k1 + 1);
120
- const denominator = tf + this.k1 * (1 - this.b + this.b * docLen / this.avgDocLen);
121
- fieldScore += idf * (numerator / denominator);
122
-
123
- matchedOn.push(field);
124
- }
125
-
126
- totalScore += fieldScore * (weight || 1);
127
- }
128
-
129
- if (totalScore > 0) {
130
- results.push({
131
- item: doc,
132
- score: totalScore,
133
- matchedOn: [...new Set(matchedOn)],
134
- });
135
- }
136
- }
137
-
138
- results.sort((a, b) => b.score - a.score);
139
-
140
- const limit = options?.limit ?? 10;
141
- const minScore = options?.minScore ?? 0.01;
142
-
143
- return results.filter((r) => r.score >= minScore).slice(0, limit);
144
- }
21
+ private readonly documents: T[];
22
+ private readonly fieldWeights: Record<string, number>;
23
+ private readonly avgDocLen: number;
24
+ private readonly k1: number;
25
+ private readonly b: number;
26
+ private readonly docLenMap: Map<string, number>;
27
+ private readonly N: number;
28
+ /**
29
+ * Precomputed document frequency per term. Cached at construction time
30
+ * to avoid O(N) recomputation on every search() call. The cache is
31
+ * immutable for a given document corpus, so it's safe to share across
32
+ * search() invocations.
33
+ */
34
+ private readonly dfCache: Map<string, number>;
35
+
36
+ constructor(documents: T[], fieldWeights: Record<string, number> = {}, config: BM25Config = {}) {
37
+ this.documents = documents;
38
+ this.fieldWeights = fieldWeights;
39
+ this.k1 = config.k1 ?? 1.5;
40
+ this.b = config.b ?? 0.75;
41
+ this.N = documents.length;
42
+
43
+ this.docLenMap = new Map();
44
+ this.dfCache = new Map();
45
+
46
+ for (const doc of documents) {
47
+ const fieldValues = Object.values(doc.fields).join(" ");
48
+ const len = fieldValues.split(/\s+/).filter(Boolean).length;
49
+ this.docLenMap.set(doc.id, len);
50
+ }
51
+
52
+ const totalLen = [...this.docLenMap.values()].reduce((a, b) => a + b, 0);
53
+ this.avgDocLen = totalLen / this.N || 1;
54
+
55
+ // Precompute df for all terms in the corpus. We do this once instead
56
+ // of on-demand to avoid the O(Q * N * field_count) cost per search call.
57
+ this.precomputeDocumentFrequencies();
58
+ }
59
+
60
+ /**
61
+ * Build a map of term -> document frequency. O(N * avg_terms * field_count).
62
+ * Called once in the constructor.
63
+ */
64
+ private precomputeDocumentFrequencies(): void {
65
+ for (const doc of this.documents) {
66
+ for (const field of Object.keys(this.fieldWeights)) {
67
+ const text = (doc.fields[field] ?? "").toLowerCase();
68
+ // Extract unique terms via split on whitespace
69
+ const terms = new Set(text.split(/\s+/).filter(Boolean));
70
+ for (const term of terms) {
71
+ if (term.length === 0) continue;
72
+ this.dfCache.set(term, (this.dfCache.get(term) ?? 0) + 1);
73
+ }
74
+ }
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Get document frequency for a term. Returns the precomputed value.
80
+ * O(1) lookup.
81
+ */
82
+ private df(term: string): number {
83
+ return this.dfCache.get(term.toLowerCase()) ?? 0;
84
+ }
85
+
86
+ search(query: string, options?: { limit?: number; minScore?: number }): SearchResult<T>[] {
87
+ const queryTerms = query.toLowerCase().split(/\s+/).filter(Boolean);
88
+ if (queryTerms.length === 0) return [];
89
+
90
+ const results: SearchResult<T>[] = [];
91
+
92
+ for (const doc of this.documents) {
93
+ let totalScore = 0;
94
+ const matchedOn: string[] = [];
95
+
96
+ for (const [field, weight] of Object.entries(this.fieldWeights)) {
97
+ const text = doc.fields[field] ?? "";
98
+ const textLower = text.toLowerCase();
99
+ let fieldScore = 0;
100
+
101
+ for (const term of queryTerms) {
102
+ // Use indexOf for linear-time substring counting instead of regex
103
+ const termLower = term.toLowerCase();
104
+ let tf = 0;
105
+ let pos = 0;
106
+ while ((pos = textLower.indexOf(termLower, pos)) !== -1) {
107
+ tf++;
108
+ pos += termLower.length;
109
+ // Cap tf to prevent runaway on repeated patterns
110
+ if (tf > 100) break;
111
+ }
112
+ if (tf === 0) continue;
113
+
114
+ const df = this.df(termLower);
115
+ if (df === 0) continue;
116
+
117
+ const idf = Math.log((this.N - df + 0.5) / (df + 0.5) + 1);
118
+ const docLen = this.docLenMap.get(doc.id) ?? this.avgDocLen;
119
+ const numerator = tf * (this.k1 + 1);
120
+ const denominator = tf + this.k1 * (1 - this.b + (this.b * docLen) / this.avgDocLen);
121
+ fieldScore += idf * (numerator / denominator);
122
+
123
+ matchedOn.push(field);
124
+ }
125
+
126
+ totalScore += fieldScore * (weight || 1);
127
+ }
128
+
129
+ if (totalScore > 0) {
130
+ results.push({
131
+ item: doc,
132
+ score: totalScore,
133
+ matchedOn: [...new Set(matchedOn)],
134
+ });
135
+ }
136
+ }
137
+
138
+ results.sort((a, b) => b.score - a.score);
139
+
140
+ const limit = options?.limit ?? 10;
141
+ const minScore = options?.minScore ?? 0.01;
142
+
143
+ return results.filter((r) => r.score >= minScore).slice(0, limit);
144
+ }
145
145
  }
146
146
 
147
147
  // Agent search interface
148
148
  interface AgentSearchResult {
149
- agent: AgentConfig;
150
- score: number;
151
- matchedOn: string[];
149
+ agent: AgentConfig;
150
+ score: number;
151
+ matchedOn: string[];
152
152
  }
153
153
 
154
154
  /**
@@ -156,44 +156,44 @@ interface AgentSearchResult {
156
156
  * Uses dynamic import to avoid ESM/CJS issues at module load time.
157
157
  */
158
158
  export async function searchAgents(query: string, options?: { limit?: number }): Promise<AgentSearchResult[]> {
159
- // LAZY: defer dynamic import of ../agents/discover-agents.ts to its call site.
160
- const { discoverAgents, allAgents } = await import("../agents/discover-agents.ts");
161
- const discovery = discoverAgents(process.cwd());
162
- const all = allAgents(discovery);
163
-
164
- const docs: (SearchDocument & { agent: AgentConfig })[] = all.map((agent: AgentConfig) => ({
165
- id: agent.name,
166
- fields: {
167
- name: agent.name,
168
- description: agent.description ?? "",
169
- skills: (agent.skills ?? []).join(" "),
170
- },
171
- agent,
172
- }));
173
-
174
- const engine = new BM25Search(docs, {
175
- name: 3.0,
176
- description: 1.5,
177
- skills: 1.0,
178
- });
179
-
180
- const results = engine.search(query, {
181
- limit: options?.limit ?? 10,
182
- minScore: 0.1,
183
- });
184
-
185
- return results.map((r) => ({
186
- agent: r.item.agent,
187
- score: r.score,
188
- matchedOn: r.matchedOn,
189
- }));
159
+ // LAZY: defer dynamic import of ../agents/discover-agents.ts to its call site.
160
+ const { discoverAgents, allAgents } = await import("../agents/discover-agents.ts");
161
+ const discovery = discoverAgents(process.cwd());
162
+ const all = allAgents(discovery);
163
+
164
+ const docs: (SearchDocument & { agent: AgentConfig })[] = all.map((agent: AgentConfig) => ({
165
+ id: agent.name,
166
+ fields: {
167
+ name: agent.name,
168
+ description: agent.description ?? "",
169
+ skills: (agent.skills ?? []).join(" "),
170
+ },
171
+ agent,
172
+ }));
173
+
174
+ const engine = new BM25Search(docs, {
175
+ name: 3.0,
176
+ description: 1.5,
177
+ skills: 1.0,
178
+ });
179
+
180
+ const results = engine.search(query, {
181
+ limit: options?.limit ?? 10,
182
+ minScore: 0.1,
183
+ });
184
+
185
+ return results.map((r) => ({
186
+ agent: r.item.agent,
187
+ score: r.score,
188
+ matchedOn: r.matchedOn,
189
+ }));
190
190
  }
191
191
 
192
192
  // Team search interface
193
193
  interface TeamSearchResult {
194
- team: TeamConfig;
195
- score: number;
196
- matchedOn: string[];
194
+ team: TeamConfig;
195
+ score: number;
196
+ matchedOn: string[];
197
197
  }
198
198
 
199
199
  /**
@@ -201,35 +201,35 @@ interface TeamSearchResult {
201
201
  * Uses dynamic import to avoid ESM/CJS issues at module load time.
202
202
  */
203
203
  export async function searchTeams(query: string, options?: { limit?: number }): Promise<TeamSearchResult[]> {
204
- // LAZY: defer dynamic import of ../teams/discover-teams.ts to its call site.
205
- const { discoverTeams, allTeams } = await import("../teams/discover-teams.ts");
206
- const discovery = discoverTeams(process.cwd());
207
- const all = allTeams(discovery);
208
-
209
- const docs: (SearchDocument & { team: TeamConfig })[] = all.map((team: TeamConfig) => ({
210
- id: team.name,
211
- fields: {
212
- name: team.name,
213
- description: team.description ?? "",
214
- roles: (team.roles ?? []).map((r: { name: string }) => r.name).join(" "),
215
- },
216
- team,
217
- }));
218
-
219
- const engine = new BM25Search(docs, {
220
- name: 2.0,
221
- description: 1.5,
222
- roles: 1.0,
223
- });
224
-
225
- const results = engine.search(query, {
226
- limit: options?.limit ?? 5,
227
- minScore: 0.1,
228
- });
229
-
230
- return results.map((r) => ({
231
- team: r.item.team,
232
- score: r.score,
233
- matchedOn: r.matchedOn,
234
- }));
204
+ // LAZY: defer dynamic import of ../teams/discover-teams.ts to its call site.
205
+ const { discoverTeams, allTeams } = await import("../teams/discover-teams.ts");
206
+ const discovery = discoverTeams(process.cwd());
207
+ const all = allTeams(discovery);
208
+
209
+ const docs: (SearchDocument & { team: TeamConfig })[] = all.map((team: TeamConfig) => ({
210
+ id: team.name,
211
+ fields: {
212
+ name: team.name,
213
+ description: team.description ?? "",
214
+ roles: (team.roles ?? []).map((r: { name: string }) => r.name).join(" "),
215
+ },
216
+ team,
217
+ }));
218
+
219
+ const engine = new BM25Search(docs, {
220
+ name: 2.0,
221
+ description: 1.5,
222
+ roles: 1.0,
223
+ });
224
+
225
+ const results = engine.search(query, {
226
+ limit: options?.limit ?? 5,
227
+ minScore: 0.1,
228
+ });
229
+
230
+ return results.map((r) => ({
231
+ team: r.item.team,
232
+ score: r.score,
233
+ matchedOn: r.matchedOn,
234
+ }));
235
235
  }
@@ -73,7 +73,11 @@ export function scanConflictLines(lines: readonly string[], firstLineNumber: num
73
73
 
74
74
  const oursLabel = matchMarker(line, OURS_PREFIX);
75
75
  if (oursLabel !== null) {
76
- partial = { startLine: ln, oursLabel: oursLabel || undefined, oursLines: [] };
76
+ partial = {
77
+ startLine: ln,
78
+ oursLabel: oursLabel || undefined,
79
+ oursLines: [],
80
+ };
77
81
  phase = "ours";
78
82
  continue;
79
83
  }
@@ -318,9 +322,7 @@ export function parseConflictUri(raw: string): ParsedConflictUri | null {
318
322
  let scope: ConflictScope | undefined;
319
323
  if (scopePart !== undefined) {
320
324
  if (!CONFLICT_SCOPES.has(scopePart as ConflictScope)) {
321
- throw new Error(
322
- `Invalid conflict URI '${raw}': scope must be one of 'ours', 'theirs', 'base', or omitted.`,
323
- );
325
+ throw new Error(`Invalid conflict URI '${raw}': scope must be one of 'ours', 'theirs', 'base', or omitted.`);
324
326
  }
325
327
  scope = scopePart as ConflictScope;
326
328
  }
@@ -375,7 +377,10 @@ function locateRegion(
375
377
  if (expected.length === 0 || expected.length > lines.length) return null;
376
378
  // Fast path: try the recorded position first.
377
379
  if (preferredIdx >= 0 && matchesAt(lines, preferredIdx, expected)) {
378
- return { startIdx: preferredIdx, endIdx: preferredIdx + expected.length - 1 };
380
+ return {
381
+ startIdx: preferredIdx,
382
+ endIdx: preferredIdx + expected.length - 1,
383
+ };
379
384
  }
380
385
  let best: number | null = null;
381
386
  let bestDist = Number.POSITIVE_INFINITY;
@@ -462,15 +467,15 @@ function markerLine(prefix: string, label: string | undefined): string {
462
467
  * - `startLine`: the 1-indexed file line number `lines[0]` corresponds
463
468
  * to, so the read formatter can label hashline anchors.
464
469
  */
465
- export function renderConflictRegion(
466
- entry: ConflictEntry,
467
- scope: ConflictScope | undefined,
468
- ): { lines: string[]; startLine: number } {
470
+ export function renderConflictRegion(entry: ConflictEntry, scope: ConflictScope | undefined): { lines: string[]; startLine: number } {
469
471
  if (scope === "ours") {
470
472
  return { lines: [...entry.oursLines], startLine: entry.startLine + 1 };
471
473
  }
472
474
  if (scope === "theirs") {
473
- return { lines: [...entry.theirsLines], startLine: entry.separatorLine + 1 };
475
+ return {
476
+ lines: [...entry.theirsLines],
477
+ startLine: entry.separatorLine + 1,
478
+ };
474
479
  }
475
480
  if (scope === "base") {
476
481
  if (entry.baseLines === undefined || entry.baseLine === undefined) {
@@ -495,10 +500,7 @@ export function renderConflictRegion(
495
500
 
496
501
  const PREVIEW_SIDE_LINES = 6;
497
502
 
498
- function pickLabel(
499
- entries: readonly ConflictEntry[],
500
- get: (e: ConflictEntry) => string | undefined,
501
- ): string | undefined {
503
+ function pickLabel(entries: readonly ConflictEntry[], get: (e: ConflictEntry) => string | undefined): string | undefined {
502
504
  for (const e of entries) {
503
505
  const label = get(e);
504
506
  if (label && label.trim().length > 0) return label;
@@ -552,10 +554,7 @@ export interface FormatConflictWarningOptions {
552
554
  * >>> theirs
553
555
  * …theirs body…
554
556
  */
555
- export function formatConflictWarning(
556
- entries: readonly ConflictEntry[],
557
- options: FormatConflictWarningOptions = {},
558
- ): string {
557
+ export function formatConflictWarning(entries: readonly ConflictEntry[], options: FormatConflictWarningOptions = {}): string {
559
558
  if (entries.length === 0) return "";
560
559
  const total = options.totalInFile ?? entries.length;
561
560
  const partial = total > entries.length;
@@ -585,7 +584,7 @@ export function formatConflictWarning(
585
584
  'NOTICE: Inspect a block by reading `conflict://<N>` (add `/ours` / `/theirs` / `/base` to render a single side). Resolve with `write({ path: "conflict://<N>", content })`, or bulk-resolve every registered conflict with `write({ path: "conflict://*", content })`.',
586
585
  );
587
586
  out.push(
588
- '`content` shorthand: a line that is exactly `@ours` / `@theirs` / `@base` / `@both` expands to that recorded section. Non-token lines pass through verbatim.',
587
+ "`content` shorthand: a line that is exactly `@ours` / `@theirs` / `@base` / `@both` expands to that recorded section. Non-token lines pass through verbatim.",
589
588
  );
590
589
 
591
590
  for (const entry of entries) {
@@ -627,7 +626,9 @@ export function formatConflictWarning(
627
626
  */
628
627
  export function formatConflictSummary(
629
628
  entries: readonly ConflictEntry[],
630
- options: { displayPath: string; scanTruncated?: boolean } = { displayPath: "" },
629
+ options: { displayPath: string; scanTruncated?: boolean } = {
630
+ displayPath: "",
631
+ },
631
632
  ): string {
632
633
  const lines: string[] = [];
633
634
  const total = entries.length;
@@ -658,4 +659,4 @@ export function formatConflictSummary(
658
659
  lines.push(`${idCell} ${range}${kind}`);
659
660
  }
660
661
  return lines.join("\n");
661
- }
662
+ }
@@ -5,13 +5,20 @@ import { isSecretKey } from "./redaction.ts";
5
5
  // These are "secret" by pattern (contain KEY/API) but are safe to allowlist
6
6
  // because they are standard provider credentials, not arbitrary secrets.
7
7
  const KNOWN_PROVIDER_KEYS = new Set([
8
- "MINIMAX_API_KEY", "MINIMAX_GROUP_ID",
9
- "OPENAI_API_KEY", "OPENAI_ORG_ID",
8
+ "MINIMAX_API_KEY",
9
+ "MINIMAX_GROUP_ID",
10
+ "OPENAI_API_KEY",
11
+ "OPENAI_ORG_ID",
10
12
  "ANTHROPIC_API_KEY",
11
- "GOOGLE_API_KEY", "GOOGLE_GENERATIVE_LANGUAGE_API_KEY",
12
- "AZURE_OPENAI_API_KEY", "AZURE_OPENAI_ENDPOINT",
13
- "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION",
14
- "ZEU_API_KEY", "ZERODEV_API_KEY",
13
+ "GOOGLE_API_KEY",
14
+ "GOOGLE_GENERATIVE_LANGUAGE_API_KEY",
15
+ "AZURE_OPENAI_API_KEY",
16
+ "AZURE_OPENAI_ENDPOINT",
17
+ "AWS_ACCESS_KEY_ID",
18
+ "AWS_SECRET_ACCESS_KEY",
19
+ "AWS_REGION",
20
+ "ZEU_API_KEY",
21
+ "ZERODEV_API_KEY",
15
22
  ]);
16
23
 
17
24
  function isKnownProviderKey(key: string): boolean {
@@ -96,4 +103,4 @@ export function sanitizeEnvSecrets(env: NodeJS.ProcessEnv, options?: SanitizeEnv
96
103
  if (value !== undefined && !isSecretKey(key)) filtered[key] = value;
97
104
  }
98
105
  return filtered;
99
- }
106
+ }
@@ -23,7 +23,11 @@ export interface FileCoalescer {
23
23
  clear(): void;
24
24
  }
25
25
 
26
- export function createFileCoalescer(handler: (file: string) => void, defaultDelayMs: number, timerApi: TimerApi = defaultTimerApi): FileCoalescer {
26
+ export function createFileCoalescer(
27
+ handler: (file: string) => void,
28
+ defaultDelayMs: number,
29
+ timerApi: TimerApi = defaultTimerApi,
30
+ ): FileCoalescer {
27
31
  const pending = new Map<string, unknown>();
28
32
  return {
29
33
  schedule(file, delayMs = defaultDelayMs) {
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { createHash, type Hash } from "node:crypto";
11
- import { readFileSync, writeFileSync, existsSync, statSync } from "node:fs";
11
+ import { existsSync, readFileSync, statSync, writeFileSync } from "node:fs";
12
12
  import { logInternalError } from "../utils/internal-error.ts";
13
13
 
14
14
  // ── Types ────────────────────────────────────────────────────────────────
@@ -66,7 +66,7 @@ export function computeStructuralSignature(content: string, filePath: string): s
66
66
  if (
67
67
  // Function/method declarations
68
68
  /^(export\s+)?(async\s+)?function\s/.test(trimmed) ||
69
- /^\w+\s*\(/.test(trimmed) && !/^(if|for|while|switch|return|throw|await)/.test(trimmed) ||
69
+ (/^\w+\s*\(/.test(trimmed) && !/^(if|for|while|switch|return|throw|await)/.test(trimmed)) ||
70
70
  // Class declarations
71
71
  /^(export\s+)?(abstract\s+)?class\s/.test(trimmed) ||
72
72
  /^(public|private|protected|static|readonly|abstract)\s/.test(trimmed) ||
@@ -147,10 +147,7 @@ export function saveFingerprintBaseline(storePath: string, fingerprints: Map<str
147
147
  *
148
148
  * Only returns STRUCTURAL changes in the `modified` field.
149
149
  */
150
- export function computeFingerprintDelta(
151
- baseline: Map<string, FileFingerprint>,
152
- current: Map<string, FileFingerprint>,
153
- ): FingerprintDelta {
150
+ export function computeFingerprintDelta(baseline: Map<string, FileFingerprint>, current: Map<string, FileFingerprint>): FingerprintDelta {
154
151
  const added: string[] = [];
155
152
  const removed: string[] = [];
156
153
  const modified: FileFingerprint[] = [];
@@ -44,7 +44,9 @@ function parseLines(raw: string): Record<string, string> {
44
44
  export function parseCsv(value: string | undefined): string[] | undefined {
45
45
  if (value === undefined) return undefined;
46
46
  // Handle quoted values with commas inside.
47
- const values = splitCsv(value).map((item) => item.trim()).filter(Boolean);
47
+ const values = splitCsv(value)
48
+ .map((item) => item.trim())
49
+ .filter(Boolean);
48
50
  return values.length > 0 ? [...new Set(values)] : undefined;
49
51
  }
50
52
 
@@ -1,5 +1,5 @@
1
- import * as fs from "node:fs";
2
1
  import type { FSWatcher, WatchListener } from "node:fs";
2
+ import * as fs from "node:fs";
3
3
 
4
4
  /**
5
5
  * Filesystem watcher helpers (slimmed down — pts/2 hang fix 2026-06-16).
@@ -25,11 +25,7 @@ export function closeWatcher(watcher: FSWatcher | null | undefined): void {
25
25
  }
26
26
  }
27
27
 
28
- export function watchWithErrorHandler(
29
- path: string,
30
- listener: WatchListener<string>,
31
- onError: (error?: unknown) => void,
32
- ): FSWatcher | null {
28
+ export function watchWithErrorHandler(path: string, listener: WatchListener<string>, onError: (error?: unknown) => void): FSWatcher | null {
33
29
  try {
34
30
  const watcher = fs.watch(path, listener);
35
31
  watcher.on("error", onError);