muonroi-cli 1.8.4 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (562) hide show
  1. package/LICENSE +17 -5
  2. package/dist/packages/agent-harness-core/src/driver.d.ts +27 -1
  3. package/dist/packages/agent-harness-core/src/driver.js +46 -0
  4. package/dist/packages/agent-harness-core/src/event-filter.js +11 -0
  5. package/dist/packages/agent-harness-core/src/event-redact.js +7 -0
  6. package/dist/packages/agent-harness-core/src/event-tee.d.ts +64 -0
  7. package/dist/packages/agent-harness-core/src/event-tee.js +104 -0
  8. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +25 -0
  9. package/dist/packages/agent-harness-core/src/mcp-server.js +169 -21
  10. package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
  11. package/dist/packages/agent-harness-core/src/protocol.d.ts +90 -4
  12. package/dist/packages/agent-harness-core/src/protocol.js +15 -0
  13. package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
  14. package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
  15. package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
  16. package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
  17. package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
  18. package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
  19. package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
  20. package/dist/packages/agent-harness-opentui/src/install.js +10 -0
  21. package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
  22. package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
  23. package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
  24. package/dist/src/agent-harness/mock-model.d.ts +38 -0
  25. package/dist/src/agent-harness/mock-model.js +69 -3
  26. package/dist/src/agent-harness/test-spawn.js +31 -0
  27. package/dist/src/chat/chat-keychain.d.ts +7 -12
  28. package/dist/src/chat/chat-keychain.js +19 -86
  29. package/dist/src/cli/config/screen-providers.js +1 -1
  30. package/dist/src/cli/cost-forensics.d.ts +10 -0
  31. package/dist/src/cli/cost-forensics.js +18 -3
  32. package/dist/src/cli/keys-bundle.d.ts +1 -1
  33. package/dist/src/cli/keys-bundle.js +1 -1
  34. package/dist/src/cli/keys.d.ts +10 -47
  35. package/dist/src/cli/keys.js +31 -399
  36. package/dist/src/council/clarifier.d.ts +31 -3
  37. package/dist/src/council/clarifier.js +220 -32
  38. package/dist/src/council/context.js +49 -15
  39. package/dist/src/council/debate-checkpoint.d.ts +129 -0
  40. package/dist/src/council/debate-checkpoint.js +176 -0
  41. package/dist/src/council/debate-planner.js +54 -5
  42. package/dist/src/council/debate-summary.d.ts +25 -0
  43. package/dist/src/council/debate-summary.js +85 -0
  44. package/dist/src/council/debate.d.ts +169 -2
  45. package/dist/src/council/debate.js +1265 -135
  46. package/dist/src/council/index.d.ts +108 -1
  47. package/dist/src/council/index.js +670 -197
  48. package/dist/src/council/leader.d.ts +26 -0
  49. package/dist/src/council/leader.js +150 -9
  50. package/dist/src/council/llm.d.ts +94 -0
  51. package/dist/src/council/llm.js +348 -55
  52. package/dist/src/council/panel-select.d.ts +30 -0
  53. package/dist/src/council/panel-select.js +82 -0
  54. package/dist/src/council/planner.js +40 -0
  55. package/dist/src/council/preflight.d.ts +17 -0
  56. package/dist/src/council/preflight.js +50 -2
  57. package/dist/src/council/prompts.d.ts +39 -4
  58. package/dist/src/council/prompts.js +256 -69
  59. package/dist/src/council/stance-recall.d.ts +42 -0
  60. package/dist/src/council/stance-recall.js +57 -0
  61. package/dist/src/council/strip-think.d.ts +17 -0
  62. package/dist/src/council/strip-think.js +33 -0
  63. package/dist/src/council/types.d.ts +138 -0
  64. package/dist/src/ee/artifact-cache.d.ts +16 -0
  65. package/dist/src/ee/artifact-cache.js +32 -0
  66. package/dist/src/ee/auth.d.ts +20 -0
  67. package/dist/src/ee/auth.js +54 -2
  68. package/dist/src/ee/bridge.d.ts +10 -0
  69. package/dist/src/ee/bridge.js +58 -0
  70. package/dist/src/ee/client.js +109 -21
  71. package/dist/src/ee/ee-onboarding.js +6 -26
  72. package/dist/src/ee/export-transcripts.d.ts +1 -0
  73. package/dist/src/ee/export-transcripts.js +8 -10
  74. package/dist/src/ee/extract-session.js +29 -0
  75. package/dist/src/ee/extract-style.d.ts +58 -0
  76. package/dist/src/ee/extract-style.js +270 -0
  77. package/dist/src/ee/recall-ledger.d.ts +9 -0
  78. package/dist/src/ee/recall-ledger.js +3 -0
  79. package/dist/src/ee/scope.d.ts +1 -0
  80. package/dist/src/ee/scope.js +26 -1
  81. package/dist/src/ee/search.d.ts +7 -0
  82. package/dist/src/ee/search.js +24 -0
  83. package/dist/src/ee/transcript-emit.js +2 -0
  84. package/dist/src/ee/types.d.ts +22 -0
  85. package/dist/src/ee/who-am-i-brain.d.ts +35 -0
  86. package/dist/src/ee/who-am-i-brain.js +220 -0
  87. package/dist/src/ee/who-am-i.d.ts +10 -3
  88. package/dist/src/ee/who-am-i.js +12 -0
  89. package/dist/src/ee/workflow-event.d.ts +48 -0
  90. package/dist/src/ee/workflow-event.js +81 -0
  91. package/dist/src/flow/compaction/compress.d.ts +3 -3
  92. package/dist/src/flow/compaction/compress.js +58 -8
  93. package/dist/src/flow/compaction/extract.d.ts +4 -7
  94. package/dist/src/flow/compaction/extract.js +50 -10
  95. package/dist/src/flow/compaction/index.d.ts +14 -1
  96. package/dist/src/flow/compaction/index.js +96 -3
  97. package/dist/src/flow/compaction/input-guard.d.ts +24 -0
  98. package/dist/src/flow/compaction/input-guard.js +43 -0
  99. package/dist/src/flow/compaction/progress.d.ts +35 -0
  100. package/dist/src/flow/compaction/progress.js +35 -0
  101. package/dist/src/flow/fold-planning.d.ts +36 -0
  102. package/dist/src/flow/fold-planning.js +83 -0
  103. package/dist/src/flow/hierarchy.d.ts +146 -0
  104. package/dist/src/flow/hierarchy.js +427 -0
  105. package/dist/src/flow/index.d.ts +1 -0
  106. package/dist/src/flow/index.js +2 -0
  107. package/dist/src/flow/run-artifacts.d.ts +102 -0
  108. package/dist/src/flow/run-artifacts.js +208 -0
  109. package/dist/src/generated/version.d.ts +1 -1
  110. package/dist/src/generated/version.js +1 -1
  111. package/dist/src/gsd/assessment-schema.d.ts +44 -0
  112. package/dist/src/gsd/assessment-schema.js +134 -0
  113. package/dist/src/gsd/capability-registry.d.ts +45 -0
  114. package/dist/src/gsd/capability-registry.js +337 -0
  115. package/dist/src/gsd/complexity-assessor.d.ts +39 -0
  116. package/dist/src/gsd/complexity-assessor.js +152 -0
  117. package/dist/src/gsd/config-bridge.d.ts +7 -0
  118. package/dist/src/gsd/config-bridge.js +114 -0
  119. package/dist/src/gsd/config-loader.d.ts +27 -0
  120. package/dist/src/gsd/config-loader.js +50 -0
  121. package/dist/src/gsd/council-context.d.ts +44 -0
  122. package/dist/src/gsd/council-context.js +114 -0
  123. package/dist/src/gsd/ee-closure.d.ts +28 -0
  124. package/dist/src/gsd/ee-closure.js +49 -0
  125. package/dist/src/gsd/flags.d.ts +66 -0
  126. package/dist/src/gsd/flags.js +102 -0
  127. package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
  128. package/dist/src/gsd/gsd-dispatch.js +131 -0
  129. package/dist/src/gsd/gsd-runtime.d.ts +22 -0
  130. package/dist/src/gsd/gsd-runtime.js +37 -0
  131. package/dist/src/gsd/host-adapter.d.ts +11 -0
  132. package/dist/src/gsd/host-adapter.js +29 -0
  133. package/dist/src/gsd/index.d.ts +24 -1
  134. package/dist/src/gsd/index.js +27 -0
  135. package/dist/src/gsd/loop-host-contract.d.ts +21 -0
  136. package/dist/src/gsd/loop-host-contract.js +39 -0
  137. package/dist/src/gsd/loop-host.d.ts +69 -0
  138. package/dist/src/gsd/loop-host.js +245 -0
  139. package/dist/src/gsd/loop-resolver.d.ts +36 -0
  140. package/dist/src/gsd/loop-resolver.js +79 -0
  141. package/dist/src/gsd/model-tier.d.ts +13 -0
  142. package/dist/src/gsd/model-tier.js +45 -0
  143. package/dist/src/gsd/mutation-gate.d.ts +16 -0
  144. package/dist/src/gsd/mutation-gate.js +41 -0
  145. package/dist/src/gsd/native-roadmap.d.ts +89 -0
  146. package/dist/src/gsd/native-roadmap.js +343 -0
  147. package/dist/src/gsd/native-state.d.ts +47 -0
  148. package/dist/src/gsd/native-state.js +220 -0
  149. package/dist/src/gsd/paths.d.ts +23 -0
  150. package/dist/src/gsd/paths.js +66 -0
  151. package/dist/src/gsd/phase-dag.d.ts +12 -0
  152. package/dist/src/gsd/phase-dag.js +94 -0
  153. package/dist/src/gsd/phase-sync.d.ts +42 -0
  154. package/dist/src/gsd/phase-sync.js +321 -0
  155. package/dist/src/gsd/pil-gate-context.d.ts +13 -0
  156. package/dist/src/gsd/pil-gate-context.js +64 -0
  157. package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
  158. package/dist/src/gsd/pil-gate-critic.js +74 -0
  159. package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
  160. package/dist/src/gsd/plan-council-prompts.js +79 -0
  161. package/dist/src/gsd/plan-council.d.ts +44 -0
  162. package/dist/src/gsd/plan-council.js +283 -0
  163. package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
  164. package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
  165. package/dist/src/gsd/product-workspace.d.ts +13 -0
  166. package/dist/src/gsd/product-workspace.js +124 -0
  167. package/dist/src/gsd/ship-bridge.d.ts +25 -0
  168. package/dist/src/gsd/ship-bridge.js +65 -0
  169. package/dist/src/gsd/state-document.d.ts +40 -0
  170. package/dist/src/gsd/state-document.js +163 -0
  171. package/dist/src/gsd/verdict-schema.d.ts +39 -0
  172. package/dist/src/gsd/verdict-schema.js +144 -0
  173. package/dist/src/gsd/verify-context.d.ts +22 -0
  174. package/dist/src/gsd/verify-context.js +27 -0
  175. package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
  176. package/dist/src/gsd/verify-council-prompts.js +85 -0
  177. package/dist/src/gsd/verify-council.d.ts +25 -0
  178. package/dist/src/gsd/verify-council.js +119 -0
  179. package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
  180. package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
  181. package/dist/src/gsd/workflow-engine.d.ts +60 -0
  182. package/dist/src/gsd/workflow-engine.js +207 -0
  183. package/dist/src/gsd/workflow-tools.d.ts +13 -0
  184. package/dist/src/gsd/workflow-tools.js +277 -0
  185. package/dist/src/headless/council-answers.js +4 -0
  186. package/dist/src/hooks/index.js +1 -1
  187. package/dist/src/index.js +172 -270
  188. package/dist/src/lsp/builtins.js +3 -1
  189. package/dist/src/lsp/manager.d.ts +5 -1
  190. package/dist/src/lsp/manager.js +249 -3
  191. package/dist/src/lsp/npm-cache.d.ts +11 -1
  192. package/dist/src/lsp/npm-cache.js +17 -1
  193. package/dist/src/lsp/runtime.d.ts +6 -1
  194. package/dist/src/lsp/runtime.js +17 -1
  195. package/dist/src/lsp/types.d.ts +83 -1
  196. package/dist/src/lsp/types.js +10 -0
  197. package/dist/src/maintain/pr-builder.js +23 -13
  198. package/dist/src/mcp/auto-setup.js +57 -32
  199. package/dist/src/mcp/client-pool.js +44 -16
  200. package/dist/src/mcp/lsp-tools.d.ts +5 -1
  201. package/dist/src/mcp/lsp-tools.js +93 -2
  202. package/dist/src/mcp/mcp-keychain.d.ts +3 -5
  203. package/dist/src/mcp/mcp-keychain.js +9 -49
  204. package/dist/src/mcp/research-onboarding.js +8 -7
  205. package/dist/src/mcp/runtime.js +34 -2
  206. package/dist/src/mcp/setup-guide-text.d.ts +1 -1
  207. package/dist/src/mcp/setup-guide-text.js +22 -2
  208. package/dist/src/mcp/tools-server.d.ts +10 -0
  209. package/dist/src/mcp/tools-server.js +10 -2
  210. package/dist/src/models/catalog-client.d.ts +87 -0
  211. package/dist/src/models/catalog-client.js +105 -38
  212. package/dist/src/models/catalog.json +528 -265
  213. package/dist/src/models/registry.d.ts +22 -7
  214. package/dist/src/models/registry.js +73 -10
  215. package/dist/src/ops/doctor.js +1 -1
  216. package/dist/src/orchestrator/ask-user.d.ts +61 -0
  217. package/dist/src/orchestrator/ask-user.js +65 -0
  218. package/dist/src/orchestrator/auto-commit.js +1 -1
  219. package/dist/src/orchestrator/batch-turn-runner.js +2 -2
  220. package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
  221. package/dist/src/orchestrator/cache-prefix.js +83 -0
  222. package/dist/src/orchestrator/compact-request.d.ts +32 -0
  223. package/dist/src/orchestrator/compact-request.js +41 -0
  224. package/dist/src/orchestrator/compaction.d.ts +12 -3
  225. package/dist/src/orchestrator/compaction.js +35 -15
  226. package/dist/src/orchestrator/council-manager.d.ts +12 -3
  227. package/dist/src/orchestrator/council-manager.js +74 -32
  228. package/dist/src/orchestrator/council-request.d.ts +49 -0
  229. package/dist/src/orchestrator/council-request.js +62 -0
  230. package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
  231. package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
  232. package/dist/src/orchestrator/error-utils.d.ts +29 -0
  233. package/dist/src/orchestrator/error-utils.js +132 -24
  234. package/dist/src/orchestrator/grounding-check.js +39 -1
  235. package/dist/src/orchestrator/interactive-pause.d.ts +26 -0
  236. package/dist/src/orchestrator/interactive-pause.js +36 -0
  237. package/dist/src/orchestrator/message-processor.d.ts +4 -0
  238. package/dist/src/orchestrator/message-processor.js +268 -41
  239. package/dist/src/orchestrator/orchestrator.d.ts +64 -3
  240. package/dist/src/orchestrator/orchestrator.js +823 -120
  241. package/dist/src/orchestrator/preprocessor.js +3 -3
  242. package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
  243. package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
  244. package/dist/src/orchestrator/prompts.js +17 -17
  245. package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
  246. package/dist/src/orchestrator/reactive-delegation.js +59 -0
  247. package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
  248. package/dist/src/orchestrator/retry-classifier.js +46 -2
  249. package/dist/src/orchestrator/safety-askcard.d.ts +1 -1
  250. package/dist/src/orchestrator/safety-askcard.js +5 -2
  251. package/dist/src/orchestrator/safety-intercept.d.ts +50 -0
  252. package/dist/src/orchestrator/safety-intercept.js +62 -0
  253. package/dist/src/orchestrator/scope-reminder.js +1 -1
  254. package/dist/src/orchestrator/session-experience.d.ts +2 -1
  255. package/dist/src/orchestrator/session-experience.js +2 -1
  256. package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
  257. package/dist/src/orchestrator/should-run-gate.js +18 -0
  258. package/dist/src/orchestrator/stall-watchdog.d.ts +31 -3
  259. package/dist/src/orchestrator/stall-watchdog.js +65 -10
  260. package/dist/src/orchestrator/stream-runner.d.ts +13 -3
  261. package/dist/src/orchestrator/stream-runner.js +115 -49
  262. package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
  263. package/dist/src/orchestrator/sub-agent-cap.js +16 -1
  264. package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
  265. package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
  266. package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
  267. package/dist/src/orchestrator/subagent-compactor.js +126 -15
  268. package/dist/src/orchestrator/tool-engine.d.ts +41 -0
  269. package/dist/src/orchestrator/tool-engine.js +846 -66
  270. package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
  271. package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
  272. package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
  273. package/dist/src/orchestrator/turn-watchdog.d.ts +44 -0
  274. package/dist/src/orchestrator/turn-watchdog.js +84 -0
  275. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  276. package/dist/src/pil/agent-operating-contract.js +6 -4
  277. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  278. package/dist/src/pil/cheap-model-playbook.js +5 -1
  279. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  280. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  281. package/dist/src/pil/discovery-types.d.ts +1 -0
  282. package/dist/src/pil/discovery.d.ts +1 -1
  283. package/dist/src/pil/discovery.js +18 -13
  284. package/dist/src/pil/layer1-intent.d.ts +18 -6
  285. package/dist/src/pil/layer1-intent.js +66 -757
  286. package/dist/src/pil/layer15-context-scan.js +15 -1
  287. package/dist/src/pil/layer1_5-complexity-size.d.ts +7 -0
  288. package/dist/src/pil/layer1_5-complexity-size.js +31 -5
  289. package/dist/src/pil/layer3-ee-injection.js +23 -8
  290. package/dist/src/pil/layer4-gsd.js +69 -16
  291. package/dist/src/pil/layer5-context.js +7 -3
  292. package/dist/src/pil/layer6-output.d.ts +23 -0
  293. package/dist/src/pil/layer6-output.js +5 -1
  294. package/dist/src/pil/llm-classify.d.ts +111 -5
  295. package/dist/src/pil/llm-classify.js +421 -189
  296. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  297. package/dist/src/pil/native-capabilities-workbook.js +8 -0
  298. package/dist/src/pil/pipeline.js +36 -2
  299. package/dist/src/pil/repo-grounding-probe.d.ts +15 -0
  300. package/dist/src/pil/repo-grounding-probe.js +136 -0
  301. package/dist/src/pil/repo-structure-hints.d.ts +7 -0
  302. package/dist/src/pil/repo-structure-hints.js +45 -0
  303. package/dist/src/pil/response-tools.js +5 -3
  304. package/dist/src/pil/schema.d.ts +1 -0
  305. package/dist/src/pil/schema.js +2 -0
  306. package/dist/src/pil/types.d.ts +18 -0
  307. package/dist/src/playbook/directives.d.ts +4 -0
  308. package/dist/src/playbook/directives.js +17 -5
  309. package/dist/src/product-loop/artifact-io.js +4 -0
  310. package/dist/src/product-loop/backlog-builder.d.ts +14 -1
  311. package/dist/src/product-loop/backlog-builder.js +30 -6
  312. package/dist/src/product-loop/criteria-seed.d.ts +51 -0
  313. package/dist/src/product-loop/criteria-seed.js +200 -0
  314. package/dist/src/product-loop/discovery-context-format.js +3 -1
  315. package/dist/src/product-loop/discovery-ecosystem.js +4 -1
  316. package/dist/src/product-loop/discovery-interview.d.ts +9 -0
  317. package/dist/src/product-loop/discovery-interview.js +60 -12
  318. package/dist/src/product-loop/discovery-recommender.js +2 -1
  319. package/dist/src/product-loop/discovery-schema.js +19 -2
  320. package/dist/src/product-loop/discovery-triage.d.ts +23 -0
  321. package/dist/src/product-loop/discovery-triage.js +109 -0
  322. package/dist/src/product-loop/gather.js +150 -2
  323. package/dist/src/product-loop/ideal-trace.d.ts +7 -0
  324. package/dist/src/product-loop/ideal-trace.js +64 -0
  325. package/dist/src/product-loop/index.d.ts +13 -1
  326. package/dist/src/product-loop/index.js +340 -52
  327. package/dist/src/product-loop/loop-driver.d.ts +7 -0
  328. package/dist/src/product-loop/loop-driver.js +330 -106
  329. package/dist/src/product-loop/phase-plan.d.ts +21 -0
  330. package/dist/src/product-loop/phase-plan.js +81 -6
  331. package/dist/src/product-loop/phase-rituals.d.ts +3 -0
  332. package/dist/src/product-loop/phase-rituals.js +8 -3
  333. package/dist/src/product-loop/phase-runner.js +39 -12
  334. package/dist/src/product-loop/plan-adherence-review.d.ts +26 -0
  335. package/dist/src/product-loop/plan-adherence-review.js +144 -0
  336. package/dist/src/product-loop/sprint-runner.d.ts +173 -0
  337. package/dist/src/product-loop/sprint-runner.js +863 -19
  338. package/dist/src/product-loop/types.d.ts +61 -5
  339. package/dist/src/providers/adapter.d.ts +1 -1
  340. package/dist/src/providers/adapter.js +3 -4
  341. package/dist/src/providers/anthropic.d.ts +9 -8
  342. package/dist/src/providers/anthropic.js +13 -47
  343. package/dist/src/providers/auth/browser-flow.d.ts +1 -1
  344. package/dist/src/providers/auth/browser-flow.js +1 -1
  345. package/dist/src/providers/auth/grok-oauth.d.ts +1 -0
  346. package/dist/src/providers/auth/grok-oauth.js +30 -5
  347. package/dist/src/providers/auth/openai-oauth.d.ts +1 -0
  348. package/dist/src/providers/auth/openai-oauth.js +15 -1
  349. package/dist/src/providers/auth/registry.js +0 -34
  350. package/dist/src/providers/auth/token-store.d.ts +9 -9
  351. package/dist/src/providers/auth/token-store.js +8 -67
  352. package/dist/src/providers/auth/types.d.ts +9 -1
  353. package/dist/src/providers/auth/types.js +1 -1
  354. package/dist/src/providers/capabilities.d.ts +24 -5
  355. package/dist/src/providers/capabilities.js +42 -24
  356. package/dist/src/providers/endpoints.d.ts +2 -2
  357. package/dist/src/providers/endpoints.js +11 -10
  358. package/dist/src/providers/env-store.d.ts +17 -0
  359. package/dist/src/providers/env-store.js +228 -0
  360. package/dist/src/providers/keychain.d.ts +22 -18
  361. package/dist/src/providers/keychain.js +127 -140
  362. package/dist/src/providers/mcp-vision-bridge.js +56 -146
  363. package/dist/src/providers/openai-compatible.js +8 -1
  364. package/dist/src/providers/pricing.d.ts +2 -2
  365. package/dist/src/providers/pricing.js +3 -13
  366. package/dist/src/providers/runtime.d.ts +43 -3
  367. package/dist/src/providers/runtime.js +88 -14
  368. package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
  369. package/dist/src/providers/strategies/base.strategy.js +24 -1
  370. package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
  371. package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
  372. package/dist/src/providers/strategies/registry.js +4 -4
  373. package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
  374. package/dist/src/providers/strategies/thinking-mode.js +288 -1
  375. package/dist/src/providers/strategies/xai.strategy.js +27 -0
  376. package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
  377. package/dist/src/providers/strategies/zai.strategy.js +44 -0
  378. package/dist/src/providers/types.d.ts +5 -6
  379. package/dist/src/providers/types.js +2 -2
  380. package/dist/src/providers/vision-backend.d.ts +47 -0
  381. package/dist/src/providers/vision-backend.js +258 -0
  382. package/dist/src/providers/vision-proxy.d.ts +22 -9
  383. package/dist/src/providers/vision-proxy.js +63 -132
  384. package/dist/src/providers/warm.d.ts +65 -0
  385. package/dist/src/providers/warm.js +145 -0
  386. package/dist/src/providers/wire-debug.js +95 -0
  387. package/dist/src/router/decide.d.ts +13 -0
  388. package/dist/src/router/decide.js +138 -36
  389. package/dist/src/router/peak-hour.d.ts +38 -0
  390. package/dist/src/router/peak-hour.js +107 -0
  391. package/dist/src/router/step-router.js +3 -2
  392. package/dist/src/router/warm.js +4 -5
  393. package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
  394. package/dist/src/scaffold/continuation-prompt.js +26 -0
  395. package/dist/src/scaffold/point-to-existing.d.ts +21 -0
  396. package/dist/src/scaffold/point-to-existing.js +25 -0
  397. package/dist/src/self-qa/agentic-loop.js +6 -5
  398. package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
  399. package/dist/src/{ui/state → state}/active-run.js +21 -0
  400. package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
  401. package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
  402. package/dist/src/state/turn-trace.d.ts +43 -0
  403. package/dist/src/state/turn-trace.js +32 -0
  404. package/dist/src/storage/db.js +2 -1
  405. package/dist/src/storage/index.d.ts +1 -1
  406. package/dist/src/storage/index.js +1 -1
  407. package/dist/src/storage/interaction-log.d.ts +1 -1
  408. package/dist/src/storage/migrations.js +71 -1
  409. package/dist/src/storage/sessions.d.ts +28 -10
  410. package/dist/src/storage/sessions.js +78 -21
  411. package/dist/src/storage/transcript-view.js +1 -1
  412. package/dist/src/storage/transcript.d.ts +51 -0
  413. package/dist/src/storage/transcript.js +340 -15
  414. package/dist/src/tools/file.d.ts +15 -0
  415. package/dist/src/tools/file.js +32 -0
  416. package/dist/src/tools/git-safety.d.ts +19 -0
  417. package/dist/src/tools/git-safety.js +168 -0
  418. package/dist/src/tools/native-tools.d.ts +1 -1
  419. package/dist/src/tools/native-tools.js +81 -1
  420. package/dist/src/tools/registry.d.ts +20 -0
  421. package/dist/src/tools/registry.js +576 -23
  422. package/dist/src/tools/research.d.ts +29 -0
  423. package/dist/src/tools/research.js +233 -0
  424. package/dist/src/types/index.d.ts +147 -4
  425. package/dist/src/ui/app.js +0 -0
  426. package/dist/src/ui/cards/product-status-card.js +1 -1
  427. package/dist/src/ui/components/agent-rail-activities.d.ts +26 -0
  428. package/dist/src/ui/components/agent-rail-activities.js +47 -0
  429. package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
  430. package/dist/src/ui/components/bubble-body-guard.js +50 -0
  431. package/dist/src/ui/components/compact-progress-card.d.ts +24 -0
  432. package/dist/src/ui/components/compact-progress-card.js +42 -0
  433. package/dist/src/ui/components/context-rail.d.ts +26 -0
  434. package/dist/src/ui/components/context-rail.js +33 -0
  435. package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
  436. package/dist/src/ui/components/council-conclusion-card.js +420 -0
  437. package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
  438. package/dist/src/ui/components/council-debate-pill.js +34 -0
  439. package/dist/src/ui/components/council-info-card.js +2 -2
  440. package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
  441. package/dist/src/ui/components/council-leader-bubble.js +21 -11
  442. package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
  443. package/dist/src/ui/components/council-message-bubble.js +16 -15
  444. package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
  445. package/dist/src/ui/components/council-phase-timeline.js +66 -17
  446. package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
  447. package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
  448. package/dist/src/ui/components/council-question-card.js +13 -12
  449. package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
  450. package/dist/src/ui/components/council-rail-rounds.js +57 -0
  451. package/dist/src/ui/components/council-round-group.d.ts +38 -0
  452. package/dist/src/ui/components/council-round-group.js +88 -0
  453. package/dist/src/ui/components/council-status-list.d.ts +3 -1
  454. package/dist/src/ui/components/council-status-list.js +36 -24
  455. package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
  456. package/dist/src/ui/components/council-synthesis-banner.js +20 -5
  457. package/dist/src/ui/components/halt-recovery-card.js +9 -5
  458. package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
  459. package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
  460. package/dist/src/ui/components/message-view.d.ts +15 -0
  461. package/dist/src/ui/components/message-view.js +50 -1
  462. package/dist/src/ui/components/prompt-box.js +18 -16
  463. package/dist/src/ui/components/session-tree-card.d.ts +14 -0
  464. package/dist/src/ui/components/session-tree-card.js +46 -0
  465. package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
  466. package/dist/src/ui/components/slash-inline-menu.js +26 -5
  467. package/dist/src/ui/components/task-list-panel.d.ts +14 -1
  468. package/dist/src/ui/components/task-list-panel.js +22 -2
  469. package/dist/src/ui/components/tool-group.d.ts +15 -3
  470. package/dist/src/ui/components/tool-group.js +69 -11
  471. package/dist/src/ui/containers/modals-layer.d.ts +4 -2
  472. package/dist/src/ui/containers/modals-layer.js +2 -2
  473. package/dist/src/ui/council-harness-event.d.ts +57 -0
  474. package/dist/src/ui/council-harness-event.js +46 -0
  475. package/dist/src/ui/heartbeat-debug.d.ts +29 -0
  476. package/dist/src/ui/heartbeat-debug.js +45 -0
  477. package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
  478. package/dist/src/ui/mcp-modal.js +2 -4
  479. package/dist/src/ui/modals/api-key-modal.js +1 -1
  480. package/dist/src/ui/modals/connect-modal.js +4 -3
  481. package/dist/src/ui/modals/model-picker-modal.d.ts +8 -18
  482. package/dist/src/ui/modals/model-picker-modal.js +8 -10
  483. package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
  484. package/dist/src/ui/modals/session-picker-modal.js +3 -5
  485. package/dist/src/ui/picker-providers.d.ts +1 -1
  486. package/dist/src/ui/picker-providers.js +1 -1
  487. package/dist/src/ui/primitives/index.d.ts +1 -0
  488. package/dist/src/ui/primitives/index.js +2 -0
  489. package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
  490. package/dist/src/ui/primitives/semantic-primitives.js +81 -0
  491. package/dist/src/ui/slash/compact.js +5 -7
  492. package/dist/src/ui/slash/cost.js +1 -1
  493. package/dist/src/ui/slash/council.js +19 -1
  494. package/dist/src/ui/slash/debug.d.ts +3 -31
  495. package/dist/src/ui/slash/debug.js +9 -20
  496. package/dist/src/ui/slash/ee.js +81 -0
  497. package/dist/src/ui/slash/ideal.d.ts +6 -2
  498. package/dist/src/ui/slash/ideal.js +97 -7
  499. package/dist/src/ui/slash/menu-items.d.ts +7 -0
  500. package/dist/src/ui/slash/menu-items.js +23 -20
  501. package/dist/src/ui/slash/registry.d.ts +2 -0
  502. package/dist/src/ui/slash/registry.js +4 -0
  503. package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
  504. package/dist/src/ui/status-bar/cache-hit.js +9 -0
  505. package/dist/src/ui/status-bar/index.d.ts +1 -1
  506. package/dist/src/ui/status-bar/index.js +7 -3
  507. package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
  508. package/dist/src/ui/status-bar/usd-meter.js +6 -4
  509. package/dist/src/ui/theme.d.ts +1 -0
  510. package/dist/src/ui/theme.js +2 -0
  511. package/dist/src/ui/types.d.ts +7 -0
  512. package/dist/src/ui/use-app-logic.js +0 -0
  513. package/dist/src/ui/utils/agent-activities.d.ts +39 -0
  514. package/dist/src/ui/utils/agent-activities.js +96 -0
  515. package/dist/src/ui/utils/format.d.ts +14 -0
  516. package/dist/src/ui/utils/format.js +23 -3
  517. package/dist/src/ui/utils/group-tool-entries.d.ts +26 -0
  518. package/dist/src/ui/utils/group-tool-entries.js +111 -0
  519. package/dist/src/ui/utils/tool-summary.d.ts +21 -0
  520. package/dist/src/ui/utils/tool-summary.js +91 -0
  521. package/dist/src/usage/downgrade.js +2 -2
  522. package/dist/src/usage/product-ledger.js +2 -2
  523. package/dist/src/utils/event-loop-monitor.d.ts +85 -0
  524. package/dist/src/utils/event-loop-monitor.js +107 -0
  525. package/dist/src/utils/install-manager.js +2 -1
  526. package/dist/src/utils/llm-deadline.d.ts +14 -0
  527. package/dist/src/utils/llm-deadline.js +19 -0
  528. package/dist/src/utils/logger.js +2 -2
  529. package/dist/src/utils/loop-profiler.d.ts +102 -0
  530. package/dist/src/utils/loop-profiler.js +202 -0
  531. package/dist/src/utils/permission-mode.js +5 -3
  532. package/dist/src/utils/redactor.js +1 -1
  533. package/dist/src/utils/settings.d.ts +180 -5
  534. package/dist/src/utils/settings.js +271 -31
  535. package/dist/src/utils/side-question.d.ts +1 -2
  536. package/dist/src/utils/side-question.js +2 -2
  537. package/dist/src/utils/visible-retry.d.ts +11 -0
  538. package/dist/src/utils/visible-retry.js +10 -1
  539. package/dist/src/verify/entrypoint.d.ts +1 -1
  540. package/dist/src/verify/entrypoint.js +52 -17
  541. package/dist/src/verify/orchestrator.d.ts +1 -1
  542. package/dist/src/verify/orchestrator.js +20 -3
  543. package/dist/src/verify/recipes.d.ts +13 -0
  544. package/dist/src/verify/recipes.js +15 -0
  545. package/package.json +134 -132
  546. package/dist/src/cli/bw-vault.d.ts +0 -55
  547. package/dist/src/cli/bw-vault.js +0 -133
  548. package/dist/src/mcp/ee-tools.d.ts +0 -46
  549. package/dist/src/mcp/ee-tools.js +0 -193
  550. package/dist/src/providers/auth/gcloud.d.ts +0 -28
  551. package/dist/src/providers/auth/gcloud.js +0 -102
  552. package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
  553. package/dist/src/providers/auth/gemini-oauth.js +0 -472
  554. package/dist/src/providers/gemini.d.ts +0 -11
  555. package/dist/src/providers/gemini.js +0 -45
  556. package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
  557. package/dist/src/providers/siliconflow-sse-repair.js +0 -177
  558. package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
  559. package/dist/src/providers/strategies/google.strategy.js +0 -174
  560. package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
  561. package/dist/src/ui/containers/chat-feed.d.ts +0 -40
  562. package/dist/src/ui/containers/chat-feed.js +0 -66
@@ -1,3 +1,4 @@
1
+ import { execSync } from "node:child_process";
1
2
  import { existsSync, readdirSync, readFileSync } from "node:fs";
2
3
  import { join } from "node:path";
3
4
  export function detectLanguage(cwd, exists = (p) => existsSync(p)) {
@@ -141,14 +142,27 @@ export async function scanProjectContext(raw, cwd) {
141
142
  catch {
142
143
  /* EE unavailable */
143
144
  }
145
+ let recentModifiedFiles = [];
146
+ try {
147
+ const gitOut = execSync("git status --porcelain", { cwd, encoding: "utf-8", stdio: "pipe" });
148
+ recentModifiedFiles = gitOut
149
+ .split("\n")
150
+ .map((line) => line.slice(3).trim())
151
+ .filter((line) => line.length > 0)
152
+ .slice(0, 10);
153
+ }
154
+ catch {
155
+ // Not a git repo or git not installed
156
+ }
144
157
  return {
145
158
  language,
146
159
  framework,
147
160
  packageManager,
148
- domain: language,
161
+ domain: null,
149
162
  boundedContexts,
150
163
  eePatterns,
151
164
  relevantModules,
165
+ recentModifiedFiles,
152
166
  scannedAt: Date.now(),
153
167
  cwd,
154
168
  };
@@ -11,13 +11,20 @@
11
11
  * "Layer 1.5 complexity-size (4C)"). Do NOT alter weights without re-running the
12
12
  * baseline harness regression.
13
13
  */
14
+ import type { RepoStructureHint } from "./repo-structure-hints.js";
14
15
  export interface ComplexitySizeInput {
15
16
  rawText: string;
16
17
  taskType: string;
18
+ repoHints?: RepoStructureHint[];
17
19
  }
18
20
  export interface ComplexitySizeResult {
19
21
  size: "small" | "medium" | "large";
20
22
  score: number;
21
23
  features: Record<string, number | boolean>;
22
24
  }
25
+ export declare function extractPathTokens(rawText: string): string[];
26
+ export declare function scoreRepoGrounding(paths: string[], hints: RepoStructureHint[]): {
27
+ score: number;
28
+ hits: number;
29
+ };
23
30
  export declare function scoreComplexitySize(input: ComplexitySizeInput): ComplexitySizeResult;
@@ -62,14 +62,32 @@ function effectiveLen(rawText, taskType) {
62
62
  // ---------------------------------------------------------------------------
63
63
  // Path token counter — counts DISTINCT path-like tokens.
64
64
  // ---------------------------------------------------------------------------
65
- function countDistinctPaths(rawText) {
65
+ export function extractPathTokens(rawText) {
66
66
  const matches = rawText.match(PATH_TOKEN_RE);
67
67
  if (!matches)
68
- return 0;
68
+ return [];
69
69
  const set = new Set();
70
70
  for (const m of matches)
71
71
  set.add(m.toLowerCase());
72
- return set.size;
72
+ return [...set];
73
+ }
74
+ export function scoreRepoGrounding(paths, hints) {
75
+ if (paths.length === 0 || hints.length === 0)
76
+ return { score: 0, hits: 0 };
77
+ const hinted = new Map(hints.map((hint) => [hint.path.toLowerCase(), hint]));
78
+ let score = 0;
79
+ let hits = 0;
80
+ for (const path of paths) {
81
+ const hint = hinted.get(path);
82
+ if (!hint)
83
+ continue;
84
+ hits += 1;
85
+ if (hint.lineCount >= 5000)
86
+ score = Math.max(score, 4);
87
+ else if (hint.lineCount >= 2000)
88
+ score = Math.max(score, 2);
89
+ }
90
+ return { score, hits };
73
91
  }
74
92
  // ---------------------------------------------------------------------------
75
93
  // Main: scoreComplexitySize
@@ -77,6 +95,7 @@ function countDistinctPaths(rawText) {
77
95
  export function scoreComplexitySize(input) {
78
96
  const rawText = input.rawText ?? "";
79
97
  const taskType = input.taskType ?? "general";
98
+ const repoHints = input.repoHints ?? [];
80
99
  // 1. Length score (debug + stack-trace gets mitigation).
81
100
  // CONTEXT-locked thresholds are <60 / >240. We use <80 for the "small" knee
82
101
  // because the baseline-2 prompt "đổi default --max-tool-rounds từ 100 →
@@ -102,13 +121,18 @@ export function scoreComplexitySize(input) {
102
121
  // baseline-2 "đổi default ... trong src/orchestrator/cli-args.ts")
103
122
  // - zero paths is neutral (vagueness is handled by `vaguenessAmplifier`)
104
123
  // - ≥3 paths is multi-file work, push toward large
105
- const pathCount = countDistinctPaths(rawText);
124
+ const distinctPaths = extractPathTokens(rawText);
125
+ const pathCount = distinctPaths.length;
106
126
  let pathScore = 0;
107
127
  if (pathCount === 1)
108
128
  pathScore = -1;
109
129
  else if (pathCount >= 3)
110
130
  pathScore = 2;
111
131
  // 0 or 2 → 0 (neutral)
132
+ // 4.5 Repo-structure grounding probe. Cheap deterministic lookup against the
133
+ // checked-in REPO_DEEP_MAP index: monolith roots like src/ui/app.tsx should
134
+ // not size the same as a narrow leaf module when both appear as one-path asks.
135
+ const repoGrounding = scoreRepoGrounding(distinctPaths, repoHints);
112
136
  // 5. Question form score.
113
137
  const trimmed = rawText.trim();
114
138
  const isQuestion = QUESTION_START_RE.test(trimmed) || trimmed.endsWith("?");
@@ -123,7 +147,7 @@ export function scoreComplexitySize(input) {
123
147
  // "improve X" / "clean up Y" without targets is the canonical wandering shape.
124
148
  const vaguenessAmplifier = sweepCount > 0 && pathCount === 0 ? 4 : 0;
125
149
  // Total score → bucket.
126
- const score = lenScore + sweepScore + heavyScore + pathScore + questionScore + vaguenessAmplifier;
150
+ const score = lenScore + sweepScore + heavyScore + pathScore + repoGrounding.score + questionScore + vaguenessAmplifier;
127
151
  let size;
128
152
  if (score <= -1)
129
153
  size = "small";
@@ -142,6 +166,8 @@ export function scoreComplexitySize(input) {
142
166
  heavyScore,
143
167
  pathCount,
144
168
  pathScore,
169
+ repoGroundingHits: repoGrounding.hits,
170
+ repoGroundingScore: repoGrounding.score,
145
171
  isQuestion,
146
172
  questionScore,
147
173
  isImperative,
@@ -19,6 +19,8 @@ import { searchByText } from "../ee/bridge.js";
19
19
  import { updateLastSurfacedState } from "../ee/intercept.js";
20
20
  import { formatPendingReminder, isRecallLedgerEnabled, sessionRecallLedger } from "../ee/recall-ledger.js";
21
21
  import { getRenderSink } from "../ee/render.js";
22
+ import { PLANNING_CHECKPOINT_QUERY } from "../gsd/ee-closure.js";
23
+ import { isGsdNativeEnabled } from "../gsd/flags.js";
22
24
  import { logInteraction } from "../storage/interaction-log.js";
23
25
  import { classifyEeError, logEeFailure, readTimeoutEnv } from "../utils/ee-logger.js";
24
26
  import { truncateToBudget } from "./budget.js";
@@ -138,10 +140,13 @@ async function queryEeBridge(raw, taskType) {
138
140
  // Phase 3 (ee-anti-mu): third arm for compaction checkpoints so PIL can surface
139
141
  // prior "Progress ✔ DONE / elided" without the agent having to ask "task finished?".
140
142
  const signal = AbortSignal.timeout(PIL_SEARCH_TIMEOUT_MS);
143
+ const planningQuery = isGsdNativeEnabled()
144
+ ? `${PLANNING_CHECKPOINT_QUERY} OR compaction checkpoint`
145
+ : 'Context checkpoint summary OR "compaction checkpoint" recent Progress DONE elided OR tool-artifact OR "tool result id="';
141
146
  const [principleRaw, behavioralRaw, checkpointRaw] = await Promise.all([
142
147
  searchByText(queryWithTask, ["experience-principles"], 3, signal),
143
148
  searchByText(queryWithTask, ["experience-behavioral"], 4, signal),
144
- searchByText('Context checkpoint summary OR "compaction checkpoint" recent Progress DONE elided OR tool-artifact OR "tool result id="', ["experience-behavioral"], 3, signal).catch(() => []),
149
+ searchByText(planningQuery, ["experience-behavioral"], 3, signal).catch(() => []),
145
150
  ]);
146
151
  const principlePoints = principleRaw.filter((p) => (p.score ?? 0) >= PIL_PRINCIPLES_FLOOR);
147
152
  const behavioralPoints = behavioralRaw.filter((p) => (p.score ?? 0) >= PIL_SCORE_FLOOR);
@@ -217,10 +222,15 @@ export async function layer3EeInjection(ctx) {
217
222
  ...p,
218
223
  collection: p.collection ?? "experience-behavioral",
219
224
  }));
220
- // Suppress already-fedback entries so they don't re-inject as noise.
225
+ // Suppress (a) already-fed-back entries AND (b) entries already surfaced
226
+ // earlier this session (still pending) — re-injecting the full body of a
227
+ // hint the agent already saw is pure repetition (the "hint lặp"); the hit
228
+ // stays in the feedback nudge (shown once via _surfacedPendingIds) so the
229
+ // rating path is preserved without duplicating content every turn.
221
230
  if (isRecallLedgerEnabled()) {
222
- principleItems = principleItems.filter((p) => !sessionRecallLedger.wasCleared(String(p.id)));
223
- behavioralItems = behavioralItems.filter((p) => !sessionRecallLedger.wasCleared(String(p.id)));
231
+ const alreadyShown = (id) => sessionRecallLedger.wasCleared(id) || sessionRecallLedger.isPending(id);
232
+ principleItems = principleItems.filter((p) => !alreadyShown(String(p.id)));
233
+ behavioralItems = behavioralItems.filter((p) => !alreadyShown(String(p.id)));
224
234
  }
225
235
  // Render the [id:..] handle inline (mirrors formatPrincipleRules/Hints) so the
226
236
  // [id collection] reminder below refers to handles the agent can actually see.
@@ -397,11 +407,16 @@ export async function layer3EeInjection(ctx) {
397
407
  return text.length === 0 || !checkpointMarkerShas.has(payloadSha16(text));
398
408
  })
399
409
  : result.checkpointPoints || [];
400
- // Feedback-cleared suppression: skip points that were already rated via ee_feedback in an earlier turn.
401
- // This prevents already-judged entries from being re-injected as noise.
410
+ // Suppression: skip rateable hints that were already (a) rated via ee_feedback
411
+ // OR (b) surfaced earlier this session (still pending). Re-injecting the full
412
+ // body of a hint the agent already saw is the "hint lặp" repetition; the entry
413
+ // stays in the feedback nudge (shown once) so rating is still prompted.
414
+ // Checkpoints are GSD status context (not rateable) — only cleared-suppressed,
415
+ // they may legitimately re-surface each turn.
402
416
  const ledgerEnabled = isRecallLedgerEnabled();
403
- const clearedFilteredPrinciples = deduplicatedPrinciples.filter((p) => !(ledgerEnabled && sessionRecallLedger.wasCleared(String(p.id))));
404
- const clearedFilteredBehavioral = deduplicatedBehavioral.filter((p) => !(ledgerEnabled && sessionRecallLedger.wasCleared(String(p.id))));
417
+ const alreadyShown = (id) => ledgerEnabled && (sessionRecallLedger.wasCleared(id) || sessionRecallLedger.isPending(id));
418
+ const clearedFilteredPrinciples = deduplicatedPrinciples.filter((p) => !alreadyShown(String(p.id)));
419
+ const clearedFilteredBehavioral = deduplicatedBehavioral.filter((p) => !alreadyShown(String(p.id)));
405
420
  const clearedFilteredCheckpoints = deduplicatedCheckpoints.filter((p) => !(ledgerEnabled && sessionRecallLedger.wasCleared(String(p.id))));
406
421
  const allPoints = [...clearedFilteredPrinciples, ...clearedFilteredBehavioral, ...clearedFilteredCheckpoints];
407
422
  // STALE-01: Register injected point IDs for prompt-stale reconciliation.
@@ -17,10 +17,12 @@
17
17
  * the agent, into the user's language.
18
18
  */
19
19
  import { getWhoAmIProfile, routeTask } from "../ee/bridge.js";
20
+ import { isGsdNativeEnabled } from "../gsd/flags.js";
21
+ import { readState } from "../gsd/workflow-engine.js";
20
22
  import { buildDirective } from "../playbook/directives.js";
21
23
  import { classifyEeError, logEeFailure } from "../utils/ee-logger.js";
22
24
  import { truncateToBudget } from "./budget.js";
23
- import { isImplementationIntent, isMetaAnalysisPrompt, isQuestionLike } from "./layer6-output.js";
25
+ import { isImplementationIntent, isMetaAnalysisPrompt, isQuestionLike, isSprintPlanExecution, } from "./layer6-output.js";
24
26
  function mapRouteToPhase(route) {
25
27
  switch (route) {
26
28
  case "qc-flow":
@@ -66,10 +68,10 @@ export async function layer4Gsd(ctx) {
66
68
  }
67
69
  let phase = ctx.gsdPhase ?? null;
68
70
  let routeSource = "preset";
69
- // Skip brain routeTask when L1's unified call already supplied brain data:
70
- // any phase L1 derived is already on ctx.gsdPhase, and a separate routeTask
71
- // round-trip would duplicate the brain hit the unified endpoint replaces.
72
- if (!phase && !ctx._brainData) {
71
+ // Skip brain routeTask when L1 unified pilContext already supplied gsd_phase
72
+ // (on ctx.gsdPhase) or brain retrieval data (_brainData) a separate routeTask
73
+ // round-trip would duplicate the unified endpoint.
74
+ if (!phase && !ctx._brainData && !ctx.gsdPhase) {
73
75
  const eeRoute = await routeTask(ctx.raw).catch((err) => {
74
76
  logEeFailure("pil.layer4.routeTask", classifyEeError(err), err);
75
77
  return null;
@@ -124,13 +126,23 @@ export async function layer4Gsd(ctx) {
124
126
  // read/summarize/architecture tasks (deliverableKind "report") down the heavy
125
127
  // council + AskUserQuestion path, over-asking on a task that just wanted a
126
128
  // written summary (session 666630479c1a: "Đọc và tóm tắt kiến trúc…" raised 2
127
- // askcards + a council loop). Only when the model emitted no deliverable
128
- // (deliverableKind null → legacy cascade) do we fall back to regex predicates:
129
+ // askcards + a council loop).
130
+ //
131
+ // BUT a "report" deliverable can still be a genuine implementation request the
132
+ // model mis-tagged (e.g. "make a plan to implement OAuth device flow" — the
133
+ // deliverable IS a plan/report, yet the raw prompt asks to implement). Without
134
+ // a guard this never entered GSD. isImplementationIntent re-checks the raw
135
+ // text so a real implementation ask overrides the deliverable-kind shortcut;
136
+ // a genuine summary/read prompt (no implementation keywords) still passes
137
+ // through as informational.
138
+ //
139
+ // Only when the model emitted no deliverable (deliverableKind null → legacy
140
+ // cascade) do we fall back to regex predicates:
129
141
  // 1. isMetaAnalysisPrompt — self/CLI evaluation, prior-turn reflection.
130
142
  // 2. taskType "general" classified as a real task by L1.
131
143
  // 3. question-shaped prompt that is NOT an implementation request.
132
144
  const informational = ctx.deliverableKind
133
- ? ctx.deliverableKind !== "code"
145
+ ? ctx.deliverableKind !== "code" && !isImplementationIntent(ctx.raw)
134
146
  : isMetaAnalysisPrompt(ctx.raw) ||
135
147
  (ctx.taskType === "general" && ctx.intentKind === "task") ||
136
148
  (isQuestionLike(ctx.raw) && !isImplementationIntent(ctx.raw));
@@ -141,17 +153,57 @@ export async function layer4Gsd(ctx) {
141
153
  // language the model detected (the old regex only caught Vietnamese).
142
154
  const ecosystem = ctx.ecosystemScope === true;
143
155
  const replyLanguage = ctx.replyLanguage ?? undefined;
144
- const directive = buildDirective({ tier, phase, informational, ecosystem, replyLanguage });
145
- // truncateToBudget takes a TOKEN budget (×CHARS_PER_TOKEN internally). Floor it
146
- // at DIRECTIVE_MIN_TOKENS so the full directive always survives, even at the
147
- // default tokenBudget=500 where the bare fraction would gut it.
148
- const directiveTokenBudget = Math.max(Math.floor(ctx.tokenBudget * DIRECTIVE_BUDGET_FRACTION), DIRECTIVE_MIN_TOKENS);
149
- const trimmed = truncateToBudget(directive.text, directiveTokenBudget);
156
+ const native = isGsdNativeEnabled();
157
+ const sprintExecution = isSprintPlanExecution(ctx.raw);
158
+ let trimmed;
159
+ let blocking = false;
160
+ let appliedTier = tier;
161
+ if (sprintExecution) {
162
+ // Sprint plan execution: the plan has already been debated and reviewed by
163
+ // the council. The impl turn must APPLY it, not re-enter gsd_plan_review.
164
+ // Override any depth-tier hint that would tell the model to plan first.
165
+ const execDirective = [
166
+ "[sprint-execution] The attached text is an APPROVED sprint plan.",
167
+ "EXECUTE it directly with edit_file/write_file/bash tools.",
168
+ "Do NOT call gsd_discuss, gsd_plan, or gsd_plan_review — the plan is already reviewed.",
169
+ "After edits, run gsd_verify if verification steps are listed, otherwise finish.",
170
+ ].join(" ");
171
+ trimmed = truncateToBudget(execDirective, 200);
172
+ blocking = false;
173
+ appliedTier = "standard";
174
+ }
175
+ else if (native && !informational) {
176
+ const cwd = process.cwd();
177
+ const wf = readState(cwd);
178
+ // Heavy is now a hard MANDATORY sequence (Task 8 wires the runtime mutation
179
+ // gate that actually BLOCKs edit_file/write_file/bash on this depth); standard
180
+ // stays advisory-only — never say BLOCKED for standard, the gate doesn't fire there.
181
+ const heavyLine = tier === "heavy"
182
+ ? " MANDATORY (heavy): gsd_status → gsd_discuss → gsd_plan → gsd_plan_review BEFORE any edit_file/write_file/bash. Mutation tools are BLOCKED until plan-review passes. Start with gsd_status now."
183
+ : "";
184
+ const nativeHint = [
185
+ "[gsd-native] Tools: gsd_status, gsd_discuss, gsd_plan, gsd_plan_review, gsd_execute, gsd_verify, gsd_ship.",
186
+ `Depth=${tier}. standard/heavy: recommend gsd_plan_review before gsd_execute; then gsd_verify → gsd_ship.${heavyLine}`,
187
+ wf.phase ? `phase=${wf.phase}` : "gsd_status bootstraps .planning/",
188
+ wf.planVerified ? "plan-verified=yes" : "plan-verified=pending",
189
+ ].join(" ");
190
+ trimmed = truncateToBudget(nativeHint, 200);
191
+ blocking = tier === "heavy";
192
+ appliedTier = tier;
193
+ }
194
+ else {
195
+ const directive = buildDirective({ tier, phase, informational, ecosystem, replyLanguage, nativeGsd: native });
196
+ const directiveTokenBudget = Math.max(Math.floor(ctx.tokenBudget * DIRECTIVE_BUDGET_FRACTION), DIRECTIVE_MIN_TOKENS);
197
+ trimmed = truncateToBudget(directive.text, directiveTokenBudget);
198
+ blocking = directive.blocking;
199
+ appliedTier = directive.tier;
200
+ }
150
201
  const depthSource = ctx.modelDepthTier ? "model" : "default";
151
202
  return {
152
203
  ...ctx,
153
204
  gsdPhase: phase,
154
205
  complexityTier: tier,
206
+ gsdGateBlocking: blocking,
155
207
  grayAreas,
156
208
  enriched: `${ctx.enriched}\n${trimmed}`,
157
209
  layers: [
@@ -160,11 +212,12 @@ export async function layer4Gsd(ctx) {
160
212
  name: "gsd-workflow-structuring",
161
213
  applied: true,
162
214
  delta: [
163
- `tier=${directive.tier}`,
215
+ `tier=${appliedTier}`,
216
+ `native=${native}`,
164
217
  `depth=${depthSource}`,
165
218
  `phase=${phase ?? "none"}`,
166
219
  `route=${routeSource}`,
167
- `blocking=${directive.blocking}`,
220
+ `blocking=${blocking}`,
168
221
  `chars=${trimmed.length}`,
169
222
  ].join(" "),
170
223
  },
@@ -50,11 +50,15 @@ async function fetchPrinciples(raw, budget) {
50
50
  }
51
51
  async function fetchFlowState(cwd, budget) {
52
52
  try {
53
- const activeRunPath = path.join(cwd, ".muonroi-flow", "active-run");
54
- const runId = (await fs.readFile(activeRunPath, "utf8")).trim();
53
+ // Canonical focus pointer: `state.md` `Active Run` (run-manager). The old
54
+ // `.muonroi-flow/active-run` file had no writer in src and always read stale
55
+ // (F8 follow-up: dropped that dead path in favor of the single source).
56
+ const { getActiveRunId } = await import("../flow/run-manager.js");
57
+ const flowDir = path.join(cwd, ".muonroi-flow");
58
+ const runId = await getActiveRunId(flowDir);
55
59
  if (!runId)
56
60
  return "";
57
- const statePath = path.join(cwd, ".muonroi-flow", "runs", runId, "state.md");
61
+ const statePath = path.join(flowDir, "runs", runId, "state.md");
58
62
  const state = await fs.readFile(statePath, "utf8");
59
63
  const phaseLine = state.match(/phase:\s*(.+)/i)?.[1]?.trim() ?? "unknown";
60
64
  const statusLine = state.match(/status:\s*(.+)/i)?.[1]?.trim() ?? "unknown";
@@ -17,6 +17,29 @@ import type { ProviderId } from "../providers/types.js";
17
17
  import type { PipelineContext } from "./types.js";
18
18
  export declare function isMetaAnalysisPrompt(raw: string): boolean;
19
19
  export declare function applyPilSuffix(systemPrompt: string, ctx: PipelineContext, responseToolsActive?: boolean): string;
20
+ /**
21
+ * Detect an explicit IMPLEMENTATION / edit-the-files intent. When the user asks
22
+ * to implement/edit/refactor (the deliverable is file changes, not a structured
23
+ * report), a terminal `respond_<task>` tool is inappropriate: the model can call
24
+ * it mid-task to "state a plan/answer" and the turn then winds down before the
25
+ * edits are finished. Live (grok session 19fa8895c41c): an "Improve … implement
26
+ * these fixes" prompt was classified `debug`, so `respond_debug` was offered; the
27
+ * model called it after reading the files, made a few edits, then stopped — the
28
+ * HTML was never wired. Dropping the tool just falls through to the markdown
29
+ * OUTPUT RULES (graceful — exactly what code-heavy tasks already do), so a false
30
+ * positive on an analysis turn only forgoes structured JSON, never breaks output.
31
+ *
32
+ * High-signal verbs only (implement/edit/wire/rewrite/rename/scaffold/refactor/
33
+ * improve, "make the change", "apply the fix/patch", VI equivalents incl. "cải
34
+ * thiện"). Bare "fix"/"replace" are excluded — too common in analysis ("explain
35
+ * the fix") — so pure analyze/plan/debug-investigation turns keep their
36
+ * structured output. "improve(ment)" / "cải thiện" added after session
37
+ * 2b7a10219499: "lên plan rồi improvement … cải thiện Compaction" was an
38
+ * implement turn the model mis-classified as a `report`, so a terminal
39
+ * respond_plan ended it on a plan (edits done but uncommitted/unreported).
40
+ */
41
+ export declare const SPRINT_EXECUTION_MARKER = "[SPRINT-PLAN-EXECUTION: locked]";
42
+ export declare function isSprintPlanExecution(raw: string): boolean;
20
43
  export declare function isImplementationIntent(raw: string): boolean;
21
44
  export declare function isQuestionLike(raw: string): boolean;
22
45
  export declare function prefersStructuredReport(raw: string): boolean;
@@ -285,7 +285,11 @@ export function applyPilSuffix(systemPrompt, ctx, responseToolsActive = false) {
285
285
  * implement turn the model mis-classified as a `report`, so a terminal
286
286
  * respond_plan ended it on a plan (edits done but uncommitted/unreported).
287
287
  */
288
- const IMPLEMENTATION_INTENT_RE = /\b(implement|edit|wire(?:\s+up)?|rewrite|rename|scaffold|refactor)\b|\bimprove(?:ment)?\b|\bmake\s+(the\s+)?(change|edit|modification)s?\b|\bapply\s+(the\s+)?(fix|change|patch|edit|diff)\b|(?:^|\s)(triển\s*khai|trien\s*khai|chỉnh\s*sửa|chinh\s*sua|viết\s*lại|viet\s*lai|đổi\s*tên|doi\s*ten|cải\s*thiện|cai\s*thien)\b/i;
288
+ export const SPRINT_EXECUTION_MARKER = "[SPRINT-PLAN-EXECUTION: locked]";
289
+ export function isSprintPlanExecution(raw) {
290
+ return raw.includes(SPRINT_EXECUTION_MARKER) || raw.includes("--- SPRINT PLAN TO IMPLEMENT ---");
291
+ }
292
+ const IMPLEMENTATION_INTENT_RE = /\b(implement|edit|wire(?:\s+up)?|rewrite|rename|scaffold|refactor)\b|\bimprove(?:ment)?\b|\bmake\s+(the\s+)?(change|edit|modification)s?\b|\bapply\s+(the\s+)?(fix|change|patch|edit|diff)\b|(?:^|\s)(triển\s*khai|trien\s*khai|chỉnh\s*sửa|chinh\s*sua|viết\s*lại|viet\s*lai|đổi\s*tên|doi\s*ten|cải\s*thiện|cai\s*thien)\b|\[SPRINT-PLAN-EXECUTION:\s*locked\]/i;
289
293
  export function isImplementationIntent(raw) {
290
294
  return !!raw && IMPLEMENTATION_INTENT_RE.test(raw);
291
295
  }
@@ -1,4 +1,4 @@
1
- import type { ProviderFactory } from "../providers/runtime.js";
1
+ import type { ProviderId } from "../providers/types.js";
2
2
  import type { OutputStyle, TaskType } from "./types.js";
3
3
  /**
4
4
  * What the user wants the turn to PRODUCE — decided by the model (Phase 2b) so
@@ -49,6 +49,18 @@ export interface LlmClassifyResult {
49
49
  * what the task actually entails, not by which keywords it happens to contain.
50
50
  */
51
51
  depthTier: DepthTier | null;
52
+ /**
53
+ * Model-decided clarity: true when the request is UNDERSPECIFIED — missing
54
+ * information the agent would need to proceed without guessing (an unstated
55
+ * target/scope, a vague "make it better", competing interpretations, or an
56
+ * unresolved design choice). Drives the interview gate: a `standard`-depth
57
+ * task that is underspecified earns a clarify/council pass instead of hot-
58
+ * pathing straight to implementation. `false` = well-specified enough to plan
59
+ * directly. null when the model omitted the word → treated as not-
60
+ * underspecified (the don't-over-ask safe direction). Agent-first replacement
61
+ * for the regex `scoreSufficiency` scorer.
62
+ */
63
+ needsClarification: boolean | null;
52
64
  /**
53
65
  * Model-decided scope: true when the turn is about the Muonroi PLATFORM /
54
66
  * ecosystem (BB/.NET packages, building-block, open-core, rule engine,
@@ -67,7 +79,69 @@ export interface LlmClassifyResult {
67
79
  */
68
80
  replyLanguage: string | null;
69
81
  }
70
- export type LlmClassifyFn = (prompt: string, signal?: AbortSignal) => Promise<LlmClassifyResult | null>;
82
+ /**
83
+ * Options for a classify call. `recentTurns` is a compact digest of the last
84
+ * few conversation turns; when present the classifier uses it ONLY to resolve
85
+ * back-references in the new message (e.g. "từ các phần đó", "làm tiếp", "this")
86
+ * so a terse follow-up that points at heavy prior work is not mis-scored as a
87
+ * trivial one-liner. Without it the classifier sees the bare prompt and is blind
88
+ * to context — the documented "chấm điểm chỉ dựa only prompt" failure.
89
+ */
90
+ export interface LlmClassifyOptions {
91
+ recentTurns?: string | null;
92
+ signal?: AbortSignal;
93
+ }
94
+ export type LlmClassifyFn = (prompt: string, opts?: LlmClassifyOptions) => Promise<LlmClassifyResult | null>;
95
+ /**
96
+ * Factory-level options for `createLlmClassifier` (distinct from the per-call
97
+ * `LlmClassifyOptions`). Chosen once when the closure is built.
98
+ */
99
+ export interface CreateClassifierOptions {
100
+ /**
101
+ * Route the throwaway classify to the provider's fast tier when one exists
102
+ * (mirrors `classifySubSessionAction`). Same-provider only, so the already-
103
+ * bound factory/key still works. A no-op when the provider exposes no
104
+ * routable fast model (e.g. xai). Zero-hardcode: the fast id comes from
105
+ * `getRoutedModelByTier`, not a literal. Cheap — safe on every turn.
106
+ */
107
+ routeFastTier?: boolean;
108
+ /**
109
+ * When the session provider has NO same-provider fast tier (e.g. xai, whose
110
+ * session model may be an agentic model that ignores the terse classify
111
+ * contract — measured 2026-07-15 for grok-composer), also try keyed fast
112
+ * models from OTHER configured providers, in catalog switch order, until one
113
+ * parses. Bounded by CLASSIFY_TOTAL_BUDGET_MS so a chain of dead/slow keys
114
+ * can't stall the turn. This adds latency ONLY on that fallback path, so it is
115
+ * opt-in per call-site: enable it for the high-value /ideal routing classify,
116
+ * NOT for the per-turn PIL classify (there a fast fail-open "standard" is fine
117
+ * and cheaper than chaining providers on every message).
118
+ */
119
+ crossProviderFallback?: boolean;
120
+ }
121
+ /**
122
+ * Compute the classify call budget from the resolved model's catalog metadata.
123
+ *
124
+ * TIMEOUT is a flat safety-net ceiling for all models — see CLASSIFY_TIMEOUT_MS.
125
+ * Measurement showed classify latency is provider-independent and well under
126
+ * the ceiling, so keying the timeout off `tier`/`reasoning` added no value and
127
+ * amounted to an identity-proxy soft-hardcode.
128
+ *
129
+ * MAX-OUTPUT scales with REASONING only: a reasoning model burns its output
130
+ * budget on reasoning tokens before any visible text, so it needs the room in
131
+ * tokens; a non-reasoning model emits the 8 words directly. This knob is real —
132
+ * it is the fix for reasoning models routing the verdict into the reasoning
133
+ * channel — and stays decoupled from the (now flat) timeout.
134
+ */
135
+ export declare function classifierBudget(modelInfo: {
136
+ reasoning?: boolean;
137
+ tier?: string;
138
+ } | undefined): {
139
+ isReasoning: boolean;
140
+ timeoutMs: number;
141
+ maxOutputTokens: number;
142
+ };
143
+ /** Test seam — clear the cross-provider factory cache between specs. */
144
+ export declare function __resetClassifyFactoryCache(): void;
71
145
  /**
72
146
  * Build a closure the PIL pipeline can call. Reuses the orchestrator's already-
73
147
  * constructed providerFactory + modelId so we don't pay key-loading cost twice.
@@ -75,15 +149,47 @@ export type LlmClassifyFn = (prompt: string, signal?: AbortSignal) => Promise<Ll
75
149
  * Returns null if the call fails / times out / parses to garbage. Callers must
76
150
  * fail-open (keep prior taskType, do not block the turn).
77
151
  */
78
- export declare function createLlmClassifier(factory: ProviderFactory, modelId: string): LlmClassifyFn;
152
+ /**
153
+ * Order the classify candidate list.
154
+ *
155
+ * - `hasSameFast` (e.g. openai → gpt-5.4-mini): the same-provider fast tier is a
156
+ * real fast model, so try it FIRST, then keyed cross-provider models as a
157
+ * FALLBACK. This is the fix for the failure-not-just-absence case: an
158
+ * openai-OAuth session's fast tier can 401 on the api-key path — previously
159
+ * the chain stopped there and fail-opened to "standard" (so /ideal
160
+ * over-councilled trivial tasks). Appending the cross-provider models lets a
161
+ * working alternative (a keyed deepseek/opencode fast model) rescue it.
162
+ * - No same-provider fast tier (e.g. xai, whose session model is agentic and
163
+ * ignores the terse contract): try keyed cross-provider fast models FIRST and
164
+ * keep the session model as the last-resort candidate.
165
+ */
166
+ export declare function orderClassifyCandidates(args: {
167
+ primaryModelId: string;
168
+ hasSameFast: boolean;
169
+ crossModels: ReadonlyArray<{
170
+ modelId: string;
171
+ providerId: ProviderId;
172
+ }>;
173
+ }): Array<{
174
+ modelId: string;
175
+ providerId: ProviderId | null;
176
+ }>;
177
+ export declare function createLlmClassifier(modelId: string, classifyOpts?: CreateClassifierOptions): LlmClassifyFn;
79
178
  export type SubSessionAction = "DIRECT_ANSWER" | "ROTATE_SESSION" | "SPAWN_SUB_SESSION";
80
179
  export interface SubSessionRouteResult {
81
180
  action: SubSessionAction;
82
181
  confidence: number;
83
182
  reason: string;
84
183
  }
85
- export declare function classifySubSessionActionHeuristic(prompt: string): SubSessionRouteResult | null;
86
- export declare function classifySubSessionAction(factory: ProviderFactory, modelId: string, prompt: string, contextInfo?: {
184
+ export declare function classifySubSessionAction(modelId: string, prompt: string, contextInfo?: {
87
185
  currentChars: number;
88
186
  threshold: number;
187
+ /**
188
+ * Compact digest of recent conversation turns. The router's system prompt
189
+ * says it decides "based on the conversation history" — without this the
190
+ * history was never actually supplied and the router judged the prompt in
191
+ * isolation, so a follow-up like "ok làm phần đó đi" could not be told apart
192
+ * from a fresh unrelated task. Supplying it makes the claim true.
193
+ */
194
+ recentTurns?: string | null;
89
195
  }, signal?: AbortSignal): Promise<SubSessionRouteResult | null>;