muonroi-cli 1.8.3 → 1.8.5

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 (477) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +133 -122
  3. package/dist/packages/agent-harness-core/src/driver.d.ts +27 -1
  4. package/dist/packages/agent-harness-core/src/driver.js +46 -0
  5. package/dist/packages/agent-harness-core/src/event-tee.d.ts +48 -0
  6. package/dist/packages/agent-harness-core/src/event-tee.js +77 -0
  7. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +11 -0
  8. package/dist/packages/agent-harness-core/src/mcp-server.js +87 -15
  9. package/dist/packages/agent-harness-core/src/protocol.d.ts +66 -2
  10. package/dist/packages/agent-harness-core/src/protocol.js +15 -0
  11. package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
  12. package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
  13. package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
  14. package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
  15. package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
  16. package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
  17. package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
  18. package/dist/packages/agent-harness-opentui/src/install.js +10 -0
  19. package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
  20. package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
  21. package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
  22. package/dist/src/agent-harness/mock-model.d.ts +28 -0
  23. package/dist/src/agent-harness/mock-model.js +63 -1
  24. package/dist/src/agent-harness/test-spawn.js +31 -0
  25. package/dist/src/cli/config/screen-providers.js +1 -1
  26. package/dist/src/cli/cost-forensics.d.ts +10 -0
  27. package/dist/src/cli/cost-forensics.js +30 -15
  28. package/dist/src/cli/keys-bundle.d.ts +1 -1
  29. package/dist/src/cli/keys-bundle.js +1 -1
  30. package/dist/src/cli/keys.d.ts +2 -2
  31. package/dist/src/cli/keys.js +19 -81
  32. package/dist/src/council/clarifier.d.ts +28 -2
  33. package/dist/src/council/clarifier.js +81 -15
  34. package/dist/src/council/context.js +49 -15
  35. package/dist/src/council/debate-checkpoint.d.ts +129 -0
  36. package/dist/src/council/debate-checkpoint.js +176 -0
  37. package/dist/src/council/debate-planner.js +51 -3
  38. package/dist/src/council/debate-summary.d.ts +25 -0
  39. package/dist/src/council/debate-summary.js +85 -0
  40. package/dist/src/council/debate.d.ts +169 -2
  41. package/dist/src/council/debate.js +1210 -134
  42. package/dist/src/council/index.d.ts +85 -1
  43. package/dist/src/council/index.js +634 -196
  44. package/dist/src/council/leader.d.ts +26 -0
  45. package/dist/src/council/leader.js +150 -9
  46. package/dist/src/council/llm.d.ts +32 -0
  47. package/dist/src/council/llm.js +231 -38
  48. package/dist/src/council/panel-select.d.ts +30 -0
  49. package/dist/src/council/panel-select.js +72 -0
  50. package/dist/src/council/planner.js +23 -0
  51. package/dist/src/council/preflight.d.ts +7 -0
  52. package/dist/src/council/preflight.js +14 -2
  53. package/dist/src/council/prompts.d.ts +30 -3
  54. package/dist/src/council/prompts.js +254 -84
  55. package/dist/src/council/stance-recall.d.ts +42 -0
  56. package/dist/src/council/stance-recall.js +57 -0
  57. package/dist/src/council/strip-think.d.ts +17 -0
  58. package/dist/src/council/strip-think.js +33 -0
  59. package/dist/src/council/types.d.ts +128 -0
  60. package/dist/src/ee/artifact-cache.d.ts +16 -0
  61. package/dist/src/ee/artifact-cache.js +32 -0
  62. package/dist/src/ee/auth.d.ts +1 -0
  63. package/dist/src/ee/auth.js +15 -2
  64. package/dist/src/ee/bridge.d.ts +10 -0
  65. package/dist/src/ee/bridge.js +58 -0
  66. package/dist/src/ee/client.js +81 -18
  67. package/dist/src/ee/export-transcripts.d.ts +1 -0
  68. package/dist/src/ee/export-transcripts.js +8 -10
  69. package/dist/src/ee/extract-session.js +29 -0
  70. package/dist/src/ee/extract-style.d.ts +58 -0
  71. package/dist/src/ee/extract-style.js +270 -0
  72. package/dist/src/ee/recall-ledger.d.ts +9 -0
  73. package/dist/src/ee/recall-ledger.js +3 -0
  74. package/dist/src/ee/scope.d.ts +1 -0
  75. package/dist/src/ee/scope.js +26 -1
  76. package/dist/src/ee/search.d.ts +7 -0
  77. package/dist/src/ee/search.js +24 -0
  78. package/dist/src/ee/transcript-emit.js +2 -0
  79. package/dist/src/ee/types.d.ts +22 -0
  80. package/dist/src/ee/who-am-i-brain.d.ts +35 -0
  81. package/dist/src/ee/who-am-i-brain.js +220 -0
  82. package/dist/src/ee/who-am-i.d.ts +10 -3
  83. package/dist/src/ee/who-am-i.js +12 -0
  84. package/dist/src/ee/workflow-event.d.ts +48 -0
  85. package/dist/src/ee/workflow-event.js +81 -0
  86. package/dist/src/flow/compaction/compress.d.ts +3 -3
  87. package/dist/src/flow/compaction/compress.js +45 -8
  88. package/dist/src/flow/compaction/extract.d.ts +4 -7
  89. package/dist/src/flow/compaction/extract.js +50 -10
  90. package/dist/src/flow/compaction/index.d.ts +13 -1
  91. package/dist/src/flow/compaction/index.js +70 -3
  92. package/dist/src/flow/compaction/input-guard.d.ts +24 -0
  93. package/dist/src/flow/compaction/input-guard.js +43 -0
  94. package/dist/src/flow/fold-planning.d.ts +36 -0
  95. package/dist/src/flow/fold-planning.js +83 -0
  96. package/dist/src/flow/hierarchy.d.ts +146 -0
  97. package/dist/src/flow/hierarchy.js +427 -0
  98. package/dist/src/flow/index.d.ts +1 -0
  99. package/dist/src/flow/index.js +2 -0
  100. package/dist/src/flow/run-artifacts.d.ts +102 -0
  101. package/dist/src/flow/run-artifacts.js +208 -0
  102. package/dist/src/generated/version.d.ts +1 -1
  103. package/dist/src/generated/version.js +1 -1
  104. package/dist/src/gsd/assessment-schema.d.ts +44 -0
  105. package/dist/src/gsd/assessment-schema.js +134 -0
  106. package/dist/src/gsd/capability-registry.d.ts +45 -0
  107. package/dist/src/gsd/capability-registry.js +337 -0
  108. package/dist/src/gsd/complexity-assessor.d.ts +39 -0
  109. package/dist/src/gsd/complexity-assessor.js +152 -0
  110. package/dist/src/gsd/config-bridge.d.ts +7 -0
  111. package/dist/src/gsd/config-bridge.js +114 -0
  112. package/dist/src/gsd/config-loader.d.ts +27 -0
  113. package/dist/src/gsd/config-loader.js +50 -0
  114. package/dist/src/gsd/council-context.d.ts +44 -0
  115. package/dist/src/gsd/council-context.js +114 -0
  116. package/dist/src/gsd/ee-closure.d.ts +28 -0
  117. package/dist/src/gsd/ee-closure.js +49 -0
  118. package/dist/src/gsd/flags.d.ts +55 -0
  119. package/dist/src/gsd/flags.js +83 -0
  120. package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
  121. package/dist/src/gsd/gsd-dispatch.js +131 -0
  122. package/dist/src/gsd/gsd-runtime.d.ts +22 -0
  123. package/dist/src/gsd/gsd-runtime.js +37 -0
  124. package/dist/src/gsd/host-adapter.d.ts +11 -0
  125. package/dist/src/gsd/host-adapter.js +29 -0
  126. package/dist/src/gsd/index.d.ts +24 -1
  127. package/dist/src/gsd/index.js +27 -0
  128. package/dist/src/gsd/loop-host-contract.d.ts +21 -0
  129. package/dist/src/gsd/loop-host-contract.js +39 -0
  130. package/dist/src/gsd/loop-host.d.ts +69 -0
  131. package/dist/src/gsd/loop-host.js +245 -0
  132. package/dist/src/gsd/loop-resolver.d.ts +36 -0
  133. package/dist/src/gsd/loop-resolver.js +79 -0
  134. package/dist/src/gsd/model-tier.d.ts +13 -0
  135. package/dist/src/gsd/model-tier.js +45 -0
  136. package/dist/src/gsd/mutation-gate.d.ts +16 -0
  137. package/dist/src/gsd/mutation-gate.js +41 -0
  138. package/dist/src/gsd/native-roadmap.d.ts +89 -0
  139. package/dist/src/gsd/native-roadmap.js +343 -0
  140. package/dist/src/gsd/native-state.d.ts +47 -0
  141. package/dist/src/gsd/native-state.js +220 -0
  142. package/dist/src/gsd/paths.d.ts +23 -0
  143. package/dist/src/gsd/paths.js +66 -0
  144. package/dist/src/gsd/phase-dag.d.ts +12 -0
  145. package/dist/src/gsd/phase-dag.js +94 -0
  146. package/dist/src/gsd/phase-sync.d.ts +42 -0
  147. package/dist/src/gsd/phase-sync.js +321 -0
  148. package/dist/src/gsd/pil-gate-context.d.ts +13 -0
  149. package/dist/src/gsd/pil-gate-context.js +64 -0
  150. package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
  151. package/dist/src/gsd/pil-gate-critic.js +74 -0
  152. package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
  153. package/dist/src/gsd/plan-council-prompts.js +79 -0
  154. package/dist/src/gsd/plan-council.d.ts +44 -0
  155. package/dist/src/gsd/plan-council.js +251 -0
  156. package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
  157. package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
  158. package/dist/src/gsd/product-workspace.d.ts +13 -0
  159. package/dist/src/gsd/product-workspace.js +124 -0
  160. package/dist/src/gsd/ship-bridge.d.ts +25 -0
  161. package/dist/src/gsd/ship-bridge.js +65 -0
  162. package/dist/src/gsd/state-document.d.ts +40 -0
  163. package/dist/src/gsd/state-document.js +163 -0
  164. package/dist/src/gsd/verdict-schema.d.ts +39 -0
  165. package/dist/src/gsd/verdict-schema.js +144 -0
  166. package/dist/src/gsd/verify-context.d.ts +22 -0
  167. package/dist/src/gsd/verify-context.js +27 -0
  168. package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
  169. package/dist/src/gsd/verify-council-prompts.js +85 -0
  170. package/dist/src/gsd/verify-council.d.ts +25 -0
  171. package/dist/src/gsd/verify-council.js +119 -0
  172. package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
  173. package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
  174. package/dist/src/gsd/workflow-engine.d.ts +60 -0
  175. package/dist/src/gsd/workflow-engine.js +207 -0
  176. package/dist/src/gsd/workflow-tools.d.ts +13 -0
  177. package/dist/src/gsd/workflow-tools.js +277 -0
  178. package/dist/src/hooks/index.js +1 -1
  179. package/dist/src/index.js +44 -11
  180. package/dist/src/maintain/pr-builder.js +23 -13
  181. package/dist/src/mcp/auto-setup.js +57 -32
  182. package/dist/src/mcp/client-pool.js +1 -1
  183. package/dist/src/mcp/ee-tools.js +1 -0
  184. package/dist/src/mcp/oauth-callback.js +2 -2
  185. package/dist/src/mcp/research-onboarding.js +8 -7
  186. package/dist/src/mcp/runtime.js +34 -2
  187. package/dist/src/mcp/setup-guide-text.d.ts +1 -1
  188. package/dist/src/mcp/setup-guide-text.js +77 -76
  189. package/dist/src/models/catalog-client.d.ts +87 -0
  190. package/dist/src/models/catalog-client.js +105 -38
  191. package/dist/src/models/catalog.json +528 -265
  192. package/dist/src/models/registry.d.ts +22 -7
  193. package/dist/src/models/registry.js +73 -10
  194. package/dist/src/ops/doctor.js +8 -8
  195. package/dist/src/orchestrator/auto-commit.js +1 -1
  196. package/dist/src/orchestrator/batch-turn-runner.js +2 -2
  197. package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
  198. package/dist/src/orchestrator/cache-prefix.js +83 -0
  199. package/dist/src/orchestrator/compact-request.d.ts +32 -0
  200. package/dist/src/orchestrator/compact-request.js +41 -0
  201. package/dist/src/orchestrator/compaction.d.ts +10 -0
  202. package/dist/src/orchestrator/compaction.js +27 -7
  203. package/dist/src/orchestrator/council-manager.d.ts +12 -3
  204. package/dist/src/orchestrator/council-manager.js +65 -24
  205. package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
  206. package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
  207. package/dist/src/orchestrator/error-utils.d.ts +29 -0
  208. package/dist/src/orchestrator/error-utils.js +132 -24
  209. package/dist/src/orchestrator/grounding-check.js +39 -1
  210. package/dist/src/orchestrator/message-processor.js +242 -33
  211. package/dist/src/orchestrator/orchestrator.d.ts +39 -3
  212. package/dist/src/orchestrator/orchestrator.js +651 -102
  213. package/dist/src/orchestrator/preprocessor.js +1 -1
  214. package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
  215. package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
  216. package/dist/src/orchestrator/prompts.js +159 -159
  217. package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
  218. package/dist/src/orchestrator/reactive-delegation.js +59 -0
  219. package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
  220. package/dist/src/orchestrator/retry-classifier.js +46 -2
  221. package/dist/src/orchestrator/safety-intercept.d.ts +45 -0
  222. package/dist/src/orchestrator/safety-intercept.js +55 -0
  223. package/dist/src/orchestrator/scope-reminder.js +1 -1
  224. package/dist/src/orchestrator/session-experience.d.ts +2 -1
  225. package/dist/src/orchestrator/session-experience.js +2 -1
  226. package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
  227. package/dist/src/orchestrator/should-run-gate.js +18 -0
  228. package/dist/src/orchestrator/stall-watchdog.d.ts +24 -3
  229. package/dist/src/orchestrator/stall-watchdog.js +47 -13
  230. package/dist/src/orchestrator/stream-runner.js +62 -29
  231. package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
  232. package/dist/src/orchestrator/sub-agent-cap.js +16 -1
  233. package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
  234. package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
  235. package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
  236. package/dist/src/orchestrator/subagent-compactor.js +126 -15
  237. package/dist/src/orchestrator/tool-engine.d.ts +26 -0
  238. package/dist/src/orchestrator/tool-engine.js +669 -56
  239. package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
  240. package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
  241. package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
  242. package/dist/src/orchestrator/turn-watchdog.d.ts +37 -0
  243. package/dist/src/orchestrator/turn-watchdog.js +55 -0
  244. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  245. package/dist/src/pil/agent-operating-contract.js +1 -1
  246. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  247. package/dist/src/pil/cheap-model-playbook.js +5 -1
  248. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  249. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  250. package/dist/src/pil/discovery-types.d.ts +1 -0
  251. package/dist/src/pil/discovery.js +16 -11
  252. package/dist/src/pil/layer1-intent.d.ts +18 -6
  253. package/dist/src/pil/layer1-intent.js +66 -757
  254. package/dist/src/pil/layer15-context-scan.js +15 -1
  255. package/dist/src/pil/layer2_5-ponytail.js +8 -8
  256. package/dist/src/pil/layer3-ee-injection.js +23 -8
  257. package/dist/src/pil/layer4-gsd.js +69 -16
  258. package/dist/src/pil/layer5-context.js +7 -3
  259. package/dist/src/pil/layer6-output.d.ts +23 -0
  260. package/dist/src/pil/layer6-output.js +5 -1
  261. package/dist/src/pil/llm-classify.d.ts +33 -2
  262. package/dist/src/pil/llm-classify.js +123 -131
  263. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  264. package/dist/src/pil/native-capabilities-workbook.js +1 -0
  265. package/dist/src/pil/pipeline.js +34 -2
  266. package/dist/src/pil/response-tools.js +5 -3
  267. package/dist/src/pil/schema.d.ts +1 -0
  268. package/dist/src/pil/schema.js +2 -0
  269. package/dist/src/pil/types.d.ts +18 -0
  270. package/dist/src/playbook/directives.d.ts +4 -0
  271. package/dist/src/playbook/directives.js +17 -5
  272. package/dist/src/product-loop/backlog-builder.d.ts +14 -1
  273. package/dist/src/product-loop/backlog-builder.js +30 -6
  274. package/dist/src/product-loop/discovery-context-format.js +3 -1
  275. package/dist/src/product-loop/discovery-ecosystem.js +4 -1
  276. package/dist/src/product-loop/discovery-interview.js +32 -3
  277. package/dist/src/product-loop/discovery-schema.js +5 -1
  278. package/dist/src/product-loop/done-gate.js +3 -3
  279. package/dist/src/product-loop/ideal-trace.d.ts +7 -0
  280. package/dist/src/product-loop/ideal-trace.js +64 -0
  281. package/dist/src/product-loop/index.d.ts +13 -1
  282. package/dist/src/product-loop/index.js +333 -52
  283. package/dist/src/product-loop/loop-driver.d.ts +7 -0
  284. package/dist/src/product-loop/loop-driver.js +327 -116
  285. package/dist/src/product-loop/phase-plan.d.ts +5 -0
  286. package/dist/src/product-loop/phase-plan.js +39 -2
  287. package/dist/src/product-loop/phase-runner.js +9 -1
  288. package/dist/src/product-loop/progress-snapshot.js +4 -4
  289. package/dist/src/product-loop/sprint-runner.d.ts +111 -0
  290. package/dist/src/product-loop/sprint-runner.js +559 -16
  291. package/dist/src/product-loop/types.d.ts +36 -5
  292. package/dist/src/providers/adapter.d.ts +1 -1
  293. package/dist/src/providers/adapter.js +3 -4
  294. package/dist/src/providers/auth/browser-flow.d.ts +1 -1
  295. package/dist/src/providers/auth/browser-flow.js +1 -1
  296. package/dist/src/providers/auth/openai-oauth.js +1 -1
  297. package/dist/src/providers/auth/registry.js +0 -34
  298. package/dist/src/providers/auth/token-store.js +4 -1
  299. package/dist/src/providers/auth/types.d.ts +1 -1
  300. package/dist/src/providers/auth/types.js +1 -1
  301. package/dist/src/providers/capabilities.d.ts +24 -5
  302. package/dist/src/providers/capabilities.js +42 -24
  303. package/dist/src/providers/endpoints.d.ts +2 -2
  304. package/dist/src/providers/endpoints.js +11 -10
  305. package/dist/src/providers/keychain.d.ts +1 -1
  306. package/dist/src/providers/keychain.js +7 -9
  307. package/dist/src/providers/mcp-vision-bridge.js +82 -172
  308. package/dist/src/providers/openai-compatible.js +8 -1
  309. package/dist/src/providers/pricing.d.ts +2 -2
  310. package/dist/src/providers/pricing.js +3 -13
  311. package/dist/src/providers/runtime.d.ts +27 -2
  312. package/dist/src/providers/runtime.js +78 -15
  313. package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
  314. package/dist/src/providers/strategies/base.strategy.js +24 -1
  315. package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
  316. package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
  317. package/dist/src/providers/strategies/registry.js +4 -4
  318. package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
  319. package/dist/src/providers/strategies/thinking-mode.js +280 -1
  320. package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
  321. package/dist/src/providers/strategies/zai.strategy.js +44 -0
  322. package/dist/src/providers/types.d.ts +5 -6
  323. package/dist/src/providers/types.js +2 -2
  324. package/dist/src/providers/vision-backend.d.ts +47 -0
  325. package/dist/src/providers/vision-backend.js +258 -0
  326. package/dist/src/providers/vision-proxy.d.ts +22 -9
  327. package/dist/src/providers/vision-proxy.js +63 -132
  328. package/dist/src/providers/wire-debug.js +95 -0
  329. package/dist/src/reporter/index.js +1 -1
  330. package/dist/src/router/decide.d.ts +13 -0
  331. package/dist/src/router/decide.js +138 -36
  332. package/dist/src/router/peak-hour.d.ts +38 -0
  333. package/dist/src/router/peak-hour.js +107 -0
  334. package/dist/src/router/step-router.js +3 -2
  335. package/dist/src/router/warm.js +4 -5
  336. package/dist/src/scaffold/bb-ecosystem-apply.js +47 -47
  337. package/dist/src/scaffold/bb-quality-gate.js +5 -5
  338. package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
  339. package/dist/src/scaffold/continuation-prompt.js +86 -60
  340. package/dist/src/scaffold/init-new.js +453 -453
  341. package/dist/src/scaffold/point-to-existing.d.ts +21 -0
  342. package/dist/src/scaffold/point-to-existing.js +25 -0
  343. package/dist/src/self-qa/agentic-loop.js +22 -22
  344. package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
  345. package/dist/src/{ui/state → state}/active-run.js +21 -0
  346. package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
  347. package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
  348. package/dist/src/state/turn-trace.d.ts +43 -0
  349. package/dist/src/state/turn-trace.js +32 -0
  350. package/dist/src/storage/db.js +2 -1
  351. package/dist/src/storage/index.d.ts +1 -1
  352. package/dist/src/storage/index.js +1 -1
  353. package/dist/src/storage/interaction-log.d.ts +1 -1
  354. package/dist/src/storage/interaction-log.js +5 -5
  355. package/dist/src/storage/migrations.js +196 -126
  356. package/dist/src/storage/session-experience-store.js +4 -4
  357. package/dist/src/storage/sessions.d.ts +28 -10
  358. package/dist/src/storage/sessions.js +112 -55
  359. package/dist/src/storage/transcript-view.js +1 -1
  360. package/dist/src/storage/transcript.d.ts +51 -0
  361. package/dist/src/storage/transcript.js +383 -112
  362. package/dist/src/storage/usage.js +14 -14
  363. package/dist/src/storage/workspaces.js +12 -12
  364. package/dist/src/tools/file.d.ts +15 -0
  365. package/dist/src/tools/file.js +32 -0
  366. package/dist/src/tools/native-tools.js +5 -0
  367. package/dist/src/tools/registry.d.ts +3 -0
  368. package/dist/src/tools/registry.js +460 -22
  369. package/dist/src/tools/research.d.ts +29 -0
  370. package/dist/src/tools/research.js +233 -0
  371. package/dist/src/types/index.d.ts +118 -3
  372. package/dist/src/ui/app.js +0 -0
  373. package/dist/src/ui/cards/product-status-card.js +1 -1
  374. package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
  375. package/dist/src/ui/components/bubble-body-guard.js +50 -0
  376. package/dist/src/ui/components/context-rail.d.ts +26 -0
  377. package/dist/src/ui/components/context-rail.js +33 -0
  378. package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
  379. package/dist/src/ui/components/council-conclusion-card.js +420 -0
  380. package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
  381. package/dist/src/ui/components/council-debate-pill.js +34 -0
  382. package/dist/src/ui/components/council-info-card.js +2 -2
  383. package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
  384. package/dist/src/ui/components/council-leader-bubble.js +21 -11
  385. package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
  386. package/dist/src/ui/components/council-message-bubble.js +16 -15
  387. package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
  388. package/dist/src/ui/components/council-phase-timeline.js +49 -15
  389. package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
  390. package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
  391. package/dist/src/ui/components/council-question-card.js +12 -12
  392. package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
  393. package/dist/src/ui/components/council-rail-rounds.js +57 -0
  394. package/dist/src/ui/components/council-round-group.d.ts +38 -0
  395. package/dist/src/ui/components/council-round-group.js +88 -0
  396. package/dist/src/ui/components/council-status-list.d.ts +3 -1
  397. package/dist/src/ui/components/council-status-list.js +36 -24
  398. package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
  399. package/dist/src/ui/components/council-synthesis-banner.js +20 -5
  400. package/dist/src/ui/components/halt-recovery-card.js +9 -5
  401. package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
  402. package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
  403. package/dist/src/ui/components/prompt-box.js +18 -16
  404. package/dist/src/ui/components/session-tree-card.d.ts +14 -0
  405. package/dist/src/ui/components/session-tree-card.js +46 -0
  406. package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
  407. package/dist/src/ui/components/slash-inline-menu.js +26 -5
  408. package/dist/src/ui/components/task-list-panel.d.ts +14 -1
  409. package/dist/src/ui/components/task-list-panel.js +22 -2
  410. package/dist/src/ui/containers/modals-layer.d.ts +2 -1
  411. package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
  412. package/dist/src/ui/mcp-modal.js +2 -4
  413. package/dist/src/ui/modals/api-key-modal.js +1 -1
  414. package/dist/src/ui/modals/connect-modal.js +4 -3
  415. package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
  416. package/dist/src/ui/modals/session-picker-modal.js +3 -5
  417. package/dist/src/ui/picker-providers.d.ts +1 -1
  418. package/dist/src/ui/picker-providers.js +1 -1
  419. package/dist/src/ui/primitives/index.d.ts +1 -0
  420. package/dist/src/ui/primitives/index.js +2 -0
  421. package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
  422. package/dist/src/ui/primitives/semantic-primitives.js +81 -0
  423. package/dist/src/ui/slash/compact.js +5 -7
  424. package/dist/src/ui/slash/cost.js +1 -1
  425. package/dist/src/ui/slash/council-inspect.js +4 -4
  426. package/dist/src/ui/slash/council.js +19 -1
  427. package/dist/src/ui/slash/debug.d.ts +3 -31
  428. package/dist/src/ui/slash/debug.js +9 -20
  429. package/dist/src/ui/slash/ideal.d.ts +6 -2
  430. package/dist/src/ui/slash/ideal.js +97 -7
  431. package/dist/src/ui/slash/menu-items.d.ts +7 -0
  432. package/dist/src/ui/slash/menu-items.js +12 -18
  433. package/dist/src/ui/slash/registry.d.ts +2 -0
  434. package/dist/src/ui/slash/registry.js +4 -0
  435. package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
  436. package/dist/src/ui/status-bar/cache-hit.js +9 -0
  437. package/dist/src/ui/status-bar/index.d.ts +1 -1
  438. package/dist/src/ui/status-bar/index.js +7 -3
  439. package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
  440. package/dist/src/ui/status-bar/usd-meter.js +6 -4
  441. package/dist/src/ui/theme.d.ts +1 -0
  442. package/dist/src/ui/theme.js +2 -0
  443. package/dist/src/ui/types.d.ts +7 -0
  444. package/dist/src/ui/use-app-logic.js +0 -0
  445. package/dist/src/ui/utils/format.d.ts +14 -0
  446. package/dist/src/ui/utils/format.js +23 -3
  447. package/dist/src/usage/downgrade.js +2 -2
  448. package/dist/src/usage/product-ledger.js +2 -2
  449. package/dist/src/utils/clipboard-image.js +23 -23
  450. package/dist/src/utils/install-manager.js +14 -11
  451. package/dist/src/utils/logger.js +2 -2
  452. package/dist/src/utils/permission-mode.js +5 -3
  453. package/dist/src/utils/redactor.js +1 -1
  454. package/dist/src/utils/settings.d.ts +153 -5
  455. package/dist/src/utils/settings.js +233 -29
  456. package/dist/src/utils/side-question.js +2 -2
  457. package/dist/src/utils/skills.js +3 -3
  458. package/dist/src/utils/visible-retry.d.ts +11 -0
  459. package/dist/src/utils/visible-retry.js +10 -1
  460. package/dist/src/verify/entrypoint.d.ts +1 -1
  461. package/dist/src/verify/entrypoint.js +1 -1
  462. package/dist/src/verify/recipes.d.ts +13 -0
  463. package/dist/src/verify/recipes.js +15 -0
  464. package/package.json +135 -132
  465. package/dist/src/providers/auth/gcloud.d.ts +0 -28
  466. package/dist/src/providers/auth/gcloud.js +0 -102
  467. package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
  468. package/dist/src/providers/auth/gemini-oauth.js +0 -472
  469. package/dist/src/providers/gemini.d.ts +0 -11
  470. package/dist/src/providers/gemini.js +0 -45
  471. package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
  472. package/dist/src/providers/siliconflow-sse-repair.js +0 -177
  473. package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
  474. package/dist/src/providers/strategies/google.strategy.js +0 -174
  475. package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
  476. package/dist/src/ui/containers/chat-feed.d.ts +0 -40
  477. package/dist/src/ui/containers/chat-feed.js +0 -66
@@ -0,0 +1,45 @@
1
+ import { getModelByTier, getModelInfo, getModelsForProvider } from "../models/registry.js";
2
+ import { detectProviderForModel } from "../providers/runtime.js";
3
+ const TIER_RANK = { fast: 0, balanced: 1, premium: 2 };
4
+ /**
5
+ * GSD-only premium resolver — always picks the highest-tier model on the
6
+ * session provider for plan-council / verify gates. Unlike
7
+ * resolveLeaderModelDetailed, this intentionally promotes within-provider
8
+ * for critical GSD stages.
9
+ */
10
+ export function resolveGsdPremiumModel(sessionModelId) {
11
+ const providerId = detectProviderForModel(sessionModelId);
12
+ let best;
13
+ for (const m of getModelsForProvider(providerId)) {
14
+ if (m.tierRouting === false)
15
+ continue;
16
+ if (!m.tier)
17
+ continue;
18
+ if (!best || TIER_RANK[m.tier] > TIER_RANK[best.tier]) {
19
+ best = { id: m.id, tier: m.tier };
20
+ }
21
+ }
22
+ if (best)
23
+ return best.id;
24
+ const premium = getModelByTier("premium", providerId);
25
+ if (premium)
26
+ return premium.id;
27
+ return sessionModelId;
28
+ }
29
+ /** Research perspectives ground against the codebase; others validate rigorously. */
30
+ export function resolveGsdPerspectiveAgent(id) {
31
+ return id === "research" ? "explore" : "verify";
32
+ }
33
+ export function buildGsdPerspectiveTaskRequest(prompt, perspective, sessionModelId, descriptionPrefix = "plan-council") {
34
+ return {
35
+ agent: resolveGsdPerspectiveAgent(perspective.id),
36
+ prompt,
37
+ description: `${descriptionPrefix}:${perspective.id}`,
38
+ maxToolRounds: 4,
39
+ modelId: resolveGsdPremiumModel(sessionModelId),
40
+ };
41
+ }
42
+ export function tierOfModel(modelId) {
43
+ return getModelInfo(modelId)?.tier;
44
+ }
45
+ //# sourceMappingURL=model-tier.js.map
@@ -0,0 +1,16 @@
1
+ export interface MutationGateDecision {
2
+ blocked: boolean;
3
+ reason: string;
4
+ }
5
+ /**
6
+ * Gate = the SDK's own canExecute, keyed on the SDK STATE.md Depth (written by the
7
+ * turn's syncWorkflowContext). Reading depth from readState — NOT from a
8
+ * caller-passed value or pilCtx — makes STATE.md the single source of truth and
9
+ * decouples the gate from pilCtx object propagation. quick depth is fast-pathed by
10
+ * canExecute; standard/heavy gate on plan-verify pass.
11
+ */
12
+ export declare function evaluateMutationGate(cwd: string, opts: {
13
+ toolName: string;
14
+ hardGateEnabled: boolean;
15
+ directAnswer?: boolean;
16
+ }): MutationGateDecision;
@@ -0,0 +1,41 @@
1
+ import { canExecute, readState } from "./workflow-engine.js";
2
+ const NEVER_GATED_PREFIXES = ["gsd_", "respond_"];
3
+ const NEVER_GATED = new Set(["read_file", "grep", "glob", "bash_output_get", "gsd_status", "compact"]);
4
+ function isNeverGated(t) {
5
+ return NEVER_GATED.has(t) || NEVER_GATED_PREFIXES.some((p) => t.startsWith(p));
6
+ }
7
+ const GATE_DIRECTIVE = "BLOCKED: this task was assessed as non-trivial. GSD requires a reviewed plan before any code edit. " +
8
+ "Call gsd_status, then gsd_discuss → gsd_plan → gsd_plan_review. Mutation tools unlock only after " +
9
+ "plan-review returns verdict: pass. If this is genuinely trivial, call gsd_execute with force:true to override.";
10
+ /**
11
+ * Gate = the SDK's own canExecute, keyed on the SDK STATE.md Depth (written by the
12
+ * turn's syncWorkflowContext). Reading depth from readState — NOT from a
13
+ * caller-passed value or pilCtx — makes STATE.md the single source of truth and
14
+ * decouples the gate from pilCtx object propagation. quick depth is fast-pathed by
15
+ * canExecute; standard/heavy gate on plan-verify pass.
16
+ */
17
+ export function evaluateMutationGate(cwd, opts) {
18
+ const allow = { blocked: false, reason: "" };
19
+ if (!opts.hardGateEnabled || opts.directAnswer || isNeverGated(opts.toolName))
20
+ return allow;
21
+ try {
22
+ const depth = readState(cwd).depth;
23
+ // Fail OPEN on anything but an EXPLICIT "heavy" depth. quick/standard/null all pass:
24
+ // - null STATE (not classified / native off mid-turn / write failed) → over-blocking on
25
+ // "we don't know" is the failure mode the design forbids.
26
+ // - quick → trivial fast-path.
27
+ // - standard → ADVISORY only. The layer4 directive still nudges gsd_plan_review, but
28
+ // hard-blocking every default-tier bash/edit until a plan-review pass over-reaches
29
+ // ("hard thì mọi tier không tốt"). Only genuinely non-trivial work (heavy, incl. tasks
30
+ // the leader-tier assessor UPGRADES to heavy) earns the hard gate.
31
+ if (!depth || depth === "quick" || depth === "standard")
32
+ return allow;
33
+ const gate = canExecute(cwd, depth);
34
+ return gate.allowed ? allow : { blocked: true, reason: GATE_DIRECTIVE };
35
+ }
36
+ catch (err) {
37
+ console.error(`[gsd] mutation-gate canExecute failed, failing open: ${err.message}`);
38
+ return allow; // fail open — a corrupt .planning must not brick the turn; caps still bound loops
39
+ }
40
+ }
41
+ //# sourceMappingURL=mutation-gate.js.map
@@ -0,0 +1,89 @@
1
+ /**
2
+ * native-roadmap.ts — Native replacements for the ROADMAP-oriented gsd-tools
3
+ * subcommands: `roadmap analyze` (read-only), `phase add` (create dir + append),
4
+ * and — Part B step 2 — the two mutating commands `roadmap update-plan-progress`
5
+ * and `phase complete`.
6
+ *
7
+ * The mutating commands rewrite ROADMAP.md (checkbox/table/plan-count) and, for
8
+ * phase-complete, STATE.md. muonroi's only callers (phase-sync, task workflow)
9
+ * read just `ok` + a cosmetic `raw` line — they do NOT consume the rich JSON —
10
+ * so native parity is about performing the FILE mutations correctly, verified
11
+ * against the subprocess oracle in the native-roadmap contract tests.
12
+ */
13
+ export interface RoadmapAnalyzePhase {
14
+ number: string;
15
+ name: string;
16
+ depends_on: string | null;
17
+ disk_status: string;
18
+ }
19
+ export interface RoadmapAnalyzeData {
20
+ error?: string;
21
+ milestones: Array<{
22
+ heading: string;
23
+ version?: string;
24
+ }>;
25
+ phases: RoadmapAnalyzePhase[];
26
+ phase_count: number;
27
+ current_phase: string | null;
28
+ next_phase: string | null;
29
+ }
30
+ /** Slugify per gsd-core core-utils: lowercase, non-alnum→'-', trim, cap 60. */
31
+ export declare function phaseSlug(text: string): string;
32
+ /**
33
+ * Native `roadmap analyze` — parse ROADMAP.md phase headings (current milestone)
34
+ * + per-phase Depends-on + disk status. Read-only. Returns {error} when
35
+ * ROADMAP.md is absent (mirrors subprocess, exit 0).
36
+ */
37
+ export declare function nativeRoadmapAnalyze(cwd: string): RoadmapAnalyzeData;
38
+ export interface PhaseAddData {
39
+ phase_number: number;
40
+ padded: string;
41
+ name: string;
42
+ slug: string;
43
+ directory: string;
44
+ naming_mode: string;
45
+ }
46
+ /**
47
+ * Native `phase add <description>` — sequential naming mode only (custom `--id`
48
+ * mode is not used by muonroi's callers). Creates `.planning/phases/<NN>-<slug>/`
49
+ * + `.gitkeep`, and appends a phase block to ROADMAP.md before the trailing
50
+ * `---` separator. Returns {error} when ROADMAP.md is absent (matching the
51
+ * subprocess exit-1 contract via ok:false at the dispatch layer).
52
+ */
53
+ export declare function nativePhaseAdd(cwd: string, description: string): PhaseAddData | {
54
+ error: string;
55
+ };
56
+ export interface RoadmapPlanProgressData {
57
+ updated: boolean;
58
+ reason?: string;
59
+ phase?: string;
60
+ plan_count?: number;
61
+ summary_count?: number;
62
+ status?: string;
63
+ complete?: boolean;
64
+ /** Plain-text `--raw` line, e.g. "2/3 In Progress". */
65
+ raw?: string;
66
+ }
67
+ /**
68
+ * Native `roadmap update-plan-progress <N>` — recompute plan/summary counts from
69
+ * the phase dir and sync the ROADMAP: phase checkbox (when complete), plan
70
+ * checkboxes for summarized plans, and the `**Plans:**` count line. Returns
71
+ * {updated:false} (exit-0 semantics) when the phase or ROADMAP is missing.
72
+ */
73
+ export declare function nativeRoadmapPlanProgress(cwd: string, phaseNum: string): RoadmapPlanProgressData;
74
+ export interface PhaseCompleteData {
75
+ ok: boolean;
76
+ error?: string;
77
+ completed_phase?: string;
78
+ roadmap_updated?: boolean;
79
+ state_updated?: boolean;
80
+ }
81
+ /**
82
+ * Native `phase complete <N>` — mark the phase done in ROADMAP.md (checkbox +
83
+ * plan checkboxes + Plans line) and reflect completion in STATE.md (Status). The
84
+ * subprocess gates on a `passed` VERIFICATION; muonroi's caller writes that
85
+ * verification immediately before calling, so the gate is satisfied by
86
+ * construction — we still mark the ROADMAP/STATE so the workflow state is
87
+ * consistent. Returns {ok:false} when the phase / ROADMAP is missing.
88
+ */
89
+ export declare function nativePhaseComplete(cwd: string, phaseNum: string): PhaseCompleteData;
@@ -0,0 +1,343 @@
1
+ /**
2
+ * native-roadmap.ts — Native replacements for the ROADMAP-oriented gsd-tools
3
+ * subcommands: `roadmap analyze` (read-only), `phase add` (create dir + append),
4
+ * and — Part B step 2 — the two mutating commands `roadmap update-plan-progress`
5
+ * and `phase complete`.
6
+ *
7
+ * The mutating commands rewrite ROADMAP.md (checkbox/table/plan-count) and, for
8
+ * phase-complete, STATE.md. muonroi's only callers (phase-sync, task workflow)
9
+ * read just `ok` + a cosmetic `raw` line — they do NOT consume the rich JSON —
10
+ * so native parity is about performing the FILE mutations correctly, verified
11
+ * against the subprocess oracle in the native-roadmap contract tests.
12
+ */
13
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import { loadConfig } from "./config-loader.js";
16
+ import { planningArtifact, planningPhasesRoot } from "./paths.js";
17
+ import { normalizeStateStatus, stateReplaceField } from "./state-document.js";
18
+ const PHASE_HEADING_RE = /#{2,4}\s*(?:\[[^\]]+\]\s*)?Phase\s+(\d+[A-Za-z]?(?:[.-]\d+)*)\s*:\s*([^\n]+)/gi;
19
+ function isSentinel(num) {
20
+ return num === "0" || num.startsWith("999");
21
+ }
22
+ /** Slugify per gsd-core core-utils: lowercase, non-alnum→'-', trim, cap 60. */
23
+ export function phaseSlug(text) {
24
+ return text
25
+ .toLowerCase()
26
+ .replace(/[^a-z0-9]+/g, "-")
27
+ .replace(/^-+|-+$/g, "")
28
+ .substring(0, 60);
29
+ }
30
+ /** Disk status for a phase dir given plan/summary/context/research presence. */
31
+ function diskStatusFor(cwd, number) {
32
+ const root = planningPhasesRoot(cwd);
33
+ if (!existsSync(root))
34
+ return "no_directory";
35
+ let dir;
36
+ try {
37
+ dir = readdirSync(root, { withFileTypes: true })
38
+ .filter((e) => e.isDirectory())
39
+ .map((e) => e.name)
40
+ .find((name) => new RegExp(`(^|[^0-9])0*${number}-`).test(name) || name.startsWith(`${number.padStart(2, "0")}-`));
41
+ }
42
+ catch {
43
+ return "no_directory";
44
+ }
45
+ if (!dir)
46
+ return "no_directory";
47
+ let plans = 0;
48
+ let summaries = 0;
49
+ let hasResearch = false;
50
+ try {
51
+ for (const f of readdirSync(join(root, dir))) {
52
+ if (/PLAN.*\.md$/i.test(f))
53
+ plans += 1;
54
+ if (/SUMMARY.*\.md$/i.test(f))
55
+ summaries += 1;
56
+ if (/RESEARCH.*\.md$/i.test(f))
57
+ hasResearch = true;
58
+ }
59
+ }
60
+ catch {
61
+ return "empty";
62
+ }
63
+ if (plans > 0 && summaries >= plans)
64
+ return "complete";
65
+ if (summaries > 0)
66
+ return "partial";
67
+ if (plans > 0)
68
+ return "planned";
69
+ if (hasResearch)
70
+ return "researched";
71
+ return "empty";
72
+ }
73
+ /**
74
+ * Native `roadmap analyze` — parse ROADMAP.md phase headings (current milestone)
75
+ * + per-phase Depends-on + disk status. Read-only. Returns {error} when
76
+ * ROADMAP.md is absent (mirrors subprocess, exit 0).
77
+ */
78
+ export function nativeRoadmapAnalyze(cwd) {
79
+ const roadmapPath = planningArtifact(cwd, "ROADMAP.md");
80
+ if (!existsSync(roadmapPath)) {
81
+ return {
82
+ error: "ROADMAP.md not found",
83
+ milestones: [],
84
+ phases: [],
85
+ phase_count: 0,
86
+ current_phase: null,
87
+ next_phase: null,
88
+ };
89
+ }
90
+ const text = readFileSync(roadmapPath, "utf8");
91
+ const milestones = [];
92
+ const msRe = /##\s*(.*v(\d+(?:\.\d+)+)[^(\n]*)/gi;
93
+ for (let m = msRe.exec(text); m; m = msRe.exec(text)) {
94
+ milestones.push({ heading: m[1].trim(), version: m[2] });
95
+ }
96
+ const checkboxDone = new Set();
97
+ const cbRe = /-\s*\[([ xX])\]\s*\*\*Phase\s+(\d+[A-Za-z]?(?:[.-]\d+)*)/gi;
98
+ for (let m = cbRe.exec(text); m; m = cbRe.exec(text)) {
99
+ if (m[1].toLowerCase() === "x")
100
+ checkboxDone.add(m[2]);
101
+ }
102
+ const phases = [];
103
+ const seen = new Set();
104
+ PHASE_HEADING_RE.lastIndex = 0;
105
+ const matches = [...text.matchAll(PHASE_HEADING_RE)];
106
+ for (let i = 0; i < matches.length; i++) {
107
+ const number = matches[i][1];
108
+ if (isSentinel(number) || seen.has(number))
109
+ continue;
110
+ seen.add(number);
111
+ const name = matches[i][2].trim();
112
+ // Depends-on: scan the section body between this heading and the next.
113
+ const sectionStart = matches[i].index ?? 0;
114
+ const sectionEnd = i + 1 < matches.length ? (matches[i + 1].index ?? text.length) : text.length;
115
+ const section = text.slice(sectionStart, sectionEnd);
116
+ const depMatch = section.match(/\*\*Depends on:\*\*\s*([^\n]+)/i);
117
+ const depends_on = depMatch ? depMatch[1].trim() : null;
118
+ const diskStatus = checkboxDone.has(number) ? "complete" : diskStatusFor(cwd, number);
119
+ phases.push({ number, name, depends_on, disk_status: diskStatus });
120
+ }
121
+ // "current" = the first phase that is STARTED but not complete (matches the
122
+ // subprocess: a phase with no directory is "not started" → null, not current).
123
+ const inProgress = new Set(["partial", "planned", "researched", "discussed"]);
124
+ const current = phases.find((p) => inProgress.has(p.disk_status)) ?? null;
125
+ const currentIdx = current ? phases.indexOf(current) : -1;
126
+ // next = the first not-complete phase after the last complete one.
127
+ const firstIncomplete = phases.find((p) => p.disk_status !== "complete") ?? null;
128
+ const next = current ? (currentIdx + 1 < phases.length ? phases[currentIdx + 1] : null) : firstIncomplete;
129
+ return {
130
+ milestones,
131
+ phases,
132
+ phase_count: phases.length,
133
+ current_phase: current?.number ?? null,
134
+ next_phase: next?.number ?? null,
135
+ };
136
+ }
137
+ /** Highest phase number used across headings + roadmap bullets + phase dirs. */
138
+ function maxUsedPhaseNumber(cwd, roadmapText) {
139
+ let max = 0;
140
+ const collect = (n) => {
141
+ const v = Number.parseInt(n, 10);
142
+ if (Number.isFinite(v) && v !== 999 && v > max)
143
+ max = v;
144
+ };
145
+ for (const m of roadmapText.matchAll(/#{2,4}\s*Phase\s+(\d+)[A-Za-z]?(?:\.\d+)*:/gi))
146
+ collect(m[1]);
147
+ for (const m of roadmapText.matchAll(/^[ \t]*-[ \t]*\[[^\]]*\][ \t]*\*{0,2}Phase[ \t]+(\d+)(?=[:.\s*]|$)/gim))
148
+ collect(m[1]);
149
+ const root = planningPhasesRoot(cwd);
150
+ if (existsSync(root)) {
151
+ try {
152
+ for (const e of readdirSync(root, { withFileTypes: true })) {
153
+ if (!e.isDirectory())
154
+ continue;
155
+ const dm = e.name.match(/^(?:[A-Z][A-Z0-9]*-)?(\d+)-/);
156
+ if (dm)
157
+ collect(dm[1]);
158
+ }
159
+ }
160
+ catch {
161
+ /* ignore unreadable phases dir */
162
+ }
163
+ }
164
+ return max;
165
+ }
166
+ /**
167
+ * Native `phase add <description>` — sequential naming mode only (custom `--id`
168
+ * mode is not used by muonroi's callers). Creates `.planning/phases/<NN>-<slug>/`
169
+ * + `.gitkeep`, and appends a phase block to ROADMAP.md before the trailing
170
+ * `---` separator. Returns {error} when ROADMAP.md is absent (matching the
171
+ * subprocess exit-1 contract via ok:false at the dispatch layer).
172
+ */
173
+ export function nativePhaseAdd(cwd, description) {
174
+ const desc = description.trim();
175
+ if (!desc)
176
+ return { error: "phase add requires a description" };
177
+ const roadmapPath = planningArtifact(cwd, "ROADMAP.md");
178
+ if (!existsSync(roadmapPath))
179
+ return { error: "ROADMAP.md not found" };
180
+ const config = loadConfig(cwd);
181
+ const projectCode = typeof config.project_code === "string" && config.project_code ? `${config.project_code}-` : "";
182
+ const roadmapText = readFileSync(roadmapPath, "utf8");
183
+ const id = maxUsedPhaseNumber(cwd, roadmapText) + 1;
184
+ const padded = String(id).padStart(2, "0");
185
+ const slug = phaseSlug(desc);
186
+ const directory = `${projectCode}${padded}-${slug}`;
187
+ // Create phase dir + .gitkeep.
188
+ const phaseDir = join(planningPhasesRoot(cwd), directory);
189
+ mkdirSync(phaseDir, { recursive: true });
190
+ writeFileSync(join(phaseDir, ".gitkeep"), "", "utf8");
191
+ // Append the phase block before the last `---` separator (or at EOF).
192
+ const block = `\n### Phase ${id}: ${desc}\n\n**Goal:** [To be planned]\n**Requirements**: TBD\n**Depends on:** Phase ${id - 1}\n**Plans:** 0 plans\n\nPlans:\n- [ ] TBD (run gsd-slash plan-phase ${id} to break down)\n`;
193
+ const sepIdx = roadmapText.lastIndexOf("\n---");
194
+ const nextRoadmap = sepIdx >= 0 ? `${roadmapText.slice(0, sepIdx)}${block}${roadmapText.slice(sepIdx)}` : `${roadmapText}${block}`;
195
+ writeFileSync(roadmapPath, nextRoadmap, "utf8");
196
+ return { phase_number: id, padded, name: desc, slug, directory, naming_mode: "sequential" };
197
+ }
198
+ // ─── Part B step 2: mutating commands ───────────────────────────────────────
199
+ function today() {
200
+ return new Date().toISOString().slice(0, 10);
201
+ }
202
+ /** Find the phase directory name for a phase number (unpadded or padded). */
203
+ function findPhaseDir(cwd, phaseNum) {
204
+ const root = planningPhasesRoot(cwd);
205
+ if (!existsSync(root))
206
+ return null;
207
+ const n = phaseNum.replace(/^0+/, "") || phaseNum;
208
+ try {
209
+ const dirs = readdirSync(root, { withFileTypes: true })
210
+ .filter((e) => e.isDirectory())
211
+ .map((e) => e.name);
212
+ return dirs.find((d) => new RegExp(`(^|[^0-9])0*${n}-`).test(d) || d.startsWith(`${n.padStart(2, "0")}-`)) ?? null;
213
+ }
214
+ catch {
215
+ return null;
216
+ }
217
+ }
218
+ /** Count PLAN / SUMMARY files (and derive plan ids from summaries) in a phase dir. */
219
+ function phasePlanCounts(cwd, dir) {
220
+ let planCount = 0;
221
+ let summaryCount = 0;
222
+ const summaryPlanIds = [];
223
+ try {
224
+ for (const f of readdirSync(join(planningPhasesRoot(cwd), dir))) {
225
+ if (/PLAN.*\.md$/i.test(f))
226
+ planCount += 1;
227
+ if (/SUMMARY.*\.md$/i.test(f)) {
228
+ summaryCount += 1;
229
+ summaryPlanIds.push(f.replace(/-?SUMMARY.*\.md$/i, ""));
230
+ }
231
+ }
232
+ }
233
+ catch {
234
+ /* unreadable dir → zero counts */
235
+ }
236
+ return { planCount, summaryCount, summaryPlanIds };
237
+ }
238
+ function statusFor(planCount, summaryCount) {
239
+ if (planCount > 0 && summaryCount >= planCount)
240
+ return "Complete";
241
+ if (summaryCount > 0)
242
+ return "In Progress";
243
+ return "Planned";
244
+ }
245
+ /** Toggle the ROADMAP checkbox for a phase to [x] (+ completed date). */
246
+ function checkPhaseBox(text, phaseNum) {
247
+ const esc = phaseNum.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
248
+ const re = new RegExp(`(-\\s*\\[)[ ](\\]\\s*.*Phase\\s+${esc}[:\\s][^\\n]*)`, "i");
249
+ if (!re.test(text))
250
+ return text;
251
+ return text.replace(re, (_m, a, b) => `${a}x${b} (completed ${today()})`);
252
+ }
253
+ /** Check each summarized plan's checkbox in the ROADMAP. */
254
+ function checkPlanBoxes(text, planIds) {
255
+ let out = text;
256
+ for (const pid of planIds) {
257
+ const esc = pid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
258
+ const re = new RegExp(`(-\\s*\\[) (\\]\\s*(?:\\*\\*)?${esc}(?:\\*\\*)?)`, "g");
259
+ out = out.replace(re, (_m, a, b) => `${a}x${b}`);
260
+ }
261
+ return out;
262
+ }
263
+ /** Update the `**Plans:**` count line in a phase section. */
264
+ function updatePlansLine(text, summary, plan, complete) {
265
+ const re = /(\*\*Plans:\*\*\s*)([^\n]*)/i;
266
+ if (!re.test(text))
267
+ return text;
268
+ const word = complete ? "complete" : "executed";
269
+ return text.replace(re, (_m, pre) => `${pre}${summary}/${plan} plans ${word}`);
270
+ }
271
+ /**
272
+ * Native `roadmap update-plan-progress <N>` — recompute plan/summary counts from
273
+ * the phase dir and sync the ROADMAP: phase checkbox (when complete), plan
274
+ * checkboxes for summarized plans, and the `**Plans:**` count line. Returns
275
+ * {updated:false} (exit-0 semantics) when the phase or ROADMAP is missing.
276
+ */
277
+ export function nativeRoadmapPlanProgress(cwd, phaseNum) {
278
+ const dir = findPhaseDir(cwd, phaseNum);
279
+ if (!dir)
280
+ return { updated: false, reason: `Phase ${phaseNum} not found`, raw: "no phase" };
281
+ const roadmapPath = planningArtifact(cwd, "ROADMAP.md");
282
+ if (!existsSync(roadmapPath))
283
+ return { updated: false, reason: "ROADMAP.md not found", raw: "no roadmap" };
284
+ const { planCount, summaryCount, summaryPlanIds } = phasePlanCounts(cwd, dir);
285
+ if (planCount === 0)
286
+ return { updated: false, reason: "No plans found", phase: phaseNum, plan_count: 0, raw: "no plans" };
287
+ const status = statusFor(planCount, summaryCount);
288
+ const complete = status === "Complete";
289
+ let text = readFileSync(roadmapPath, "utf8");
290
+ text = updatePlansLine(text, summaryCount, planCount, complete);
291
+ text = checkPlanBoxes(text, summaryPlanIds);
292
+ if (complete)
293
+ text = checkPhaseBox(text, phaseNum);
294
+ writeFileSync(roadmapPath, text, "utf8");
295
+ return {
296
+ updated: true,
297
+ phase: phaseNum,
298
+ plan_count: planCount,
299
+ summary_count: summaryCount,
300
+ status,
301
+ complete,
302
+ raw: `${summaryCount}/${planCount} ${status}`,
303
+ };
304
+ }
305
+ /**
306
+ * Native `phase complete <N>` — mark the phase done in ROADMAP.md (checkbox +
307
+ * plan checkboxes + Plans line) and reflect completion in STATE.md (Status). The
308
+ * subprocess gates on a `passed` VERIFICATION; muonroi's caller writes that
309
+ * verification immediately before calling, so the gate is satisfied by
310
+ * construction — we still mark the ROADMAP/STATE so the workflow state is
311
+ * consistent. Returns {ok:false} when the phase / ROADMAP is missing.
312
+ */
313
+ export function nativePhaseComplete(cwd, phaseNum) {
314
+ const dir = findPhaseDir(cwd, phaseNum);
315
+ if (!dir)
316
+ return { ok: false, error: `Phase ${phaseNum} not found` };
317
+ const roadmapPath = planningArtifact(cwd, "ROADMAP.md");
318
+ if (!existsSync(roadmapPath))
319
+ return { ok: false, error: "ROADMAP.md not found" };
320
+ const { planCount, summaryCount, summaryPlanIds } = phasePlanCounts(cwd, dir);
321
+ let text = readFileSync(roadmapPath, "utf8");
322
+ text = checkPhaseBox(text, phaseNum);
323
+ text = checkPlanBoxes(text, summaryPlanIds);
324
+ text = updatePlansLine(text, summaryCount, planCount, true);
325
+ writeFileSync(roadmapPath, text, "utf8");
326
+ // STATE.md — reflect completion on the body Status field (best-effort).
327
+ let stateUpdated = false;
328
+ const statePath = planningArtifact(cwd, "STATE.md");
329
+ if (existsSync(statePath)) {
330
+ const content = readFileSync(statePath, "utf8");
331
+ const m = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
332
+ const body = m ? m[2] : content;
333
+ const fm = m ? m[1] : null;
334
+ const nextBody = stateReplaceField(body, "Status", normalizeStateStatus("Phase complete"));
335
+ if (nextBody !== null) {
336
+ const next = fm !== null ? `---\n${fm}\n---\n\n${nextBody.replace(/^\n+/, "")}` : nextBody;
337
+ writeFileSync(statePath, next, "utf8");
338
+ stateUpdated = true;
339
+ }
340
+ }
341
+ return { ok: true, completed_phase: phaseNum, roadmap_updated: true, state_updated: stateUpdated };
342
+ }
343
+ //# sourceMappingURL=native-roadmap.js.map
@@ -0,0 +1,47 @@
1
+ /**
2
+ * native-state.ts — Native replacements for the STATE.md-oriented gsd-tools
3
+ * subcommands (`state update`, `state json`, `init progress`).
4
+ *
5
+ * Part B: these fully replace the former `@opengsd/gsd-core` subprocess (removed
6
+ * in step 2). Output shapes follow the old gsd-tools `--raw`/JSON contract:
7
+ * state update → {updated:boolean, reason?}, state json → frontmatter object,
8
+ * init progress → progress projection.
9
+ */
10
+ export interface StateUpdateResult {
11
+ updated: boolean;
12
+ reason?: string;
13
+ }
14
+ /**
15
+ * Native `state update <field> <value>`.
16
+ * Mirrors gsd-core updateCore: strip frontmatter, `stateReplaceField` on the
17
+ * BODY only, reassemble. Returns {updated:false, reason} when the field is not
18
+ * present or STATE.md is missing (never throws). Caller invalidates cache.
19
+ */
20
+ export declare function nativeStateUpdate(cwd: string, field: string, value: string): StateUpdateResult;
21
+ /**
22
+ * Native `state json` — frontmatter snapshot derived from STATE.md body fields
23
+ * + roadmap phase count. Note: gsd-core emits a fresh `last_updated` ISO stamp;
24
+ * we OMIT that non-deterministic field so consumers/tests get a stable object
25
+ * (workflow-engine only reads it loosely as `state_frontmatter`).
26
+ */
27
+ export declare function nativeStateJson(cwd: string): Record<string, unknown>;
28
+ /**
29
+ * Native `init progress` — the projection consumed by workflow-engine.readProgress.
30
+ * Mirrors the subset of gsd-core's cmdInitProgress that muonroi actually reads:
31
+ * existence flags, phase list + counts, current/next phase.
32
+ */
33
+ export declare function nativeInitProgress(cwd: string): Record<string, unknown>;
34
+ /** True when STATE.md exists (used by callers to decide native vs. bootstrap). */
35
+ export declare function stateFileMtime(cwd: string): number;
36
+ /**
37
+ * Native `config-ensure-section` — ensure the `.planning/` directory exists.
38
+ * muonroi's only caller (loop-host.ensureHost) invokes this immediately before
39
+ * `ensurePlanningWorkspace`, which writes the real model-bound config.json. So
40
+ * native config-ensure MUST NOT write a stub config here — that would shadow the
41
+ * proper config (ensurePlanningWorkspace only writes when config.json is absent).
42
+ * We just guarantee the directory, matching the pair's net effect.
43
+ */
44
+ export declare function nativeConfigEnsure(cwd: string): {
45
+ ok: boolean;
46
+ created: boolean;
47
+ };