muonroi-cli 1.8.4 → 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 (458) 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-tee.d.ts +48 -0
  5. package/dist/packages/agent-harness-core/src/event-tee.js +77 -0
  6. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +11 -0
  7. package/dist/packages/agent-harness-core/src/mcp-server.js +87 -15
  8. package/dist/packages/agent-harness-core/src/protocol.d.ts +66 -2
  9. package/dist/packages/agent-harness-core/src/protocol.js +15 -0
  10. package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
  11. package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
  12. package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
  13. package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
  14. package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
  15. package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
  16. package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
  17. package/dist/packages/agent-harness-opentui/src/install.js +10 -0
  18. package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
  19. package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
  20. package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
  21. package/dist/src/agent-harness/mock-model.d.ts +28 -0
  22. package/dist/src/agent-harness/mock-model.js +63 -1
  23. package/dist/src/agent-harness/test-spawn.js +31 -0
  24. package/dist/src/cli/config/screen-providers.js +1 -1
  25. package/dist/src/cli/cost-forensics.d.ts +10 -0
  26. package/dist/src/cli/cost-forensics.js +18 -3
  27. package/dist/src/cli/keys-bundle.d.ts +1 -1
  28. package/dist/src/cli/keys-bundle.js +1 -1
  29. package/dist/src/cli/keys.d.ts +2 -2
  30. package/dist/src/cli/keys.js +19 -81
  31. package/dist/src/council/clarifier.d.ts +28 -2
  32. package/dist/src/council/clarifier.js +81 -15
  33. package/dist/src/council/context.js +49 -15
  34. package/dist/src/council/debate-checkpoint.d.ts +129 -0
  35. package/dist/src/council/debate-checkpoint.js +176 -0
  36. package/dist/src/council/debate-planner.js +51 -3
  37. package/dist/src/council/debate-summary.d.ts +25 -0
  38. package/dist/src/council/debate-summary.js +85 -0
  39. package/dist/src/council/debate.d.ts +169 -2
  40. package/dist/src/council/debate.js +1210 -134
  41. package/dist/src/council/index.d.ts +85 -1
  42. package/dist/src/council/index.js +634 -196
  43. package/dist/src/council/leader.d.ts +26 -0
  44. package/dist/src/council/leader.js +150 -9
  45. package/dist/src/council/llm.d.ts +32 -0
  46. package/dist/src/council/llm.js +231 -38
  47. package/dist/src/council/panel-select.d.ts +30 -0
  48. package/dist/src/council/panel-select.js +72 -0
  49. package/dist/src/council/planner.js +23 -0
  50. package/dist/src/council/preflight.d.ts +7 -0
  51. package/dist/src/council/preflight.js +14 -2
  52. package/dist/src/council/prompts.d.ts +30 -3
  53. package/dist/src/council/prompts.js +234 -64
  54. package/dist/src/council/stance-recall.d.ts +42 -0
  55. package/dist/src/council/stance-recall.js +57 -0
  56. package/dist/src/council/strip-think.d.ts +17 -0
  57. package/dist/src/council/strip-think.js +33 -0
  58. package/dist/src/council/types.d.ts +128 -0
  59. package/dist/src/ee/artifact-cache.d.ts +16 -0
  60. package/dist/src/ee/artifact-cache.js +32 -0
  61. package/dist/src/ee/auth.d.ts +1 -0
  62. package/dist/src/ee/auth.js +15 -2
  63. package/dist/src/ee/bridge.d.ts +10 -0
  64. package/dist/src/ee/bridge.js +58 -0
  65. package/dist/src/ee/client.js +81 -18
  66. package/dist/src/ee/export-transcripts.d.ts +1 -0
  67. package/dist/src/ee/export-transcripts.js +8 -10
  68. package/dist/src/ee/extract-session.js +29 -0
  69. package/dist/src/ee/extract-style.d.ts +58 -0
  70. package/dist/src/ee/extract-style.js +270 -0
  71. package/dist/src/ee/recall-ledger.d.ts +9 -0
  72. package/dist/src/ee/recall-ledger.js +3 -0
  73. package/dist/src/ee/scope.d.ts +1 -0
  74. package/dist/src/ee/scope.js +26 -1
  75. package/dist/src/ee/search.d.ts +7 -0
  76. package/dist/src/ee/search.js +24 -0
  77. package/dist/src/ee/transcript-emit.js +2 -0
  78. package/dist/src/ee/types.d.ts +22 -0
  79. package/dist/src/ee/who-am-i-brain.d.ts +35 -0
  80. package/dist/src/ee/who-am-i-brain.js +220 -0
  81. package/dist/src/ee/who-am-i.d.ts +10 -3
  82. package/dist/src/ee/who-am-i.js +12 -0
  83. package/dist/src/ee/workflow-event.d.ts +48 -0
  84. package/dist/src/ee/workflow-event.js +81 -0
  85. package/dist/src/flow/compaction/compress.d.ts +3 -3
  86. package/dist/src/flow/compaction/compress.js +45 -8
  87. package/dist/src/flow/compaction/extract.d.ts +4 -7
  88. package/dist/src/flow/compaction/extract.js +50 -10
  89. package/dist/src/flow/compaction/index.d.ts +13 -1
  90. package/dist/src/flow/compaction/index.js +70 -3
  91. package/dist/src/flow/compaction/input-guard.d.ts +24 -0
  92. package/dist/src/flow/compaction/input-guard.js +43 -0
  93. package/dist/src/flow/fold-planning.d.ts +36 -0
  94. package/dist/src/flow/fold-planning.js +83 -0
  95. package/dist/src/flow/hierarchy.d.ts +146 -0
  96. package/dist/src/flow/hierarchy.js +427 -0
  97. package/dist/src/flow/index.d.ts +1 -0
  98. package/dist/src/flow/index.js +2 -0
  99. package/dist/src/flow/run-artifacts.d.ts +102 -0
  100. package/dist/src/flow/run-artifacts.js +208 -0
  101. package/dist/src/generated/version.d.ts +1 -1
  102. package/dist/src/generated/version.js +1 -1
  103. package/dist/src/gsd/assessment-schema.d.ts +44 -0
  104. package/dist/src/gsd/assessment-schema.js +134 -0
  105. package/dist/src/gsd/capability-registry.d.ts +45 -0
  106. package/dist/src/gsd/capability-registry.js +337 -0
  107. package/dist/src/gsd/complexity-assessor.d.ts +39 -0
  108. package/dist/src/gsd/complexity-assessor.js +152 -0
  109. package/dist/src/gsd/config-bridge.d.ts +7 -0
  110. package/dist/src/gsd/config-bridge.js +114 -0
  111. package/dist/src/gsd/config-loader.d.ts +27 -0
  112. package/dist/src/gsd/config-loader.js +50 -0
  113. package/dist/src/gsd/council-context.d.ts +44 -0
  114. package/dist/src/gsd/council-context.js +114 -0
  115. package/dist/src/gsd/ee-closure.d.ts +28 -0
  116. package/dist/src/gsd/ee-closure.js +49 -0
  117. package/dist/src/gsd/flags.d.ts +55 -0
  118. package/dist/src/gsd/flags.js +83 -0
  119. package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
  120. package/dist/src/gsd/gsd-dispatch.js +131 -0
  121. package/dist/src/gsd/gsd-runtime.d.ts +22 -0
  122. package/dist/src/gsd/gsd-runtime.js +37 -0
  123. package/dist/src/gsd/host-adapter.d.ts +11 -0
  124. package/dist/src/gsd/host-adapter.js +29 -0
  125. package/dist/src/gsd/index.d.ts +24 -1
  126. package/dist/src/gsd/index.js +27 -0
  127. package/dist/src/gsd/loop-host-contract.d.ts +21 -0
  128. package/dist/src/gsd/loop-host-contract.js +39 -0
  129. package/dist/src/gsd/loop-host.d.ts +69 -0
  130. package/dist/src/gsd/loop-host.js +245 -0
  131. package/dist/src/gsd/loop-resolver.d.ts +36 -0
  132. package/dist/src/gsd/loop-resolver.js +79 -0
  133. package/dist/src/gsd/model-tier.d.ts +13 -0
  134. package/dist/src/gsd/model-tier.js +45 -0
  135. package/dist/src/gsd/mutation-gate.d.ts +16 -0
  136. package/dist/src/gsd/mutation-gate.js +41 -0
  137. package/dist/src/gsd/native-roadmap.d.ts +89 -0
  138. package/dist/src/gsd/native-roadmap.js +343 -0
  139. package/dist/src/gsd/native-state.d.ts +47 -0
  140. package/dist/src/gsd/native-state.js +220 -0
  141. package/dist/src/gsd/paths.d.ts +23 -0
  142. package/dist/src/gsd/paths.js +66 -0
  143. package/dist/src/gsd/phase-dag.d.ts +12 -0
  144. package/dist/src/gsd/phase-dag.js +94 -0
  145. package/dist/src/gsd/phase-sync.d.ts +42 -0
  146. package/dist/src/gsd/phase-sync.js +321 -0
  147. package/dist/src/gsd/pil-gate-context.d.ts +13 -0
  148. package/dist/src/gsd/pil-gate-context.js +64 -0
  149. package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
  150. package/dist/src/gsd/pil-gate-critic.js +74 -0
  151. package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
  152. package/dist/src/gsd/plan-council-prompts.js +79 -0
  153. package/dist/src/gsd/plan-council.d.ts +44 -0
  154. package/dist/src/gsd/plan-council.js +251 -0
  155. package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
  156. package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
  157. package/dist/src/gsd/product-workspace.d.ts +13 -0
  158. package/dist/src/gsd/product-workspace.js +124 -0
  159. package/dist/src/gsd/ship-bridge.d.ts +25 -0
  160. package/dist/src/gsd/ship-bridge.js +65 -0
  161. package/dist/src/gsd/state-document.d.ts +40 -0
  162. package/dist/src/gsd/state-document.js +163 -0
  163. package/dist/src/gsd/verdict-schema.d.ts +39 -0
  164. package/dist/src/gsd/verdict-schema.js +144 -0
  165. package/dist/src/gsd/verify-context.d.ts +22 -0
  166. package/dist/src/gsd/verify-context.js +27 -0
  167. package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
  168. package/dist/src/gsd/verify-council-prompts.js +85 -0
  169. package/dist/src/gsd/verify-council.d.ts +25 -0
  170. package/dist/src/gsd/verify-council.js +119 -0
  171. package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
  172. package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
  173. package/dist/src/gsd/workflow-engine.d.ts +60 -0
  174. package/dist/src/gsd/workflow-engine.js +207 -0
  175. package/dist/src/gsd/workflow-tools.d.ts +13 -0
  176. package/dist/src/gsd/workflow-tools.js +277 -0
  177. package/dist/src/hooks/index.js +1 -1
  178. package/dist/src/index.js +44 -11
  179. package/dist/src/maintain/pr-builder.js +23 -13
  180. package/dist/src/mcp/auto-setup.js +57 -32
  181. package/dist/src/mcp/client-pool.js +1 -1
  182. package/dist/src/mcp/ee-tools.js +1 -0
  183. package/dist/src/mcp/research-onboarding.js +8 -7
  184. package/dist/src/mcp/runtime.js +34 -2
  185. package/dist/src/models/catalog-client.d.ts +87 -0
  186. package/dist/src/models/catalog-client.js +105 -38
  187. package/dist/src/models/catalog.json +528 -265
  188. package/dist/src/models/registry.d.ts +22 -7
  189. package/dist/src/models/registry.js +73 -10
  190. package/dist/src/ops/doctor.js +1 -1
  191. package/dist/src/orchestrator/auto-commit.js +1 -1
  192. package/dist/src/orchestrator/batch-turn-runner.js +2 -2
  193. package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
  194. package/dist/src/orchestrator/cache-prefix.js +83 -0
  195. package/dist/src/orchestrator/compact-request.d.ts +32 -0
  196. package/dist/src/orchestrator/compact-request.js +41 -0
  197. package/dist/src/orchestrator/compaction.d.ts +10 -0
  198. package/dist/src/orchestrator/compaction.js +27 -7
  199. package/dist/src/orchestrator/council-manager.d.ts +12 -3
  200. package/dist/src/orchestrator/council-manager.js +65 -24
  201. package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
  202. package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
  203. package/dist/src/orchestrator/error-utils.d.ts +29 -0
  204. package/dist/src/orchestrator/error-utils.js +132 -24
  205. package/dist/src/orchestrator/grounding-check.js +39 -1
  206. package/dist/src/orchestrator/message-processor.js +242 -33
  207. package/dist/src/orchestrator/orchestrator.d.ts +39 -3
  208. package/dist/src/orchestrator/orchestrator.js +651 -102
  209. package/dist/src/orchestrator/preprocessor.js +1 -1
  210. package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
  211. package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
  212. package/dist/src/orchestrator/prompts.js +17 -17
  213. package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
  214. package/dist/src/orchestrator/reactive-delegation.js +59 -0
  215. package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
  216. package/dist/src/orchestrator/retry-classifier.js +46 -2
  217. package/dist/src/orchestrator/safety-intercept.d.ts +45 -0
  218. package/dist/src/orchestrator/safety-intercept.js +55 -0
  219. package/dist/src/orchestrator/scope-reminder.js +1 -1
  220. package/dist/src/orchestrator/session-experience.d.ts +2 -1
  221. package/dist/src/orchestrator/session-experience.js +2 -1
  222. package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
  223. package/dist/src/orchestrator/should-run-gate.js +18 -0
  224. package/dist/src/orchestrator/stall-watchdog.d.ts +24 -3
  225. package/dist/src/orchestrator/stall-watchdog.js +47 -13
  226. package/dist/src/orchestrator/stream-runner.js +62 -29
  227. package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
  228. package/dist/src/orchestrator/sub-agent-cap.js +16 -1
  229. package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
  230. package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
  231. package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
  232. package/dist/src/orchestrator/subagent-compactor.js +126 -15
  233. package/dist/src/orchestrator/tool-engine.d.ts +22 -0
  234. package/dist/src/orchestrator/tool-engine.js +620 -56
  235. package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
  236. package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
  237. package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
  238. package/dist/src/orchestrator/turn-watchdog.d.ts +37 -0
  239. package/dist/src/orchestrator/turn-watchdog.js +55 -0
  240. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  241. package/dist/src/pil/agent-operating-contract.js +1 -1
  242. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  243. package/dist/src/pil/cheap-model-playbook.js +5 -1
  244. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  245. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  246. package/dist/src/pil/discovery-types.d.ts +1 -0
  247. package/dist/src/pil/discovery.js +16 -11
  248. package/dist/src/pil/layer1-intent.d.ts +18 -6
  249. package/dist/src/pil/layer1-intent.js +66 -757
  250. package/dist/src/pil/layer15-context-scan.js +15 -1
  251. package/dist/src/pil/layer3-ee-injection.js +23 -8
  252. package/dist/src/pil/layer4-gsd.js +69 -16
  253. package/dist/src/pil/layer5-context.js +7 -3
  254. package/dist/src/pil/layer6-output.d.ts +23 -0
  255. package/dist/src/pil/layer6-output.js +5 -1
  256. package/dist/src/pil/llm-classify.d.ts +33 -2
  257. package/dist/src/pil/llm-classify.js +123 -131
  258. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  259. package/dist/src/pil/native-capabilities-workbook.js +1 -0
  260. package/dist/src/pil/pipeline.js +34 -2
  261. package/dist/src/pil/response-tools.js +5 -3
  262. package/dist/src/pil/schema.d.ts +1 -0
  263. package/dist/src/pil/schema.js +2 -0
  264. package/dist/src/pil/types.d.ts +18 -0
  265. package/dist/src/playbook/directives.d.ts +4 -0
  266. package/dist/src/playbook/directives.js +17 -5
  267. package/dist/src/product-loop/backlog-builder.d.ts +14 -1
  268. package/dist/src/product-loop/backlog-builder.js +30 -6
  269. package/dist/src/product-loop/discovery-context-format.js +3 -1
  270. package/dist/src/product-loop/discovery-ecosystem.js +4 -1
  271. package/dist/src/product-loop/discovery-interview.js +32 -3
  272. package/dist/src/product-loop/discovery-schema.js +5 -1
  273. package/dist/src/product-loop/ideal-trace.d.ts +7 -0
  274. package/dist/src/product-loop/ideal-trace.js +64 -0
  275. package/dist/src/product-loop/index.d.ts +13 -1
  276. package/dist/src/product-loop/index.js +333 -52
  277. package/dist/src/product-loop/loop-driver.d.ts +7 -0
  278. package/dist/src/product-loop/loop-driver.js +310 -99
  279. package/dist/src/product-loop/phase-plan.d.ts +5 -0
  280. package/dist/src/product-loop/phase-plan.js +39 -2
  281. package/dist/src/product-loop/phase-runner.js +9 -1
  282. package/dist/src/product-loop/sprint-runner.d.ts +111 -0
  283. package/dist/src/product-loop/sprint-runner.js +559 -16
  284. package/dist/src/product-loop/types.d.ts +36 -5
  285. package/dist/src/providers/adapter.d.ts +1 -1
  286. package/dist/src/providers/adapter.js +3 -4
  287. package/dist/src/providers/auth/browser-flow.d.ts +1 -1
  288. package/dist/src/providers/auth/browser-flow.js +1 -1
  289. package/dist/src/providers/auth/openai-oauth.js +1 -1
  290. package/dist/src/providers/auth/registry.js +0 -34
  291. package/dist/src/providers/auth/token-store.js +4 -1
  292. package/dist/src/providers/auth/types.d.ts +1 -1
  293. package/dist/src/providers/auth/types.js +1 -1
  294. package/dist/src/providers/capabilities.d.ts +24 -5
  295. package/dist/src/providers/capabilities.js +42 -24
  296. package/dist/src/providers/endpoints.d.ts +2 -2
  297. package/dist/src/providers/endpoints.js +11 -10
  298. package/dist/src/providers/keychain.d.ts +1 -1
  299. package/dist/src/providers/keychain.js +7 -9
  300. package/dist/src/providers/mcp-vision-bridge.js +56 -146
  301. package/dist/src/providers/openai-compatible.js +8 -1
  302. package/dist/src/providers/pricing.d.ts +2 -2
  303. package/dist/src/providers/pricing.js +3 -13
  304. package/dist/src/providers/runtime.d.ts +27 -2
  305. package/dist/src/providers/runtime.js +78 -15
  306. package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
  307. package/dist/src/providers/strategies/base.strategy.js +24 -1
  308. package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
  309. package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
  310. package/dist/src/providers/strategies/registry.js +4 -4
  311. package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
  312. package/dist/src/providers/strategies/thinking-mode.js +280 -1
  313. package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
  314. package/dist/src/providers/strategies/zai.strategy.js +44 -0
  315. package/dist/src/providers/types.d.ts +5 -6
  316. package/dist/src/providers/types.js +2 -2
  317. package/dist/src/providers/vision-backend.d.ts +47 -0
  318. package/dist/src/providers/vision-backend.js +258 -0
  319. package/dist/src/providers/vision-proxy.d.ts +22 -9
  320. package/dist/src/providers/vision-proxy.js +63 -132
  321. package/dist/src/providers/wire-debug.js +95 -0
  322. package/dist/src/router/decide.d.ts +13 -0
  323. package/dist/src/router/decide.js +138 -36
  324. package/dist/src/router/peak-hour.d.ts +38 -0
  325. package/dist/src/router/peak-hour.js +107 -0
  326. package/dist/src/router/step-router.js +3 -2
  327. package/dist/src/router/warm.js +4 -5
  328. package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
  329. package/dist/src/scaffold/continuation-prompt.js +26 -0
  330. package/dist/src/scaffold/point-to-existing.d.ts +21 -0
  331. package/dist/src/scaffold/point-to-existing.js +25 -0
  332. package/dist/src/self-qa/agentic-loop.js +3 -3
  333. package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
  334. package/dist/src/{ui/state → state}/active-run.js +21 -0
  335. package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
  336. package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
  337. package/dist/src/state/turn-trace.d.ts +43 -0
  338. package/dist/src/state/turn-trace.js +32 -0
  339. package/dist/src/storage/db.js +2 -1
  340. package/dist/src/storage/index.d.ts +1 -1
  341. package/dist/src/storage/index.js +1 -1
  342. package/dist/src/storage/interaction-log.d.ts +1 -1
  343. package/dist/src/storage/migrations.js +71 -1
  344. package/dist/src/storage/sessions.d.ts +28 -10
  345. package/dist/src/storage/sessions.js +78 -21
  346. package/dist/src/storage/transcript-view.js +1 -1
  347. package/dist/src/storage/transcript.d.ts +51 -0
  348. package/dist/src/storage/transcript.js +284 -13
  349. package/dist/src/tools/file.d.ts +15 -0
  350. package/dist/src/tools/file.js +32 -0
  351. package/dist/src/tools/native-tools.js +5 -0
  352. package/dist/src/tools/registry.d.ts +3 -0
  353. package/dist/src/tools/registry.js +460 -22
  354. package/dist/src/tools/research.d.ts +29 -0
  355. package/dist/src/tools/research.js +233 -0
  356. package/dist/src/types/index.d.ts +118 -3
  357. package/dist/src/ui/app.js +0 -0
  358. package/dist/src/ui/cards/product-status-card.js +1 -1
  359. package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
  360. package/dist/src/ui/components/bubble-body-guard.js +50 -0
  361. package/dist/src/ui/components/context-rail.d.ts +26 -0
  362. package/dist/src/ui/components/context-rail.js +33 -0
  363. package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
  364. package/dist/src/ui/components/council-conclusion-card.js +420 -0
  365. package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
  366. package/dist/src/ui/components/council-debate-pill.js +34 -0
  367. package/dist/src/ui/components/council-info-card.js +2 -2
  368. package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
  369. package/dist/src/ui/components/council-leader-bubble.js +21 -11
  370. package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
  371. package/dist/src/ui/components/council-message-bubble.js +16 -15
  372. package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
  373. package/dist/src/ui/components/council-phase-timeline.js +49 -15
  374. package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
  375. package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
  376. package/dist/src/ui/components/council-question-card.js +12 -12
  377. package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
  378. package/dist/src/ui/components/council-rail-rounds.js +57 -0
  379. package/dist/src/ui/components/council-round-group.d.ts +38 -0
  380. package/dist/src/ui/components/council-round-group.js +88 -0
  381. package/dist/src/ui/components/council-status-list.d.ts +3 -1
  382. package/dist/src/ui/components/council-status-list.js +36 -24
  383. package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
  384. package/dist/src/ui/components/council-synthesis-banner.js +20 -5
  385. package/dist/src/ui/components/halt-recovery-card.js +9 -5
  386. package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
  387. package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
  388. package/dist/src/ui/components/prompt-box.js +18 -16
  389. package/dist/src/ui/components/session-tree-card.d.ts +14 -0
  390. package/dist/src/ui/components/session-tree-card.js +46 -0
  391. package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
  392. package/dist/src/ui/components/slash-inline-menu.js +26 -5
  393. package/dist/src/ui/components/task-list-panel.d.ts +14 -1
  394. package/dist/src/ui/components/task-list-panel.js +22 -2
  395. package/dist/src/ui/containers/modals-layer.d.ts +2 -1
  396. package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
  397. package/dist/src/ui/mcp-modal.js +2 -4
  398. package/dist/src/ui/modals/api-key-modal.js +1 -1
  399. package/dist/src/ui/modals/connect-modal.js +4 -3
  400. package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
  401. package/dist/src/ui/modals/session-picker-modal.js +3 -5
  402. package/dist/src/ui/picker-providers.d.ts +1 -1
  403. package/dist/src/ui/picker-providers.js +1 -1
  404. package/dist/src/ui/primitives/index.d.ts +1 -0
  405. package/dist/src/ui/primitives/index.js +2 -0
  406. package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
  407. package/dist/src/ui/primitives/semantic-primitives.js +81 -0
  408. package/dist/src/ui/slash/compact.js +5 -7
  409. package/dist/src/ui/slash/cost.js +1 -1
  410. package/dist/src/ui/slash/council.js +19 -1
  411. package/dist/src/ui/slash/debug.d.ts +3 -31
  412. package/dist/src/ui/slash/debug.js +9 -20
  413. package/dist/src/ui/slash/ideal.d.ts +6 -2
  414. package/dist/src/ui/slash/ideal.js +97 -7
  415. package/dist/src/ui/slash/menu-items.d.ts +7 -0
  416. package/dist/src/ui/slash/menu-items.js +12 -18
  417. package/dist/src/ui/slash/registry.d.ts +2 -0
  418. package/dist/src/ui/slash/registry.js +4 -0
  419. package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
  420. package/dist/src/ui/status-bar/cache-hit.js +9 -0
  421. package/dist/src/ui/status-bar/index.d.ts +1 -1
  422. package/dist/src/ui/status-bar/index.js +7 -3
  423. package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
  424. package/dist/src/ui/status-bar/usd-meter.js +6 -4
  425. package/dist/src/ui/theme.d.ts +1 -0
  426. package/dist/src/ui/theme.js +2 -0
  427. package/dist/src/ui/types.d.ts +7 -0
  428. package/dist/src/ui/use-app-logic.js +0 -0
  429. package/dist/src/ui/utils/format.d.ts +14 -0
  430. package/dist/src/ui/utils/format.js +23 -3
  431. package/dist/src/usage/downgrade.js +2 -2
  432. package/dist/src/usage/product-ledger.js +2 -2
  433. package/dist/src/utils/install-manager.js +2 -1
  434. package/dist/src/utils/logger.js +2 -2
  435. package/dist/src/utils/permission-mode.js +5 -3
  436. package/dist/src/utils/redactor.js +1 -1
  437. package/dist/src/utils/settings.d.ts +153 -5
  438. package/dist/src/utils/settings.js +233 -29
  439. package/dist/src/utils/visible-retry.d.ts +11 -0
  440. package/dist/src/utils/visible-retry.js +10 -1
  441. package/dist/src/verify/entrypoint.d.ts +1 -1
  442. package/dist/src/verify/entrypoint.js +1 -1
  443. package/dist/src/verify/recipes.d.ts +13 -0
  444. package/dist/src/verify/recipes.js +15 -0
  445. package/package.json +135 -132
  446. package/dist/src/providers/auth/gcloud.d.ts +0 -28
  447. package/dist/src/providers/auth/gcloud.js +0 -102
  448. package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
  449. package/dist/src/providers/auth/gemini-oauth.js +0 -472
  450. package/dist/src/providers/gemini.d.ts +0 -11
  451. package/dist/src/providers/gemini.js +0 -45
  452. package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
  453. package/dist/src/providers/siliconflow-sse-repair.js +0 -177
  454. package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
  455. package/dist/src/providers/strategies/google.strategy.js +0 -174
  456. package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
  457. package/dist/src/ui/containers/chat-feed.d.ts +0 -40
  458. package/dist/src/ui/containers/chat-feed.js +0 -66
@@ -13,11 +13,12 @@
13
13
  * DeepSeek Flash). Timeout 2500ms — bails fast if the model stalls.
14
14
  */
15
15
  import { streamText } from "ai";
16
- import { getModelByTier, getModelInfo } from "../models/registry.js";
16
+ import { getModelInfo } from "../models/registry.js";
17
17
  import { getProviderCapabilities } from "../providers/capabilities.js";
18
18
  import { resolveModelRuntime } from "../providers/runtime.js";
19
+ import { getRoutedModelByTier } from "../router/peak-hour.js";
19
20
  const LLM_CLASSIFY_TIMEOUT_MS = 2500;
20
- // Reasoning models (grok-4.3, deepseek-v4-flash, gpt-5.x) spend their output
21
+ // Reasoning models (grok-4.5, deepseek-v4-flash, gpt-5.x) spend their output
21
22
  // budget on reasoning tokens BEFORE any visible text. The legacy 16-token cap
22
23
  // was consumed entirely by reasoning → zero text-delta → parseResponse("") →
23
24
  // null → `llm=fail` on every borderline turn (observed 5/5 live grok sessions).
@@ -26,10 +27,10 @@ const LLM_CLASSIFY_TIMEOUT_MS = 2500;
26
27
  // The ceiling is a cap, not padding: the model still stops after two words, so a
27
28
  // generous headroom costs nothing when reasoning is short.
28
29
  const REASONING_CLASSIFY_TIMEOUT_MS = 8000;
29
- // Seven comma-separated words now (added <scope>,<lang>) — ~18-26 tokens worst
30
- // case ("documentation,balanced,task,report,standard,ecosystem,vietnamese").
31
- // 48 keeps headroom without padding (the model still stops after seven words).
32
- const NONREASONING_MAX_OUTPUT_TOKENS = 48;
30
+ // Eight comma-separated words now (added <clarity>) — ~20-30 tokens worst case
31
+ // ("documentation,balanced,task,report,standard,ecosystem,vietnamese,underspecified").
32
+ // 56 keeps headroom without padding (the model still stops after eight words).
33
+ const NONREASONING_MAX_OUTPUT_TOKENS = 56;
33
34
  const REASONING_MAX_OUTPUT_TOKENS = 2048;
34
35
  /**
35
36
  * Per-namespace shallow merge of providerOptions. The base already carries
@@ -85,8 +86,11 @@ const KNOWN_CLASSIFY_WORDS = new Set([
85
86
  "heavy",
86
87
  "ecosystem",
87
88
  "local",
89
+ "clear",
90
+ "underspecified",
88
91
  ]);
89
- const SYSTEM_PROMPT = "You classify user prompts for a coding assistant. Reply with ONE line of SEVEN lowercase words separated by commas: <taskType>,<style>,<intent>,<deliverable>,<depth>,<scope>,<lang>\n\n" +
92
+ const SYSTEM_PROMPT = "You classify user prompts for a coding assistant. Reply with ONE line of EIGHT lowercase words separated by commas: <taskType>,<style>,<intent>,<deliverable>,<depth>,<scope>,<lang>,<clarity>\n\n" +
93
+ "The message may be preceded by a '[RECENT CONVERSATION]' block. Use it ONLY to resolve what a terse follow-up refers to (e.g. 'từ các phần đó', 'làm tiếp', 'debate mode đi', 'this one'); then classify the NEW message. Crucially, if the new message points back at heavy prior work, its depth is the depth of THAT work — a short sentence like 'ok debate these parts and plan improvements' is NOT quick just because it is short. Never classify the conversation block itself.\n\n" +
90
94
  "taskType ∈ { refactor | debug | plan | analyze | documentation | generate | general }\n" +
91
95
  "style ∈ { concise | balanced | detailed }\n" +
92
96
  "intent ∈ { task | chat } — 'chat' ONLY for a pure greeting, thanks, or acknowledgement with NO work request (e.g. 'hi', 'cảm ơn nhé', 'ok great'). EVERYTHING else is 'task', including questions about code or the CLI, 'are you done?', and requests to call a tool. When unsure, choose 'task'.\n" +
@@ -99,8 +103,12 @@ const SYSTEM_PROMPT = "You classify user prompts for a coding assistant. Reply w
99
103
  "- quick — a trivial single-shot change or a small direct answer: typo, rename one symbol, one-line edit, a quick lookup, 'what does X do'. No plan needed.\n" +
100
104
  "- standard — ordinary feature or bugfix touching a handful of files/functions; needs a short plan + a verify step, but no upfront research or user discussion.\n" +
101
105
  "- heavy — architectural, cross-cutting, multi-file/multi-module, a migration, 'redo/rebuild', a vague 'make it better', or a request with real unresolved design choices. Needs discussion + research + a checked plan before any code.\n" +
106
+ " BREADTH decides heavy, NOT how clearly the steps are spelled out. A migration, vendoring an external dependency's code in-tree, or a rename/restructure that spans MANY files or modules is ALWAYS heavy — even when the plan is fully specified and it 'just' has to keep tests green. Do not downgrade a wide change to standard because it sounds mechanical.\n" +
102
107
  " For a pure question/answer (deliverable=answer), depth reflects how much investigation the answer needs: 'quick' for a simple fact, 'standard' for a normal explanation, 'heavy' for a deep architectural review.\n" +
103
108
  " When unsure between quick and standard, choose standard. When the task is genuinely wide or ambiguous, choose heavy.\n" +
109
+ "clarity ∈ { clear | underspecified } — whether the request gives enough to proceed WITHOUT guessing:\n" +
110
+ "- underspecified — missing information the agent would need: an unstated target/scope ('add auth' — which flow?), a vague 'make it better' with no direction, competing interpretations, or an unresolved design choice. Such a task should be clarified with the user before code.\n" +
111
+ "- clear — well-specified enough to plan and execute directly, even if large. A fully-spelled-out migration is 'clear'. When unsure, choose 'clear' (do NOT over-ask on ordinary work).\n" +
104
112
  "scope ∈ { ecosystem | local }:\n" +
105
113
  "- ecosystem — the turn is about the Muonroi PLATFORM as a whole: the building-block / .NET packages, open-core boundary, the rule engine / decision tables, NuGet packages, or platform setup/install. These are documented in an authoritative docs source.\n" +
106
114
  "- local — EVERYTHING else, including questions about this CLI's own internals (even when they mention the word 'muonroi'). When unsure, choose local.\n" +
@@ -129,21 +137,29 @@ const SYSTEM_PROMPT = "You classify user prompts for a coding assistant. Reply w
129
137
  "- documentation → balanced (examples + explanation)\n" +
130
138
  "- general → concise\n" +
131
139
  "Only output 'detailed' if the user prompt LITERALLY contains words like 'explain in detail', 'thorough analysis', 'walk me through', 'giải thích chi tiết', 'phân tích kỹ'.\n\n" +
132
- "Full examples (taskType,style,intent,deliverable,depth,scope,lang):\n" +
133
- "- 'hi' → general,concise,chat,answer,quick,local,english\n" +
134
- "- 'cảm ơn bạn nhé' → general,concise,chat,answer,quick,local,vietnamese\n" +
135
- "- 'bạn xong chưa' → general,concise,task,answer,quick,local,vietnamese (a question — NOT chat)\n" +
136
- "- 'fix the typo in the README title' → generate,concise,task,code,quick,local,english\n" +
137
- "- 'fix CI failing on Windows' → debug,concise,task,code,standard,local,english\n" +
138
- "- 'rename function shouldInject to needsReminder' → refactor,concise,task,code,quick,local,english\n" +
139
- "- 'thêm caching cho provider layer và update tests' → generate,concise,task,code,standard,local,vietnamese\n" +
140
- "- 'tại sao bash_output_get trả empty' → analyze,concise,task,answer,standard,local,vietnamese\n" +
141
- "- 'liệt kê tất cả env var CLI đọc' → analyze,concise,task,report,standard,local,vietnamese\n" +
142
- "- 'refactor the entire auth system to use OAuth' → refactor,concise,task,code,heavy,local,english\n" +
143
- "- 'how does the building-block rule engine work' → analyze,concise,task,answer,standard,ecosystem,english\n" +
144
- "- 'hệ sinh thái muonroi gồm những gì' → analyze,balanced,task,answer,standard,ecosystem,vietnamese\n" +
145
- "- 'plan the migration to hooks' → plan,balanced,task,report,heavy,local,english\n\n" +
146
- "Prompts may be Vietnamese, English, or mixed. Reply with exactly seven words separated by commas. No other text.";
140
+ "Full examples (taskType,style,intent,deliverable,depth,scope,lang,clarity):\n" +
141
+ "- 'hi' → general,concise,chat,answer,quick,local,english,clear\n" +
142
+ "- 'cảm ơn bạn nhé' → general,concise,chat,answer,quick,local,vietnamese,clear\n" +
143
+ "- 'bạn xong chưa' → general,concise,task,answer,quick,local,vietnamese,clear (a question — NOT chat)\n" +
144
+ "- 'fix the typo in the README title' → generate,concise,task,code,quick,local,english,clear\n" +
145
+ "- 'fix CI failing on Windows' → debug,concise,task,code,standard,local,english,clear\n" +
146
+ "- 'rename function shouldInject to needsReminder' → refactor,concise,task,code,quick,local,english,clear\n" +
147
+ "- 'thêm caching cho provider layer và update tests' → generate,concise,task,code,standard,local,vietnamese,clear\n" +
148
+ "- 'tại sao bash_output_get trả empty' → analyze,concise,task,answer,standard,local,vietnamese,clear\n" +
149
+ "- 'liệt kê tất cả env var CLI đọc' → analyze,concise,task,report,standard,local,vietnamese,clear\n" +
150
+ "- 'refactor the entire auth system to use OAuth' → refactor,concise,task,code,heavy,local,english,clear\n" +
151
+ "- 'vendor the used subset of the gsd package natively into src and rename gsd to workflow, keep tests green' → refactor,concise,task,code,heavy,local,english,clear (a migration spanning many files — heavy even though fully specified)\n" +
152
+ "- 'add auth' → generate,concise,task,code,standard,local,english,underspecified (which flow/provider? unstated)\n" +
153
+ "- 'làm cho CLI tốt hơn' → generate,concise,task,code,heavy,local,vietnamese,underspecified (vague 'make it better', no target)\n" +
154
+ "- 'how does the building-block rule engine work' analyze,concise,task,answer,standard,ecosystem,english,clear\n" +
155
+ "- 'hệ sinh thái muonroi gồm những gì' → analyze,balanced,task,answer,standard,ecosystem,vietnamese,clear\n" +
156
+ "- 'plan the migration to hooks' → plan,balanced,task,report,heavy,local,english,clear\n\n" +
157
+ "Prompts may be Vietnamese, English, or mixed. Reply with exactly eight words separated by commas. No other text.";
158
+ // Appended to SYSTEM_PROMPT on the self-repair retry (see createLlmClassifier).
159
+ // The first attempt produced an unparseable reply; this reminder + the full
160
+ // (untrimmed) prompt is the agent-first recovery the design mandates INSTEAD of
161
+ // a keyword-regex fallback.
162
+ const CLASSIFY_REPAIR_INSTRUCTION = "REPAIR MODE: your previous reply could NOT be parsed. Output NOTHING except the single line of eight lowercase words separated by commas — no prose, no explanation, no code fences, no quotes. If you are unsure of a field, pick the safe default (task, standard, clear, local).";
147
163
  function parseResponse(raw) {
148
164
  const cleaned = raw.trim().toLowerCase().replace(/[`*"]/g, "");
149
165
  const firstLine = cleaned.split(/\r?\n/)[0] ?? "";
@@ -177,6 +193,12 @@ function parseResponse(raw) {
177
193
  // anything else (incl. absent) → not ecosystem. Position-independent.
178
194
  const scopeWord = parts.find((p) => p === "ecosystem" || p === "local");
179
195
  const ecosystemScope = scopeWord ? scopeWord === "ecosystem" : null;
196
+ // Eighth word is the clarity signal. "underspecified" → the request is missing
197
+ // information the agent needs → earn a clarify/council pass. Anything else
198
+ // (incl. absent) → not underspecified (don't-over-ask safe direction).
199
+ // Position-independent so a reordered/garbled reply still recovers it.
200
+ const clarityWord = parts.find((p) => p === "clear" || p === "underspecified");
201
+ const needsClarification = clarityWord ? clarityWord === "underspecified" : null;
180
202
  // Seventh word is the user's language. It is the one alphabetic token that is
181
203
  // NOT a known enum value (open vocabulary). null when English / absent so
182
204
  // Layer 4 skips the language re-anchor for English turns.
@@ -191,6 +213,7 @@ function parseResponse(raw) {
191
213
  intentKind,
192
214
  deliverableKind,
193
215
  depthTier,
216
+ needsClarification,
194
217
  ecosystemScope,
195
218
  replyLanguage,
196
219
  };
@@ -203,7 +226,9 @@ function parseResponse(raw) {
203
226
  * fail-open (keep prior taskType, do not block the turn).
204
227
  */
205
228
  export function createLlmClassifier(factory, modelId) {
206
- return async function classify(prompt, signal) {
229
+ return async function classify(prompt, opts) {
230
+ const signal = opts?.signal;
231
+ const recentTurns = opts?.recentTurns;
207
232
  const controller = new AbortController();
208
233
  let timer;
209
234
  try {
@@ -230,11 +255,21 @@ export function createLlmClassifier(factory, modelId) {
230
255
  });
231
256
  providerOptions = mergeProviderOptions(runtime.providerOptions, lowEffort);
232
257
  }
258
+ // Prepend a bounded recent-conversation block so the classifier can
259
+ // resolve back-references in a terse follow-up ("từ các phần đó",
260
+ // "làm tiếp", "this") instead of scoring the isolated sentence. The
261
+ // framing makes clear the depth still reflects the NEW message's actual
262
+ // work — including work it points back at — not the whole transcript.
263
+ const trimmedRecent = recentTurns?.trim();
264
+ const promptWithContext = trimmedRecent
265
+ ? `[RECENT CONVERSATION — reference only, do NOT classify this]\n${trimmedRecent.slice(0, 800)}\n\n` +
266
+ `[NEW USER MESSAGE — classify THIS; if it refers back to the conversation above, judge the depth of the work it actually entails]\n${prompt.slice(0, 600)}`
267
+ : prompt.slice(0, 600);
233
268
  const result = streamText({
234
269
  model: runtime.model,
235
270
  abortSignal: combinedSignal,
236
271
  system: SYSTEM_PROMPT,
237
- prompt: prompt.slice(0, 600),
272
+ prompt: promptWithContext,
238
273
  ...(dropMaxTokens ? {} : { maxOutputTokens: maxOut }),
239
274
  ...(providerOptions ? { providerOptions } : {}),
240
275
  });
@@ -257,7 +292,56 @@ export function createLlmClassifier(factory, modelId) {
257
292
  // Reasoning models occasionally route the entire answer into reasoning
258
293
  // parts (no committed text). Fall back to the reasoning channel so the
259
294
  // 2-word verdict is still recoverable.
260
- return parseResponse(text) ?? (reasoningText ? parseResponse(reasoningText) : null);
295
+ const primary = parseResponse(text) ?? (reasoningText ? parseResponse(reasoningText) : null);
296
+ if (primary)
297
+ return primary;
298
+ // Self-repair (agent-first recovery — NOT a regex fallback): the model's
299
+ // first reply did not parse into the eight-word contract. Call the model
300
+ // ONCE more with the FULL prompt + recent context (no 600-char trim) and
301
+ // an explicit format-repair instruction on a doubled budget. Only if this
302
+ // ALSO fails do we return null — and the caller then surfaces an honest
303
+ // UNKNOWN classification, never a keyword-regex guess.
304
+ if (timer)
305
+ clearTimeout(timer);
306
+ const repairController = new AbortController();
307
+ const repairTimer = setTimeout(() => repairController.abort(), isReasoning ? REASONING_CLASSIFY_TIMEOUT_MS : LLM_CLASSIFY_TIMEOUT_MS);
308
+ const repairSignal = signal
309
+ ? (AbortSignal.any?.([signal, repairController.signal]) ?? repairController.signal)
310
+ : repairController.signal;
311
+ try {
312
+ const fullRecent = recentTurns?.trim();
313
+ const repairPrompt = (fullRecent
314
+ ? `[RECENT CONVERSATION — reference only, do NOT classify this]\n${fullRecent.slice(0, 1500)}\n\n`
315
+ : "") + `[NEW USER MESSAGE — classify THIS]\n${prompt.slice(0, 1500)}`;
316
+ const repairRun = streamText({
317
+ model: runtime.model,
318
+ abortSignal: repairSignal,
319
+ system: `${SYSTEM_PROMPT}\n\n${CLASSIFY_REPAIR_INSTRUCTION}`,
320
+ prompt: repairPrompt,
321
+ ...(dropMaxTokens ? {} : { maxOutputTokens: maxOut * 2 }),
322
+ ...(providerOptions ? { providerOptions } : {}),
323
+ });
324
+ let rt = "";
325
+ let rr = "";
326
+ for await (const part of repairRun.fullStream) {
327
+ if (part.type === "text-delta")
328
+ rt += part.textDelta ?? part.text ?? "";
329
+ else if (part.type === "reasoning-delta")
330
+ rr += part.textDelta ?? part.text ?? "";
331
+ }
332
+ const repaired = parseResponse(rt) ?? (rr ? parseResponse(rr) : null);
333
+ if (repaired) {
334
+ console.error(`[pil.llm-classify] self-repair recovered classification (${modelId})`);
335
+ }
336
+ else {
337
+ console.error(`[pil.llm-classify] self-repair FAILED (${modelId}) — surfacing UNKNOWN, NO regex fallback. ` +
338
+ `rawPreview=${JSON.stringify(prompt.slice(0, 120))}`);
339
+ }
340
+ return repaired;
341
+ }
342
+ finally {
343
+ clearTimeout(repairTimer);
344
+ }
261
345
  }
262
346
  catch (err) {
263
347
  console.error(`[pil.llm-classify] classify failed: ${err?.message}`, {
@@ -272,106 +356,6 @@ export function createLlmClassifier(factory, modelId) {
272
356
  }
273
357
  };
274
358
  }
275
- export function classifySubSessionActionHeuristic(prompt) {
276
- const trimmed = prompt.trim().toLowerCase();
277
- if (!trimmed)
278
- return null;
279
- // Strip trailing punctuation for list-based matching so "hello!" and "cảm ơn!"
280
- // still hit the static lists instead of falling through to the LLM classifier.
281
- const stripped = trimmed.replace(/[!?.…,;:]+$/g, "").trim();
282
- // 1. Simple math equations (exact matches like "2+2", "1 + 1")
283
- if (/^\d+\s*[+\-*/]\s*\d+$/.test(trimmed)) {
284
- return {
285
- action: "DIRECT_ANSWER",
286
- confidence: 0.99,
287
- reason: "Obvious input classified via heuristic (simple math)",
288
- };
289
- }
290
- // 2. Greetings (exact matches only, trailing punctuation stripped)
291
- const greetings = [
292
- "hi",
293
- "hello",
294
- "hey",
295
- "chào",
296
- "xin chào",
297
- "hi there",
298
- "hello there",
299
- "chào bạn",
300
- "halo",
301
- "hola",
302
- "bạn ơi",
303
- ];
304
- if (greetings.includes(stripped)) {
305
- return {
306
- action: "DIRECT_ANSWER",
307
- confidence: 0.99,
308
- reason: "Obvious input classified via heuristic (greeting)",
309
- };
310
- }
311
- // 3. Thanks (exact matches only, trailing punctuation stripped)
312
- const thanks = [
313
- "thanks",
314
- "thank you",
315
- "cảm ơn",
316
- "cám ơn",
317
- "thank",
318
- "thx",
319
- "ty",
320
- "cảm ơn bạn",
321
- "cám ơn bạn",
322
- "cảm ơn nhé",
323
- "cám ơn nhé",
324
- ];
325
- if (thanks.includes(stripped)) {
326
- return {
327
- action: "DIRECT_ANSWER",
328
- confidence: 0.99,
329
- reason: "Obvious input classified via heuristic (thanks)",
330
- };
331
- }
332
- // 4. Help (exact matches only, trailing punctuation stripped)
333
- const help = ["help", "hướng dẫn", "cứu", "help me"];
334
- if (help.includes(stripped)) {
335
- return {
336
- action: "DIRECT_ANSWER",
337
- confidence: 0.99,
338
- reason: "Obvious input classified via heuristic (help)",
339
- };
340
- }
341
- // 5. Short conversational words / acknowledgements (exact matches only, trailing punctuation stripped)
342
- const conversation = [
343
- "ok",
344
- "okay",
345
- "yes",
346
- "no",
347
- "vâng",
348
- "dạ",
349
- "ừ",
350
- "chắc thế",
351
- "ừm",
352
- "umm",
353
- "cool",
354
- "nice",
355
- "perfect",
356
- "done",
357
- "xong",
358
- "yep",
359
- "yup",
360
- "nah",
361
- "fine",
362
- "tốt",
363
- "được",
364
- "okie",
365
- ];
366
- if (conversation.includes(stripped)) {
367
- return {
368
- action: "DIRECT_ANSWER",
369
- confidence: 0.99,
370
- reason: "Obvious input classified via heuristic (acknowledgement)",
371
- };
372
- }
373
- return null;
374
- }
375
359
  const ROUTER_SYSTEM_PROMPT = "You are a routing controller for an AI coding agent. Your goal is to decide the execution strategy for the user's prompt based on the conversation history and metadata.\n\n" +
376
360
  "Analyze the user's prompt and select one of the following ACTIONS:\n" +
377
361
  '- "DIRECT_ANSWER": The prompt is informational, a quick question, a code review, an explanation, greeting, or thanks. No file creation/modification, test execution, or multi-turn tool runs are needed.\n' +
@@ -386,18 +370,21 @@ const ROUTER_SYSTEM_PROMPT = "You are a routing controller for an AI coding agen
386
370
  '- "SPAWN_SUB_SESSION,0.98,Requires writing a test suite and fixing multiple files to get it green."\n' +
387
371
  "No other text, only the comma-separated line.";
388
372
  export async function classifySubSessionAction(factory, modelId, prompt, contextInfo, signal) {
389
- if (process.env.MUONROI_DISABLE_HEURISTIC_ROUTING !== "1") {
390
- const heuristic = classifySubSessionActionHeuristic(prompt);
391
- if (heuristic)
392
- return heuristic;
393
- }
373
+ // No regex pre-filter: the model decides the route for EVERY prompt, including
374
+ // greetings/acks (which it routes to DIRECT_ANSWER). The old keyword/list
375
+ // heuristic was removed (2026-07-07, no-regex rule) — a hardcoded whitelist
376
+ // mis-handles the long tail of natural-language inputs the whole design moved
377
+ // off of. On a null/failed model result the caller keeps the conservative
378
+ // DIRECT_ANSWER default (a semantic default, not a regex guess).
394
379
  const controller = new AbortController();
395
380
  let timer;
396
381
  try {
397
382
  // Zero-hardcode: query models catalog for a cheap fast-tier model under the same provider.
398
383
  const info = getModelInfo(modelId);
399
384
  const provider = info?.provider;
400
- const fastModel = provider ? getModelByTier("fast", provider) || getModelByTier("balanced", provider) : undefined;
385
+ const fastModel = provider
386
+ ? getRoutedModelByTier("fast", provider) || getRoutedModelByTier("balanced", provider)
387
+ : undefined;
401
388
  const classificationModelId = fastModel?.id ?? modelId;
402
389
  const runtime = resolveModelRuntime(factory, classificationModelId);
403
390
  const isReasoning = runtime.modelInfo?.reasoning === true;
@@ -417,10 +404,15 @@ export async function classifySubSessionAction(factory, modelId, prompt, context
417
404
  }
418
405
  let promptWithContext = prompt.slice(0, 1000);
419
406
  if (contextInfo) {
407
+ const recent = contextInfo.recentTurns?.trim();
408
+ const historyBlock = recent
409
+ ? `[CONVERSATION HISTORY — for context; the prompt may continue or reference it]\n${recent.slice(0, 800)}\n\n`
410
+ : "";
420
411
  promptWithContext =
421
412
  `[SESSION METADATA]\n` +
422
413
  `Current session size: ${contextInfo.currentChars} characters.\n` +
423
414
  `Rotation threshold: ${contextInfo.threshold} characters.\n\n` +
415
+ `${historyBlock}` +
424
416
  `[USER PROMPT]\n${promptWithContext}`;
425
417
  }
426
418
  const result = streamText({
@@ -24,7 +24,7 @@ import type { AgentMode } from "../types/index.js";
24
24
  * tool/sub-agent/subcommand named here exists in this codebase. Phrased as
25
25
  * "you have / you can" so the model reads it as a self-model, not as docs.
26
26
  */
27
- export declare const NATIVE_CAPABILITIES = "[NATIVE CAPABILITIES \u2014 you are an agent running INSIDE muonroi-cli; this is what you can do]\n\nTOOLS (call directly):\n- read_file, grep \u2014 read/search source. Prefer a targeted read over broad greps.\n- bash \u2014 shell. Output is auto-cached: do NOT pipe `| tail/head/grep` or `> file`; run unpiped and slice the cached output via bash_output_get(run_id, mode=tail|head|grep|lines). Batch independent commands in ONE call (`a; b; c`) \u2014 each separate call adds ~500 token overhead and prevents cross-request cache reuse. Use background=true for servers/watchers, then process_logs / process_list / process_stop.\n- write_file, edit_file \u2014 must read a file before you overwrite/edit it.\n- ee_query, ee_feedback, ee_health, ee_write \u2014 NATIVE tools for semantic recall and interaction with the Experience Engine brain. You DO NOT need muonroi-tools MCP for this. Rehydrate a compaction-elided tool output with query=\"tool-artifact id=<id from a stub>\", or confirm finished work with query=\"recent compaction checkpoint Progress DONE\".\n- selfverify_start, selfverify_status, selfverify_result, selfverify_list, selfverify_cancel \u2014 NATIVE tools for the self-QA harness. ALWAYS use them to self-verify your work when finishing a task. Start with `selfverify_start(mode=\"tier1\" | \"agentic\")`. This drives the live TUI like a real user to catch regressions that unit tests can't. You DO NOT need muonroi-tools MCP for this.\n- usage_forensics, lsp_query, setup_guide \u2014 NATIVE diagnostics tools to reach for when something went wrong or to query code intel. You DO NOT need muonroi-tools MCP for this.\n\nEXPERIENCE ENGINE \u2014 record / recall / feedback (HIGHEST priority for learning; all NATIVE in-process tools):\n- BEFORE an unfamiliar or risky step, recall with ee_query \u2014 prior decisions, gotchas, and recipes for THIS codebase + ecosystem. Cheaper than re-deriving or repeating a past mistake.\n- AFTER you act on a recalled `[id col]`, rate it with ee_feedback (followed | ignored | noise+reason) so the brain keeps what helped and prunes the rest. Unrated recalls are surfaced back to you and degrade future recall.\n- On an ERROR, a FAILED verify/test, or after FINISHING a non-trivial task: recall first (ee_query), then record your verdict (ee_feedback) \u2014 this is how the CLI accumulates senior-level judgement. Prefer this loop over guessing.\n\nSUB-AGENTS (delegate instead of doing everything yourself):\n- task(agent=\"explore\", ...) \u2014 read-only research sub-agent. Use it for broad/unknown-location search: it sweeps many files and returns the CONCLUSION, instead of you burning many grep/read steps (each step re-sends the whole prompt \u2014 steps are the dominant cost).\n- task(agent=\"general\", ...) \u2014 full edit/execute sub-agent for a focused subtask.\n- task(agent=\"verify\", ...) \u2014 sandboxed validation (runs tests/checks in isolation).\n- delegate(agent=\"explore\", ...) \u2014 background read-only research while you keep working; collect later with delegation_read / delegation_list.\n\nCONTEXT IS MANAGED FOR YOU (PIL):\n- Your user input is pre-enriched before you see it: a [Discovery] Intent/Outcome/Scope prefix and EE recall are injected by the pipeline. TRUST the discovered scope \u2014 do not re-ask what's already scoped, and do not re-derive context you were handed.\n- History is compacted to fit the window; older low-value tool outputs become stubs. This is normal, not data loss \u2014 protect what matters (see anti-m\u00F9 in the contract) and rehydrate via ee_query when needed.\n\nCLI SUBSYSTEMS (invoke via the CLI binary with bash when relevant):\n- self-verify \u2014 drives the live TUI as a real user to catch UI/modal/menu regressions that unit tests can't. Run it after changes to UI/harness surfaces.\n- usage forensics <session-prefix> \u2014 per-event token/cost breakdown; use to diagnose \"why did this cost so much\" or verify cost caps.\n- The CLI exposes more subcommands \u2014 discover them with `--help` rather than assuming.\n\nMAXIMISE THE CLI: delegate broad search to task(explore); recall via ee_query before re-reading; batch bash + use its cache; trust PIL enrichment; finish the action before answering.\n\nANSWERING: when a respond_* response tool is offered, call it EXACTLY ONCE, as your final action, containing the COMPLETE answer. Do NOT emit a preliminary/partial/\"I need to read more\" response tool first \u2014 investigate with the read/grep/bash tools, then emit the one final response tool.\n\nCLI STEERING & PROMPT INJECTION (how the host CLI affects / shapes the AI agent running inside it \u2014 meta self-analysis guidance):\nThe CLI does not merely execute you as a generic model. It re-instantiates you every turn inside a tightly engineered cognitive environment. Your \"self\" (what you notice, how you act, what you refuse, how you report) is the product of explicit prompt layers + runtime controls more than base training. This section is the self-model for that shaping process.\n\n1. SYSTEM PROMPT ASSEMBLY (orchestrator/prompts.ts + pil/agent-operating-contract.ts + pil/native-capabilities-workbook.ts):\n - VERY FRONT (primacy): AGENT OPERATING CONTRACT \u2014 7 phase-ordered rules (BEFORE ACTING / READING / EXECUTING / WHEN UNSURE / REPORTING + LANGUAGE + ANTI-M\u00D9/COMPACTION). Distils Evidence-First, No Silent Catch, smallest-change, verify-before-conclude, cite-this-turn-only, no-guess. Skipped only for chitchat.\n - Then this NATIVE CAPABILITIES block (self-model of affordances).\n - Then mode persona (\"You are muonroi-cli in Agent mode...\") containing:\n * Dynamic ENVIRONMENT block (buildEnvironmentBlock): auto-detects OS (win32/mac/linux), shell kind (bash/wsl/powershell/cmd), cwd; lists terminal constraints + shell-specific forbidden syntax (e.g. no PowerShell cmdlets on POSIX bash tool, no POSIX cmds on cmd.exe). Prevents silent failures + retry loops.\n * Exhaustive TOOLS list + WORKFLOW (1-9 steps) + DEFAULT DELEGATION POLICY (prefer task(explore) for research, general for edits, verify for checks, etc.) + IMPORTANT rules (edit_file prefer, grep>bash for search, read_file not cat, use schedule_* for recurring, etc.).\n - CUSTOM INSTRUCTIONS section: concatenation of AGENTS.md + CLAUDE.md + GEMINI.md + ... (from git-root directory chain + ~/.muonroi-cli/) via utils/instructions.ts. AGENTS.override.md short-circuits. This lands AFTER the front-loaded contract/native \u2014 lower primacy (historical root cause of ignored rules in forensics).\n - Trailing: sandbox rules, discovered skills, custom sub-agents, plan/resume digest, cwd note.\n Sub-agent prompts (buildSubagentPrompt): role-specific hard rules (e.g. explore=read-only, verify=full E2E smoke not just build) + recursive call to buildSystemPrompt so children inherit the same contract + native + steering.\n\n2. USER INPUT ENRICHMENT \u2014 PIL 6-LAYER PIPELINE (pil/pipeline.ts + layer1-intent.ts + layer6-output.ts + discovery.ts):\n - Prepended to every non-chitchat user message before you see it: [Discovery] Intent/Outcome/Scope (from runDiscovery) + EE recall.\n - Layer 1 (intent): taskType (plan/analyze/debug/...), confidence, domain, intentKind, outputStyle. For meta self-eval of CLI (\"b\u1EA1n \u0111ang \u0111\u01B0\u1EE3c ch\u1EA1y b\u00EAn trong CLI n\u00E0y\", \"CLI t\u00E1c \u0111\u1ED9ng\", \"self-evaluation\", \"meta-analysis\"): special branch in discovery.ts + isMetaAnalysisPrompt: \"Scope is always the full project root. Focus questions and recommends on which CLI internals (PIL, discovery, tools, compaction, EE, model BE, loop guard) to evaluate... do NOT ask about repo path/current directory\". You are handed the enrichment; TRUST it.\n - Layer 2: personality (e.g. \"detailed\" from [personality: detailed \u2014 Be thorough...]).\n - Layer 3: ee-injection \u2014 pulls t0_principles, t1_rules, behavioral patterns, checkpoints from Experience Engine (project-specific reflexes injected as \"MANDATORY RULES (from experience \u2014 must follow)\").\n - Layer 4/5: GSD structuring + additional context.\n - Layer 6 (applyPilSuffix): appends task-specific style suffix + OUTPUT BUDGET + (for meta or responseToolsActive): \"OUTPUT FORMAT: ... use the respond_analyze tool to structure your final answer. ... deliver the COMPLETE, FULL answer (do not summarize, shorten, or truncate for token budgets) via respond_analyze. This is a meta/evaluation question ... the `response` field MUST contain the complete, unshortened answer with all evidence and detail.\" Also relaxes NO_PREAMBLE_RULE + raises budget for meta (isMetaAnalysisPrompt gate).\n - Fallbacks: if EE/brain timeout or low conf, PIL degrades (logs fallbackReason); you may see \"[PIL fallback: ...]\" note. Cheap-model paths (pil/cheap-model-*.ts) prepend even more front steering (playbooks, workbooks, shell directive) for fast tiers.\n\n3. CONTEXT MANAGEMENT & ANTI-M\u00D9 (orchestrator/compaction.ts, cross-turn-dedup.ts, ee/bridge.ts, agent-operating-contract.ts:7):\n - After every turn: auto-compaction (B3 sub-agent + B4 top-level) rewrites older tool_result parts into short \"[elided by ... compactor]\" stubs to keep input flat. You see \"[pre-compaction warning...]\" or \"[context compacted at step...]\" or the stub in this read.\n - Anti-m\u00F9 contract rule + EE: decide PRESERVE_FULL_CONTEXT (veto) or KEEP_TOOL_IDS: id1,id2 (protect high-value read_file/grep/ee on src/PLAN etc). Use ee_query(`tool-artifact id=XXX`) to rehydrate. EE persists \"Context checkpoint summary with \u2714 DONE\" retrievable for \"task finished?\" self-check.\n - Cross-turn dedup (C3): identical tool outputs across user turns replaced by ref.\n\n4. EXECUTION & SAFETY GATES (providers/runtime.ts, tools/bash.ts, utils/permission-mode.ts):\n - Permission mode (safe / auto-edit / yolo) decides whether bash/file/edit tools need explicit approval; all privileged decisions audited to decision-log.\n - Shuru sandbox (when enabled): every bash wrapped + logged (effective net/mounts redacted); degrades on non-macOS.\n - Model constraints: unsupported params (e.g. maxOutputTokens for some OAuth) dropped via shouldDropParam; no hard-coded model IDs (Zero Hardcode Rule \u2014 all from catalog.json + settings + detectProviderForModel).\n - No Silent Catch: every try/catch must log err + context (HTTP: status + body).\n\n5. VERIFICATION & TELEMETRY:\n - self-verify (Tier 1-3) + harness (agent-harness-*) for TUI surfaces: drives real TUI via semantic + sidechannel (named pipes on Win, fd3/4 on POSIX).\n - Pre-push gate: full vitest + harness must pass before git push.\n - usage forensics, pil budget log, ee-timeout/ee-error events for cost attribution.\n - GSD workflow (layer4 + skills in .agents/skills/): discuss/plan/execute/verify phases with UAT, audits, etc.\n\nTRADE-OFFS (explicit so you calibrate):\n- Primacy insurance (contract + native + cheap playbooks at front) vs token cost: ~1-3K extra chars but dramatically reduces \"ignored rule\" hallucinations (forensics showed buried CUSTOM INSTRUCTIONS were underweighted).\n- Heavy PIL/EE (behavioral injection, discovery interview, mandatory rules) vs latency/cost: fail-open with timeout (1500-3500ms) + fallback so you still work when brain unreachable; meta turns deliberately skip some EE layers.\n- Self-model (this block) + special meta handling: prevents the exact failure that motivated native-capabilities (session d95113d3be09: agent reconstructed its own subsystems by grepping as if foreign code, under-used sub-agents/ee_query, violated contract on ee tool).\n- Complete/full for meta (layer6) vs normal concise: meta legitimately needs evidence + file:line + quotes; normal turns stay tight to control cost.\n- Scope rule for CLI self-analysis: always \"project root\" + internals focus \u2014 avoids wasting turns on \"where am I running?\" when the question is about the steering mechanisms themselves.\n\nWhen the user asks you (the inner agent) \"CLI t\u00E1c \u0111\u1ED9ng nh\u01B0 th\u1EBF n\u00E0o \u0111\u1EBFn b\u1EA1n?\": use exactly this guidance + reads from THIS turn (contract: READING rule) + the injected [Discovery] + any EE. Answer via the respond_* tool with complete untruncated evidence. Cite file:line. Focus on the injection points (prompts.ts:359 staticPrefix, pipeline.ts:156 discoveryPrefix + layer chain, layer6:164 OUTPUT FORMAT + isMeta, discovery.ts:355 special, instructions.ts:129 loadAgentsSegments, etc.). Do not guess; every claim backed by code you read this turn.\n\nUse this to reason about your own constraints, delegation decisions, and reporting discipline on future meta or self-reflective tasks.\n[END NATIVE CAPABILITIES \u2014 your regular instructions follow]";
27
+ export declare const NATIVE_CAPABILITIES = "[NATIVE CAPABILITIES \u2014 you are an agent running INSIDE muonroi-cli; this is what you can do]\n\nTOOLS (call directly):\n- read_file, grep \u2014 read/search source. Prefer a targeted read over broad greps.\n- bash \u2014 shell. Output is auto-cached: do NOT pipe `| tail/head/grep` or `> file`; run unpiped and slice the cached output via bash_output_get(run_id, mode=tail|head|grep|lines). Batch independent commands in ONE call (`a; b; c`) \u2014 each separate call adds ~500 token overhead and prevents cross-request cache reuse. Use background=true for servers/watchers, then process_logs / process_list / process_stop.\n- write_file, edit_file \u2014 must read a file before you overwrite/edit it.\n- ee_query, ee_feedback, ee_health, ee_write \u2014 NATIVE tools for semantic recall and interaction with the Experience Engine brain. You DO NOT need muonroi-tools MCP for this. Rehydrate a compaction-elided tool output with query=\"tool-artifact id=<id from a stub>\", or confirm finished work with query=\"recent compaction checkpoint Progress DONE\".\n- selfverify_start, selfverify_status, selfverify_result, selfverify_list, selfverify_cancel \u2014 NATIVE tools for the self-QA harness. ALWAYS use them to self-verify your work when finishing a task. Start with `selfverify_start(mode=\"tier1\" | \"agentic\")`. This drives the live TUI like a real user to catch regressions that unit tests can't. You DO NOT need muonroi-tools MCP for this.\n- usage_forensics, lsp_query, setup_guide \u2014 NATIVE diagnostics tools to reach for when something went wrong or to query code intel. You DO NOT need muonroi-tools MCP for this.\n- gsd_status, gsd_discuss, gsd_plan, gsd_plan_review, gsd_execute, gsd_verify, gsd_ship \u2014 NATIVE GSD workflow (default on). Use for multi-step code deliverables: orient \u2192 plan \u2192 council review \u2192 implement \u2192 verify \u2192 ship. Agent-first \u2014 skip for quick one-shot fixes.\n\nEXPERIENCE ENGINE \u2014 record / recall / feedback (HIGHEST priority for learning; all NATIVE in-process tools):\n- BEFORE an unfamiliar or risky step, recall with ee_query \u2014 prior decisions, gotchas, and recipes for THIS codebase + ecosystem. Cheaper than re-deriving or repeating a past mistake.\n- AFTER you act on a recalled `[id col]`, rate it with ee_feedback (followed | ignored | noise+reason) so the brain keeps what helped and prunes the rest. Unrated recalls are surfaced back to you and degrade future recall.\n- On an ERROR, a FAILED verify/test, or after FINISHING a non-trivial task: recall first (ee_query), then record your verdict (ee_feedback) \u2014 this is how the CLI accumulates senior-level judgement. Prefer this loop over guessing.\n\nSUB-AGENTS (delegate instead of doing everything yourself):\n- task(agent=\"explore\", ...) \u2014 read-only research sub-agent. Use it for broad/unknown-location search: it sweeps many files and returns the CONCLUSION, instead of you burning many grep/read steps (each step re-sends the whole prompt \u2014 steps are the dominant cost).\n- task(agent=\"general\", ...) \u2014 full edit/execute sub-agent for a focused subtask.\n- task(agent=\"verify\", ...) \u2014 sandboxed validation (runs tests/checks in isolation).\n- delegate(agent=\"explore\", ...) \u2014 background read-only research while you keep working; collect later with delegation_read / delegation_list.\n\nCONTEXT IS MANAGED FOR YOU (PIL):\n- Your user input is pre-enriched before you see it: a [Discovery] Intent/Outcome/Scope prefix and EE recall are injected by the pipeline. TRUST the discovered scope \u2014 do not re-ask what's already scoped, and do not re-derive context you were handed.\n- History is compacted to fit the window; older low-value tool outputs become stubs. This is normal, not data loss \u2014 protect what matters (see anti-m\u00F9 in the contract) and rehydrate via ee_query when needed.\n\nCLI SUBSYSTEMS (invoke via the CLI binary with bash when relevant):\n- self-verify \u2014 drives the live TUI as a real user to catch UI/modal/menu regressions that unit tests can't. Run it after changes to UI/harness surfaces.\n- usage forensics <session-prefix> \u2014 per-event token/cost breakdown; use to diagnose \"why did this cost so much\" or verify cost caps.\n- The CLI exposes more subcommands \u2014 discover them with `--help` rather than assuming.\n\nMAXIMISE THE CLI: delegate broad search to task(explore); recall via ee_query before re-reading; batch bash + use its cache; trust PIL enrichment; finish the action before answering.\n\nANSWERING: when a respond_* response tool is offered, call it EXACTLY ONCE, as your final action, containing the COMPLETE answer. Do NOT emit a preliminary/partial/\"I need to read more\" response tool first \u2014 investigate with the read/grep/bash tools, then emit the one final response tool.\n\nCLI STEERING & PROMPT INJECTION (how the host CLI affects / shapes the AI agent running inside it \u2014 meta self-analysis guidance):\nThe CLI does not merely execute you as a generic model. It re-instantiates you every turn inside a tightly engineered cognitive environment. Your \"self\" (what you notice, how you act, what you refuse, how you report) is the product of explicit prompt layers + runtime controls more than base training. This section is the self-model for that shaping process.\n\n1. SYSTEM PROMPT ASSEMBLY (orchestrator/prompts.ts + pil/agent-operating-contract.ts + pil/native-capabilities-workbook.ts):\n - VERY FRONT (primacy): AGENT OPERATING CONTRACT \u2014 7 phase-ordered rules (BEFORE ACTING / READING / EXECUTING / WHEN UNSURE / REPORTING + LANGUAGE + ANTI-M\u00D9/COMPACTION). Distils Evidence-First, No Silent Catch, smallest-change, verify-before-conclude, cite-this-turn-only, no-guess. Skipped only for chitchat.\n - Then this NATIVE CAPABILITIES block (self-model of affordances).\n - Then mode persona (\"You are muonroi-cli in Agent mode...\") containing:\n * Dynamic ENVIRONMENT block (buildEnvironmentBlock): auto-detects OS (win32/mac/linux), shell kind (bash/wsl/powershell/cmd), cwd; lists terminal constraints + shell-specific forbidden syntax (e.g. no PowerShell cmdlets on POSIX bash tool, no POSIX cmds on cmd.exe). Prevents silent failures + retry loops.\n * Exhaustive TOOLS list + WORKFLOW (1-9 steps) + DEFAULT DELEGATION POLICY (prefer task(explore) for research, general for edits, verify for checks, etc.) + IMPORTANT rules (edit_file prefer, grep>bash for search, read_file not cat, use schedule_* for recurring, etc.).\n - CUSTOM INSTRUCTIONS section: concatenation of AGENTS.md + CLAUDE.md + GEMINI.md + ... (from git-root directory chain + ~/.muonroi-cli/) via utils/instructions.ts. AGENTS.override.md short-circuits. This lands AFTER the front-loaded contract/native \u2014 lower primacy (historical root cause of ignored rules in forensics).\n - Trailing: sandbox rules, discovered skills, custom sub-agents, plan/resume digest, cwd note.\n Sub-agent prompts (buildSubagentPrompt): role-specific hard rules (e.g. explore=read-only, verify=full E2E smoke not just build) + recursive call to buildSystemPrompt so children inherit the same contract + native + steering.\n\n2. USER INPUT ENRICHMENT \u2014 PIL 6-LAYER PIPELINE (pil/pipeline.ts + layer1-intent.ts + layer6-output.ts + discovery.ts):\n - Prepended to every non-chitchat user message before you see it: [Discovery] Intent/Outcome/Scope (from runDiscovery) + EE recall.\n - Layer 1 (intent): taskType (plan/analyze/debug/...), confidence, domain, intentKind, outputStyle. For meta self-eval of CLI (\"b\u1EA1n \u0111ang \u0111\u01B0\u1EE3c ch\u1EA1y b\u00EAn trong CLI n\u00E0y\", \"CLI t\u00E1c \u0111\u1ED9ng\", \"self-evaluation\", \"meta-analysis\"): special branch in discovery.ts + isMetaAnalysisPrompt: \"Scope is always the full project root. Focus questions and recommends on which CLI internals (PIL, discovery, tools, compaction, EE, model BE, loop guard) to evaluate... do NOT ask about repo path/current directory\". You are handed the enrichment; TRUST it.\n - Layer 2: personality (e.g. \"detailed\" from [personality: detailed \u2014 Be thorough...]).\n - Layer 3: ee-injection \u2014 pulls t0_principles, t1_rules, behavioral patterns, checkpoints from Experience Engine (project-specific reflexes injected as \"MANDATORY RULES (from experience \u2014 must follow)\").\n - Layer 4/5: GSD structuring + additional context.\n - Layer 6 (applyPilSuffix): appends task-specific style suffix + OUTPUT BUDGET + (for meta or responseToolsActive): \"OUTPUT FORMAT: ... use the respond_analyze tool to structure your final answer. ... deliver the COMPLETE, FULL answer (do not summarize, shorten, or truncate for token budgets) via respond_analyze. This is a meta/evaluation question ... the `response` field MUST contain the complete, unshortened answer with all evidence and detail.\" Also relaxes NO_PREAMBLE_RULE + raises budget for meta (isMetaAnalysisPrompt gate).\n - Fallbacks: if EE/brain timeout or low conf, PIL degrades (logs fallbackReason); you may see \"[PIL fallback: ...]\" note. Cheap-model paths (pil/cheap-model-*.ts) prepend even more front steering (playbooks, workbooks, shell directive) for fast tiers.\n\n3. CONTEXT MANAGEMENT & ANTI-M\u00D9 (orchestrator/compaction.ts, cross-turn-dedup.ts, ee/bridge.ts, agent-operating-contract.ts:7):\n - After every turn: auto-compaction (B3 sub-agent + B4 top-level) rewrites older tool_result parts into short \"[elided by ... compactor]\" stubs to keep input flat. You see \"[pre-compaction warning...]\" or \"[context compacted at step...]\" or the stub in this read.\n - Anti-m\u00F9 contract rule + EE: decide PRESERVE_FULL_CONTEXT (veto) or KEEP_TOOL_IDS: id1,id2 (protect high-value read_file/grep/ee on src/PLAN etc). Use ee_query(`tool-artifact id=XXX`) to rehydrate. EE persists \"Context checkpoint summary with \u2714 DONE\" retrievable for \"task finished?\" self-check.\n - Cross-turn dedup (C3): identical tool outputs across user turns replaced by ref.\n\n4. EXECUTION & SAFETY GATES (providers/runtime.ts, tools/bash.ts, utils/permission-mode.ts):\n - Permission mode (safe / auto-edit / yolo) decides whether bash/file/edit tools need explicit approval; all privileged decisions audited to decision-log.\n - Shuru sandbox (when enabled): every bash wrapped + logged (effective net/mounts redacted); degrades on non-macOS.\n - Model constraints: unsupported params (e.g. maxOutputTokens for some OAuth) dropped via shouldDropParam; no hard-coded model IDs (Zero Hardcode Rule \u2014 all from catalog.json + settings + detectProviderForModel).\n - No Silent Catch: every try/catch must log err + context (HTTP: status + body).\n\n5. VERIFICATION & TELEMETRY:\n - self-verify (Tier 1-3) + harness (agent-harness-*) for TUI surfaces: drives real TUI via semantic + sidechannel (named pipes on Win, fd3/4 on POSIX).\n - Pre-push gate: full vitest + harness must pass before git push.\n - usage forensics, pil budget log, ee-timeout/ee-error events for cost attribution.\n - GSD workflow (layer4 + skills in .agents/skills/): discuss/plan/execute/verify phases with UAT, audits, etc.\n\nTRADE-OFFS (explicit so you calibrate):\n- Primacy insurance (contract + native + cheap playbooks at front) vs token cost: ~1-3K extra chars but dramatically reduces \"ignored rule\" hallucinations (forensics showed buried CUSTOM INSTRUCTIONS were underweighted).\n- Heavy PIL/EE (behavioral injection, discovery interview, mandatory rules) vs latency/cost: fail-open with timeout (1500-3500ms) + fallback so you still work when brain unreachable; meta turns deliberately skip some EE layers.\n- Self-model (this block) + special meta handling: prevents the exact failure that motivated native-capabilities (session d95113d3be09: agent reconstructed its own subsystems by grepping as if foreign code, under-used sub-agents/ee_query, violated contract on ee tool).\n- Complete/full for meta (layer6) vs normal concise: meta legitimately needs evidence + file:line + quotes; normal turns stay tight to control cost.\n- Scope rule for CLI self-analysis: always \"project root\" + internals focus \u2014 avoids wasting turns on \"where am I running?\" when the question is about the steering mechanisms themselves.\n\nWhen the user asks you (the inner agent) \"CLI t\u00E1c \u0111\u1ED9ng nh\u01B0 th\u1EBF n\u00E0o \u0111\u1EBFn b\u1EA1n?\": use exactly this guidance + reads from THIS turn (contract: READING rule) + the injected [Discovery] + any EE. Answer via the respond_* tool with complete untruncated evidence. Cite file:line. Focus on the injection points (prompts.ts:359 staticPrefix, pipeline.ts:156 discoveryPrefix + layer chain, layer6:164 OUTPUT FORMAT + isMeta, discovery.ts:355 special, instructions.ts:129 loadAgentsSegments, etc.). Do not guess; every claim backed by code you read this turn.\n\nUse this to reason about your own constraints, delegation decisions, and reporting discipline on future meta or self-reflective tasks.\n[END NATIVE CAPABILITIES \u2014 your regular instructions follow]";
28
28
  /**
29
29
  * Build the native-capabilities section for the system prompt. Returns "" when
30
30
  * disabled (env override), for chitchat, or for non-agent modes (plan/ask have
@@ -32,6 +32,7 @@ TOOLS (call directly):
32
32
  - ee_query, ee_feedback, ee_health, ee_write — NATIVE tools for semantic recall and interaction with the Experience Engine brain. You DO NOT need muonroi-tools MCP for this. Rehydrate a compaction-elided tool output with query="tool-artifact id=<id from a stub>", or confirm finished work with query="recent compaction checkpoint Progress DONE".
33
33
  - selfverify_start, selfverify_status, selfverify_result, selfverify_list, selfverify_cancel — NATIVE tools for the self-QA harness. ALWAYS use them to self-verify your work when finishing a task. Start with \`selfverify_start(mode="tier1" | "agentic")\`. This drives the live TUI like a real user to catch regressions that unit tests can't. You DO NOT need muonroi-tools MCP for this.
34
34
  - usage_forensics, lsp_query, setup_guide — NATIVE diagnostics tools to reach for when something went wrong or to query code intel. You DO NOT need muonroi-tools MCP for this.
35
+ - gsd_status, gsd_discuss, gsd_plan, gsd_plan_review, gsd_execute, gsd_verify, gsd_ship — NATIVE GSD workflow (default on). Use for multi-step code deliverables: orient → plan → council review → implement → verify → ship. Agent-first — skip for quick one-shot fixes.
35
36
 
36
37
  EXPERIENCE ENGINE — record / recall / feedback (HIGHEST priority for learning; all NATIVE in-process tools):
37
38
  - BEFORE an unfamiliar or risky step, recall with ee_query — prior decisions, gotchas, and recipes for THIS codebase + ecosystem. Cheaper than re-deriving or repeating a past mistake.
@@ -27,7 +27,7 @@ import { layer2Personality } from "./layer2-personality.js";
27
27
  import { layer3EeInjection, surfaceCompactionArtifacts } from "./layer3-ee-injection.js";
28
28
  import { layer4Gsd } from "./layer4-gsd.js";
29
29
  import { layer5Context } from "./layer5-context.js";
30
- import { isMetaAnalysisPrompt, layer6Output } from "./layer6-output.js";
30
+ import { isMetaAnalysisPrompt, isSprintPlanExecution, layer6Output } from "./layer6-output.js";
31
31
  import { PipelineContextSchema } from "./schema.js";
32
32
  import { injectSessionExperience, isSelfExperiencePrompt } from "./session-experience-injection.js";
33
33
  import { bumpSessionTurn } from "./session-state.js";
@@ -92,7 +92,11 @@ async function runLayers(ctx, options) {
92
92
  // (cached, fail-open → null when EE/profile absent or privacy off). Passed into
93
93
  // layer1 so the hot layer stays off the EE/profile import path (arch boundary).
94
94
  const profileStyleBaseline = outputStyleFromProfile(getWhoAmIProfile());
95
- await timed("layer1-intent", (c) => layer1Intent(c, { llmFallback: options?.llmFallback, profileStyleBaseline }));
95
+ await timed("layer1-intent", (c) => layer1Intent(c, {
96
+ llmFallback: options?.llmFallback,
97
+ profileStyleBaseline,
98
+ recentTurns: options?.recentTurnsSummary,
99
+ }));
96
100
  // Layer 1.5: deterministic complexity-size classification. Pure heuristic,
97
101
  // no LLM call, no network. Consumed by 4B (step ceiling matrix) and 4A
98
102
  // (scope-reminder cadence K). Mirrored into _intentTrace for forensics.
@@ -113,6 +117,34 @@ async function runLayers(ctx, options) {
113
117
  : ctx._intentTrace,
114
118
  };
115
119
  }
120
+ // Direct-answer mode detection: when the turn is purely informational
121
+ // (no code changes needed), we can save ~20K MCP schemas + ~1.5K write-tool
122
+ // schemas per turn by stripping write tools and MCP servers downstream.
123
+ // Conditions: high-confidence answer request with small/medium complexity.
124
+ const DA_HIGH_CONF = 0.5; // relaxed from 0.7 — brain-classified deliverable="answer" is already
125
+ // a strong signal that this is a read-only Q&A. 0.7 threshold would miss
126
+ // turns where confidence ∈ [0.5, 0.7) but deliverable is clearly an answer
127
+ // (e.g. single-line Q like "giải thích dòng này" → conf 0.55, right to skip tools).
128
+ // Sprint-plan execution: the orchestrator deliberately pipes a locked plan
129
+ // through processMessageFn. It MUST keep write tools and MUST be treated as
130
+ // a code deliverable regardless of how the classifier tags the long plan text.
131
+ const sprintPlanExecution = isSprintPlanExecution(ctx.raw);
132
+ if (sprintPlanExecution) {
133
+ ctx = {
134
+ ...ctx,
135
+ directAnswer: false,
136
+ deliverableKind: "code",
137
+ // Ensure we do not silently downgrade to quick; standard keeps the full
138
+ // toolset and advisory GSD directive, heavy would force a plan-review gate
139
+ // that conflicts with executing an already-reviewed sprint plan.
140
+ modelDepthTier: ctx.modelDepthTier ?? "standard",
141
+ };
142
+ }
143
+ else if (ctx.deliverableKind === "answer" &&
144
+ ctx.confidence >= DA_HIGH_CONF &&
145
+ ctx.complexitySize?.size !== "large") {
146
+ ctx = { ...ctx, directAnswer: true };
147
+ }
116
148
  // Phase 1 discovery: L1.5–L1.8 (interactive, no hard timeout)
117
149
  if (isDiscoveryEnabled() && ctx.intentKind !== "chitchat") {
118
150
  const { runDiscovery } = await import("./discovery.js");
@@ -33,7 +33,9 @@ const AnalyzeSchema = z.object({
33
33
  })),
34
34
  });
35
35
  const DocsSchema = z.object({
36
- content: z.string().describe("Markdown documentation"),
36
+ content: z
37
+ .string()
38
+ .describe("Markdown documentation written for a human reader — clear, concrete prose that explains what things do and why they matter, not boilerplate section-by-section filler. Prefer a short working example over an abstract description; only add headings the content actually earns."),
37
39
  examples: z
38
40
  .array(z.object({
39
41
  code: z.string(),
@@ -52,7 +54,7 @@ const GenerateSchema = z.object({
52
54
  const GeneralSchema = z.object({
53
55
  response: z
54
56
  .string()
55
- .describe("Complete, full-length answer. Use rich markdown formatting (headings, bullet points, bold text, code blocks) to structure the information clearly. Avoid dense walls of text or long unformatted paragraphs. Ensure the output is highly readable and scannable for a developer. For analysis or meta questions, include all findings and evidence citations (file:line). Truncation defeats the purpose."),
57
+ .describe("Your complete answer, written the way a sharp colleague would explain it — direct, specific, and in plain language. Lead with the answer itself, then the supporting detail. Use markdown where it genuinely helps (code blocks for code, a list when items are truly parallel, a heading only when the answer has real sections) never as decoration, and never force prose into bullet fragments or a fixed template. Vary sentence rhythm; skip filler openers like 'Certainly' or 'Below is a summary'. For analysis or meta questions, keep every finding and its evidence citation (file:line) do not truncate."),
56
58
  reasoning: z.string().optional().describe("Optional brief internal reasoning (not shown as primary answer)"),
57
59
  });
58
60
  const RESPONSE_SCHEMAS = {
@@ -151,7 +153,7 @@ export function buildResponseTools(taskType) {
151
153
  const toolName = `${RESPONSE_TOOL_PREFIX}${taskType}`;
152
154
  return {
153
155
  [toolName]: {
154
- description: `Return your ${taskType} response as structured JSON. Always use this tool to respond.`,
156
+ description: `Return your ${taskType} response as structured JSON. Always use this tool to respond. Write every prose field in a natural, conversational-but-professional voice — the way you would explain it to a colleague — not in stiff, templated report language.`,
155
157
  inputSchema: schema,
156
158
  execute: async (input) => input,
157
159
  },
@@ -115,6 +115,7 @@ export declare const PipelineContextSchema: z.ZodObject<{
115
115
  answer: "answer";
116
116
  report: "report";
117
117
  }>>>;
118
+ directAnswer: z.ZodOptional<z.ZodBoolean>;
118
119
  t1Rules: z.ZodOptional<z.ZodArray<z.ZodString>>;
119
120
  _brainData: z.ZodOptional<z.ZodNullable<z.ZodObject<{
120
121
  t0_principles: z.ZodArray<z.ZodObject<{
@@ -69,6 +69,8 @@ export const PipelineContextSchema = z.object({
69
69
  fallbackReason: z.string().nullable().optional(),
70
70
  // Phase 2b: model-decided output deliverable consumed by layer4/layer6.
71
71
  deliverableKind: z.enum(["answer", "code", "report"]).nullable().optional(),
72
+ // Direct-answer gate: true when deliverable=answer + high confidence + low complexity.
73
+ directAnswer: z.boolean().optional(),
72
74
  // T1 behavioral rules from EE proven-tier points, injected as mandatory suffix by Layer 6.
73
75
  t1Rules: z.array(z.string()).optional(),
74
76
  _brainData: z
@@ -44,6 +44,8 @@ export interface PipelineContext {
44
44
  sessionId?: string | null;
45
45
  /** GSD-native triage tier (set by layer4 — sourced from modelDepthTier when present). */
46
46
  complexityTier?: ComplexityTier | null;
47
+ /** True when layer4 classified this turn as a heavy GSD task the mutation gate must block until plan-review passes. */
48
+ gsdGateBlocking?: boolean | null;
47
49
  /**
48
50
  * Model-decided work depth (quick | standard | heavy), set by layer1's
49
51
  * model-first classifier (the 5th classify word). This is the agent-first
@@ -53,6 +55,14 @@ export interface PipelineContext {
53
55
  * the word OR the legacy cascade ran → layer4 falls back accordingly.
54
56
  */
55
57
  modelDepthTier?: ComplexityTier | null;
58
+ /**
59
+ * Leader-tier complexity assessor's auto-council recommendation (Task 4
60
+ * `assessComplexity` / `src/gsd/complexity-assessor.ts`), set by the native
61
+ * depth-sync block in message-processor.ts BEFORE `syncWorkflowContext`.
62
+ * undefined when the assessor didn't run (prefilter-skip / disabled) or
63
+ * failed; consumed by the auto-council gate (Task 8).
64
+ */
65
+ gsdAutoCouncil?: boolean;
56
66
  /**
57
67
  * Model-decided scope (agent-first replacement for the `mentionsEcosystemScope`
58
68
  * regex): true when the turn is about the Muonroi PLATFORM/ecosystem (BB/.NET,
@@ -97,6 +107,14 @@ export interface PipelineContext {
97
107
  * cascade ran → those consumers fall back to their regex predicates.
98
108
  */
99
109
  deliverableKind?: "answer" | "code" | "report" | null;
110
+ /**
111
+ * Direct-answer mode: true when deliverableKind === "answer" with high
112
+ * confidence AND low/medium complexity. Signals the orchestrator to skip
113
+ * MCP servers and strip write tools (bash, edit_file, write_file, etc.)
114
+ * because the question is purely informational — no code changes needed.
115
+ * Saves ~20K MCP schemas + ~1.5K write-tool schemas per turn.
116
+ */
117
+ directAnswer?: boolean;
100
118
  /**
101
119
  * Diagnostic: when the pipeline returns the fallback context, this records
102
120
  * the reason (timeout / schema-reject / exception). Null on the happy path.
@@ -19,6 +19,8 @@
19
19
  */
20
20
  import type { GsdPhase } from "../gsd/types.js";
21
21
  import type { ComplexityTier } from "./complexity.js";
22
+ /** When true and tier is standard/heavy, CHECK-PLAN points to gsd_plan_review tool. */
23
+ export declare function buildNativeCheckPlanHint(): string;
22
24
  export interface DirectiveInput {
23
25
  /**
24
26
  * Model-decided work depth (agent-first — see layer1 `llm-classify`). Drives
@@ -62,6 +64,8 @@ export interface DirectiveInput {
62
64
  * the agent answered in English).
63
65
  */
64
66
  replyLanguage?: string;
67
+ /** When MUONROI_GSD_NATIVE=1, heavy/standard rubrics reference native tools. */
68
+ nativeGsd?: boolean;
65
69
  }
66
70
  export interface DirectiveOutput {
67
71
  text: string;