@caupulican/pi-adaptative 0.81.39 → 0.81.40

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 (667) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +2 -0
  3. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts +2 -0
  4. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -1
  5. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +2 -0
  6. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -1
  7. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +3 -0
  8. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +9 -0
  9. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
  10. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +290 -107
  11. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
  12. package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +357 -122
  13. package/dist/bundled-resources/skills/tool-call-repair/references/repair-catalogue.md +2 -2
  14. package/dist/cli/args.d.ts +2 -0
  15. package/dist/cli/args.d.ts.map +1 -1
  16. package/dist/cli/args.js +9 -0
  17. package/dist/cli/args.js.map +1 -1
  18. package/dist/core/agent-directory-layout.d.ts +15 -0
  19. package/dist/core/agent-directory-layout.d.ts.map +1 -0
  20. package/dist/core/agent-directory-layout.js +72 -0
  21. package/dist/core/agent-directory-layout.js.map +1 -0
  22. package/dist/core/agent-paths.d.ts +19 -2
  23. package/dist/core/agent-paths.d.ts.map +1 -1
  24. package/dist/core/agent-paths.js +67 -4
  25. package/dist/core/agent-paths.js.map +1 -1
  26. package/dist/core/agent-session-runtime.d.ts +52 -8
  27. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  28. package/dist/core/agent-session-runtime.js +397 -79
  29. package/dist/core/agent-session-runtime.js.map +1 -1
  30. package/dist/core/agent-session-services.d.ts +1 -0
  31. package/dist/core/agent-session-services.d.ts.map +1 -1
  32. package/dist/core/agent-session-services.js +1 -0
  33. package/dist/core/agent-session-services.js.map +1 -1
  34. package/dist/core/agent-session.d.ts +71 -136
  35. package/dist/core/agent-session.d.ts.map +1 -1
  36. package/dist/core/agent-session.js +477 -1318
  37. package/dist/core/agent-session.js.map +1 -1
  38. package/dist/core/autonomy/approval-gate.d.ts +3 -2
  39. package/dist/core/autonomy/approval-gate.d.ts.map +1 -1
  40. package/dist/core/autonomy/approval-gate.js +6 -28
  41. package/dist/core/autonomy/approval-gate.js.map +1 -1
  42. package/dist/core/autonomy/bounded-completion.d.ts +1 -1
  43. package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
  44. package/dist/core/autonomy/bounded-completion.js +1 -1
  45. package/dist/core/autonomy/bounded-completion.js.map +1 -1
  46. package/dist/core/autonomy/contracts.d.ts +20 -12
  47. package/dist/core/autonomy/contracts.d.ts.map +1 -1
  48. package/dist/core/autonomy/contracts.js.map +1 -1
  49. package/dist/core/autonomy/foreground-envelope.d.ts +8 -2
  50. package/dist/core/autonomy/foreground-envelope.d.ts.map +1 -1
  51. package/dist/core/autonomy/foreground-envelope.js +8 -25
  52. package/dist/core/autonomy/foreground-envelope.js.map +1 -1
  53. package/dist/core/autonomy/gates.d.ts.map +1 -1
  54. package/dist/core/autonomy/gates.js +8 -10
  55. package/dist/core/autonomy/gates.js.map +1 -1
  56. package/dist/core/autonomy/lane-private-paths.d.ts +2 -0
  57. package/dist/core/autonomy/lane-private-paths.d.ts.map +1 -0
  58. package/dist/core/autonomy/lane-private-paths.js +16 -0
  59. package/dist/core/autonomy/lane-private-paths.js.map +1 -0
  60. package/dist/core/autonomy/lane-tool-surface.d.ts +10 -0
  61. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  62. package/dist/core/autonomy/lane-tool-surface.js +46 -8
  63. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  64. package/dist/core/autonomy/lane-tracker.d.ts +14 -0
  65. package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
  66. package/dist/core/autonomy/lane-tracker.js +38 -0
  67. package/dist/core/autonomy/lane-tracker.js.map +1 -1
  68. package/dist/core/autonomy/risk-assessment.d.ts +1 -2
  69. package/dist/core/autonomy/risk-assessment.d.ts.map +1 -1
  70. package/dist/core/autonomy/risk-assessment.js +1 -123
  71. package/dist/core/autonomy/risk-assessment.js.map +1 -1
  72. package/dist/core/autonomy/session-lane-record.d.ts +4 -4
  73. package/dist/core/autonomy/session-lane-record.d.ts.map +1 -1
  74. package/dist/core/autonomy/session-lane-record.js +16 -29
  75. package/dist/core/autonomy/session-lane-record.js.map +1 -1
  76. package/dist/core/autonomy/telemetry-events.d.ts +1 -1
  77. package/dist/core/autonomy/telemetry-events.d.ts.map +1 -1
  78. package/dist/core/autonomy/telemetry-events.js +1 -1
  79. package/dist/core/autonomy/telemetry-events.js.map +1 -1
  80. package/dist/core/autonomy-telemetry.d.ts +7 -7
  81. package/dist/core/autonomy-telemetry.d.ts.map +1 -1
  82. package/dist/core/autonomy-telemetry.js +9 -9
  83. package/dist/core/autonomy-telemetry.js.map +1 -1
  84. package/dist/core/background-lane-controller.d.ts +54 -236
  85. package/dist/core/background-lane-controller.d.ts.map +1 -1
  86. package/dist/core/background-lane-controller.js +140 -1273
  87. package/dist/core/background-lane-controller.js.map +1 -1
  88. package/dist/core/capability-contract.d.ts +4 -0
  89. package/dist/core/capability-contract.d.ts.map +1 -0
  90. package/dist/core/capability-contract.js +28 -0
  91. package/dist/core/capability-contract.js.map +1 -0
  92. package/dist/core/compaction-controller.d.ts +90 -0
  93. package/dist/core/compaction-controller.d.ts.map +1 -0
  94. package/dist/core/compaction-controller.js +452 -0
  95. package/dist/core/compaction-controller.js.map +1 -0
  96. package/dist/core/compaction-support.d.ts +12 -11
  97. package/dist/core/compaction-support.d.ts.map +1 -1
  98. package/dist/core/compaction-support.js.map +1 -1
  99. package/dist/core/context/context-artifacts.d.ts +6 -2
  100. package/dist/core/context/context-artifacts.d.ts.map +1 -1
  101. package/dist/core/context/context-artifacts.js +34 -2
  102. package/dist/core/context/context-artifacts.js.map +1 -1
  103. package/dist/core/context/context-store-retention.d.ts +8 -2
  104. package/dist/core/context/context-store-retention.d.ts.map +1 -1
  105. package/dist/core/context/context-store-retention.js +158 -35
  106. package/dist/core/context/context-store-retention.js.map +1 -1
  107. package/dist/core/context/okf-memory.d.ts.map +1 -1
  108. package/dist/core/context/okf-memory.js +9 -11
  109. package/dist/core/context/okf-memory.js.map +1 -1
  110. package/dist/core/context/sqlite-runtime-index.d.ts.map +1 -1
  111. package/dist/core/context/sqlite-runtime-index.js +6 -8
  112. package/dist/core/context/sqlite-runtime-index.js.map +1 -1
  113. package/dist/core/context-gc.d.ts +3 -0
  114. package/dist/core/context-gc.d.ts.map +1 -1
  115. package/dist/core/context-gc.js +10 -5
  116. package/dist/core/context-gc.js.map +1 -1
  117. package/dist/core/context-pipeline.d.ts.map +1 -1
  118. package/dist/core/context-pipeline.js +9 -4
  119. package/dist/core/context-pipeline.js.map +1 -1
  120. package/dist/core/default-tool-surface.d.ts.map +1 -1
  121. package/dist/core/default-tool-surface.js +1 -0
  122. package/dist/core/default-tool-surface.js.map +1 -1
  123. package/dist/core/delegation/managed-lane-controller.d.ts +34 -0
  124. package/dist/core/delegation/managed-lane-controller.d.ts.map +1 -0
  125. package/dist/core/delegation/managed-lane-controller.js +217 -0
  126. package/dist/core/delegation/managed-lane-controller.js.map +1 -0
  127. package/dist/core/delegation/session-worker-claim.d.ts +44 -0
  128. package/dist/core/delegation/session-worker-claim.d.ts.map +1 -0
  129. package/dist/core/delegation/session-worker-claim.js +98 -0
  130. package/dist/core/delegation/session-worker-claim.js.map +1 -0
  131. package/dist/core/delegation/worker-actions.d.ts +7 -5
  132. package/dist/core/delegation/worker-actions.d.ts.map +1 -1
  133. package/dist/core/delegation/worker-actions.js +20 -4
  134. package/dist/core/delegation/worker-actions.js.map +1 -1
  135. package/dist/core/delegation/{worker-result.d.ts → worker-claim.d.ts} +13 -13
  136. package/dist/core/delegation/worker-claim.d.ts.map +1 -0
  137. package/dist/core/delegation/{worker-result.js → worker-claim.js} +61 -51
  138. package/dist/core/delegation/worker-claim.js.map +1 -0
  139. package/dist/core/delegation/worker-delegation-controller.d.ts +110 -0
  140. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -0
  141. package/dist/core/delegation/worker-delegation-controller.js +861 -0
  142. package/dist/core/delegation/worker-delegation-controller.js.map +1 -0
  143. package/dist/core/delegation/worker-delegation-request.d.ts +11 -0
  144. package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -0
  145. package/dist/core/delegation/worker-delegation-request.js +2 -0
  146. package/dist/core/delegation/worker-delegation-request.js.map +1 -0
  147. package/dist/core/delegation/worker-dispatch-scheduler.d.ts +40 -0
  148. package/dist/core/delegation/worker-dispatch-scheduler.d.ts.map +1 -0
  149. package/dist/core/delegation/worker-dispatch-scheduler.js +93 -0
  150. package/dist/core/delegation/worker-dispatch-scheduler.js.map +1 -0
  151. package/dist/core/delegation/worker-execution-policy.d.ts +62 -0
  152. package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -0
  153. package/dist/core/delegation/worker-execution-policy.js +160 -0
  154. package/dist/core/delegation/worker-execution-policy.js.map +1 -0
  155. package/dist/core/delegation/worker-lane-projection.d.ts +14 -0
  156. package/dist/core/delegation/worker-lane-projection.d.ts.map +1 -0
  157. package/dist/core/delegation/worker-lane-projection.js +100 -0
  158. package/dist/core/delegation/worker-lane-projection.js.map +1 -0
  159. package/dist/core/delegation/worker-lifecycle.d.ts +97 -0
  160. package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -0
  161. package/dist/core/delegation/worker-lifecycle.js +339 -0
  162. package/dist/core/delegation/worker-lifecycle.js.map +1 -0
  163. package/dist/core/delegation/worker-notification-coordinator.d.ts +36 -0
  164. package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -0
  165. package/dist/core/delegation/worker-notification-coordinator.js +90 -0
  166. package/dist/core/delegation/worker-notification-coordinator.js.map +1 -0
  167. package/dist/core/delegation/worker-profile-resolver.d.ts +55 -0
  168. package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -0
  169. package/dist/core/delegation/worker-profile-resolver.js +113 -0
  170. package/dist/core/delegation/worker-profile-resolver.js.map +1 -0
  171. package/dist/core/delegation/worker-runner.d.ts +25 -14
  172. package/dist/core/delegation/worker-runner.d.ts.map +1 -1
  173. package/dist/core/delegation/worker-runner.js +122 -53
  174. package/dist/core/delegation/worker-runner.js.map +1 -1
  175. package/dist/core/delegation/worker-task-label.d.ts +3 -0
  176. package/dist/core/delegation/worker-task-label.d.ts.map +1 -0
  177. package/dist/core/delegation/worker-task-label.js +11 -0
  178. package/dist/core/delegation/worker-task-label.js.map +1 -0
  179. package/dist/core/doctor.d.ts +8 -0
  180. package/dist/core/doctor.d.ts.map +1 -1
  181. package/dist/core/doctor.js +32 -1
  182. package/dist/core/doctor.js.map +1 -1
  183. package/dist/core/extensions/index.d.ts +1 -1
  184. package/dist/core/extensions/index.d.ts.map +1 -1
  185. package/dist/core/extensions/index.js.map +1 -1
  186. package/dist/core/extensions/loader.d.ts +5 -1
  187. package/dist/core/extensions/loader.d.ts.map +1 -1
  188. package/dist/core/extensions/loader.js +50 -15
  189. package/dist/core/extensions/loader.js.map +1 -1
  190. package/dist/core/extensions/runner.d.ts.map +1 -1
  191. package/dist/core/extensions/runner.js +6 -0
  192. package/dist/core/extensions/runner.js.map +1 -1
  193. package/dist/core/extensions/storage.d.ts +8 -0
  194. package/dist/core/extensions/storage.d.ts.map +1 -0
  195. package/dist/core/extensions/storage.js +28 -0
  196. package/dist/core/extensions/storage.js.map +1 -0
  197. package/dist/core/extensions/types.d.ts +70 -21
  198. package/dist/core/extensions/types.d.ts.map +1 -1
  199. package/dist/core/extensions/types.js.map +1 -1
  200. package/dist/core/failure-corpus.d.ts +1 -15
  201. package/dist/core/failure-corpus.d.ts.map +1 -1
  202. package/dist/core/failure-corpus.js +9 -37
  203. package/dist/core/failure-corpus.js.map +1 -1
  204. package/dist/core/foreground-recovery-controller.d.ts +52 -0
  205. package/dist/core/foreground-recovery-controller.d.ts.map +1 -0
  206. package/dist/core/foreground-recovery-controller.js +111 -0
  207. package/dist/core/foreground-recovery-controller.js.map +1 -0
  208. package/dist/core/gateways/channel-provider.d.ts +3 -0
  209. package/dist/core/gateways/channel-provider.d.ts.map +1 -1
  210. package/dist/core/gateways/channel-provider.js +31 -6
  211. package/dist/core/gateways/channel-provider.js.map +1 -1
  212. package/dist/core/goals/goal-acceptance.d.ts +11 -0
  213. package/dist/core/goals/goal-acceptance.d.ts.map +1 -0
  214. package/dist/core/goals/goal-acceptance.js +25 -0
  215. package/dist/core/goals/goal-acceptance.js.map +1 -0
  216. package/dist/core/goals/goal-auto-continue-controller.d.ts +27 -0
  217. package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -0
  218. package/dist/core/goals/goal-auto-continue-controller.js +93 -0
  219. package/dist/core/goals/goal-auto-continue-controller.js.map +1 -0
  220. package/dist/core/goals/goal-continuation-controller.d.ts +1 -1
  221. package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
  222. package/dist/core/goals/goal-continuation-controller.js +10 -0
  223. package/dist/core/goals/goal-continuation-controller.js.map +1 -1
  224. package/dist/core/goals/goal-continuation-prompt.d.ts +1 -1
  225. package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
  226. package/dist/core/goals/goal-continuation-prompt.js +6 -6
  227. package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
  228. package/dist/core/goals/goal-lifecycle.d.ts +20 -0
  229. package/dist/core/goals/goal-lifecycle.d.ts.map +1 -0
  230. package/dist/core/goals/goal-lifecycle.js +17 -0
  231. package/dist/core/goals/goal-lifecycle.js.map +1 -0
  232. package/dist/core/goals/goal-runtime-snapshot.d.ts +11 -9
  233. package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
  234. package/dist/core/goals/goal-runtime-snapshot.js +10 -8
  235. package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
  236. package/dist/core/goals/goal-state.d.ts +1 -0
  237. package/dist/core/goals/goal-state.d.ts.map +1 -1
  238. package/dist/core/goals/goal-state.js +7 -10
  239. package/dist/core/goals/goal-state.js.map +1 -1
  240. package/dist/core/goals/goal-tool-core.d.ts +8 -6
  241. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  242. package/dist/core/goals/goal-tool-core.js +11 -41
  243. package/dist/core/goals/goal-tool-core.js.map +1 -1
  244. package/dist/core/goals/session-goal-state.d.ts +2 -4
  245. package/dist/core/goals/session-goal-state.d.ts.map +1 -1
  246. package/dist/core/goals/session-goal-state.js +10 -33
  247. package/dist/core/goals/session-goal-state.js.map +1 -1
  248. package/dist/core/human-input.d.ts +100 -0
  249. package/dist/core/human-input.d.ts.map +1 -0
  250. package/dist/core/human-input.js +362 -0
  251. package/dist/core/human-input.js.map +1 -0
  252. package/dist/core/index.d.ts +9 -1
  253. package/dist/core/index.d.ts.map +1 -1
  254. package/dist/core/index.js +9 -1
  255. package/dist/core/index.js.map +1 -1
  256. package/dist/core/{telemetry.d.ts → install-telemetry.d.ts} +1 -1
  257. package/dist/core/install-telemetry.d.ts.map +1 -0
  258. package/dist/core/{telemetry.js → install-telemetry.js} +1 -1
  259. package/dist/core/install-telemetry.js.map +1 -0
  260. package/dist/core/keybindings.d.ts +17 -1
  261. package/dist/core/keybindings.d.ts.map +1 -1
  262. package/dist/core/keybindings.js +24 -6
  263. package/dist/core/keybindings.js.map +1 -1
  264. package/dist/core/learning/learning-audit.d.ts +2 -4
  265. package/dist/core/learning/learning-audit.d.ts.map +1 -1
  266. package/dist/core/learning/learning-audit.js +9 -29
  267. package/dist/core/learning/learning-audit.js.map +1 -1
  268. package/dist/core/learning/learning-gate.d.ts.map +1 -1
  269. package/dist/core/learning/learning-gate.js +1 -6
  270. package/dist/core/learning/learning-gate.js.map +1 -1
  271. package/dist/core/learning/session-learning-decision.d.ts +2 -4
  272. package/dist/core/learning/session-learning-decision.d.ts.map +1 -1
  273. package/dist/core/learning/session-learning-decision.js +9 -29
  274. package/dist/core/learning/session-learning-decision.js.map +1 -1
  275. package/dist/core/memory-controller.d.ts.map +1 -1
  276. package/dist/core/memory-controller.js +4 -4
  277. package/dist/core/memory-controller.js.map +1 -1
  278. package/dist/core/model-capability.d.ts.map +1 -1
  279. package/dist/core/model-capability.js +1 -0
  280. package/dist/core/model-capability.js.map +1 -1
  281. package/dist/core/model-resolver.d.ts +1 -1
  282. package/dist/core/model-resolver.d.ts.map +1 -1
  283. package/dist/core/model-resolver.js +6 -9
  284. package/dist/core/model-resolver.js.map +1 -1
  285. package/dist/core/model-router/intent-classifier.d.ts +1 -4
  286. package/dist/core/model-router/intent-classifier.d.ts.map +1 -1
  287. package/dist/core/model-router/intent-classifier.js +1 -156
  288. package/dist/core/model-router/intent-classifier.js.map +1 -1
  289. package/dist/core/model-router-controller.d.ts.map +1 -1
  290. package/dist/core/model-router-controller.js +2 -2
  291. package/dist/core/model-router-controller.js.map +1 -1
  292. package/dist/core/model-selection-controller.d.ts +4 -4
  293. package/dist/core/model-selection-controller.d.ts.map +1 -1
  294. package/dist/core/model-selection-controller.js.map +1 -1
  295. package/dist/core/model-tool-protocol.d.ts +23 -0
  296. package/dist/core/model-tool-protocol.d.ts.map +1 -0
  297. package/dist/core/model-tool-protocol.js +43 -0
  298. package/dist/core/model-tool-protocol.js.map +1 -0
  299. package/dist/core/models/adaptation-store.d.ts +4 -6
  300. package/dist/core/models/adaptation-store.d.ts.map +1 -1
  301. package/dist/core/models/adaptation-store.js +95 -83
  302. package/dist/core/models/adaptation-store.js.map +1 -1
  303. package/dist/core/models/fitness-store.d.ts +2 -12
  304. package/dist/core/models/fitness-store.d.ts.map +1 -1
  305. package/dist/core/models/fitness-store.js +84 -57
  306. package/dist/core/models/fitness-store.js.map +1 -1
  307. package/dist/core/models/host-state-store.d.ts +34 -0
  308. package/dist/core/models/host-state-store.d.ts.map +1 -0
  309. package/dist/core/models/host-state-store.js +86 -0
  310. package/dist/core/models/host-state-store.js.map +1 -0
  311. package/dist/core/orchestration/agent-resume.d.ts +24 -0
  312. package/dist/core/orchestration/agent-resume.d.ts.map +1 -0
  313. package/dist/core/orchestration/agent-resume.js +90 -0
  314. package/dist/core/orchestration/agent-resume.js.map +1 -0
  315. package/dist/core/orchestration/capability-gateway.d.ts +61 -0
  316. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -0
  317. package/dist/core/orchestration/capability-gateway.js +152 -0
  318. package/dist/core/orchestration/capability-gateway.js.map +1 -0
  319. package/dist/core/orchestration/contracts.d.ts +343 -0
  320. package/dist/core/orchestration/contracts.d.ts.map +1 -0
  321. package/dist/core/orchestration/contracts.js +135 -0
  322. package/dist/core/orchestration/contracts.js.map +1 -0
  323. package/dist/core/orchestration/delegation-ledger.d.ts +56 -0
  324. package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -0
  325. package/dist/core/orchestration/delegation-ledger.js +197 -0
  326. package/dist/core/orchestration/delegation-ledger.js.map +1 -0
  327. package/dist/core/orchestration/event-store.d.ts +83 -0
  328. package/dist/core/orchestration/event-store.d.ts.map +1 -0
  329. package/dist/core/orchestration/event-store.js +560 -0
  330. package/dist/core/orchestration/event-store.js.map +1 -0
  331. package/dist/core/orchestration/lane-tool-manifests.d.ts +9 -0
  332. package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -0
  333. package/dist/core/orchestration/lane-tool-manifests.js +37 -0
  334. package/dist/core/orchestration/lane-tool-manifests.js.map +1 -0
  335. package/dist/core/orchestration/model-binding.d.ts +15 -0
  336. package/dist/core/orchestration/model-binding.d.ts.map +1 -0
  337. package/dist/core/orchestration/model-binding.js +29 -0
  338. package/dist/core/orchestration/model-binding.js.map +1 -0
  339. package/dist/core/orchestration/policy-compiler.d.ts +49 -0
  340. package/dist/core/orchestration/policy-compiler.d.ts.map +1 -0
  341. package/dist/core/orchestration/policy-compiler.js +191 -0
  342. package/dist/core/orchestration/policy-compiler.js.map +1 -0
  343. package/dist/core/orchestration/policy-gate.d.ts +18 -0
  344. package/dist/core/orchestration/policy-gate.d.ts.map +1 -0
  345. package/dist/core/orchestration/policy-gate.js +24 -0
  346. package/dist/core/orchestration/policy-gate.js.map +1 -0
  347. package/dist/core/orchestration/profile-registry.d.ts +51 -0
  348. package/dist/core/orchestration/profile-registry.d.ts.map +1 -0
  349. package/dist/core/orchestration/profile-registry.js +393 -0
  350. package/dist/core/orchestration/profile-registry.js.map +1 -0
  351. package/dist/core/orchestration/profile-store.d.ts +31 -0
  352. package/dist/core/orchestration/profile-store.d.ts.map +1 -0
  353. package/dist/core/orchestration/profile-store.js +136 -0
  354. package/dist/core/orchestration/profile-store.js.map +1 -0
  355. package/dist/core/orchestration/risk-budget.d.ts +9 -0
  356. package/dist/core/orchestration/risk-budget.d.ts.map +1 -0
  357. package/dist/core/orchestration/risk-budget.js +48 -0
  358. package/dist/core/orchestration/risk-budget.js.map +1 -0
  359. package/dist/core/orchestration/task-runtime.d.ts +168 -0
  360. package/dist/core/orchestration/task-runtime.d.ts.map +1 -0
  361. package/dist/core/orchestration/task-runtime.js +1600 -0
  362. package/dist/core/orchestration/task-runtime.js.map +1 -0
  363. package/dist/core/orchestration/work-state-projection.d.ts +32 -0
  364. package/dist/core/orchestration/work-state-projection.d.ts.map +1 -0
  365. package/dist/core/orchestration/work-state-projection.js +116 -0
  366. package/dist/core/orchestration/work-state-projection.js.map +1 -0
  367. package/dist/core/orchestration/worker-execution-contract.d.ts +21 -0
  368. package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -0
  369. package/dist/core/orchestration/worker-execution-contract.js +179 -0
  370. package/dist/core/orchestration/worker-execution-contract.js.map +1 -0
  371. package/dist/core/orchestration/worker-result-adapter.d.ts +21 -0
  372. package/dist/core/orchestration/worker-result-adapter.d.ts.map +1 -0
  373. package/dist/core/orchestration/worker-result-adapter.js +109 -0
  374. package/dist/core/orchestration/worker-result-adapter.js.map +1 -0
  375. package/dist/core/process-identity.d.ts +11 -0
  376. package/dist/core/process-identity.d.ts.map +1 -0
  377. package/dist/core/process-identity.js +26 -0
  378. package/dist/core/process-identity.js.map +1 -0
  379. package/dist/core/process-matrix/codes.d.ts +14 -3
  380. package/dist/core/process-matrix/codes.d.ts.map +1 -1
  381. package/dist/core/process-matrix/codes.js.map +1 -1
  382. package/dist/core/process-matrix/resume-launcher.d.ts +26 -0
  383. package/dist/core/process-matrix/resume-launcher.d.ts.map +1 -0
  384. package/dist/core/process-matrix/resume-launcher.js +62 -0
  385. package/dist/core/process-matrix/resume-launcher.js.map +1 -0
  386. package/dist/core/process-matrix/runtime.d.ts +37 -22
  387. package/dist/core/process-matrix/runtime.d.ts.map +1 -1
  388. package/dist/core/process-matrix/runtime.js +399 -76
  389. package/dist/core/process-matrix/runtime.js.map +1 -1
  390. package/dist/core/process-matrix/store.d.ts +5 -2
  391. package/dist/core/process-matrix/store.d.ts.map +1 -1
  392. package/dist/core/process-matrix/store.js +123 -14
  393. package/dist/core/process-matrix/store.js.map +1 -1
  394. package/dist/core/process-matrix/supervisor.d.ts +10 -7
  395. package/dist/core/process-matrix/supervisor.d.ts.map +1 -1
  396. package/dist/core/process-matrix/supervisor.js +45 -14
  397. package/dist/core/process-matrix/supervisor.js.map +1 -1
  398. package/dist/core/profile-registry.d.ts.map +1 -1
  399. package/dist/core/profile-registry.js +6 -8
  400. package/dist/core/profile-registry.js.map +1 -1
  401. package/dist/core/reflection-controller.d.ts +4 -4
  402. package/dist/core/reflection-controller.d.ts.map +1 -1
  403. package/dist/core/reflection-controller.js +2 -1
  404. package/dist/core/reflection-controller.js.map +1 -1
  405. package/dist/core/reload-blockers.d.ts.map +1 -1
  406. package/dist/core/reload-blockers.js +6 -8
  407. package/dist/core/reload-blockers.js.map +1 -1
  408. package/dist/core/research/evidence-bundle.d.ts.map +1 -1
  409. package/dist/core/research/evidence-bundle.js +1 -6
  410. package/dist/core/research/evidence-bundle.js.map +1 -1
  411. package/dist/core/research/lane-model-resolver.d.ts +33 -0
  412. package/dist/core/research/lane-model-resolver.d.ts.map +1 -0
  413. package/dist/core/research/lane-model-resolver.js +65 -0
  414. package/dist/core/research/lane-model-resolver.js.map +1 -0
  415. package/dist/core/research/model-fitness-controller.d.ts +38 -0
  416. package/dist/core/research/model-fitness-controller.d.ts.map +1 -0
  417. package/dist/core/research/model-fitness-controller.js +106 -0
  418. package/dist/core/research/model-fitness-controller.js.map +1 -0
  419. package/dist/core/research/model-fitness.d.ts +1 -1
  420. package/dist/core/research/model-fitness.d.ts.map +1 -1
  421. package/dist/core/research/model-fitness.js +4 -4
  422. package/dist/core/research/model-fitness.js.map +1 -1
  423. package/dist/core/research/research-gate.d.ts.map +1 -1
  424. package/dist/core/research/research-gate.js +7 -7
  425. package/dist/core/research/research-gate.js.map +1 -1
  426. package/dist/core/research/research-lane-controller.d.ts +62 -0
  427. package/dist/core/research/research-lane-controller.d.ts.map +1 -0
  428. package/dist/core/research/research-lane-controller.js +292 -0
  429. package/dist/core/research/research-lane-controller.js.map +1 -0
  430. package/dist/core/research/session-evidence-bundle.d.ts +2 -4
  431. package/dist/core/research/session-evidence-bundle.d.ts.map +1 -1
  432. package/dist/core/research/session-evidence-bundle.js +10 -46
  433. package/dist/core/research/session-evidence-bundle.js.map +1 -1
  434. package/dist/core/resource-loader.d.ts.map +1 -1
  435. package/dist/core/resource-loader.js +7 -2
  436. package/dist/core/resource-loader.js.map +1 -1
  437. package/dist/core/risk-classifier.d.ts +6 -0
  438. package/dist/core/risk-classifier.d.ts.map +1 -0
  439. package/dist/core/risk-classifier.js +225 -0
  440. package/dist/core/risk-classifier.js.map +1 -0
  441. package/dist/core/runtime-builder.d.ts +26 -20
  442. package/dist/core/runtime-builder.d.ts.map +1 -1
  443. package/dist/core/runtime-builder.js +237 -178
  444. package/dist/core/runtime-builder.js.map +1 -1
  445. package/dist/core/sdk.d.ts +6 -3
  446. package/dist/core/sdk.d.ts.map +1 -1
  447. package/dist/core/sdk.js +61 -24
  448. package/dist/core/sdk.js.map +1 -1
  449. package/dist/core/session-analytics.d.ts.map +1 -1
  450. package/dist/core/session-analytics.js +28 -1
  451. package/dist/core/session-analytics.js.map +1 -1
  452. package/dist/core/session-image-store.d.ts +33 -0
  453. package/dist/core/session-image-store.d.ts.map +1 -0
  454. package/dist/core/session-image-store.js +283 -0
  455. package/dist/core/session-image-store.js.map +1 -0
  456. package/dist/core/session-role.d.ts +6 -4
  457. package/dist/core/session-role.d.ts.map +1 -1
  458. package/dist/core/session-role.js +10 -4
  459. package/dist/core/session-role.js.map +1 -1
  460. package/dist/core/session-snapshot.d.ts +34 -0
  461. package/dist/core/session-snapshot.d.ts.map +1 -0
  462. package/dist/core/session-snapshot.js +68 -0
  463. package/dist/core/session-snapshot.js.map +1 -0
  464. package/dist/core/session-supervision-runtime.d.ts +31 -0
  465. package/dist/core/session-supervision-runtime.d.ts.map +1 -0
  466. package/dist/core/session-supervision-runtime.js +97 -0
  467. package/dist/core/session-supervision-runtime.js.map +1 -0
  468. package/dist/core/settings-manager.d.ts +9 -4
  469. package/dist/core/settings-manager.d.ts.map +1 -1
  470. package/dist/core/settings-manager.js +80 -28
  471. package/dist/core/settings-manager.js.map +1 -1
  472. package/dist/core/tasks/session-task-state.d.ts +2 -4
  473. package/dist/core/tasks/session-task-state.d.ts.map +1 -1
  474. package/dist/core/tasks/session-task-state.js +10 -28
  475. package/dist/core/tasks/session-task-state.js.map +1 -1
  476. package/dist/core/tasks/task-projection.d.ts +20 -0
  477. package/dist/core/tasks/task-projection.d.ts.map +1 -0
  478. package/dist/core/tasks/task-projection.js +47 -0
  479. package/dist/core/tasks/task-projection.js.map +1 -0
  480. package/dist/core/tasks/task-state.d.ts +4 -0
  481. package/dist/core/tasks/task-state.d.ts.map +1 -1
  482. package/dist/core/tasks/task-state.js +28 -11
  483. package/dist/core/tasks/task-state.js.map +1 -1
  484. package/dist/core/tool-capability-policy.d.ts +13 -0
  485. package/dist/core/tool-capability-policy.d.ts.map +1 -0
  486. package/dist/core/tool-capability-policy.js +85 -0
  487. package/dist/core/tool-capability-policy.js.map +1 -0
  488. package/dist/core/tool-protocol-controller.d.ts +91 -0
  489. package/dist/core/tool-protocol-controller.d.ts.map +1 -0
  490. package/dist/core/tool-protocol-controller.js +512 -0
  491. package/dist/core/tool-protocol-controller.js.map +1 -0
  492. package/dist/core/tool-recovery-log-records.d.ts +2 -3
  493. package/dist/core/tool-recovery-log-records.d.ts.map +1 -1
  494. package/dist/core/tool-recovery-log-records.js +9 -35
  495. package/dist/core/tool-recovery-log-records.js.map +1 -1
  496. package/dist/core/tool-selection/tool-performance-store.d.ts +3 -7
  497. package/dist/core/tool-selection/tool-performance-store.d.ts.map +1 -1
  498. package/dist/core/tool-selection/tool-performance-store.js +97 -138
  499. package/dist/core/tool-selection/tool-performance-store.js.map +1 -1
  500. package/dist/core/tools/ask-question.d.ts +124 -0
  501. package/dist/core/tools/ask-question.d.ts.map +1 -0
  502. package/dist/core/tools/ask-question.js +693 -0
  503. package/dist/core/tools/ask-question.js.map +1 -0
  504. package/dist/core/tools/delegate-status.d.ts +31 -3
  505. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  506. package/dist/core/tools/delegate-status.js +149 -29
  507. package/dist/core/tools/delegate-status.js.map +1 -1
  508. package/dist/core/tools/delegate.d.ts +15 -13
  509. package/dist/core/tools/delegate.d.ts.map +1 -1
  510. package/dist/core/tools/delegate.js +108 -23
  511. package/dist/core/tools/delegate.js.map +1 -1
  512. package/dist/core/tools/extensionify.d.ts.map +1 -1
  513. package/dist/core/tools/extensionify.js +1 -0
  514. package/dist/core/tools/extensionify.js.map +1 -1
  515. package/dist/core/tools/goal.d.ts +5 -5
  516. package/dist/core/tools/goal.d.ts.map +1 -1
  517. package/dist/core/tools/goal.js +10 -10
  518. package/dist/core/tools/goal.js.map +1 -1
  519. package/dist/core/tools/model-fitness.d.ts.map +1 -1
  520. package/dist/core/tools/model-fitness.js +2 -2
  521. package/dist/core/tools/model-fitness.js.map +1 -1
  522. package/dist/core/tools/orchestration-panel.d.ts +43 -0
  523. package/dist/core/tools/orchestration-panel.d.ts.map +1 -0
  524. package/dist/core/tools/orchestration-panel.js +168 -0
  525. package/dist/core/tools/orchestration-panel.js.map +1 -0
  526. package/dist/core/tools/run-process.d.ts +26 -0
  527. package/dist/core/tools/run-process.d.ts.map +1 -0
  528. package/dist/core/tools/run-process.js +138 -0
  529. package/dist/core/tools/run-process.js.map +1 -0
  530. package/dist/core/tools/task-steps.d.ts +2 -0
  531. package/dist/core/tools/task-steps.d.ts.map +1 -1
  532. package/dist/core/tools/task-steps.js +102 -0
  533. package/dist/core/tools/task-steps.js.map +1 -1
  534. package/dist/core/tools/tmux-dispatch.d.ts +3 -5
  535. package/dist/core/tools/tmux-dispatch.d.ts.map +1 -1
  536. package/dist/core/tools/tmux-dispatch.js +4 -4
  537. package/dist/core/tools/tmux-dispatch.js.map +1 -1
  538. package/dist/core/tools/windows-shell-engine.d.ts.map +1 -1
  539. package/dist/core/tools/windows-shell-engine.js +4 -6
  540. package/dist/core/tools/windows-shell-engine.js.map +1 -1
  541. package/dist/core/util/bounded-jsonl.d.ts +10 -0
  542. package/dist/core/util/bounded-jsonl.d.ts.map +1 -0
  543. package/dist/core/util/bounded-jsonl.js +75 -0
  544. package/dist/core/util/bounded-jsonl.js.map +1 -0
  545. package/dist/core/util/value-guards.d.ts +5 -0
  546. package/dist/core/util/value-guards.d.ts.map +1 -0
  547. package/dist/core/util/value-guards.js +12 -0
  548. package/dist/core/util/value-guards.js.map +1 -0
  549. package/dist/core/worktree-sync/store.d.ts +3 -3
  550. package/dist/core/worktree-sync/store.d.ts.map +1 -1
  551. package/dist/core/worktree-sync/store.js +10 -5
  552. package/dist/core/worktree-sync/store.js.map +1 -1
  553. package/dist/index.d.ts +13 -3
  554. package/dist/index.d.ts.map +1 -1
  555. package/dist/index.js +12 -2
  556. package/dist/index.js.map +1 -1
  557. package/dist/main.d.ts.map +1 -1
  558. package/dist/main.js +128 -44
  559. package/dist/main.js.map +1 -1
  560. package/dist/migrations.d.ts +4 -6
  561. package/dist/migrations.d.ts.map +1 -1
  562. package/dist/migrations.js +186 -28
  563. package/dist/migrations.js.map +1 -1
  564. package/dist/modes/interactive/clipboard-input.d.ts +7 -1
  565. package/dist/modes/interactive/clipboard-input.d.ts.map +1 -1
  566. package/dist/modes/interactive/clipboard-input.js +44 -6
  567. package/dist/modes/interactive/clipboard-input.js.map +1 -1
  568. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  569. package/dist/modes/interactive/components/settings-selector.js +2 -2
  570. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  571. package/dist/modes/interactive/config-backup.d.ts.map +1 -1
  572. package/dist/modes/interactive/config-backup.js +5 -4
  573. package/dist/modes/interactive/config-backup.js.map +1 -1
  574. package/dist/modes/interactive/extension-ui-host.d.ts +14 -0
  575. package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
  576. package/dist/modes/interactive/extension-ui-host.js +76 -15
  577. package/dist/modes/interactive/extension-ui-host.js.map +1 -1
  578. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  579. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  580. package/dist/modes/interactive/interactive-mode.js +63 -1
  581. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  582. package/dist/modes/interactive/key-handlers.d.ts.map +1 -1
  583. package/dist/modes/interactive/key-handlers.js +1 -1
  584. package/dist/modes/interactive/key-handlers.js.map +1 -1
  585. package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -1
  586. package/dist/modes/interactive/profile-menu-controller.js +7 -7
  587. package/dist/modes/interactive/profile-menu-controller.js.map +1 -1
  588. package/dist/modes/interactive/report-commands.d.ts.map +1 -1
  589. package/dist/modes/interactive/report-commands.js +21 -0
  590. package/dist/modes/interactive/report-commands.js.map +1 -1
  591. package/dist/modes/interactive/session-flow-commands.d.ts +17 -2
  592. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
  593. package/dist/modes/interactive/session-flow-commands.js +50 -17
  594. package/dist/modes/interactive/session-flow-commands.js.map +1 -1
  595. package/dist/modes/interactive/session-io-commands.d.ts.map +1 -1
  596. package/dist/modes/interactive/session-io-commands.js +16 -6
  597. package/dist/modes/interactive/session-io-commands.js.map +1 -1
  598. package/dist/modes/interactive/session-replacement-errors.d.ts +7 -0
  599. package/dist/modes/interactive/session-replacement-errors.d.ts.map +1 -0
  600. package/dist/modes/interactive/session-replacement-errors.js +15 -0
  601. package/dist/modes/interactive/session-replacement-errors.js.map +1 -0
  602. package/dist/modes/interactive/startup-checks.d.ts.map +1 -1
  603. package/dist/modes/interactive/startup-checks.js +1 -1
  604. package/dist/modes/interactive/startup-checks.js.map +1 -1
  605. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  606. package/dist/modes/rpc/rpc-mode.js +82 -23
  607. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  608. package/dist/modes/rpc/rpc-types.d.ts +15 -0
  609. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  610. package/dist/modes/rpc/rpc-types.js +138 -1
  611. package/dist/modes/rpc/rpc-types.js.map +1 -1
  612. package/dist/utils/clipboard-image.d.ts.map +1 -1
  613. package/dist/utils/clipboard-image.js +2 -13
  614. package/dist/utils/clipboard-image.js.map +1 -1
  615. package/dist/utils/clipboard-native.d.ts +1 -0
  616. package/dist/utils/clipboard-native.d.ts.map +1 -1
  617. package/dist/utils/clipboard-native.js.map +1 -1
  618. package/dist/utils/clipboard.d.ts +1 -0
  619. package/dist/utils/clipboard.d.ts.map +1 -1
  620. package/dist/utils/clipboard.js +52 -1
  621. package/dist/utils/clipboard.js.map +1 -1
  622. package/dist/utils/platform.d.ts +3 -0
  623. package/dist/utils/platform.d.ts.map +1 -0
  624. package/dist/utils/platform.js +8 -0
  625. package/dist/utils/platform.js.map +1 -0
  626. package/dist/utils/work-directory.d.ts +11 -0
  627. package/dist/utils/work-directory.d.ts.map +1 -1
  628. package/dist/utils/work-directory.js +30 -9
  629. package/dist/utils/work-directory.js.map +1 -1
  630. package/docs/UI_POLISH_ORCHESTRATION.md +44 -0
  631. package/docs/UI_QUALITY_ORCHESTRATION.md +30 -0
  632. package/docs/docs.json +4 -0
  633. package/docs/extensions.md +62 -2
  634. package/docs/harness-architecture.md +156 -0
  635. package/docs/keybindings.md +11 -1
  636. package/docs/process-matrix.md +59 -26
  637. package/docs/rpc.md +45 -2
  638. package/docs/sessions.md +15 -0
  639. package/docs/settings.md +125 -11
  640. package/docs/task-steps.md +8 -0
  641. package/docs/telemetry.md +19 -0
  642. package/docs/tmux-agent-manager.md +10 -3
  643. package/docs/ui-reference/README.md +9 -0
  644. package/docs/ui-reference/orchestration-after.txt +7 -0
  645. package/docs/ui-reference/orchestration-before.txt +7 -0
  646. package/docs/ui-reference/orchestration-reference.txt +6 -0
  647. package/docs/usage.md +14 -2
  648. package/docs/work-directory.md +19 -8
  649. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  650. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  651. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  652. package/examples/extensions/question.ts +34 -245
  653. package/examples/extensions/questionnaire.ts +41 -407
  654. package/examples/extensions/sandbox/package-lock.json +2 -2
  655. package/examples/extensions/sandbox/package.json +1 -1
  656. package/examples/extensions/with-deps/package-lock.json +2 -2
  657. package/examples/extensions/with-deps/package.json +1 -1
  658. package/npm-shrinkwrap.json +12 -12
  659. package/package.json +4 -4
  660. package/dist/core/delegation/session-worker-result.d.ts +0 -46
  661. package/dist/core/delegation/session-worker-result.d.ts.map +0 -1
  662. package/dist/core/delegation/session-worker-result.js +0 -113
  663. package/dist/core/delegation/session-worker-result.js.map +0 -1
  664. package/dist/core/delegation/worker-result.d.ts.map +0 -1
  665. package/dist/core/delegation/worker-result.js.map +0 -1
  666. package/dist/core/telemetry.d.ts.map +0 -1
  667. package/dist/core/telemetry.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"extensionify.js","sourceRoot":"","sources":["../../../src/core/tools/extensionify.ts"],"names":[],"mappings":"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","sourcesContent":["import { rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AgentTool } from \"@caupulican/pi-agent-core\";\nimport { type Static, Type } from \"typebox\";\nimport { getAgentDir } from \"../../config.ts\";\nimport { acquireWorkRun, type WorkRunLease } from \"../../utils/work-directory.ts\";\nimport { createEventBus } from \"../event-bus.ts\";\nimport { createExtensionRuntime, loadExtension } from \"../extensions/loader.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst extensionifySchema = Type.Object({\n\tname: Type.String({ description: \"Extension name (lowercase, a-z 0-9 hyphens only)\" }),\n\tcode: Type.String({ description: \"Extension factory code (TypeScript/JavaScript)\" }),\n\tpackageJson: Type.Optional(Type.String({ description: \"Optional package.json content as JSON string\" })),\n});\n\nexport type ExtensionifyInput = Static<typeof extensionifySchema>;\n\nexport interface ExtensionifyReport {\n\tok: boolean;\n\tsmokeTestPassed: boolean;\n\tdiagnostics: string[];\n\tregistered: {\n\t\ttools: string[];\n\t\tcommands: string[];\n\t};\n\tproposedPath: string;\n\tdraft: {\n\t\tname: string;\n\t\tcode: string;\n\t\tpackageJson?: string;\n\t};\n}\n\nexport interface ExtensionifyToolDetails {\n\treport?: ExtensionifyReport;\n}\n\nexport interface ExtensionifyToolOptions {\n\tagentDir?: string;\n}\n\nexport function createExtensionifyToolDefinition(\n\t_cwd: string,\n\toptions?: ExtensionifyToolOptions,\n): ToolDefinition<typeof extensionifySchema, ExtensionifyReport> {\n\treturn {\n\t\tname: \"extensionify\",\n\t\tlabel: \"extensionify\",\n\t\tdescription:\n\t\t\t\"Smoke-test a draft extension in an isolated throwaway runtime. Pure analysis tool: creates temporary scaffold, loads it, inspects registrations, then completely deletes temp dir. Does NOT write to the real extensions dir or modify the live runtime. Returns proposal with registration details.\",\n\t\tpromptSnippet: \"Smoke-test a draft extension\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use extensionify to validate draft extensions before creating them.\",\n\t\t\t\"Fix any factory errors or registration issues; review tools and commands registered.\",\n\t\t\t\"The tool runs in complete isolation; the live session is never touched.\",\n\t\t\t\"Persistent write and activation happen later via a separate step.\",\n\t\t],\n\t\tparameters: extensionifySchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ name, code, packageJson }: ExtensionifyInput,\n\t\t\t_signal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\t_ctx?,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: ExtensionifyReport;\n\t\t}> {\n\t\t\tconst diagnostics: string[] = [];\n\t\t\tlet smokeTestPassed = false;\n\t\t\tconst registeredTools: string[] = [];\n\t\t\tconst registeredCommands: string[] = [];\n\t\t\tconst agentDir = options?.agentDir ?? getAgentDir();\n\t\t\tconst proposedPath = join(agentDir, \"extensions\", name);\n\n\t\t\tlet tempDir: string | null = null;\n\t\t\tlet workRun: WorkRunLease | undefined;\n\t\t\ttry {\n\t\t\t\tworkRun = acquireWorkRun({ agentDir, category: \"extensions\", tenant: \"smoke-test\" });\n\t\t\t\ttempDir = workRun.path;\n\n\t\t\t\t// Write index.ts with the factory code\n\t\t\t\tconst indexPath = join(tempDir, \"index.ts\");\n\t\t\t\twriteFileSync(indexPath, code, \"utf-8\");\n\n\t\t\t\t// Write package.json if provided\n\t\t\t\tif (packageJson) {\n\t\t\t\t\tconst packageJsonPath = join(tempDir, \"package.json\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Validate it's valid JSON\n\t\t\t\t\t\tJSON.parse(packageJson);\n\t\t\t\t\t\twriteFileSync(packageJsonPath, packageJson, \"utf-8\");\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tdiagnostics.push(`Invalid package.json: ${err instanceof Error ? err.message : String(err)}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Create isolated runtime and event bus\n\t\t\t\tconst eventBus = createEventBus();\n\t\t\t\tconst runtime = createExtensionRuntime();\n\n\t\t\t\t// Load the extension in isolation\n\t\t\t\tconst { extension, error: loadError } = await loadExtension(indexPath, tempDir, eventBus, runtime, {\n\t\t\t\t\tfresh: true,\n\t\t\t\t});\n\n\t\t\t\tif (loadError) {\n\t\t\t\t\tdiagnostics.push(`Factory error: ${loadError}`);\n\t\t\t\t\tsmokeTestPassed = false;\n\t\t\t\t} else if (extension) {\n\t\t\t\t\tsmokeTestPassed = true;\n\n\t\t\t\t\t// Inspect registered tools\n\t\t\t\t\tfor (const [toolName] of extension.tools) {\n\t\t\t\t\t\tregisteredTools.push(toolName);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Inspect registered commands\n\t\t\t\t\tfor (const [cmdName] of extension.commands) {\n\t\t\t\t\t\tregisteredCommands.push(cmdName);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (registeredTools.length === 0 && registeredCommands.length === 0) {\n\t\t\t\t\t\tdiagnostics.push(\"Extension loaded but registered no tools or commands\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tdiagnostics.push(`Test error: ${err instanceof Error ? err.message : String(err)}`);\n\t\t\t\tsmokeTestPassed = false;\n\t\t\t} finally {\n\t\t\t\t// Always clean up the temporary directory.\n\t\t\t\tworkRun?.release();\n\t\t\t\tif (tempDir) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\trmSync(tempDir, { recursive: true, force: true });\n\t\t\t\t\t} catch (cleanupErr) {\n\t\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t\t`Cleanup warning: ${cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst ok = smokeTestPassed && diagnostics.length === 0;\n\n\t\t\tconst report: ExtensionifyReport = {\n\t\t\t\tok,\n\t\t\t\tsmokeTestPassed,\n\t\t\t\tdiagnostics,\n\t\t\t\tregistered: {\n\t\t\t\t\ttools: registeredTools,\n\t\t\t\t\tcommands: registeredCommands,\n\t\t\t\t},\n\t\t\t\tproposedPath,\n\t\t\t\tdraft: { name, code, packageJson },\n\t\t\t};\n\n\t\t\t// Format the report as readable text\n\t\t\tconst lines: string[] = [];\n\t\t\tlines.push(`Extensionify smoke-test: ${smokeTestPassed ? \"✓ passed\" : \"✗ failed\"}`);\n\n\t\t\tif (diagnostics.length > 0) {\n\t\t\t\tlines.push(\"\\nDiagnostics:\");\n\t\t\t\tfor (const diag of diagnostics) {\n\t\t\t\t\tlines.push(`- ${diag}`);\n\t\t\t\t}\n\t\t\t} else if (smokeTestPassed) {\n\t\t\t\tlines.push(\"\\n✓ No errors during factory execution.\");\n\t\t\t}\n\n\t\t\tif (registeredTools.length > 0) {\n\t\t\t\tlines.push(`\\nRegistered tools (${registeredTools.length}):`);\n\t\t\t\tfor (const toolName of registeredTools) {\n\t\t\t\t\tlines.push(`- ${toolName}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (registeredCommands.length > 0) {\n\t\t\t\tlines.push(`\\nRegistered commands (${registeredCommands.length}):`);\n\t\t\t\tfor (const cmdName of registeredCommands) {\n\t\t\t\t\tlines.push(`- ${cmdName}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (registeredTools.length === 0 && registeredCommands.length === 0 && smokeTestPassed) {\n\t\t\t\tlines.push(\"\\n⚠ Extension loaded but registered nothing.\");\n\t\t\t}\n\n\t\t\tif (ok) {\n\t\t\t\tlines.push(\"\\n✓ Extension ready for creation.\");\n\t\t\t}\n\n\t\t\tlines.push(`\\nProposed install path: ${proposedPath}`);\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: lines.join(\"\\n\") }],\n\t\t\t\tdetails: report,\n\t\t\t};\n\t\t},\n\t};\n}\n\nexport function createExtensionifyTool(\n\tcwd: string,\n\toptions?: ExtensionifyToolOptions,\n): AgentTool<typeof extensionifySchema> {\n\treturn wrapToolDefinition(createExtensionifyToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"extensionify.js","sourceRoot":"","sources":["../../../src/core/tools/extensionify.ts"],"names":[],"mappings":"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","sourcesContent":["import { rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AgentTool } from \"@caupulican/pi-agent-core\";\nimport { type Static, Type } from \"typebox\";\nimport { getAgentDir } from \"../../config.ts\";\nimport { acquireWorkRun, type WorkRunLease } from \"../../utils/work-directory.ts\";\nimport { createEventBus } from \"../event-bus.ts\";\nimport { createExtensionRuntime, loadExtension } from \"../extensions/loader.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst extensionifySchema = Type.Object({\n\tname: Type.String({ description: \"Extension name (lowercase, a-z 0-9 hyphens only)\" }),\n\tcode: Type.String({ description: \"Extension factory code (TypeScript/JavaScript)\" }),\n\tpackageJson: Type.Optional(Type.String({ description: \"Optional package.json content as JSON string\" })),\n});\n\nexport type ExtensionifyInput = Static<typeof extensionifySchema>;\n\nexport interface ExtensionifyReport {\n\tok: boolean;\n\tsmokeTestPassed: boolean;\n\tdiagnostics: string[];\n\tregistered: {\n\t\ttools: string[];\n\t\tcommands: string[];\n\t};\n\tproposedPath: string;\n\tdraft: {\n\t\tname: string;\n\t\tcode: string;\n\t\tpackageJson?: string;\n\t};\n}\n\nexport interface ExtensionifyToolDetails {\n\treport?: ExtensionifyReport;\n}\n\nexport interface ExtensionifyToolOptions {\n\tagentDir?: string;\n}\n\nexport function createExtensionifyToolDefinition(\n\t_cwd: string,\n\toptions?: ExtensionifyToolOptions,\n): ToolDefinition<typeof extensionifySchema, ExtensionifyReport> {\n\treturn {\n\t\tname: \"extensionify\",\n\t\tlabel: \"extensionify\",\n\t\tdescription:\n\t\t\t\"Smoke-test a draft extension in an isolated throwaway runtime. Pure analysis tool: creates temporary scaffold, loads it, inspects registrations, then completely deletes temp dir. Does NOT write to the real extensions dir or modify the live runtime. Returns proposal with registration details.\",\n\t\tpromptSnippet: \"Smoke-test a draft extension\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use extensionify to validate draft extensions before creating them.\",\n\t\t\t\"Fix any factory errors or registration issues; review tools and commands registered.\",\n\t\t\t\"The tool runs in complete isolation; the live session is never touched.\",\n\t\t\t\"Persistent write and activation happen later via a separate step.\",\n\t\t],\n\t\tparameters: extensionifySchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ name, code, packageJson }: ExtensionifyInput,\n\t\t\t_signal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\t_ctx?,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: ExtensionifyReport;\n\t\t}> {\n\t\t\tconst diagnostics: string[] = [];\n\t\t\tlet smokeTestPassed = false;\n\t\t\tconst registeredTools: string[] = [];\n\t\t\tconst registeredCommands: string[] = [];\n\t\t\tconst agentDir = options?.agentDir ?? getAgentDir();\n\t\t\tconst proposedPath = join(agentDir, \"extensions\", name);\n\n\t\t\tlet tempDir: string | null = null;\n\t\t\tlet workRun: WorkRunLease | undefined;\n\t\t\ttry {\n\t\t\t\tworkRun = acquireWorkRun({ agentDir, category: \"extensions\", tenant: \"smoke-test\" });\n\t\t\t\ttempDir = workRun.path;\n\n\t\t\t\t// Write index.ts with the factory code\n\t\t\t\tconst indexPath = join(tempDir, \"index.ts\");\n\t\t\t\twriteFileSync(indexPath, code, \"utf-8\");\n\n\t\t\t\t// Write package.json if provided\n\t\t\t\tif (packageJson) {\n\t\t\t\t\tconst packageJsonPath = join(tempDir, \"package.json\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Validate it's valid JSON\n\t\t\t\t\t\tJSON.parse(packageJson);\n\t\t\t\t\t\twriteFileSync(packageJsonPath, packageJson, \"utf-8\");\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tdiagnostics.push(`Invalid package.json: ${err instanceof Error ? err.message : String(err)}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Create isolated runtime and event bus\n\t\t\t\tconst eventBus = createEventBus();\n\t\t\t\tconst runtime = createExtensionRuntime();\n\n\t\t\t\t// Load the extension in isolation\n\t\t\t\tconst { extension, error: loadError } = await loadExtension(indexPath, tempDir, eventBus, runtime, {\n\t\t\t\t\tfresh: true,\n\t\t\t\t\tagentDir,\n\t\t\t\t});\n\n\t\t\t\tif (loadError) {\n\t\t\t\t\tdiagnostics.push(`Factory error: ${loadError}`);\n\t\t\t\t\tsmokeTestPassed = false;\n\t\t\t\t} else if (extension) {\n\t\t\t\t\tsmokeTestPassed = true;\n\n\t\t\t\t\t// Inspect registered tools\n\t\t\t\t\tfor (const [toolName] of extension.tools) {\n\t\t\t\t\t\tregisteredTools.push(toolName);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Inspect registered commands\n\t\t\t\t\tfor (const [cmdName] of extension.commands) {\n\t\t\t\t\t\tregisteredCommands.push(cmdName);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (registeredTools.length === 0 && registeredCommands.length === 0) {\n\t\t\t\t\t\tdiagnostics.push(\"Extension loaded but registered no tools or commands\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tdiagnostics.push(`Test error: ${err instanceof Error ? err.message : String(err)}`);\n\t\t\t\tsmokeTestPassed = false;\n\t\t\t} finally {\n\t\t\t\t// Always clean up the temporary directory.\n\t\t\t\tworkRun?.release();\n\t\t\t\tif (tempDir) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\trmSync(tempDir, { recursive: true, force: true });\n\t\t\t\t\t} catch (cleanupErr) {\n\t\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t\t`Cleanup warning: ${cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst ok = smokeTestPassed && diagnostics.length === 0;\n\n\t\t\tconst report: ExtensionifyReport = {\n\t\t\t\tok,\n\t\t\t\tsmokeTestPassed,\n\t\t\t\tdiagnostics,\n\t\t\t\tregistered: {\n\t\t\t\t\ttools: registeredTools,\n\t\t\t\t\tcommands: registeredCommands,\n\t\t\t\t},\n\t\t\t\tproposedPath,\n\t\t\t\tdraft: { name, code, packageJson },\n\t\t\t};\n\n\t\t\t// Format the report as readable text\n\t\t\tconst lines: string[] = [];\n\t\t\tlines.push(`Extensionify smoke-test: ${smokeTestPassed ? \"✓ passed\" : \"✗ failed\"}`);\n\n\t\t\tif (diagnostics.length > 0) {\n\t\t\t\tlines.push(\"\\nDiagnostics:\");\n\t\t\t\tfor (const diag of diagnostics) {\n\t\t\t\t\tlines.push(`- ${diag}`);\n\t\t\t\t}\n\t\t\t} else if (smokeTestPassed) {\n\t\t\t\tlines.push(\"\\n✓ No errors during factory execution.\");\n\t\t\t}\n\n\t\t\tif (registeredTools.length > 0) {\n\t\t\t\tlines.push(`\\nRegistered tools (${registeredTools.length}):`);\n\t\t\t\tfor (const toolName of registeredTools) {\n\t\t\t\t\tlines.push(`- ${toolName}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (registeredCommands.length > 0) {\n\t\t\t\tlines.push(`\\nRegistered commands (${registeredCommands.length}):`);\n\t\t\t\tfor (const cmdName of registeredCommands) {\n\t\t\t\t\tlines.push(`- ${cmdName}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (registeredTools.length === 0 && registeredCommands.length === 0 && smokeTestPassed) {\n\t\t\t\tlines.push(\"\\n⚠ Extension loaded but registered nothing.\");\n\t\t\t}\n\n\t\t\tif (ok) {\n\t\t\t\tlines.push(\"\\n✓ Extension ready for creation.\");\n\t\t\t}\n\n\t\t\tlines.push(`\\nProposed install path: ${proposedPath}`);\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: lines.join(\"\\n\") }],\n\t\t\t\tdetails: report,\n\t\t\t};\n\t\t},\n\t};\n}\n\nexport function createExtensionifyTool(\n\tcwd: string,\n\toptions?: ExtensionifyToolOptions,\n): AgentTool<typeof extensionifySchema> {\n\treturn wrapToolDefinition(createExtensionifyToolDefinition(cwd, options));\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { type Static, Type } from "typebox";
2
- import type { WorkerResult } from "../autonomy/contracts.ts";
2
+ import type { WorkerClaim } from "../autonomy/contracts.ts";
3
3
  import type { LaneRecord } from "../autonomy/lane-tracker.ts";
4
4
  import type { ToolDefinition } from "../extensions/types.ts";
5
5
  import type { GoalState } from "../goals/goal-state.ts";
@@ -31,7 +31,7 @@ export interface GoalToolDetails {
31
31
  dispatchedLaneId?: string;
32
32
  /** Set on 'dispatch_worker' when no worker was dispatched: a wired dependency declined (e.g. worker
33
33
  * delegation disabled, already at capacity, or an honest tmux skip reason -- see
34
- * {@link GoalToolDependencies.dispatchTmuxWorker}), or the reload-vanish dedupe guard refused a
34
+ * {@link GoalToolDependencies.dispatchTmuxWorker}), or the indeterminate-binding guard refused a
35
35
  * re-dispatch against an already-bound requirement (`requirement_already_bound`/`bound_lane_indeterminate`).
36
36
  * The binding is recorded (or, for a guard refusal, left exactly as it was) with no NEW laneId. */
37
37
  dispatchSkipReason?: string;
@@ -57,13 +57,13 @@ export interface GoalToolDependencies {
57
57
  */
58
58
  getLaneRecords?: () => readonly LaneRecord[];
59
59
  /**
60
- * Read persisted worker result snapshots (keyed by `WorkerResult.requestId`, which is the same
60
+ * Read persisted worker claim snapshots (keyed by `WorkerClaim.requestId`, which is the same
61
61
  * id as the dispatching lane's laneId), for validating kind:"worker" evidence refs. See
62
- * {@link getLaneRecords}. A matching result that is `parentReviewRequired && !parentReviewedAt`
62
+ * {@link getLaneRecords}. A matching claim that is `parentReviewRequired && !parentReviewedAt`
63
63
  * verifies `false` -- an unreviewed worker completion must never ungate goal completion through
64
64
  * the existing verified/complete gate.
65
65
  */
66
- getWorkerResultSnapshots?: () => readonly WorkerResult[];
66
+ getWorkerClaimSnapshots?: () => readonly WorkerClaim[];
67
67
  /**
68
68
  * Tool-layer side effect for a 'dispatch_worker' action when `dispatchTarget` is 'in_process'
69
69
  * (the default) or when {@link dispatchTmuxWorker} is not wired: dispatches a real in-process
@@ -1 +1 @@
1
- {"version":3,"file":"goal.d.ts","sourceRoot":"","sources":["../../../src/core/tools/goal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAoB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAGN,KAAK,cAAc,EACnB,KAAK,eAAe,EAEpB,MAAM,4BAA4B,CAAC;AAGpC,QAAA,MAAM,UAAU;;;;;;;;;;;;;;EAiEf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;iHAE6G;IAC7G,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;uGAImG;IACnG,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACpC,mEAAmE;IACnE,YAAY,EAAE,MAAM,SAAS,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAChD;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,SAAS,UAAU,EAAE,CAAC;IAC7C;;;;;;OAMG;IACH,wBAAwB,CAAC,EAAE,MAAM,SAAS,YAAY,EAAE,CAAC;IACzD;;;;;;;;;OASG;IACH,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC9B,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACrB,KAAK;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC3D;;;;;;;;;;;;;;;;;OAiBG;IACH,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACrB,KAAK,OAAO,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,mGAAmG;IACnG,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;;OAGG;IACH,oCAAoC,CAAC,EAAE,MAAM,OAAO,CAAC;IACrD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,SAAS,eAAe,EAAE,CAAC;CACpD;AAkGD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,oBAAoB,GAAG,cAAc,CA6InF","sourcesContent":["import { stat as fsStat } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport type { WorkerResult } from \"../autonomy/contracts.ts\";\nimport type { LaneRecord } from \"../autonomy/lane-tracker.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { GoalEvidenceKind, GoalState } from \"../goals/goal-state.ts\";\nimport {\n\tapplyGoalAction,\n\ttype GoalAction,\n\ttype GoalActionName,\n\ttype OpenTaskStepRef,\n\tsummarizeGoalState,\n} from \"../goals/goal-tool-core.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\n\nconst goalSchema = Type.Object(\n\t{\n\t\taction: Type.Union(\n\t\t\t[\n\t\t\t\tType.Literal(\"start\"),\n\t\t\t\tType.Literal(\"add_requirement\"),\n\t\t\t\tType.Literal(\"satisfy_requirement\"),\n\t\t\t\tType.Literal(\"block_requirement\"),\n\t\t\t\tType.Literal(\"reopen_requirement\"),\n\t\t\t\tType.Literal(\"dispatch_worker\"),\n\t\t\t\tType.Literal(\"add_evidence\"),\n\t\t\t\tType.Literal(\"progress\"),\n\t\t\t\tType.Literal(\"no_progress\"),\n\t\t\t\tType.Literal(\"complete\"),\n\t\t\t\tType.Literal(\"block_goal\"),\n\t\t\t\tType.Literal(\"resume_goal\"),\n\t\t\t\tType.Literal(\"cancel\"),\n\t\t\t],\n\t\t\t{ description: \"Ledger action to record.\" },\n\t\t),\n\t\tgoalId: Type.Optional(Type.String({ description: \"Stable goal id. Required for action 'start'.\" })),\n\t\tuserGoal: Type.Optional(Type.String({ description: \"The goal statement. Required for action 'start'.\" })),\n\t\trequirementId: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Requirement id for add_requirement/satisfy_requirement/block_requirement/reopen_requirement/dispatch_worker.\",\n\t\t\t}),\n\t\t),\n\t\ttext: Type.Optional(Type.String({ description: \"Requirement text. Required for add_requirement.\" })),\n\t\tinstructions: Type.Optional(Type.String({ description: \"Worker instructions. Required for dispatch_worker.\" })),\n\t\tevidenceId: Type.Optional(Type.String({ description: \"Evidence id. Required for add_evidence.\" })),\n\t\tevidenceIds: Type.Optional(\n\t\t\tType.Array(Type.String(), {\n\t\t\t\tdescription: \"Evidence ids supporting a satisfy_requirement action. Each must already be recorded.\",\n\t\t\t}),\n\t\t),\n\t\tkind: Type.Optional(\n\t\t\tType.Union(\n\t\t\t\t[\n\t\t\t\t\tType.Literal(\"file\"),\n\t\t\t\t\tType.Literal(\"test\"),\n\t\t\t\t\tType.Literal(\"tool\"),\n\t\t\t\t\tType.Literal(\"user\"),\n\t\t\t\t\tType.Literal(\"finding\"),\n\t\t\t\t\tType.Literal(\"worker\"),\n\t\t\t\t],\n\t\t\t\t{ description: \"Evidence kind. Required for add_evidence.\" },\n\t\t\t),\n\t\t),\n\t\tsummary: Type.Optional(Type.String({ description: \"Evidence summary. Required for add_evidence.\" })),\n\t\turi: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Optional evidence locator (path/URL for kind 'file', a toolCallId for kind 'tool', a laneId for kind 'worker').\",\n\t\t\t}),\n\t\t),\n\t\treason: Type.Optional(Type.String({ description: \"Reason for block_requirement or block_goal.\" })),\n\t\tdispatchTarget: Type.Optional(\n\t\t\tType.Union([Type.Literal(\"in_process\"), Type.Literal(\"tmux\")], {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Worker runtime for dispatch_worker. Defaults to 'in_process'. 'tmux' dispatches a persistent tmux worker via the tmux_agent_manager extension -- only takes effect when that dependency is wired AND an owner-granted standing dispatch grant covers it; otherwise the dispatch is honestly skipped with a dispatchSkipReason (never a silent fallback or a fake launch).\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type GoalToolInput = Static<typeof goalSchema>;\n\nexport interface GoalToolDetails {\n\taction: GoalActionName;\n\tapplied: boolean;\n\terror?: string;\n\tstate?: GoalState;\n\t/** Set on 'dispatch_worker' when a worker lane actually started; mirrors the requirement's\n\t * new `boundLaneId`. The in-process route by default, or a real persistent tmux lane when\n\t * `dispatchTarget:\"tmux\"` was selected and routed -- see {@link GoalToolDependencies.dispatchTmuxWorker}. */\n\tdispatchedLaneId?: string;\n\t/** Set on 'dispatch_worker' when no worker was dispatched: a wired dependency declined (e.g. worker\n\t * delegation disabled, already at capacity, or an honest tmux skip reason -- see\n\t * {@link GoalToolDependencies.dispatchTmuxWorker}), or the reload-vanish dedupe guard refused a\n\t * re-dispatch against an already-bound requirement (`requirement_already_bound`/`bound_lane_indeterminate`).\n\t * The binding is recorded (or, for a guard refusal, left exactly as it was) with no NEW laneId. */\n\tdispatchSkipReason?: string;\n}\n\nexport interface GoalToolDependencies {\n\t/** Read the latest persisted goal state for the active session. */\n\tgetGoalState: () => GoalState | undefined;\n\t/** Persist a new goal state snapshot to the active session. */\n\tsaveGoalState: (state: GoalState) => void;\n\t/** Clock injection for deterministic tests. */\n\tnow?: () => string;\n\t/**\n\t * Check whether `toolCallId` exists in this session's records, for validating kind:\"tool\"\n\t * evidence refs at add_evidence time. When not wired, a \"tool\" ref cannot be proven and is\n\t * recorded as `verified: false` rather than assumed true.\n\t */\n\thasToolCallId?: (toolCallId: string) => boolean;\n\t/**\n\t * Read the session's live worker lane records, for validating kind:\"worker\" evidence refs\n\t * (the `uri` is a laneId) at add_evidence time. Read-defensive: when not wired -- exactly like\n\t * `hasToolCallId` -- a \"worker\" ref cannot be proven and is recorded as `verified: false` rather\n\t * than assumed true. Live wiring is added separately.\n\t */\n\tgetLaneRecords?: () => readonly LaneRecord[];\n\t/**\n\t * Read persisted worker result snapshots (keyed by `WorkerResult.requestId`, which is the same\n\t * id as the dispatching lane's laneId), for validating kind:\"worker\" evidence refs. See\n\t * {@link getLaneRecords}. A matching result that is `parentReviewRequired && !parentReviewedAt`\n\t * verifies `false` -- an unreviewed worker completion must never ungate goal completion through\n\t * the existing verified/complete gate.\n\t */\n\tgetWorkerResultSnapshots?: () => readonly WorkerResult[];\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `dispatchTarget` is 'in_process'\n\t * (the default) or when {@link dispatchTmuxWorker} is not wired: dispatches a real in-process\n\t * worker lane for the given requirement and returns the resulting laneId to bind onto it. When\n\t * the dependency is present but the underlying delegation starter declines (disabled, already at\n\t * capacity, etc.), return `{ skipReason }` instead of a laneId -- a real, non-silent skip that\n\t * the tool response surfaces, distinct from this dependency being altogether unwired (`undefined`\n\t * dep, or the dep returning `undefined`), which records the binding attempt structurally with no\n\t * laneId (a no-op).\n\t */\n\tstartWorkerDelegation?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => { laneId?: string; skipReason?: string } | undefined;\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `input.dispatchTarget === \"tmux\"`:\n\t * dispatches a REAL persistent tmux worker via the tmux_agent_manager extension's `fire_task`\n\t * action (core structurally invokes the same tool call the model would make; no extension change,\n\t * no faked launch or laneId -- see `tmux-dispatch.ts`'s `dispatchTmuxWorker`). Selected ONLY when\n\t * BOTH `input.dispatchTarget === \"tmux\"` AND this dependency is present; otherwise the EXISTING\n\t * {@link startWorkerDelegation} in-process path runs, byte-identical to before this field existed.\n\t * The honest skip-reason vocabulary this can return: `tmux_extension_not_loaded`,\n\t * `no_standing_grant` (the owner has not authorized unattended tmux dispatch),\n\t * `tmux_dispatch_failed`, `tmux_dispatch_incomplete`, `lane_correlation_failed`,\n\t * `worktree_create_failed` (worktree-sync is enabled but the lane-first `create_lane` call was\n\t * refused -- e.g. max lanes reached -- so no fire_task call was ever attempted),\n\t * `worker_capability_insufficient` (the model is sub-full class, has an unknown context window,\n\t * does not advertise a native tool-call path, or is graded-demoted to text-protocol/none -- see\n\t * `model-capability.ts`'s `evaluateLaneWorkerRefusal`; this is the parent's best-effort check\n\t * only, refused before any lane/pane side effect -- the dispatched child still refuses\n\t * authoritatively at its own startup regardless).\n\t */\n\tdispatchTmuxWorker?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => Promise<{ laneId?: string; skipReason?: string }>;\n\t/** Working directory for resolving kind:\"file\" evidence ref paths. Defaults to `process.cwd()`. */\n\tcwd?: () => string;\n\t/**\n\t * Gate agent-facing 'complete' on verified/user evidence backing. Defaults to `true` (on)\n\t * when omitted -- the conservative default; set to a function returning `false` to opt out.\n\t */\n\trequireVerifiedEvidenceForCompletion?: () => boolean;\n\t/**\n\t * Read-only open (non-terminal) task_steps steps on the active branch, for the goal⇄task\n\t * cross-visibility nudge in the tool response. When omitted, `summarizeGoalState` gets\n\t * no task-step context and simply emits no nudge -- goal-tool-core stays pure and never reads\n\t * task state itself; this is the only place that supplies it.\n\t */\n\tgetOpenTaskSteps?: () => readonly OpenTaskStepRef[];\n}\n\n/**\n * Validate an evidence ref's `uri` against session records (\"tool\") or the filesystem (\"file\").\n * Returns `undefined` for kinds/refs that carry nothing checkable (e.g. \"user\"/\"finding\"/\"test\",\n * or a missing `uri`) -- absence of a ref is not the same as a ref that failed to verify.\n */\nasync function resolveEvidenceVerified(\n\tkind: GoalEvidenceKind,\n\turi: string | undefined,\n\tdeps: GoalToolDependencies,\n): Promise<boolean | undefined> {\n\tconst trimmedUri = uri?.trim();\n\tif (!trimmedUri) return undefined;\n\tif (kind === \"tool\") {\n\t\treturn deps.hasToolCallId ? deps.hasToolCallId(trimmedUri) : false;\n\t}\n\tif (kind === \"file\") {\n\t\tconst cwd = deps.cwd?.() ?? process.cwd();\n\t\ttry {\n\t\t\tconst stats = await fsStat(resolveToCwd(trimmedUri, cwd));\n\t\t\treturn stats.isFile();\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (kind === \"worker\") {\n\t\tif (!deps.getLaneRecords || !deps.getWorkerResultSnapshots) return false;\n\t\tconst laneId = trimmedUri;\n\t\tconst record = deps.getLaneRecords().find((candidate) => candidate.laneId === laneId);\n\t\tif (!record) return false;\n\t\tconst result = deps.getWorkerResultSnapshots().find((candidate) => candidate.requestId === laneId);\n\t\tif (!result) return false;\n\t\t// An unreviewed mutation (parentReviewRequired && no parentReviewedAt) can never verify true --\n\t\t// this is what stops an unreviewed worker completion from ungating goal completion through\n\t\t// the existing verified/complete gate (goal-tool-core's isVerifiedOrUserEvidence/complete).\n\t\tif (result.parentReviewRequired === true && result.parentReviewedAt === undefined) return false;\n\t\treturn result.status === \"completed\";\n\t}\n\treturn undefined;\n}\n\nfunction toGoalAction(input: GoalToolInput): GoalAction | { error: string } {\n\tswitch (input.action) {\n\t\tcase \"start\":\n\t\t\treturn { action: \"start\", goalId: input.goalId ?? \"\", userGoal: input.userGoal ?? \"\" };\n\t\tcase \"add_requirement\":\n\t\t\treturn { action: \"add_requirement\", requirementId: input.requirementId ?? \"\", text: input.text ?? \"\" };\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"satisfy_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tevidenceIds: input.evidenceIds,\n\t\t\t};\n\t\tcase \"block_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"block_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\treason: input.reason ?? \"\",\n\t\t\t};\n\t\tcase \"reopen_requirement\":\n\t\t\treturn { action: \"reopen_requirement\", requirementId: input.requirementId ?? \"\" };\n\t\tcase \"dispatch_worker\":\n\t\t\treturn {\n\t\t\t\taction: \"dispatch_worker\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tinstructions: input.instructions ?? \"\",\n\t\t\t};\n\t\tcase \"add_evidence\": {\n\t\t\tif (input.kind === undefined) {\n\t\t\t\treturn { error: \"add_evidence requires a kind.\" };\n\t\t\t}\n\t\t\tconst kind: GoalEvidenceKind = input.kind;\n\t\t\treturn {\n\t\t\t\taction: \"add_evidence\",\n\t\t\t\tevidenceId: input.evidenceId ?? \"\",\n\t\t\t\tkind,\n\t\t\t\tsummary: input.summary ?? \"\",\n\t\t\t\turi: input.uri,\n\t\t\t};\n\t\t}\n\t\tcase \"progress\":\n\t\t\treturn { action: \"progress\" };\n\t\tcase \"no_progress\":\n\t\t\treturn { action: \"no_progress\" };\n\t\tcase \"complete\":\n\t\t\treturn { action: \"complete\" };\n\t\tcase \"block_goal\":\n\t\t\treturn { action: \"block_goal\", reason: input.reason ?? \"\" };\n\t\tcase \"resume_goal\":\n\t\t\treturn { action: \"resume_goal\" };\n\t\tcase \"cancel\":\n\t\t\treturn { action: \"cancel\" };\n\t\tdefault:\n\t\t\treturn { error: \"Unknown goal action.\" };\n\t}\n}\n\nexport function createGoalToolDefinition(deps: GoalToolDependencies): ToolDefinition {\n\tconst now = deps.now ?? (() => new Date().toISOString());\n\treturn {\n\t\tname: \"goal\",\n\t\tlabel: \"goal\",\n\t\tdescription:\n\t\t\t\"Record and update the durable goal ledger for the current task. Maintains a structured goal with requirements, evidence, and progress so long tasks can be resumed and continued. Start a goal, add requirements, attach evidence, mark requirements satisfied or blocked, reopen resolved blockers, resume blocked goals, and mark progress. This is the producer that drives /goal-continue; without recorded goal state, continuation has nothing to act on.\",\n\t\tpromptSnippet: \"Record goal, requirements, evidence, and progress in the durable goal ledger.\",\n\t\tpromptGuidelines: [\n\t\t\t\"At the start of a multi-step task, call goal with action 'start' to record the user goal, then add the concrete requirements with 'add_requirement'.\",\n\t\t\t\"As you make progress, record evidence with 'add_evidence' and mark requirements satisfied with 'satisfy_requirement', citing the evidence ids.\",\n\t\t\t\"For 'add_evidence', kind 'tool' expects a real toolCallId in 'uri' and kind 'file' expects a real path; both are checked and recorded as verified or not. Kind 'worker' expects a laneId in 'uri' and verifies true only for a reviewed, completed worker result. Kinds 'user'/'finding'/'test' carry no checkable ref.\",\n\t\t\t\"Use 'dispatch_worker' to bind a requirement to a worker lane while it is being worked; this records the binding only -- it never satisfies the requirement. Record 'worker'-kind evidence citing that laneId once the worker completes, then call 'satisfy_requirement'.\",\n\t\t\t\"Use 'progress' when you advance without satisfying a specific requirement, and 'no_progress' when a turn yields nothing, so stall detection works.\",\n\t\t\t\"When the user resolves a blocker, use 'resume_goal' and 'reopen_requirement' as needed; do not strand the old ledger or start a duplicate goal.\",\n\t\t\t\"Mark the goal 'complete' only when every requirement is satisfied; completion normally also requires at least one satisfied requirement backed by verified 'tool'/'file' evidence or kind 'user' evidence. Use 'block_goal' or 'block_requirement' with a reason when you are stuck and need the user. A blocked goal can still be resumed or cancelled.\",\n\t\t],\n\t\tparameters: goalSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tinput: GoalToolInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: GoalToolDetails;\n\t\t}> {\n\t\t\tconst mapped = toGoalAction(input);\n\t\t\tif (\"error\" in mapped) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${mapped.error}` }],\n\t\t\t\t\tdetails: { action: input.action, applied: false, error: mapped.error },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet action: GoalAction = mapped;\n\t\t\tif (action.action === \"add_evidence\") {\n\t\t\t\tconst verified = await resolveEvidenceVerified(action.kind, action.uri, deps);\n\t\t\t\taction = { ...action, verified };\n\t\t\t}\n\t\t\t// Honest dispatch reporting: distinguish \"dispatched\" (laneId), \"declined\" (skipReason --\n\t\t\t// the dependency IS wired but the underlying delegation starter refused, e.g. disabled or\n\t\t\t// already at capacity), and \"unwired\" (no dependency at all) -- never collapse a real\n\t\t\t// decline into a silent no-laneId no-op indistinguishable from the dep being absent.\n\t\t\tlet dispatchNote: string | undefined;\n\t\t\tlet dispatchSkipReason: string | undefined;\n\t\t\t// Reload-vanish dedupe guard: checked BEFORE any dispatch side effect, for BOTH\n\t\t\t// routes. A requirement already bound to a lane that is either still live (a plain\n\t\t\t// duplicate) or whose liveness/outcome cannot be determined at all (the reload-vanish\n\t\t\t// case -- the lane record and any worker-result snapshot are both gone) must never be\n\t\t\t// re-dispatched silently; only a CONFIRMED terminal outcome allows a legitimate retry.\n\t\t\tlet dispatchGuardRefused = false;\n\t\t\tif (action.action === \"dispatch_worker\") {\n\t\t\t\t// Captured into a `const` so the \"dispatch_worker\" narrowing survives into the closures\n\t\t\t\t// below -- TS does not narrow a `let`-bound outer variable across a callback boundary.\n\t\t\t\tconst dispatchAction = action;\n\t\t\t\tconst boundRequirement = deps\n\t\t\t\t\t.getGoalState()\n\t\t\t\t\t?.requirements.find((r) => r.id === dispatchAction.requirementId);\n\t\t\t\tconst bound = boundRequirement?.boundLaneId;\n\t\t\t\tif (bound !== undefined) {\n\t\t\t\t\tconst boundLaneRecord = deps.getLaneRecords?.().find((record) => record.laneId === bound);\n\t\t\t\t\tconst isLiveInFlight =\n\t\t\t\t\t\tboundLaneRecord !== undefined &&\n\t\t\t\t\t\t(boundLaneRecord.status === \"queued\" || boundLaneRecord.status === \"running\");\n\t\t\t\t\tif (isLiveInFlight) {\n\t\t\t\t\t\tdispatchSkipReason = \"requirement_already_bound\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// `boundLaneRecord` present here is necessarily terminal (isLiveInFlight was false).\n\t\t\t\t\t\tconst hasTerminalOutcome =\n\t\t\t\t\t\t\tboundLaneRecord !== undefined ||\n\t\t\t\t\t\t\t(deps.getWorkerResultSnapshots?.().some((result) => result.requestId === bound) ?? false);\n\t\t\t\t\t\tif (!hasTerminalOutcome) dispatchSkipReason = \"bound_lane_indeterminate\";\n\t\t\t\t\t}\n\t\t\t\t\tif (dispatchSkipReason) {\n\t\t\t\t\t\tdispatchGuardRefused = true;\n\t\t\t\t\t\tdispatchNote = `No worker was dispatched (${dispatchSkipReason}); requirement '${dispatchAction.requirementId}' remains bound to lane '${bound}'.`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (action.action === \"dispatch_worker\" && !dispatchGuardRefused) {\n\t\t\t\tconst useTmux = input.dispatchTarget === \"tmux\" && deps.dispatchTmuxWorker !== undefined;\n\t\t\t\tconst dispatched = useTmux\n\t\t\t\t\t? await deps.dispatchTmuxWorker?.({\n\t\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t\t})\n\t\t\t\t\t: deps.startWorkerDelegation?.({\n\t\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t\t});\n\t\t\t\taction = { ...action, laneId: dispatched?.laneId };\n\t\t\t\tif (dispatched?.laneId) {\n\t\t\t\t\tdispatchNote = useTmux\n\t\t\t\t\t\t? `Dispatched tmux worker lane '${dispatched.laneId}' for requirement '${action.requirementId}'.`\n\t\t\t\t\t\t: `Dispatched in-process worker lane '${dispatched.laneId}' for requirement '${action.requirementId}' (tmux dispatch is not available from this tool yet).`;\n\t\t\t\t} else {\n\t\t\t\t\tconst wired = useTmux ? deps.dispatchTmuxWorker : deps.startWorkerDelegation;\n\t\t\t\t\tdispatchSkipReason = dispatched?.skipReason ?? (wired ? \"declined\" : \"dependency_unwired\");\n\t\t\t\t\tdispatchNote = `No worker was dispatched (${dispatchSkipReason}); requirement '${action.requirementId}' is recorded but not bound to a lane.`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst current = deps.getGoalState();\n\t\t\tlet nextState: GoalState;\n\t\t\tif (action.action === \"dispatch_worker\" && dispatchGuardRefused) {\n\t\t\t\t// Short-circuit: the guard refused before any dispatch attempt -- never call\n\t\t\t\t// applyGoalAction for this turn, so the requirement's existing `boundLaneId` is\n\t\t\t\t// preserved exactly as-is rather than clobbered to `undefined` by the reducer's\n\t\t\t\t// unconditional `boundLaneId: event.laneId` write (goal-state.ts's dispatch_worker case).\n\t\t\t\t// `current` is guaranteed defined here: the guard only refuses when a requirement with\n\t\t\t\t// a `boundLaneId` was found on it.\n\t\t\t\tnextState = current as GoalState;\n\t\t\t} else {\n\t\t\t\tconst result = applyGoalAction(current, action, now(), {\n\t\t\t\t\trequireVerifiedEvidenceForCompletion: deps.requireVerifiedEvidenceForCompletion?.() ?? true,\n\t\t\t\t});\n\t\t\t\tif (!result.ok) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${result.error}` }],\n\t\t\t\t\t\tdetails: { action: input.action, applied: false, error: result.error, state: current },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tdeps.saveGoalState(result.state);\n\t\t\t\tnextState = result.state;\n\t\t\t}\n\n\t\t\tconst summary = summarizeGoalState(nextState, { action, openTaskSteps: deps.getOpenTaskSteps?.() });\n\t\t\tconst text = dispatchNote\n\t\t\t\t? `goal ${input.action} recorded.\\n${summary}\\n${dispatchNote}`\n\t\t\t\t: `goal ${input.action} recorded.\\n${summary}`;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text }],\n\t\t\t\tdetails: {\n\t\t\t\t\taction: input.action,\n\t\t\t\t\tapplied: true,\n\t\t\t\t\tstate: nextState,\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && action.laneId ? { dispatchedLaneId: action.laneId } : {}),\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && !action.laneId ? { dispatchSkipReason } : {}),\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"goal.d.ts","sourceRoot":"","sources":["../../../src/core/tools/goal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAoB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAGN,KAAK,cAAc,EACnB,KAAK,eAAe,EAEpB,MAAM,4BAA4B,CAAC;AAGpC,QAAA,MAAM,UAAU;;;;;;;;;;;;;;EAiEf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;iHAE6G;IAC7G,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;uGAImG;IACnG,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACpC,mEAAmE;IACnE,YAAY,EAAE,MAAM,SAAS,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAChD;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,SAAS,UAAU,EAAE,CAAC;IAC7C;;;;;;OAMG;IACH,uBAAuB,CAAC,EAAE,MAAM,SAAS,WAAW,EAAE,CAAC;IACvD;;;;;;;;;OASG;IACH,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC9B,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACrB,KAAK;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC3D;;;;;;;;;;;;;;;;;OAiBG;IACH,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACrB,KAAK,OAAO,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,mGAAmG;IACnG,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;;OAGG;IACH,oCAAoC,CAAC,EAAE,MAAM,OAAO,CAAC;IACrD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,SAAS,eAAe,EAAE,CAAC;CACpD;AAkGD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,oBAAoB,GAAG,cAAc,CA6InF","sourcesContent":["import { stat as fsStat } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport type { WorkerClaim } from \"../autonomy/contracts.ts\";\nimport type { LaneRecord } from \"../autonomy/lane-tracker.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { GoalEvidenceKind, GoalState } from \"../goals/goal-state.ts\";\nimport {\n\tapplyGoalAction,\n\ttype GoalAction,\n\ttype GoalActionName,\n\ttype OpenTaskStepRef,\n\tsummarizeGoalState,\n} from \"../goals/goal-tool-core.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\n\nconst goalSchema = Type.Object(\n\t{\n\t\taction: Type.Union(\n\t\t\t[\n\t\t\t\tType.Literal(\"start\"),\n\t\t\t\tType.Literal(\"add_requirement\"),\n\t\t\t\tType.Literal(\"satisfy_requirement\"),\n\t\t\t\tType.Literal(\"block_requirement\"),\n\t\t\t\tType.Literal(\"reopen_requirement\"),\n\t\t\t\tType.Literal(\"dispatch_worker\"),\n\t\t\t\tType.Literal(\"add_evidence\"),\n\t\t\t\tType.Literal(\"progress\"),\n\t\t\t\tType.Literal(\"no_progress\"),\n\t\t\t\tType.Literal(\"complete\"),\n\t\t\t\tType.Literal(\"block_goal\"),\n\t\t\t\tType.Literal(\"resume_goal\"),\n\t\t\t\tType.Literal(\"cancel\"),\n\t\t\t],\n\t\t\t{ description: \"Ledger action to record.\" },\n\t\t),\n\t\tgoalId: Type.Optional(Type.String({ description: \"Stable goal id. Required for action 'start'.\" })),\n\t\tuserGoal: Type.Optional(Type.String({ description: \"The goal statement. Required for action 'start'.\" })),\n\t\trequirementId: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Requirement id for add_requirement/satisfy_requirement/block_requirement/reopen_requirement/dispatch_worker.\",\n\t\t\t}),\n\t\t),\n\t\ttext: Type.Optional(Type.String({ description: \"Requirement text. Required for add_requirement.\" })),\n\t\tinstructions: Type.Optional(Type.String({ description: \"Worker instructions. Required for dispatch_worker.\" })),\n\t\tevidenceId: Type.Optional(Type.String({ description: \"Evidence id. Required for add_evidence.\" })),\n\t\tevidenceIds: Type.Optional(\n\t\t\tType.Array(Type.String(), {\n\t\t\t\tdescription: \"Evidence ids supporting a satisfy_requirement action. Each must already be recorded.\",\n\t\t\t}),\n\t\t),\n\t\tkind: Type.Optional(\n\t\t\tType.Union(\n\t\t\t\t[\n\t\t\t\t\tType.Literal(\"file\"),\n\t\t\t\t\tType.Literal(\"test\"),\n\t\t\t\t\tType.Literal(\"tool\"),\n\t\t\t\t\tType.Literal(\"user\"),\n\t\t\t\t\tType.Literal(\"finding\"),\n\t\t\t\t\tType.Literal(\"worker\"),\n\t\t\t\t],\n\t\t\t\t{ description: \"Evidence kind. Required for add_evidence.\" },\n\t\t\t),\n\t\t),\n\t\tsummary: Type.Optional(Type.String({ description: \"Evidence summary. Required for add_evidence.\" })),\n\t\turi: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Optional evidence locator (path/URL for kind 'file', a toolCallId for kind 'tool', a laneId for kind 'worker').\",\n\t\t\t}),\n\t\t),\n\t\treason: Type.Optional(Type.String({ description: \"Reason for block_requirement or block_goal.\" })),\n\t\tdispatchTarget: Type.Optional(\n\t\t\tType.Union([Type.Literal(\"in_process\"), Type.Literal(\"tmux\")], {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Worker runtime for dispatch_worker. Defaults to 'in_process'. 'tmux' dispatches a persistent tmux worker via the tmux_agent_manager extension -- only takes effect when that dependency is wired AND an owner-granted standing dispatch grant covers it; otherwise the dispatch is honestly skipped with a dispatchSkipReason (never a silent fallback or a fake launch).\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type GoalToolInput = Static<typeof goalSchema>;\n\nexport interface GoalToolDetails {\n\taction: GoalActionName;\n\tapplied: boolean;\n\terror?: string;\n\tstate?: GoalState;\n\t/** Set on 'dispatch_worker' when a worker lane actually started; mirrors the requirement's\n\t * new `boundLaneId`. The in-process route by default, or a real persistent tmux lane when\n\t * `dispatchTarget:\"tmux\"` was selected and routed -- see {@link GoalToolDependencies.dispatchTmuxWorker}. */\n\tdispatchedLaneId?: string;\n\t/** Set on 'dispatch_worker' when no worker was dispatched: a wired dependency declined (e.g. worker\n\t * delegation disabled, already at capacity, or an honest tmux skip reason -- see\n\t * {@link GoalToolDependencies.dispatchTmuxWorker}), or the indeterminate-binding guard refused a\n\t * re-dispatch against an already-bound requirement (`requirement_already_bound`/`bound_lane_indeterminate`).\n\t * The binding is recorded (or, for a guard refusal, left exactly as it was) with no NEW laneId. */\n\tdispatchSkipReason?: string;\n}\n\nexport interface GoalToolDependencies {\n\t/** Read the latest persisted goal state for the active session. */\n\tgetGoalState: () => GoalState | undefined;\n\t/** Persist a new goal state snapshot to the active session. */\n\tsaveGoalState: (state: GoalState) => void;\n\t/** Clock injection for deterministic tests. */\n\tnow?: () => string;\n\t/**\n\t * Check whether `toolCallId` exists in this session's records, for validating kind:\"tool\"\n\t * evidence refs at add_evidence time. When not wired, a \"tool\" ref cannot be proven and is\n\t * recorded as `verified: false` rather than assumed true.\n\t */\n\thasToolCallId?: (toolCallId: string) => boolean;\n\t/**\n\t * Read the session's live worker lane records, for validating kind:\"worker\" evidence refs\n\t * (the `uri` is a laneId) at add_evidence time. Read-defensive: when not wired -- exactly like\n\t * `hasToolCallId` -- a \"worker\" ref cannot be proven and is recorded as `verified: false` rather\n\t * than assumed true. Live wiring is added separately.\n\t */\n\tgetLaneRecords?: () => readonly LaneRecord[];\n\t/**\n\t * Read persisted worker claim snapshots (keyed by `WorkerClaim.requestId`, which is the same\n\t * id as the dispatching lane's laneId), for validating kind:\"worker\" evidence refs. See\n\t * {@link getLaneRecords}. A matching claim that is `parentReviewRequired && !parentReviewedAt`\n\t * verifies `false` -- an unreviewed worker completion must never ungate goal completion through\n\t * the existing verified/complete gate.\n\t */\n\tgetWorkerClaimSnapshots?: () => readonly WorkerClaim[];\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `dispatchTarget` is 'in_process'\n\t * (the default) or when {@link dispatchTmuxWorker} is not wired: dispatches a real in-process\n\t * worker lane for the given requirement and returns the resulting laneId to bind onto it. When\n\t * the dependency is present but the underlying delegation starter declines (disabled, already at\n\t * capacity, etc.), return `{ skipReason }` instead of a laneId -- a real, non-silent skip that\n\t * the tool response surfaces, distinct from this dependency being altogether unwired (`undefined`\n\t * dep, or the dep returning `undefined`), which records the binding attempt structurally with no\n\t * laneId (a no-op).\n\t */\n\tstartWorkerDelegation?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => { laneId?: string; skipReason?: string } | undefined;\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `input.dispatchTarget === \"tmux\"`:\n\t * dispatches a REAL persistent tmux worker via the tmux_agent_manager extension's `fire_task`\n\t * action (core structurally invokes the same tool call the model would make; no extension change,\n\t * no faked launch or laneId -- see `tmux-dispatch.ts`'s `dispatchTmuxWorker`). Selected ONLY when\n\t * BOTH `input.dispatchTarget === \"tmux\"` AND this dependency is present; otherwise the EXISTING\n\t * {@link startWorkerDelegation} in-process path runs, byte-identical to before this field existed.\n\t * The honest skip-reason vocabulary this can return: `tmux_extension_not_loaded`,\n\t * `no_standing_grant` (the owner has not authorized unattended tmux dispatch),\n\t * `tmux_dispatch_failed`, `tmux_dispatch_incomplete`, `lane_correlation_failed`,\n\t * `worktree_create_failed` (worktree-sync is enabled but the lane-first `create_lane` call was\n\t * refused -- e.g. max lanes reached -- so no fire_task call was ever attempted),\n\t * `worker_capability_insufficient` (the model is sub-full class, has an unknown context window,\n\t * does not advertise a native tool-call path, or is graded-demoted to text-protocol/none -- see\n\t * `model-capability.ts`'s `evaluateLaneWorkerRefusal`; this is the parent's best-effort check\n\t * only, refused before any lane/pane side effect -- the dispatched child still refuses\n\t * authoritatively at its own startup regardless).\n\t */\n\tdispatchTmuxWorker?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => Promise<{ laneId?: string; skipReason?: string }>;\n\t/** Working directory for resolving kind:\"file\" evidence ref paths. Defaults to `process.cwd()`. */\n\tcwd?: () => string;\n\t/**\n\t * Gate agent-facing 'complete' on verified/user evidence backing. Defaults to `true` (on)\n\t * when omitted -- the conservative default; set to a function returning `false` to opt out.\n\t */\n\trequireVerifiedEvidenceForCompletion?: () => boolean;\n\t/**\n\t * Read-only open (non-terminal) task_steps steps on the active branch, for the goal⇄task\n\t * cross-visibility nudge in the tool response. When omitted, `summarizeGoalState` gets\n\t * no task-step context and simply emits no nudge -- goal-tool-core stays pure and never reads\n\t * task state itself; this is the only place that supplies it.\n\t */\n\tgetOpenTaskSteps?: () => readonly OpenTaskStepRef[];\n}\n\n/**\n * Validate an evidence ref's `uri` against session records (\"tool\") or the filesystem (\"file\").\n * Returns `undefined` for kinds/refs that carry nothing checkable (e.g. \"user\"/\"finding\"/\"test\",\n * or a missing `uri`) -- absence of a ref is not the same as a ref that failed to verify.\n */\nasync function resolveEvidenceVerified(\n\tkind: GoalEvidenceKind,\n\turi: string | undefined,\n\tdeps: GoalToolDependencies,\n): Promise<boolean | undefined> {\n\tconst trimmedUri = uri?.trim();\n\tif (!trimmedUri) return undefined;\n\tif (kind === \"tool\") {\n\t\treturn deps.hasToolCallId ? deps.hasToolCallId(trimmedUri) : false;\n\t}\n\tif (kind === \"file\") {\n\t\tconst cwd = deps.cwd?.() ?? process.cwd();\n\t\ttry {\n\t\t\tconst stats = await fsStat(resolveToCwd(trimmedUri, cwd));\n\t\t\treturn stats.isFile();\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (kind === \"worker\") {\n\t\tif (!deps.getLaneRecords || !deps.getWorkerClaimSnapshots) return false;\n\t\tconst laneId = trimmedUri;\n\t\tconst record = deps.getLaneRecords().find((candidate) => candidate.laneId === laneId);\n\t\tif (!record) return false;\n\t\tconst claim = deps.getWorkerClaimSnapshots().find((candidate) => candidate.requestId === laneId);\n\t\tif (!claim) return false;\n\t\t// An unreviewed mutation (parentReviewRequired && no parentReviewedAt) can never verify true --\n\t\t// this is what stops an unreviewed worker completion from ungating goal completion through\n\t\t// the existing verified/complete gate (goal-tool-core's isVerifiedOrUserEvidence/complete).\n\t\tif (claim.parentReviewRequired === true && claim.parentReviewedAt === undefined) return false;\n\t\treturn claim.status === \"completed\";\n\t}\n\treturn undefined;\n}\n\nfunction toGoalAction(input: GoalToolInput): GoalAction | { error: string } {\n\tswitch (input.action) {\n\t\tcase \"start\":\n\t\t\treturn { action: \"start\", goalId: input.goalId ?? \"\", userGoal: input.userGoal ?? \"\" };\n\t\tcase \"add_requirement\":\n\t\t\treturn { action: \"add_requirement\", requirementId: input.requirementId ?? \"\", text: input.text ?? \"\" };\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"satisfy_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tevidenceIds: input.evidenceIds,\n\t\t\t};\n\t\tcase \"block_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"block_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\treason: input.reason ?? \"\",\n\t\t\t};\n\t\tcase \"reopen_requirement\":\n\t\t\treturn { action: \"reopen_requirement\", requirementId: input.requirementId ?? \"\" };\n\t\tcase \"dispatch_worker\":\n\t\t\treturn {\n\t\t\t\taction: \"dispatch_worker\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tinstructions: input.instructions ?? \"\",\n\t\t\t};\n\t\tcase \"add_evidence\": {\n\t\t\tif (input.kind === undefined) {\n\t\t\t\treturn { error: \"add_evidence requires a kind.\" };\n\t\t\t}\n\t\t\tconst kind: GoalEvidenceKind = input.kind;\n\t\t\treturn {\n\t\t\t\taction: \"add_evidence\",\n\t\t\t\tevidenceId: input.evidenceId ?? \"\",\n\t\t\t\tkind,\n\t\t\t\tsummary: input.summary ?? \"\",\n\t\t\t\turi: input.uri,\n\t\t\t};\n\t\t}\n\t\tcase \"progress\":\n\t\t\treturn { action: \"progress\" };\n\t\tcase \"no_progress\":\n\t\t\treturn { action: \"no_progress\" };\n\t\tcase \"complete\":\n\t\t\treturn { action: \"complete\" };\n\t\tcase \"block_goal\":\n\t\t\treturn { action: \"block_goal\", reason: input.reason ?? \"\" };\n\t\tcase \"resume_goal\":\n\t\t\treturn { action: \"resume_goal\" };\n\t\tcase \"cancel\":\n\t\t\treturn { action: \"cancel\" };\n\t\tdefault:\n\t\t\treturn { error: \"Unknown goal action.\" };\n\t}\n}\n\nexport function createGoalToolDefinition(deps: GoalToolDependencies): ToolDefinition {\n\tconst now = deps.now ?? (() => new Date().toISOString());\n\treturn {\n\t\tname: \"goal\",\n\t\tlabel: \"goal\",\n\t\tdescription:\n\t\t\t\"Record and update the durable goal ledger for the current task. Maintains a structured goal with requirements, evidence, and progress so long tasks can be resumed and continued. Start a goal, add requirements, attach evidence, mark requirements satisfied or blocked, reopen resolved blockers, resume blocked goals, and mark progress. This is the producer that drives /goal-continue; without recorded goal state, continuation has nothing to act on.\",\n\t\tpromptSnippet: \"Record goal, requirements, evidence, and progress in the durable goal ledger.\",\n\t\tpromptGuidelines: [\n\t\t\t\"At the start of a multi-step task, call goal with action 'start' to record the user goal, then add the concrete requirements with 'add_requirement'.\",\n\t\t\t\"As you make progress, record evidence with 'add_evidence' and mark requirements satisfied with 'satisfy_requirement', citing the evidence ids.\",\n\t\t\t\"For 'add_evidence', kind 'tool' expects a real toolCallId in 'uri' and kind 'file' expects a real path; both are checked and recorded as verified or not. Kind 'worker' expects a laneId in 'uri' and verifies true only for a reviewed, completed worker result. Kinds 'user'/'finding'/'test' carry no checkable ref.\",\n\t\t\t\"Use 'dispatch_worker' to bind a requirement to a worker lane while it is being worked; this records the binding only -- it never satisfies the requirement. Record 'worker'-kind evidence citing that laneId once the worker completes, then call 'satisfy_requirement'.\",\n\t\t\t\"Use 'progress' when you advance without satisfying a specific requirement, and 'no_progress' when a turn yields nothing, so stall detection works.\",\n\t\t\t\"When the user resolves a blocker, use 'resume_goal' and 'reopen_requirement' as needed; do not strand the old ledger or start a duplicate goal.\",\n\t\t\t\"Mark the goal 'complete' only when every requirement is satisfied and each requirement cites verified or user-confirmed evidence. Use 'block_goal' or 'block_requirement' with a reason when you are stuck and need the user. A blocked goal can still be resumed or cancelled.\",\n\t\t],\n\t\tparameters: goalSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tinput: GoalToolInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: GoalToolDetails;\n\t\t}> {\n\t\t\tconst mapped = toGoalAction(input);\n\t\t\tif (\"error\" in mapped) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${mapped.error}` }],\n\t\t\t\t\tdetails: { action: input.action, applied: false, error: mapped.error },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet action: GoalAction = mapped;\n\t\t\tif (action.action === \"add_evidence\") {\n\t\t\t\tconst verified = await resolveEvidenceVerified(action.kind, action.uri, deps);\n\t\t\t\taction = { ...action, verified };\n\t\t\t}\n\t\t\t// Honest dispatch reporting: distinguish \"dispatched\" (laneId), \"declined\" (skipReason --\n\t\t\t// the dependency IS wired but the underlying delegation starter refused, e.g. disabled or\n\t\t\t// already at capacity), and \"unwired\" (no dependency at all) -- never collapse a real\n\t\t\t// decline into a silent no-laneId no-op indistinguishable from the dep being absent.\n\t\t\tlet dispatchNote: string | undefined;\n\t\t\tlet dispatchSkipReason: string | undefined;\n\t\t\t// Indeterminate-binding dedupe guard: checked BEFORE any dispatch side effect, for BOTH\n\t\t\t// routes. A requirement already bound to a lane that is either still live (a plain\n\t\t\t// duplicate) or whose liveness/outcome cannot be determined at all (for example, a legacy\n\t\t\t// snapshot with no lane record or worker result) must never be\n\t\t\t// re-dispatched silently; only a CONFIRMED terminal outcome allows a legitimate retry.\n\t\t\tlet dispatchGuardRefused = false;\n\t\t\tif (action.action === \"dispatch_worker\") {\n\t\t\t\t// Captured into a `const` so the \"dispatch_worker\" narrowing survives into the closures\n\t\t\t\t// below -- TS does not narrow a `let`-bound outer variable across a callback boundary.\n\t\t\t\tconst dispatchAction = action;\n\t\t\t\tconst boundRequirement = deps\n\t\t\t\t\t.getGoalState()\n\t\t\t\t\t?.requirements.find((r) => r.id === dispatchAction.requirementId);\n\t\t\t\tconst bound = boundRequirement?.boundLaneId;\n\t\t\t\tif (bound !== undefined) {\n\t\t\t\t\tconst boundLaneRecord = deps.getLaneRecords?.().find((record) => record.laneId === bound);\n\t\t\t\t\tconst isLiveInFlight =\n\t\t\t\t\t\tboundLaneRecord !== undefined &&\n\t\t\t\t\t\t(boundLaneRecord.status === \"queued\" || boundLaneRecord.status === \"running\");\n\t\t\t\t\tif (isLiveInFlight) {\n\t\t\t\t\t\tdispatchSkipReason = \"requirement_already_bound\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// `boundLaneRecord` present here is necessarily terminal (isLiveInFlight was false).\n\t\t\t\t\t\tconst hasTerminalOutcome =\n\t\t\t\t\t\t\tboundLaneRecord !== undefined ||\n\t\t\t\t\t\t\t(deps.getWorkerClaimSnapshots?.().some((claim) => claim.requestId === bound) ?? false);\n\t\t\t\t\t\tif (!hasTerminalOutcome) dispatchSkipReason = \"bound_lane_indeterminate\";\n\t\t\t\t\t}\n\t\t\t\t\tif (dispatchSkipReason) {\n\t\t\t\t\t\tdispatchGuardRefused = true;\n\t\t\t\t\t\tdispatchNote = `No worker was dispatched (${dispatchSkipReason}); requirement '${dispatchAction.requirementId}' remains bound to lane '${bound}'.`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (action.action === \"dispatch_worker\" && !dispatchGuardRefused) {\n\t\t\t\tconst useTmux = input.dispatchTarget === \"tmux\" && deps.dispatchTmuxWorker !== undefined;\n\t\t\t\tconst dispatched = useTmux\n\t\t\t\t\t? await deps.dispatchTmuxWorker?.({\n\t\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t\t})\n\t\t\t\t\t: deps.startWorkerDelegation?.({\n\t\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t\t});\n\t\t\t\taction = { ...action, laneId: dispatched?.laneId };\n\t\t\t\tif (dispatched?.laneId) {\n\t\t\t\t\tdispatchNote = useTmux\n\t\t\t\t\t\t? `Dispatched tmux worker lane '${dispatched.laneId}' for requirement '${action.requirementId}'.`\n\t\t\t\t\t\t: `Dispatched in-process worker lane '${dispatched.laneId}' for requirement '${action.requirementId}' (tmux dispatch is not available from this tool yet).`;\n\t\t\t\t} else {\n\t\t\t\t\tconst wired = useTmux ? deps.dispatchTmuxWorker : deps.startWorkerDelegation;\n\t\t\t\t\tdispatchSkipReason = dispatched?.skipReason ?? (wired ? \"declined\" : \"dependency_unwired\");\n\t\t\t\t\tdispatchNote = `No worker was dispatched (${dispatchSkipReason}); requirement '${action.requirementId}' is recorded but not bound to a lane.`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst current = deps.getGoalState();\n\t\t\tlet nextState: GoalState;\n\t\t\tif (action.action === \"dispatch_worker\" && dispatchGuardRefused) {\n\t\t\t\t// Short-circuit: the guard refused before any dispatch attempt -- never call\n\t\t\t\t// applyGoalAction for this turn, so the requirement's existing `boundLaneId` is\n\t\t\t\t// preserved exactly as-is rather than clobbered to `undefined` by the reducer's\n\t\t\t\t// unconditional `boundLaneId: event.laneId` write (goal-state.ts's dispatch_worker case).\n\t\t\t\t// `current` is guaranteed defined here: the guard only refuses when a requirement with\n\t\t\t\t// a `boundLaneId` was found on it.\n\t\t\t\tnextState = current as GoalState;\n\t\t\t} else {\n\t\t\t\tconst result = applyGoalAction(current, action, now(), {\n\t\t\t\t\trequireVerifiedEvidenceForCompletion: deps.requireVerifiedEvidenceForCompletion?.() ?? true,\n\t\t\t\t});\n\t\t\t\tif (!result.ok) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${result.error}` }],\n\t\t\t\t\t\tdetails: { action: input.action, applied: false, error: result.error, state: current },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tdeps.saveGoalState(result.state);\n\t\t\t\tnextState = result.state;\n\t\t\t}\n\n\t\t\tconst summary = summarizeGoalState(nextState, { action, openTaskSteps: deps.getOpenTaskSteps?.() });\n\t\t\tconst text = dispatchNote\n\t\t\t\t? `goal ${input.action} recorded.\\n${summary}\\n${dispatchNote}`\n\t\t\t\t: `goal ${input.action} recorded.\\n${summary}`;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text }],\n\t\t\t\tdetails: {\n\t\t\t\t\taction: input.action,\n\t\t\t\t\tapplied: true,\n\t\t\t\t\tstate: nextState,\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && action.laneId ? { dispatchedLaneId: action.laneId } : {}),\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && !action.laneId ? { dispatchSkipReason } : {}),\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -69,21 +69,21 @@ async function resolveEvidenceVerified(kind, uri, deps) {
69
69
  }
70
70
  }
71
71
  if (kind === "worker") {
72
- if (!deps.getLaneRecords || !deps.getWorkerResultSnapshots)
72
+ if (!deps.getLaneRecords || !deps.getWorkerClaimSnapshots)
73
73
  return false;
74
74
  const laneId = trimmedUri;
75
75
  const record = deps.getLaneRecords().find((candidate) => candidate.laneId === laneId);
76
76
  if (!record)
77
77
  return false;
78
- const result = deps.getWorkerResultSnapshots().find((candidate) => candidate.requestId === laneId);
79
- if (!result)
78
+ const claim = deps.getWorkerClaimSnapshots().find((candidate) => candidate.requestId === laneId);
79
+ if (!claim)
80
80
  return false;
81
81
  // An unreviewed mutation (parentReviewRequired && no parentReviewedAt) can never verify true --
82
82
  // this is what stops an unreviewed worker completion from ungating goal completion through
83
83
  // the existing verified/complete gate (goal-tool-core's isVerifiedOrUserEvidence/complete).
84
- if (result.parentReviewRequired === true && result.parentReviewedAt === undefined)
84
+ if (claim.parentReviewRequired === true && claim.parentReviewedAt === undefined)
85
85
  return false;
86
- return result.status === "completed";
86
+ return claim.status === "completed";
87
87
  }
88
88
  return undefined;
89
89
  }
@@ -156,7 +156,7 @@ export function createGoalToolDefinition(deps) {
156
156
  "Use 'dispatch_worker' to bind a requirement to a worker lane while it is being worked; this records the binding only -- it never satisfies the requirement. Record 'worker'-kind evidence citing that laneId once the worker completes, then call 'satisfy_requirement'.",
157
157
  "Use 'progress' when you advance without satisfying a specific requirement, and 'no_progress' when a turn yields nothing, so stall detection works.",
158
158
  "When the user resolves a blocker, use 'resume_goal' and 'reopen_requirement' as needed; do not strand the old ledger or start a duplicate goal.",
159
- "Mark the goal 'complete' only when every requirement is satisfied; completion normally also requires at least one satisfied requirement backed by verified 'tool'/'file' evidence or kind 'user' evidence. Use 'block_goal' or 'block_requirement' with a reason when you are stuck and need the user. A blocked goal can still be resumed or cancelled.",
159
+ "Mark the goal 'complete' only when every requirement is satisfied and each requirement cites verified or user-confirmed evidence. Use 'block_goal' or 'block_requirement' with a reason when you are stuck and need the user. A blocked goal can still be resumed or cancelled.",
160
160
  ],
161
161
  parameters: goalSchema,
162
162
  async execute(_toolCallId, input) {
@@ -178,10 +178,10 @@ export function createGoalToolDefinition(deps) {
178
178
  // decline into a silent no-laneId no-op indistinguishable from the dep being absent.
179
179
  let dispatchNote;
180
180
  let dispatchSkipReason;
181
- // Reload-vanish dedupe guard: checked BEFORE any dispatch side effect, for BOTH
181
+ // Indeterminate-binding dedupe guard: checked BEFORE any dispatch side effect, for BOTH
182
182
  // routes. A requirement already bound to a lane that is either still live (a plain
183
- // duplicate) or whose liveness/outcome cannot be determined at all (the reload-vanish
184
- // case -- the lane record and any worker-result snapshot are both gone) must never be
183
+ // duplicate) or whose liveness/outcome cannot be determined at all (for example, a legacy
184
+ // snapshot with no lane record or worker result) must never be
185
185
  // re-dispatched silently; only a CONFIRMED terminal outcome allows a legitimate retry.
186
186
  let dispatchGuardRefused = false;
187
187
  if (action.action === "dispatch_worker") {
@@ -202,7 +202,7 @@ export function createGoalToolDefinition(deps) {
202
202
  else {
203
203
  // `boundLaneRecord` present here is necessarily terminal (isLiveInFlight was false).
204
204
  const hasTerminalOutcome = boundLaneRecord !== undefined ||
205
- (deps.getWorkerResultSnapshots?.().some((result) => result.requestId === bound) ?? false);
205
+ (deps.getWorkerClaimSnapshots?.().some((claim) => claim.requestId === bound) ?? false);
206
206
  if (!hasTerminalOutcome)
207
207
  dispatchSkipReason = "bound_lane_indeterminate";
208
208
  }
@@ -1 +1 @@
1
- {"version":3,"file":"goal.js","sourceRoot":"","sources":["../../../src/core/tools/goal.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat as fsStat } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport type { WorkerResult } from \"../autonomy/contracts.ts\";\nimport type { LaneRecord } from \"../autonomy/lane-tracker.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { GoalEvidenceKind, GoalState } from \"../goals/goal-state.ts\";\nimport {\n\tapplyGoalAction,\n\ttype GoalAction,\n\ttype GoalActionName,\n\ttype OpenTaskStepRef,\n\tsummarizeGoalState,\n} from \"../goals/goal-tool-core.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\n\nconst goalSchema = Type.Object(\n\t{\n\t\taction: Type.Union(\n\t\t\t[\n\t\t\t\tType.Literal(\"start\"),\n\t\t\t\tType.Literal(\"add_requirement\"),\n\t\t\t\tType.Literal(\"satisfy_requirement\"),\n\t\t\t\tType.Literal(\"block_requirement\"),\n\t\t\t\tType.Literal(\"reopen_requirement\"),\n\t\t\t\tType.Literal(\"dispatch_worker\"),\n\t\t\t\tType.Literal(\"add_evidence\"),\n\t\t\t\tType.Literal(\"progress\"),\n\t\t\t\tType.Literal(\"no_progress\"),\n\t\t\t\tType.Literal(\"complete\"),\n\t\t\t\tType.Literal(\"block_goal\"),\n\t\t\t\tType.Literal(\"resume_goal\"),\n\t\t\t\tType.Literal(\"cancel\"),\n\t\t\t],\n\t\t\t{ description: \"Ledger action to record.\" },\n\t\t),\n\t\tgoalId: Type.Optional(Type.String({ description: \"Stable goal id. Required for action 'start'.\" })),\n\t\tuserGoal: Type.Optional(Type.String({ description: \"The goal statement. Required for action 'start'.\" })),\n\t\trequirementId: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Requirement id for add_requirement/satisfy_requirement/block_requirement/reopen_requirement/dispatch_worker.\",\n\t\t\t}),\n\t\t),\n\t\ttext: Type.Optional(Type.String({ description: \"Requirement text. Required for add_requirement.\" })),\n\t\tinstructions: Type.Optional(Type.String({ description: \"Worker instructions. Required for dispatch_worker.\" })),\n\t\tevidenceId: Type.Optional(Type.String({ description: \"Evidence id. Required for add_evidence.\" })),\n\t\tevidenceIds: Type.Optional(\n\t\t\tType.Array(Type.String(), {\n\t\t\t\tdescription: \"Evidence ids supporting a satisfy_requirement action. Each must already be recorded.\",\n\t\t\t}),\n\t\t),\n\t\tkind: Type.Optional(\n\t\t\tType.Union(\n\t\t\t\t[\n\t\t\t\t\tType.Literal(\"file\"),\n\t\t\t\t\tType.Literal(\"test\"),\n\t\t\t\t\tType.Literal(\"tool\"),\n\t\t\t\t\tType.Literal(\"user\"),\n\t\t\t\t\tType.Literal(\"finding\"),\n\t\t\t\t\tType.Literal(\"worker\"),\n\t\t\t\t],\n\t\t\t\t{ description: \"Evidence kind. Required for add_evidence.\" },\n\t\t\t),\n\t\t),\n\t\tsummary: Type.Optional(Type.String({ description: \"Evidence summary. Required for add_evidence.\" })),\n\t\turi: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Optional evidence locator (path/URL for kind 'file', a toolCallId for kind 'tool', a laneId for kind 'worker').\",\n\t\t\t}),\n\t\t),\n\t\treason: Type.Optional(Type.String({ description: \"Reason for block_requirement or block_goal.\" })),\n\t\tdispatchTarget: Type.Optional(\n\t\t\tType.Union([Type.Literal(\"in_process\"), Type.Literal(\"tmux\")], {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Worker runtime for dispatch_worker. Defaults to 'in_process'. 'tmux' dispatches a persistent tmux worker via the tmux_agent_manager extension -- only takes effect when that dependency is wired AND an owner-granted standing dispatch grant covers it; otherwise the dispatch is honestly skipped with a dispatchSkipReason (never a silent fallback or a fake launch).\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type GoalToolInput = Static<typeof goalSchema>;\n\nexport interface GoalToolDetails {\n\taction: GoalActionName;\n\tapplied: boolean;\n\terror?: string;\n\tstate?: GoalState;\n\t/** Set on 'dispatch_worker' when a worker lane actually started; mirrors the requirement's\n\t * new `boundLaneId`. The in-process route by default, or a real persistent tmux lane when\n\t * `dispatchTarget:\"tmux\"` was selected and routed -- see {@link GoalToolDependencies.dispatchTmuxWorker}. */\n\tdispatchedLaneId?: string;\n\t/** Set on 'dispatch_worker' when no worker was dispatched: a wired dependency declined (e.g. worker\n\t * delegation disabled, already at capacity, or an honest tmux skip reason -- see\n\t * {@link GoalToolDependencies.dispatchTmuxWorker}), or the reload-vanish dedupe guard refused a\n\t * re-dispatch against an already-bound requirement (`requirement_already_bound`/`bound_lane_indeterminate`).\n\t * The binding is recorded (or, for a guard refusal, left exactly as it was) with no NEW laneId. */\n\tdispatchSkipReason?: string;\n}\n\nexport interface GoalToolDependencies {\n\t/** Read the latest persisted goal state for the active session. */\n\tgetGoalState: () => GoalState | undefined;\n\t/** Persist a new goal state snapshot to the active session. */\n\tsaveGoalState: (state: GoalState) => void;\n\t/** Clock injection for deterministic tests. */\n\tnow?: () => string;\n\t/**\n\t * Check whether `toolCallId` exists in this session's records, for validating kind:\"tool\"\n\t * evidence refs at add_evidence time. When not wired, a \"tool\" ref cannot be proven and is\n\t * recorded as `verified: false` rather than assumed true.\n\t */\n\thasToolCallId?: (toolCallId: string) => boolean;\n\t/**\n\t * Read the session's live worker lane records, for validating kind:\"worker\" evidence refs\n\t * (the `uri` is a laneId) at add_evidence time. Read-defensive: when not wired -- exactly like\n\t * `hasToolCallId` -- a \"worker\" ref cannot be proven and is recorded as `verified: false` rather\n\t * than assumed true. Live wiring is added separately.\n\t */\n\tgetLaneRecords?: () => readonly LaneRecord[];\n\t/**\n\t * Read persisted worker result snapshots (keyed by `WorkerResult.requestId`, which is the same\n\t * id as the dispatching lane's laneId), for validating kind:\"worker\" evidence refs. See\n\t * {@link getLaneRecords}. A matching result that is `parentReviewRequired && !parentReviewedAt`\n\t * verifies `false` -- an unreviewed worker completion must never ungate goal completion through\n\t * the existing verified/complete gate.\n\t */\n\tgetWorkerResultSnapshots?: () => readonly WorkerResult[];\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `dispatchTarget` is 'in_process'\n\t * (the default) or when {@link dispatchTmuxWorker} is not wired: dispatches a real in-process\n\t * worker lane for the given requirement and returns the resulting laneId to bind onto it. When\n\t * the dependency is present but the underlying delegation starter declines (disabled, already at\n\t * capacity, etc.), return `{ skipReason }` instead of a laneId -- a real, non-silent skip that\n\t * the tool response surfaces, distinct from this dependency being altogether unwired (`undefined`\n\t * dep, or the dep returning `undefined`), which records the binding attempt structurally with no\n\t * laneId (a no-op).\n\t */\n\tstartWorkerDelegation?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => { laneId?: string; skipReason?: string } | undefined;\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `input.dispatchTarget === \"tmux\"`:\n\t * dispatches a REAL persistent tmux worker via the tmux_agent_manager extension's `fire_task`\n\t * action (core structurally invokes the same tool call the model would make; no extension change,\n\t * no faked launch or laneId -- see `tmux-dispatch.ts`'s `dispatchTmuxWorker`). Selected ONLY when\n\t * BOTH `input.dispatchTarget === \"tmux\"` AND this dependency is present; otherwise the EXISTING\n\t * {@link startWorkerDelegation} in-process path runs, byte-identical to before this field existed.\n\t * The honest skip-reason vocabulary this can return: `tmux_extension_not_loaded`,\n\t * `no_standing_grant` (the owner has not authorized unattended tmux dispatch),\n\t * `tmux_dispatch_failed`, `tmux_dispatch_incomplete`, `lane_correlation_failed`,\n\t * `worktree_create_failed` (worktree-sync is enabled but the lane-first `create_lane` call was\n\t * refused -- e.g. max lanes reached -- so no fire_task call was ever attempted),\n\t * `worker_capability_insufficient` (the model is sub-full class, has an unknown context window,\n\t * does not advertise a native tool-call path, or is graded-demoted to text-protocol/none -- see\n\t * `model-capability.ts`'s `evaluateLaneWorkerRefusal`; this is the parent's best-effort check\n\t * only, refused before any lane/pane side effect -- the dispatched child still refuses\n\t * authoritatively at its own startup regardless).\n\t */\n\tdispatchTmuxWorker?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => Promise<{ laneId?: string; skipReason?: string }>;\n\t/** Working directory for resolving kind:\"file\" evidence ref paths. Defaults to `process.cwd()`. */\n\tcwd?: () => string;\n\t/**\n\t * Gate agent-facing 'complete' on verified/user evidence backing. Defaults to `true` (on)\n\t * when omitted -- the conservative default; set to a function returning `false` to opt out.\n\t */\n\trequireVerifiedEvidenceForCompletion?: () => boolean;\n\t/**\n\t * Read-only open (non-terminal) task_steps steps on the active branch, for the goal⇄task\n\t * cross-visibility nudge in the tool response. When omitted, `summarizeGoalState` gets\n\t * no task-step context and simply emits no nudge -- goal-tool-core stays pure and never reads\n\t * task state itself; this is the only place that supplies it.\n\t */\n\tgetOpenTaskSteps?: () => readonly OpenTaskStepRef[];\n}\n\n/**\n * Validate an evidence ref's `uri` against session records (\"tool\") or the filesystem (\"file\").\n * Returns `undefined` for kinds/refs that carry nothing checkable (e.g. \"user\"/\"finding\"/\"test\",\n * or a missing `uri`) -- absence of a ref is not the same as a ref that failed to verify.\n */\nasync function resolveEvidenceVerified(\n\tkind: GoalEvidenceKind,\n\turi: string | undefined,\n\tdeps: GoalToolDependencies,\n): Promise<boolean | undefined> {\n\tconst trimmedUri = uri?.trim();\n\tif (!trimmedUri) return undefined;\n\tif (kind === \"tool\") {\n\t\treturn deps.hasToolCallId ? deps.hasToolCallId(trimmedUri) : false;\n\t}\n\tif (kind === \"file\") {\n\t\tconst cwd = deps.cwd?.() ?? process.cwd();\n\t\ttry {\n\t\t\tconst stats = await fsStat(resolveToCwd(trimmedUri, cwd));\n\t\t\treturn stats.isFile();\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (kind === \"worker\") {\n\t\tif (!deps.getLaneRecords || !deps.getWorkerResultSnapshots) return false;\n\t\tconst laneId = trimmedUri;\n\t\tconst record = deps.getLaneRecords().find((candidate) => candidate.laneId === laneId);\n\t\tif (!record) return false;\n\t\tconst result = deps.getWorkerResultSnapshots().find((candidate) => candidate.requestId === laneId);\n\t\tif (!result) return false;\n\t\t// An unreviewed mutation (parentReviewRequired && no parentReviewedAt) can never verify true --\n\t\t// this is what stops an unreviewed worker completion from ungating goal completion through\n\t\t// the existing verified/complete gate (goal-tool-core's isVerifiedOrUserEvidence/complete).\n\t\tif (result.parentReviewRequired === true && result.parentReviewedAt === undefined) return false;\n\t\treturn result.status === \"completed\";\n\t}\n\treturn undefined;\n}\n\nfunction toGoalAction(input: GoalToolInput): GoalAction | { error: string } {\n\tswitch (input.action) {\n\t\tcase \"start\":\n\t\t\treturn { action: \"start\", goalId: input.goalId ?? \"\", userGoal: input.userGoal ?? \"\" };\n\t\tcase \"add_requirement\":\n\t\t\treturn { action: \"add_requirement\", requirementId: input.requirementId ?? \"\", text: input.text ?? \"\" };\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"satisfy_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tevidenceIds: input.evidenceIds,\n\t\t\t};\n\t\tcase \"block_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"block_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\treason: input.reason ?? \"\",\n\t\t\t};\n\t\tcase \"reopen_requirement\":\n\t\t\treturn { action: \"reopen_requirement\", requirementId: input.requirementId ?? \"\" };\n\t\tcase \"dispatch_worker\":\n\t\t\treturn {\n\t\t\t\taction: \"dispatch_worker\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tinstructions: input.instructions ?? \"\",\n\t\t\t};\n\t\tcase \"add_evidence\": {\n\t\t\tif (input.kind === undefined) {\n\t\t\t\treturn { error: \"add_evidence requires a kind.\" };\n\t\t\t}\n\t\t\tconst kind: GoalEvidenceKind = input.kind;\n\t\t\treturn {\n\t\t\t\taction: \"add_evidence\",\n\t\t\t\tevidenceId: input.evidenceId ?? \"\",\n\t\t\t\tkind,\n\t\t\t\tsummary: input.summary ?? \"\",\n\t\t\t\turi: input.uri,\n\t\t\t};\n\t\t}\n\t\tcase \"progress\":\n\t\t\treturn { action: \"progress\" };\n\t\tcase \"no_progress\":\n\t\t\treturn { action: \"no_progress\" };\n\t\tcase \"complete\":\n\t\t\treturn { action: \"complete\" };\n\t\tcase \"block_goal\":\n\t\t\treturn { action: \"block_goal\", reason: input.reason ?? \"\" };\n\t\tcase \"resume_goal\":\n\t\t\treturn { action: \"resume_goal\" };\n\t\tcase \"cancel\":\n\t\t\treturn { action: \"cancel\" };\n\t\tdefault:\n\t\t\treturn { error: \"Unknown goal action.\" };\n\t}\n}\n\nexport function createGoalToolDefinition(deps: GoalToolDependencies): ToolDefinition {\n\tconst now = deps.now ?? (() => new Date().toISOString());\n\treturn {\n\t\tname: \"goal\",\n\t\tlabel: \"goal\",\n\t\tdescription:\n\t\t\t\"Record and update the durable goal ledger for the current task. Maintains a structured goal with requirements, evidence, and progress so long tasks can be resumed and continued. Start a goal, add requirements, attach evidence, mark requirements satisfied or blocked, reopen resolved blockers, resume blocked goals, and mark progress. This is the producer that drives /goal-continue; without recorded goal state, continuation has nothing to act on.\",\n\t\tpromptSnippet: \"Record goal, requirements, evidence, and progress in the durable goal ledger.\",\n\t\tpromptGuidelines: [\n\t\t\t\"At the start of a multi-step task, call goal with action 'start' to record the user goal, then add the concrete requirements with 'add_requirement'.\",\n\t\t\t\"As you make progress, record evidence with 'add_evidence' and mark requirements satisfied with 'satisfy_requirement', citing the evidence ids.\",\n\t\t\t\"For 'add_evidence', kind 'tool' expects a real toolCallId in 'uri' and kind 'file' expects a real path; both are checked and recorded as verified or not. Kind 'worker' expects a laneId in 'uri' and verifies true only for a reviewed, completed worker result. Kinds 'user'/'finding'/'test' carry no checkable ref.\",\n\t\t\t\"Use 'dispatch_worker' to bind a requirement to a worker lane while it is being worked; this records the binding only -- it never satisfies the requirement. Record 'worker'-kind evidence citing that laneId once the worker completes, then call 'satisfy_requirement'.\",\n\t\t\t\"Use 'progress' when you advance without satisfying a specific requirement, and 'no_progress' when a turn yields nothing, so stall detection works.\",\n\t\t\t\"When the user resolves a blocker, use 'resume_goal' and 'reopen_requirement' as needed; do not strand the old ledger or start a duplicate goal.\",\n\t\t\t\"Mark the goal 'complete' only when every requirement is satisfied; completion normally also requires at least one satisfied requirement backed by verified 'tool'/'file' evidence or kind 'user' evidence. Use 'block_goal' or 'block_requirement' with a reason when you are stuck and need the user. A blocked goal can still be resumed or cancelled.\",\n\t\t],\n\t\tparameters: goalSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tinput: GoalToolInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: GoalToolDetails;\n\t\t}> {\n\t\t\tconst mapped = toGoalAction(input);\n\t\t\tif (\"error\" in mapped) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${mapped.error}` }],\n\t\t\t\t\tdetails: { action: input.action, applied: false, error: mapped.error },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet action: GoalAction = mapped;\n\t\t\tif (action.action === \"add_evidence\") {\n\t\t\t\tconst verified = await resolveEvidenceVerified(action.kind, action.uri, deps);\n\t\t\t\taction = { ...action, verified };\n\t\t\t}\n\t\t\t// Honest dispatch reporting: distinguish \"dispatched\" (laneId), \"declined\" (skipReason --\n\t\t\t// the dependency IS wired but the underlying delegation starter refused, e.g. disabled or\n\t\t\t// already at capacity), and \"unwired\" (no dependency at all) -- never collapse a real\n\t\t\t// decline into a silent no-laneId no-op indistinguishable from the dep being absent.\n\t\t\tlet dispatchNote: string | undefined;\n\t\t\tlet dispatchSkipReason: string | undefined;\n\t\t\t// Reload-vanish dedupe guard: checked BEFORE any dispatch side effect, for BOTH\n\t\t\t// routes. A requirement already bound to a lane that is either still live (a plain\n\t\t\t// duplicate) or whose liveness/outcome cannot be determined at all (the reload-vanish\n\t\t\t// case -- the lane record and any worker-result snapshot are both gone) must never be\n\t\t\t// re-dispatched silently; only a CONFIRMED terminal outcome allows a legitimate retry.\n\t\t\tlet dispatchGuardRefused = false;\n\t\t\tif (action.action === \"dispatch_worker\") {\n\t\t\t\t// Captured into a `const` so the \"dispatch_worker\" narrowing survives into the closures\n\t\t\t\t// below -- TS does not narrow a `let`-bound outer variable across a callback boundary.\n\t\t\t\tconst dispatchAction = action;\n\t\t\t\tconst boundRequirement = deps\n\t\t\t\t\t.getGoalState()\n\t\t\t\t\t?.requirements.find((r) => r.id === dispatchAction.requirementId);\n\t\t\t\tconst bound = boundRequirement?.boundLaneId;\n\t\t\t\tif (bound !== undefined) {\n\t\t\t\t\tconst boundLaneRecord = deps.getLaneRecords?.().find((record) => record.laneId === bound);\n\t\t\t\t\tconst isLiveInFlight =\n\t\t\t\t\t\tboundLaneRecord !== undefined &&\n\t\t\t\t\t\t(boundLaneRecord.status === \"queued\" || boundLaneRecord.status === \"running\");\n\t\t\t\t\tif (isLiveInFlight) {\n\t\t\t\t\t\tdispatchSkipReason = \"requirement_already_bound\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// `boundLaneRecord` present here is necessarily terminal (isLiveInFlight was false).\n\t\t\t\t\t\tconst hasTerminalOutcome =\n\t\t\t\t\t\t\tboundLaneRecord !== undefined ||\n\t\t\t\t\t\t\t(deps.getWorkerResultSnapshots?.().some((result) => result.requestId === bound) ?? false);\n\t\t\t\t\t\tif (!hasTerminalOutcome) dispatchSkipReason = \"bound_lane_indeterminate\";\n\t\t\t\t\t}\n\t\t\t\t\tif (dispatchSkipReason) {\n\t\t\t\t\t\tdispatchGuardRefused = true;\n\t\t\t\t\t\tdispatchNote = `No worker was dispatched (${dispatchSkipReason}); requirement '${dispatchAction.requirementId}' remains bound to lane '${bound}'.`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (action.action === \"dispatch_worker\" && !dispatchGuardRefused) {\n\t\t\t\tconst useTmux = input.dispatchTarget === \"tmux\" && deps.dispatchTmuxWorker !== undefined;\n\t\t\t\tconst dispatched = useTmux\n\t\t\t\t\t? await deps.dispatchTmuxWorker?.({\n\t\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t\t})\n\t\t\t\t\t: deps.startWorkerDelegation?.({\n\t\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t\t});\n\t\t\t\taction = { ...action, laneId: dispatched?.laneId };\n\t\t\t\tif (dispatched?.laneId) {\n\t\t\t\t\tdispatchNote = useTmux\n\t\t\t\t\t\t? `Dispatched tmux worker lane '${dispatched.laneId}' for requirement '${action.requirementId}'.`\n\t\t\t\t\t\t: `Dispatched in-process worker lane '${dispatched.laneId}' for requirement '${action.requirementId}' (tmux dispatch is not available from this tool yet).`;\n\t\t\t\t} else {\n\t\t\t\t\tconst wired = useTmux ? deps.dispatchTmuxWorker : deps.startWorkerDelegation;\n\t\t\t\t\tdispatchSkipReason = dispatched?.skipReason ?? (wired ? \"declined\" : \"dependency_unwired\");\n\t\t\t\t\tdispatchNote = `No worker was dispatched (${dispatchSkipReason}); requirement '${action.requirementId}' is recorded but not bound to a lane.`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst current = deps.getGoalState();\n\t\t\tlet nextState: GoalState;\n\t\t\tif (action.action === \"dispatch_worker\" && dispatchGuardRefused) {\n\t\t\t\t// Short-circuit: the guard refused before any dispatch attempt -- never call\n\t\t\t\t// applyGoalAction for this turn, so the requirement's existing `boundLaneId` is\n\t\t\t\t// preserved exactly as-is rather than clobbered to `undefined` by the reducer's\n\t\t\t\t// unconditional `boundLaneId: event.laneId` write (goal-state.ts's dispatch_worker case).\n\t\t\t\t// `current` is guaranteed defined here: the guard only refuses when a requirement with\n\t\t\t\t// a `boundLaneId` was found on it.\n\t\t\t\tnextState = current as GoalState;\n\t\t\t} else {\n\t\t\t\tconst result = applyGoalAction(current, action, now(), {\n\t\t\t\t\trequireVerifiedEvidenceForCompletion: deps.requireVerifiedEvidenceForCompletion?.() ?? true,\n\t\t\t\t});\n\t\t\t\tif (!result.ok) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${result.error}` }],\n\t\t\t\t\t\tdetails: { action: input.action, applied: false, error: result.error, state: current },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tdeps.saveGoalState(result.state);\n\t\t\t\tnextState = result.state;\n\t\t\t}\n\n\t\t\tconst summary = summarizeGoalState(nextState, { action, openTaskSteps: deps.getOpenTaskSteps?.() });\n\t\t\tconst text = dispatchNote\n\t\t\t\t? `goal ${input.action} recorded.\\n${summary}\\n${dispatchNote}`\n\t\t\t\t: `goal ${input.action} recorded.\\n${summary}`;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text }],\n\t\t\t\tdetails: {\n\t\t\t\t\taction: input.action,\n\t\t\t\t\tapplied: true,\n\t\t\t\t\tstate: nextState,\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && action.laneId ? { dispatchedLaneId: action.laneId } : {}),\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && !action.laneId ? { dispatchSkipReason } : {}),\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"goal.js","sourceRoot":"","sources":["../../../src/core/tools/goal.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat as fsStat } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport type { WorkerClaim } from \"../autonomy/contracts.ts\";\nimport type { LaneRecord } from \"../autonomy/lane-tracker.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { GoalEvidenceKind, GoalState } from \"../goals/goal-state.ts\";\nimport {\n\tapplyGoalAction,\n\ttype GoalAction,\n\ttype GoalActionName,\n\ttype OpenTaskStepRef,\n\tsummarizeGoalState,\n} from \"../goals/goal-tool-core.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\n\nconst goalSchema = Type.Object(\n\t{\n\t\taction: Type.Union(\n\t\t\t[\n\t\t\t\tType.Literal(\"start\"),\n\t\t\t\tType.Literal(\"add_requirement\"),\n\t\t\t\tType.Literal(\"satisfy_requirement\"),\n\t\t\t\tType.Literal(\"block_requirement\"),\n\t\t\t\tType.Literal(\"reopen_requirement\"),\n\t\t\t\tType.Literal(\"dispatch_worker\"),\n\t\t\t\tType.Literal(\"add_evidence\"),\n\t\t\t\tType.Literal(\"progress\"),\n\t\t\t\tType.Literal(\"no_progress\"),\n\t\t\t\tType.Literal(\"complete\"),\n\t\t\t\tType.Literal(\"block_goal\"),\n\t\t\t\tType.Literal(\"resume_goal\"),\n\t\t\t\tType.Literal(\"cancel\"),\n\t\t\t],\n\t\t\t{ description: \"Ledger action to record.\" },\n\t\t),\n\t\tgoalId: Type.Optional(Type.String({ description: \"Stable goal id. Required for action 'start'.\" })),\n\t\tuserGoal: Type.Optional(Type.String({ description: \"The goal statement. Required for action 'start'.\" })),\n\t\trequirementId: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Requirement id for add_requirement/satisfy_requirement/block_requirement/reopen_requirement/dispatch_worker.\",\n\t\t\t}),\n\t\t),\n\t\ttext: Type.Optional(Type.String({ description: \"Requirement text. Required for add_requirement.\" })),\n\t\tinstructions: Type.Optional(Type.String({ description: \"Worker instructions. Required for dispatch_worker.\" })),\n\t\tevidenceId: Type.Optional(Type.String({ description: \"Evidence id. Required for add_evidence.\" })),\n\t\tevidenceIds: Type.Optional(\n\t\t\tType.Array(Type.String(), {\n\t\t\t\tdescription: \"Evidence ids supporting a satisfy_requirement action. Each must already be recorded.\",\n\t\t\t}),\n\t\t),\n\t\tkind: Type.Optional(\n\t\t\tType.Union(\n\t\t\t\t[\n\t\t\t\t\tType.Literal(\"file\"),\n\t\t\t\t\tType.Literal(\"test\"),\n\t\t\t\t\tType.Literal(\"tool\"),\n\t\t\t\t\tType.Literal(\"user\"),\n\t\t\t\t\tType.Literal(\"finding\"),\n\t\t\t\t\tType.Literal(\"worker\"),\n\t\t\t\t],\n\t\t\t\t{ description: \"Evidence kind. Required for add_evidence.\" },\n\t\t\t),\n\t\t),\n\t\tsummary: Type.Optional(Type.String({ description: \"Evidence summary. Required for add_evidence.\" })),\n\t\turi: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Optional evidence locator (path/URL for kind 'file', a toolCallId for kind 'tool', a laneId for kind 'worker').\",\n\t\t\t}),\n\t\t),\n\t\treason: Type.Optional(Type.String({ description: \"Reason for block_requirement or block_goal.\" })),\n\t\tdispatchTarget: Type.Optional(\n\t\t\tType.Union([Type.Literal(\"in_process\"), Type.Literal(\"tmux\")], {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Worker runtime for dispatch_worker. Defaults to 'in_process'. 'tmux' dispatches a persistent tmux worker via the tmux_agent_manager extension -- only takes effect when that dependency is wired AND an owner-granted standing dispatch grant covers it; otherwise the dispatch is honestly skipped with a dispatchSkipReason (never a silent fallback or a fake launch).\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type GoalToolInput = Static<typeof goalSchema>;\n\nexport interface GoalToolDetails {\n\taction: GoalActionName;\n\tapplied: boolean;\n\terror?: string;\n\tstate?: GoalState;\n\t/** Set on 'dispatch_worker' when a worker lane actually started; mirrors the requirement's\n\t * new `boundLaneId`. The in-process route by default, or a real persistent tmux lane when\n\t * `dispatchTarget:\"tmux\"` was selected and routed -- see {@link GoalToolDependencies.dispatchTmuxWorker}. */\n\tdispatchedLaneId?: string;\n\t/** Set on 'dispatch_worker' when no worker was dispatched: a wired dependency declined (e.g. worker\n\t * delegation disabled, already at capacity, or an honest tmux skip reason -- see\n\t * {@link GoalToolDependencies.dispatchTmuxWorker}), or the indeterminate-binding guard refused a\n\t * re-dispatch against an already-bound requirement (`requirement_already_bound`/`bound_lane_indeterminate`).\n\t * The binding is recorded (or, for a guard refusal, left exactly as it was) with no NEW laneId. */\n\tdispatchSkipReason?: string;\n}\n\nexport interface GoalToolDependencies {\n\t/** Read the latest persisted goal state for the active session. */\n\tgetGoalState: () => GoalState | undefined;\n\t/** Persist a new goal state snapshot to the active session. */\n\tsaveGoalState: (state: GoalState) => void;\n\t/** Clock injection for deterministic tests. */\n\tnow?: () => string;\n\t/**\n\t * Check whether `toolCallId` exists in this session's records, for validating kind:\"tool\"\n\t * evidence refs at add_evidence time. When not wired, a \"tool\" ref cannot be proven and is\n\t * recorded as `verified: false` rather than assumed true.\n\t */\n\thasToolCallId?: (toolCallId: string) => boolean;\n\t/**\n\t * Read the session's live worker lane records, for validating kind:\"worker\" evidence refs\n\t * (the `uri` is a laneId) at add_evidence time. Read-defensive: when not wired -- exactly like\n\t * `hasToolCallId` -- a \"worker\" ref cannot be proven and is recorded as `verified: false` rather\n\t * than assumed true. Live wiring is added separately.\n\t */\n\tgetLaneRecords?: () => readonly LaneRecord[];\n\t/**\n\t * Read persisted worker claim snapshots (keyed by `WorkerClaim.requestId`, which is the same\n\t * id as the dispatching lane's laneId), for validating kind:\"worker\" evidence refs. See\n\t * {@link getLaneRecords}. A matching claim that is `parentReviewRequired && !parentReviewedAt`\n\t * verifies `false` -- an unreviewed worker completion must never ungate goal completion through\n\t * the existing verified/complete gate.\n\t */\n\tgetWorkerClaimSnapshots?: () => readonly WorkerClaim[];\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `dispatchTarget` is 'in_process'\n\t * (the default) or when {@link dispatchTmuxWorker} is not wired: dispatches a real in-process\n\t * worker lane for the given requirement and returns the resulting laneId to bind onto it. When\n\t * the dependency is present but the underlying delegation starter declines (disabled, already at\n\t * capacity, etc.), return `{ skipReason }` instead of a laneId -- a real, non-silent skip that\n\t * the tool response surfaces, distinct from this dependency being altogether unwired (`undefined`\n\t * dep, or the dep returning `undefined`), which records the binding attempt structurally with no\n\t * laneId (a no-op).\n\t */\n\tstartWorkerDelegation?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => { laneId?: string; skipReason?: string } | undefined;\n\t/**\n\t * Tool-layer side effect for a 'dispatch_worker' action when `input.dispatchTarget === \"tmux\"`:\n\t * dispatches a REAL persistent tmux worker via the tmux_agent_manager extension's `fire_task`\n\t * action (core structurally invokes the same tool call the model would make; no extension change,\n\t * no faked launch or laneId -- see `tmux-dispatch.ts`'s `dispatchTmuxWorker`). Selected ONLY when\n\t * BOTH `input.dispatchTarget === \"tmux\"` AND this dependency is present; otherwise the EXISTING\n\t * {@link startWorkerDelegation} in-process path runs, byte-identical to before this field existed.\n\t * The honest skip-reason vocabulary this can return: `tmux_extension_not_loaded`,\n\t * `no_standing_grant` (the owner has not authorized unattended tmux dispatch),\n\t * `tmux_dispatch_failed`, `tmux_dispatch_incomplete`, `lane_correlation_failed`,\n\t * `worktree_create_failed` (worktree-sync is enabled but the lane-first `create_lane` call was\n\t * refused -- e.g. max lanes reached -- so no fire_task call was ever attempted),\n\t * `worker_capability_insufficient` (the model is sub-full class, has an unknown context window,\n\t * does not advertise a native tool-call path, or is graded-demoted to text-protocol/none -- see\n\t * `model-capability.ts`'s `evaluateLaneWorkerRefusal`; this is the parent's best-effort check\n\t * only, refused before any lane/pane side effect -- the dispatched child still refuses\n\t * authoritatively at its own startup regardless).\n\t */\n\tdispatchTmuxWorker?: (args: {\n\t\trequirementId: string;\n\t\tinstructions: string;\n\t}) => Promise<{ laneId?: string; skipReason?: string }>;\n\t/** Working directory for resolving kind:\"file\" evidence ref paths. Defaults to `process.cwd()`. */\n\tcwd?: () => string;\n\t/**\n\t * Gate agent-facing 'complete' on verified/user evidence backing. Defaults to `true` (on)\n\t * when omitted -- the conservative default; set to a function returning `false` to opt out.\n\t */\n\trequireVerifiedEvidenceForCompletion?: () => boolean;\n\t/**\n\t * Read-only open (non-terminal) task_steps steps on the active branch, for the goal⇄task\n\t * cross-visibility nudge in the tool response. When omitted, `summarizeGoalState` gets\n\t * no task-step context and simply emits no nudge -- goal-tool-core stays pure and never reads\n\t * task state itself; this is the only place that supplies it.\n\t */\n\tgetOpenTaskSteps?: () => readonly OpenTaskStepRef[];\n}\n\n/**\n * Validate an evidence ref's `uri` against session records (\"tool\") or the filesystem (\"file\").\n * Returns `undefined` for kinds/refs that carry nothing checkable (e.g. \"user\"/\"finding\"/\"test\",\n * or a missing `uri`) -- absence of a ref is not the same as a ref that failed to verify.\n */\nasync function resolveEvidenceVerified(\n\tkind: GoalEvidenceKind,\n\turi: string | undefined,\n\tdeps: GoalToolDependencies,\n): Promise<boolean | undefined> {\n\tconst trimmedUri = uri?.trim();\n\tif (!trimmedUri) return undefined;\n\tif (kind === \"tool\") {\n\t\treturn deps.hasToolCallId ? deps.hasToolCallId(trimmedUri) : false;\n\t}\n\tif (kind === \"file\") {\n\t\tconst cwd = deps.cwd?.() ?? process.cwd();\n\t\ttry {\n\t\t\tconst stats = await fsStat(resolveToCwd(trimmedUri, cwd));\n\t\t\treturn stats.isFile();\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (kind === \"worker\") {\n\t\tif (!deps.getLaneRecords || !deps.getWorkerClaimSnapshots) return false;\n\t\tconst laneId = trimmedUri;\n\t\tconst record = deps.getLaneRecords().find((candidate) => candidate.laneId === laneId);\n\t\tif (!record) return false;\n\t\tconst claim = deps.getWorkerClaimSnapshots().find((candidate) => candidate.requestId === laneId);\n\t\tif (!claim) return false;\n\t\t// An unreviewed mutation (parentReviewRequired && no parentReviewedAt) can never verify true --\n\t\t// this is what stops an unreviewed worker completion from ungating goal completion through\n\t\t// the existing verified/complete gate (goal-tool-core's isVerifiedOrUserEvidence/complete).\n\t\tif (claim.parentReviewRequired === true && claim.parentReviewedAt === undefined) return false;\n\t\treturn claim.status === \"completed\";\n\t}\n\treturn undefined;\n}\n\nfunction toGoalAction(input: GoalToolInput): GoalAction | { error: string } {\n\tswitch (input.action) {\n\t\tcase \"start\":\n\t\t\treturn { action: \"start\", goalId: input.goalId ?? \"\", userGoal: input.userGoal ?? \"\" };\n\t\tcase \"add_requirement\":\n\t\t\treturn { action: \"add_requirement\", requirementId: input.requirementId ?? \"\", text: input.text ?? \"\" };\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"satisfy_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tevidenceIds: input.evidenceIds,\n\t\t\t};\n\t\tcase \"block_requirement\":\n\t\t\treturn {\n\t\t\t\taction: \"block_requirement\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\treason: input.reason ?? \"\",\n\t\t\t};\n\t\tcase \"reopen_requirement\":\n\t\t\treturn { action: \"reopen_requirement\", requirementId: input.requirementId ?? \"\" };\n\t\tcase \"dispatch_worker\":\n\t\t\treturn {\n\t\t\t\taction: \"dispatch_worker\",\n\t\t\t\trequirementId: input.requirementId ?? \"\",\n\t\t\t\tinstructions: input.instructions ?? \"\",\n\t\t\t};\n\t\tcase \"add_evidence\": {\n\t\t\tif (input.kind === undefined) {\n\t\t\t\treturn { error: \"add_evidence requires a kind.\" };\n\t\t\t}\n\t\t\tconst kind: GoalEvidenceKind = input.kind;\n\t\t\treturn {\n\t\t\t\taction: \"add_evidence\",\n\t\t\t\tevidenceId: input.evidenceId ?? \"\",\n\t\t\t\tkind,\n\t\t\t\tsummary: input.summary ?? \"\",\n\t\t\t\turi: input.uri,\n\t\t\t};\n\t\t}\n\t\tcase \"progress\":\n\t\t\treturn { action: \"progress\" };\n\t\tcase \"no_progress\":\n\t\t\treturn { action: \"no_progress\" };\n\t\tcase \"complete\":\n\t\t\treturn { action: \"complete\" };\n\t\tcase \"block_goal\":\n\t\t\treturn { action: \"block_goal\", reason: input.reason ?? \"\" };\n\t\tcase \"resume_goal\":\n\t\t\treturn { action: \"resume_goal\" };\n\t\tcase \"cancel\":\n\t\t\treturn { action: \"cancel\" };\n\t\tdefault:\n\t\t\treturn { error: \"Unknown goal action.\" };\n\t}\n}\n\nexport function createGoalToolDefinition(deps: GoalToolDependencies): ToolDefinition {\n\tconst now = deps.now ?? (() => new Date().toISOString());\n\treturn {\n\t\tname: \"goal\",\n\t\tlabel: \"goal\",\n\t\tdescription:\n\t\t\t\"Record and update the durable goal ledger for the current task. Maintains a structured goal with requirements, evidence, and progress so long tasks can be resumed and continued. Start a goal, add requirements, attach evidence, mark requirements satisfied or blocked, reopen resolved blockers, resume blocked goals, and mark progress. This is the producer that drives /goal-continue; without recorded goal state, continuation has nothing to act on.\",\n\t\tpromptSnippet: \"Record goal, requirements, evidence, and progress in the durable goal ledger.\",\n\t\tpromptGuidelines: [\n\t\t\t\"At the start of a multi-step task, call goal with action 'start' to record the user goal, then add the concrete requirements with 'add_requirement'.\",\n\t\t\t\"As you make progress, record evidence with 'add_evidence' and mark requirements satisfied with 'satisfy_requirement', citing the evidence ids.\",\n\t\t\t\"For 'add_evidence', kind 'tool' expects a real toolCallId in 'uri' and kind 'file' expects a real path; both are checked and recorded as verified or not. Kind 'worker' expects a laneId in 'uri' and verifies true only for a reviewed, completed worker result. Kinds 'user'/'finding'/'test' carry no checkable ref.\",\n\t\t\t\"Use 'dispatch_worker' to bind a requirement to a worker lane while it is being worked; this records the binding only -- it never satisfies the requirement. Record 'worker'-kind evidence citing that laneId once the worker completes, then call 'satisfy_requirement'.\",\n\t\t\t\"Use 'progress' when you advance without satisfying a specific requirement, and 'no_progress' when a turn yields nothing, so stall detection works.\",\n\t\t\t\"When the user resolves a blocker, use 'resume_goal' and 'reopen_requirement' as needed; do not strand the old ledger or start a duplicate goal.\",\n\t\t\t\"Mark the goal 'complete' only when every requirement is satisfied and each requirement cites verified or user-confirmed evidence. Use 'block_goal' or 'block_requirement' with a reason when you are stuck and need the user. A blocked goal can still be resumed or cancelled.\",\n\t\t],\n\t\tparameters: goalSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tinput: GoalToolInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: GoalToolDetails;\n\t\t}> {\n\t\t\tconst mapped = toGoalAction(input);\n\t\t\tif (\"error\" in mapped) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${mapped.error}` }],\n\t\t\t\t\tdetails: { action: input.action, applied: false, error: mapped.error },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet action: GoalAction = mapped;\n\t\t\tif (action.action === \"add_evidence\") {\n\t\t\t\tconst verified = await resolveEvidenceVerified(action.kind, action.uri, deps);\n\t\t\t\taction = { ...action, verified };\n\t\t\t}\n\t\t\t// Honest dispatch reporting: distinguish \"dispatched\" (laneId), \"declined\" (skipReason --\n\t\t\t// the dependency IS wired but the underlying delegation starter refused, e.g. disabled or\n\t\t\t// already at capacity), and \"unwired\" (no dependency at all) -- never collapse a real\n\t\t\t// decline into a silent no-laneId no-op indistinguishable from the dep being absent.\n\t\t\tlet dispatchNote: string | undefined;\n\t\t\tlet dispatchSkipReason: string | undefined;\n\t\t\t// Indeterminate-binding dedupe guard: checked BEFORE any dispatch side effect, for BOTH\n\t\t\t// routes. A requirement already bound to a lane that is either still live (a plain\n\t\t\t// duplicate) or whose liveness/outcome cannot be determined at all (for example, a legacy\n\t\t\t// snapshot with no lane record or worker result) must never be\n\t\t\t// re-dispatched silently; only a CONFIRMED terminal outcome allows a legitimate retry.\n\t\t\tlet dispatchGuardRefused = false;\n\t\t\tif (action.action === \"dispatch_worker\") {\n\t\t\t\t// Captured into a `const` so the \"dispatch_worker\" narrowing survives into the closures\n\t\t\t\t// below -- TS does not narrow a `let`-bound outer variable across a callback boundary.\n\t\t\t\tconst dispatchAction = action;\n\t\t\t\tconst boundRequirement = deps\n\t\t\t\t\t.getGoalState()\n\t\t\t\t\t?.requirements.find((r) => r.id === dispatchAction.requirementId);\n\t\t\t\tconst bound = boundRequirement?.boundLaneId;\n\t\t\t\tif (bound !== undefined) {\n\t\t\t\t\tconst boundLaneRecord = deps.getLaneRecords?.().find((record) => record.laneId === bound);\n\t\t\t\t\tconst isLiveInFlight =\n\t\t\t\t\t\tboundLaneRecord !== undefined &&\n\t\t\t\t\t\t(boundLaneRecord.status === \"queued\" || boundLaneRecord.status === \"running\");\n\t\t\t\t\tif (isLiveInFlight) {\n\t\t\t\t\t\tdispatchSkipReason = \"requirement_already_bound\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// `boundLaneRecord` present here is necessarily terminal (isLiveInFlight was false).\n\t\t\t\t\t\tconst hasTerminalOutcome =\n\t\t\t\t\t\t\tboundLaneRecord !== undefined ||\n\t\t\t\t\t\t\t(deps.getWorkerClaimSnapshots?.().some((claim) => claim.requestId === bound) ?? false);\n\t\t\t\t\t\tif (!hasTerminalOutcome) dispatchSkipReason = \"bound_lane_indeterminate\";\n\t\t\t\t\t}\n\t\t\t\t\tif (dispatchSkipReason) {\n\t\t\t\t\t\tdispatchGuardRefused = true;\n\t\t\t\t\t\tdispatchNote = `No worker was dispatched (${dispatchSkipReason}); requirement '${dispatchAction.requirementId}' remains bound to lane '${bound}'.`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (action.action === \"dispatch_worker\" && !dispatchGuardRefused) {\n\t\t\t\tconst useTmux = input.dispatchTarget === \"tmux\" && deps.dispatchTmuxWorker !== undefined;\n\t\t\t\tconst dispatched = useTmux\n\t\t\t\t\t? await deps.dispatchTmuxWorker?.({\n\t\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t\t})\n\t\t\t\t\t: deps.startWorkerDelegation?.({\n\t\t\t\t\t\t\trequirementId: action.requirementId,\n\t\t\t\t\t\t\tinstructions: action.instructions,\n\t\t\t\t\t\t});\n\t\t\t\taction = { ...action, laneId: dispatched?.laneId };\n\t\t\t\tif (dispatched?.laneId) {\n\t\t\t\t\tdispatchNote = useTmux\n\t\t\t\t\t\t? `Dispatched tmux worker lane '${dispatched.laneId}' for requirement '${action.requirementId}'.`\n\t\t\t\t\t\t: `Dispatched in-process worker lane '${dispatched.laneId}' for requirement '${action.requirementId}' (tmux dispatch is not available from this tool yet).`;\n\t\t\t\t} else {\n\t\t\t\t\tconst wired = useTmux ? deps.dispatchTmuxWorker : deps.startWorkerDelegation;\n\t\t\t\t\tdispatchSkipReason = dispatched?.skipReason ?? (wired ? \"declined\" : \"dependency_unwired\");\n\t\t\t\t\tdispatchNote = `No worker was dispatched (${dispatchSkipReason}); requirement '${action.requirementId}' is recorded but not bound to a lane.`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst current = deps.getGoalState();\n\t\t\tlet nextState: GoalState;\n\t\t\tif (action.action === \"dispatch_worker\" && dispatchGuardRefused) {\n\t\t\t\t// Short-circuit: the guard refused before any dispatch attempt -- never call\n\t\t\t\t// applyGoalAction for this turn, so the requirement's existing `boundLaneId` is\n\t\t\t\t// preserved exactly as-is rather than clobbered to `undefined` by the reducer's\n\t\t\t\t// unconditional `boundLaneId: event.laneId` write (goal-state.ts's dispatch_worker case).\n\t\t\t\t// `current` is guaranteed defined here: the guard only refuses when a requirement with\n\t\t\t\t// a `boundLaneId` was found on it.\n\t\t\t\tnextState = current as GoalState;\n\t\t\t} else {\n\t\t\t\tconst result = applyGoalAction(current, action, now(), {\n\t\t\t\t\trequireVerifiedEvidenceForCompletion: deps.requireVerifiedEvidenceForCompletion?.() ?? true,\n\t\t\t\t});\n\t\t\t\tif (!result.ok) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `goal ${input.action} failed: ${result.error}` }],\n\t\t\t\t\t\tdetails: { action: input.action, applied: false, error: result.error, state: current },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tdeps.saveGoalState(result.state);\n\t\t\t\tnextState = result.state;\n\t\t\t}\n\n\t\t\tconst summary = summarizeGoalState(nextState, { action, openTaskSteps: deps.getOpenTaskSteps?.() });\n\t\t\tconst text = dispatchNote\n\t\t\t\t? `goal ${input.action} recorded.\\n${summary}\\n${dispatchNote}`\n\t\t\t\t: `goal ${input.action} recorded.\\n${summary}`;\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text }],\n\t\t\t\tdetails: {\n\t\t\t\t\taction: input.action,\n\t\t\t\t\tapplied: true,\n\t\t\t\t\tstate: nextState,\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && action.laneId ? { dispatchedLaneId: action.laneId } : {}),\n\t\t\t\t\t...(action.action === \"dispatch_worker\" && !action.laneId ? { dispatchSkipReason } : {}),\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"model-fitness.d.ts","sourceRoot":"","sources":["../../../src/core/tools/model-fitness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,QAAA,MAAM,kBAAkB;;;EAcvB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEtE,MAAM,WAAW,uBAAuB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC5B;AAED,MAAM,WAAW,4BAA4B;IAC5C,QAAQ,EAAE,CAAC,IAAI,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB;;;;;WAKG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACpB,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrH;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,4BAA4B,GAAG,cAAc,CAiCnG","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { ModelFitnessReport } from \"../research/model-fitness.ts\";\nimport { formatModelFitnessReport } from \"../research/model-fitness.ts\";\n\nconst modelFitnessSchema = Type.Object(\n\t{\n\t\tmodel: Type.String({\n\t\t\tdescription:\n\t\t\t\t'Model pattern to probe, e.g. \"ollama/qwen3:0.6b\" or any registered provider/model pattern. The model must be registered and authenticated.',\n\t\t}),\n\t\ttrials: Type.Optional(\n\t\t\tType.Number({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Trials per lane surface (research/worker), 1-20. Default 3. The judge always runs its 6-prompt set.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type ModelFitnessToolInput = Static<typeof modelFitnessSchema>;\n\nexport interface ModelFitnessToolDetails {\n\tstarted: boolean;\n\tskipReason?: string;\n\tmodel?: string;\n\treport?: ModelFitnessReport;\n}\n\nexport interface ModelFitnessToolDependencies {\n\trunProbe: (args: {\n\t\tmodel: string;\n\t\ttrials?: number;\n\t\t/**\n\t\t * The LLM tool-call id for THIS invocation: the idempotency token a retry of the same\n\t\t * tool call reuses, so the spawned-usage reportId stays stable on a retry instead of falling\n\t\t * back to a bare (model, trials) identity — which two deliberately separate tool calls on the\n\t\t * same model/trials would otherwise collide on and silently under-count.\n\t\t */\n\t\ttoolCallId?: string;\n\t}) => Promise<{ started: true; model: string; report: ModelFitnessReport } | { started: false; skipReason: string }>;\n}\n\nexport function createModelFitnessToolDefinition(deps: ModelFitnessToolDependencies): ToolDefinition {\n\treturn {\n\t\tname: \"model_fitness\",\n\t\tlabel: \"model_fitness\",\n\t\tdescription:\n\t\t\t\"Probe whether a candidate model can drive the harness's subagent contracts: runs the real research-lane, scout-worker, and routing-judge runners against the model and reports parse/success rates, judge discrimination, latency, and probe cost. Use it to evaluate small/local models (e.g. Ollama) before configuring them as lane or judge models.\",\n\t\tpromptSnippet: \"Benchmark a candidate model against the research/worker/judge subagent contracts.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use model_fitness before recommending a model for researchLane.model, workerDelegation.model, or modelRouter.judgeModel.\",\n\t\t\t\"A good lane model has high research/worker success; a good judge additionally routes trivial prompts cheap while keeping planning elevated.\",\n\t\t\t\"Probes spend real tokens on the probed model; prefer local/free models or small trial counts.\",\n\t\t],\n\t\tparameters: modelFitnessSchema,\n\t\tasync execute(\n\t\t\ttoolCallId,\n\t\t\tinput: ModelFitnessToolInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: ModelFitnessToolDetails;\n\t\t}> {\n\t\t\tconst run = await deps.runProbe({ model: input.model, trials: input.trials, toolCallId });\n\t\t\tif (!run.started) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `model_fitness skipped: ${run.skipReason}` }],\n\t\t\t\t\tdetails: { started: false, skipReason: run.skipReason },\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: formatModelFitnessReport(run.model, run.report) }],\n\t\t\t\tdetails: { started: true, model: run.model, report: run.report },\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"model-fitness.d.ts","sourceRoot":"","sources":["../../../src/core/tools/model-fitness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,QAAA,MAAM,kBAAkB;;;EAcvB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEtE,MAAM,WAAW,uBAAuB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC5B;AAED,MAAM,WAAW,4BAA4B;IAC5C,QAAQ,EAAE,CAAC,IAAI,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB;;;;;WAKG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACpB,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrH;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,4BAA4B,GAAG,cAAc,CAiCnG","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { ModelFitnessReport } from \"../research/model-fitness.ts\";\nimport { formatModelFitnessReport } from \"../research/model-fitness.ts\";\n\nconst modelFitnessSchema = Type.Object(\n\t{\n\t\tmodel: Type.String({\n\t\t\tdescription:\n\t\t\t\t'Model pattern to probe, e.g. \"ollama/qwen3:0.6b\" or any registered provider/model pattern. The model must be registered and authenticated.',\n\t\t}),\n\t\ttrials: Type.Optional(\n\t\t\tType.Number({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Trials per lane surface (research/worker), 1-20. Default 3. The judge always runs its 6-prompt set.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type ModelFitnessToolInput = Static<typeof modelFitnessSchema>;\n\nexport interface ModelFitnessToolDetails {\n\tstarted: boolean;\n\tskipReason?: string;\n\tmodel?: string;\n\treport?: ModelFitnessReport;\n}\n\nexport interface ModelFitnessToolDependencies {\n\trunProbe: (args: {\n\t\tmodel: string;\n\t\ttrials?: number;\n\t\t/**\n\t\t * The LLM tool-call id for THIS invocation: the idempotency token a retry of the same\n\t\t * tool call reuses, so the spawned-usage reportId stays stable on a retry instead of falling\n\t\t * back to a bare (model, trials) identity — which two deliberately separate tool calls on the\n\t\t * same model/trials would otherwise collide on and silently under-count.\n\t\t */\n\t\ttoolCallId?: string;\n\t}) => Promise<{ started: true; model: string; report: ModelFitnessReport } | { started: false; skipReason: string }>;\n}\n\nexport function createModelFitnessToolDefinition(deps: ModelFitnessToolDependencies): ToolDefinition {\n\treturn {\n\t\tname: \"model_fitness\",\n\t\tlabel: \"model_fitness\",\n\t\tdescription:\n\t\t\t\"Probe whether a candidate model can drive the harness's subagent contracts: runs the real research-lane, delegated-worker, and routing-judge runners against the model and reports parse/success rates, judge discrimination, latency, and probe cost. Use it to evaluate small/local models (e.g. Ollama) before configuring them as lane or judge models.\",\n\t\tpromptSnippet: \"Benchmark a candidate model against the research/worker/judge subagent contracts.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use model_fitness before pinning a model in a worker orchestration profile, researchLane.model, or modelRouter.judgeModel.\",\n\t\t\t\"A good lane model has high research/worker success; a good judge additionally routes trivial prompts cheap while keeping planning elevated.\",\n\t\t\t\"Probes spend real tokens on the probed model; prefer local/free models or small trial counts.\",\n\t\t],\n\t\tparameters: modelFitnessSchema,\n\t\tasync execute(\n\t\t\ttoolCallId,\n\t\t\tinput: ModelFitnessToolInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: ModelFitnessToolDetails;\n\t\t}> {\n\t\t\tconst run = await deps.runProbe({ model: input.model, trials: input.trials, toolCallId });\n\t\t\tif (!run.started) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `model_fitness skipped: ${run.skipReason}` }],\n\t\t\t\t\tdetails: { started: false, skipReason: run.skipReason },\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: formatModelFitnessReport(run.model, run.report) }],\n\t\t\t\tdetails: { started: true, model: run.model, report: run.report },\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -12,10 +12,10 @@ export function createModelFitnessToolDefinition(deps) {
12
12
  return {
13
13
  name: "model_fitness",
14
14
  label: "model_fitness",
15
- description: "Probe whether a candidate model can drive the harness's subagent contracts: runs the real research-lane, scout-worker, and routing-judge runners against the model and reports parse/success rates, judge discrimination, latency, and probe cost. Use it to evaluate small/local models (e.g. Ollama) before configuring them as lane or judge models.",
15
+ description: "Probe whether a candidate model can drive the harness's subagent contracts: runs the real research-lane, delegated-worker, and routing-judge runners against the model and reports parse/success rates, judge discrimination, latency, and probe cost. Use it to evaluate small/local models (e.g. Ollama) before configuring them as lane or judge models.",
16
16
  promptSnippet: "Benchmark a candidate model against the research/worker/judge subagent contracts.",
17
17
  promptGuidelines: [
18
- "Use model_fitness before recommending a model for researchLane.model, workerDelegation.model, or modelRouter.judgeModel.",
18
+ "Use model_fitness before pinning a model in a worker orchestration profile, researchLane.model, or modelRouter.judgeModel.",
19
19
  "A good lane model has high research/worker success; a good judge additionally routes trivial prompts cheap while keeping planning elevated.",
20
20
  "Probes spend real tokens on the probed model; prefer local/free models or small trial counts.",
21
21
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"model-fitness.js","sourceRoot":"","sources":["../../../src/core/tools/model-fitness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAExE,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CACrC;IACC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,WAAW,EACV,4IAA4I;KAC7I,CAAC;IACF,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EACV,qGAAqG;KACtG,CAAC,CACF;CACD,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAC/B,CAAC;AAyBF,MAAM,UAAU,gCAAgC,CAAC,IAAkC,EAAkB;IACpG,OAAO;QACN,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,eAAe;QACtB,WAAW,EACV,yVAAyV;QAC1V,aAAa,EAAE,mFAAmF;QAClG,gBAAgB,EAAE;YACjB,0HAA0H;YAC1H,6IAA6I;YAC7I,+FAA+F;SAC/F;QACD,UAAU,EAAE,kBAAkB;QAC9B,KAAK,CAAC,OAAO,CACZ,UAAU,EACV,KAA4B,EAI1B;YACF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YAC1F,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;gBAClB,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,0BAA0B,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC;oBACtF,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE;iBACvD,CAAC;YACH,CAAC;YACD,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,wBAAwB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3F,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE;aAChE,CAAC;QAAA,CACF;KACD,CAAC;AAAA,CACF","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { ModelFitnessReport } from \"../research/model-fitness.ts\";\nimport { formatModelFitnessReport } from \"../research/model-fitness.ts\";\n\nconst modelFitnessSchema = Type.Object(\n\t{\n\t\tmodel: Type.String({\n\t\t\tdescription:\n\t\t\t\t'Model pattern to probe, e.g. \"ollama/qwen3:0.6b\" or any registered provider/model pattern. The model must be registered and authenticated.',\n\t\t}),\n\t\ttrials: Type.Optional(\n\t\t\tType.Number({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Trials per lane surface (research/worker), 1-20. Default 3. The judge always runs its 6-prompt set.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type ModelFitnessToolInput = Static<typeof modelFitnessSchema>;\n\nexport interface ModelFitnessToolDetails {\n\tstarted: boolean;\n\tskipReason?: string;\n\tmodel?: string;\n\treport?: ModelFitnessReport;\n}\n\nexport interface ModelFitnessToolDependencies {\n\trunProbe: (args: {\n\t\tmodel: string;\n\t\ttrials?: number;\n\t\t/**\n\t\t * The LLM tool-call id for THIS invocation: the idempotency token a retry of the same\n\t\t * tool call reuses, so the spawned-usage reportId stays stable on a retry instead of falling\n\t\t * back to a bare (model, trials) identity — which two deliberately separate tool calls on the\n\t\t * same model/trials would otherwise collide on and silently under-count.\n\t\t */\n\t\ttoolCallId?: string;\n\t}) => Promise<{ started: true; model: string; report: ModelFitnessReport } | { started: false; skipReason: string }>;\n}\n\nexport function createModelFitnessToolDefinition(deps: ModelFitnessToolDependencies): ToolDefinition {\n\treturn {\n\t\tname: \"model_fitness\",\n\t\tlabel: \"model_fitness\",\n\t\tdescription:\n\t\t\t\"Probe whether a candidate model can drive the harness's subagent contracts: runs the real research-lane, scout-worker, and routing-judge runners against the model and reports parse/success rates, judge discrimination, latency, and probe cost. Use it to evaluate small/local models (e.g. Ollama) before configuring them as lane or judge models.\",\n\t\tpromptSnippet: \"Benchmark a candidate model against the research/worker/judge subagent contracts.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use model_fitness before recommending a model for researchLane.model, workerDelegation.model, or modelRouter.judgeModel.\",\n\t\t\t\"A good lane model has high research/worker success; a good judge additionally routes trivial prompts cheap while keeping planning elevated.\",\n\t\t\t\"Probes spend real tokens on the probed model; prefer local/free models or small trial counts.\",\n\t\t],\n\t\tparameters: modelFitnessSchema,\n\t\tasync execute(\n\t\t\ttoolCallId,\n\t\t\tinput: ModelFitnessToolInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: ModelFitnessToolDetails;\n\t\t}> {\n\t\t\tconst run = await deps.runProbe({ model: input.model, trials: input.trials, toolCallId });\n\t\t\tif (!run.started) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `model_fitness skipped: ${run.skipReason}` }],\n\t\t\t\t\tdetails: { started: false, skipReason: run.skipReason },\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: formatModelFitnessReport(run.model, run.report) }],\n\t\t\t\tdetails: { started: true, model: run.model, report: run.report },\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"model-fitness.js","sourceRoot":"","sources":["../../../src/core/tools/model-fitness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAExE,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CACrC;IACC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,WAAW,EACV,4IAA4I;KAC7I,CAAC;IACF,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EACV,qGAAqG;KACtG,CAAC,CACF;CACD,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAC/B,CAAC;AAyBF,MAAM,UAAU,gCAAgC,CAAC,IAAkC,EAAkB;IACpG,OAAO;QACN,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,eAAe;QACtB,WAAW,EACV,6VAA6V;QAC9V,aAAa,EAAE,mFAAmF;QAClG,gBAAgB,EAAE;YACjB,4HAA4H;YAC5H,6IAA6I;YAC7I,+FAA+F;SAC/F;QACD,UAAU,EAAE,kBAAkB;QAC9B,KAAK,CAAC,OAAO,CACZ,UAAU,EACV,KAA4B,EAI1B;YACF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YAC1F,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;gBAClB,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,0BAA0B,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC;oBACtF,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE;iBACvD,CAAC;YACH,CAAC;YACD,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,wBAAwB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3F,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE;aAChE,CAAC;QAAA,CACF;KACD,CAAC;AAAA,CACF","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { ModelFitnessReport } from \"../research/model-fitness.ts\";\nimport { formatModelFitnessReport } from \"../research/model-fitness.ts\";\n\nconst modelFitnessSchema = Type.Object(\n\t{\n\t\tmodel: Type.String({\n\t\t\tdescription:\n\t\t\t\t'Model pattern to probe, e.g. \"ollama/qwen3:0.6b\" or any registered provider/model pattern. The model must be registered and authenticated.',\n\t\t}),\n\t\ttrials: Type.Optional(\n\t\t\tType.Number({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Trials per lane surface (research/worker), 1-20. Default 3. The judge always runs its 6-prompt set.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type ModelFitnessToolInput = Static<typeof modelFitnessSchema>;\n\nexport interface ModelFitnessToolDetails {\n\tstarted: boolean;\n\tskipReason?: string;\n\tmodel?: string;\n\treport?: ModelFitnessReport;\n}\n\nexport interface ModelFitnessToolDependencies {\n\trunProbe: (args: {\n\t\tmodel: string;\n\t\ttrials?: number;\n\t\t/**\n\t\t * The LLM tool-call id for THIS invocation: the idempotency token a retry of the same\n\t\t * tool call reuses, so the spawned-usage reportId stays stable on a retry instead of falling\n\t\t * back to a bare (model, trials) identity — which two deliberately separate tool calls on the\n\t\t * same model/trials would otherwise collide on and silently under-count.\n\t\t */\n\t\ttoolCallId?: string;\n\t}) => Promise<{ started: true; model: string; report: ModelFitnessReport } | { started: false; skipReason: string }>;\n}\n\nexport function createModelFitnessToolDefinition(deps: ModelFitnessToolDependencies): ToolDefinition {\n\treturn {\n\t\tname: \"model_fitness\",\n\t\tlabel: \"model_fitness\",\n\t\tdescription:\n\t\t\t\"Probe whether a candidate model can drive the harness's subagent contracts: runs the real research-lane, delegated-worker, and routing-judge runners against the model and reports parse/success rates, judge discrimination, latency, and probe cost. Use it to evaluate small/local models (e.g. Ollama) before configuring them as lane or judge models.\",\n\t\tpromptSnippet: \"Benchmark a candidate model against the research/worker/judge subagent contracts.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use model_fitness before pinning a model in a worker orchestration profile, researchLane.model, or modelRouter.judgeModel.\",\n\t\t\t\"A good lane model has high research/worker success; a good judge additionally routes trivial prompts cheap while keeping planning elevated.\",\n\t\t\t\"Probes spend real tokens on the probed model; prefer local/free models or small trial counts.\",\n\t\t],\n\t\tparameters: modelFitnessSchema,\n\t\tasync execute(\n\t\t\ttoolCallId,\n\t\t\tinput: ModelFitnessToolInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: ModelFitnessToolDetails;\n\t\t}> {\n\t\t\tconst run = await deps.runProbe({ model: input.model, trials: input.trials, toolCallId });\n\t\t\tif (!run.started) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `model_fitness skipped: ${run.skipReason}` }],\n\t\t\t\t\tdetails: { started: false, skipReason: run.skipReason },\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: formatModelFitnessReport(run.model, run.report) }],\n\t\t\t\tdetails: { started: true, model: run.model, report: run.report },\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,43 @@
1
+ import type { Component } from "@caupulican/pi-tui";
2
+ import { type TitleBadgeStatus } from "../../modes/interactive/components/tool-title.ts";
3
+ import type { Theme } from "../../modes/interactive/theme/theme.ts";
4
+ import type { LaneRecord } from "../autonomy/lane-tracker.ts";
5
+ import type { TaskStep, TaskStepsState } from "../tasks/task-state.ts";
6
+ export type OrchestrationRowStatus = "pending" | "queued" | "running" | "in_progress" | "completed" | "succeeded" | "blocked" | "failed" | "timeout" | "budget_exhausted" | "cancelled" | "canceled" | "reviewed" | "info";
7
+ export interface OrchestrationPanelRow {
8
+ status: OrchestrationRowStatus;
9
+ label: string;
10
+ section?: string;
11
+ meta?: readonly string[];
12
+ details?: readonly string[];
13
+ }
14
+ export interface OrchestrationPanelNotice {
15
+ status: "info" | "success" | "warning" | "error";
16
+ text: string;
17
+ }
18
+ export interface OrchestrationPanelModel {
19
+ label: string;
20
+ action?: string;
21
+ status?: TitleBadgeStatus;
22
+ summary?: readonly string[];
23
+ rows?: readonly OrchestrationPanelRow[];
24
+ notices?: readonly OrchestrationPanelNotice[];
25
+ emptyText?: string;
26
+ hiddenRowCount?: number;
27
+ }
28
+ export declare function taskStepPanelRow(step: TaskStep): OrchestrationPanelRow;
29
+ /** Build the quiet below-editor view from native session truth. No active work means no widget. */
30
+ export declare function createOrchestrationActivityModel(taskState: TaskStepsState | undefined, laneRecords: readonly LaneRecord[]): OrchestrationPanelModel | undefined;
31
+ export declare function renderOrchestrationPanelLines(theme: Theme, model: OrchestrationPanelModel, width: number, expanded?: boolean): string[];
32
+ export declare class OrchestrationPanelComponent implements Component {
33
+ private cachedWidth?;
34
+ private cachedLines?;
35
+ private readonly theme;
36
+ private readonly model;
37
+ private readonly expanded;
38
+ constructor(theme: Theme, model: OrchestrationPanelModel, expanded?: boolean);
39
+ render(width: number): string[];
40
+ invalidate(): void;
41
+ }
42
+ export declare function emptyOrchestrationCall(): Component;
43
+ //# sourceMappingURL=orchestration-panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestration-panel.d.ts","sourceRoot":"","sources":["../../../src/core/tools/orchestration-panel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,kDAAkD,CAAC;AAC3G,OAAO,KAAK,EAAE,KAAK,EAAc,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEvE,MAAM,MAAM,sBAAsB,GAC/B,SAAS,GACT,QAAQ,GACR,SAAS,GACT,aAAa,GACb,WAAW,GACX,WAAW,GACX,SAAS,GACT,QAAQ,GACR,SAAS,GACT,kBAAkB,GAClB,WAAW,GACX,UAAU,GACV,UAAU,GACV,MAAM,CAAC;AAEV,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACxC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IACjD,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,uBAAuB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,IAAI,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACxC,OAAO,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAC;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAiCD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,qBAAqB,CAmBtE;AAED,mGAAmG;AACnG,wBAAgB,gCAAgC,CAC/C,SAAS,EAAE,cAAc,GAAG,SAAS,EACrC,WAAW,EAAE,SAAS,UAAU,EAAE,GAChC,uBAAuB,GAAG,SAAS,CA8CrC;AAoBD,wBAAgB,6BAA6B,CAC5C,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,uBAAuB,EAC9B,KAAK,EAAE,MAAM,EACb,QAAQ,UAAQ,GACd,MAAM,EAAE,CA8BV;AAED,qBAAa,2BAA4B,YAAW,SAAS;IAC5D,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAW;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IAEnC,YAAY,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,QAAQ,UAAQ,EAIzE;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAK9B;IAED,UAAU,IAAI,IAAI,CAGjB;CACD;AAED,wBAAgB,sBAAsB,IAAI,SAAS,CAKlD","sourcesContent":["import type { Component } from \"@caupulican/pi-tui\";\nimport { truncateToWidth, visibleWidth } from \"@caupulican/pi-tui\";\nimport { renderTitleBadge, type TitleBadgeStatus } from \"../../modes/interactive/components/tool-title.ts\";\nimport type { Theme, ThemeColor } from \"../../modes/interactive/theme/theme.ts\";\nimport type { LaneRecord } from \"../autonomy/lane-tracker.ts\";\nimport type { TaskStep, TaskStepsState } from \"../tasks/task-state.ts\";\n\nexport type OrchestrationRowStatus =\n\t| \"pending\"\n\t| \"queued\"\n\t| \"running\"\n\t| \"in_progress\"\n\t| \"completed\"\n\t| \"succeeded\"\n\t| \"blocked\"\n\t| \"failed\"\n\t| \"timeout\"\n\t| \"budget_exhausted\"\n\t| \"cancelled\"\n\t| \"canceled\"\n\t| \"reviewed\"\n\t| \"info\";\n\nexport interface OrchestrationPanelRow {\n\tstatus: OrchestrationRowStatus;\n\tlabel: string;\n\tsection?: string;\n\tmeta?: readonly string[];\n\tdetails?: readonly string[];\n}\n\nexport interface OrchestrationPanelNotice {\n\tstatus: \"info\" | \"success\" | \"warning\" | \"error\";\n\ttext: string;\n}\n\nexport interface OrchestrationPanelModel {\n\tlabel: string;\n\taction?: string;\n\tstatus?: TitleBadgeStatus;\n\tsummary?: readonly string[];\n\trows?: readonly OrchestrationPanelRow[];\n\tnotices?: readonly OrchestrationPanelNotice[];\n\temptyText?: string;\n\thiddenRowCount?: number;\n}\n\ninterface RowStyle {\n\ticon: string;\n\tcolor: ThemeColor;\n\tstrike?: boolean;\n\tbold?: boolean;\n}\n\nconst ROW_STYLES: Record<OrchestrationRowStatus, RowStyle> = {\n\tpending: { icon: \"○\", color: \"muted\" },\n\tqueued: { icon: \"◌\", color: \"warning\" },\n\trunning: { icon: \"●\", color: \"accent\", bold: true },\n\tin_progress: { icon: \"●\", color: \"accent\", bold: true },\n\tcompleted: { icon: \"✓\", color: \"success\", strike: true },\n\tsucceeded: { icon: \"✓\", color: \"success\" },\n\tblocked: { icon: \"!\", color: \"warning\", bold: true },\n\tfailed: { icon: \"×\", color: \"error\", bold: true },\n\ttimeout: { icon: \"×\", color: \"warning\" },\n\tbudget_exhausted: { icon: \"!\", color: \"warning\" },\n\tcancelled: { icon: \"–\", color: \"muted\", strike: true },\n\tcanceled: { icon: \"–\", color: \"muted\", strike: true },\n\treviewed: { icon: \"✓\", color: \"success\" },\n\tinfo: { icon: \"·\", color: \"muted\" },\n};\n\nconst NOTICE_STYLES: Record<OrchestrationPanelNotice[\"status\"], { icon: string; color: ThemeColor }> = {\n\tinfo: { icon: \"·\", color: \"muted\" },\n\tsuccess: { icon: \"✓\", color: \"success\" },\n\twarning: { icon: \"!\", color: \"warning\" },\n\terror: { icon: \"×\", color: \"error\" },\n};\n\nexport function taskStepPanelRow(step: TaskStep): OrchestrationPanelRow {\n\tconst meta = [\n\t\tstep.priority === \"high\" ? \"high priority\" : undefined,\n\t\tstep.owner ? `@${step.owner}` : undefined,\n\t\tstep.requirementIds?.length\n\t\t\t? `${step.requirementIds.length} requirement${step.requirementIds.length === 1 ? \"\" : \"s\"}`\n\t\t\t: undefined,\n\t\tstep.evidence.length ? `${step.evidence.length} evidence` : undefined,\n\t].filter((value): value is string => value !== undefined);\n\tconst details = [\n\t\t...step.notes.slice(-2).map((note) => `note: ${note}`),\n\t\t...step.evidence.slice(-2).map((evidence) => `evidence: ${evidence}`),\n\t];\n\treturn {\n\t\tstatus: step.status,\n\t\tlabel: step.status === \"in_progress\" ? (step.activeForm ?? step.content) : step.content,\n\t\tmeta,\n\t\tdetails,\n\t};\n}\n\n/** Build the quiet below-editor view from native session truth. No active work means no widget. */\nexport function createOrchestrationActivityModel(\n\ttaskState: TaskStepsState | undefined,\n\tlaneRecords: readonly LaneRecord[],\n): OrchestrationPanelModel | undefined {\n\tconst openSteps =\n\t\ttaskState?.steps.filter((step) => step.status !== \"completed\" && step.status !== \"cancelled\") ?? [];\n\tconst orderedSteps = [\n\t\t...openSteps.filter((step) => step.status === \"in_progress\"),\n\t\t...openSteps.filter((step) => step.status === \"blocked\"),\n\t\t...openSteps.filter((step) => step.status === \"pending\"),\n\t];\n\tconst activeLanes = laneRecords.filter(\n\t\t(lane) =>\n\t\t\t(lane.type === \"worker\" || lane.type === \"tmux-worker\") &&\n\t\t\t(lane.status === \"running\" || lane.status === \"queued\"),\n\t);\n\tif (openSteps.length === 0 && activeLanes.length === 0) return undefined;\n\n\tconst taskRows = orderedSteps.slice(0, 5).map((step) => ({ ...taskStepPanelRow(step), section: \"Steps\" }));\n\tconst laneRows: OrchestrationPanelRow[] = activeLanes.slice(0, 3).map((lane) => ({\n\t\tstatus: lane.status,\n\t\tlabel: lane.label ?? lane.laneId,\n\t\tsection: \"Agents\",\n\t\tmeta: [\n\t\t\tlane.label ? lane.laneId : undefined,\n\t\t\tlane.profileId ? `profile ${lane.profileId}` : undefined,\n\t\t\tlane.type === \"tmux-worker\" ? \"tmux\" : undefined,\n\t\t].filter((value): value is string => value !== undefined),\n\t}));\n\tconst runningLanes = activeLanes.filter((lane) => lane.status === \"running\").length;\n\tconst queuedLanes = activeLanes.length - runningLanes;\n\tconst blockedSteps = openSteps.filter((step) => step.status === \"blocked\").length;\n\tconst workingSteps = openSteps.filter((step) => step.status === \"in_progress\").length;\n\tconst evidenceMissing = taskState?.steps.some((step) => step.status === \"completed\" && step.evidence.length === 0);\n\treturn {\n\t\tlabel: \"work\",\n\t\taction: workingSteps + runningLanes > 0 ? \"active\" : \"ready\",\n\t\tstatus: blockedSteps > 0 ? \"warning\" : workingSteps + runningLanes > 0 ? \"running\" : \"idle\",\n\t\tsummary: [\n\t\t\topenSteps.length ? `${openSteps.length} step${openSteps.length === 1 ? \"\" : \"s\"}` : undefined,\n\t\t\trunningLanes ? `${runningLanes} agent${runningLanes === 1 ? \"\" : \"s\"}` : undefined,\n\t\t\tqueuedLanes ? `${queuedLanes} queued` : undefined,\n\t\t].filter((value): value is string => value !== undefined),\n\t\trows: [...taskRows, ...laneRows],\n\t\thiddenRowCount: Math.max(0, openSteps.length + activeLanes.length - taskRows.length - laneRows.length),\n\t\tnotices: evidenceMissing\n\t\t\t? [{ status: \"warning\", text: \"Completed work still needs attached evidence.\" }]\n\t\t\t: undefined,\n\t};\n}\n\nfunction renderRow(theme: Theme, row: OrchestrationPanelRow, width: number, expanded: boolean): string[] {\n\tconst style = ROW_STYLES[row.status];\n\tconst prefix = ` ${theme.fg(style.color, style.icon)} `;\n\tconst meta = row.meta?.filter(Boolean).join(\" · \") ?? \"\";\n\tconst suffix = meta ? ` ${theme.fg(\"dim\", meta)}` : \"\";\n\tconst labelWidth = Math.max(4, width - visibleWidth(prefix) - visibleWidth(suffix));\n\tconst clippedLabel = truncateToWidth(row.label, labelWidth, \"…\");\n\tlet label = style.bold ? theme.bold(clippedLabel) : clippedLabel;\n\tif (style.strike) label = theme.strikethrough(label);\n\tconst lines = [`${prefix}${theme.fg(style.strike ? \"dim\" : \"text\", label)}${suffix}`];\n\tif (expanded) {\n\t\tfor (const detail of row.details ?? []) {\n\t\t\tlines.push(` ${theme.fg(\"dim\", truncateToWidth(detail, Math.max(4, width - 4), \"…\"))}`);\n\t\t}\n\t}\n\treturn lines;\n}\n\nexport function renderOrchestrationPanelLines(\n\ttheme: Theme,\n\tmodel: OrchestrationPanelModel,\n\twidth: number,\n\texpanded = false,\n): string[] {\n\tconst safeWidth = Math.max(1, width);\n\tconst title = renderTitleBadge(theme, {\n\t\tlabel: model.label,\n\t\taction: model.action,\n\t\tstatus: model.status ?? \"info\",\n\t});\n\tconst summary = model.summary?.filter(Boolean).join(theme.fg(\"dim\", \" · \")) ?? \"\";\n\tconst lines = [summary ? `${title} ${theme.fg(\"dim\", summary)}` : title];\n\tconst rows = model.rows ?? [];\n\tif (rows.length > 0) {\n\t\tlet section: string | undefined;\n\t\tfor (const row of rows) {\n\t\t\tif (row.section && row.section !== section) {\n\t\t\t\tsection = row.section;\n\t\t\t\tlines.push(` ${theme.fg(\"muted\", theme.bold(row.section))}`);\n\t\t\t}\n\t\t\tlines.push(...renderRow(theme, row, safeWidth, expanded));\n\t\t}\n\t} else if (model.emptyText) {\n\t\tlines.push(` ${theme.fg(\"muted\", model.emptyText)}`);\n\t}\n\tif ((model.hiddenRowCount ?? 0) > 0) {\n\t\tlines.push(` ${theme.fg(\"dim\", `… ${model.hiddenRowCount} more`)}`);\n\t}\n\tfor (const notice of model.notices ?? []) {\n\t\tconst style = NOTICE_STYLES[notice.status];\n\t\tlines.push(` ${theme.fg(style.color, style.icon)} ${theme.fg(\"dim\", notice.text)}`);\n\t}\n\treturn lines.map((line) => truncateToWidth(line, safeWidth, \"\"));\n}\n\nexport class OrchestrationPanelComponent implements Component {\n\tprivate cachedWidth?: number;\n\tprivate cachedLines?: string[];\n\tprivate readonly theme: Theme;\n\tprivate readonly model: OrchestrationPanelModel;\n\tprivate readonly expanded: boolean;\n\n\tconstructor(theme: Theme, model: OrchestrationPanelModel, expanded = false) {\n\t\tthis.theme = theme;\n\t\tthis.model = model;\n\t\tthis.expanded = expanded;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (this.cachedWidth === width && this.cachedLines) return this.cachedLines;\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedLines = renderOrchestrationPanelLines(this.theme, this.model, width, this.expanded);\n\t\treturn this.cachedLines;\n\t}\n\n\tinvalidate(): void {\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n}\n\nexport function emptyOrchestrationCall(): Component {\n\treturn {\n\t\trender: () => [],\n\t\tinvalidate() {},\n\t};\n}\n"]}