pi-crew 0.9.55 → 0.9.57

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 (309) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +58 -0
  3. package/README.md +53 -5
  4. package/dist/index.mjs +5666 -4370
  5. package/docs/README.md +54 -0
  6. package/package.json +12 -13
  7. package/skills/real-test-pi-crew/SKILL.md +93 -3
  8. package/src/agents/discover-agents.ts +68 -10
  9. package/src/benchmark/feedback-loop.ts +1 -1
  10. package/src/config/config.ts +2 -1
  11. package/src/config/types.ts +12 -0
  12. package/src/extension/action-suggestions.ts +16 -63
  13. package/src/extension/async-notifier.ts +3 -3
  14. package/src/extension/command-completions.ts +2 -2
  15. package/src/extension/crew-cleanup.ts +3 -3
  16. package/src/extension/crew-vibes/footer.ts +4 -2
  17. package/src/extension/cross-extension-rpc.ts +10 -5
  18. package/src/extension/knowledge-injection.ts +57 -10
  19. package/src/extension/register.ts +2 -2
  20. package/src/extension/registration/artifact-cleanup.ts +41 -3
  21. package/src/extension/registration/commands.ts +4 -4
  22. package/src/extension/registration/context-builder.ts +10 -10
  23. package/src/extension/registration/crash-recovery-cache.ts +3 -3
  24. package/src/extension/registration/foreground-run-controller.ts +1 -1
  25. package/src/extension/registration/lazy-configurers.ts +2 -2
  26. package/src/extension/registration/lifecycle-handlers.ts +12 -12
  27. package/src/extension/registration/lifecycle.ts +2 -2
  28. package/src/extension/registration/observability.ts +2 -2
  29. package/src/extension/registration/registration-types.ts +3 -3
  30. package/src/extension/registration/runtime-cleanup.ts +1 -1
  31. package/src/extension/registration/subagent-helpers.ts +2 -2
  32. package/src/extension/registration/subagent-manager-setup.ts +2 -2
  33. package/src/extension/registration/subagent-tools.ts +21 -16
  34. package/src/extension/registration/team-tool.ts +109 -17
  35. package/src/extension/registration/viewers.ts +3 -4
  36. package/src/extension/registration/wire-cross-extension.ts +7 -7
  37. package/src/extension/rpc-hmac.ts +3 -2
  38. package/src/extension/run-bundle-schema.ts +13 -4
  39. package/src/extension/run-export.ts +2 -2
  40. package/src/extension/run-index.ts +2 -3
  41. package/src/extension/run-maintenance.ts +57 -1
  42. package/src/extension/team-manager-command.ts +3 -1
  43. package/src/extension/team-tool/anchor.ts +8 -2
  44. package/src/extension/team-tool/api.ts +117 -39
  45. package/src/extension/team-tool/cancel.ts +23 -8
  46. package/src/extension/team-tool/chain-executor.ts +1 -1
  47. package/src/extension/team-tool/dispatch/automate.ts +17 -2
  48. package/src/extension/team-tool/dispatch/control.ts +17 -2
  49. package/src/extension/team-tool/dispatch/manage.ts +34 -2
  50. package/src/extension/team-tool/dispatch/run.ts +17 -2
  51. package/src/extension/team-tool/dispatch/status.ts +37 -5
  52. package/src/extension/team-tool/doctor.ts +2 -2
  53. package/src/extension/team-tool/explain.ts +1 -1
  54. package/src/extension/team-tool/goal-wrap.ts +5 -5
  55. package/src/extension/team-tool/goal.ts +30 -9
  56. package/src/extension/team-tool/handle-schedule.ts +37 -19
  57. package/src/extension/team-tool/inspect.ts +21 -5
  58. package/src/extension/team-tool/lifecycle-actions.ts +53 -10
  59. package/src/extension/team-tool/parallel-dispatch.ts +14 -5
  60. package/src/extension/team-tool/param-error.ts +138 -0
  61. package/src/extension/team-tool/respond.ts +20 -6
  62. package/src/extension/team-tool/run.ts +27 -17
  63. package/src/extension/team-tool/status.ts +17 -6
  64. package/src/extension/team-tool.ts +26 -19
  65. package/src/hooks/registry.ts +1 -1
  66. package/src/i18n.ts +22 -0
  67. package/src/observability/event-bus.ts +1 -1
  68. package/src/prompt/prompt-runtime.ts +2 -2
  69. package/src/runtime/README.md +35 -0
  70. package/src/runtime/agent-control.ts +1 -1
  71. package/src/runtime/anchor-manager.ts +0 -2
  72. package/src/runtime/async-runner.ts +1 -1
  73. package/src/runtime/attention-events.ts +3 -2
  74. package/src/runtime/auto-summarize.ts +0 -2
  75. package/src/runtime/background-runner.ts +103 -30
  76. package/src/runtime/{crew-broker-child.ts → broker/crew-broker-child.ts} +2 -2
  77. package/src/runtime/{crew-broker-client.ts → broker/crew-broker-client.ts} +4 -7
  78. package/src/runtime/{crew-broker.ts → broker/crew-broker.ts} +13 -21
  79. package/src/runtime/chain-runner.ts +50 -5
  80. package/src/runtime/{child-pi-constants.ts → child-pi/child-pi-constants.ts} +1 -1
  81. package/src/runtime/{child-pi-kill.ts → child-pi/child-pi-kill.ts} +3 -3
  82. package/src/runtime/{child-pi-spawn.ts → child-pi/child-pi-spawn.ts} +28 -12
  83. package/src/runtime/{child-pi-steering.ts → child-pi/child-pi-steering.ts} +1 -1
  84. package/src/runtime/{child-pi-streams.ts → child-pi/child-pi-streams.ts} +23 -4
  85. package/src/runtime/{child-pi-transcript.ts → child-pi/child-pi-transcript.ts} +6 -6
  86. package/src/runtime/{child-pi.ts → child-pi/child-pi.ts} +47 -78
  87. package/src/runtime/compaction/compact-stages/bounded-tail.ts +84 -0
  88. package/src/runtime/{compact-stages → compaction/compact-stages}/index.ts +2 -2
  89. package/src/runtime/{compaction-summary.ts → compaction/compaction-summary.ts} +3 -3
  90. package/src/runtime/{tool-output-pruner.ts → compaction/tool-output-pruner.ts} +1 -1
  91. package/src/runtime/crew-agent-records.ts +48 -2
  92. package/src/runtime/custom-tools/irc-tool.ts +2 -2
  93. package/src/runtime/delivery-coordinator.ts +0 -3
  94. package/src/runtime/diagnostic-export.ts +5 -4
  95. package/src/runtime/foreground-control.ts +1 -1
  96. package/src/runtime/foreground-watchdog.ts +1 -1
  97. package/src/runtime/{adaptive-plan.ts → goal-workflow/adaptive-plan.ts} +8 -8
  98. package/src/runtime/{dynamic-workflow-context.ts → goal-workflow/dynamic-workflow-context.ts} +16 -16
  99. package/src/runtime/{dynamic-workflow-runner.ts → goal-workflow/dynamic-workflow-runner.ts} +10 -10
  100. package/src/runtime/{goal-achievement.ts → goal-workflow/goal-achievement.ts} +3 -3
  101. package/src/runtime/{goal-evaluator.ts → goal-workflow/goal-evaluator.ts} +8 -8
  102. package/src/runtime/{goal-loop-runner.ts → goal-workflow/goal-loop-runner.ts} +27 -25
  103. package/src/runtime/{goal-state-store.ts → goal-workflow/goal-state-store.ts} +8 -8
  104. package/src/runtime/{plan-templates.ts → goal-workflow/plan-templates.ts} +1 -1
  105. package/src/runtime/group-join.ts +3 -3
  106. package/src/runtime/handoff-manager.ts +0 -2
  107. package/src/runtime/{heartbeat-watcher.ts → heartbeat/heartbeat-watcher.ts} +7 -7
  108. package/src/runtime/iteration-hooks.ts +1 -1
  109. package/src/runtime/{live-agent-control.ts → live-session/live-agent-control.ts} +2 -2
  110. package/src/runtime/{live-agent-manager.ts → live-session/live-agent-manager.ts} +4 -4
  111. package/src/runtime/{live-session-runtime.ts → live-session/live-session-runtime.ts} +39 -41
  112. package/src/runtime/manifest-cache.ts +6 -2
  113. package/src/runtime/{model-fallback.ts → model/model-fallback.ts} +1 -1
  114. package/src/runtime/{pi-args.ts → model/pi-args.ts} +20 -5
  115. package/src/runtime/model/provider-extensions.ts +116 -0
  116. package/src/runtime/{runtime-policy.ts → model/runtime-policy.ts} +2 -2
  117. package/src/runtime/{runtime-resolver.ts → model/runtime-resolver.ts} +3 -3
  118. package/src/runtime/{runtime-warmup.ts → model/runtime-warmup.ts} +8 -8
  119. package/src/runtime/orphan-worker-registry.ts +1 -1
  120. package/src/runtime/{progress-tracker.ts → output/progress-tracker.ts} +1 -1
  121. package/src/runtime/{result-extractor.ts → output/result-extractor.ts} +4 -4
  122. package/src/runtime/{sidechain-output.ts → output/sidechain-output.ts} +2 -2
  123. package/src/runtime/{stream-preview.ts → output/stream-preview.ts} +1 -1
  124. package/src/runtime/{streaming-output.ts → output/streaming-output.ts} +2 -2
  125. package/src/runtime/{tool-progress.ts → output/tool-progress.ts} +1 -1
  126. package/src/runtime/parent-guard.ts +30 -10
  127. package/src/runtime/pipeline-runner.ts +2 -2
  128. package/src/runtime/policy-engine.ts +2 -2
  129. package/src/runtime/{cancellation.ts → process/cancellation.ts} +1 -1
  130. package/src/runtime/{post-exit-stdio-guard.ts → process/post-exit-stdio-guard.ts} +1 -1
  131. package/src/runtime/{process-lifecycle.ts → process/process-lifecycle.ts} +3 -3
  132. package/src/runtime/{checkpoint.ts → recovery/checkpoint.ts} +4 -4
  133. package/src/runtime/{crash-recovery.ts → recovery/crash-recovery.ts} +93 -21
  134. package/src/runtime/{overflow-recovery.ts → recovery/overflow-recovery.ts} +1 -1
  135. package/src/runtime/{recovery-recipes.ts → recovery/recovery-recipes.ts} +1 -1
  136. package/src/runtime/{retry-executor.ts → recovery/retry-executor.ts} +2 -2
  137. package/src/runtime/{retry-runner.ts → recovery/retry-runner.ts} +2 -8
  138. package/src/runtime/run-tracker.ts +1 -1
  139. package/src/runtime/run-worker.ts +3 -3
  140. package/src/runtime/{coalesce-tasks.ts → scheduling/coalesce-tasks.ts} +3 -3
  141. package/src/runtime/{concurrency.ts → scheduling/concurrency.ts} +9 -3
  142. package/src/runtime/{parallel-research.ts → scheduling/parallel-research.ts} +4 -2
  143. package/src/runtime/{run-coalesced-task-group.ts → scheduling/run-coalesced-task-group.ts} +95 -36
  144. package/src/runtime/{semaphore.ts → scheduling/semaphore.ts} +4 -1
  145. package/src/runtime/{task-graph-scheduler.ts → scheduling/task-graph-scheduler.ts} +1 -1
  146. package/src/runtime/session-resources.ts +1 -1
  147. package/src/runtime/settings-store.ts +1 -1
  148. package/src/runtime/single-agent-compose.ts +1 -0
  149. package/src/runtime/stale-reconciler.ts +1 -1
  150. package/src/runtime/subagent-manager.ts +1 -1
  151. package/src/runtime/supervisor-contact.ts +28 -13
  152. package/src/runtime/task-output-context.ts +7 -5
  153. package/src/runtime/task-runner/child-executor.ts +67 -31
  154. package/src/runtime/task-runner/live-executor.ts +8 -8
  155. package/src/runtime/task-runner/post-execution.ts +12 -12
  156. package/src/runtime/task-runner/pre-execution.ts +6 -6
  157. package/src/runtime/task-runner/progress.ts +1 -1
  158. package/src/runtime/task-runner/run-projection.ts +1 -1
  159. package/src/runtime/task-runner/scaffold-executor.ts +1 -1
  160. package/src/runtime/task-runner/state-helpers.ts +2 -2
  161. package/src/runtime/task-runner.ts +4 -4
  162. package/src/runtime/team-runner.ts +441 -175
  163. package/src/runtime/{completion-guard.ts → verification/completion-guard.ts} +1 -1
  164. package/src/runtime/{green-contract.ts → verification/green-contract.ts} +1 -1
  165. package/src/runtime/{post-checks.ts → verification/post-checks.ts} +4 -4
  166. package/src/runtime/{verification-gates.ts → verification/verification-gates.ts} +5 -5
  167. package/src/runtime/{verification-integrity.ts → verification/verification-integrity.ts} +1 -1
  168. package/src/schema/config-schema.ts +1 -0
  169. package/src/schema/team-tool-schema.ts +149 -185
  170. package/src/state/README.md +44 -0
  171. package/src/state/atomic-write.ts +24 -3
  172. package/src/state/{locks.ts → coordination/locks.ts} +118 -38
  173. package/src/state/{mailbox.ts → coordination/mailbox.ts} +14 -8
  174. package/src/state/{schedule.ts → coordination/schedule.ts} +3 -3
  175. package/src/state/{task-claims.ts → coordination/task-claims.ts} +1 -1
  176. package/src/state/decision-ledger.ts +1 -1
  177. package/src/state/{event-log-rotation.ts → event-log/event-log-rotation.ts} +189 -31
  178. package/src/state/{event-log.ts → event-log/event-log.ts} +77 -39
  179. package/src/state/{jsonl-writer.ts → event-log/jsonl-writer.ts} +14 -6
  180. package/src/state/hook-instinct-bridge.ts +2 -2
  181. package/src/state/{active-run-registry.ts → stores/active-run-registry.ts} +7 -7
  182. package/src/state/{artifact-store.ts → stores/artifact-store.ts} +62 -4
  183. package/src/state/{blob-store.ts → stores/blob-store.ts} +3 -3
  184. package/src/state/{health-store.ts → stores/health-store.ts} +3 -3
  185. package/src/state/{instinct-store.ts → stores/instinct-store.ts} +3 -3
  186. package/src/state/{observation-store.ts → stores/observation-store.ts} +2 -2
  187. package/src/state/{run-cache.ts → stores/run-cache.ts} +4 -4
  188. package/src/state/{run-graph.ts → stores/run-graph.ts} +4 -4
  189. package/src/state/{run-metrics.ts → stores/run-metrics.ts} +3 -3
  190. package/src/state/{state-store.ts → stores/state-store.ts} +254 -21
  191. package/src/state/types.ts +27 -3
  192. package/src/ui/component.ts +55 -0
  193. package/src/ui/crew-select-list.ts +3 -1
  194. package/src/ui/dashboard-panes/agents-pane.ts +1 -1
  195. package/src/ui/dwf-phase-display.ts +1 -1
  196. package/src/ui/heartbeat-aggregator.ts +1 -1
  197. package/src/ui/keybinding-map.ts +179 -6
  198. package/src/ui/layout-primitives.ts +9 -5
  199. package/src/ui/live-conversation-overlay.ts +1 -1
  200. package/src/ui/live-run-sidebar.ts +1 -1
  201. package/src/ui/overlay-stack.ts +148 -0
  202. package/src/ui/overlays/agent-picker-overlay.ts +1 -1
  203. package/src/ui/overlays/mailbox-compose-overlay.ts +1 -1
  204. package/src/ui/overlays/mailbox-detail-overlay.ts +2 -2
  205. package/src/ui/powerbar-publisher.ts +1 -1
  206. package/src/ui/render-scheduler.ts +1 -1
  207. package/src/ui/run-action-dispatcher.ts +3 -3
  208. package/src/ui/run-dashboard.ts +5 -33
  209. package/src/ui/run-event-bus.ts +3 -3
  210. package/src/ui/run-snapshot-cache.ts +37 -18
  211. package/src/ui/settings-overlay.ts +13 -21
  212. package/src/ui/snapshot-types.ts +1 -1
  213. package/src/ui/status-colors.ts +0 -2
  214. package/src/ui/terminal-status.ts +1 -1
  215. package/src/ui/theme-adapter.ts +33 -13
  216. package/src/ui/tool-renderers/index.ts +8 -0
  217. package/src/ui/transcript-viewer.ts +37 -13
  218. package/src/ui/widget/index.ts +32 -9
  219. package/src/ui/widget/widget-formatters.ts +62 -4
  220. package/src/ui/widget/widget-model.ts +2 -2
  221. package/src/ui/widget/widget-renderer.ts +1 -1
  222. package/src/utils/conflict-detect.ts +58 -5
  223. package/src/utils/ndjson.ts +2 -2
  224. package/src/utils/redaction.ts +39 -0
  225. package/src/utils/socket-path.ts +1 -1
  226. package/src/workflows/workflow-config.ts +1 -1
  227. package/src/worktree/cleanup.ts +1 -1
  228. package/src/worktree/worktree-manager.ts +111 -47
  229. package/workflows/chain.workflow.md +2 -2
  230. package/dist/build-meta.json +0 -16807
  231. package/index.bundle.ts +0 -25
  232. package/scripts/bench-check.mjs +0 -96
  233. package/scripts/bench-cold-start.mjs +0 -216
  234. package/scripts/build-bundle.mjs +0 -92
  235. package/scripts/check-all-skills.ts +0 -294
  236. package/scripts/check-bundle-size.mjs +0 -38
  237. package/scripts/check-bundle-staleness.mjs +0 -97
  238. package/scripts/check-conflict-markers.mjs +0 -91
  239. package/scripts/check-lazy-imports.mjs +0 -28
  240. package/scripts/dev-runner.mjs +0 -106
  241. package/scripts/profile-startup.mjs +0 -125
  242. package/scripts/release-smoke.mjs +0 -74
  243. package/scripts/run-bench.mjs +0 -47
  244. package/scripts/run-real-chain.ts +0 -41
  245. package/scripts/test-issue-29-crash.ts +0 -111
  246. package/scripts/test-issue-29-e2e.ts +0 -183
  247. package/scripts/test-issue-29-real-runtime.ts +0 -330
  248. package/scripts/test-issue-29-real-tasks.ts +0 -387
  249. package/scripts/test-issue-29-team-tool.ts +0 -105
  250. package/scripts/test-runner.mjs +0 -84
  251. package/scripts/verify-flicker-fix.ts +0 -109
  252. package/scripts/verify-skill.ts +0 -550
  253. package/scripts/watch-bundle.mjs +0 -259
  254. package/scripts/watchdog-harness.ts +0 -119
  255. package/src/adapters/claude-adapter.ts +0 -23
  256. package/src/adapters/codex-adapter.ts +0 -21
  257. package/src/adapters/cursor-adapter.ts +0 -17
  258. package/src/adapters/export-util.ts +0 -143
  259. package/src/adapters/index.ts +0 -15
  260. package/src/adapters/registry.ts +0 -18
  261. package/src/adapters/types.ts +0 -23
  262. package/src/runtime/code-summary.ts +0 -292
  263. package/src/runtime/cross-extension-rpc.ts +0 -143
  264. package/src/runtime/hidden-handoff.ts +0 -407
  265. package/src/runtime/prose-compressor.ts +0 -162
  266. package/src/subagents/async-entry.ts +0 -1
  267. package/src/subagents/index.ts +0 -3
  268. package/src/subagents/live/control.ts +0 -1
  269. package/src/subagents/live/manager.ts +0 -1
  270. package/src/subagents/live/realtime.ts +0 -1
  271. package/src/subagents/live/session-runtime.ts +0 -1
  272. package/src/subagents/manager.ts +0 -1
  273. package/src/subagents/spawn.ts +0 -1
  274. package/test-integration-check.ts +0 -118
  275. /package/src/runtime/{broker-issuer.ts → broker/broker-issuer.ts} +0 -0
  276. /package/src/runtime/{crew-broker-tokens.ts → broker/crew-broker-tokens.ts} +0 -0
  277. /package/src/runtime/{child-pi-pool.ts → child-pi/child-pi-pool.ts} +0 -0
  278. /package/src/runtime/{compact-pipeline.ts → compaction/compact-pipeline.ts} +0 -0
  279. /package/src/runtime/{compact-stages → compaction/compact-stages}/ansi-strip-stage.ts +0 -0
  280. /package/src/runtime/{compact-stages → compaction/compact-stages}/blank-collapse-stage.ts +0 -0
  281. /package/src/runtime/{compact-stages → compaction/compact-stages}/deduplicate-stage.ts +0 -0
  282. /package/src/runtime/{compact-stages → compaction/compact-stages}/head-snap-stage.ts +0 -0
  283. /package/src/runtime/{compact-stages → compaction/compact-stages}/tail-capture-stage.ts +0 -0
  284. /package/src/runtime/{compact-stages → compaction/compact-stages}/truncation-stage.ts +0 -0
  285. /package/src/runtime/{important-line-classifier.ts → compaction/important-line-classifier.ts} +0 -0
  286. /package/src/runtime/{heartbeat-gradient.ts → heartbeat/heartbeat-gradient.ts} +0 -0
  287. /package/src/runtime/{worker-heartbeat.ts → heartbeat/worker-heartbeat.ts} +0 -0
  288. /package/src/runtime/{worker-startup.ts → heartbeat/worker-startup.ts} +0 -0
  289. /package/src/runtime/{intercom-bridge.ts → live-session/intercom-bridge.ts} +0 -0
  290. /package/src/runtime/{live-control-realtime.ts → live-session/live-control-realtime.ts} +0 -0
  291. /package/src/runtime/{live-extension-bridge.ts → live-session/live-extension-bridge.ts} +0 -0
  292. /package/src/runtime/{live-irc.ts → live-session/live-irc.ts} +0 -0
  293. /package/src/runtime/{live-session-health.ts → live-session/live-session-health.ts} +0 -0
  294. /package/src/runtime/{model-resolver.ts → model/model-resolver.ts} +0 -0
  295. /package/src/runtime/{model-scope.ts → model/model-scope.ts} +0 -0
  296. /package/src/runtime/{output-validator.ts → output/output-validator.ts} +0 -0
  297. /package/src/runtime/{pi-json-output.ts → output/pi-json-output.ts} +0 -0
  298. /package/src/runtime/{progress-event-coalescer.ts → output/progress-event-coalescer.ts} +0 -0
  299. /package/src/runtime/{cancellation-token.ts → process/cancellation-token.ts} +0 -0
  300. /package/src/runtime/{zombie-scanner.ts → process/zombie-scanner.ts} +0 -0
  301. /package/src/runtime/{crash-classification.ts → recovery/crash-classification.ts} +0 -0
  302. /package/src/runtime/{batch-barrier.ts → scheduling/batch-barrier.ts} +0 -0
  303. /package/src/runtime/{global-worker-cap.ts → scheduling/global-worker-cap.ts} +0 -0
  304. /package/src/runtime/{parallel-utils.ts → scheduling/parallel-utils.ts} +0 -0
  305. /package/src/runtime/{scheduler.ts → scheduling/scheduler.ts} +0 -0
  306. /package/src/runtime/{task-graph.ts → scheduling/task-graph.ts} +0 -0
  307. /package/src/runtime/{verification-worktree.ts → verification/verification-worktree.ts} +0 -0
  308. /package/src/state/{event-reconstructor.ts → event-log/event-reconstructor.ts} +0 -0
  309. /package/src/state/{worker-atomic-writer.ts → event-log/worker-atomic-writer.ts} +0 -0
@@ -1,14 +1,16 @@
1
1
  import { statSync } from "node:fs";
2
2
  import type { ExtensionAPI, ExtensionContext, ToolDefinition } from "@earendil-works/pi-coding-agent";
3
3
  import { Text } from "@earendil-works/pi-tui";
4
+ import type { TObject } from "@sinclair/typebox";
4
5
  import { Value } from "@sinclair/typebox/value";
5
6
  import { loadConfig } from "../../config/config.ts";
7
+ import { findClosestKey } from "../../config/suggestions.ts";
6
8
  import type { MetricRegistry } from "../../observability/metric-registry.ts";
7
9
  import type { createManifestCache } from "../../runtime/manifest-cache.ts";
8
10
  import { TeamToolParams, type TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
9
11
  import { updatePiCrewPowerbar } from "../../ui/powerbar-publisher.ts";
10
12
  import type { createRunSnapshotCache } from "../../ui/run-snapshot-cache.ts";
11
- import { statusIcon, teamToolRenderer } from "../../ui/tool-renderers/index.ts";
13
+ import { statusIcon, type ToolRenderContext, teamToolRenderer } from "../../ui/tool-renderers/index.ts";
12
14
  import type { CrewWidgetState } from "../../ui/widget/index.ts";
13
15
  import { updateCrewWidget } from "../../ui/widget/index.ts";
14
16
  import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
@@ -29,12 +31,39 @@ async function handleTeamTool(
29
31
  }
30
32
 
31
33
  import { readCrewAgents } from "../../runtime/crew-agent-records.ts";
32
- import { loadRunManifestById } from "../../state/state-store.ts";
34
+ import type { CrewAgentRecord } from "../../runtime/crew-agent-runtime.ts";
35
+ import { loadRunManifestById } from "../../state/stores/state-store.ts";
33
36
  import { formatCompactToolProgress } from "../../ui/tool-progress-formatter.ts";
34
37
  import { logInternalError } from "../../utils/internal-error.ts";
35
38
  import { withSessionId } from "../team-tool/context.ts";
39
+ import { formatTeamToolParamError } from "../team-tool/param-error.ts";
36
40
  import { toolResult } from "../tool-result.ts";
37
41
 
42
+ /**
43
+ * Normalize model-generated tool params before schema validation.
44
+ *
45
+ * Calling models (esp. Claude-style tool callers, incl. deepseek-via-commandcode)
46
+ * routinely emit EVERY schema key with a default/empty value ("", 0, false)
47
+ * rather than omitting it. Strict TypeBox unions/patterns then reject the call
48
+ * even though the intent was "unset": e.g. `runId: ""` fails the
49
+ * `^[A-Za-z0-9_-]+$` pattern, `workspaceMode: ""` fails the
50
+ * Literal("single"|"worktree") union, `context: ""` / `scope: ""` likewise.
51
+ *
52
+ * Only EMPTY string values are dropped — non-empty strings, booleans, numbers,
53
+ * arrays, objects are preserved verbatim so genuine invalid values still fail
54
+ * validation with a helpful message.
55
+ */
56
+ export function normalizeTeamParams(params: unknown): unknown {
57
+ if (typeof params !== "object" || params === null || Array.isArray(params)) return params;
58
+ const p = params as Record<string, unknown>;
59
+ const out: Record<string, unknown> = {};
60
+ for (const [key, value] of Object.entries(p)) {
61
+ if (typeof value === "string" && value.trim() === "") continue; // drop empty-string "unset" values
62
+ out[key] = value;
63
+ }
64
+ return out;
65
+ }
66
+
38
67
  const TEAM_TOOL_PROGRESS_TICK_MS = 1000;
39
68
 
40
69
  type OnUpdate = (chunk: { content: { type: "text"; text: string }[] }) => void;
@@ -71,22 +100,72 @@ export function resolveCwdOverride(
71
100
  }
72
101
  }
73
102
 
103
+ /**
104
+ * EXT-1: detect unrecognized (likely typo'd) parameter field names.
105
+ *
106
+ * `TeamToolParams` is declared with `additionalProperties: true`, so TypeBox
107
+ * `Value.Check` does NOT reject unknown keys. A mistyped call like
108
+ * `{ action: "run", goals: "..." }` (typo `goals` vs `goal`) passes validation,
109
+ * the handler then reads `params.goal` (undefined) and returns a generic
110
+ * "Run requires goal or task." with ZERO hint about the typo — so calling
111
+ * agents (LLMs) loop indefinitely on the same malformed shape.
112
+ *
113
+ * This scans `params` for keys absent from `schema.properties` (`action` is
114
+ * excluded — it is validated separately by the schema enum) and, for each
115
+ * unknown key, suggests the closest known field via Levenshtein distance.
116
+ *
117
+ * @returns A multi-line actionable error message, or `null` when every key
118
+ * is recognized.
119
+ */
120
+ export function detectUnrecognizedParams(schema: TObject, params: unknown): string | null {
121
+ if (typeof params !== "object" || params === null || Array.isArray(params)) return null;
122
+ const knownKeys = Object.keys(schema.properties ?? {});
123
+ const knownSet = new Set(knownKeys);
124
+
125
+ const p = params as Record<string, unknown>;
126
+ const unknowns: string[] = [];
127
+ for (const key of Object.keys(p)) {
128
+ if (key === "action") continue; // validated separately by the schema action enum
129
+ if (!knownSet.has(key)) unknowns.push(key);
130
+ }
131
+ if (unknowns.length === 0) return null;
132
+
133
+ // Suggest the closest known field for each typo (action excluded as a candidate).
134
+ const candidates = knownKeys.filter((k) => k !== "action");
135
+ const hints = unknowns.map((key) => {
136
+ const closest = findClosestKey(key, candidates);
137
+ return closest ? `Unrecognized field '${key}' — did you mean '${closest}'?` : `Unrecognized field '${key}'.`;
138
+ });
139
+
140
+ return [
141
+ `Unrecognized team tool parameter field${unknowns.length > 1 ? "s" : ""}:`,
142
+ ...hints.map((h) => ` • ${h}`),
143
+ "",
144
+ "Check the field name spelling against the schema. Common fields:",
145
+ "action, goal, team, runId, task, role, agent, workflow, model, cwd.",
146
+ ].join("\n");
147
+ }
148
+
74
149
  export function registerTeamTool(pi: ExtensionAPI, deps: RegisterTeamToolDeps): void {
75
150
  const tool: ToolDefinition = {
76
151
  name: "team",
77
152
  label: "Team",
153
+ // EXT-11: do NOT embed one-off performance benchmarks ("Run #3", "~30× faster",
154
+ // "5.7× slower", etc.) in the tool description — they are stale, do not
155
+ // generalize, and mislead the calling LLM about when to reach for the
156
+ // team tool. Keep factual usage guidance (what the tool does, preflight
157
+ // advisory behavior, action='recommend').
78
158
  description: [
79
159
  "Coordinate Pi teams. Use proactively for complex multi-file work, planning, implementation, tests, reviews, security audits, research, async/background runs, and worktree-isolated execution. Use action='recommend' when unsure which team/workflow to choose. Destructive actions require explicit user confirmation.",
80
160
  "",
81
161
  "ℹ️ ADVISORY NOTE (preflight, never blocks): pi-crew prints informational notes about workflow topology. Review the note, then decide. There is no BLOCK — agents always exercise judgment.",
82
- "- Single-task run: raw `Agent` tool would be ~30× faster and ~5× cheaper. pi-crew notes this and proceeds anyway.",
83
- "- 2–3 step sequential run: measured 5.7× slower than raw `Agent` calls in Run #3. pi-crew notes this and proceeds anyway.",
84
- "- ≥3 concurrent or complex DAG: validated good use case, pi-crew notes 'validated use case'.",
162
+ "- Single-task or 2–3 step sequential run: pi-crew notes that a raw `Agent` call may be simpler and faster, then proceeds anyway.",
163
+ "- ≥3 concurrent or complex DAG: validated good use case; pi-crew notes 'validated use case'.",
85
164
  "If unsure, call { action: 'recommend', goal } first to get a team/workflow suggestion.",
86
165
  ].join("\n"),
87
166
  promptSnippet: [
88
167
  "Use the team tool for multi-agent orchestration when you need ≥3 concurrent agents or a complex DAG.",
89
- "For single tasks or 2–3 sequential steps, the raw Agent tool is usually faster (raw calls = ~5× faster for 3-step chains).",
168
+ "For single tasks or 2–3 sequential steps, the raw Agent tool is usually faster.",
90
169
  "pi-crew notes the topology (informational only) but proceeds either way — you decide based on your context (audit trail, team coordination, etc.).",
91
170
  "If unsure, call { action: 'recommend', goal } first.",
92
171
  ].join("\n"),
@@ -99,11 +178,21 @@ export function registerTeamTool(pi: ExtensionAPI, deps: RegisterTeamToolDeps):
99
178
  signal?.addEventListener("abort", abort, { once: true });
100
179
  const stopProgress = startTeamToolProgressBinder(onUpdate as OnUpdate | undefined);
101
180
  try {
181
+ // Models emit empty-string defaults for unset keys; drop them BEFORE
182
+ // validation so strict unions/patterns accept "unset" as omitted.
183
+ const normalized = normalizeTeamParams(params);
102
184
  // Defense-in-depth: validate params at runtime even though Pi framework already does
103
- if (!Value.Check(TeamToolParams, params)) {
104
- return toolResult("Invalid team tool parameters", { action: "list", status: "error" }, true);
185
+ if (!Value.Check(TeamToolParams, normalized)) {
186
+ return toolResult(formatTeamToolParamError(TeamToolParams, normalized), { action: "list", status: "error" }, true);
187
+ }
188
+ // EXT-1: additionalProperties:true lets unknown (typo'd) keys slip past
189
+ // Value.Check. Catch them here and suggest the closest known field so
190
+ // the caller gets an actionable hint instead of a generic handler error.
191
+ const typoError = detectUnrecognizedParams(TeamToolParams, normalized);
192
+ if (typoError) {
193
+ return toolResult(typoError, { action: "list", status: "error" }, true);
105
194
  }
106
- const resolved = params as TeamToolParamsValue;
195
+ const resolved = normalized as TeamToolParamsValue;
107
196
  const cwdOverride = resolveCwdOverride(ctx.cwd, resolved.cwd);
108
197
  if (!cwdOverride.ok) return toolResult(cwdOverride.error, { action: resolved.action ?? "list", status: "error" }, true);
109
198
  const toolCtx = withSessionId({ ...ctx, cwd: cwdOverride.cwd });
@@ -148,14 +237,17 @@ export function registerTeamTool(pi: ExtensionAPI, deps: RegisterTeamToolDeps):
148
237
  stopProgress.stop();
149
238
  }
150
239
  },
151
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
152
- renderCall(args: any, theme: any, context: any): any {
153
- return teamToolRenderer.renderCall(args, theme, context);
240
+ renderCall(args, theme, context) {
241
+ return teamToolRenderer.renderCall(args as Record<string, unknown>, theme, context as ToolRenderContext);
154
242
  },
155
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
156
- renderResult(result: any, options: any, theme: any, context: any): any {
243
+ renderResult(result, options, theme, context) {
157
244
  try {
158
- return teamToolRenderer.renderResult(result, options, theme, context);
245
+ return teamToolRenderer.renderResult(
246
+ result as unknown as Record<string, unknown>,
247
+ options,
248
+ theme,
249
+ context as ToolRenderContext,
250
+ );
159
251
  } catch {
160
252
  return new Text(statusIcon("completed", theme) + " done", 0, 0);
161
253
  }
@@ -171,7 +263,7 @@ interface TeamToolProgressBinder {
171
263
 
172
264
  function startTeamToolProgressBinder(onUpdate: OnUpdate | undefined): TeamToolProgressBinder {
173
265
  if (!onUpdate) {
174
- return { attach: () => {}, stop: () => {} };
266
+ return { attach: () => undefined, stop: () => undefined };
175
267
  }
176
268
  const startedAt = Date.now();
177
269
  let cwd: string | undefined;
@@ -191,7 +283,7 @@ function startTeamToolProgressBinder(onUpdate: OnUpdate | undefined): TeamToolPr
191
283
  onUpdate({ content: [{ type: "text", text: msg }] });
192
284
  return;
193
285
  }
194
- let agents;
286
+ let agents: CrewAgentRecord[] | undefined;
195
287
  try {
196
288
  agents = readCrewAgents(loaded.manifest);
197
289
  } catch {
@@ -1,8 +1,8 @@
1
1
  import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
2
  import { loadConfig } from "../../config/config.ts";
3
3
  import { readCrewAgents } from "../../runtime/crew-agent-records.ts";
4
- import { listLiveAgents } from "../../runtime/live-agent-manager.ts";
5
- import { loadRunManifestById } from "../../state/state-store.ts";
4
+ import { listLiveAgents } from "../../runtime/live-session/live-agent-manager.ts";
5
+ import { loadRunManifestById } from "../../state/stores/state-store.ts";
6
6
  import { LiveConversationOverlay } from "../../ui/live-conversation-overlay.ts";
7
7
  import { asCrewTheme } from "../../ui/theme-adapter.ts";
8
8
  // Lazy-loaded: DurableTranscriptViewer is 658ms — only needed for /crew transcript command
@@ -84,9 +84,8 @@ export async function openLiveConversation(
84
84
  const handle = liveAgents.find((h) => h.runId === selected.runId && (selected.taskId ? h.taskId === selected.taskId : true));
85
85
  if (!handle) return false;
86
86
  const theme = asCrewTheme({});
87
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
88
87
  await ctx.ui.custom<undefined>(
89
- (tui: any, _theme: any, _keybindings: any, done: (result: undefined) => void) => {
88
+ (tui, _theme, _keybindings, done) => {
90
89
  const columns = tui?.terminal?.columns ?? 80;
91
90
  const rows = tui?.terminal?.rows ?? 24;
92
91
  const overlay = new LiveConversationOverlay(handle, theme, columns, rows);
@@ -4,10 +4,10 @@
4
4
  * Two small wires:
5
5
  * • wireRpc — the in-process pi-crew RPC handle (other modules in
6
6
  * the same extension can subscribe via `pi.events`).
7
- * • wireGlobalRegistry — the cross-extension crew global registry,
8
- * lazily loaded from team-tool.ts (heavy module) and installed under
9
- * `globalThis[Symbol.for("pi-crew:registry")]` so peer extensions
10
- * (e.g., pi-subagents3) can discover pi-crew at runtime.
7
+ * • wireGlobalRegistry — the crew registry, lazily loaded from
8
+ * team-tool.ts (heavy module) and installed in module-scoped state so
9
+ * the rest of pi-crew can discover pi-crew's RPC handle at runtime
10
+ * (EXT-9: no longer on globalThis[Symbol.for(...)]).
11
11
  */
12
12
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
13
13
  import { registerPiCrewRpc } from "../cross-extension-rpc.ts";
@@ -24,9 +24,9 @@ export function installCrossExtensionWiring(pi: ExtensionAPI, ctx: RegistrationC
24
24
  };
25
25
  ctx.rpcHandle = registerPiCrewRpc(getPiEvents(), () => ctx.currentCtx);
26
26
 
27
- // Install the cross-extension crew global registry. Lazy import keeps
28
- // team-tool.ts (which pulls in the entire runtime chain) out of the
29
- // cold-start module graph.
27
+ // Install the crew registry. Lazy import keeps team-tool.ts (which pulls
28
+ // in the entire runtime chain) out of the cold-start module graph. EXT-9:
29
+ // the registry now lives in module-scoped state, not globalThis.
30
30
  void import("../team-tool.ts").then(({ installCrewGlobalRegistry }) => {
31
31
  const manifestCacheForRegistry = ctx.getManifestCache(ctx.currentCtx?.cwd ?? process.cwd());
32
32
  installCrewGlobalRegistry({
@@ -134,8 +134,9 @@ export function verifyRpcSignature(payload: RpcSignedPayload, body: unknown): {
134
134
  export function withHmacVerification<P extends { requestId: string }>(
135
135
  handler: (params: P) => unknown | Promise<unknown>,
136
136
  _channel: string,
137
- ): (params: P) => unknown | Promise<unknown> {
138
- return (params: P) => {
137
+ ): (raw: unknown) => unknown | Promise<unknown> {
138
+ return (raw: unknown) => {
139
+ const params = raw as P;
139
140
  if (!isHmacEnabled()) {
140
141
  // No secret configured → backward compat: allow unsigned.
141
142
  // Emit a soft info note (once per process) only when an actual RPC
@@ -1,5 +1,5 @@
1
1
  import { isTeamRunStatus, isTeamTaskStatus } from "../state/contracts.ts";
2
- import type { TeamEvent } from "../state/event-log.ts";
2
+ import type { TeamEvent } from "../state/event-log/event-log.ts";
3
3
  import type { ArtifactDescriptor, TeamRunManifest, TeamTaskState } from "../state/types.ts";
4
4
  import type { ExportedRunBundle } from "./run-export.ts";
5
5
 
@@ -52,7 +52,10 @@ function validateManifest(value: unknown, errors: string[]): value is TeamRunMan
52
52
  if (value.workspaceMode !== "single" && value.workspaceMode !== "worktree")
53
53
  errors.push("manifest.workspaceMode must be single or worktree.");
54
54
  if (!Array.isArray(value.artifacts)) errors.push("manifest.artifacts must be an array.");
55
- else value.artifacts.forEach((artifact, index) => validateArtifact(artifact, index, errors));
55
+ else
56
+ value.artifacts.forEach((artifact, index) => {
57
+ validateArtifact(artifact, index, errors);
58
+ });
56
59
  return errors.length === before;
57
60
  }
58
61
 
@@ -89,9 +92,15 @@ export function validateRunBundle(value: unknown): BundleValidationResult {
89
92
  if (typeof value.exportedAt !== "string") errors.push("exportedAt must be a string.");
90
93
  validateManifest(value.manifest, errors);
91
94
  if (!Array.isArray(value.tasks)) errors.push("tasks must be an array.");
92
- else value.tasks.forEach((task, index) => validateTask(task, index, errors));
95
+ else
96
+ value.tasks.forEach((task, index) => {
97
+ validateTask(task, index, errors);
98
+ });
93
99
  if (!Array.isArray(value.events)) errors.push("events must be an array.");
94
- else value.events.forEach((event, index) => validateEvent(event, index, errors));
100
+ else
101
+ value.events.forEach((event, index) => {
102
+ validateEvent(event, index, errors);
103
+ });
95
104
  if (!Array.isArray(value.artifactPaths) || !value.artifactPaths.every((item) => typeof item === "string"))
96
105
  errors.push("artifactPaths must be an array of strings.");
97
106
  return { ok: errors.length === 0, errors };
@@ -2,8 +2,8 @@ import * as crypto from "node:crypto";
2
2
  import * as fs from "node:fs";
3
3
  import * as os from "node:os";
4
4
  import * as path from "node:path";
5
- import { writeArtifact } from "../state/artifact-store.ts";
6
- import { readEvents, type TeamEvent } from "../state/event-log.ts";
5
+ import { readEvents, type TeamEvent } from "../state/event-log/event-log.ts";
6
+ import { writeArtifact } from "../state/stores/artifact-store.ts";
7
7
  import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
8
8
  import { redactSecrets } from "../utils/redaction.ts";
9
9
 
@@ -2,8 +2,8 @@ import * as fs from "node:fs";
2
2
  import * as os from "node:os";
3
3
  import * as path from "node:path";
4
4
  import { DEFAULT_PATHS } from "../config/defaults.ts";
5
- import { createCancellationToken } from "../runtime/cancellation-token.ts";
6
- import { activeRunEntries } from "../state/active-run-registry.ts";
5
+ import { createCancellationToken } from "../runtime/process/cancellation-token.ts";
6
+ import { activeRunEntries } from "../state/stores/active-run-registry.ts";
7
7
  import type { TeamRunManifest } from "../state/types.ts";
8
8
  import { findRepoRoot, projectCrewRoot, userCrewRoot } from "../utils/paths.ts";
9
9
  import { isSafePathId, resolveRealContainedPath } from "../utils/safe-paths.ts";
@@ -124,7 +124,6 @@ export function listRunsByScope(
124
124
  return projectRoot ? collectRuns(projectCrewRoot(cwd), max, signal) : [];
125
125
  case "user":
126
126
  return collectRuns(userCrewRoot(), max, signal);
127
- case "all":
128
127
  default:
129
128
  return max !== undefined ? listRecentRuns(cwd, max, signal) : listRuns(cwd, signal);
130
129
  }
@@ -1,7 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { DEFAULT_PATHS } from "../config/defaults.ts";
4
- import { createCancellationToken } from "../runtime/cancellation-token.ts";
4
+ import { createCancellationToken } from "../runtime/process/cancellation-token.ts";
5
5
  import type { TeamRunManifest } from "../state/types.ts";
6
6
  import { logInternalError } from "../utils/internal-error.ts";
7
7
  import { projectCrewRoot, userCrewRoot } from "../utils/paths.ts";
@@ -21,6 +21,56 @@ export interface PruneRunsOptions {
21
21
  signal?: AbortSignal;
22
22
  }
23
23
 
24
+ /**
25
+ * Default age threshold for stale .corrupt-* quarantine files: 7 days.
26
+ * Quarantined manifests older than this are deleted to prevent unbounded growth.
27
+ */
28
+ export const DEFAULT_CORRUPT_FILE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
29
+
30
+ /**
31
+ * Sweep and delete .corrupt-* files older than maxAgeMs in a runs directory tree.
32
+ *
33
+ * These files are created by crash-recovery's purgeStaleActiveRunIndex when a
34
+ * manifest fails to parse (SyntaxError) or encounters an unexpected error.
35
+ * Without this sweep, they accumulate indefinitely across runs.
36
+ *
37
+ * @param runsDir Absolute path to the runs directory (<crewRoot>/state/runs/)
38
+ * @returns count of stale .corrupt-* files deleted
39
+ */
40
+ export function sweepStaleCorruptFiles(runsDir: string, maxAgeMs = DEFAULT_CORRUPT_FILE_TTL_MS, now = Date.now()): number {
41
+ let deleted = 0;
42
+ let runDirs: fs.Dirent[];
43
+ try {
44
+ runDirs = fs.readdirSync(runsDir, { withFileTypes: true });
45
+ } catch {
46
+ return 0;
47
+ }
48
+ for (const dir of runDirs) {
49
+ if (!dir.isDirectory()) continue;
50
+ const runDirPath = path.join(runsDir, dir.name);
51
+ let files: string[];
52
+ try {
53
+ files = fs.readdirSync(runDirPath);
54
+ } catch {
55
+ continue;
56
+ }
57
+ for (const file of files) {
58
+ if (!file.includes(".corrupt-")) continue;
59
+ const filePath = path.join(runDirPath, file);
60
+ try {
61
+ const mtime = fs.statSync(filePath).mtimeMs;
62
+ if (now - mtime > maxAgeMs) {
63
+ fs.unlinkSync(filePath);
64
+ deleted++;
65
+ }
66
+ } catch {
67
+ // Best effort — file may have been removed concurrently
68
+ }
69
+ }
70
+ }
71
+ return deleted;
72
+ }
73
+
24
74
  function isFinished(run: TeamRunManifest): boolean {
25
75
  // P3: "blocked" is NOT a terminal status — the run is waiting on something
26
76
  // (plan approval, mailbox reply, scheduler stall) and can transition to
@@ -98,6 +148,9 @@ export function pruneFinishedRuns(cwd: string, keep: number, options: PruneRunsO
98
148
  fs.rmSync(run.artifactsRoot, { recursive: true, force: true });
99
149
  removed.push(run.runId);
100
150
  }
151
+ // ST-6: Sweep stale .corrupt-* quarantine files to prevent unbounded growth.
152
+ sweepStaleCorruptFiles(path.join(projectCrewRoot(cwd), DEFAULT_PATHS.state.runsSubdir));
153
+
101
154
  const auditPath = appendPruneAudit(cwd, {
102
155
  action: "prune",
103
156
  keep,
@@ -186,5 +239,8 @@ export function pruneUserLevelRuns(keep: number): PruneRunsResult {
186
239
  removed.push(run.runId);
187
240
  }
188
241
 
242
+ // ST-6: Sweep stale .corrupt-* quarantine files at user level too.
243
+ sweepStaleCorruptFiles(runsRoot);
244
+
189
245
  return { kept, removed: [...removed, ...ghostRemoved] };
190
246
  }
@@ -148,6 +148,8 @@ export async function handleTeamManagerCommand(_args: string, ctx: ExtensionComm
148
148
  "Force cleanup?",
149
149
  "Force may remove dirty worktrees. Choose false to preserve dirty worktrees and capture cleanup diffs.",
150
150
  );
151
- await notifyResult(ctx, await handleTeamTool({ action: "cleanup", runId, force }, ctx));
151
+ // SEC-5: confirm:true is implicit — the user explicitly invoked cleanup
152
+ // via the UI picker, so the self-enforcement guard is satisfied.
153
+ await notifyResult(ctx, await handleTeamTool({ action: "cleanup", runId, force, confirm: true }, ctx));
152
154
  }
153
155
  }
@@ -3,7 +3,13 @@
3
3
  * Provides set/clear/status commands for anchor points.
4
4
  */
5
5
 
6
- import { type AnchorManager, AnchorNotFoundError, createAnchorManager, NoHandoffsError } from "../../runtime/anchor-manager.ts";
6
+ import {
7
+ type AnchorManager,
8
+ AnchorNotFoundError,
9
+ type AnchorStatus,
10
+ createAnchorManager,
11
+ NoHandoffsError,
12
+ } from "../../runtime/anchor-manager.ts";
7
13
  import type { HandoffSummary } from "../../runtime/handoff-manager.ts";
8
14
  import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
9
15
  import type { PiTeamsToolResult } from "../tool-result.ts";
@@ -130,7 +136,7 @@ export function handleAnchorStatus(params: TeamToolParamsValue, ctx: TeamContext
130
136
  anchorId = cfg.anchorId as string;
131
137
  }
132
138
 
133
- let status;
139
+ let status: AnchorStatus | null;
134
140
  if (anchorId) {
135
141
  status = manager.getAnchorStatus(anchorId);
136
142
  } else {