muonroi-cli 1.8.4 → 1.9.0

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 (562) hide show
  1. package/LICENSE +17 -5
  2. package/dist/packages/agent-harness-core/src/driver.d.ts +27 -1
  3. package/dist/packages/agent-harness-core/src/driver.js +46 -0
  4. package/dist/packages/agent-harness-core/src/event-filter.js +11 -0
  5. package/dist/packages/agent-harness-core/src/event-redact.js +7 -0
  6. package/dist/packages/agent-harness-core/src/event-tee.d.ts +64 -0
  7. package/dist/packages/agent-harness-core/src/event-tee.js +104 -0
  8. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +25 -0
  9. package/dist/packages/agent-harness-core/src/mcp-server.js +169 -21
  10. package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
  11. package/dist/packages/agent-harness-core/src/protocol.d.ts +90 -4
  12. package/dist/packages/agent-harness-core/src/protocol.js +15 -0
  13. package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
  14. package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
  15. package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
  16. package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
  17. package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
  18. package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
  19. package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
  20. package/dist/packages/agent-harness-opentui/src/install.js +10 -0
  21. package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
  22. package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
  23. package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
  24. package/dist/src/agent-harness/mock-model.d.ts +38 -0
  25. package/dist/src/agent-harness/mock-model.js +69 -3
  26. package/dist/src/agent-harness/test-spawn.js +31 -0
  27. package/dist/src/chat/chat-keychain.d.ts +7 -12
  28. package/dist/src/chat/chat-keychain.js +19 -86
  29. package/dist/src/cli/config/screen-providers.js +1 -1
  30. package/dist/src/cli/cost-forensics.d.ts +10 -0
  31. package/dist/src/cli/cost-forensics.js +18 -3
  32. package/dist/src/cli/keys-bundle.d.ts +1 -1
  33. package/dist/src/cli/keys-bundle.js +1 -1
  34. package/dist/src/cli/keys.d.ts +10 -47
  35. package/dist/src/cli/keys.js +31 -399
  36. package/dist/src/council/clarifier.d.ts +31 -3
  37. package/dist/src/council/clarifier.js +220 -32
  38. package/dist/src/council/context.js +49 -15
  39. package/dist/src/council/debate-checkpoint.d.ts +129 -0
  40. package/dist/src/council/debate-checkpoint.js +176 -0
  41. package/dist/src/council/debate-planner.js +54 -5
  42. package/dist/src/council/debate-summary.d.ts +25 -0
  43. package/dist/src/council/debate-summary.js +85 -0
  44. package/dist/src/council/debate.d.ts +169 -2
  45. package/dist/src/council/debate.js +1265 -135
  46. package/dist/src/council/index.d.ts +108 -1
  47. package/dist/src/council/index.js +670 -197
  48. package/dist/src/council/leader.d.ts +26 -0
  49. package/dist/src/council/leader.js +150 -9
  50. package/dist/src/council/llm.d.ts +94 -0
  51. package/dist/src/council/llm.js +348 -55
  52. package/dist/src/council/panel-select.d.ts +30 -0
  53. package/dist/src/council/panel-select.js +82 -0
  54. package/dist/src/council/planner.js +40 -0
  55. package/dist/src/council/preflight.d.ts +17 -0
  56. package/dist/src/council/preflight.js +50 -2
  57. package/dist/src/council/prompts.d.ts +39 -4
  58. package/dist/src/council/prompts.js +256 -69
  59. package/dist/src/council/stance-recall.d.ts +42 -0
  60. package/dist/src/council/stance-recall.js +57 -0
  61. package/dist/src/council/strip-think.d.ts +17 -0
  62. package/dist/src/council/strip-think.js +33 -0
  63. package/dist/src/council/types.d.ts +138 -0
  64. package/dist/src/ee/artifact-cache.d.ts +16 -0
  65. package/dist/src/ee/artifact-cache.js +32 -0
  66. package/dist/src/ee/auth.d.ts +20 -0
  67. package/dist/src/ee/auth.js +54 -2
  68. package/dist/src/ee/bridge.d.ts +10 -0
  69. package/dist/src/ee/bridge.js +58 -0
  70. package/dist/src/ee/client.js +109 -21
  71. package/dist/src/ee/ee-onboarding.js +6 -26
  72. package/dist/src/ee/export-transcripts.d.ts +1 -0
  73. package/dist/src/ee/export-transcripts.js +8 -10
  74. package/dist/src/ee/extract-session.js +29 -0
  75. package/dist/src/ee/extract-style.d.ts +58 -0
  76. package/dist/src/ee/extract-style.js +270 -0
  77. package/dist/src/ee/recall-ledger.d.ts +9 -0
  78. package/dist/src/ee/recall-ledger.js +3 -0
  79. package/dist/src/ee/scope.d.ts +1 -0
  80. package/dist/src/ee/scope.js +26 -1
  81. package/dist/src/ee/search.d.ts +7 -0
  82. package/dist/src/ee/search.js +24 -0
  83. package/dist/src/ee/transcript-emit.js +2 -0
  84. package/dist/src/ee/types.d.ts +22 -0
  85. package/dist/src/ee/who-am-i-brain.d.ts +35 -0
  86. package/dist/src/ee/who-am-i-brain.js +220 -0
  87. package/dist/src/ee/who-am-i.d.ts +10 -3
  88. package/dist/src/ee/who-am-i.js +12 -0
  89. package/dist/src/ee/workflow-event.d.ts +48 -0
  90. package/dist/src/ee/workflow-event.js +81 -0
  91. package/dist/src/flow/compaction/compress.d.ts +3 -3
  92. package/dist/src/flow/compaction/compress.js +58 -8
  93. package/dist/src/flow/compaction/extract.d.ts +4 -7
  94. package/dist/src/flow/compaction/extract.js +50 -10
  95. package/dist/src/flow/compaction/index.d.ts +14 -1
  96. package/dist/src/flow/compaction/index.js +96 -3
  97. package/dist/src/flow/compaction/input-guard.d.ts +24 -0
  98. package/dist/src/flow/compaction/input-guard.js +43 -0
  99. package/dist/src/flow/compaction/progress.d.ts +35 -0
  100. package/dist/src/flow/compaction/progress.js +35 -0
  101. package/dist/src/flow/fold-planning.d.ts +36 -0
  102. package/dist/src/flow/fold-planning.js +83 -0
  103. package/dist/src/flow/hierarchy.d.ts +146 -0
  104. package/dist/src/flow/hierarchy.js +427 -0
  105. package/dist/src/flow/index.d.ts +1 -0
  106. package/dist/src/flow/index.js +2 -0
  107. package/dist/src/flow/run-artifacts.d.ts +102 -0
  108. package/dist/src/flow/run-artifacts.js +208 -0
  109. package/dist/src/generated/version.d.ts +1 -1
  110. package/dist/src/generated/version.js +1 -1
  111. package/dist/src/gsd/assessment-schema.d.ts +44 -0
  112. package/dist/src/gsd/assessment-schema.js +134 -0
  113. package/dist/src/gsd/capability-registry.d.ts +45 -0
  114. package/dist/src/gsd/capability-registry.js +337 -0
  115. package/dist/src/gsd/complexity-assessor.d.ts +39 -0
  116. package/dist/src/gsd/complexity-assessor.js +152 -0
  117. package/dist/src/gsd/config-bridge.d.ts +7 -0
  118. package/dist/src/gsd/config-bridge.js +114 -0
  119. package/dist/src/gsd/config-loader.d.ts +27 -0
  120. package/dist/src/gsd/config-loader.js +50 -0
  121. package/dist/src/gsd/council-context.d.ts +44 -0
  122. package/dist/src/gsd/council-context.js +114 -0
  123. package/dist/src/gsd/ee-closure.d.ts +28 -0
  124. package/dist/src/gsd/ee-closure.js +49 -0
  125. package/dist/src/gsd/flags.d.ts +66 -0
  126. package/dist/src/gsd/flags.js +102 -0
  127. package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
  128. package/dist/src/gsd/gsd-dispatch.js +131 -0
  129. package/dist/src/gsd/gsd-runtime.d.ts +22 -0
  130. package/dist/src/gsd/gsd-runtime.js +37 -0
  131. package/dist/src/gsd/host-adapter.d.ts +11 -0
  132. package/dist/src/gsd/host-adapter.js +29 -0
  133. package/dist/src/gsd/index.d.ts +24 -1
  134. package/dist/src/gsd/index.js +27 -0
  135. package/dist/src/gsd/loop-host-contract.d.ts +21 -0
  136. package/dist/src/gsd/loop-host-contract.js +39 -0
  137. package/dist/src/gsd/loop-host.d.ts +69 -0
  138. package/dist/src/gsd/loop-host.js +245 -0
  139. package/dist/src/gsd/loop-resolver.d.ts +36 -0
  140. package/dist/src/gsd/loop-resolver.js +79 -0
  141. package/dist/src/gsd/model-tier.d.ts +13 -0
  142. package/dist/src/gsd/model-tier.js +45 -0
  143. package/dist/src/gsd/mutation-gate.d.ts +16 -0
  144. package/dist/src/gsd/mutation-gate.js +41 -0
  145. package/dist/src/gsd/native-roadmap.d.ts +89 -0
  146. package/dist/src/gsd/native-roadmap.js +343 -0
  147. package/dist/src/gsd/native-state.d.ts +47 -0
  148. package/dist/src/gsd/native-state.js +220 -0
  149. package/dist/src/gsd/paths.d.ts +23 -0
  150. package/dist/src/gsd/paths.js +66 -0
  151. package/dist/src/gsd/phase-dag.d.ts +12 -0
  152. package/dist/src/gsd/phase-dag.js +94 -0
  153. package/dist/src/gsd/phase-sync.d.ts +42 -0
  154. package/dist/src/gsd/phase-sync.js +321 -0
  155. package/dist/src/gsd/pil-gate-context.d.ts +13 -0
  156. package/dist/src/gsd/pil-gate-context.js +64 -0
  157. package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
  158. package/dist/src/gsd/pil-gate-critic.js +74 -0
  159. package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
  160. package/dist/src/gsd/plan-council-prompts.js +79 -0
  161. package/dist/src/gsd/plan-council.d.ts +44 -0
  162. package/dist/src/gsd/plan-council.js +283 -0
  163. package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
  164. package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
  165. package/dist/src/gsd/product-workspace.d.ts +13 -0
  166. package/dist/src/gsd/product-workspace.js +124 -0
  167. package/dist/src/gsd/ship-bridge.d.ts +25 -0
  168. package/dist/src/gsd/ship-bridge.js +65 -0
  169. package/dist/src/gsd/state-document.d.ts +40 -0
  170. package/dist/src/gsd/state-document.js +163 -0
  171. package/dist/src/gsd/verdict-schema.d.ts +39 -0
  172. package/dist/src/gsd/verdict-schema.js +144 -0
  173. package/dist/src/gsd/verify-context.d.ts +22 -0
  174. package/dist/src/gsd/verify-context.js +27 -0
  175. package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
  176. package/dist/src/gsd/verify-council-prompts.js +85 -0
  177. package/dist/src/gsd/verify-council.d.ts +25 -0
  178. package/dist/src/gsd/verify-council.js +119 -0
  179. package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
  180. package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
  181. package/dist/src/gsd/workflow-engine.d.ts +60 -0
  182. package/dist/src/gsd/workflow-engine.js +207 -0
  183. package/dist/src/gsd/workflow-tools.d.ts +13 -0
  184. package/dist/src/gsd/workflow-tools.js +277 -0
  185. package/dist/src/headless/council-answers.js +4 -0
  186. package/dist/src/hooks/index.js +1 -1
  187. package/dist/src/index.js +172 -270
  188. package/dist/src/lsp/builtins.js +3 -1
  189. package/dist/src/lsp/manager.d.ts +5 -1
  190. package/dist/src/lsp/manager.js +249 -3
  191. package/dist/src/lsp/npm-cache.d.ts +11 -1
  192. package/dist/src/lsp/npm-cache.js +17 -1
  193. package/dist/src/lsp/runtime.d.ts +6 -1
  194. package/dist/src/lsp/runtime.js +17 -1
  195. package/dist/src/lsp/types.d.ts +83 -1
  196. package/dist/src/lsp/types.js +10 -0
  197. package/dist/src/maintain/pr-builder.js +23 -13
  198. package/dist/src/mcp/auto-setup.js +57 -32
  199. package/dist/src/mcp/client-pool.js +44 -16
  200. package/dist/src/mcp/lsp-tools.d.ts +5 -1
  201. package/dist/src/mcp/lsp-tools.js +93 -2
  202. package/dist/src/mcp/mcp-keychain.d.ts +3 -5
  203. package/dist/src/mcp/mcp-keychain.js +9 -49
  204. package/dist/src/mcp/research-onboarding.js +8 -7
  205. package/dist/src/mcp/runtime.js +34 -2
  206. package/dist/src/mcp/setup-guide-text.d.ts +1 -1
  207. package/dist/src/mcp/setup-guide-text.js +22 -2
  208. package/dist/src/mcp/tools-server.d.ts +10 -0
  209. package/dist/src/mcp/tools-server.js +10 -2
  210. package/dist/src/models/catalog-client.d.ts +87 -0
  211. package/dist/src/models/catalog-client.js +105 -38
  212. package/dist/src/models/catalog.json +528 -265
  213. package/dist/src/models/registry.d.ts +22 -7
  214. package/dist/src/models/registry.js +73 -10
  215. package/dist/src/ops/doctor.js +1 -1
  216. package/dist/src/orchestrator/ask-user.d.ts +61 -0
  217. package/dist/src/orchestrator/ask-user.js +65 -0
  218. package/dist/src/orchestrator/auto-commit.js +1 -1
  219. package/dist/src/orchestrator/batch-turn-runner.js +2 -2
  220. package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
  221. package/dist/src/orchestrator/cache-prefix.js +83 -0
  222. package/dist/src/orchestrator/compact-request.d.ts +32 -0
  223. package/dist/src/orchestrator/compact-request.js +41 -0
  224. package/dist/src/orchestrator/compaction.d.ts +12 -3
  225. package/dist/src/orchestrator/compaction.js +35 -15
  226. package/dist/src/orchestrator/council-manager.d.ts +12 -3
  227. package/dist/src/orchestrator/council-manager.js +74 -32
  228. package/dist/src/orchestrator/council-request.d.ts +49 -0
  229. package/dist/src/orchestrator/council-request.js +62 -0
  230. package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
  231. package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
  232. package/dist/src/orchestrator/error-utils.d.ts +29 -0
  233. package/dist/src/orchestrator/error-utils.js +132 -24
  234. package/dist/src/orchestrator/grounding-check.js +39 -1
  235. package/dist/src/orchestrator/interactive-pause.d.ts +26 -0
  236. package/dist/src/orchestrator/interactive-pause.js +36 -0
  237. package/dist/src/orchestrator/message-processor.d.ts +4 -0
  238. package/dist/src/orchestrator/message-processor.js +268 -41
  239. package/dist/src/orchestrator/orchestrator.d.ts +64 -3
  240. package/dist/src/orchestrator/orchestrator.js +823 -120
  241. package/dist/src/orchestrator/preprocessor.js +3 -3
  242. package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
  243. package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
  244. package/dist/src/orchestrator/prompts.js +17 -17
  245. package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
  246. package/dist/src/orchestrator/reactive-delegation.js +59 -0
  247. package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
  248. package/dist/src/orchestrator/retry-classifier.js +46 -2
  249. package/dist/src/orchestrator/safety-askcard.d.ts +1 -1
  250. package/dist/src/orchestrator/safety-askcard.js +5 -2
  251. package/dist/src/orchestrator/safety-intercept.d.ts +50 -0
  252. package/dist/src/orchestrator/safety-intercept.js +62 -0
  253. package/dist/src/orchestrator/scope-reminder.js +1 -1
  254. package/dist/src/orchestrator/session-experience.d.ts +2 -1
  255. package/dist/src/orchestrator/session-experience.js +2 -1
  256. package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
  257. package/dist/src/orchestrator/should-run-gate.js +18 -0
  258. package/dist/src/orchestrator/stall-watchdog.d.ts +31 -3
  259. package/dist/src/orchestrator/stall-watchdog.js +65 -10
  260. package/dist/src/orchestrator/stream-runner.d.ts +13 -3
  261. package/dist/src/orchestrator/stream-runner.js +115 -49
  262. package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
  263. package/dist/src/orchestrator/sub-agent-cap.js +16 -1
  264. package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
  265. package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
  266. package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
  267. package/dist/src/orchestrator/subagent-compactor.js +126 -15
  268. package/dist/src/orchestrator/tool-engine.d.ts +41 -0
  269. package/dist/src/orchestrator/tool-engine.js +846 -66
  270. package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
  271. package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
  272. package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
  273. package/dist/src/orchestrator/turn-watchdog.d.ts +44 -0
  274. package/dist/src/orchestrator/turn-watchdog.js +84 -0
  275. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  276. package/dist/src/pil/agent-operating-contract.js +6 -4
  277. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  278. package/dist/src/pil/cheap-model-playbook.js +5 -1
  279. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  280. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  281. package/dist/src/pil/discovery-types.d.ts +1 -0
  282. package/dist/src/pil/discovery.d.ts +1 -1
  283. package/dist/src/pil/discovery.js +18 -13
  284. package/dist/src/pil/layer1-intent.d.ts +18 -6
  285. package/dist/src/pil/layer1-intent.js +66 -757
  286. package/dist/src/pil/layer15-context-scan.js +15 -1
  287. package/dist/src/pil/layer1_5-complexity-size.d.ts +7 -0
  288. package/dist/src/pil/layer1_5-complexity-size.js +31 -5
  289. package/dist/src/pil/layer3-ee-injection.js +23 -8
  290. package/dist/src/pil/layer4-gsd.js +69 -16
  291. package/dist/src/pil/layer5-context.js +7 -3
  292. package/dist/src/pil/layer6-output.d.ts +23 -0
  293. package/dist/src/pil/layer6-output.js +5 -1
  294. package/dist/src/pil/llm-classify.d.ts +111 -5
  295. package/dist/src/pil/llm-classify.js +421 -189
  296. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  297. package/dist/src/pil/native-capabilities-workbook.js +8 -0
  298. package/dist/src/pil/pipeline.js +36 -2
  299. package/dist/src/pil/repo-grounding-probe.d.ts +15 -0
  300. package/dist/src/pil/repo-grounding-probe.js +136 -0
  301. package/dist/src/pil/repo-structure-hints.d.ts +7 -0
  302. package/dist/src/pil/repo-structure-hints.js +45 -0
  303. package/dist/src/pil/response-tools.js +5 -3
  304. package/dist/src/pil/schema.d.ts +1 -0
  305. package/dist/src/pil/schema.js +2 -0
  306. package/dist/src/pil/types.d.ts +18 -0
  307. package/dist/src/playbook/directives.d.ts +4 -0
  308. package/dist/src/playbook/directives.js +17 -5
  309. package/dist/src/product-loop/artifact-io.js +4 -0
  310. package/dist/src/product-loop/backlog-builder.d.ts +14 -1
  311. package/dist/src/product-loop/backlog-builder.js +30 -6
  312. package/dist/src/product-loop/criteria-seed.d.ts +51 -0
  313. package/dist/src/product-loop/criteria-seed.js +200 -0
  314. package/dist/src/product-loop/discovery-context-format.js +3 -1
  315. package/dist/src/product-loop/discovery-ecosystem.js +4 -1
  316. package/dist/src/product-loop/discovery-interview.d.ts +9 -0
  317. package/dist/src/product-loop/discovery-interview.js +60 -12
  318. package/dist/src/product-loop/discovery-recommender.js +2 -1
  319. package/dist/src/product-loop/discovery-schema.js +19 -2
  320. package/dist/src/product-loop/discovery-triage.d.ts +23 -0
  321. package/dist/src/product-loop/discovery-triage.js +109 -0
  322. package/dist/src/product-loop/gather.js +150 -2
  323. package/dist/src/product-loop/ideal-trace.d.ts +7 -0
  324. package/dist/src/product-loop/ideal-trace.js +64 -0
  325. package/dist/src/product-loop/index.d.ts +13 -1
  326. package/dist/src/product-loop/index.js +340 -52
  327. package/dist/src/product-loop/loop-driver.d.ts +7 -0
  328. package/dist/src/product-loop/loop-driver.js +330 -106
  329. package/dist/src/product-loop/phase-plan.d.ts +21 -0
  330. package/dist/src/product-loop/phase-plan.js +81 -6
  331. package/dist/src/product-loop/phase-rituals.d.ts +3 -0
  332. package/dist/src/product-loop/phase-rituals.js +8 -3
  333. package/dist/src/product-loop/phase-runner.js +39 -12
  334. package/dist/src/product-loop/plan-adherence-review.d.ts +26 -0
  335. package/dist/src/product-loop/plan-adherence-review.js +144 -0
  336. package/dist/src/product-loop/sprint-runner.d.ts +173 -0
  337. package/dist/src/product-loop/sprint-runner.js +863 -19
  338. package/dist/src/product-loop/types.d.ts +61 -5
  339. package/dist/src/providers/adapter.d.ts +1 -1
  340. package/dist/src/providers/adapter.js +3 -4
  341. package/dist/src/providers/anthropic.d.ts +9 -8
  342. package/dist/src/providers/anthropic.js +13 -47
  343. package/dist/src/providers/auth/browser-flow.d.ts +1 -1
  344. package/dist/src/providers/auth/browser-flow.js +1 -1
  345. package/dist/src/providers/auth/grok-oauth.d.ts +1 -0
  346. package/dist/src/providers/auth/grok-oauth.js +30 -5
  347. package/dist/src/providers/auth/openai-oauth.d.ts +1 -0
  348. package/dist/src/providers/auth/openai-oauth.js +15 -1
  349. package/dist/src/providers/auth/registry.js +0 -34
  350. package/dist/src/providers/auth/token-store.d.ts +9 -9
  351. package/dist/src/providers/auth/token-store.js +8 -67
  352. package/dist/src/providers/auth/types.d.ts +9 -1
  353. package/dist/src/providers/auth/types.js +1 -1
  354. package/dist/src/providers/capabilities.d.ts +24 -5
  355. package/dist/src/providers/capabilities.js +42 -24
  356. package/dist/src/providers/endpoints.d.ts +2 -2
  357. package/dist/src/providers/endpoints.js +11 -10
  358. package/dist/src/providers/env-store.d.ts +17 -0
  359. package/dist/src/providers/env-store.js +228 -0
  360. package/dist/src/providers/keychain.d.ts +22 -18
  361. package/dist/src/providers/keychain.js +127 -140
  362. package/dist/src/providers/mcp-vision-bridge.js +56 -146
  363. package/dist/src/providers/openai-compatible.js +8 -1
  364. package/dist/src/providers/pricing.d.ts +2 -2
  365. package/dist/src/providers/pricing.js +3 -13
  366. package/dist/src/providers/runtime.d.ts +43 -3
  367. package/dist/src/providers/runtime.js +88 -14
  368. package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
  369. package/dist/src/providers/strategies/base.strategy.js +24 -1
  370. package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
  371. package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
  372. package/dist/src/providers/strategies/registry.js +4 -4
  373. package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
  374. package/dist/src/providers/strategies/thinking-mode.js +288 -1
  375. package/dist/src/providers/strategies/xai.strategy.js +27 -0
  376. package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
  377. package/dist/src/providers/strategies/zai.strategy.js +44 -0
  378. package/dist/src/providers/types.d.ts +5 -6
  379. package/dist/src/providers/types.js +2 -2
  380. package/dist/src/providers/vision-backend.d.ts +47 -0
  381. package/dist/src/providers/vision-backend.js +258 -0
  382. package/dist/src/providers/vision-proxy.d.ts +22 -9
  383. package/dist/src/providers/vision-proxy.js +63 -132
  384. package/dist/src/providers/warm.d.ts +65 -0
  385. package/dist/src/providers/warm.js +145 -0
  386. package/dist/src/providers/wire-debug.js +95 -0
  387. package/dist/src/router/decide.d.ts +13 -0
  388. package/dist/src/router/decide.js +138 -36
  389. package/dist/src/router/peak-hour.d.ts +38 -0
  390. package/dist/src/router/peak-hour.js +107 -0
  391. package/dist/src/router/step-router.js +3 -2
  392. package/dist/src/router/warm.js +4 -5
  393. package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
  394. package/dist/src/scaffold/continuation-prompt.js +26 -0
  395. package/dist/src/scaffold/point-to-existing.d.ts +21 -0
  396. package/dist/src/scaffold/point-to-existing.js +25 -0
  397. package/dist/src/self-qa/agentic-loop.js +6 -5
  398. package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
  399. package/dist/src/{ui/state → state}/active-run.js +21 -0
  400. package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
  401. package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
  402. package/dist/src/state/turn-trace.d.ts +43 -0
  403. package/dist/src/state/turn-trace.js +32 -0
  404. package/dist/src/storage/db.js +2 -1
  405. package/dist/src/storage/index.d.ts +1 -1
  406. package/dist/src/storage/index.js +1 -1
  407. package/dist/src/storage/interaction-log.d.ts +1 -1
  408. package/dist/src/storage/migrations.js +71 -1
  409. package/dist/src/storage/sessions.d.ts +28 -10
  410. package/dist/src/storage/sessions.js +78 -21
  411. package/dist/src/storage/transcript-view.js +1 -1
  412. package/dist/src/storage/transcript.d.ts +51 -0
  413. package/dist/src/storage/transcript.js +340 -15
  414. package/dist/src/tools/file.d.ts +15 -0
  415. package/dist/src/tools/file.js +32 -0
  416. package/dist/src/tools/git-safety.d.ts +19 -0
  417. package/dist/src/tools/git-safety.js +168 -0
  418. package/dist/src/tools/native-tools.d.ts +1 -1
  419. package/dist/src/tools/native-tools.js +81 -1
  420. package/dist/src/tools/registry.d.ts +20 -0
  421. package/dist/src/tools/registry.js +576 -23
  422. package/dist/src/tools/research.d.ts +29 -0
  423. package/dist/src/tools/research.js +233 -0
  424. package/dist/src/types/index.d.ts +147 -4
  425. package/dist/src/ui/app.js +0 -0
  426. package/dist/src/ui/cards/product-status-card.js +1 -1
  427. package/dist/src/ui/components/agent-rail-activities.d.ts +26 -0
  428. package/dist/src/ui/components/agent-rail-activities.js +47 -0
  429. package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
  430. package/dist/src/ui/components/bubble-body-guard.js +50 -0
  431. package/dist/src/ui/components/compact-progress-card.d.ts +24 -0
  432. package/dist/src/ui/components/compact-progress-card.js +42 -0
  433. package/dist/src/ui/components/context-rail.d.ts +26 -0
  434. package/dist/src/ui/components/context-rail.js +33 -0
  435. package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
  436. package/dist/src/ui/components/council-conclusion-card.js +420 -0
  437. package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
  438. package/dist/src/ui/components/council-debate-pill.js +34 -0
  439. package/dist/src/ui/components/council-info-card.js +2 -2
  440. package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
  441. package/dist/src/ui/components/council-leader-bubble.js +21 -11
  442. package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
  443. package/dist/src/ui/components/council-message-bubble.js +16 -15
  444. package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
  445. package/dist/src/ui/components/council-phase-timeline.js +66 -17
  446. package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
  447. package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
  448. package/dist/src/ui/components/council-question-card.js +13 -12
  449. package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
  450. package/dist/src/ui/components/council-rail-rounds.js +57 -0
  451. package/dist/src/ui/components/council-round-group.d.ts +38 -0
  452. package/dist/src/ui/components/council-round-group.js +88 -0
  453. package/dist/src/ui/components/council-status-list.d.ts +3 -1
  454. package/dist/src/ui/components/council-status-list.js +36 -24
  455. package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
  456. package/dist/src/ui/components/council-synthesis-banner.js +20 -5
  457. package/dist/src/ui/components/halt-recovery-card.js +9 -5
  458. package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
  459. package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
  460. package/dist/src/ui/components/message-view.d.ts +15 -0
  461. package/dist/src/ui/components/message-view.js +50 -1
  462. package/dist/src/ui/components/prompt-box.js +18 -16
  463. package/dist/src/ui/components/session-tree-card.d.ts +14 -0
  464. package/dist/src/ui/components/session-tree-card.js +46 -0
  465. package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
  466. package/dist/src/ui/components/slash-inline-menu.js +26 -5
  467. package/dist/src/ui/components/task-list-panel.d.ts +14 -1
  468. package/dist/src/ui/components/task-list-panel.js +22 -2
  469. package/dist/src/ui/components/tool-group.d.ts +15 -3
  470. package/dist/src/ui/components/tool-group.js +69 -11
  471. package/dist/src/ui/containers/modals-layer.d.ts +4 -2
  472. package/dist/src/ui/containers/modals-layer.js +2 -2
  473. package/dist/src/ui/council-harness-event.d.ts +57 -0
  474. package/dist/src/ui/council-harness-event.js +46 -0
  475. package/dist/src/ui/heartbeat-debug.d.ts +29 -0
  476. package/dist/src/ui/heartbeat-debug.js +45 -0
  477. package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
  478. package/dist/src/ui/mcp-modal.js +2 -4
  479. package/dist/src/ui/modals/api-key-modal.js +1 -1
  480. package/dist/src/ui/modals/connect-modal.js +4 -3
  481. package/dist/src/ui/modals/model-picker-modal.d.ts +8 -18
  482. package/dist/src/ui/modals/model-picker-modal.js +8 -10
  483. package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
  484. package/dist/src/ui/modals/session-picker-modal.js +3 -5
  485. package/dist/src/ui/picker-providers.d.ts +1 -1
  486. package/dist/src/ui/picker-providers.js +1 -1
  487. package/dist/src/ui/primitives/index.d.ts +1 -0
  488. package/dist/src/ui/primitives/index.js +2 -0
  489. package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
  490. package/dist/src/ui/primitives/semantic-primitives.js +81 -0
  491. package/dist/src/ui/slash/compact.js +5 -7
  492. package/dist/src/ui/slash/cost.js +1 -1
  493. package/dist/src/ui/slash/council.js +19 -1
  494. package/dist/src/ui/slash/debug.d.ts +3 -31
  495. package/dist/src/ui/slash/debug.js +9 -20
  496. package/dist/src/ui/slash/ee.js +81 -0
  497. package/dist/src/ui/slash/ideal.d.ts +6 -2
  498. package/dist/src/ui/slash/ideal.js +97 -7
  499. package/dist/src/ui/slash/menu-items.d.ts +7 -0
  500. package/dist/src/ui/slash/menu-items.js +23 -20
  501. package/dist/src/ui/slash/registry.d.ts +2 -0
  502. package/dist/src/ui/slash/registry.js +4 -0
  503. package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
  504. package/dist/src/ui/status-bar/cache-hit.js +9 -0
  505. package/dist/src/ui/status-bar/index.d.ts +1 -1
  506. package/dist/src/ui/status-bar/index.js +7 -3
  507. package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
  508. package/dist/src/ui/status-bar/usd-meter.js +6 -4
  509. package/dist/src/ui/theme.d.ts +1 -0
  510. package/dist/src/ui/theme.js +2 -0
  511. package/dist/src/ui/types.d.ts +7 -0
  512. package/dist/src/ui/use-app-logic.js +0 -0
  513. package/dist/src/ui/utils/agent-activities.d.ts +39 -0
  514. package/dist/src/ui/utils/agent-activities.js +96 -0
  515. package/dist/src/ui/utils/format.d.ts +14 -0
  516. package/dist/src/ui/utils/format.js +23 -3
  517. package/dist/src/ui/utils/group-tool-entries.d.ts +26 -0
  518. package/dist/src/ui/utils/group-tool-entries.js +111 -0
  519. package/dist/src/ui/utils/tool-summary.d.ts +21 -0
  520. package/dist/src/ui/utils/tool-summary.js +91 -0
  521. package/dist/src/usage/downgrade.js +2 -2
  522. package/dist/src/usage/product-ledger.js +2 -2
  523. package/dist/src/utils/event-loop-monitor.d.ts +85 -0
  524. package/dist/src/utils/event-loop-monitor.js +107 -0
  525. package/dist/src/utils/install-manager.js +2 -1
  526. package/dist/src/utils/llm-deadline.d.ts +14 -0
  527. package/dist/src/utils/llm-deadline.js +19 -0
  528. package/dist/src/utils/logger.js +2 -2
  529. package/dist/src/utils/loop-profiler.d.ts +102 -0
  530. package/dist/src/utils/loop-profiler.js +202 -0
  531. package/dist/src/utils/permission-mode.js +5 -3
  532. package/dist/src/utils/redactor.js +1 -1
  533. package/dist/src/utils/settings.d.ts +180 -5
  534. package/dist/src/utils/settings.js +271 -31
  535. package/dist/src/utils/side-question.d.ts +1 -2
  536. package/dist/src/utils/side-question.js +2 -2
  537. package/dist/src/utils/visible-retry.d.ts +11 -0
  538. package/dist/src/utils/visible-retry.js +10 -1
  539. package/dist/src/verify/entrypoint.d.ts +1 -1
  540. package/dist/src/verify/entrypoint.js +52 -17
  541. package/dist/src/verify/orchestrator.d.ts +1 -1
  542. package/dist/src/verify/orchestrator.js +20 -3
  543. package/dist/src/verify/recipes.d.ts +13 -0
  544. package/dist/src/verify/recipes.js +15 -0
  545. package/package.json +134 -132
  546. package/dist/src/cli/bw-vault.d.ts +0 -55
  547. package/dist/src/cli/bw-vault.js +0 -133
  548. package/dist/src/mcp/ee-tools.d.ts +0 -46
  549. package/dist/src/mcp/ee-tools.js +0 -193
  550. package/dist/src/providers/auth/gcloud.d.ts +0 -28
  551. package/dist/src/providers/auth/gcloud.js +0 -102
  552. package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
  553. package/dist/src/providers/auth/gemini-oauth.js +0 -472
  554. package/dist/src/providers/gemini.d.ts +0 -11
  555. package/dist/src/providers/gemini.js +0 -45
  556. package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
  557. package/dist/src/providers/siliconflow-sse-repair.js +0 -177
  558. package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
  559. package/dist/src/providers/strategies/google.strategy.js +0 -174
  560. package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
  561. package/dist/src/ui/containers/chat-feed.d.ts +0 -40
  562. package/dist/src/ui/containers/chat-feed.js +0 -66
@@ -3,15 +3,80 @@ import { promises as fs } from "node:fs";
3
3
  import * as path from "node:path";
4
4
  import { readArtifact, writeArtifact } from "../flow/artifact-io.js";
5
5
  import { withRateLimitBackoff } from "./discovery-recommender.js";
6
- export const PHASE_PLANNER_SYSTEM = "You decompose a product idea into 3–5 sequential phases. Output strict JSON only. " +
7
- "Each phase covers a subset of successCriteria verbatim from the input spec. " +
8
- "Union of all phases.successCriteria MUST equal the input successCriteria array (no drift, no omission).";
6
+ export const PHASE_PLANNER_SYSTEM = "You are the PO/tech-lead planning an agile delivery. Decompose a product idea into 3–5 " +
7
+ "sequential phases. Output strict JSON only. Each phase covers a subset of successCriteria " +
8
+ "verbatim from the input spec. Union of all phases.successCriteria MUST equal the input " +
9
+ "successCriteria array (no drift, no omission).\n\n" +
10
+ "Size each phase to its REAL difficulty. For every phase, YOU decide its `maxSprints` — the " +
11
+ "maximum sprint iterations that phase may need — from that phase's own scope, risk, and " +
12
+ "uncertainty, exactly as a tech lead would in agile planning: a simple/mechanical phase needs " +
13
+ "1; a phase with hard, uncertain, or risky work needs more (2–5). Do NOT split a fixed budget " +
14
+ "evenly, do NOT pad to a quota, and never emit a fraction. `maxSprints` is a CEILING — the " +
15
+ "done-gate ends a phase early once its criteria are met — so give genuinely hard phases enough " +
16
+ "room to iterate rather than rationing them.";
17
+ /**
18
+ * Coerce a phase id / dependsOn element to the canonical `phase-N` string form.
19
+ *
20
+ * The phase-planner prompt does not pin `id` to a string, so the LLM frequently
21
+ * emits bare numbers — e.g. `"id": 1, "dependsOn": [1]` instead of
22
+ * `"id": "phase-1", "dependsOn": ["phase-1"]`. Downstream consumers assume the
23
+ * declared `Phase.id: string` / `dependsOn: string[]` contract; the roadmap
24
+ * renderer (`buildRoadmapFromPhasePlan`) calls `dep.match(...)` and crashed with
25
+ * `dep.match is not a function` on a numeric id, aborting the whole /ideal run
26
+ * right after the sprint plan committed — before any implementation ran.
27
+ * Normalising here (the single parse choke-point) restores the contract for
28
+ * every consumer.
29
+ */
30
+ function normalizePhaseRef(ref) {
31
+ if (typeof ref === "number" && Number.isFinite(ref))
32
+ return `phase-${ref}`;
33
+ const s = String(ref).trim();
34
+ const bareNumber = s.match(/^(\d+)$/);
35
+ if (bareNumber)
36
+ return `phase-${bareNumber[1]}`;
37
+ return s;
38
+ }
39
+ /**
40
+ * Normalise `id` + `dependsOn` on every phase to the canonical string form.
41
+ * Mutates and returns the same plan object. Safe on already-normalised plans.
42
+ */
43
+ /**
44
+ * Coerce a plan's per-phase `maxSprints` to a usable sprint COUNT: an integer
45
+ * in [1, 20]. This is a pure VALIDITY FLOOR — it does NOT allocate or divide any
46
+ * budget. The PO/leader decides each phase's `maxSprints` from that phase's
47
+ * difficulty (see PHASE_PLANNER_SYSTEM); this only defends the executor against a
48
+ * malformed value the model might still emit.
49
+ *
50
+ * The sprint loop is `for (sprintN = 1; sprintN <= phase.maxSprints; sprintN++)`,
51
+ * so any value < 1 makes `1 <= 0.n` false → the loop body NEVER runs → `runSprint`
52
+ * is never called → implementation is silently skipped (the historical
53
+ * "plan is great but implement never starts / hangs" bug — a small `--max-sprints`
54
+ * once made the old "divide the budget across phases" prompt emit fractions like
55
+ * `0.3 / 0.2 / 0.5`). Flooring to an integer ≥ 1 guarantees every planned phase
56
+ * executes at least one sprint regardless of what the model returns.
57
+ */
58
+ export function clampMaxSprints(raw) {
59
+ const n = typeof raw === "number" ? raw : Number(raw);
60
+ if (!Number.isFinite(n) || n < 1)
61
+ return 1;
62
+ return Math.min(20, Math.round(n));
63
+ }
64
+ export function normalizePhasePlan(plan) {
65
+ if (Array.isArray(plan?.phases)) {
66
+ for (const phase of plan.phases) {
67
+ phase.id = normalizePhaseRef(phase.id);
68
+ phase.dependsOn = Array.isArray(phase.dependsOn) ? phase.dependsOn.map(normalizePhaseRef) : [];
69
+ phase.maxSprints = clampMaxSprints(phase.maxSprints);
70
+ }
71
+ }
72
+ return plan;
73
+ }
9
74
  export function parsePhasePlanJson(raw) {
10
75
  const stripped = raw
11
76
  .replace(/^```(?:json)?\s*/, "")
12
77
  .replace(/\s*```$/, "")
13
78
  .trim();
14
- return JSON.parse(stripped);
79
+ return normalizePhasePlan(JSON.parse(stripped));
15
80
  }
16
81
  export function validatePhasePlan(plan, spec) {
17
82
  if (plan.phases.length < 1 || plan.phases.length > 6) {
@@ -98,7 +163,15 @@ function buildPhasePlannerPrompt(args) {
98
163
  `Scope: ${args.clarifiedSpec.scope}`,
99
164
  `SuccessCriteria (return these verbatim, distributed across 3-5 phases):`,
100
165
  ...args.clarifiedSpec.successCriteria.map((c, i) => ` ${i + 1}. ${c}`),
101
- `MaxSprints budget: ${args.manifest.maxSprints} (divide across phases).`,
166
+ // maxSprints is PO-decided PER PHASE from that phase's difficulty (see the
167
+ // system prompt) — NOT a global budget to divide. The user's --max-sprints is
168
+ // only a SOFT guide for overall ambition, never an arithmetic cap the planner
169
+ // must partition. Each phase's "maxSprints" MUST be a whole integer >= 1.
170
+ `Sprint sizing: decide each phase's "maxSprints" from its own difficulty/scope/risk — a whole ` +
171
+ `integer >= 1, more for harder phases. The user suggested roughly ${args.manifest.maxSprints} ` +
172
+ `sprint(s) total as a soft guide to overall ambition; you may use fewer if the work is simple ` +
173
+ `or allocate more per phase if the work genuinely needs it. Do not divide it evenly and do not ` +
174
+ `treat it as a hard budget.`,
102
175
  `Output JSON shape: { version:1, generatedAt:<ISO>, phases:[{id,name,goal,successCriteria,scope,exitCondition:{type:"criteria-threshold",min:${args.manifest.doneThreshold}},dependsOn,maxSprints}] }`,
103
176
  ].join("\n");
104
177
  }
@@ -109,7 +182,9 @@ export async function readPhasePlan(flowDir, runId) {
109
182
  if (!raw)
110
183
  return null;
111
184
  try {
112
- return JSON.parse(raw);
185
+ // Normalise on read too: runs persisted before the parse-time normalisation
186
+ // landed (or hand-edited phases.md) can still carry numeric ids.
187
+ return normalizePhasePlan(JSON.parse(raw));
113
188
  }
114
189
  catch {
115
190
  return null;
@@ -6,6 +6,9 @@ export interface SprintState {
6
6
  scoreAfter: number;
7
7
  criteriaMet: number;
8
8
  totalCriteria: number;
9
+ /** Verify verdict for this sprint (PASS/FAIL/ERROR) — grounds the review so it
10
+ * describes what actually happened instead of confabulating an agile narrative. */
11
+ verifyVerdict?: string;
9
12
  }
10
13
  export declare function generateSprintReview(args: {
11
14
  sprintState: SprintState;
@@ -15,9 +15,14 @@ export async function generateSprintReview(args) {
15
15
  if (args.remainingUsd < reviewFloor(args.capUsd)) {
16
16
  return { summary: deterministicReview(args.sprintState), usedFallback: true };
17
17
  }
18
- const prompt = `Sprint ${args.sprintState.sprintN} of phase ${args.phase.id}: score ${args.sprintState.scoreBefore.toFixed(2)} → ${args.sprintState.scoreAfter.toFixed(2)}, ` +
19
- `met ${args.sprintState.criteriaMet}/${args.sprintState.totalCriteria} criteria. ` +
20
- `Write a ≤500-char demo summary for the customer.`;
18
+ const s = args.sprintState;
19
+ const verifyLine = s.verifyVerdict ? ` Verify: ${s.verifyVerdict}.` : "";
20
+ const goal = args.phase.goal ? ` Phase goal: ${args.phase.goal}.` : "";
21
+ const prompt = `Sprint ${s.sprintN} of phase ${args.phase.id}: score ${s.scoreBefore.toFixed(2)} → ${s.scoreAfter.toFixed(2)}, ` +
22
+ `met ${s.criteriaMet}/${s.totalCriteria} acceptance criteria.${verifyLine}${goal} ` +
23
+ `Write a ≤500-char demo summary describing ONLY what these numbers show — the concrete progress on criteria and verify status. ` +
24
+ `Do NOT invent activities (e.g. "team alignment", "environment setup") that the metrics do not evidence. ` +
25
+ `If 0/${s.totalCriteria} criteria are met, say plainly that no criteria passed yet and why (verify status), not that setup was done.`;
21
26
  try {
22
27
  const res = await withRateLimitBackoff(() => args.leader.generate({ system: "You write concise sprint demo summaries.", prompt, maxTokens: 250 }), { delays: args.backoffDelays });
23
28
  return { summary: res.content.trim().slice(0, 500), usedFallback: false };
@@ -1,5 +1,7 @@
1
1
  import * as path from "node:path";
2
2
  import { readArtifact, writeArtifact } from "../flow/artifact-io.js";
3
+ import { isGsdNativeEnabled } from "../gsd/flags.js";
4
+ import { orderPhasesForExecution, syncPhasePlanToRoadmap } from "../gsd/phase-dag.js";
3
5
  import { buildSprintContext, digestSprintIntoPhase, handoffPhaseToNext } from "./context-policy.js";
4
6
  import { formatProjectContextForPrompt } from "./discovery-context-format.js";
5
7
  import { backupCorruptPhases, generatePhasePlan, readPhasePlan, validatePhasePlan, writePhasePlan, } from "./phase-plan.js";
@@ -249,8 +251,14 @@ export async function* runPhases(args) {
249
251
  backoffDelays: args.backoffDelays,
250
252
  });
251
253
  await writePhasePlan(args.flowDir, args.runId, plan);
254
+ if (isGsdNativeEnabled() && args.projectCwd) {
255
+ syncPhasePlanToRoadmap(args.projectCwd, args.idea ?? args.clarifiedSpec.problemStatement, plan);
256
+ }
252
257
  }
253
- for (const phase of orderByDeps(plan.phases)) {
258
+ const orderedPhases = args.projectCwd
259
+ ? orderPhasesForExecution(args.projectCwd, plan.phases)
260
+ : orderByDeps(plan.phases);
261
+ for (const phase of orderedPhases) {
254
262
  const status = await readPhaseStatus(args.flowDir, args.runId, phase.id);
255
263
  if (status === "done" || status === "blocked")
256
264
  continue;
@@ -305,7 +313,11 @@ export async function* runPhases(args) {
305
313
  lastSprintState = sprintResult;
306
314
  totalSprints += 1;
307
315
  const review = await generateSprintReview({
308
- sprintState: { sprintN, ...sprintResult },
316
+ sprintState: {
317
+ sprintN,
318
+ ...sprintResult,
319
+ verifyVerdict: sprintResult.lastVerifyResult,
320
+ },
309
321
  phase,
310
322
  leader: args.leader,
311
323
  capUsd: args.capUsd,
@@ -315,15 +327,29 @@ export async function* runPhases(args) {
315
327
  if (!args.suppressPush) {
316
328
  yield { type: "push_notification", content: review.summary };
317
329
  }
318
- await markAwaitingCustomerReview(args.flowDir, args.runId, phase.id, sprintN);
319
- const verdict = await args.awaitCustomerVerdict({
320
- flowDir: args.flowDir,
321
- runId: args.runId,
322
- phaseId: phase.id,
323
- sprintN,
324
- reviewSummary: review.summary,
325
- });
326
- await clearAwaitingCustomerReview(args.flowDir, args.runId, phase.id, sprintN);
330
+ // Autonomy fix: by default /ideal advances between sprints WITHOUT a blocking
331
+ // human verdict (previously the loop parked in discordAwaitVerdict's poll and
332
+ // never reached sprint 2 unless a human replied). Set
333
+ // MUONROI_IDEAL_REQUIRE_VERDICT=1 to restore the human customer-review gate.
334
+ const requireVerdict = process.env.MUONROI_IDEAL_REQUIRE_VERDICT === "1";
335
+ let verdict;
336
+ if (requireVerdict) {
337
+ await markAwaitingCustomerReview(args.flowDir, args.runId, phase.id, sprintN);
338
+ verdict = await args.awaitCustomerVerdict({
339
+ flowDir: args.flowDir,
340
+ runId: args.runId,
341
+ phaseId: phase.id,
342
+ sprintN,
343
+ reviewSummary: review.summary,
344
+ });
345
+ await clearAwaitingCustomerReview(args.flowDir, args.runId, phase.id, sprintN);
346
+ }
347
+ else {
348
+ verdict = {
349
+ verdict: "accept",
350
+ feedback: "[auto-advance: autonomous mode (MUONROI_IDEAL_REQUIRE_VERDICT unset)]",
351
+ };
352
+ }
327
353
  await appendCustomerDecision(args.flowDir, args.runId, {
328
354
  phaseId: phase.id,
329
355
  sprintN,
@@ -352,7 +378,8 @@ export async function* runPhases(args) {
352
378
  // retro skipped
353
379
  }
354
380
  await clearRetroPending(args.flowDir, args.runId, phase.id, sprintN);
355
- const phaseRatio = sprintResult.criteriaMet / Math.max(1, sprintResult.totalCriteria);
381
+ const phaseTotal = sprintResult.totalCriteria ?? phase.successCriteria.length;
382
+ const phaseRatio = sprintResult.criteriaMet / Math.max(1, phaseTotal);
356
383
  if (phaseRatio >= phase.exitCondition.min)
357
384
  break;
358
385
  }
@@ -0,0 +1,26 @@
1
+ import type { StreamChunk, TaskRequest, ToolResult } from "../types/index.js";
2
+ /**
3
+ * Plan-adherence review gate (requested 2026-07-12): after implementation, spawn a
4
+ * HIGH-TIER reviewer agent to check the actual diff against the approved plan
5
+ * (file_edits + acceptance_criteria). When it finds deviations, hand a concrete fix
6
+ * task to a LOWER-TIER agent and re-review. Bounded rounds; never halts the sprint
7
+ * (verify + the criteria done-gate remain the hard gates). This catches the Sprint-1
8
+ * failure mode where a cheap implementer received a rich plan but diverged (wrong
9
+ * LSP op, stub tools) with nothing to notice.
10
+ */
11
+ export interface AdherenceVerdict {
12
+ rounds: number;
13
+ adherent: boolean;
14
+ deviations: string[];
15
+ }
16
+ export declare function runPlanAdherenceReview(args: {
17
+ sprintN: number;
18
+ planSynthesis: string;
19
+ cwd: string;
20
+ reviewModelId: string;
21
+ fixModelId: string;
22
+ runIsolatedTask: (req: TaskRequest) => Promise<ToolResult>;
23
+ maxRounds?: number;
24
+ /** Injectable for tests; defaults to `git diff HEAD` in cwd. */
25
+ diffProvider?: (cwd: string) => string;
26
+ }): AsyncGenerator<StreamChunk, AdherenceVerdict, unknown>;
@@ -0,0 +1,144 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { getIsolatedTaskDeadlineMs, withDeadlineRace } from "../utils/llm-deadline.js";
3
+ /**
4
+ * Run an isolated sub-agent with a wall-clock backstop. The review/fix agents
5
+ * were bare `await`s — a provider that hangs post-stream would wedge the whole
6
+ * sprint (same class as the impl stall, run mrhc43f0fb9b). On timeout the race
7
+ * rejects; we convert it into a failure ToolResult so the existing `.success`
8
+ * paths handle it (review → leave gate; fix → stop the loop) instead of hanging.
9
+ */
10
+ async function runIsolatedGuarded(run, req, label) {
11
+ try {
12
+ return await withDeadlineRace(() => run(req), getIsolatedTaskDeadlineMs(), label);
13
+ }
14
+ catch (err) {
15
+ return { success: false, output: "", error: err instanceof Error ? err.message : String(err) };
16
+ }
17
+ }
18
+ function currentDiff(cwd) {
19
+ try {
20
+ const r = spawnSync("git", ["diff", "HEAD"], {
21
+ cwd,
22
+ encoding: "utf8",
23
+ timeout: 20000,
24
+ maxBuffer: 20 * 1024 * 1024,
25
+ });
26
+ return (r.stdout ?? "").trim();
27
+ }
28
+ catch {
29
+ return "";
30
+ }
31
+ }
32
+ function parseReview(output) {
33
+ const m = output.match(/\{[\s\S]*\}/);
34
+ if (!m)
35
+ return null;
36
+ try {
37
+ return JSON.parse(m[0]);
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ function normalizeDeviations(dev) {
44
+ if (!Array.isArray(dev))
45
+ return [];
46
+ return dev
47
+ .map((d) => {
48
+ if (typeof d === "string")
49
+ return d.trim();
50
+ const where = d.where ? `[${d.where}] ` : "";
51
+ const issue = d.issue ?? "";
52
+ const fix = d.fix ? ` → FIX: ${d.fix}` : "";
53
+ return `${where}${issue}${fix}`.trim();
54
+ })
55
+ .filter((s) => s.length > 0);
56
+ }
57
+ export async function* runPlanAdherenceReview(args) {
58
+ const maxRounds = Math.max(1, Math.min(4, args.maxRounds ?? 2));
59
+ const plan = args.planSynthesis.trim();
60
+ if (!plan)
61
+ return { rounds: 0, adherent: true, deviations: [] };
62
+ const getDiff = args.diffProvider ?? currentDiff;
63
+ let diff = getDiff(args.cwd);
64
+ if (!diff) {
65
+ yield { type: "content", content: `\n> [adherence] No diff to review for sprint ${args.sprintN}; skipping.\n` };
66
+ return { rounds: 0, adherent: true, deviations: [] };
67
+ }
68
+ let lastDeviations = [];
69
+ for (let round = 1; round <= maxRounds; round++) {
70
+ const reviewPrompt = `You are a SENIOR code reviewer. Judge whether the implementation faithfully ` +
71
+ `follows the APPROVED PLAN below — both its file_edits (right files, right ` +
72
+ `approach: e.g. pass-through vs re-implementation, correct operation/API) and ` +
73
+ `its acceptance_criteria. Be strict and specific.\n\n` +
74
+ `=== APPROVED PLAN ===\n${plan.slice(0, 9000)}\n\n` +
75
+ `=== ACTUAL GIT DIFF ===\n${diff.slice(0, 12000)}\n\n` +
76
+ `Return ONLY JSON: {"adherent": boolean, "deviations": [{"where":"<file/symbol>",` +
77
+ `"issue":"<what diverges from the plan>","fix":"<concrete instruction to conform>"}]}. ` +
78
+ `adherent=true ONLY if there are no material deviations.`;
79
+ const review = await runIsolatedGuarded(args.runIsolatedTask, {
80
+ agent: "general",
81
+ description: `Sprint ${args.sprintN} plan-adherence review (round ${round})`,
82
+ prompt: reviewPrompt,
83
+ modelId: args.reviewModelId,
84
+ maxToolRounds: 12,
85
+ }, `adherence-review-s${args.sprintN}-r${round}`);
86
+ const parsed = review.success ? parseReview(review.output ?? "") : null;
87
+ if (!parsed) {
88
+ yield {
89
+ type: "content",
90
+ content: `\n> [adherence] Reviewer produced no parseable verdict (round ${round}); leaving verify+criteria as the gate.\n`,
91
+ };
92
+ return { rounds: round, adherent: true, deviations: [] };
93
+ }
94
+ lastDeviations = normalizeDeviations(parsed.deviations);
95
+ const adherent = parsed.adherent === true || lastDeviations.length === 0;
96
+ if (adherent) {
97
+ yield {
98
+ type: "content",
99
+ content: `\n> [adherence] Round ${round}: reviewer (${args.reviewModelId}) confirms the implementation follows the plan.\n`,
100
+ };
101
+ return { rounds: round, adherent: true, deviations: [] };
102
+ }
103
+ yield {
104
+ type: "content",
105
+ content: `\n> [adherence] Round ${round}: ${lastDeviations.length} deviation(s) from plan:\n` +
106
+ lastDeviations.map((d) => ` - ${d}`).join("\n") +
107
+ "\n",
108
+ };
109
+ if (round === maxRounds) {
110
+ yield {
111
+ type: "content",
112
+ content: `\n> [adherence] Max rounds reached; deviations remain for the verify+criteria gate to catch.\n`,
113
+ };
114
+ return { rounds: round, adherent: false, deviations: lastDeviations };
115
+ }
116
+ // Hand the fix to the lower-tier agent.
117
+ const fixPrompt = `The implementation deviates from the APPROVED PLAN. A senior reviewer found ` +
118
+ `these deviations — fix EACH one by editing the code so it conforms to the plan. ` +
119
+ `Apply edits directly; do not narrate or re-plan.\n\n` +
120
+ `Deviations:\n${lastDeviations.map((d, i) => `${i + 1}. ${d}`).join("\n")}\n\n` +
121
+ `=== APPROVED PLAN (for reference) ===\n${plan.slice(0, 6000)}\n`;
122
+ yield {
123
+ type: "content",
124
+ content: `\n> [adherence] Dispatching fix task to ${args.fixModelId} (round ${round})…\n`,
125
+ };
126
+ const fix = await runIsolatedGuarded(args.runIsolatedTask, {
127
+ agent: "general",
128
+ description: `Sprint ${args.sprintN} plan-adherence fix (round ${round})`,
129
+ prompt: fixPrompt,
130
+ modelId: args.fixModelId,
131
+ }, `adherence-fix-s${args.sprintN}-r${round}`);
132
+ if (!fix.success) {
133
+ yield {
134
+ type: "content",
135
+ content: `\n> [adherence] Fix task failed (round ${round}): ${fix.error ?? "unknown"}; stopping the loop.\n`,
136
+ };
137
+ return { rounds: round, adherent: false, deviations: lastDeviations };
138
+ }
139
+ // Re-read the diff for the next review round.
140
+ diff = getDiff(args.cwd);
141
+ }
142
+ return { rounds: maxRounds, adherent: false, deviations: lastDeviations };
143
+ }
144
+ //# sourceMappingURL=plan-adherence-review.js.map
@@ -26,6 +26,139 @@ import type { ContinueFeedback } from "./feedback-routing.js";
26
26
  import type { DriverContext, IterationState, ProductSpec, RoleSlot } from "./types.js";
27
27
  /** @internal Test-only: reset CB-2 retry state for a given runId. */
28
28
  export declare function _resetCb2RetryUsed(runId: string): void;
29
+ /**
30
+ * Idle-chunk ceiling for the implementation stage (ms). Override with
31
+ * MUONROI_SPRINT_IMPL_IDLE_MS. This is a TIME-SINCE-LAST-CHUNK budget, not a
32
+ * total-turn cap — a legitimately long implementation streams progress the
33
+ * whole way, so it may run for many minutes, but it must never go completely
34
+ * silent (no chunk at all) for this long.
35
+ */
36
+ export declare function getImplIdleTimeoutMs(): number;
37
+ /**
38
+ * Hard total-elapsed ceiling for the implementation stage (ms). Override with
39
+ * MUONROI_SPRINT_IMPL_TOTAL_MS. Unlike the idle budget this is armed once and is
40
+ * NOT reset by chunks, so it catches a hang that keeps the idle guard alive with
41
+ * heartbeat/status chunks. Generous by default so a legitimately large sprint is
42
+ * not cut short; a genuine hang still terminates within this ceiling.
43
+ */
44
+ export declare function getImplTotalTimeoutMs(): number;
45
+ /**
46
+ * Whether the implement stage runs in an ISOLATED bounded sub-agent context
47
+ * (ctx.runIsolatedTask) instead of the shared top-level turn (processMessageFn).
48
+ * Default ON. Disable with MUONROI_SPRINT_ISOLATED_IMPL=0.
49
+ *
50
+ * The isolated path is the fix for the live ctx-overflow wedge: the flat
51
+ * processMessageFn turn inherited the full council-debate history (~5.9M tokens
52
+ * observed), started implementation already at ~94% context, then wedged after a
53
+ * mid-turn compaction. A fresh child context (getSubAgentBudgetChars cap +
54
+ * independent in-loop compaction) never inherits the debate, so it starts near
55
+ * empty and its clutter is absorbed as one compact ToolResult.
56
+ */
57
+ export declare function getSprintIsolatedImplEnabled(): boolean;
58
+ /**
59
+ * Pure decision: use the isolated sub-agent path for the implement stage?
60
+ * True only when the flag is on AND the driver actually provides the bridge
61
+ * (legacy/test drivers omit runIsolatedTask → fall back to processMessageFn).
62
+ * Extracted for unit testing without spinning up a full runSprint.
63
+ */
64
+ export declare function shouldUseIsolatedImpl(hasBridge: boolean, enabled?: boolean): boolean;
65
+ /**
66
+ * Imperative execution directive prepended to the sprint plan before it is
67
+ * handed to the orchestrator. The raw plan synthesis is a declarative design
68
+ * document; without this prefix the impl turn narrates it back instead of
69
+ * applying edits. Exported for test assertion. @internal
70
+ */
71
+ export declare const IMPL_EXECUTION_DIRECTIVE: string;
72
+ /**
73
+ * Wrap the implementation `processMessageFn` stream with an idle-chunk watchdog.
74
+ *
75
+ * Root cause it addresses (observed live 2026-07-08, /ideal resume of the
76
+ * gsd-core migration): the implementation stage delegates to the host
77
+ * orchestrator turn via `ctx.processMessageFn(implPrompt)` and consumes it with
78
+ * `for await (const chunk of implGen)`. The orchestrator turn finished its final
79
+ * LLM response cleanly (finishReason "stop", text-only) but the generator then
80
+ * suspended post-finish and never completed — the `for await` blocked for 17+
81
+ * minutes with NO chunk, NO phaseDone, NO advance to Verify, NO error. Because
82
+ * the LLM STREAM had already finished, the orchestrator's mid-stream
83
+ * time-to-next-chunk stall-watchdog does not fire — the hang is on the JS side
84
+ * after the stream terminator.
85
+ *
86
+ * TWO complementary guards (a single idle guard was observed live to be
87
+ * defeated: the impl created 2 files then emitted only non-progress heartbeat
88
+ * chunks for 9+ min, resetting a per-chunk idle timer without ever completing):
89
+ * - `idleMs` — resets on every yielded chunk; catches a TOTALLY silent stall
90
+ * (the post-finish hang above, zero chunks) quickly.
91
+ * - `totalMs` — armed ONCE at entry, NOT reset by chunks; a hard ceiling that
92
+ * fires even when heartbeat/status chunks keep the idle guard alive while no
93
+ * real progress is made.
94
+ * Either firing throws so the caller's existing try/catch converts the wedge
95
+ * into a visible phaseError (the sprint then surfaces + can recover), exactly
96
+ * like `runVerifyWithWatchdog` does for the verify stage. The suspended
97
+ * orchestrator promise may leak in the background, but the run recovers.
98
+ */
99
+ export declare function withImplIdleWatchdog(gen: AsyncGenerator<StreamChunk, void, unknown>, idleMs: number, sprintN: number, totalMs?: number): AsyncGenerator<StreamChunk, void, unknown>;
100
+ /**
101
+ * Wall-clock deadline for the ISOLATED implementation path.
102
+ *
103
+ * The isolated path (`ctx.runIsolatedTask`) returns a single Promise, not a
104
+ * stream, so `withImplIdleWatchdog` (which guards the streamed non-isolated
105
+ * path) cannot wrap it. Its only protection was the sub-agent's INTERNAL
106
+ * per-chunk stall-watchdog — which does NOT fire once the sub-agent's LLM stream
107
+ * has finished but its orchestrator turn hangs on the JS side afterwards (the
108
+ * exact "wrote N files then went silent" wedge documented on
109
+ * `withImplIdleWatchdog`). Observed live 2026-07-12 (run mrhc43f0fb9b): the
110
+ * isolated impl wrote 2 files, emitted its final `llm-done`, then wedged for 30+
111
+ * min with zero events and an idle process — because this `await` had no outer
112
+ * ceiling.
113
+ *
114
+ * This races the isolated task against a hard total-elapsed deadline. On
115
+ * timeout it rejects so the caller's existing try/catch converts the wedge into
116
+ * a visible phaseError (the sprint surfaces + can recover), mirroring what
117
+ * `withImplIdleWatchdog` / `runVerifyWithWatchdog` do for the other stages. The
118
+ * suspended sub-agent promise may leak in the background, but the run recovers.
119
+ * `totalMs <= 0` disables the guard (returns the task unchanged).
120
+ */
121
+ /**
122
+ * Extract why an isolated implementation task failed, from its ToolResult.
123
+ *
124
+ * `output` is checked because StreamRunner reports EVERY sub-agent failure
125
+ * there — "Task failed: …" (stream-runner.ts:1061), "[Cancelled]" (:982), a
126
+ * provider stall (:988), an unknown-agent message (:265) — and never assigns
127
+ * `error`; grep stream-runner.ts for `error:` and there are no hits. Reading
128
+ * `error` alone made `result.error?.trim()` permanently undefined, so every
129
+ * distinct failure collapsed into the contentless fallback and two /ideal runs
130
+ * halted 1s into implementation with the cause already erased.
131
+ *
132
+ * `error` still wins when a caller does populate it — ToolResult declares the
133
+ * field, so a future non-StreamRunner producer may be more specific.
134
+ */
135
+ export declare function resolveImplFailureReason(result: {
136
+ output?: string;
137
+ error?: string;
138
+ }): string;
139
+ /**
140
+ * Persist an implementation-stage failure to `interaction_logs`.
141
+ *
142
+ * The implementation stage is where /ideal either ships code or does not, so its
143
+ * exception is the single most valuable line in a post-mortem — yet run
144
+ * mrn9yfle9801 halted with only `halt_card_open {trigger:"loop_throw"}` on
145
+ * record and the message itself unrecoverable: stderr belongs to the TUI child
146
+ * (the harness never captures it) and the council path writes no `messages`
147
+ * rows. `elapsedMs` is what separates the two indistinguishable causes — an
148
+ * immediate `!result.success` from a `withIsolatedImplDeadline` watchdog trip.
149
+ *
150
+ * Never throws: a broken audit trail must not take down the sprint it is
151
+ * describing.
152
+ */
153
+ export declare function logSprintImplError(ctx: DriverContext, info: {
154
+ sprintN: number;
155
+ message: string;
156
+ stack?: string;
157
+ implModelId?: string;
158
+ elapsedMs: number;
159
+ isolated: boolean;
160
+ }): void;
161
+ export declare function withIsolatedImplDeadline<T>(task: Promise<T>, totalMs: number, sprintN: number): Promise<T>;
29
162
  export { computeFailureSignature, loadVerifyFailureSignatures, pushFailureToEE, recordVerifyFailureAndMaybePush, saveVerifyFailureSignatures, type VerifyFailureRecord, type VerifyFailureSignatures, } from "./verify-failure-tracking.js";
30
163
  export interface RunSprintArgs {
31
164
  sprintN: number;
@@ -60,4 +193,44 @@ export interface RunSprintArgs {
60
193
  * Throws on circuit-breaker halt — caller (loop driver) catches and writes
61
194
  * the appropriate halt state to manifest/state.
62
195
  */
196
+ /** Path to the persisted per-sprint plan synthesis (Wave 2). @internal */
197
+ export declare function sprintPlanPath(runDir: string, sprintN: number): string;
198
+ /**
199
+ * Wave 2: read a persisted sprint plan if present. Returns "" when absent or on
200
+ * read error (caller then runs the planning council). Never throws.
201
+ *
202
+ * The planning council is non-deterministic — re-running it on a resumed/retried
203
+ * sprint produces a different design AND a different target folder, which is why
204
+ * the impl turn was observed re-scaffolding in a new location each run. Reusing
205
+ * the persisted plan makes per-sprint planning idempotent so the same target
206
+ * files are continued across resume.
207
+ */
208
+ export declare function readPersistedSprintPlan(planPath: string): Promise<string>;
209
+ /** Wave 2: persist a sprint plan synthesis for idempotent resume. Never throws. */
210
+ export declare function persistSprintPlan(planPath: string, synthesis: string): Promise<void>;
211
+ /**
212
+ * Extract repo-relative target file paths a sprint plan names (src/…, packages/…,
213
+ * tests/…). Deduped, capped. Used by Wave 3 (existing targets → continue) and 4A
214
+ * (missing targets → completeness re-check). Never throws.
215
+ */
216
+ export declare function extractPlanTargetPaths(planSynthesis: string, cap?: number): string[];
217
+ /**
218
+ * Wave 3: plan-named target file paths that ALREADY EXIST on disk, so the impl
219
+ * turn continues them rather than re-scaffolding in a new location. Empty on a
220
+ * greenfield sprint (files don't exist yet) → no injection.
221
+ */
222
+ export declare function detectExistingPlanTargets(planSynthesis: string, cwd: string, cap?: number): Promise<string[]>;
223
+ /**
224
+ * 4A: plan-named target file paths that STILL DO NOT EXIST after the impl turn —
225
+ * i.e. action items the implementer left unaddressed. Drives the post-impl
226
+ * completeness re-check (spend an extra turn ONLY when there is proven-incomplete
227
+ * work, unlike an unconditional reviewer pass). Empty ⇒ every named target landed.
228
+ */
229
+ export declare function computeMissingPlanTargets(planSynthesis: string, cwd: string, cap?: number): Promise<string[]>;
230
+ /**
231
+ * 4A completeness re-check toggle. Default ON; disable with
232
+ * MUONROI_SPRINT_IMPL_RECHECK=0. When on, and the impl turn left plan-named
233
+ * target files missing, ONE focused follow-up turn is spent to finish them.
234
+ */
235
+ export declare function getImplRecheckEnabled(): boolean;
63
236
  export declare function runSprint(args: RunSprintArgs): AsyncGenerator<StreamChunk, IterationState, unknown>;