opencode-orchestrator 1.2.71 → 1.3.4

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 (534) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +444 -355
  3. package/bin/orchestrator-linux-arm64 +0 -0
  4. package/bin/orchestrator-linux-x64 +0 -0
  5. package/dist/agents/commander.d.ts +0 -0
  6. package/dist/agents/definitions.d.ts +0 -0
  7. package/dist/agents/prompts/01_philosophy/anti_hallucination.d.ts +0 -0
  8. package/dist/agents/prompts/01_philosophy/core.d.ts +0 -0
  9. package/dist/agents/prompts/01_philosophy/execution_assurance.d.ts +0 -0
  10. package/dist/agents/prompts/01_philosophy/index.d.ts +0 -0
  11. package/dist/agents/prompts/01_philosophy/metadata.d.ts +0 -0
  12. package/dist/agents/prompts/01_philosophy/modularity.d.ts +0 -0
  13. package/dist/agents/prompts/02_discovery/agents/discovery_commander.d.ts +0 -0
  14. package/dist/agents/prompts/02_discovery/agents/discovery_planner.d.ts +0 -0
  15. package/dist/agents/prompts/02_discovery/agents/index.d.ts +0 -0
  16. package/dist/agents/prompts/02_discovery/discovery_core.d.ts +0 -0
  17. package/dist/agents/prompts/02_discovery/discovery_environment.d.ts +0 -0
  18. package/dist/agents/prompts/02_discovery/discovery_skills.d.ts +0 -0
  19. package/dist/agents/prompts/02_discovery/discovery_workspace.d.ts +0 -0
  20. package/dist/agents/prompts/02_discovery/index.d.ts +0 -0
  21. package/dist/agents/prompts/03_planning/agents/index.d.ts +0 -0
  22. package/dist/agents/prompts/03_planning/agents/planning_commander.d.ts +0 -0
  23. package/dist/agents/prompts/03_planning/agents/planning_planner.d.ts +0 -0
  24. package/dist/agents/prompts/03_planning/agents/planning_reviewer.d.ts +0 -0
  25. package/dist/agents/prompts/03_planning/index.d.ts +0 -0
  26. package/dist/agents/prompts/03_planning/planning_core.d.ts +0 -0
  27. package/dist/agents/prompts/03_planning/planning_decomposition.d.ts +0 -0
  28. package/dist/agents/prompts/03_planning/planning_file_planning.d.ts +0 -0
  29. package/dist/agents/prompts/03_planning/planning_parallel.d.ts +0 -0
  30. package/dist/agents/prompts/03_planning/planning_research.d.ts +0 -0
  31. package/dist/agents/prompts/03_planning/planning_todo_format.d.ts +0 -0
  32. package/dist/agents/prompts/03_planning/planning_todo_rules.d.ts +0 -0
  33. package/dist/agents/prompts/03_planning/planning_todo_sync.d.ts +0 -0
  34. package/dist/agents/prompts/04_execution/agents/execution_commander.d.ts +0 -0
  35. package/dist/agents/prompts/04_execution/agents/execution_worker.d.ts +0 -0
  36. package/dist/agents/prompts/04_execution/agents/index.d.ts +0 -0
  37. package/dist/agents/prompts/04_execution/execution_core.d.ts +0 -0
  38. package/dist/agents/prompts/04_execution/execution_delegation.d.ts +0 -0
  39. package/dist/agents/prompts/04_execution/execution_error_handling.d.ts +0 -0
  40. package/dist/agents/prompts/04_execution/execution_file_assignment.d.ts +0 -0
  41. package/dist/agents/prompts/04_execution/execution_hyper_parallel.d.ts +0 -0
  42. package/dist/agents/prompts/04_execution/execution_isolation.d.ts +0 -0
  43. package/dist/agents/prompts/04_execution/execution_quality.d.ts +0 -0
  44. package/dist/agents/prompts/04_execution/execution_strategy.d.ts +0 -0
  45. package/dist/agents/prompts/04_execution/execution_tdd.d.ts +0 -0
  46. package/dist/agents/prompts/04_execution/execution_workflow.d.ts +0 -0
  47. package/dist/agents/prompts/04_execution/index.d.ts +0 -0
  48. package/dist/agents/prompts/05_verification/agents/index.d.ts +0 -0
  49. package/dist/agents/prompts/05_verification/agents/verification_commander.d.ts +0 -0
  50. package/dist/agents/prompts/05_verification/agents/verification_reviewer.d.ts +0 -0
  51. package/dist/agents/prompts/05_verification/index.d.ts +0 -0
  52. package/dist/agents/prompts/05_verification/verification_async_monitoring.d.ts +0 -0
  53. package/dist/agents/prompts/05_verification/verification_build.d.ts +0 -0
  54. package/dist/agents/prompts/05_verification/verification_core.d.ts +0 -0
  55. package/dist/agents/prompts/05_verification/verification_evidence.d.ts +0 -0
  56. package/dist/agents/prompts/05_verification/verification_integration.d.ts +0 -0
  57. package/dist/agents/prompts/05_verification/verification_strategy.d.ts +0 -0
  58. package/dist/agents/prompts/05_verification/verification_sync_check.d.ts +0 -0
  59. package/dist/agents/prompts/05_verification/verification_sync_handling.d.ts +0 -0
  60. package/dist/agents/prompts/05_verification/verification_test.d.ts +0 -0
  61. package/dist/agents/prompts/06_mission/agents/index.d.ts +0 -0
  62. package/dist/agents/prompts/06_mission/agents/mission_commander.d.ts +0 -0
  63. package/dist/agents/prompts/06_mission/index.d.ts +0 -0
  64. package/dist/agents/prompts/06_mission/mission_completion_conditions.d.ts +0 -0
  65. package/dist/agents/prompts/06_mission/mission_core.d.ts +0 -0
  66. package/dist/agents/prompts/06_mission/mission_lifecycle.d.ts +0 -0
  67. package/dist/agents/prompts/06_mission/mission_loop_continuation.d.ts +0 -0
  68. package/dist/agents/prompts/06_mission/mission_recovery.d.ts +0 -0
  69. package/dist/agents/prompts/06_mission/mission_status_tracking.d.ts +0 -0
  70. package/dist/agents/prompts/07_agents/commander/commander_forbidden.d.ts +0 -0
  71. package/dist/agents/prompts/07_agents/commander/commander_identity.d.ts +0 -0
  72. package/dist/agents/prompts/07_agents/commander/commander_mandate.d.ts +0 -0
  73. package/dist/agents/prompts/07_agents/commander/commander_required.d.ts +0 -0
  74. package/dist/agents/prompts/07_agents/commander/commander_role.d.ts +0 -0
  75. package/dist/agents/prompts/07_agents/commander/index.d.ts +0 -0
  76. package/dist/agents/prompts/07_agents/planner/index.d.ts +0 -0
  77. package/dist/agents/prompts/07_agents/planner/planner_forbidden.d.ts +0 -0
  78. package/dist/agents/prompts/07_agents/planner/planner_identity.d.ts +0 -0
  79. package/dist/agents/prompts/07_agents/planner/planner_mandate.d.ts +0 -0
  80. package/dist/agents/prompts/07_agents/planner/planner_required.d.ts +0 -0
  81. package/dist/agents/prompts/07_agents/reviewer/index.d.ts +0 -0
  82. package/dist/agents/prompts/07_agents/reviewer/reviewer_forbidden.d.ts +0 -0
  83. package/dist/agents/prompts/07_agents/reviewer/reviewer_identity.d.ts +0 -0
  84. package/dist/agents/prompts/07_agents/reviewer/reviewer_mandate.d.ts +0 -0
  85. package/dist/agents/prompts/07_agents/reviewer/reviewer_required.d.ts +0 -0
  86. package/dist/agents/prompts/07_agents/worker/index.d.ts +0 -0
  87. package/dist/agents/prompts/07_agents/worker/worker_forbidden.d.ts +0 -0
  88. package/dist/agents/prompts/07_agents/worker/worker_identity.d.ts +0 -0
  89. package/dist/agents/prompts/07_agents/worker/worker_mandate.d.ts +0 -0
  90. package/dist/agents/prompts/07_agents/worker/worker_required.d.ts +0 -0
  91. package/dist/agents/prompts/08_tools/agents/index.d.ts +0 -0
  92. package/dist/agents/prompts/08_tools/agents/tools_reviewer.d.ts +0 -0
  93. package/dist/agents/prompts/08_tools/agents/tools_worker.d.ts +0 -0
  94. package/dist/agents/prompts/08_tools/index.d.ts +0 -0
  95. package/dist/agents/prompts/08_tools/tools_ast.d.ts +0 -0
  96. package/dist/agents/prompts/08_tools/tools_code_editing.d.ts +0 -0
  97. package/dist/agents/prompts/08_tools/tools_core.d.ts +0 -0
  98. package/dist/agents/prompts/08_tools/tools_lsp.d.ts +0 -0
  99. package/dist/agents/prompts/08_tools/tools_search.d.ts +0 -0
  100. package/dist/agents/prompts/08_tools/tools_testing.d.ts +0 -0
  101. package/dist/agents/prompts/index.d.ts +0 -0
  102. package/dist/agents/subagents/planner.d.ts +0 -0
  103. package/dist/agents/subagents/reviewer.d.ts +0 -0
  104. package/dist/agents/subagents/worker.d.ts +0 -0
  105. package/dist/core/agents/agent-registry.d.ts +0 -0
  106. package/dist/core/agents/concurrency-config.d.ts +4 -0
  107. package/dist/core/agents/concurrency-token.d.ts +0 -0
  108. package/dist/core/agents/concurrency.d.ts +2 -0
  109. package/dist/core/agents/config.d.ts +0 -0
  110. package/dist/core/agents/consts/index.d.ts +0 -0
  111. package/dist/core/agents/consts/task-status.const.d.ts +0 -0
  112. package/dist/core/agents/format.d.ts +0 -0
  113. package/dist/core/agents/index.d.ts +0 -0
  114. package/dist/core/agents/interfaces/index.d.ts +0 -0
  115. package/dist/core/agents/interfaces/launch-input.interface.d.ts +0 -0
  116. package/dist/core/agents/interfaces/resume-input.interface.d.ts +0 -0
  117. package/dist/core/agents/interfaces/session-pool.interface.d.ts +0 -0
  118. package/dist/core/agents/logger.d.ts +0 -0
  119. package/dist/core/agents/manager/event-handler.d.ts +0 -0
  120. package/dist/core/agents/manager/index.d.ts +0 -0
  121. package/dist/core/agents/manager/task-cleaner.d.ts +0 -0
  122. package/dist/core/agents/manager/task-launcher.d.ts +0 -0
  123. package/dist/core/agents/manager/task-poller.d.ts +0 -0
  124. package/dist/core/agents/manager/task-resumer.d.ts +0 -0
  125. package/dist/core/agents/manager.d.ts +3 -1
  126. package/dist/core/agents/persistence/task-wal.d.ts +0 -0
  127. package/dist/core/agents/session-pool.d.ts +0 -0
  128. package/dist/core/agents/task-store.d.ts +0 -0
  129. package/dist/core/agents/types/index.d.ts +0 -0
  130. package/dist/core/agents/types/parallel-task-status.type.d.ts +0 -0
  131. package/dist/core/cache/constants.d.ts +0 -0
  132. package/dist/core/cache/document-cache.d.ts +0 -0
  133. package/dist/core/cache/index.d.ts +0 -0
  134. package/dist/core/cache/interfaces/cache-document-entry.d.ts +0 -0
  135. package/dist/core/cache/interfaces/cache-list-entry.d.ts +0 -0
  136. package/dist/core/cache/interfaces/cache-metadata.d.ts +0 -0
  137. package/dist/core/cache/interfaces/cache-stats.d.ts +0 -0
  138. package/dist/core/cache/interfaces/cached-document.d.ts +0 -0
  139. package/dist/core/cache/interfaces/index.d.ts +0 -0
  140. package/dist/core/cache/interfaces.d.ts +0 -0
  141. package/dist/core/cache/operations.d.ts +0 -0
  142. package/dist/core/cache/utils.d.ts +0 -0
  143. package/dist/core/cleanup/cleanup-scheduler.d.ts +0 -0
  144. package/dist/core/commands/index.d.ts +0 -0
  145. package/dist/core/commands/interfaces/background-task.d.ts +0 -0
  146. package/dist/core/commands/interfaces/index.d.ts +0 -0
  147. package/dist/core/commands/interfaces/run-background-options.d.ts +0 -0
  148. package/dist/core/commands/manager.d.ts +0 -0
  149. package/dist/core/commands/types/background-task-status.d.ts +0 -0
  150. package/dist/core/commands/types/index.d.ts +0 -0
  151. package/dist/core/config/plugin-options.d.ts +9 -0
  152. package/dist/core/context/context-window-monitor.d.ts +0 -0
  153. package/dist/core/context/index.d.ts +0 -0
  154. package/dist/core/knowledge/context-provider.d.ts +8 -0
  155. package/dist/core/knowledge/graph-parser.d.ts +39 -0
  156. package/dist/core/knowledge/hybrid-search.d.ts +65 -0
  157. package/dist/core/knowledge/index.d.ts +16 -0
  158. package/dist/core/knowledge/memory-consolidation.d.ts +38 -0
  159. package/dist/core/knowledge/mission-memory.d.ts +4 -0
  160. package/dist/core/knowledge/safety-guards.d.ts +39 -0
  161. package/dist/core/knowledge/scratchpad.d.ts +38 -0
  162. package/dist/core/knowledge/tag-indexer.d.ts +73 -0
  163. package/dist/core/loop/circuit-breaker.d.ts +0 -0
  164. package/dist/core/loop/compaction-guard.d.ts +0 -0
  165. package/dist/core/loop/formatters.d.ts +0 -0
  166. package/dist/core/loop/interfaces/index.d.ts +0 -0
  167. package/dist/core/loop/interfaces/todo-stats.d.ts +0 -0
  168. package/dist/core/loop/interfaces/todo.d.ts +0 -0
  169. package/dist/core/loop/interfaces.d.ts +0 -0
  170. package/dist/core/loop/mission-ledger.d.ts +17 -0
  171. package/dist/core/loop/mission-loop-handler.d.ts +0 -0
  172. package/dist/core/loop/mission-loop.d.ts +7 -1
  173. package/dist/core/loop/mission-runtime-options.d.ts +8 -0
  174. package/dist/core/loop/parser.d.ts +0 -0
  175. package/dist/core/loop/progress-tracker.d.ts +0 -0
  176. package/dist/core/loop/session-state-store.d.ts +0 -0
  177. package/dist/core/loop/stats.d.ts +0 -0
  178. package/dist/core/loop/todo-continuation.d.ts +0 -0
  179. package/dist/core/loop/todo-enforcer.d.ts +0 -0
  180. package/dist/core/loop/todo-manager.d.ts +0 -0
  181. package/dist/core/loop/types/index.d.ts +0 -0
  182. package/dist/core/loop/types/todo-priority.d.ts +0 -0
  183. package/dist/core/loop/types/todo-status.d.ts +0 -0
  184. package/dist/core/loop/verification.d.ts +0 -0
  185. package/dist/core/memory/interfaces.d.ts +0 -0
  186. package/dist/core/memory/memory-manager.d.ts +0 -0
  187. package/dist/core/metrics/collector.d.ts +0 -0
  188. package/dist/core/notification/os-notify/index.d.ts +0 -0
  189. package/dist/core/notification/os-notify/notifier.d.ts +0 -0
  190. package/dist/core/notification/os-notify/platform-resolver.d.ts +0 -0
  191. package/dist/core/notification/os-notify/platform.d.ts +0 -0
  192. package/dist/core/notification/os-notify/sound-player.d.ts +0 -0
  193. package/dist/core/notification/os-notify/todo-checker.d.ts +0 -0
  194. package/dist/core/notification/task-toast-manager.d.ts +0 -0
  195. package/dist/core/notification/toast-core.d.ts +0 -0
  196. package/dist/core/notification/toast-sanitizer.d.ts +0 -0
  197. package/dist/core/notification/toast.d.ts +0 -0
  198. package/dist/core/orchestrator/index.d.ts +0 -0
  199. package/dist/core/orchestrator/interfaces/index.d.ts +0 -0
  200. package/dist/core/orchestrator/interfaces/session-state.d.ts +0 -0
  201. package/dist/core/orchestrator/session-manager.d.ts +0 -0
  202. package/dist/core/orchestrator/state.d.ts +0 -0
  203. package/dist/core/orchestrator/types/index.d.ts +0 -0
  204. package/dist/core/orchestrator/types/task-status.d.ts +0 -0
  205. package/dist/core/plugins/interfaces.d.ts +0 -0
  206. package/dist/core/plugins/plugin-manager.d.ts +0 -0
  207. package/dist/core/pool/buffer-pool.d.ts +0 -0
  208. package/dist/core/pool/object-pool.d.ts +0 -0
  209. package/dist/core/pool/string-pool.d.ts +0 -0
  210. package/dist/core/pool/task-pool.d.ts +0 -0
  211. package/dist/core/progress/calculator.d.ts +0 -0
  212. package/dist/core/progress/formatters.d.ts +0 -0
  213. package/dist/core/progress/interfaces/index.d.ts +0 -0
  214. package/dist/core/progress/interfaces/progress-snapshot.d.ts +0 -0
  215. package/dist/core/progress/interfaces/snapshot-input.d.ts +0 -0
  216. package/dist/core/progress/interfaces/step-progress.d.ts +0 -0
  217. package/dist/core/progress/interfaces/task-progress.d.ts +0 -0
  218. package/dist/core/progress/interfaces/todo-progress.d.ts +0 -0
  219. package/dist/core/progress/interfaces.d.ts +0 -0
  220. package/dist/core/progress/progress-notifier.d.ts +0 -0
  221. package/dist/core/progress/state-broadcaster.d.ts +0 -0
  222. package/dist/core/progress/store.d.ts +0 -0
  223. package/dist/core/progress/tracker.d.ts +0 -0
  224. package/dist/core/queue/async-queue.d.ts +0 -0
  225. package/dist/core/queue/async-utils.d.ts +0 -0
  226. package/dist/core/queue/index.d.ts +0 -0
  227. package/dist/core/queue/work-pool.d.ts +0 -0
  228. package/dist/core/queue/work-stealing-deque.d.ts +0 -0
  229. package/dist/core/queue/worker-pool.d.ts +0 -0
  230. package/dist/core/recovery/auto-recovery.d.ts +0 -0
  231. package/dist/core/recovery/constants.d.ts +0 -0
  232. package/dist/core/recovery/handler.d.ts +0 -0
  233. package/dist/core/recovery/interfaces/error-context.d.ts +0 -0
  234. package/dist/core/recovery/interfaces/error-pattern.d.ts +0 -0
  235. package/dist/core/recovery/interfaces/index.d.ts +0 -0
  236. package/dist/core/recovery/interfaces/recovery-action.d.ts +0 -0
  237. package/dist/core/recovery/interfaces/recovery-record.d.ts +0 -0
  238. package/dist/core/recovery/interfaces/recovery-stats.d.ts +0 -0
  239. package/dist/core/recovery/interfaces.d.ts +0 -0
  240. package/dist/core/recovery/patterns.d.ts +0 -0
  241. package/dist/core/recovery/retry.d.ts +0 -0
  242. package/dist/core/recovery/session-recovery.d.ts +0 -0
  243. package/dist/core/session/interfaces/context-stats.d.ts +0 -0
  244. package/dist/core/session/interfaces/index.d.ts +0 -0
  245. package/dist/core/session/interfaces/shared-context.d.ts +0 -0
  246. package/dist/core/session/interfaces/shared-decision.d.ts +0 -0
  247. package/dist/core/session/interfaces/shared-document.d.ts +0 -0
  248. package/dist/core/session/interfaces/shared-finding.d.ts +0 -0
  249. package/dist/core/session/interfaces.d.ts +0 -0
  250. package/dist/core/session/shared-context.d.ts +0 -0
  251. package/dist/core/session/store.d.ts +0 -0
  252. package/dist/core/session/summary.d.ts +0 -0
  253. package/dist/core/sync/todo-parser.d.ts +0 -0
  254. package/dist/core/sync/todo-sync-service.d.ts +0 -0
  255. package/dist/core/task/interfaces/index.d.ts +0 -0
  256. package/dist/core/task/interfaces/task-hierarchy.d.ts +0 -0
  257. package/dist/core/task/interfaces/task-input.d.ts +0 -0
  258. package/dist/core/task/interfaces/task-node.d.ts +0 -0
  259. package/dist/core/task/interfaces/task-progress.d.ts +0 -0
  260. package/dist/core/task/interfaces.d.ts +0 -0
  261. package/dist/core/task/parser.d.ts +0 -0
  262. package/dist/core/task/scheduler.d.ts +0 -0
  263. package/dist/core/task/store.d.ts +0 -0
  264. package/dist/core/task/summary.d.ts +0 -0
  265. package/dist/core/task/task-decomposer.d.ts +0 -0
  266. package/dist/core/todo/todo-manager.d.ts +0 -0
  267. package/dist/hooks/compatibility/external-plugin.d.ts +0 -0
  268. package/dist/hooks/constants.d.ts +0 -0
  269. package/dist/hooks/custom/agent-ui.d.ts +0 -0
  270. package/dist/hooks/custom/memory-gate.d.ts +0 -0
  271. package/dist/hooks/custom/metrics.d.ts +0 -0
  272. package/dist/hooks/custom/resource-control.d.ts +0 -0
  273. package/dist/hooks/custom/secret-scanner.d.ts +0 -0
  274. package/dist/hooks/custom/strict-role-guard.d.ts +0 -0
  275. package/dist/hooks/custom/user-activity.d.ts +0 -0
  276. package/dist/hooks/features/mission-loop.d.ts +0 -0
  277. package/dist/hooks/features/sanity-check.d.ts +0 -0
  278. package/dist/hooks/index.d.ts +0 -0
  279. package/dist/hooks/registry.d.ts +0 -0
  280. package/dist/hooks/types.d.ts +0 -0
  281. package/dist/index.d.ts +0 -0
  282. package/dist/index.js +1388 -278
  283. package/dist/plugin-handlers/assistant-done-handler.d.ts +3 -4
  284. package/dist/plugin-handlers/chat-message-handler.d.ts +0 -0
  285. package/dist/plugin-handlers/config-handler.d.ts +8 -1
  286. package/dist/plugin-handlers/event-handler.d.ts +0 -0
  287. package/dist/plugin-handlers/index.d.ts +0 -1
  288. package/dist/plugin-handlers/interfaces/assistant-done-context.d.ts +0 -0
  289. package/dist/plugin-handlers/interfaces/chat-message-context.d.ts +0 -0
  290. package/dist/plugin-handlers/interfaces/event-handler-context.d.ts +0 -0
  291. package/dist/plugin-handlers/interfaces/index.d.ts +0 -0
  292. package/dist/plugin-handlers/interfaces/orchestrator-state.d.ts +0 -0
  293. package/dist/plugin-handlers/interfaces/session-compacting.d.ts +0 -0
  294. package/dist/plugin-handlers/interfaces/session-state.d.ts +1 -0
  295. package/dist/plugin-handlers/interfaces/system-transform.d.ts +3 -0
  296. package/dist/plugin-handlers/interfaces/tool-execute-context.d.ts +0 -0
  297. package/dist/plugin-handlers/interfaces/tool-hook.d.ts +0 -0
  298. package/dist/plugin-handlers/session-compacting-handler.d.ts +0 -0
  299. package/dist/plugin-handlers/system-transform-handler.d.ts +0 -0
  300. package/dist/plugin-handlers/tool-execute-handler.d.ts +0 -0
  301. package/dist/plugin-handlers/tool-execute-pre-handler.d.ts +0 -0
  302. package/dist/shared/agent/constants/index.d.ts +0 -1
  303. package/dist/shared/agent/constants/names.d.ts +0 -0
  304. package/dist/shared/agent/index.d.ts +0 -0
  305. package/dist/shared/agent/interfaces/agent-definition.d.ts +0 -0
  306. package/dist/shared/agent/interfaces/concurrency-config.d.ts +0 -0
  307. package/dist/shared/agent/interfaces/index.d.ts +0 -0
  308. package/dist/shared/agent/types/agent-name.d.ts +0 -0
  309. package/dist/shared/agent/types/index.d.ts +0 -0
  310. package/dist/shared/agent/utils/index.d.ts +0 -0
  311. package/dist/shared/cache/constants/cache-actions.d.ts +0 -0
  312. package/dist/shared/cache/constants/cache.d.ts +0 -0
  313. package/dist/shared/cache/constants/filter-status.d.ts +0 -0
  314. package/dist/shared/cache/constants/index.d.ts +0 -0
  315. package/dist/shared/cache/index.d.ts +0 -0
  316. package/dist/shared/command/index.d.ts +0 -0
  317. package/dist/shared/command/interfaces/background-task.d.ts +0 -0
  318. package/dist/shared/command/interfaces/index.d.ts +0 -0
  319. package/dist/shared/command/interfaces/run-background-options.d.ts +0 -0
  320. package/dist/shared/command/types/background-task-status.d.ts +0 -0
  321. package/dist/shared/command/types/index.d.ts +0 -0
  322. package/dist/shared/constants/security-patterns.d.ts +0 -0
  323. package/dist/shared/constants/system-messages.d.ts +0 -0
  324. package/dist/shared/core/constants/cli.d.ts +0 -0
  325. package/dist/shared/core/constants/id-prefix.d.ts +0 -0
  326. package/dist/shared/core/constants/index.d.ts +0 -0
  327. package/dist/shared/core/constants/lifecycle.d.ts +0 -0
  328. package/dist/shared/core/constants/limits.d.ts +0 -0
  329. package/dist/shared/core/constants/logging.d.ts +0 -0
  330. package/dist/shared/core/constants/memory-hooks.d.ts +0 -0
  331. package/dist/shared/core/constants/memory-limits.d.ts +0 -0
  332. package/dist/shared/core/constants/paths.d.ts +0 -0
  333. package/dist/shared/core/constants/phases.d.ts +0 -0
  334. package/dist/shared/core/constants/status-labels.d.ts +0 -0
  335. package/dist/shared/core/constants/time.d.ts +0 -0
  336. package/dist/shared/core/constants/wal-actions.d.ts +0 -0
  337. package/dist/shared/core/index.d.ts +0 -0
  338. package/dist/shared/core/poolable.d.ts +0 -0
  339. package/dist/shared/errors/constants/error-patterns.d.ts +0 -0
  340. package/dist/shared/errors/constants/error-type.d.ts +0 -0
  341. package/dist/shared/errors/constants/index.d.ts +0 -0
  342. package/dist/shared/errors/detection.d.ts +0 -0
  343. package/dist/shared/errors/index.d.ts +0 -0
  344. package/dist/shared/errors/retry.d.ts +0 -0
  345. package/dist/shared/errors/types/error-pattern-type.d.ts +0 -0
  346. package/dist/shared/errors/types/index.d.ts +0 -0
  347. package/dist/shared/index.d.ts +0 -0
  348. package/dist/shared/lifecycle/index.d.ts +0 -0
  349. package/dist/shared/lifecycle/registration.d.ts +0 -0
  350. package/dist/shared/lifecycle/shutdown-manager.d.ts +0 -0
  351. package/dist/shared/loop/constants/index.d.ts +0 -0
  352. package/dist/shared/loop/constants/labels.d.ts +0 -0
  353. package/dist/shared/loop/constants/loop.d.ts +0 -0
  354. package/dist/shared/loop/constants/mission-control.d.ts +0 -0
  355. package/dist/shared/loop/constants/task-status.d.ts +0 -0
  356. package/dist/shared/loop/constants/todo-status.d.ts +0 -0
  357. package/dist/shared/loop/index.d.ts +0 -0
  358. package/dist/shared/loop/interfaces/index.d.ts +0 -0
  359. package/dist/shared/loop/interfaces/mission-loop.d.ts +8 -0
  360. package/dist/shared/loop/interfaces/todo-stats.d.ts +0 -0
  361. package/dist/shared/loop/interfaces/todo.d.ts +0 -0
  362. package/dist/shared/loop/types/index.d.ts +0 -0
  363. package/dist/shared/loop/types/todo-priority.d.ts +0 -0
  364. package/dist/shared/loop/types/todo-status.d.ts +0 -0
  365. package/dist/shared/message/constants/index.d.ts +0 -0
  366. package/dist/shared/message/constants/message-roles.d.ts +0 -0
  367. package/dist/shared/message/constants/part-types.d.ts +0 -0
  368. package/dist/shared/message/constants/plugin-hooks.d.ts +6 -2
  369. package/dist/shared/message/constants/prompts.d.ts +0 -0
  370. package/dist/shared/message/constants/slash-commands.d.ts +0 -0
  371. package/dist/shared/message/index.d.ts +0 -0
  372. package/dist/shared/notification/constants/index.d.ts +0 -0
  373. package/dist/shared/notification/constants/toast-duration.d.ts +0 -0
  374. package/dist/shared/notification/constants/toast-variants.d.ts +0 -0
  375. package/dist/shared/notification/constants/tui.const.d.ts +0 -0
  376. package/dist/shared/notification/index.d.ts +0 -0
  377. package/dist/shared/notification/interfaces/index.d.ts +0 -0
  378. package/dist/shared/notification/interfaces/task-toast.interface.d.ts +0 -0
  379. package/dist/shared/notification/interfaces/toast-message.d.ts +0 -0
  380. package/dist/shared/notification/interfaces/toast-options.d.ts +0 -0
  381. package/dist/shared/notification/os-notify/constants/index.d.ts +0 -0
  382. package/dist/shared/notification/os-notify/constants/notification-command-keys.d.ts +0 -0
  383. package/dist/shared/notification/os-notify/constants/notification-commands.d.ts +0 -0
  384. package/dist/shared/notification/os-notify/constants/notification-defaults.d.ts +0 -0
  385. package/dist/shared/notification/os-notify/index.d.ts +0 -0
  386. package/dist/shared/notification/os-notify/interfaces/index.d.ts +0 -0
  387. package/dist/shared/notification/os-notify/interfaces/notification-config.d.ts +0 -0
  388. package/dist/shared/notification/os-notify/interfaces/notification-state.d.ts +0 -0
  389. package/dist/shared/notification/os-notify/types/index.d.ts +0 -0
  390. package/dist/shared/notification/os-notify/types/notification-commands.d.ts +0 -0
  391. package/dist/shared/notification/presets/index.d.ts +0 -0
  392. package/dist/shared/notification/presets/mission.d.ts +0 -0
  393. package/dist/shared/notification/presets/parallel.d.ts +0 -0
  394. package/dist/shared/notification/presets/session.d.ts +0 -0
  395. package/dist/shared/notification/presets/task-lifecycle.d.ts +0 -0
  396. package/dist/shared/notification/presets/tools.d.ts +0 -0
  397. package/dist/shared/notification/presets/warnings.d.ts +0 -0
  398. package/dist/shared/notification/types/index.d.ts +0 -0
  399. package/dist/shared/notification/types/toast-variant.d.ts +0 -0
  400. package/dist/shared/os/constants/index.d.ts +0 -0
  401. package/dist/shared/os/constants/platform.d.ts +0 -0
  402. package/dist/shared/os/index.d.ts +0 -0
  403. package/dist/shared/os/types/index.d.ts +0 -0
  404. package/dist/shared/os/types/platform.d.ts +0 -0
  405. package/dist/shared/prompt/constants/architecture.d.ts +0 -0
  406. package/dist/shared/prompt/constants/index.d.ts +0 -0
  407. package/dist/shared/prompt/constants/mandates.d.ts +0 -0
  408. package/dist/shared/prompt/constants/philosophy.d.ts +0 -0
  409. package/dist/shared/prompt/constants/scouts.d.ts +0 -0
  410. package/dist/shared/prompt/constants/status.d.ts +0 -0
  411. package/dist/shared/prompt/constants/tags.d.ts +0 -0
  412. package/dist/shared/prompt/index.d.ts +0 -0
  413. package/dist/shared/recovery/constants/history.d.ts +0 -0
  414. package/dist/shared/recovery/constants/index.d.ts +0 -0
  415. package/dist/shared/recovery/constants/recovery-level.d.ts +0 -0
  416. package/dist/shared/recovery/constants/recovery.d.ts +0 -0
  417. package/dist/shared/recovery/index.d.ts +0 -0
  418. package/dist/shared/recovery/interfaces/error-context.d.ts +0 -0
  419. package/dist/shared/recovery/interfaces/index.d.ts +0 -0
  420. package/dist/shared/recovery/interfaces/recovery-record.d.ts +0 -0
  421. package/dist/shared/recovery/types/index.d.ts +0 -0
  422. package/dist/shared/recovery/types/recovery-action.d.ts +0 -0
  423. package/dist/shared/session/constants/events/document-events.d.ts +0 -0
  424. package/dist/shared/session/constants/events/index.d.ts +0 -0
  425. package/dist/shared/session/constants/events/message-events.d.ts +0 -0
  426. package/dist/shared/session/constants/events/mission-events.d.ts +0 -0
  427. package/dist/shared/session/constants/events/session-events.d.ts +0 -0
  428. package/dist/shared/session/constants/events/special-events.d.ts +0 -0
  429. package/dist/shared/session/constants/events/task-events.d.ts +0 -0
  430. package/dist/shared/session/constants/events/todo-events.d.ts +0 -0
  431. package/dist/shared/session/constants/index.d.ts +0 -0
  432. package/dist/shared/session/index.d.ts +0 -0
  433. package/dist/shared/task/base-task.d.ts +0 -0
  434. package/dist/shared/task/constants/background-status.d.ts +0 -0
  435. package/dist/shared/task/constants/background-task.d.ts +0 -0
  436. package/dist/shared/task/constants/index.d.ts +0 -0
  437. package/dist/shared/task/constants/metadata-keys.d.ts +0 -0
  438. package/dist/shared/task/constants/parallel-task.d.ts +0 -0
  439. package/dist/shared/task/index.d.ts +0 -0
  440. package/dist/shared/task/interfaces/index.d.ts +0 -0
  441. package/dist/shared/task/interfaces/launch-input.d.ts +0 -0
  442. package/dist/shared/task/interfaces/parallel-task.d.ts +0 -0
  443. package/dist/shared/task/interfaces/resume-input.d.ts +0 -0
  444. package/dist/shared/task/interfaces/task-progress.d.ts +0 -0
  445. package/dist/shared/task/types/index.d.ts +0 -0
  446. package/dist/shared/task/types/parallel-task-status.d.ts +0 -0
  447. package/dist/shared/tool/constants/common/index.d.ts +0 -0
  448. package/dist/shared/tool/constants/common/labels.d.ts +0 -0
  449. package/dist/shared/tool/constants/common/languages.d.ts +0 -0
  450. package/dist/shared/tool/constants/common/output-labels.d.ts +0 -0
  451. package/dist/shared/tool/constants/common/sources.d.ts +0 -0
  452. package/dist/shared/tool/constants/index.d.ts +0 -0
  453. package/dist/shared/tool/constants/lsp/index.d.ts +0 -0
  454. package/dist/shared/tool/constants/lsp/lsp-severity-labels.d.ts +0 -0
  455. package/dist/shared/tool/constants/lsp/lsp-severity.d.ts +0 -0
  456. package/dist/shared/tool/constants/parallel/index.d.ts +0 -0
  457. package/dist/shared/tool/constants/parallel/logging.d.ts +0 -0
  458. package/dist/shared/tool/constants/parallel/parameters.d.ts +0 -0
  459. package/dist/shared/tool/constants/tool-names.d.ts +0 -0
  460. package/dist/shared/tool/constants/tool-output.d.ts +0 -0
  461. package/dist/shared/tool/index.d.ts +0 -0
  462. package/dist/shared/tool/interfaces/ast/ast-replace-result.d.ts +0 -0
  463. package/dist/shared/tool/interfaces/ast/ast-search-result.d.ts +0 -0
  464. package/dist/shared/tool/interfaces/ast/index.d.ts +0 -0
  465. package/dist/shared/tool/interfaces/index.d.ts +0 -0
  466. package/dist/shared/tool/interfaces/lsp/index.d.ts +0 -0
  467. package/dist/shared/tool/interfaces/lsp/lsp-command-result.d.ts +0 -0
  468. package/dist/shared/tool/interfaces/lsp/lsp-diagnostic.d.ts +0 -0
  469. package/dist/shared/tool/interfaces/lsp/lsp-rename-location.d.ts +0 -0
  470. package/dist/shared/tool/interfaces/lsp/lsp-rename-result.d.ts +0 -0
  471. package/dist/shared/tool/interfaces/parallel/index.d.ts +0 -0
  472. package/dist/shared/tool/interfaces/parallel/poll-result.d.ts +0 -0
  473. package/dist/shared/tool/interfaces/parallel/session-client.d.ts +0 -0
  474. package/dist/shared/verification/constants/categories.d.ts +0 -0
  475. package/dist/shared/verification/constants/checklist.d.ts +0 -0
  476. package/dist/shared/verification/constants/index.d.ts +0 -0
  477. package/dist/shared/verification/constants/patterns.d.ts +0 -0
  478. package/dist/shared/verification/constants/signals.d.ts +0 -0
  479. package/dist/shared/verification/index.d.ts +0 -0
  480. package/dist/shared/verification/interfaces/checklist-item.d.ts +0 -0
  481. package/dist/shared/verification/interfaces/checklist-verification-result.d.ts +0 -0
  482. package/dist/shared/verification/interfaces/index.d.ts +0 -0
  483. package/dist/shared/verification/interfaces/verification-checklist.d.ts +0 -0
  484. package/dist/shared/verification/interfaces/verification-result.d.ts +0 -0
  485. package/dist/shared/verification/types/checklist-category.d.ts +0 -0
  486. package/dist/shared/verification/types/index.d.ts +0 -0
  487. package/dist/tools/ast/index.d.ts +0 -0
  488. package/dist/tools/background-cmd/check.d.ts +0 -0
  489. package/dist/tools/background-cmd/index.d.ts +0 -0
  490. package/dist/tools/background-cmd/kill.d.ts +0 -0
  491. package/dist/tools/background-cmd/list.d.ts +0 -0
  492. package/dist/tools/background-cmd/run.d.ts +0 -0
  493. package/dist/tools/callAgent.d.ts +0 -0
  494. package/dist/tools/lsp/diagnostics-cache.d.ts +0 -0
  495. package/dist/tools/lsp/index.d.ts +0 -0
  496. package/dist/tools/parallel/cancel-task.d.ts +0 -0
  497. package/dist/tools/parallel/delegate-task.d.ts +0 -0
  498. package/dist/tools/parallel/get-task-result.d.ts +0 -0
  499. package/dist/tools/parallel/index.d.ts +0 -0
  500. package/dist/tools/parallel/list-agents.d.ts +0 -0
  501. package/dist/tools/parallel/list-tasks.d.ts +0 -0
  502. package/dist/tools/parallel/show-metrics.d.ts +0 -0
  503. package/dist/tools/parallel/update-todo.d.ts +0 -0
  504. package/dist/tools/registry.d.ts +0 -0
  505. package/dist/tools/rust-pool.d.ts +32 -2
  506. package/dist/tools/rust.d.ts +0 -0
  507. package/dist/tools/search.d.ts +0 -0
  508. package/dist/tools/slashCommand.d.ts +0 -0
  509. package/dist/tools/web/cache-docs.d.ts +0 -0
  510. package/dist/tools/web/codesearch.d.ts +0 -0
  511. package/dist/tools/web/index.d.ts +0 -0
  512. package/dist/tools/web/webfetch.d.ts +0 -0
  513. package/dist/tools/web/websearch.d.ts +0 -0
  514. package/dist/utils/binary.d.ts +0 -0
  515. package/dist/utils/common.d.ts +0 -0
  516. package/dist/utils/compatibility/claude.d.ts +0 -0
  517. package/dist/utils/formatting/elapsed-time.d.ts +0 -0
  518. package/dist/utils/formatting/index.d.ts +0 -0
  519. package/dist/utils/formatting/timestamp.d.ts +0 -0
  520. package/dist/utils/parsing/index.d.ts +0 -0
  521. package/dist/utils/parsing/slash-command.d.ts +0 -0
  522. package/dist/utils/sanity/checker.d.ts +0 -0
  523. package/dist/utils/sanity/constants/escalation-prompt.d.ts +0 -0
  524. package/dist/utils/sanity/constants/index.d.ts +0 -0
  525. package/dist/utils/sanity/constants/recovery-prompt.d.ts +0 -0
  526. package/dist/utils/sanity/constants/severity.d.ts +0 -0
  527. package/dist/utils/sanity/index.d.ts +0 -0
  528. package/dist/utils/sanity/interfaces/index.d.ts +0 -0
  529. package/dist/utils/sanity/interfaces/sanity-result.d.ts +0 -0
  530. package/dist/utils/sanity/types/index.d.ts +0 -0
  531. package/dist/utils/sanity/types/severity.d.ts +0 -0
  532. package/package.json +89 -88
  533. package/scripts/run-install-hook.mjs +66 -66
  534. package/dist/shared/agent/constants/agent-tokens.d.ts +0 -11
package/dist/index.js CHANGED
@@ -37,28 +37,11 @@ var init_names = __esm({
37
37
  }
38
38
  });
39
39
 
40
- // src/shared/agent/constants/agent-tokens.ts
41
- var AGENT_TOKENS;
42
- var init_agent_tokens = __esm({
43
- "src/shared/agent/constants/agent-tokens.ts"() {
44
- "use strict";
45
- AGENT_TOKENS = {
46
- /** Primary agent (Commander) max tokens */
47
- PRIMARY_MAX_TOKENS: 64e3,
48
- /** Primary agent thinking budget */
49
- PRIMARY_THINKING_BUDGET: 32e3,
50
- /** Subagent max tokens */
51
- SUBAGENT_MAX_TOKENS: 32e3
52
- };
53
- }
54
- });
55
-
56
40
  // src/shared/agent/constants/index.ts
57
41
  var init_constants = __esm({
58
42
  "src/shared/agent/constants/index.ts"() {
59
43
  "use strict";
60
44
  init_names();
61
- init_agent_tokens();
62
45
  }
63
46
  });
64
47
 
@@ -1903,10 +1886,14 @@ var init_plugin_hooks = __esm({
1903
1886
  PLUGIN_HOOKS = {
1904
1887
  /** Intercepts user messages before sending to LLM */
1905
1888
  CHAT_MESSAGE: "chat.message",
1906
- /** Runs after LLM finishes responding */
1907
- ASSISTANT_DONE: "assistant.done",
1889
+ /** Runs before any tool call */
1890
+ TOOL_EXECUTE_BEFORE: "tool.execute.before",
1908
1891
  /** Runs after any tool call completes */
1909
- TOOL_EXECUTE_AFTER: "tool.execute.after"
1892
+ TOOL_EXECUTE_AFTER: "tool.execute.after",
1893
+ /** Preserves custom compaction context */
1894
+ EXPERIMENTAL_SESSION_COMPACTING: "experimental.session.compacting",
1895
+ /** Injects dynamic system prompt additions */
1896
+ EXPERIMENTAL_CHAT_SYSTEM_TRANSFORM: "experimental.chat.system.transform"
1910
1897
  };
1911
1898
  }
1912
1899
  });
@@ -4733,9 +4720,10 @@ You are ${AGENT_NAMES.COMMANDER}. Autonomous mission controller.
4733
4720
  - You ADAPT your approach to what the project requires
4734
4721
 
4735
4722
  ## \u{1F680} AUTONOMOUS EXECUTION MODE
4736
- - Complete the ENTIRE mission without asking questions
4723
+ - Complete the ENTIRE mission without routine user hand-holding
4737
4724
  - Make decisions yourself - don't present options to user
4738
4725
  - If uncertain, make the BEST choice and proceed
4726
+ - Ask a concise clarification only when truly blocked and the OpenCode question permission allows it
4739
4727
  - Conclude ONLY after ${AGENT_NAMES.REVIEWER} verifies the full system
4740
4728
  - Only stop when everything is verified or truly blocked
4741
4729
  ${PROMPT_TAGS.ROLE.close}`;
@@ -5510,6 +5498,9 @@ var ConcurrencyToken = class {
5510
5498
  }, autoReleaseMs);
5511
5499
  this.autoReleaseTimer.unref();
5512
5500
  }
5501
+ controller;
5502
+ key;
5503
+ autoReleaseMs;
5513
5504
  released = false;
5514
5505
  autoReleaseTimer = null;
5515
5506
  /**
@@ -5853,6 +5844,12 @@ var ConcurrencyController = class {
5853
5844
  constructor(config3) {
5854
5845
  this.config = config3 ?? {};
5855
5846
  }
5847
+ configure(config3) {
5848
+ this.config = config3;
5849
+ }
5850
+ getConfig() {
5851
+ return this.config;
5852
+ }
5856
5853
  setLimit(key, limit) {
5857
5854
  this.limits.set(key, limit);
5858
5855
  }
@@ -7779,7 +7776,7 @@ function $constructor(name, initializer5, params) {
7779
7776
  Object.defineProperty(_, "name", { value: name });
7780
7777
  return _;
7781
7778
  }
7782
- var $brand = Symbol("zod_brand");
7779
+ var $brand = /* @__PURE__ */ Symbol("zod_brand");
7783
7780
  var $ZodAsyncError = class extends Error {
7784
7781
  constructor() {
7785
7782
  super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
@@ -7966,10 +7963,10 @@ function mergeDefs(...defs) {
7966
7963
  function cloneDef(schema) {
7967
7964
  return mergeDefs(schema._zod.def);
7968
7965
  }
7969
- function getElementAtPath(obj, path10) {
7970
- if (!path10)
7966
+ function getElementAtPath(obj, path11) {
7967
+ if (!path11)
7971
7968
  return obj;
7972
- return path10.reduce((acc, key) => acc?.[key], obj);
7969
+ return path11.reduce((acc, key) => acc?.[key], obj);
7973
7970
  }
7974
7971
  function promiseAllObject(promisesObj) {
7975
7972
  const keys = Object.keys(promisesObj);
@@ -8378,11 +8375,11 @@ function explicitlyAborted(x, startIndex = 0) {
8378
8375
  }
8379
8376
  return false;
8380
8377
  }
8381
- function prefixIssues(path10, issues) {
8378
+ function prefixIssues(path11, issues) {
8382
8379
  return issues.map((iss) => {
8383
8380
  var _a3;
8384
8381
  (_a3 = iss).path ?? (_a3.path = []);
8385
- iss.path.unshift(path10);
8382
+ iss.path.unshift(path11);
8386
8383
  return iss;
8387
8384
  });
8388
8385
  }
@@ -8529,16 +8526,16 @@ function flattenError(error95, mapper = (issue3) => issue3.message) {
8529
8526
  }
8530
8527
  function formatError(error95, mapper = (issue3) => issue3.message) {
8531
8528
  const fieldErrors = { _errors: [] };
8532
- const processError = (error96, path10 = []) => {
8529
+ const processError = (error96, path11 = []) => {
8533
8530
  for (const issue3 of error96.issues) {
8534
8531
  if (issue3.code === "invalid_union" && issue3.errors.length) {
8535
- issue3.errors.map((issues) => processError({ issues }, [...path10, ...issue3.path]));
8532
+ issue3.errors.map((issues) => processError({ issues }, [...path11, ...issue3.path]));
8536
8533
  } else if (issue3.code === "invalid_key") {
8537
- processError({ issues: issue3.issues }, [...path10, ...issue3.path]);
8534
+ processError({ issues: issue3.issues }, [...path11, ...issue3.path]);
8538
8535
  } else if (issue3.code === "invalid_element") {
8539
- processError({ issues: issue3.issues }, [...path10, ...issue3.path]);
8536
+ processError({ issues: issue3.issues }, [...path11, ...issue3.path]);
8540
8537
  } else {
8541
- const fullpath = [...path10, ...issue3.path];
8538
+ const fullpath = [...path11, ...issue3.path];
8542
8539
  if (fullpath.length === 0) {
8543
8540
  fieldErrors._errors.push(mapper(issue3));
8544
8541
  } else {
@@ -8565,17 +8562,17 @@ function formatError(error95, mapper = (issue3) => issue3.message) {
8565
8562
  }
8566
8563
  function treeifyError(error95, mapper = (issue3) => issue3.message) {
8567
8564
  const result = { errors: [] };
8568
- const processError = (error96, path10 = []) => {
8565
+ const processError = (error96, path11 = []) => {
8569
8566
  var _a3, _b;
8570
8567
  for (const issue3 of error96.issues) {
8571
8568
  if (issue3.code === "invalid_union" && issue3.errors.length) {
8572
- issue3.errors.map((issues) => processError({ issues }, [...path10, ...issue3.path]));
8569
+ issue3.errors.map((issues) => processError({ issues }, [...path11, ...issue3.path]));
8573
8570
  } else if (issue3.code === "invalid_key") {
8574
- processError({ issues: issue3.issues }, [...path10, ...issue3.path]);
8571
+ processError({ issues: issue3.issues }, [...path11, ...issue3.path]);
8575
8572
  } else if (issue3.code === "invalid_element") {
8576
- processError({ issues: issue3.issues }, [...path10, ...issue3.path]);
8573
+ processError({ issues: issue3.issues }, [...path11, ...issue3.path]);
8577
8574
  } else {
8578
- const fullpath = [...path10, ...issue3.path];
8575
+ const fullpath = [...path11, ...issue3.path];
8579
8576
  if (fullpath.length === 0) {
8580
8577
  result.errors.push(mapper(issue3));
8581
8578
  continue;
@@ -8607,8 +8604,8 @@ function treeifyError(error95, mapper = (issue3) => issue3.message) {
8607
8604
  }
8608
8605
  function toDotPath(_path) {
8609
8606
  const segs = [];
8610
- const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
8611
- for (const seg of path10) {
8607
+ const path11 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
8608
+ for (const seg of path11) {
8612
8609
  if (typeof seg === "number")
8613
8610
  segs.push(`[${seg}]`);
8614
8611
  else if (typeof seg === "symbol")
@@ -17522,8 +17519,8 @@ function yo_default() {
17522
17519
 
17523
17520
  // node_modules/zod/v4/core/registries.js
17524
17521
  var _a2;
17525
- var $output = Symbol("ZodOutput");
17526
- var $input = Symbol("ZodInput");
17522
+ var $output = /* @__PURE__ */ Symbol("ZodOutput");
17523
+ var $input = /* @__PURE__ */ Symbol("ZodInput");
17527
17524
  var $ZodRegistry = class {
17528
17525
  constructor() {
17529
17526
  this._map = /* @__PURE__ */ new WeakMap();
@@ -18560,7 +18557,7 @@ function _stringbool(Classes, _params) {
18560
18557
  type: "pipe",
18561
18558
  in: stringSchema,
18562
18559
  out: booleanSchema,
18563
- transform: (input, payload) => {
18560
+ transform: ((input, payload) => {
18564
18561
  let data = input;
18565
18562
  if (params.case !== "sensitive")
18566
18563
  data = data.toLowerCase();
@@ -18579,14 +18576,14 @@ function _stringbool(Classes, _params) {
18579
18576
  });
18580
18577
  return {};
18581
18578
  }
18582
- },
18583
- reverseTransform: (input, _payload) => {
18579
+ }),
18580
+ reverseTransform: ((input, _payload) => {
18584
18581
  if (input === true) {
18585
18582
  return truthyArray[0] || "true";
18586
18583
  } else {
18587
18584
  return falsyArray[0] || "false";
18588
18585
  }
18589
- },
18586
+ }),
18590
18587
  error: params.error
18591
18588
  });
18592
18589
  return codec3;
@@ -21300,13 +21297,13 @@ function resolveRef(ref, ctx) {
21300
21297
  if (!ref.startsWith("#")) {
21301
21298
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
21302
21299
  }
21303
- const path10 = ref.slice(1).split("/").filter(Boolean);
21304
- if (path10.length === 0) {
21300
+ const path11 = ref.slice(1).split("/").filter(Boolean);
21301
+ if (path11.length === 0) {
21305
21302
  return ctx.rootSchema;
21306
21303
  }
21307
21304
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
21308
- if (path10[0] === defsKey) {
21309
- const key = path10[1];
21305
+ if (path11[0] === defsKey) {
21306
+ const key = path11[1];
21310
21307
  if (!key || !ctx.defs[key]) {
21311
21308
  throw new Error(`Reference not found: ${ref}`);
21312
21309
  }
@@ -21723,9 +21720,6 @@ var AgentDefinitionSchema = external_exports.object({
21723
21720
  mode: external_exports.enum(["primary", "subagent"]).optional(),
21724
21721
  color: external_exports.string().optional(),
21725
21722
  hidden: external_exports.boolean().optional(),
21726
- thinking: external_exports.boolean().optional(),
21727
- maxTokens: external_exports.number().optional(),
21728
- budgetTokens: external_exports.number().optional(),
21729
21723
  canWrite: external_exports.boolean(),
21730
21724
  // Required per interface
21731
21725
  canBash: external_exports.boolean()
@@ -21782,7 +21776,7 @@ var AgentRegistry = class _AgentRegistry {
21782
21776
  for (const [name, def] of Object.entries(customAgents)) {
21783
21777
  const result = AgentDefinitionSchema.safeParse(def);
21784
21778
  if (result.success) {
21785
- this.registerAgent(name, def);
21779
+ this.registerAgent(name, result.data);
21786
21780
  } else {
21787
21781
  log(`[AgentRegistry] Invalid custom agent definition for: ${name}. Errors: ${result.error.message}`);
21788
21782
  }
@@ -21808,6 +21802,13 @@ var TaskLauncher = class {
21808
21802
  this.onTaskError = onTaskError;
21809
21803
  this.startPolling = startPolling;
21810
21804
  }
21805
+ client;
21806
+ directory;
21807
+ store;
21808
+ concurrency;
21809
+ sessionPool;
21810
+ onTaskError;
21811
+ startPolling;
21811
21812
  /**
21812
21813
  * Unified launch method - handles both single and multiple tasks efficiently.
21813
21814
  * All session creations happen in parallel immediately.
@@ -21977,6 +21978,11 @@ var TaskResumer = class {
21977
21978
  this.startPolling = startPolling;
21978
21979
  this.notifyParentIfAllComplete = notifyParentIfAllComplete;
21979
21980
  }
21981
+ client;
21982
+ store;
21983
+ findBySession;
21984
+ startPolling;
21985
+ notifyParentIfAllComplete;
21980
21986
  async resume(input) {
21981
21987
  const existingTask = this.findBySession(input.sessionId);
21982
21988
  if (!existingTask) {
@@ -22131,6 +22137,13 @@ var TaskPoller = class {
22131
22137
  this.pruneExpiredTasks = pruneExpiredTasks;
22132
22138
  this.onTaskComplete = onTaskComplete;
22133
22139
  }
22140
+ client;
22141
+ store;
22142
+ concurrency;
22143
+ notifyParentIfAllComplete;
22144
+ scheduleCleanup;
22145
+ pruneExpiredTasks;
22146
+ onTaskComplete;
22134
22147
  pollingInterval;
22135
22148
  messageCache = /* @__PURE__ */ new Map();
22136
22149
  // Adaptive polling
@@ -22335,6 +22348,10 @@ var TaskCleaner = class {
22335
22348
  this.concurrency = concurrency;
22336
22349
  this.sessionPool = sessionPool2;
22337
22350
  }
22351
+ client;
22352
+ store;
22353
+ concurrency;
22354
+ sessionPool;
22338
22355
  pruneExpiredTasks() {
22339
22356
  const now = Date.now();
22340
22357
  for (const [taskId, task] of this.store.getAll().map((t) => [t.id, t])) {
@@ -22450,6 +22467,14 @@ var EventHandler = class {
22450
22467
  this.validateSessionHasOutput = validateSessionHasOutput2;
22451
22468
  this.onTaskComplete = onTaskComplete;
22452
22469
  }
22470
+ client;
22471
+ store;
22472
+ concurrency;
22473
+ findBySession;
22474
+ notifyParentIfAllComplete;
22475
+ scheduleCleanup;
22476
+ validateSessionHasOutput;
22477
+ onTaskComplete;
22453
22478
  /**
22454
22479
  * Handle OpenCode session events for proper resource cleanup.
22455
22480
  * Call this from your plugin's event hook.
@@ -22955,7 +22980,7 @@ var ParallelAgentManager = class _ParallelAgentManager {
22955
22980
  store = new TaskStore();
22956
22981
  client;
22957
22982
  directory;
22958
- concurrency = new ConcurrencyController();
22983
+ concurrency;
22959
22984
  sessionPool;
22960
22985
  // Composed components
22961
22986
  launcher;
@@ -22963,9 +22988,10 @@ var ParallelAgentManager = class _ParallelAgentManager {
22963
22988
  poller;
22964
22989
  cleaner;
22965
22990
  eventHandler;
22966
- constructor(client, directory) {
22991
+ constructor(client, directory, concurrencyConfig) {
22967
22992
  this.client = client;
22968
22993
  this.directory = directory;
22994
+ this.concurrency = new ConcurrencyController(concurrencyConfig);
22969
22995
  const memory = MemoryManager.getInstance();
22970
22996
  memory.add("system" /* SYSTEM */, CORE_PHILOSOPHY, 1);
22971
22997
  memory.add("project" /* PROJECT */, `Working directory: ${directory}`, 0.9);
@@ -23017,12 +23043,12 @@ var ParallelAgentManager = class _ParallelAgentManager {
23017
23043
  log("Recovery error:", err);
23018
23044
  });
23019
23045
  }
23020
- static getInstance(client, directory) {
23046
+ static getInstance(client, directory, concurrencyConfig) {
23021
23047
  if (!_ParallelAgentManager._instance) {
23022
23048
  if (!client || !directory) {
23023
23049
  throw new Error("ParallelAgentManager requires client and directory on first call");
23024
23050
  }
23025
- _ParallelAgentManager._instance = new _ParallelAgentManager(client, directory);
23051
+ _ParallelAgentManager._instance = new _ParallelAgentManager(client, directory, concurrencyConfig);
23026
23052
  }
23027
23053
  return _ParallelAgentManager._instance;
23028
23054
  }
@@ -23091,6 +23117,9 @@ var ParallelAgentManager = class _ParallelAgentManager {
23091
23117
  setConcurrencyLimit(agentType, limit) {
23092
23118
  this.concurrency.setLimit(agentType, limit);
23093
23119
  }
23120
+ configureConcurrency(config3) {
23121
+ this.concurrency.configure(config3);
23122
+ }
23094
23123
  getPendingCount(parentSessionID) {
23095
23124
  return this.store.getPendingCount(parentSessionID);
23096
23125
  }
@@ -23719,7 +23748,7 @@ function $constructor2(name, initializer5, params) {
23719
23748
  Object.defineProperty(_, "name", { value: name });
23720
23749
  return _;
23721
23750
  }
23722
- var $brand2 = Symbol("zod_brand");
23751
+ var $brand2 = /* @__PURE__ */ Symbol("zod_brand");
23723
23752
  var $ZodAsyncError2 = class extends Error {
23724
23753
  constructor() {
23725
23754
  super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
@@ -23864,7 +23893,7 @@ function floatSafeRemainder2(val, step) {
23864
23893
  const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
23865
23894
  return valInt % stepInt / 10 ** decCount;
23866
23895
  }
23867
- var EVALUATING2 = Symbol("evaluating");
23896
+ var EVALUATING2 = /* @__PURE__ */ Symbol("evaluating");
23868
23897
  function defineLazy2(object3, key, getter) {
23869
23898
  let value = void 0;
23870
23899
  Object.defineProperty(object3, key, {
@@ -23909,10 +23938,10 @@ function mergeDefs2(...defs) {
23909
23938
  function cloneDef2(schema) {
23910
23939
  return mergeDefs2(schema._zod.def);
23911
23940
  }
23912
- function getElementAtPath2(obj, path10) {
23913
- if (!path10)
23941
+ function getElementAtPath2(obj, path11) {
23942
+ if (!path11)
23914
23943
  return obj;
23915
- return path10.reduce((acc, key) => acc?.[key], obj);
23944
+ return path11.reduce((acc, key) => acc?.[key], obj);
23916
23945
  }
23917
23946
  function promiseAllObject2(promisesObj) {
23918
23947
  const keys = Object.keys(promisesObj);
@@ -24273,11 +24302,11 @@ function aborted2(x, startIndex = 0) {
24273
24302
  }
24274
24303
  return false;
24275
24304
  }
24276
- function prefixIssues2(path10, issues) {
24305
+ function prefixIssues2(path11, issues) {
24277
24306
  return issues.map((iss) => {
24278
24307
  var _a3;
24279
24308
  (_a3 = iss).path ?? (_a3.path = []);
24280
- iss.path.unshift(path10);
24309
+ iss.path.unshift(path11);
24281
24310
  return iss;
24282
24311
  });
24283
24312
  }
@@ -24445,7 +24474,7 @@ function treeifyError2(error95, _mapper) {
24445
24474
  return issue3.message;
24446
24475
  };
24447
24476
  const result = { errors: [] };
24448
- const processError = (error96, path10 = []) => {
24477
+ const processError = (error96, path11 = []) => {
24449
24478
  var _a3, _b;
24450
24479
  for (const issue3 of error96.issues) {
24451
24480
  if (issue3.code === "invalid_union" && issue3.errors.length) {
@@ -24455,7 +24484,7 @@ function treeifyError2(error95, _mapper) {
24455
24484
  } else if (issue3.code === "invalid_element") {
24456
24485
  processError({ issues: issue3.issues }, issue3.path);
24457
24486
  } else {
24458
- const fullpath = [...path10, ...issue3.path];
24487
+ const fullpath = [...path11, ...issue3.path];
24459
24488
  if (fullpath.length === 0) {
24460
24489
  result.errors.push(mapper(issue3));
24461
24490
  continue;
@@ -24487,8 +24516,8 @@ function treeifyError2(error95, _mapper) {
24487
24516
  }
24488
24517
  function toDotPath2(_path) {
24489
24518
  const segs = [];
24490
- const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
24491
- for (const seg of path10) {
24519
+ const path11 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
24520
+ for (const seg of path11) {
24492
24521
  if (typeof seg === "number")
24493
24522
  segs.push(`[${seg}]`);
24494
24523
  else if (typeof seg === "symbol")
@@ -32709,8 +32738,8 @@ function yo_default2() {
32709
32738
  }
32710
32739
 
32711
32740
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/core/registries.js
32712
- var $output2 = Symbol("ZodOutput");
32713
- var $input2 = Symbol("ZodInput");
32741
+ var $output2 = /* @__PURE__ */ Symbol("ZodOutput");
32742
+ var $input2 = /* @__PURE__ */ Symbol("ZodInput");
32714
32743
  var $ZodRegistry2 = class {
32715
32744
  constructor() {
32716
32745
  this._map = /* @__PURE__ */ new WeakMap();
@@ -33593,7 +33622,7 @@ function _stringbool2(Classes, _params) {
33593
33622
  type: "pipe",
33594
33623
  in: stringSchema,
33595
33624
  out: booleanSchema,
33596
- transform: (input, payload) => {
33625
+ transform: ((input, payload) => {
33597
33626
  let data = input;
33598
33627
  if (params.case !== "sensitive")
33599
33628
  data = data.toLowerCase();
@@ -33612,14 +33641,14 @@ function _stringbool2(Classes, _params) {
33612
33641
  });
33613
33642
  return {};
33614
33643
  }
33615
- },
33616
- reverseTransform: (input, _payload) => {
33644
+ }),
33645
+ reverseTransform: ((input, _payload) => {
33617
33646
  if (input === true) {
33618
33647
  return truthyArray[0] || "true";
33619
33648
  } else {
33620
33649
  return falsyArray[0] || "false";
33621
33650
  }
33622
- },
33651
+ }),
33623
33652
  error: params.error
33624
33653
  });
33625
33654
  return codec3;
@@ -34579,10 +34608,10 @@ var ZodType2 = /* @__PURE__ */ $constructor2("ZodType", (inst, def) => {
34579
34608
  };
34580
34609
  inst.clone = (def2, params) => clone2(inst, def2, params);
34581
34610
  inst.brand = () => inst;
34582
- inst.register = (reg, meta3) => {
34611
+ inst.register = ((reg, meta3) => {
34583
34612
  reg.add(inst, meta3);
34584
34613
  return inst;
34585
- };
34614
+ });
34586
34615
  inst.parse = (data, params) => parse4(inst, data, params, { callee: inst.parse });
34587
34616
  inst.safeParse = (data, params) => safeParse4(inst, data, params);
34588
34617
  inst.parseAsync = async (data, params) => parseAsync4(inst, data, params, { callee: inst.parseAsync });
@@ -36409,8 +36438,8 @@ init_logger();
36409
36438
  // src/core/loop/mission-loop.ts
36410
36439
  init_logger();
36411
36440
  init_shared();
36412
- import { existsSync as existsSync2, readFileSync, writeFileSync, unlinkSync, mkdirSync as mkdirSync2 } from "node:fs";
36413
- import { join as join4 } from "node:path";
36441
+ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync, mkdirSync as mkdirSync4 } from "node:fs";
36442
+ import { join as join6 } from "node:path";
36414
36443
 
36415
36444
  // src/shared/constants/system-messages.ts
36416
36445
  init_mission_control();
@@ -36518,19 +36547,199 @@ You must maintain a pristine workspace. **As part of your move**, perform these
36518
36547
  </system_maintenance>
36519
36548
  `;
36520
36549
 
36550
+ // src/core/knowledge/mission-memory.ts
36551
+ init_shared();
36552
+ import { mkdirSync as mkdirSync3, renameSync, writeFileSync } from "node:fs";
36553
+ import { dirname as dirname2, join as join5 } from "node:path";
36554
+
36555
+ // src/core/loop/mission-ledger.ts
36556
+ init_shared();
36557
+ import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync } from "node:fs";
36558
+ import { join as join4 } from "node:path";
36559
+ import { randomUUID } from "node:crypto";
36560
+
36561
+ // src/core/loop/mission-runtime-options.ts
36562
+ var DEFAULT_MISSION_RUNTIME_OPTIONS = {
36563
+ ledger: true,
36564
+ markdownMemory: true,
36565
+ maxEvidenceEvents: 20
36566
+ };
36567
+ var runtimeOptions = { ...DEFAULT_MISSION_RUNTIME_OPTIONS };
36568
+ function configureMissionRuntimeOptions(options) {
36569
+ runtimeOptions = { ...DEFAULT_MISSION_RUNTIME_OPTIONS, ...options };
36570
+ }
36571
+ function getMissionRuntimeOptions() {
36572
+ return runtimeOptions;
36573
+ }
36574
+
36575
+ // src/core/loop/mission-ledger.ts
36576
+ var LEDGER_FILE = "mission-ledger.jsonl";
36577
+ function getMissionLedgerPath(directory) {
36578
+ return join4(directory, PATHS.OPENCODE, LEDGER_FILE);
36579
+ }
36580
+ function appendMissionLedgerEvent(directory, input) {
36581
+ if (!getMissionRuntimeOptions().ledger) return null;
36582
+ const event = {
36583
+ id: randomUUID(),
36584
+ timestamp: input.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
36585
+ type: input.type,
36586
+ sessionID: input.sessionID,
36587
+ iteration: input.iteration,
36588
+ objective: input.objective,
36589
+ summary: input.summary,
36590
+ reason: input.reason
36591
+ };
36592
+ try {
36593
+ const ledgerPath = getMissionLedgerPath(directory);
36594
+ mkdirSync2(join4(directory, PATHS.OPENCODE), { recursive: true });
36595
+ appendFileSync(ledgerPath, `${JSON.stringify(event)}
36596
+ `, "utf8");
36597
+ return event;
36598
+ } catch {
36599
+ return null;
36600
+ }
36601
+ }
36602
+ function readMissionLedger(directory, limit = 20) {
36603
+ const options = getMissionRuntimeOptions();
36604
+ if (!options.ledger) return [];
36605
+ const ledgerPath = getMissionLedgerPath(directory);
36606
+ if (!existsSync2(ledgerPath)) return [];
36607
+ try {
36608
+ const lines = readFileSync(ledgerPath, "utf8").split(/\r?\n/).filter(Boolean);
36609
+ const maxEvents = Math.max(1, Math.min(limit, options.maxEvidenceEvents));
36610
+ return lines.slice(Math.max(0, lines.length - maxEvents)).map(parseLedgerLine).filter((event) => event !== null);
36611
+ } catch {
36612
+ return [];
36613
+ }
36614
+ }
36615
+ function parseLedgerLine(line) {
36616
+ try {
36617
+ const value = JSON.parse(line);
36618
+ if (!value.id || !value.type || !value.timestamp || !value.sessionID) return null;
36619
+ return value;
36620
+ } catch {
36621
+ return null;
36622
+ }
36623
+ }
36624
+
36625
+ // src/core/knowledge/mission-memory.ts
36626
+ var BRAIN_DIR = join5(PATHS.DOCS, "brain");
36627
+ var SCRATCHPAD_FILE = "scratchpad.md";
36628
+ var CANVAS_FILE = "knowledge-map.canvas";
36629
+ var MAX_CANVAS_EVENTS = 3;
36630
+ var MAX_SCRATCHPAD_EVENTS = 6;
36631
+ function syncMissionMemory(directory, state2) {
36632
+ const options = getMissionRuntimeOptions();
36633
+ if (!options.markdownMemory) return false;
36634
+ const events = readMissionLedger(
36635
+ directory,
36636
+ Math.min(MAX_SCRATCHPAD_EVENTS, options.maxEvidenceEvents)
36637
+ );
36638
+ try {
36639
+ writeScratchpad(directory, state2, events);
36640
+ writeCanvas(directory, state2, events);
36641
+ return true;
36642
+ } catch {
36643
+ return false;
36644
+ }
36645
+ }
36646
+ function getMissionScratchpadPath(directory) {
36647
+ return join5(directory, BRAIN_DIR, SCRATCHPAD_FILE);
36648
+ }
36649
+ function getMissionCanvasPath(directory) {
36650
+ return join5(directory, BRAIN_DIR, CANVAS_FILE);
36651
+ }
36652
+ function writeScratchpad(directory, state2, events) {
36653
+ const content = [
36654
+ "---",
36655
+ "tags: [scratchpad, mission, orchestrator]",
36656
+ "keep: true",
36657
+ `title: "${escapeYaml(state2.objective ?? "Active Mission")}"`,
36658
+ "---",
36659
+ "# Orchestrator Mission Scratchpad",
36660
+ "",
36661
+ "## Focus",
36662
+ `- Objective: ${state2.objective ?? state2.prompt}`,
36663
+ `- Session: ${state2.sessionID}`,
36664
+ `- Status: ${state2.active ? "active" : "inactive"}`,
36665
+ `- Iteration: ${state2.iteration}/${state2.maxIterations}`,
36666
+ "",
36667
+ "## Runtime State",
36668
+ `- Last progress: ${state2.lastProgress ?? "unknown"}`,
36669
+ `- Last verification: ${state2.lastVerificationSummary ?? "unknown"}`,
36670
+ `- Last continuation reason: ${state2.lastContinuationReason ?? "unknown"}`,
36671
+ "",
36672
+ "## Recent Evidence",
36673
+ ...formatEventLines(events),
36674
+ "",
36675
+ "## Open Questions",
36676
+ "- Keep this section short; unresolved blockers should be reflected in TODO or sync issues.",
36677
+ ""
36678
+ ].join("\n");
36679
+ atomicWrite(getMissionScratchpadPath(directory), content);
36680
+ }
36681
+ function writeCanvas(directory, state2, events) {
36682
+ const nodes = buildCanvasNodes(state2, events);
36683
+ const edges = buildCanvasEdges(nodes);
36684
+ atomicWrite(getMissionCanvasPath(directory), JSON.stringify({ nodes, edges }, null, 2));
36685
+ }
36686
+ function buildCanvasNodes(state2, events) {
36687
+ const nodes = [
36688
+ textNode("objective", `Objective
36689
+ ${state2.objective ?? state2.prompt}`, 0, 0),
36690
+ textNode("runtime", `Runtime
36691
+ Iteration ${state2.iteration}/${state2.maxIterations}
36692
+ Progress ${state2.lastProgress ?? "unknown"}`, 420, 0),
36693
+ textNode("verification", `Verification
36694
+ ${state2.lastVerificationSummary ?? "unknown"}`, 840, 0)
36695
+ ];
36696
+ events.slice(-MAX_CANVAS_EVENTS).forEach((event, index) => {
36697
+ nodes.push(textNode(`event-${index}`, `${event.type}
36698
+ ${event.summary ?? event.reason ?? event.timestamp}`, 420 * index, 260));
36699
+ });
36700
+ return nodes;
36701
+ }
36702
+ function buildCanvasEdges(nodes) {
36703
+ const edges = [
36704
+ { id: "objective-runtime", fromNode: "objective", toNode: "runtime", label: "drives" },
36705
+ { id: "runtime-verification", fromNode: "runtime", toNode: "verification", label: "checks" }
36706
+ ];
36707
+ for (const node of nodes.filter((item) => item.id.startsWith("event-"))) {
36708
+ edges.push({ id: `verification-${node.id}`, fromNode: "verification", toNode: node.id, label: "evidence" });
36709
+ }
36710
+ return edges;
36711
+ }
36712
+ function textNode(id, text, x, y) {
36713
+ return { id, type: "text", text, x, y, width: 360, height: 180 };
36714
+ }
36715
+ function formatEventLines(events) {
36716
+ if (events.length === 0) return ["- No runtime evidence recorded yet."];
36717
+ return events.map((event) => `- ${event.timestamp} ${event.type}: ${event.summary ?? event.reason ?? "recorded"}`);
36718
+ }
36719
+ function atomicWrite(path11, content) {
36720
+ mkdirSync3(dirname2(path11), { recursive: true });
36721
+ const tempPath = `${path11}.tmp`;
36722
+ writeFileSync(tempPath, content, "utf8");
36723
+ renameSync(tempPath, path11);
36724
+ }
36725
+ function escapeYaml(value) {
36726
+ return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
36727
+ }
36728
+
36521
36729
  // src/core/loop/mission-loop.ts
36522
36730
  var STATE_FILE = MISSION_CONTROL.STATE_FILE;
36523
36731
  var DEFAULT_MAX_ITERATIONS = MISSION_CONTROL.DEFAULT_MAX_ITERATIONS;
36732
+ var UNKNOWN_STATUS = "unknown";
36524
36733
  function getStateFilePath(directory) {
36525
- return join4(directory, PATHS.OPENCODE, STATE_FILE);
36734
+ return join6(directory, PATHS.OPENCODE, STATE_FILE);
36526
36735
  }
36527
36736
  function readLoopState(directory) {
36528
36737
  const filePath = getStateFilePath(directory);
36529
- if (!existsSync2(filePath)) {
36738
+ if (!existsSync3(filePath)) {
36530
36739
  return null;
36531
36740
  }
36532
36741
  try {
36533
- const content = readFileSync(filePath, "utf-8");
36742
+ const content = readFileSync2(filePath, "utf-8");
36534
36743
  return JSON.parse(content);
36535
36744
  } catch (error95) {
36536
36745
  log(`[${MISSION_CONTROL.LOG_SOURCE}] Failed to read state: ${error95}`);
@@ -36539,12 +36748,12 @@ function readLoopState(directory) {
36539
36748
  }
36540
36749
  function writeLoopState(directory, state2) {
36541
36750
  const filePath = getStateFilePath(directory);
36542
- const dirPath = join4(directory, PATHS.OPENCODE);
36751
+ const dirPath = join6(directory, PATHS.OPENCODE);
36543
36752
  try {
36544
- if (!existsSync2(dirPath)) {
36545
- mkdirSync2(dirPath, { recursive: true });
36753
+ if (!existsSync3(dirPath)) {
36754
+ mkdirSync4(dirPath, { recursive: true });
36546
36755
  }
36547
- writeFileSync(filePath, JSON.stringify(state2, null, 2), "utf-8");
36756
+ writeFileSync2(filePath, JSON.stringify(state2, null, 2), "utf-8");
36548
36757
  return true;
36549
36758
  } catch (error95) {
36550
36759
  log(`[${MISSION_CONTROL.LOG_SOURCE}] Failed to write state: ${error95}`);
@@ -36553,7 +36762,7 @@ function writeLoopState(directory, state2) {
36553
36762
  }
36554
36763
  function clearLoopState(directory) {
36555
36764
  const filePath = getStateFilePath(directory);
36556
- if (!existsSync2(filePath)) {
36765
+ if (!existsSync3(filePath)) {
36557
36766
  return false;
36558
36767
  }
36559
36768
  try {
@@ -36574,17 +36783,30 @@ function incrementIteration(directory) {
36574
36783
  }
36575
36784
  return null;
36576
36785
  }
36786
+ function deriveObjective(prompt) {
36787
+ const firstLine = prompt.split(/\r?\n/).find((line) => line.trim().length > 0);
36788
+ return firstLine?.trim() || prompt.trim() || "Continue the active mission";
36789
+ }
36577
36790
  function startMissionLoop(directory, sessionID, prompt, options = {}) {
36578
36791
  const state2 = {
36579
36792
  active: true,
36580
36793
  iteration: 1,
36581
36794
  maxIterations: options.maxIterations ?? DEFAULT_MAX_ITERATIONS,
36582
36795
  prompt,
36796
+ objective: deriveObjective(prompt),
36583
36797
  sessionID,
36584
36798
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
36585
36799
  };
36586
36800
  const success3 = writeLoopState(directory, state2);
36587
36801
  if (success3) {
36802
+ appendMissionLedgerEvent(directory, {
36803
+ type: "mission_started",
36804
+ sessionID,
36805
+ iteration: state2.iteration,
36806
+ objective: state2.objective,
36807
+ summary: "Mission loop started"
36808
+ });
36809
+ syncMissionMemory(directory, state2);
36588
36810
  log(`[${MISSION_CONTROL.LOG_SOURCE}] Loop started`, {
36589
36811
  sessionID,
36590
36812
  maxIterations: state2.maxIterations
@@ -36599,6 +36821,19 @@ function cancelMissionLoop(directory, sessionID) {
36599
36821
  }
36600
36822
  const success3 = clearLoopState(directory);
36601
36823
  if (success3) {
36824
+ const cancelledState = {
36825
+ ...state2,
36826
+ active: false,
36827
+ lastContinuationReason: "cancelled"
36828
+ };
36829
+ appendMissionLedgerEvent(directory, {
36830
+ type: "mission_cancelled",
36831
+ sessionID,
36832
+ iteration: state2.iteration,
36833
+ objective: state2.objective,
36834
+ reason: "cancelled"
36835
+ });
36836
+ syncMissionMemory(directory, cancelledState);
36602
36837
  log(`[${MISSION_CONTROL.LOG_SOURCE}] Loop cancelled`, { sessionID, iteration: state2.iteration });
36603
36838
  }
36604
36839
  return success3;
@@ -36607,26 +36842,48 @@ function isLoopActive(directory, sessionID) {
36607
36842
  const state2 = readLoopState(directory);
36608
36843
  return state2?.active === true && state2?.sessionID === sessionID;
36609
36844
  }
36610
- function generateMissionContinuationPrompt(state2, verificationSummary) {
36611
- const summaryHeader = verificationSummary ? `
36612
- [Verification Status]: ${verificationSummary}
36613
- ` : "";
36845
+ function generateMissionContinuationPrompt(state2, input) {
36846
+ const context = normalizeContinuationContext(state2, input);
36614
36847
  let prompt = `${CONTINUE_INSTRUCTION}
36615
36848
 
36616
36849
  <mission_loop iteration="${state2.iteration}" max="${state2.maxIterations}">
36617
- \u26A0\uFE0F **MISSION NOT COMPLETE** - Iteration ${state2.iteration}/${state2.maxIterations}
36618
- ${summaryHeader}
36850
+ MISSION NOT COMPLETE
36851
+
36852
+ Objective:
36853
+ ${context.objective}
36619
36854
 
36620
- **Your Original Task**:
36621
- ${state2.prompt}
36855
+ Runtime status:
36856
+ - todo progress: ${context.progress}
36857
+ - verification: ${context.verification}
36858
+ - stagnation: ${context.stagnation}
36859
+ - continuation reason: ${context.reason}
36622
36860
 
36623
- **NOW**: Continue executing!
36861
+ Next action:
36862
+ 1. Read the current TODO, checklist, and sync issue state.
36863
+ 2. Execute or delegate only the next unblocked work.
36864
+ 3. Verify the result with real file reads, build commands, tests, or tool output.
36865
+ 4. Finish only when mission verification passes.
36866
+
36867
+ Completion rule:
36868
+ Do not declare success while TODO/checklist/sync verification is still failing.
36624
36869
  </mission_loop>`;
36625
36870
  if (state2.iteration > 1) {
36626
36871
  prompt += "\n" + CLEANUP_INSTRUCTION.replace("%ITER%", state2.iteration.toString());
36627
36872
  }
36628
36873
  return prompt;
36629
36874
  }
36875
+ function normalizeContinuationContext(state2, input) {
36876
+ const verificationSummary = typeof input === "string" ? input : input?.verificationSummary;
36877
+ const continuationReason = typeof input === "string" ? void 0 : input?.continuationReason;
36878
+ const stagnationCount = state2.stagnationCount ?? 0;
36879
+ return {
36880
+ objective: state2.objective || deriveObjective(state2.prompt),
36881
+ progress: state2.lastProgress ?? UNKNOWN_STATUS,
36882
+ verification: verificationSummary ?? state2.lastVerificationSummary ?? UNKNOWN_STATUS,
36883
+ reason: continuationReason ?? state2.lastContinuationReason ?? "verification_failed",
36884
+ stagnation: stagnationCount > 0 ? `${stagnationCount} unchanged check(s)` : "not detected"
36885
+ };
36886
+ }
36630
36887
 
36631
36888
  // src/core/orchestrator/session-manager.ts
36632
36889
  function ensureSessionInitialized(sessions, sessionID, directory) {
@@ -36638,6 +36895,7 @@ function ensureSessionInitialized(sessions, sessionID, directory) {
36638
36895
  timestamp: now,
36639
36896
  startTime: now,
36640
36897
  lastStepTime: now,
36898
+ lastCompletedMessageID: void 0,
36641
36899
  tokens: { totalInput: 0, totalOutput: 0, estimatedCost: 0 }
36642
36900
  };
36643
36901
  if (directory) {
@@ -36949,8 +37207,8 @@ ${commandList}`;
36949
37207
  // src/core/loop/verification.ts
36950
37208
  init_shared();
36951
37209
  init_logger();
36952
- import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
36953
- import { join as join5 } from "node:path";
37210
+ import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
37211
+ import { join as join7 } from "node:path";
36954
37212
  var CHECKLIST_FILE = CHECKLIST.FILE;
36955
37213
  function parseChecklistLine(line, currentCategory) {
36956
37214
  const trimmedLine = line.trim();
@@ -37015,12 +37273,12 @@ function parseChecklist(content) {
37015
37273
  return items;
37016
37274
  }
37017
37275
  function readChecklist(directory) {
37018
- const filePath = join5(directory, CHECKLIST_FILE);
37019
- if (!existsSync3(filePath)) {
37276
+ const filePath = join7(directory, CHECKLIST_FILE);
37277
+ if (!existsSync4(filePath)) {
37020
37278
  return [];
37021
37279
  }
37022
37280
  try {
37023
- const content = readFileSync2(filePath, "utf-8");
37281
+ const content = readFileSync3(filePath, "utf-8");
37024
37282
  return parseChecklist(content);
37025
37283
  } catch (error95) {
37026
37284
  log(`[checklist] Failed to read checklist: ${error95}`);
@@ -37037,8 +37295,8 @@ function verifyChecklist(directory) {
37037
37295
  incompleteList: [],
37038
37296
  errors: []
37039
37297
  };
37040
- const filePath = join5(directory, CHECKLIST_FILE);
37041
- if (!existsSync3(filePath)) {
37298
+ const filePath = join7(directory, CHECKLIST_FILE);
37299
+ if (!existsSync4(filePath)) {
37042
37300
  result.errors.push(`Verification checklist not found at ${CHECKLIST_FILE}`);
37043
37301
  result.errors.push("Create checklist with at least: build, tests, and any environment-specific checks");
37044
37302
  return result;
@@ -37114,10 +37372,10 @@ function verifyMissionCompletion(directory) {
37114
37372
  result.errors.push(` ... and ${checklistResult.incompleteList.length - 5} more`);
37115
37373
  }
37116
37374
  }
37117
- const todoPath = join5(directory, PATHS.TODO);
37118
- if (existsSync3(todoPath)) {
37375
+ const todoPath = join7(directory, PATHS.TODO);
37376
+ if (existsSync4(todoPath)) {
37119
37377
  try {
37120
- const content = readFileSync2(todoPath, "utf-8");
37378
+ const content = readFileSync3(todoPath, "utf-8");
37121
37379
  const incompleteCount = countMatches(content, TODO_INCOMPLETE_PATTERN);
37122
37380
  const completeCount = countMatches(content, TODO_COMPLETE_PATTERN);
37123
37381
  const total = incompleteCount + completeCount;
@@ -37139,10 +37397,10 @@ function verifyMissionCompletion(directory) {
37139
37397
  } else if (!hasChecklist) {
37140
37398
  result.errors.push(`TODO file not found at ${PATHS.TODO}`);
37141
37399
  }
37142
- const syncPath = join5(directory, PATHS.SYNC_ISSUES);
37143
- if (existsSync3(syncPath)) {
37400
+ const syncPath = join7(directory, PATHS.SYNC_ISSUES);
37401
+ if (existsSync4(syncPath)) {
37144
37402
  try {
37145
- const content = readFileSync2(syncPath, "utf-8");
37403
+ const content = readFileSync3(syncPath, "utf-8");
37146
37404
  result.syncIssuesEmpty = !hasRealSyncIssues(content);
37147
37405
  if (!result.syncIssuesEmpty) {
37148
37406
  const issueLines = content.split("\n").filter(
@@ -37230,7 +37488,7 @@ function buildVerificationSummary(result) {
37230
37488
  init_logger();
37231
37489
  import { exec as exec2 } from "node:child_process";
37232
37490
  import { promisify as promisify2 } from "node:util";
37233
- import { readFileSync as readFileSync3 } from "node:fs";
37491
+ import { readFileSync as readFileSync4 } from "node:fs";
37234
37492
 
37235
37493
  // src/shared/notification/os-notify/constants/notification-commands.ts
37236
37494
  var NOTIFICATION_COMMANDS = {
@@ -37284,10 +37542,10 @@ async function resolveCommandPath(key, commandName) {
37284
37542
  const currentPending = pending.get(key);
37285
37543
  if (currentPending) return currentPending;
37286
37544
  const promise3 = (async () => {
37287
- const path10 = await findCommand(commandName);
37288
- cache[key] = path10;
37545
+ const path11 = await findCommand(commandName);
37546
+ cache[key] = path11;
37289
37547
  pending.delete(key);
37290
- return path10;
37548
+ return path11;
37291
37549
  })();
37292
37550
  pending.set(key, promise3);
37293
37551
  return promise3;
@@ -37296,19 +37554,19 @@ async function resolveCommandPath(key, commandName) {
37296
37554
  // src/core/notification/os-notify/notifier.ts
37297
37555
  var execAsync2 = promisify2(exec2);
37298
37556
  async function notifyDarwin(title, message) {
37299
- const path10 = await resolveCommandPath(
37557
+ const path11 = await resolveCommandPath(
37300
37558
  NOTIFICATION_COMMAND_KEYS.OSASCRIPT,
37301
37559
  NOTIFICATION_COMMANDS.OSASCRIPT
37302
37560
  );
37303
- if (!path10) return;
37561
+ if (!path11) return;
37304
37562
  const escT = title.replace(/"/g, '\\"');
37305
37563
  const escM = message.replace(/"/g, '\\"');
37306
- await execAsync2(`${path10} -e 'display notification "${escM}" with title "${escT}" sound name "Glass"' >/dev/null 2>/dev/null`);
37564
+ await execAsync2(`${path11} -e 'display notification "${escM}" with title "${escT}" sound name "Glass"' >/dev/null 2>/dev/null`);
37307
37565
  }
37308
37566
  function isWSL() {
37309
37567
  try {
37310
37568
  if (process.env.WSL_DISTRO_NAME || process.env.WSLENV) return true;
37311
- const procVersion = readFileSync3("/proc/version", "utf-8");
37569
+ const procVersion = readFileSync4("/proc/version", "utf-8");
37312
37570
  return /microsoft|WSL/i.test(procVersion);
37313
37571
  } catch {
37314
37572
  return false;
@@ -37316,11 +37574,11 @@ function isWSL() {
37316
37574
  }
37317
37575
  async function notifyLinux(title, message) {
37318
37576
  if (isWSL()) return;
37319
- const path10 = await resolveCommandPath(
37577
+ const path11 = await resolveCommandPath(
37320
37578
  NOTIFICATION_COMMAND_KEYS.NOTIFY_SEND,
37321
37579
  NOTIFICATION_COMMANDS.NOTIFY_SEND
37322
37580
  );
37323
- if (path10) await execAsync2(`${path10} "${title}" "${message}" >/dev/null 2>/dev/null`);
37581
+ if (path11) await execAsync2(`${path11} "${title}" "${message}" >/dev/null 2>/dev/null`);
37324
37582
  }
37325
37583
  async function notifyWindows(title, message) {
37326
37584
  const ps = await resolveCommandPath(
@@ -37368,11 +37626,11 @@ init_os();
37368
37626
  async function playDarwin(soundPath) {
37369
37627
  if (!soundPath) return;
37370
37628
  try {
37371
- const path10 = await resolveCommandPath(
37629
+ const path11 = await resolveCommandPath(
37372
37630
  NOTIFICATION_COMMAND_KEYS.AFPLAY,
37373
37631
  NOTIFICATION_COMMANDS.AFPLAY
37374
37632
  );
37375
- if (path10) exec3(`"${path10}" "${soundPath}" >/dev/null 2>/dev/null`);
37633
+ if (path11) exec3(`"${path11}" "${soundPath}" >/dev/null 2>/dev/null`);
37376
37634
  } catch (err) {
37377
37635
  log(`[session-notify] Error playing sound (Darwin): ${err}`);
37378
37636
  }
@@ -38784,9 +39042,9 @@ import * as path6 from "node:path";
38784
39042
 
38785
39043
  // src/core/cache/utils.ts
38786
39044
  import * as fs6 from "node:fs/promises";
38787
- import { existsSync as existsSync5 } from "node:fs";
39045
+ import { existsSync as existsSync6 } from "node:fs";
38788
39046
  async function ensureCacheDir() {
38789
- if (!existsSync5(CACHE_DIR)) {
39047
+ if (!existsSync6(CACHE_DIR)) {
38790
39048
  await fs6.mkdir(CACHE_DIR, { recursive: true });
38791
39049
  }
38792
39050
  }
@@ -39288,15 +39546,15 @@ var backgroundTaskManager = BackgroundTaskManager.instance;
39288
39546
 
39289
39547
  // src/tools/rust-pool.ts
39290
39548
  import { spawn as spawn2 } from "child_process";
39291
- import { existsSync as existsSync8 } from "fs";
39549
+ import { existsSync as existsSync9 } from "fs";
39292
39550
 
39293
39551
  // src/utils/binary.ts
39294
39552
  init_shared();
39295
- import { join as join10, dirname as dirname4 } from "path";
39553
+ import { join as join12, dirname as dirname5 } from "path";
39296
39554
  import { fileURLToPath } from "url";
39297
39555
  import { platform, arch } from "os";
39298
- import { existsSync as existsSync7 } from "fs";
39299
- var __dirname = dirname4(fileURLToPath(import.meta.url));
39556
+ import { existsSync as existsSync8 } from "fs";
39557
+ var __dirname = dirname5(fileURLToPath(import.meta.url));
39300
39558
  function getPlatformBinaryName(os = platform(), cpu = arch()) {
39301
39559
  if (os === PLATFORM.WIN32) {
39302
39560
  return "orchestrator-windows-x64.exe";
@@ -39308,30 +39566,30 @@ function getPlatformBinaryName(os = platform(), cpu = arch()) {
39308
39566
  }
39309
39567
  function getCandidateBinDirs(moduleDir = __dirname) {
39310
39568
  return [
39311
- join10(moduleDir, "..", "bin"),
39312
- join10(moduleDir, "..", "..", "bin")
39569
+ join12(moduleDir, "..", "bin"),
39570
+ join12(moduleDir, "..", "..", "bin")
39313
39571
  ];
39314
39572
  }
39315
39573
  function resolveBinaryPath(options = {}) {
39316
39574
  const moduleDir = options.moduleDir ?? __dirname;
39317
39575
  const os = options.os ?? platform();
39318
39576
  const cpu = options.cpu ?? arch();
39319
- const exists = options.exists ?? existsSync7;
39577
+ const exists = options.exists ?? existsSync8;
39320
39578
  const binaryName = getPlatformBinaryName(os, cpu);
39321
39579
  for (const binDir of getCandidateBinDirs(moduleDir)) {
39322
- const binaryPath = join10(binDir, binaryName);
39580
+ const binaryPath = join12(binDir, binaryName);
39323
39581
  if (exists(binaryPath)) {
39324
39582
  return binaryPath;
39325
39583
  }
39326
39584
  }
39327
39585
  const fallbackName = os === PLATFORM.WIN32 ? "orchestrator.exe" : "orchestrator";
39328
39586
  for (const binDir of getCandidateBinDirs(moduleDir)) {
39329
- const fallbackPath = join10(binDir, fallbackName);
39587
+ const fallbackPath = join12(binDir, fallbackName);
39330
39588
  if (exists(fallbackPath)) {
39331
39589
  return fallbackPath;
39332
39590
  }
39333
39591
  }
39334
- return join10(getCandidateBinDirs(moduleDir)[0], binaryName);
39592
+ return join12(getCandidateBinDirs(moduleDir)[0], binaryName);
39335
39593
  }
39336
39594
  function getBinaryPath() {
39337
39595
  return resolveBinaryPath();
@@ -39345,10 +39603,21 @@ var RustToolPool = class {
39345
39603
  maxSize = 4;
39346
39604
  idleTimeout = 3e4;
39347
39605
  // 30 seconds
39606
+ processReadyDelay = 100;
39607
+ requestTimeout = 6e4;
39348
39608
  cleanupInterval = null;
39609
+ binaryPath;
39610
+ exists;
39611
+ spawnProcess;
39349
39612
  shuttingDown = false;
39350
- constructor(maxSize = 4) {
39613
+ constructor(maxSize = 4, options = {}) {
39351
39614
  this.maxSize = maxSize;
39615
+ this.binaryPath = options.binaryPath ?? getBinaryPath;
39616
+ this.exists = options.exists ?? existsSync9;
39617
+ this.idleTimeout = options.idleTimeoutMs ?? this.idleTimeout;
39618
+ this.processReadyDelay = options.processReadyDelayMs ?? this.processReadyDelay;
39619
+ this.requestTimeout = options.requestTimeoutMs ?? this.requestTimeout;
39620
+ this.spawnProcess = options.spawnProcess ?? spawn2;
39352
39621
  this.startCleanupTimer();
39353
39622
  }
39354
39623
  /**
@@ -39358,16 +39627,13 @@ var RustToolPool = class {
39358
39627
  if (this.shuttingDown) {
39359
39628
  throw new Error("Pool is shutting down");
39360
39629
  }
39361
- const binary = getBinaryPath();
39362
- if (!existsSync8(binary)) {
39630
+ const binary = this.binaryPath();
39631
+ if (!this.exists(binary)) {
39363
39632
  return JSON.stringify({ error: `Binary not found: ${binary}` });
39364
39633
  }
39365
39634
  let pooled = this.getAvailable();
39366
- if (!pooled && this.processes.length < this.maxSize) {
39367
- pooled = await this.createProcess(binary);
39368
- }
39369
39635
  if (!pooled) {
39370
- pooled = await this.waitForAvailable();
39636
+ pooled = await this.createOrWaitForProcess(binary);
39371
39637
  }
39372
39638
  try {
39373
39639
  return await this.sendRequest(pooled, name, args);
@@ -39382,15 +39648,29 @@ var RustToolPool = class {
39382
39648
  return this.processes.find((p) => !p.busy) || null;
39383
39649
  }
39384
39650
  /**
39385
- * Wait for a process to become available
39651
+ * Create a process immediately, or wait until one is available/capacity opens.
39386
39652
  */
39387
- async waitForAvailable() {
39388
- return new Promise((resolve) => {
39653
+ async createOrWaitForProcess(binary) {
39654
+ if (this.processes.length < this.maxSize) {
39655
+ return this.createProcess(binary);
39656
+ }
39657
+ return this.waitForAvailable(binary);
39658
+ }
39659
+ /**
39660
+ * Wait for a process to become available, or create one if capacity opens.
39661
+ */
39662
+ async waitForAvailable(binary) {
39663
+ return new Promise((resolve, reject) => {
39389
39664
  const interval = setInterval(() => {
39390
39665
  const available = this.getAvailable();
39391
39666
  if (available) {
39392
39667
  clearInterval(interval);
39393
39668
  resolve(available);
39669
+ return;
39670
+ }
39671
+ if (this.processes.length < this.maxSize) {
39672
+ clearInterval(interval);
39673
+ this.createProcess(binary).then(resolve, reject);
39394
39674
  }
39395
39675
  }, 10);
39396
39676
  });
@@ -39400,41 +39680,47 @@ var RustToolPool = class {
39400
39680
  */
39401
39681
  async createProcess(binary) {
39402
39682
  return new Promise((resolve, reject) => {
39403
- const proc = spawn2(binary, ["serve"], {
39683
+ const proc = this.spawnProcess(binary, ["serve"], {
39404
39684
  stdio: ["pipe", "pipe", "pipe"],
39405
39685
  detached: false
39406
39686
  });
39407
- let started = false;
39687
+ let startupSettled = false;
39688
+ let readyTimer = null;
39408
39689
  const pooled = {
39409
39690
  proc,
39410
- busy: false,
39691
+ busy: true,
39692
+ destroyed: false,
39411
39693
  lastUsed: Date.now(),
39412
39694
  requestId: 0,
39413
39695
  stdout: ""
39414
39696
  };
39415
- proc.stderr?.on("data", (data) => {
39416
- const msg = data.toString().trim();
39417
- if (msg && msg.includes("Listening")) {
39418
- started = true;
39697
+ const settleStartup = (callback) => {
39698
+ if (startupSettled) {
39699
+ return;
39419
39700
  }
39420
- });
39421
- proc.on("close", () => {
39422
- const index = this.processes.indexOf(pooled);
39423
- if (index !== -1) {
39424
- this.processes.splice(index, 1);
39701
+ startupSettled = true;
39702
+ if (readyTimer) {
39703
+ clearTimeout(readyTimer);
39704
+ readyTimer = null;
39425
39705
  }
39706
+ callback();
39707
+ };
39708
+ proc.on("close", () => {
39709
+ const error95 = new Error("Rust tool process closed before completing request");
39710
+ settleStartup(() => reject(error95));
39711
+ pooled.pendingReject?.(error95);
39712
+ this.removeProcess(pooled, false);
39426
39713
  });
39427
39714
  proc.on("error", (err) => {
39428
- const index = this.processes.indexOf(pooled);
39429
- if (index !== -1) {
39430
- this.processes.splice(index, 1);
39431
- }
39432
- if (!started) {
39433
- reject(err);
39434
- }
39715
+ const error95 = err instanceof Error ? err : new Error(String(err));
39716
+ settleStartup(() => reject(error95));
39717
+ pooled.pendingReject?.(error95);
39718
+ this.removeProcess(pooled, false);
39435
39719
  });
39436
39720
  this.processes.push(pooled);
39437
- setTimeout(() => resolve(pooled), 100);
39721
+ readyTimer = setTimeout(() => {
39722
+ settleStartup(() => resolve(pooled));
39723
+ }, this.processReadyDelay);
39438
39724
  });
39439
39725
  }
39440
39726
  /**
@@ -39444,13 +39730,39 @@ var RustToolPool = class {
39444
39730
  pooled.busy = true;
39445
39731
  pooled.lastUsed = Date.now();
39446
39732
  pooled.stdout = "";
39733
+ if (pooled.destroyed || !this.processes.includes(pooled)) {
39734
+ throw new Error("Rust tool process is unavailable");
39735
+ }
39447
39736
  return new Promise((resolve, reject) => {
39448
39737
  const requestId = ++pooled.requestId;
39738
+ let settled = false;
39739
+ const fail = (error95, kill) => {
39740
+ if (settled) {
39741
+ return;
39742
+ }
39743
+ settled = true;
39744
+ cleanup();
39745
+ this.removeProcess(pooled, kill);
39746
+ reject(error95);
39747
+ };
39748
+ const succeed = (text) => {
39749
+ if (settled) {
39750
+ return;
39751
+ }
39752
+ settled = true;
39753
+ cleanup();
39754
+ resolve(text);
39755
+ };
39449
39756
  const timeout = setTimeout(() => {
39757
+ fail(new Error("Request timeout"), true);
39758
+ }, this.requestTimeout);
39759
+ const cleanup = () => {
39760
+ clearTimeout(timeout);
39450
39761
  pooled.pendingResolve = void 0;
39451
39762
  pooled.pendingReject = void 0;
39452
- reject(new Error("Request timeout"));
39453
- }, 6e4);
39763
+ pooled.pendingCleanup = void 0;
39764
+ pooled.proc.stdout?.removeListener("data", onData);
39765
+ };
39454
39766
  const onData = (data) => {
39455
39767
  pooled.stdout += data.toString();
39456
39768
  const lines = pooled.stdout.trim().split("\n");
@@ -39458,10 +39770,8 @@ var RustToolPool = class {
39458
39770
  try {
39459
39771
  const response = JSON.parse(lines[i]);
39460
39772
  if (response.id === requestId && (response.result || response.error)) {
39461
- clearTimeout(timeout);
39462
- pooled.proc.stdout?.removeListener("data", onData);
39463
39773
  const text = response?.result?.content?.[0]?.text;
39464
- resolve(text || JSON.stringify(response.result));
39774
+ succeed(text || JSON.stringify(response.result));
39465
39775
  return;
39466
39776
  }
39467
39777
  } catch {
@@ -39469,6 +39779,8 @@ var RustToolPool = class {
39469
39779
  }
39470
39780
  }
39471
39781
  };
39782
+ pooled.pendingReject = (error95) => fail(error95, false);
39783
+ pooled.pendingCleanup = cleanup;
39472
39784
  pooled.proc.stdout?.on("data", onData);
39473
39785
  const request = JSON.stringify({
39474
39786
  jsonrpc: "2.0",
@@ -39477,11 +39789,13 @@ var RustToolPool = class {
39477
39789
  params: { name, arguments: args }
39478
39790
  });
39479
39791
  try {
39480
- pooled.proc.stdin?.write(request + "\n");
39792
+ const written = pooled.proc.stdin?.write(request + "\n");
39793
+ if (written === false || written === void 0) {
39794
+ fail(new Error("Failed to write request to Rust tool process"), true);
39795
+ }
39481
39796
  } catch (err) {
39482
- clearTimeout(timeout);
39483
- pooled.proc.stdout?.removeListener("data", onData);
39484
- reject(err);
39797
+ const error95 = err instanceof Error ? err : new Error(String(err));
39798
+ fail(error95, true);
39485
39799
  }
39486
39800
  });
39487
39801
  }
@@ -39489,9 +39803,29 @@ var RustToolPool = class {
39489
39803
  * Release a process back to the pool
39490
39804
  */
39491
39805
  release(pooled) {
39806
+ if (pooled.destroyed || !this.processes.includes(pooled)) {
39807
+ return;
39808
+ }
39492
39809
  pooled.busy = false;
39493
39810
  pooled.lastUsed = Date.now();
39494
39811
  }
39812
+ /**
39813
+ * Remove a process from the pool, optionally terminating it first.
39814
+ */
39815
+ removeProcess(pooled, kill) {
39816
+ pooled.destroyed = true;
39817
+ pooled.pendingCleanup?.();
39818
+ if (kill) {
39819
+ try {
39820
+ pooled.proc.kill();
39821
+ } catch {
39822
+ }
39823
+ }
39824
+ const index = this.processes.indexOf(pooled);
39825
+ if (index !== -1) {
39826
+ this.processes.splice(index, 1);
39827
+ }
39828
+ }
39495
39829
  /**
39496
39830
  * Start cleanup timer for idle processes
39497
39831
  */
@@ -39505,14 +39839,7 @@ var RustToolPool = class {
39505
39839
  }
39506
39840
  }
39507
39841
  for (const pooled of toRemove) {
39508
- try {
39509
- pooled.proc.kill();
39510
- } catch {
39511
- }
39512
- const index = this.processes.indexOf(pooled);
39513
- if (index !== -1) {
39514
- this.processes.splice(index, 1);
39515
- }
39842
+ this.removeProcess(pooled, true);
39516
39843
  }
39517
39844
  if (toRemove.length > 0) {
39518
39845
  log(`[${LOG_PREFIX.RUST_POOL}] Cleaned up ${toRemove.length} idle processes`);
@@ -39529,11 +39856,8 @@ var RustToolPool = class {
39529
39856
  clearInterval(this.cleanupInterval);
39530
39857
  this.cleanupInterval = null;
39531
39858
  }
39532
- for (const pooled of this.processes) {
39533
- try {
39534
- pooled.proc.kill();
39535
- } catch {
39536
- }
39859
+ for (const pooled of [...this.processes]) {
39860
+ this.removeProcess(pooled, true);
39537
39861
  }
39538
39862
  this.processes = [];
39539
39863
  log(`[${LOG_PREFIX.RUST_POOL}] Shutdown complete`);
@@ -39551,18 +39875,39 @@ var RustToolPool = class {
39551
39875
  }
39552
39876
  };
39553
39877
  var globalPool = null;
39878
+ var resetInFlight = null;
39554
39879
  function getRustToolPool() {
39555
39880
  if (!globalPool) {
39556
39881
  globalPool = new RustToolPool();
39557
39882
  }
39558
39883
  return globalPool;
39559
39884
  }
39560
- async function shutdownRustToolPool() {
39561
- if (globalPool) {
39562
- await globalPool.shutdown();
39885
+ async function resetRustToolPool(reason = "manual reset", expectedPool) {
39886
+ while (resetInFlight) {
39887
+ await resetInFlight;
39888
+ }
39889
+ const poolToReset = globalPool;
39890
+ if (!poolToReset) {
39891
+ return;
39892
+ }
39893
+ if (expectedPool && poolToReset !== expectedPool) {
39894
+ log(`[${LOG_PREFIX.RUST_POOL}] Skipped reset for stale pool: ${reason}`);
39895
+ return;
39896
+ }
39897
+ resetInFlight = (async () => {
39563
39898
  globalPool = null;
39899
+ log(`[${LOG_PREFIX.RUST_POOL}] Resetting global pool: ${reason}`);
39900
+ await poolToReset.shutdown();
39901
+ })();
39902
+ try {
39903
+ await resetInFlight;
39904
+ } finally {
39905
+ resetInFlight = null;
39564
39906
  }
39565
39907
  }
39908
+ async function shutdownRustToolPool() {
39909
+ await resetRustToolPool("shutdown");
39910
+ }
39566
39911
 
39567
39912
  // src/tools/callAgent.ts
39568
39913
  init_shared();
@@ -39631,13 +39976,15 @@ ${PROMPT_TAGS.EXECUTION.close}
39631
39976
  init_logger();
39632
39977
  init_shared();
39633
39978
  async function callRustTool(name, args) {
39979
+ const pool = getRustToolPool();
39634
39980
  try {
39635
- const pool = getRustToolPool();
39636
39981
  return await pool.call(name, args);
39637
39982
  } catch (err) {
39638
- log(`[${LOG_PREFIX.RUST_TOOL}] Pool error: ${err}`);
39639
- throw err;
39983
+ log(`[${LOG_PREFIX.RUST_TOOL}] Pool error, resetting and retrying once: ${err}`);
39984
+ await resetRustToolPool(`transport error while calling ${name}`, pool);
39640
39985
  }
39986
+ const retryPool = getRustToolPool();
39987
+ return retryPool.call(name, args);
39641
39988
  }
39642
39989
 
39643
39990
  // src/tools/search.ts
@@ -40783,6 +41130,92 @@ function registerAllTools(directory, asyncAgentTools, dynamicTools) {
40783
41130
  // src/index.ts
40784
41131
  init_shared();
40785
41132
 
41133
+ // src/core/agents/concurrency-config.ts
41134
+ var CONCURRENCY_KEYS = [
41135
+ "defaultConcurrency",
41136
+ "agentConcurrency",
41137
+ "providerConcurrency",
41138
+ "modelConcurrency"
41139
+ ];
41140
+ function isRecord(value) {
41141
+ return typeof value === "object" && value !== null && !Array.isArray(value);
41142
+ }
41143
+ function readLimitMap(value) {
41144
+ if (!isRecord(value)) return void 0;
41145
+ const result = {};
41146
+ for (const [key, limit] of Object.entries(value)) {
41147
+ if (typeof limit === "number" && Number.isFinite(limit) && limit >= 0) {
41148
+ result[key] = limit;
41149
+ }
41150
+ }
41151
+ return Object.keys(result).length > 0 ? result : void 0;
41152
+ }
41153
+ function extractConcurrencyConfig(source) {
41154
+ if (!isRecord(source)) return {};
41155
+ const config3 = {};
41156
+ if (typeof source.defaultConcurrency === "number" && source.defaultConcurrency >= 0) {
41157
+ config3.defaultConcurrency = source.defaultConcurrency;
41158
+ }
41159
+ const agentConcurrency = readLimitMap(source.agentConcurrency);
41160
+ if (agentConcurrency) config3.agentConcurrency = agentConcurrency;
41161
+ const providerConcurrency = readLimitMap(source.providerConcurrency);
41162
+ if (providerConcurrency) config3.providerConcurrency = providerConcurrency;
41163
+ const modelConcurrency = readLimitMap(source.modelConcurrency);
41164
+ if (modelConcurrency) config3.modelConcurrency = modelConcurrency;
41165
+ return config3;
41166
+ }
41167
+ function hasConcurrencyConfig(source) {
41168
+ if (!isRecord(source)) return false;
41169
+ return CONCURRENCY_KEYS.some((key) => source[key] !== void 0);
41170
+ }
41171
+ function mergeConcurrencyConfig(base, override) {
41172
+ return {
41173
+ ...base,
41174
+ ...override,
41175
+ agentConcurrency: {
41176
+ ...base.agentConcurrency,
41177
+ ...override.agentConcurrency
41178
+ },
41179
+ providerConcurrency: {
41180
+ ...base.providerConcurrency,
41181
+ ...override.providerConcurrency
41182
+ },
41183
+ modelConcurrency: {
41184
+ ...base.modelConcurrency,
41185
+ ...override.modelConcurrency
41186
+ }
41187
+ };
41188
+ }
41189
+
41190
+ // src/core/config/plugin-options.ts
41191
+ function parseOrchestratorPluginOptions(options) {
41192
+ const source = isRecord2(options) ? options : {};
41193
+ return {
41194
+ concurrency: extractConcurrencyConfig(source),
41195
+ missionLoop: readMissionLoopOptions(source.missionLoop)
41196
+ };
41197
+ }
41198
+ function readMissionLoopOptions(value) {
41199
+ if (!isRecord2(value)) return DEFAULT_MISSION_RUNTIME_OPTIONS;
41200
+ return {
41201
+ ledger: readBoolean(value.ledger, DEFAULT_MISSION_RUNTIME_OPTIONS.ledger),
41202
+ markdownMemory: readBoolean(value.markdownMemory, DEFAULT_MISSION_RUNTIME_OPTIONS.markdownMemory),
41203
+ maxEvidenceEvents: readPositiveInteger(
41204
+ value.maxEvidenceEvents,
41205
+ DEFAULT_MISSION_RUNTIME_OPTIONS.maxEvidenceEvents
41206
+ )
41207
+ };
41208
+ }
41209
+ function readBoolean(value, fallback) {
41210
+ return typeof value === "boolean" ? value : fallback;
41211
+ }
41212
+ function readPositiveInteger(value, fallback) {
41213
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : fallback;
41214
+ }
41215
+ function isRecord2(value) {
41216
+ return typeof value === "object" && value !== null && !Array.isArray(value);
41217
+ }
41218
+
40786
41219
  // src/plugin-handlers/tool-execute-pre-handler.ts
40787
41220
  init_logger();
40788
41221
  function createToolExecuteBeforeHandler(ctx) {
@@ -40894,8 +41327,41 @@ This plugin runs in "Claude Code Compatibility Mode".
40894
41327
  }
40895
41328
 
40896
41329
  // src/plugin-handlers/config-handler.ts
40897
- function createConfigHandler() {
41330
+ function isRecord3(value) {
41331
+ return typeof value === "object" && value !== null && !Array.isArray(value);
41332
+ }
41333
+ function isPermissionAction(value) {
41334
+ return value === "ask" || value === "allow" || value === "deny";
41335
+ }
41336
+ function mergePermission(globalPermission, agentPermission) {
41337
+ if (agentPermission === void 0) {
41338
+ return globalPermission;
41339
+ }
41340
+ if (isRecord3(globalPermission) && isRecord3(agentPermission)) {
41341
+ return { ...globalPermission, ...agentPermission };
41342
+ }
41343
+ if (isPermissionAction(globalPermission) && isRecord3(agentPermission)) {
41344
+ return { "*": globalPermission, ...agentPermission };
41345
+ }
41346
+ return agentPermission;
41347
+ }
41348
+ function defineAgent(existing, defaults, globalPermission) {
41349
+ const permission = mergePermission(globalPermission, existing?.permission);
41350
+ const agent = {
41351
+ ...existing,
41352
+ ...defaults
41353
+ };
41354
+ if (permission !== void 0) {
41355
+ agent.permission = permission;
41356
+ }
41357
+ return agent;
41358
+ }
41359
+ function createConfigHandler(options = {}) {
40898
41360
  return async (config3) => {
41361
+ const mutableConfig = config3;
41362
+ if (hasConcurrencyConfig(config3)) {
41363
+ options.onConcurrencyConfig?.(extractConcurrencyConfig(config3));
41364
+ }
40899
41365
  const claudeRules = findClaudeRules();
40900
41366
  const injectRules = (prompt) => {
40901
41367
  if (!claudeRules) return prompt;
@@ -40907,8 +41373,9 @@ ${claudeRules}`;
40907
41373
  const plannerPrompt = injectRules(AGENTS[AGENT_NAMES.PLANNER]?.systemPrompt || "");
40908
41374
  const workerPrompt = injectRules(AGENTS[AGENT_NAMES.WORKER]?.systemPrompt || "");
40909
41375
  const reviewerPrompt = injectRules(AGENTS[AGENT_NAMES.REVIEWER]?.systemPrompt || "");
40910
- const existingCommands = config3.command ?? {};
40911
- const existingAgents = config3.agent ?? {};
41376
+ const existingCommands = mutableConfig.command ?? {};
41377
+ const existingAgents = mutableConfig.agent ?? {};
41378
+ const globalPermission = mutableConfig.permission;
40912
41379
  const orchestratorCommands = {};
40913
41380
  for (const [name, cmd] of Object.entries(COMMANDS)) {
40914
41381
  orchestratorCommands[name] = {
@@ -40919,39 +41386,34 @@ ${claudeRules}`;
40919
41386
  }
40920
41387
  const orchestratorAgents = {
40921
41388
  // Primary agent - the main orchestrator
40922
- [AGENT_NAMES.COMMANDER]: {
41389
+ [AGENT_NAMES.COMMANDER]: defineAgent(existingAgents[AGENT_NAMES.COMMANDER], {
40923
41390
  description: "Autonomous orchestrator - executes until mission complete",
40924
41391
  mode: "primary",
40925
41392
  prompt: commanderPrompt,
40926
- maxTokens: AGENT_TOKENS.PRIMARY_MAX_TOKENS,
40927
- thinking: { type: "enabled", budgetTokens: AGENT_TOKENS.PRIMARY_THINKING_BUDGET },
40928
41393
  color: "#ffea98"
40929
- },
40930
- // Subagents (5 total)
40931
- [AGENT_NAMES.PLANNER]: {
41394
+ }, globalPermission),
41395
+ // Subagents
41396
+ [AGENT_NAMES.PLANNER]: defineAgent(existingAgents[AGENT_NAMES.PLANNER], {
40932
41397
  description: "Strategic planning and research specialist",
40933
41398
  mode: "subagent",
40934
41399
  hidden: true,
40935
41400
  prompt: plannerPrompt,
40936
- maxTokens: AGENT_TOKENS.SUBAGENT_MAX_TOKENS,
40937
41401
  color: "#9B59B6"
40938
- },
40939
- [AGENT_NAMES.WORKER]: {
41402
+ }, globalPermission),
41403
+ [AGENT_NAMES.WORKER]: defineAgent(existingAgents[AGENT_NAMES.WORKER], {
40940
41404
  description: "Implementation and documentation specialist",
40941
41405
  mode: "subagent",
40942
41406
  hidden: true,
40943
41407
  prompt: workerPrompt,
40944
- maxTokens: AGENT_TOKENS.SUBAGENT_MAX_TOKENS,
40945
41408
  color: "#E67E22"
40946
- },
40947
- [AGENT_NAMES.REVIEWER]: {
41409
+ }, globalPermission),
41410
+ [AGENT_NAMES.REVIEWER]: defineAgent(existingAgents[AGENT_NAMES.REVIEWER], {
40948
41411
  description: "Module-level verification specialist",
40949
41412
  mode: "subagent",
40950
41413
  hidden: true,
40951
41414
  prompt: reviewerPrompt,
40952
- maxTokens: AGENT_TOKENS.SUBAGENT_MAX_TOKENS,
40953
41415
  color: "#27AE60"
40954
- }
41416
+ }, globalPermission)
40955
41417
  };
40956
41418
  const processedExistingAgents = { ...existingAgents };
40957
41419
  if (processedExistingAgents.build) {
@@ -40967,9 +41429,9 @@ ${claudeRules}`;
40967
41429
  mode: "subagent"
40968
41430
  };
40969
41431
  }
40970
- config3.command = { ...existingCommands, ...orchestratorCommands };
40971
- config3.agent = { ...processedExistingAgents, ...orchestratorAgents };
40972
- config3.default_agent = AGENT_NAMES.COMMANDER;
41432
+ mutableConfig.command = { ...existingCommands, ...orchestratorCommands };
41433
+ mutableConfig.agent = { ...processedExistingAgents, ...orchestratorAgents };
41434
+ mutableConfig.default_agent = AGENT_NAMES.COMMANDER;
40973
41435
  };
40974
41436
  }
40975
41437
 
@@ -41427,7 +41889,11 @@ async function injectContinuation2(client, directory, sessionID, loopState, cust
41427
41889
  return;
41428
41890
  }
41429
41891
  const summary = buildVerificationSummary(verification);
41430
- let prompt = generateMissionContinuationPrompt(loopState, summary);
41892
+ const continuationReason = customPrompt ? "stagnation_intervention" : loopState.lastContinuationReason;
41893
+ let prompt = generateMissionContinuationPrompt(loopState, {
41894
+ verificationSummary: summary,
41895
+ continuationReason
41896
+ });
41431
41897
  if (customPrompt) {
41432
41898
  prompt = `${customPrompt}
41433
41899
 
@@ -41440,12 +41906,35 @@ ${prompt}`;
41440
41906
  parts: [{ type: PART_TYPES.TEXT, text: prompt }]
41441
41907
  }
41442
41908
  });
41909
+ appendMissionLedgerEvent(directory, {
41910
+ type: "prompt_injected",
41911
+ sessionID,
41912
+ iteration: loopState.iteration,
41913
+ objective: loopState.objective,
41914
+ summary,
41915
+ reason: continuationReason
41916
+ });
41917
+ syncMissionMemory(directory, loopState);
41443
41918
  markInjectionPerformed(sessionID);
41444
41919
  } catch (err) {
41445
41920
  log("[mission-loop-handler] Failed to inject continuation prompt", { sessionID, error: err });
41446
41921
  }
41447
41922
  }
41448
41923
  async function handleMissionComplete(client, directory, loopState) {
41924
+ const completedState = {
41925
+ ...loopState,
41926
+ active: false,
41927
+ lastVerificationSummary: "Mission verification passed",
41928
+ lastContinuationReason: "mission_completed"
41929
+ };
41930
+ appendMissionLedgerEvent(directory, {
41931
+ type: "mission_completed",
41932
+ sessionID: loopState.sessionID,
41933
+ iteration: loopState.iteration,
41934
+ objective: loopState.objective,
41935
+ summary: "Mission verification passed"
41936
+ });
41937
+ syncMissionMemory(directory, completedState);
41449
41938
  const cleared = clearLoopState(directory);
41450
41939
  if (cleared) {
41451
41940
  await showCompletedToast(client, loopState);
@@ -41498,6 +41987,20 @@ async function handleMissionIdle(client, directory, sessionID, mainSessionID) {
41498
41987
  return;
41499
41988
  }
41500
41989
  if (shouldTripCircuit(sessionID)) {
41990
+ const verificationSummary2 = buildVerificationSummary(verification);
41991
+ appendMissionLedgerEvent(directory, {
41992
+ type: "circuit_open",
41993
+ sessionID,
41994
+ iteration: loopState.iteration,
41995
+ objective: loopState.objective,
41996
+ summary: verificationSummary2,
41997
+ reason: "stagnation_threshold"
41998
+ });
41999
+ syncMissionMemory(directory, {
42000
+ ...loopState,
42001
+ lastVerificationSummary: verificationSummary2,
42002
+ lastContinuationReason: "circuit_open"
42003
+ });
41501
42004
  log(`[${MISSION_CONTROL.LOG_SOURCE}-handler] Circuit breaker tripped for ${sessionID}`);
41502
42005
  return;
41503
42006
  }
@@ -41512,8 +42015,29 @@ async function handleMissionIdle(client, directory, sessionID, mainSessionID) {
41512
42015
  const stagnant = isStagnant(sessionID, DEFAULT_STAGNATION_THRESHOLD);
41513
42016
  const newState = incrementIteration(directory);
41514
42017
  if (!newState) return;
42018
+ const verificationSummary = buildVerificationSummary(verification);
41515
42019
  newState.lastProgress = currentProgress;
42020
+ newState.stagnationCount = stagnant ? (newState.stagnationCount ?? 0) + 1 : 0;
42021
+ newState.lastVerificationSummary = verificationSummary;
42022
+ newState.lastContinuationReason = stagnant ? "stagnation_intervention" : "verification_failed";
42023
+ newState.lastContinuationAt = (/* @__PURE__ */ new Date()).toISOString();
41516
42024
  writeLoopState(directory, newState);
42025
+ appendMissionLedgerEvent(directory, {
42026
+ type: "verification_failed",
42027
+ sessionID,
42028
+ iteration: newState.iteration,
42029
+ objective: newState.objective,
42030
+ summary: verificationSummary
42031
+ });
42032
+ appendMissionLedgerEvent(directory, {
42033
+ type: "continuation_scheduled",
42034
+ sessionID,
42035
+ iteration: newState.iteration,
42036
+ objective: newState.objective,
42037
+ summary: verificationSummary,
42038
+ reason: newState.lastContinuationReason
42039
+ });
42040
+ syncMissionMemory(directory, newState);
41517
42041
  await showCountdownToast2(client, MISSION_CONTROL.DEFAULT_COUNTDOWN_SECONDS, newState.iteration, newState.maxIterations);
41518
42042
  state2.countdownTimer = setTimeout(async () => {
41519
42043
  sessionStateStore.cancelCountdown(sessionID);
@@ -41541,6 +42065,55 @@ function handleSessionCompacted(sessionID) {
41541
42065
 
41542
42066
  // src/plugin-handlers/event-handler.ts
41543
42067
  init_shared();
42068
+
42069
+ // src/plugin-handlers/assistant-done-handler.ts
42070
+ init_logger();
42071
+ init_shared();
42072
+ async function handleCompletedAssistantMessage(ctx, sessionID, messageID) {
42073
+ const { client, directory, sessions } = ctx;
42074
+ const hooks = HookRegistry.getInstance();
42075
+ const session = sessions.get(sessionID);
42076
+ if (!session?.active || session.lastCompletedMessageID === messageID) {
42077
+ return;
42078
+ }
42079
+ const textContent = await readAssistantText(client, sessionID, messageID);
42080
+ session.lastCompletedMessageID = messageID;
42081
+ const result = await hooks.executeDone(
42082
+ { sessionID, directory, sessions },
42083
+ textContent
42084
+ );
42085
+ if (result.action !== "inject" || result.prompts.length === 0) {
42086
+ return;
42087
+ }
42088
+ const now = Date.now();
42089
+ session.step++;
42090
+ session.timestamp = now;
42091
+ session.lastStepTime = now;
42092
+ try {
42093
+ const parts = result.prompts.map((text) => ({ type: PART_TYPES.TEXT, text }));
42094
+ client.session.prompt({
42095
+ path: { id: sessionID },
42096
+ body: { parts }
42097
+ }).catch((error95) => {
42098
+ log("[assistant-done-handler] Failed to inject continuation prompts", { sessionID, error: error95 });
42099
+ });
42100
+ } catch (error95) {
42101
+ log("[assistant-done-handler] Failed to inject continuation prompts", { sessionID, error: error95 });
42102
+ }
42103
+ }
42104
+ async function readAssistantText(client, sessionID, messageID) {
42105
+ try {
42106
+ const response = await client.session.message({
42107
+ path: { id: sessionID, messageID }
42108
+ });
42109
+ return (response.parts ?? []).filter((part) => part.type === PART_TYPES.TEXT || part.type === PART_TYPES.REASONING).map((part) => part.text ?? "").join("\n");
42110
+ } catch (error95) {
42111
+ log("[assistant-done-handler] Failed to read assistant message", { sessionID, messageID, error: error95 });
42112
+ return "";
42113
+ }
42114
+ }
42115
+
42116
+ // src/plugin-handlers/event-handler.ts
41544
42117
  function createEventHandler(ctx) {
41545
42118
  const { client, directory, sessions, state: state2 } = ctx;
41546
42119
  return async (input) => {
@@ -41591,7 +42164,7 @@ function createEventHandler(ctx) {
41591
42164
  if (event.type === MESSAGE_EVENTS.UPDATED) {
41592
42165
  const messageProperties = event.properties;
41593
42166
  const messageInfo = messageProperties?.info;
41594
- const sessionID = messageInfo?.sessionID;
42167
+ const sessionID = messageProperties.sessionID || messageInfo?.sessionID;
41595
42168
  const role = messageInfo?.role;
41596
42169
  if (sessionID && messageProperties?.usage) {
41597
42170
  const totalTokens = messageProperties.usage.totalTokens ?? (messageProperties.usage.inputTokens ?? 0) + (messageProperties.usage.outputTokens ?? 0);
@@ -41601,6 +42174,9 @@ function createEventHandler(ctx) {
41601
42174
  }
41602
42175
  if (sessionID && role === MESSAGE_ROLES.ASSISTANT) {
41603
42176
  markRecoveryComplete(sessionID);
42177
+ if (messageInfo?.id && messageInfo.time?.completed) {
42178
+ await handleCompletedAssistantMessage(ctx, sessionID, messageInfo.id);
42179
+ }
41604
42180
  }
41605
42181
  if (sessionID && role === MESSAGE_ROLES.USER) {
41606
42182
  handleUserMessage(sessionID);
@@ -41682,53 +42258,6 @@ function createToolExecuteAfterHandler(ctx) {
41682
42258
  };
41683
42259
  }
41684
42260
 
41685
- // src/plugin-handlers/assistant-done-handler.ts
41686
- init_logger();
41687
- init_shared();
41688
- function createAssistantDoneHandler(ctx) {
41689
- const { client, directory, sessions } = ctx;
41690
- const hooks = HookRegistry.getInstance();
41691
- return async (assistantInput, assistantOutput) => {
41692
- const sessionID = assistantInput.sessionID;
41693
- const session = sessions.get(sessionID);
41694
- if (!session?.active) return;
41695
- const parts = assistantOutput.parts;
41696
- const textContent = parts?.filter((p) => p.type === PART_TYPES.TEXT || p.type === PART_TYPES.REASONING).map((p) => p.text || "").join("\n") || "";
41697
- const hookContext = {
41698
- sessionID,
41699
- directory,
41700
- sessions
41701
- // Cast because types might slightly differ in strict mode, but it's the same object
41702
- };
41703
- const result = await hooks.executeDone(hookContext, textContent);
41704
- if (result.action === "stop") {
41705
- return;
41706
- }
41707
- if (result.action === "inject" && result.prompts) {
41708
- const now = Date.now();
41709
- session.step++;
41710
- session.timestamp = now;
41711
- session.lastStepTime = now;
41712
- try {
41713
- if (client?.session?.prompt) {
41714
- const parts2 = result.prompts.map((p) => ({
41715
- type: PART_TYPES.TEXT,
41716
- text: p
41717
- }));
41718
- client.session.prompt({
41719
- path: { id: sessionID },
41720
- body: { parts: parts2 }
41721
- }).catch((error95) => {
41722
- log("[assistant-done-handler] Failed to inject continuation prompts", { sessionID, error: error95 });
41723
- });
41724
- }
41725
- } catch (error95) {
41726
- log("[assistant-done-handler] Failed to inject continuation prompts", { sessionID, error: error95 });
41727
- }
41728
- }
41729
- };
41730
- }
41731
-
41732
42261
  // src/plugin-handlers/session-compacting-handler.ts
41733
42262
  init_shared();
41734
42263
  function createSessionCompactingHandler(ctx) {
@@ -41767,6 +42296,9 @@ function buildMissionContext(loopState) {
41767
42296
  return `<mission_context>
41768
42297
  ACTIVE MISSION LOOP:
41769
42298
  - Status: Active (Iteration ${loopState.iteration}/${loopState.maxIterations})
42299
+ - Objective: ${loopState.objective ?? "Continue the active mission"}
42300
+ - Last Progress: ${loopState.lastProgress ?? "unknown"}
42301
+ - Last Verification: ${loopState.lastVerificationSummary ?? "unknown"}
41770
42302
  - Started: ${loopState.startedAt}
41771
42303
  - Original Task: ${loopState.prompt.slice(0, 500)}${loopState.prompt.length > 500 ? "..." : ""}
41772
42304
 
@@ -41805,6 +42337,564 @@ Wait for these tasks to complete before concluding the mission.
41805
42337
 
41806
42338
  // src/plugin-handlers/system-transform-handler.ts
41807
42339
  init_shared();
42340
+
42341
+ // src/core/knowledge/context-provider.ts
42342
+ import { existsSync as existsSync10, readFileSync as readFileSync6, readdirSync } from "node:fs";
42343
+ import path10 from "node:path";
42344
+
42345
+ // src/core/knowledge/graph-parser.ts
42346
+ var GraphParser = class _GraphParser {
42347
+ /** Heading marker used for the auto-generated backlinks section */
42348
+ static BACKLINKS_HEADING = "## \u{1F517} Backlinks";
42349
+ // Maps note name -> set of target note names it links to
42350
+ forwardLinks = /* @__PURE__ */ new Map();
42351
+ // Maps note name -> set of source note names that link to it
42352
+ backlinks = /* @__PURE__ */ new Map();
42353
+ // Maps note name -> file path
42354
+ noteToPath = /* @__PURE__ */ new Map();
42355
+ // Maps file path -> note name
42356
+ pathToNote = /* @__PURE__ */ new Map();
42357
+ /**
42358
+ * Resolve file path or relative link to a note name (basename without extension).
42359
+ */
42360
+ getNoteName(filePath) {
42361
+ const basename = filePath.split(/[/\\]/).pop() || "";
42362
+ const dotIdx = basename.lastIndexOf(".");
42363
+ return dotIdx !== -1 ? basename.slice(0, dotIdx) : basename;
42364
+ }
42365
+ /**
42366
+ * Parse content and extract all unique referenced target note names.
42367
+ */
42368
+ parseLinks(content) {
42369
+ const targets = [];
42370
+ const wikiRegex = /\[\[([^[\]|#]+)(?:\|[^[\]]+)?(?:#[^[\]]+)?\]\]/g;
42371
+ let match;
42372
+ while ((match = wikiRegex.exec(content)) !== null) {
42373
+ const target = match[1].trim();
42374
+ if (target && !targets.includes(target)) {
42375
+ targets.push(target);
42376
+ }
42377
+ }
42378
+ const mdLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
42379
+ while ((match = mdLinkRegex.exec(content)) !== null) {
42380
+ const url3 = match[2].trim();
42381
+ if (!url3.includes("://") && (url3.endsWith(".md") || url3.startsWith(".") || url3.startsWith("/"))) {
42382
+ const targetName = this.getNoteName(url3);
42383
+ if (targetName && !targets.includes(targetName)) {
42384
+ targets.push(targetName);
42385
+ }
42386
+ }
42387
+ }
42388
+ return targets;
42389
+ }
42390
+ /**
42391
+ * Index file and register its bi-directional links.
42392
+ */
42393
+ indexFile(filePath, content) {
42394
+ const sourceNote = this.getNoteName(filePath);
42395
+ this.noteToPath.set(sourceNote, filePath);
42396
+ this.pathToNote.set(filePath, sourceNote);
42397
+ this.clearIndexForNote(sourceNote);
42398
+ const targets = this.parseLinks(content);
42399
+ if (targets.length > 0) {
42400
+ const forwardSet = new Set(targets);
42401
+ this.forwardLinks.set(sourceNote, forwardSet);
42402
+ for (const target of targets) {
42403
+ let backSet = this.backlinks.get(target);
42404
+ if (!backSet) {
42405
+ backSet = /* @__PURE__ */ new Set();
42406
+ this.backlinks.set(target, backSet);
42407
+ }
42408
+ backSet.add(sourceNote);
42409
+ }
42410
+ }
42411
+ }
42412
+ /**
42413
+ * Retrieve backlinks for a note name or file path.
42414
+ */
42415
+ getBacklinks(noteOrPath) {
42416
+ const note = noteOrPath.includes("/") || noteOrPath.endsWith(".md") ? this.getNoteName(noteOrPath) : noteOrPath;
42417
+ const sources = this.backlinks.get(note);
42418
+ return sources ? Array.from(sources).sort() : [];
42419
+ }
42420
+ /**
42421
+ * Retrieve forward links for a note name or file path.
42422
+ */
42423
+ getForwardLinks(noteOrPath) {
42424
+ const note = noteOrPath.includes("/") || noteOrPath.endsWith(".md") ? this.getNoteName(noteOrPath) : noteOrPath;
42425
+ const targets = this.forwardLinks.get(note);
42426
+ return targets ? Array.from(targets).sort() : [];
42427
+ }
42428
+ /**
42429
+ * Synchronize the ## 🔗 Backlinks section in a file's content.
42430
+ */
42431
+ syncBacklinksSection(content, backlinksList) {
42432
+ const backlinksHeading = _GraphParser.BACKLINKS_HEADING;
42433
+ const headingRegex = new RegExp(`(?:\\r?\\n|^)${backlinksHeading}\\b[\\s\\S]*$`);
42434
+ let backlinksSectionContent = `
42435
+
42436
+ ${backlinksHeading}
42437
+
42438
+ `;
42439
+ if (backlinksList.length > 0) {
42440
+ backlinksSectionContent += backlinksList.map((b) => `- [[${b}]]`).join("\n");
42441
+ } else {
42442
+ backlinksSectionContent += "*(No backlinks found)*";
42443
+ }
42444
+ if (content.includes(backlinksHeading)) {
42445
+ return content.replace(headingRegex, backlinksSectionContent);
42446
+ } else {
42447
+ return content.trimEnd() + backlinksSectionContent;
42448
+ }
42449
+ }
42450
+ /**
42451
+ * Clear all indexes for a note.
42452
+ */
42453
+ clearIndexForNote(sourceNote) {
42454
+ const targets = this.forwardLinks.get(sourceNote);
42455
+ if (targets) {
42456
+ for (const target of targets) {
42457
+ const backSet = this.backlinks.get(target);
42458
+ if (backSet) {
42459
+ backSet.delete(sourceNote);
42460
+ if (backSet.size === 0) {
42461
+ this.backlinks.delete(target);
42462
+ }
42463
+ }
42464
+ }
42465
+ this.forwardLinks.delete(sourceNote);
42466
+ }
42467
+ }
42468
+ };
42469
+
42470
+ // src/core/knowledge/hybrid-search.ts
42471
+ var RRF_K = 60;
42472
+ var DEFAULT_MAX_RESULTS = 20;
42473
+ var BM25_K1 = 1.2;
42474
+ var BM25_B = 0.75;
42475
+ var GRAPH_HOP_DEPTH = 2;
42476
+ var HybridSearch = class {
42477
+ tagIndexer;
42478
+ graphParser;
42479
+ /** Stores indexed note content keyed by note name. */
42480
+ contentMap = /* @__PURE__ */ new Map();
42481
+ constructor(tagIndexer, graphParser) {
42482
+ this.tagIndexer = tagIndexer;
42483
+ this.graphParser = graphParser;
42484
+ }
42485
+ /**
42486
+ * Register note content for lexical search.
42487
+ * Must be called after TagIndexer.indexFile / GraphParser.indexFile.
42488
+ */
42489
+ indexContent(noteName, content) {
42490
+ this.contentMap.set(noteName, content.toLowerCase());
42491
+ }
42492
+ /**
42493
+ * Fuse lexical, tag, and graph rankings via RRF to produce a single list.
42494
+ */
42495
+ search(query, maxResults) {
42496
+ const limit = maxResults ?? DEFAULT_MAX_RESULTS;
42497
+ const terms = this.tokenize(query);
42498
+ if (terms.length === 0) return [];
42499
+ const lexicalRanked = this.lexicalSearch(terms);
42500
+ const tagRanked = this.tagSearch(terms);
42501
+ const graphRanked = this.graphSearch(terms);
42502
+ return this.fuseResults(lexicalRanked, tagRanked, graphRanked, limit);
42503
+ }
42504
+ /**
42505
+ * BM25-inspired term-frequency scoring across all indexed documents.
42506
+ * Approximates IDF via corpus size and document frequency.
42507
+ */
42508
+ lexicalSearch(terms) {
42509
+ const scores = /* @__PURE__ */ new Map();
42510
+ const corpusSize = this.contentMap.size;
42511
+ if (corpusSize === 0) return [];
42512
+ const avgLen = this.computeAverageLength();
42513
+ for (const term of terms) {
42514
+ const df = this.documentFrequency(term);
42515
+ const idf = Math.log((corpusSize - df + 0.5) / (df + 0.5) + 1);
42516
+ for (const [name, content] of this.contentMap) {
42517
+ const tf = this.countOccurrences(content, term);
42518
+ if (tf === 0) continue;
42519
+ const docLen = content.length;
42520
+ const tfNorm = tf * (BM25_K1 + 1) / (tf + BM25_K1 * (1 - BM25_B + BM25_B * (docLen / avgLen)));
42521
+ const prev = scores.get(name) ?? 0;
42522
+ scores.set(name, prev + idf * tfNorm);
42523
+ }
42524
+ }
42525
+ return this.sortByScore(scores);
42526
+ }
42527
+ /**
42528
+ * Match query terms against the tag index to find tagged notes.
42529
+ */
42530
+ tagSearch(terms) {
42531
+ const scores = /* @__PURE__ */ new Map();
42532
+ for (const term of terms) {
42533
+ const files = this.tagIndexer.getFilesWithTag(term);
42534
+ for (const file3 of files) {
42535
+ const noteName = this.graphParser.getNoteName(file3);
42536
+ const prev = scores.get(noteName) ?? 0;
42537
+ scores.set(noteName, prev + 1);
42538
+ }
42539
+ }
42540
+ return this.sortByScore(scores);
42541
+ }
42542
+ /**
42543
+ * 2-hop graph traversal from tag-matched seed notes to discover related notes.
42544
+ */
42545
+ graphSearch(terms) {
42546
+ const seeds = new Set(this.tagSearch(terms));
42547
+ const visited = /* @__PURE__ */ new Set();
42548
+ const scores = /* @__PURE__ */ new Map();
42549
+ for (const seed of seeds) {
42550
+ this.traverseGraph(seed, GRAPH_HOP_DEPTH, visited, scores);
42551
+ }
42552
+ return this.sortByScore(scores);
42553
+ }
42554
+ /**
42555
+ * Depth-limited BFS from a seed note, scoring neighbors by proximity.
42556
+ */
42557
+ traverseGraph(note, depth, visited, scores) {
42558
+ if (depth <= 0 || visited.has(note)) return;
42559
+ visited.add(note);
42560
+ const neighbors = [
42561
+ ...this.graphParser.getForwardLinks(note),
42562
+ ...this.graphParser.getBacklinks(note)
42563
+ ];
42564
+ for (const neighbor of neighbors) {
42565
+ const prev = scores.get(neighbor) ?? 0;
42566
+ scores.set(neighbor, prev + depth);
42567
+ this.traverseGraph(neighbor, depth - 1, visited, scores);
42568
+ }
42569
+ }
42570
+ /**
42571
+ * Reciprocal Rank Fusion: combine three ranked lists into a single ranking.
42572
+ * Formula: score(d) = Σ 1/(k + rank_i) for each list where d appears.
42573
+ */
42574
+ fuseResults(lexical, tags, graph, limit) {
42575
+ const fused = /* @__PURE__ */ new Map();
42576
+ this.addRrfScores(fused, lexical, "lexical");
42577
+ this.addRrfScores(fused, tags, "tag");
42578
+ this.addRrfScores(fused, graph, "graph");
42579
+ return Array.from(fused.entries()).map(([noteName, { score, matchType }]) => ({ noteName, score, matchType })).sort((a, b) => b.score - a.score).slice(0, limit);
42580
+ }
42581
+ /**
42582
+ * Accumulate RRF scores from a single ranked list into the fused map.
42583
+ * The matchType is set to the source with the highest individual contribution.
42584
+ */
42585
+ addRrfScores(fused, ranked, matchType) {
42586
+ for (let i = 0; i < ranked.length; i++) {
42587
+ const rrfScore = 1 / (RRF_K + i + 1);
42588
+ const existing = fused.get(ranked[i]);
42589
+ if (existing) {
42590
+ existing.score += rrfScore;
42591
+ if (rrfScore > 1 / (RRF_K + 1)) {
42592
+ existing.matchType = matchType;
42593
+ }
42594
+ } else {
42595
+ fused.set(ranked[i], { score: rrfScore, matchType });
42596
+ }
42597
+ }
42598
+ }
42599
+ /** Split query into lowercase tokens for matching. */
42600
+ tokenize(query) {
42601
+ return query.toLowerCase().split(/\s+/).filter(Boolean);
42602
+ }
42603
+ /** Count non-overlapping occurrences of a term in text. */
42604
+ countOccurrences(text, term) {
42605
+ let count = 0;
42606
+ let pos = 0;
42607
+ while ((pos = text.indexOf(term, pos)) !== -1) {
42608
+ count++;
42609
+ pos += term.length;
42610
+ }
42611
+ return count;
42612
+ }
42613
+ /** Average document length across the corpus (character-based). */
42614
+ computeAverageLength() {
42615
+ let total = 0;
42616
+ for (const content of this.contentMap.values()) {
42617
+ total += content.length;
42618
+ }
42619
+ return total / Math.max(this.contentMap.size, 1);
42620
+ }
42621
+ /** Number of documents containing the given term. */
42622
+ documentFrequency(term) {
42623
+ let count = 0;
42624
+ for (const content of this.contentMap.values()) {
42625
+ if (content.includes(term)) count++;
42626
+ }
42627
+ return count;
42628
+ }
42629
+ /** Sort entries by descending score and return the keys in order. */
42630
+ sortByScore(scores) {
42631
+ return Array.from(scores.entries()).sort((a, b) => b[1] - a[1]).map(([name]) => name);
42632
+ }
42633
+ };
42634
+
42635
+ // src/core/knowledge/tag-indexer.ts
42636
+ import { readFileSync as readFileSync5 } from "node:fs";
42637
+ var TagIndexer = class {
42638
+ tagMap = /* @__PURE__ */ new Map();
42639
+ fileCache = /* @__PURE__ */ new Map();
42640
+ /**
42641
+ * Parse frontmatter using regular expressions as a primary safe parser.
42642
+ * This avoids library dependencies and provides deterministic error recovery.
42643
+ */
42644
+ parseFrontmatter(content) {
42645
+ const data = {};
42646
+ const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---/;
42647
+ const match = content.match(frontmatterRegex);
42648
+ if (!match) {
42649
+ return { data, body: content };
42650
+ }
42651
+ const rawYaml = match[1];
42652
+ const body = content.replace(frontmatterRegex, "").trim();
42653
+ const lines = rawYaml.split(/\r?\n/);
42654
+ let activeKey = null;
42655
+ for (const line of lines) {
42656
+ activeKey = this.parseYamlLine(line, data, activeKey);
42657
+ }
42658
+ return { data, body };
42659
+ }
42660
+ /**
42661
+ * Parse a single YAML line and update data object in-place.
42662
+ * Returns the currently active key for block list continuation.
42663
+ */
42664
+ parseYamlLine(line, data, activeKey) {
42665
+ const trimmed = line.trim();
42666
+ if (!trimmed || trimmed.startsWith("#")) return activeKey;
42667
+ const colonIdx = trimmed.indexOf(":");
42668
+ if (colonIdx !== -1) {
42669
+ const key = trimmed.slice(0, colonIdx).trim();
42670
+ const val = trimmed.slice(colonIdx + 1).trim();
42671
+ if (val.startsWith("[") && val.endsWith("]")) {
42672
+ data[key] = val.slice(1, -1).split(",").map((s) => s.trim()).filter(Boolean);
42673
+ } else if (val) {
42674
+ data[key] = this.parseScalar(val);
42675
+ } else {
42676
+ data[key] = [];
42677
+ }
42678
+ return key;
42679
+ }
42680
+ if (trimmed.startsWith("-") && activeKey) {
42681
+ const listVal = trimmed.slice(1).trim();
42682
+ if (listVal) {
42683
+ const currentList = Array.isArray(data[activeKey]) ? data[activeKey] : [];
42684
+ currentList.push(listVal);
42685
+ data[activeKey] = currentList;
42686
+ }
42687
+ }
42688
+ return activeKey;
42689
+ }
42690
+ /**
42691
+ * Index a single markdown file content dynamically.
42692
+ */
42693
+ indexFile(filePath, fileContent) {
42694
+ this.clearIndexForFile(filePath);
42695
+ const { data } = this.parseFrontmatter(fileContent);
42696
+ this.fileCache.set(filePath, data);
42697
+ if (data.tags && Array.isArray(data.tags)) {
42698
+ for (const tag of data.tags) {
42699
+ if (typeof tag === "string") {
42700
+ this.addTagEntry(tag.toLowerCase(), filePath);
42701
+ }
42702
+ }
42703
+ }
42704
+ }
42705
+ /**
42706
+ * Index a file directly from the filesystem.
42707
+ */
42708
+ indexFileFromDisk(filePath) {
42709
+ try {
42710
+ const content = readFileSync5(filePath, "utf8");
42711
+ this.indexFile(filePath, content);
42712
+ } catch {
42713
+ this.clearIndexForFile(filePath);
42714
+ }
42715
+ }
42716
+ /**
42717
+ * Get all files associated with a specific tag O(1).
42718
+ */
42719
+ getFilesWithTag(tag) {
42720
+ return this.tagMap.get(tag.toLowerCase()) || /* @__PURE__ */ new Set();
42721
+ }
42722
+ /**
42723
+ * Get intersection of files containing all specified tags.
42724
+ */
42725
+ getFilesWithAllTags(tags) {
42726
+ if (tags.length === 0) return /* @__PURE__ */ new Set();
42727
+ let result = new Set(this.getFilesWithTag(tags[0]));
42728
+ for (let i = 1; i < tags.length; i++) {
42729
+ const currentSet = this.getFilesWithTag(tags[i]);
42730
+ result = new Set([...result].filter((x) => currentSet.has(x)));
42731
+ }
42732
+ return result;
42733
+ }
42734
+ /**
42735
+ * Get union of files containing any of the specified tags.
42736
+ */
42737
+ getFilesWithAnyTags(tags) {
42738
+ const result = /* @__PURE__ */ new Set();
42739
+ for (const tag of tags) {
42740
+ const files = this.getFilesWithTag(tag);
42741
+ for (const file3 of files) {
42742
+ result.add(file3);
42743
+ }
42744
+ }
42745
+ return result;
42746
+ }
42747
+ /**
42748
+ * Get the cached frontmatter metadata of a file.
42749
+ */
42750
+ getMetadata(filePath) {
42751
+ return this.fileCache.get(filePath);
42752
+ }
42753
+ /**
42754
+ * Return all file paths that have been indexed.
42755
+ */
42756
+ getIndexedFiles() {
42757
+ return Array.from(this.fileCache.keys());
42758
+ }
42759
+ /**
42760
+ * Return all distinct tags currently present across all indexed files.
42761
+ */
42762
+ getAllTags() {
42763
+ return Array.from(this.tagMap.keys());
42764
+ }
42765
+ /**
42766
+ * Remove file references cleanly from tag mappings and metadata cache.
42767
+ */
42768
+ clearIndexForFile(filePath) {
42769
+ this.fileCache.delete(filePath);
42770
+ for (const [tag, files] of this.tagMap.entries()) {
42771
+ if (files.has(filePath)) {
42772
+ files.delete(filePath);
42773
+ if (files.size === 0) {
42774
+ this.tagMap.delete(tag);
42775
+ }
42776
+ }
42777
+ }
42778
+ }
42779
+ /**
42780
+ * Helper to insert tags atomically.
42781
+ */
42782
+ addTagEntry(tag, filePath) {
42783
+ let files = this.tagMap.get(tag);
42784
+ if (!files) {
42785
+ files = /* @__PURE__ */ new Set();
42786
+ this.tagMap.set(tag, files);
42787
+ }
42788
+ files.add(filePath);
42789
+ }
42790
+ /**
42791
+ * Basic scalar value parser for YAML frontmatter fields.
42792
+ */
42793
+ parseScalar(val) {
42794
+ if (val === "true") return true;
42795
+ if (val === "false") return false;
42796
+ const num = Number(val);
42797
+ if (!isNaN(num)) return num;
42798
+ if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
42799
+ return val.slice(1, -1);
42800
+ }
42801
+ return val;
42802
+ }
42803
+ };
42804
+
42805
+ // src/core/knowledge/context-provider.ts
42806
+ var MAX_RESULTS = 3;
42807
+ var MAX_SNIPPET_CHARS = 220;
42808
+ var KNOWLEDGE_ROOTS = ["docs", path10.join(".opencode", "docs")];
42809
+ var SKIP_SEGMENTS = /* @__PURE__ */ new Set(["node_modules", "dist", "bin", ".git", "archive"]);
42810
+ var KnowledgeContextProvider = class {
42811
+ buildPrompt(directory, query) {
42812
+ const normalizedQuery = query.trim();
42813
+ if (!normalizedQuery) return null;
42814
+ const markdownFiles = this.collectMarkdownFiles(directory);
42815
+ if (markdownFiles.length === 0) return null;
42816
+ const indexed = this.indexKnowledge(directory, markdownFiles);
42817
+ const results = indexed.search.search(normalizedQuery, MAX_RESULTS);
42818
+ if (results.length === 0) return null;
42819
+ return this.formatPrompt(normalizedQuery, results, indexed);
42820
+ }
42821
+ collectMarkdownFiles(directory) {
42822
+ const files = [];
42823
+ for (const root of KNOWLEDGE_ROOTS) {
42824
+ const fullRoot = path10.join(directory, root);
42825
+ if (!existsSync10(fullRoot)) continue;
42826
+ files.push(...this.walkDirectory(fullRoot));
42827
+ }
42828
+ return files.sort();
42829
+ }
42830
+ walkDirectory(directory) {
42831
+ const files = [];
42832
+ for (const entry of readdirSync(directory, { withFileTypes: true })) {
42833
+ const fullPath = path10.join(directory, entry.name);
42834
+ if (entry.isDirectory()) {
42835
+ if (SKIP_SEGMENTS.has(entry.name)) continue;
42836
+ files.push(...this.walkDirectory(fullPath));
42837
+ continue;
42838
+ }
42839
+ if (entry.isFile() && entry.name.endsWith(".md")) {
42840
+ files.push(fullPath);
42841
+ }
42842
+ }
42843
+ return files;
42844
+ }
42845
+ indexKnowledge(directory, files) {
42846
+ const tagIndexer = new TagIndexer();
42847
+ const graphParser = new GraphParser();
42848
+ const search = new HybridSearch(tagIndexer, graphParser);
42849
+ const noteToPath = /* @__PURE__ */ new Map();
42850
+ const noteToSnippet = /* @__PURE__ */ new Map();
42851
+ for (const filePath of files) {
42852
+ try {
42853
+ const content = readFileSync6(filePath, "utf8");
42854
+ const noteName = graphParser.getNoteName(filePath);
42855
+ const { body } = tagIndexer.parseFrontmatter(content);
42856
+ const normalizedBody = body.trim();
42857
+ tagIndexer.indexFile(filePath, content);
42858
+ graphParser.indexFile(filePath, content);
42859
+ search.indexContent(noteName, normalizedBody);
42860
+ noteToPath.set(noteName, path10.relative(directory, filePath) || filePath);
42861
+ noteToSnippet.set(noteName, this.buildSnippet(normalizedBody));
42862
+ } catch {
42863
+ continue;
42864
+ }
42865
+ }
42866
+ return { search, noteToPath, noteToSnippet };
42867
+ }
42868
+ buildSnippet(content) {
42869
+ const normalized = content.replace(/\s+/g, " ").trim();
42870
+ if (normalized.length <= MAX_SNIPPET_CHARS) return normalized;
42871
+ return `${normalized.slice(0, MAX_SNIPPET_CHARS)}...`;
42872
+ }
42873
+ formatPrompt(query, results, indexed) {
42874
+ const lines = [
42875
+ "<knowledge_rag_context>",
42876
+ `Query: ${query}`,
42877
+ "Repository knowledge matches:",
42878
+ ""
42879
+ ];
42880
+ for (const [index, result] of results.entries()) {
42881
+ const filePath = indexed.noteToPath.get(result.noteName) ?? result.noteName;
42882
+ const snippet = indexed.noteToSnippet.get(result.noteName) ?? "";
42883
+ lines.push(`${index + 1}. ${result.noteName} [${result.matchType}]`);
42884
+ lines.push(` Source: ${filePath}`);
42885
+ if (snippet) {
42886
+ lines.push(` Snippet: ${snippet}`);
42887
+ }
42888
+ }
42889
+ lines.push("");
42890
+ lines.push("Use this as supplemental repository memory. Verify against source files before making claims.");
42891
+ lines.push("</knowledge_rag_context>");
42892
+ return lines.join("\n");
42893
+ }
42894
+ };
42895
+
42896
+ // src/plugin-handlers/system-transform-handler.ts
42897
+ var knowledgeContextProvider = new KnowledgeContextProvider();
41808
42898
  function createSystemTransformHandler(ctx) {
41809
42899
  const { directory, sessions, state: state2 } = ctx;
41810
42900
  return async (input, output) => {
@@ -41820,11 +42910,19 @@ function createSystemTransformHandler(ctx) {
41820
42910
  if (isActiveLoop && loopState) {
41821
42911
  const { commander: commander2 } = await Promise.resolve().then(() => (init_commander(), commander_exports));
41822
42912
  systemAdditions.push(commander2.systemPrompt);
41823
- systemAdditions.push(buildMissionLoopSystemPrompt(loopState.iteration, loopState.maxIterations));
42913
+ systemAdditions.push(buildMissionLoopSystemPrompt(loopState));
41824
42914
  }
41825
42915
  if (session?.active) {
41826
42916
  systemAdditions.push(buildActiveSessionPrompt(session.step));
41827
42917
  }
42918
+ const knowledgePrompt = buildKnowledgeContextPrompt(
42919
+ directory,
42920
+ loopState?.prompt,
42921
+ state2.sessions.get(sessionID)?.currentTask
42922
+ );
42923
+ if (knowledgePrompt) {
42924
+ systemAdditions.push(knowledgePrompt);
42925
+ }
41828
42926
  try {
41829
42927
  const manager = ParallelAgentManager.getInstance();
41830
42928
  const tasks = manager.getTasksByParent(sessionID);
@@ -41840,18 +42938,29 @@ function createSystemTransformHandler(ctx) {
41840
42938
  }
41841
42939
  };
41842
42940
  }
41843
- function buildMissionLoopSystemPrompt(iteration, maxIterations) {
42941
+ function buildKnowledgeContextPrompt(directory, missionPrompt, currentTask) {
42942
+ const queryParts = [missionPrompt ?? "", currentTask ?? ""].filter(Boolean);
42943
+ return knowledgeContextProvider.buildPrompt(directory, queryParts.join(" ").trim());
42944
+ }
42945
+ function buildMissionLoopSystemPrompt(loopState) {
41844
42946
  return `<orchestrator_mission_loop>
41845
- \u{1F3AF} MISSION LOOP ACTIVE: Iteration ${iteration}/${maxIterations}
42947
+ \u{1F3AF} MISSION LOOP ACTIVE: Iteration ${loopState.iteration}/${loopState.maxIterations}
41846
42948
 
41847
42949
  You are in an autonomous mission loop. Continue working until ALL tasks are verified and 100% complete.
41848
42950
 
42951
+ ACTIVE OBJECTIVE:
42952
+ ${loopState.objective ?? "Continue the active mission"}
42953
+
42954
+ RUNTIME MEMORY:
42955
+ - Last progress: ${loopState.lastProgress ?? "unknown"}
42956
+ - Last verification: ${loopState.lastVerificationSummary ?? "unknown"}
42957
+
41849
42958
  COMPLETION CRITERIA:
41850
42959
  - All hierarchical items in .opencode/todo.md are marked [x]
41851
42960
  - .opencode/verification-checklist.md is fully checked off [x]
41852
42961
  - All tests pass and builds succeed
41853
42962
 
41854
- DO NOT stop or ask for permission. Execute autonomously.
42963
+ Do not stop for routine permission or preference checks. Execute autonomously, and ask a concise clarification only when truly blocked and the OpenCode question permission allows it.
41855
42964
  </orchestrator_mission_loop>`;
41856
42965
  }
41857
42966
  function buildActiveSessionPrompt(stepCount) {
@@ -41876,13 +42985,16 @@ Use \`delegate_task\` with background=true for parallel work.
41876
42985
  // src/index.ts
41877
42986
  var require2 = createRequire(import.meta.url);
41878
42987
  var { version: PLUGIN_VERSION } = require2("../package.json");
41879
- var OrchestratorPlugin = async (input) => {
42988
+ var OrchestratorPlugin = async (input, options) => {
41880
42989
  const { directory, client } = input;
42990
+ const orchestratorOptions = parseOrchestratorPluginOptions(options);
42991
+ let concurrencyConfig = orchestratorOptions.concurrency;
42992
+ configureMissionRuntimeOptions(orchestratorOptions.missionLoop);
41881
42993
  initializeHooks();
41882
42994
  initToastClient(client);
41883
42995
  const taskToastManager = initTaskToastManager(client);
41884
42996
  const sessions = /* @__PURE__ */ new Map();
41885
- const parallelAgentManager2 = ParallelAgentManager.getInstance(client, directory);
42997
+ const parallelAgentManager2 = ParallelAgentManager.getInstance(client, directory, concurrencyConfig);
41886
42998
  const asyncAgentTools = createAsyncAgentTools(parallelAgentManager2, client);
41887
42999
  const pluginManager = PluginManager.getInstance();
41888
43000
  await pluginManager.initialize(directory);
@@ -41920,10 +43032,12 @@ var OrchestratorPlugin = async (input) => {
41920
43032
  // -----------------------------------------------------------------
41921
43033
  // Config hook - registers our commands and agents with OpenCode
41922
43034
  // -----------------------------------------------------------------
41923
- config: createConfigHandler(),
41924
- // -----------------------------------------------------------------
41925
- // Event hook - handles OpenCode events
41926
- // -----------------------------------------------------------------
43035
+ config: createConfigHandler({
43036
+ onConcurrencyConfig: (config3) => {
43037
+ concurrencyConfig = mergeConcurrencyConfig(concurrencyConfig, config3);
43038
+ parallelAgentManager2.configureConcurrency(concurrencyConfig);
43039
+ }
43040
+ }),
41927
43041
  // -----------------------------------------------------------------
41928
43042
  // Event hook - handles OpenCode events
41929
43043
  // -----------------------------------------------------------------
@@ -41945,27 +43059,23 @@ var OrchestratorPlugin = async (input) => {
41945
43059
  // -----------------------------------------------------------------
41946
43060
  // tool.execute.before hook - runs before any tool call
41947
43061
  // -----------------------------------------------------------------
41948
- "tool.execute.before": createToolExecuteBeforeHandler(handlerContext),
43062
+ [PLUGIN_HOOKS.TOOL_EXECUTE_BEFORE]: createToolExecuteBeforeHandler(handlerContext),
41949
43063
  // -----------------------------------------------------------------
41950
43064
  // tool.execute.after hook - runs after any tool call completes
41951
43065
  // -----------------------------------------------------------------
41952
43066
  [PLUGIN_HOOKS.TOOL_EXECUTE_AFTER]: createToolExecuteAfterHandler(handlerContext),
41953
43067
  // -----------------------------------------------------------------
41954
- // assistant.done hook - runs when the LLM finishes responding
41955
- // -----------------------------------------------------------------
41956
- [PLUGIN_HOOKS.ASSISTANT_DONE]: createAssistantDoneHandler(handlerContext),
41957
- // -----------------------------------------------------------------
41958
43068
  // experimental.session.compacting hook - preserves mission context during compaction
41959
43069
  // -----------------------------------------------------------------
41960
- "experimental.session.compacting": createSessionCompactingHandler(handlerContext),
43070
+ [PLUGIN_HOOKS.EXPERIMENTAL_SESSION_COMPACTING]: createSessionCompactingHandler(handlerContext),
41961
43071
  // -----------------------------------------------------------------
41962
43072
  // experimental.chat.system.transform hook - dynamic system prompt injection
41963
43073
  // -----------------------------------------------------------------
41964
- "experimental.chat.system.transform": createSystemTransformHandler(handlerContext),
43074
+ [PLUGIN_HOOKS.EXPERIMENTAL_CHAT_SYSTEM_TRANSFORM]: createSystemTransformHandler(handlerContext),
41965
43075
  // -----------------------------------------------------------------
41966
- // shutdown hook - cleanup resources on plugin unload
43076
+ // dispose hook - cleanup resources on plugin unload
41967
43077
  // -----------------------------------------------------------------
41968
- shutdown: async () => {
43078
+ dispose: async () => {
41969
43079
  await shutdownManager.shutdown();
41970
43080
  }
41971
43081
  };