muonroi-cli 1.7.2 → 1.8.1

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 (326) hide show
  1. package/dist/packages/agent-harness-core/src/event-filter.js +1 -0
  2. package/dist/packages/agent-harness-core/src/event-redact.js +8 -0
  3. package/dist/packages/agent-harness-core/src/mcp-server.d.ts +16 -0
  4. package/dist/packages/agent-harness-core/src/mcp-server.js +88 -10
  5. package/dist/packages/agent-harness-core/src/protocol.d.ts +15 -0
  6. package/dist/packages/agent-harness-core/src/selector.js +2 -2
  7. package/dist/packages/agent-harness-core/src/transports/sidechannel.js +1 -1
  8. package/dist/packages/agent-harness-opentui/src/agent-mode.js +1 -1
  9. package/dist/packages/agent-harness-opentui/src/install.js +1 -1
  10. package/dist/src/__test-stubs__/vitest-setup.js +4 -0
  11. package/dist/src/agent-harness/__tests__/mock-model.spec.js +54 -0
  12. package/dist/src/agent-harness/mock-model.d.ts +1 -1
  13. package/dist/src/agent-harness/mock-model.js +143 -6
  14. package/dist/src/agent-harness/test-spawn.js +3 -1
  15. package/dist/src/chat/chat-keychain.js +9 -1
  16. package/dist/src/cli/cost-forensics.js +7 -4
  17. package/dist/src/cli/keys.d.ts +2 -2
  18. package/dist/src/cli/keys.js +107 -28
  19. package/dist/src/cli/usage-report.js +2 -2
  20. package/dist/src/council/__tests__/abort-threading.test.d.ts +1 -0
  21. package/dist/src/council/__tests__/abort-threading.test.js +193 -0
  22. package/dist/src/council/__tests__/clarification-prompt.test.js +21 -1
  23. package/dist/src/council/__tests__/council-turn-length-emit.test.d.ts +1 -0
  24. package/dist/src/council/__tests__/council-turn-length-emit.test.js +130 -0
  25. package/dist/src/council/__tests__/debate-round-budget.test.d.ts +1 -0
  26. package/dist/src/council/__tests__/debate-round-budget.test.js +45 -0
  27. package/dist/src/council/__tests__/evaluator-metrics.test.js +3 -0
  28. package/dist/src/council/__tests__/post-debate-recommendation.test.d.ts +1 -0
  29. package/dist/src/council/__tests__/post-debate-recommendation.test.js +58 -0
  30. package/dist/src/council/__tests__/research-tools.test.js +4 -0
  31. package/dist/src/council/__tests__/round-tools.test.js +6 -0
  32. package/dist/src/council/clarifier-question-cap.test.d.ts +12 -0
  33. package/dist/src/council/clarifier-question-cap.test.js +73 -0
  34. package/dist/src/council/clarifier.d.ts +29 -1
  35. package/dist/src/council/clarifier.js +64 -1
  36. package/dist/src/council/debate-planner.d.ts +2 -1
  37. package/dist/src/council/debate-planner.js +5 -3
  38. package/dist/src/council/debate.d.ts +9 -0
  39. package/dist/src/council/debate.js +88 -8
  40. package/dist/src/council/index.d.ts +46 -1
  41. package/dist/src/council/index.js +125 -19
  42. package/dist/src/council/llm.js +41 -13
  43. package/dist/src/council/prompts.js +36 -1
  44. package/dist/src/council/types.d.ts +14 -1
  45. package/dist/src/ee/__tests__/export-transcripts.test.js +1 -1
  46. package/dist/src/ee/bridge.d.ts +3 -1
  47. package/dist/src/ee/bridge.js +9 -3
  48. package/dist/src/ee/bridge.test.js +1 -2
  49. package/dist/src/ee/client.js +15 -2
  50. package/dist/src/ee/recall-ledger.d.ts +20 -0
  51. package/dist/src/ee/recall-ledger.js +40 -1
  52. package/dist/src/ee/search.d.ts +25 -0
  53. package/dist/src/ee/search.js +73 -0
  54. package/dist/src/ee/types.d.ts +15 -1
  55. package/dist/src/ee/who-am-i.d.ts +41 -0
  56. package/dist/src/ee/who-am-i.js +143 -0
  57. package/dist/src/ee/who-am-i.test.d.ts +1 -0
  58. package/dist/src/ee/who-am-i.test.js +101 -0
  59. package/dist/src/flow/compaction/index.d.ts +1 -0
  60. package/dist/src/flow/compaction/index.js +4 -0
  61. package/dist/src/generated/version.d.ts +1 -1
  62. package/dist/src/generated/version.js +1 -1
  63. package/dist/src/headless/council-answers.js +1 -0
  64. package/dist/src/headless/output.d.ts +30 -1
  65. package/dist/src/headless/output.js +180 -0
  66. package/dist/src/headless/output.test.js +61 -1
  67. package/dist/src/hooks/index.js +48 -2
  68. package/dist/src/index.d.ts +2 -0
  69. package/dist/src/index.js +59 -62
  70. package/dist/src/lsp/client-normalize.test.d.ts +12 -0
  71. package/dist/src/lsp/client-normalize.test.js +34 -0
  72. package/dist/src/lsp/client.d.ts +1 -0
  73. package/dist/src/lsp/client.js +10 -2
  74. package/dist/src/lsp/manager.d.ts +1 -1
  75. package/dist/src/lsp/manager.js +13 -5
  76. package/dist/src/lsp/manager.test.js +41 -2
  77. package/dist/src/lsp/runtime.d.ts +1 -1
  78. package/dist/src/lsp/runtime.js +2 -2
  79. package/dist/src/maintain/__tests__/gh-create-pr.test.js +7 -3
  80. package/dist/src/maintain/__tests__/pr-builder.test.js +7 -3
  81. package/dist/src/mcp/__tests__/client-pool.spec.js +3 -3
  82. package/dist/src/mcp/__tests__/ee-tools.test.js +42 -14
  83. package/dist/src/mcp/__tests__/forensics-tools.test.js +3 -3
  84. package/dist/src/mcp/__tests__/lsp-tools.test.js +4 -4
  85. package/dist/src/mcp/auto-setup.js +0 -8
  86. package/dist/src/mcp/client-pool.d.ts +1 -1
  87. package/dist/src/mcp/client-pool.js +25 -9
  88. package/dist/src/mcp/ee-tools.d.ts +10 -0
  89. package/dist/src/mcp/ee-tools.js +34 -0
  90. package/dist/src/mcp/self-verify-jobs.d.ts +1 -0
  91. package/dist/src/mcp/self-verify-jobs.js +1 -3
  92. package/dist/src/mcp/self-verify-runner.js +1 -1
  93. package/dist/src/models/catalog-gemini.test.js +12 -10
  94. package/dist/src/models/catalog.json +106 -38
  95. package/dist/src/orchestrator/__tests__/auto-commit.test.d.ts +1 -0
  96. package/dist/src/orchestrator/__tests__/auto-commit.test.js +142 -0
  97. package/dist/src/orchestrator/__tests__/batch-turn-runner.test.js +3 -0
  98. package/dist/src/orchestrator/__tests__/delegations.test.d.ts +1 -0
  99. package/dist/src/orchestrator/__tests__/delegations.test.js +96 -0
  100. package/dist/src/orchestrator/__tests__/message-processor.test.js +2 -0
  101. package/dist/src/orchestrator/__tests__/prompts.test.d.ts +1 -0
  102. package/dist/src/orchestrator/__tests__/prompts.test.js +88 -0
  103. package/dist/src/orchestrator/__tests__/stream-runner.test.js +29 -0
  104. package/dist/src/orchestrator/__tests__/sub-session-delegation.test.d.ts +1 -0
  105. package/dist/src/orchestrator/__tests__/sub-session-delegation.test.js +507 -0
  106. package/dist/src/orchestrator/agent.test.js +5 -2
  107. package/dist/src/orchestrator/auto-commit.d.ts +110 -0
  108. package/dist/src/orchestrator/auto-commit.js +366 -0
  109. package/dist/src/orchestrator/batch-turn-runner.d.ts +3 -2
  110. package/dist/src/orchestrator/batch-turn-runner.js +2 -1
  111. package/dist/src/orchestrator/compaction-proposer-prompt.d.ts +8 -0
  112. package/dist/src/orchestrator/compaction-proposer-prompt.js +43 -0
  113. package/dist/src/orchestrator/compaction.d.ts +22 -0
  114. package/dist/src/orchestrator/compaction.js +42 -0
  115. package/dist/src/orchestrator/delegations.d.ts +1 -0
  116. package/dist/src/orchestrator/delegations.js +41 -0
  117. package/dist/src/orchestrator/error-utils.js +27 -2
  118. package/dist/src/orchestrator/message-processor.d.ts +23 -5
  119. package/dist/src/orchestrator/message-processor.js +226 -2573
  120. package/dist/src/orchestrator/orchestrator.d.ts +11 -2
  121. package/dist/src/orchestrator/orchestrator.js +530 -43
  122. package/dist/src/orchestrator/pending-calls.js +2 -1
  123. package/dist/src/orchestrator/preprocessor.d.ts +13 -0
  124. package/dist/src/orchestrator/preprocessor.js +146 -0
  125. package/dist/src/orchestrator/prompts.d.ts +16 -0
  126. package/dist/src/orchestrator/prompts.js +130 -67
  127. package/dist/src/orchestrator/safety-askcard.d.ts +66 -0
  128. package/dist/src/orchestrator/safety-askcard.js +74 -0
  129. package/dist/src/orchestrator/sandbox.test.js +8 -5
  130. package/dist/src/orchestrator/scope-ceiling.js +1 -1
  131. package/dist/src/orchestrator/stall-watchdog.d.ts +47 -0
  132. package/dist/src/orchestrator/stall-watchdog.js +23 -0
  133. package/dist/src/orchestrator/stall-watchdog.test.js +36 -1
  134. package/dist/src/orchestrator/stream-runner.js +52 -30
  135. package/dist/src/orchestrator/sub-agent-cap.d.ts +2 -0
  136. package/dist/src/orchestrator/sub-agent-cap.js +12 -4
  137. package/dist/src/orchestrator/sub-agent-model-tier.js +1 -1
  138. package/dist/src/orchestrator/subagent-compactor.d.ts +21 -0
  139. package/dist/src/orchestrator/subagent-compactor.js +148 -24
  140. package/dist/src/orchestrator/subagent-compactor.spec.js +249 -1
  141. package/dist/src/orchestrator/text-tool-call-detector.d.ts +9 -5
  142. package/dist/src/orchestrator/text-tool-call-detector.js +16 -12
  143. package/dist/src/orchestrator/text-tool-call-detector.test.js +66 -8
  144. package/dist/src/orchestrator/tool-args-repair.js +1 -1
  145. package/dist/src/orchestrator/tool-engine.d.ts +153 -0
  146. package/dist/src/orchestrator/tool-engine.js +3138 -0
  147. package/dist/src/orchestrator/turn-runner-deps.d.ts +3 -0
  148. package/dist/src/pil/__tests__/discovery-types.test.js +15 -4
  149. package/dist/src/pil/__tests__/discovery.test.js +89 -145
  150. package/dist/src/pil/__tests__/dual-run.test.js +2 -0
  151. package/dist/src/pil/__tests__/layer1-intent-trace.test.js +3 -0
  152. package/dist/src/pil/__tests__/layer1-intent.test.js +3 -0
  153. package/dist/src/pil/__tests__/layer16-clarity.test.js +35 -32
  154. package/dist/src/pil/__tests__/layer18-acceptance.test.js +1 -78
  155. package/dist/src/pil/__tests__/layer2_5-ponytail.test.d.ts +1 -0
  156. package/dist/src/pil/__tests__/layer2_5-ponytail.test.js +53 -0
  157. package/dist/src/pil/__tests__/layer3-ee-injection.test.js +67 -4
  158. package/dist/src/pil/__tests__/layer3-injected-chunk.test.js +14 -2
  159. package/dist/src/pil/__tests__/layer4-gsd.test.js +30 -0
  160. package/dist/src/pil/__tests__/layer5-context.test.js +39 -1
  161. package/dist/src/pil/__tests__/layer6-output.test.js +30 -2
  162. package/dist/src/pil/__tests__/llm-classify.test.js +79 -1
  163. package/dist/src/pil/__tests__/orchestrator-integration.test.js +3 -1
  164. package/dist/src/pil/__tests__/pipeline.test.js +11 -8
  165. package/dist/src/pil/__tests__/response-tools.test.js +52 -0
  166. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  167. package/dist/src/pil/agent-operating-contract.js +5 -3
  168. package/dist/src/pil/agent-operating-contract.test.js +2 -2
  169. package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
  170. package/dist/src/pil/cheap-model-playbook.js +1 -1
  171. package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
  172. package/dist/src/pil/cheap-model-workbooks.js +1 -1
  173. package/dist/src/pil/config.d.ts +20 -0
  174. package/dist/src/pil/config.js +35 -0
  175. package/dist/src/pil/discovery-types.d.ts +32 -9
  176. package/dist/src/pil/discovery.d.ts +3 -3
  177. package/dist/src/pil/discovery.js +138 -244
  178. package/dist/src/pil/index.d.ts +1 -1
  179. package/dist/src/pil/index.js +1 -1
  180. package/dist/src/pil/layer1-intent.d.ts +9 -1
  181. package/dist/src/pil/layer1-intent.js +62 -7
  182. package/dist/src/pil/layer1-intent.test.js +112 -2
  183. package/dist/src/pil/layer15-context-scan.js +1 -1
  184. package/dist/src/pil/layer16-clarity.d.ts +21 -25
  185. package/dist/src/pil/layer16-clarity.js +52 -88
  186. package/dist/src/pil/layer18-acceptance.d.ts +13 -3
  187. package/dist/src/pil/layer18-acceptance.js +1 -75
  188. package/dist/src/pil/layer2-personality.js +7 -8
  189. package/dist/src/pil/layer2_5-ponytail.d.ts +2 -0
  190. package/dist/src/pil/layer2_5-ponytail.js +41 -0
  191. package/dist/src/pil/layer3-ee-injection.js +180 -14
  192. package/dist/src/pil/layer4-gsd.js +22 -8
  193. package/dist/src/pil/layer5-context.d.ts +1 -0
  194. package/dist/src/pil/layer5-context.js +26 -11
  195. package/dist/src/pil/layer6-output.js +23 -5
  196. package/dist/src/pil/llm-classify.d.ts +11 -0
  197. package/dist/src/pil/llm-classify.js +196 -3
  198. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  199. package/dist/src/pil/native-capabilities-workbook.js +4 -3
  200. package/dist/src/pil/pipeline.js +15 -1
  201. package/dist/src/pil/response-tools.d.ts +16 -0
  202. package/dist/src/pil/response-tools.js +41 -0
  203. package/dist/src/pil/schema.d.ts +8 -0
  204. package/dist/src/pil/schema.js +24 -3
  205. package/dist/src/pil/task-tier-map.js +7 -7
  206. package/dist/src/pil/types.d.ts +9 -3
  207. package/dist/src/product-loop/__tests__/discovery-interview.test.js +103 -1
  208. package/dist/src/product-loop/__tests__/gather-selectable-alts.test.js +34 -0
  209. package/dist/src/product-loop/__tests__/sprint-self-verify.test.js +12 -12
  210. package/dist/src/product-loop/discovery-interview.d.ts +20 -0
  211. package/dist/src/product-loop/discovery-interview.js +121 -7
  212. package/dist/src/product-loop/gather.js +19 -5
  213. package/dist/src/product-loop/loop-driver.js +2 -2
  214. package/dist/src/product-loop/sprint-self-verify.js +2 -2
  215. package/dist/src/providers/__tests__/reasoning-roundtrip.test.js +12 -0
  216. package/dist/src/providers/auth/__tests__/gemini-oauth.test.d.ts +1 -5
  217. package/dist/src/providers/auth/__tests__/gemini-oauth.test.js +1 -5
  218. package/dist/src/providers/auth/gcloud.d.ts +28 -0
  219. package/dist/src/providers/auth/gcloud.js +102 -0
  220. package/dist/src/providers/auth/gemini-oauth.d.ts +46 -19
  221. package/dist/src/providers/auth/gemini-oauth.js +292 -105
  222. package/dist/src/providers/auth/grok-oauth.d.ts +1 -1
  223. package/dist/src/providers/auth/grok-oauth.js +1 -1
  224. package/dist/src/providers/auth/registry.js +28 -6
  225. package/dist/src/providers/gemini.d.ts +1 -1
  226. package/dist/src/providers/gemini.js +10 -3
  227. package/dist/src/providers/keychain.d.ts +2 -2
  228. package/dist/src/providers/keychain.js +20 -2
  229. package/dist/src/providers/openai.js +5 -1
  230. package/dist/src/providers/runtime.d.ts +1 -1
  231. package/dist/src/providers/runtime.js +11 -2
  232. package/dist/src/providers/siliconflow-sse-repair.js +1 -1
  233. package/dist/src/providers/strategies/google.strategy.d.ts +9 -2
  234. package/dist/src/providers/strategies/google.strategy.js +159 -9
  235. package/dist/src/providers/strategies/thinking-mode.js +19 -6
  236. package/dist/src/providers/types.d.ts +1 -1
  237. package/dist/src/router/decide.test.js +40 -8
  238. package/dist/src/router/step-router.d.ts +20 -0
  239. package/dist/src/router/step-router.js +73 -0
  240. package/dist/src/self-qa/agentic-loop.js +30 -21
  241. package/dist/src/self-qa/orchestrator.js +5 -5
  242. package/dist/src/self-qa/scenario-planner.js +1 -1
  243. package/dist/src/self-qa/spec-emitter.js +4 -4
  244. package/dist/src/storage/__tests__/hierarchical-session.test.d.ts +1 -0
  245. package/dist/src/storage/__tests__/hierarchical-session.test.js +161 -0
  246. package/dist/src/storage/__tests__/sweep-stale-pending.test.js +2 -2
  247. package/dist/src/storage/index.d.ts +1 -1
  248. package/dist/src/storage/index.js +1 -1
  249. package/dist/src/storage/migrations.js +13 -1
  250. package/dist/src/storage/transcript-response-entry.test.js +18 -5
  251. package/dist/src/storage/transcript-view.js +7 -1
  252. package/dist/src/storage/transcript.d.ts +3 -0
  253. package/dist/src/storage/transcript.js +254 -73
  254. package/dist/src/storage/ui-interaction-log.d.ts +17 -0
  255. package/dist/src/storage/usage.js +22 -5
  256. package/dist/src/tools/__tests__/native-tools.test.js +6 -0
  257. package/dist/src/tools/bash.d.ts +36 -23
  258. package/dist/src/tools/bash.js +59 -301
  259. package/dist/src/tools/bash.test.js +2 -257
  260. package/dist/src/tools/file-tracker.d.ts +5 -0
  261. package/dist/src/tools/file-tracker.js +14 -0
  262. package/dist/src/tools/file.js +2 -0
  263. package/dist/src/tools/git-safety.d.ts +38 -1
  264. package/dist/src/tools/git-safety.js +94 -4
  265. package/dist/src/tools/git-safety.test.js +45 -1
  266. package/dist/src/tools/native-tools.d.ts +1 -1
  267. package/dist/src/tools/native-tools.js +66 -1
  268. package/dist/src/tools/registry-bash-empty-command.test.js +4 -3
  269. package/dist/src/tools/registry-git-safety.test.js +17 -6
  270. package/dist/src/tools/registry.d.ts +6 -0
  271. package/dist/src/tools/registry.js +215 -13
  272. package/dist/src/types/index.d.ts +8 -2
  273. package/dist/src/ui/app.d.ts +1 -0
  274. package/dist/src/ui/app.js +0 -0
  275. package/dist/src/ui/components/council-question-card.js +1 -0
  276. package/dist/src/ui/components/message-view.js +37 -3
  277. package/dist/src/ui/components/structured-response-view.js +7 -0
  278. package/dist/src/ui/components/task-list-panel.js +3 -12
  279. package/dist/src/ui/containers/chat-feed.d.ts +40 -0
  280. package/dist/src/ui/containers/chat-feed.js +66 -0
  281. package/dist/src/ui/containers/modals-layer.d.ts +87 -0
  282. package/dist/src/ui/containers/modals-layer.js +18 -0
  283. package/dist/src/ui/slash/__tests__/menu-parity.test.d.ts +1 -0
  284. package/dist/src/ui/slash/__tests__/menu-parity.test.js +1 -0
  285. package/dist/src/ui/slash/__tests__/ponytail.test.d.ts +1 -0
  286. package/dist/src/ui/slash/__tests__/ponytail.test.js +37 -0
  287. package/dist/src/ui/slash/expand.js +14 -1
  288. package/dist/src/ui/slash/export.js +16 -1
  289. package/dist/src/ui/slash/menu-items.js +1 -0
  290. package/dist/src/ui/slash/ponytail.d.ts +2 -0
  291. package/dist/src/ui/slash/ponytail.js +19 -0
  292. package/dist/src/ui/status-bar/store.js +0 -1
  293. package/dist/src/ui/status-bar/store.test.js +2 -2
  294. package/dist/src/ui/use-app-logic.d.ts +26 -0
  295. package/dist/src/ui/use-app-logic.js +0 -0
  296. package/dist/src/ui/utils/relaunch.js +1 -1
  297. package/dist/src/ui/utils/text.d.ts +11 -0
  298. package/dist/src/ui/utils/text.js +21 -1
  299. package/dist/src/ui/utils/text.test.js +25 -1
  300. package/dist/src/ui/utils/tools.js +3 -1
  301. package/dist/src/usage/cost-log.js +2 -2
  302. package/dist/src/usage/estimator.d.ts +14 -0
  303. package/dist/src/usage/estimator.js +22 -0
  304. package/dist/src/utils/__tests__/compaction-caps.test.d.ts +21 -0
  305. package/dist/src/utils/__tests__/compaction-caps.test.js +187 -0
  306. package/dist/src/utils/__tests__/llm-deadline-abort.test.d.ts +1 -0
  307. package/dist/src/utils/__tests__/llm-deadline-abort.test.js +33 -0
  308. package/dist/src/utils/__tests__/llm-deadline.test.js +16 -4
  309. package/dist/src/utils/__tests__/logger.test.d.ts +1 -0
  310. package/dist/src/utils/__tests__/logger.test.js +115 -0
  311. package/dist/src/utils/__tests__/settings-agent-first.test.d.ts +1 -0
  312. package/dist/src/utils/__tests__/settings-agent-first.test.js +48 -0
  313. package/dist/src/utils/install-manager.d.ts +1 -0
  314. package/dist/src/utils/install-manager.js +76 -7
  315. package/dist/src/utils/install-manager.test.js +43 -1
  316. package/dist/src/utils/llm-deadline.d.ts +9 -1
  317. package/dist/src/utils/llm-deadline.js +31 -2
  318. package/dist/src/utils/logger.d.ts +28 -0
  319. package/dist/src/utils/logger.js +171 -0
  320. package/dist/src/utils/permission-mode.d.ts +33 -0
  321. package/dist/src/utils/permission-mode.js +164 -3
  322. package/dist/src/utils/permission-mode.test.js +92 -1
  323. package/dist/src/utils/settings.d.ts +36 -32
  324. package/dist/src/utils/settings.js +151 -123
  325. package/dist/src/utils/update-checker.test.js +5 -1
  326. package/package.json +1 -1
@@ -13,6 +13,7 @@
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
17
  import { getProviderCapabilities } from "../providers/capabilities.js";
17
18
  import { resolveModelRuntime } from "../providers/runtime.js";
18
19
  const LLM_CLASSIFY_TIMEOUT_MS = 2500;
@@ -240,14 +241,14 @@ export function createLlmClassifier(factory, modelId) {
240
241
  let text = "";
241
242
  let reasoningText = "";
242
243
  const partCounts = {};
243
- const debug = process.env["MUONROI_DEBUG_PIL_CLASSIFY"] === "1";
244
+ const debug = process.env.MUONROI_DEBUG_PIL_CLASSIFY === "1";
244
245
  for await (const part of result.fullStream) {
245
246
  if (debug)
246
247
  partCounts[part.type] = (partCounts[part.type] ?? 0) + 1;
247
248
  if (part.type === "text-delta")
248
- text += part.text ?? "";
249
+ text += part.textDelta ?? part.text ?? "";
249
250
  else if (part.type === "reasoning-delta")
250
- reasoningText += part.text ?? "";
251
+ reasoningText += part.textDelta ?? part.text ?? "";
251
252
  }
252
253
  if (debug) {
253
254
  console.error(`[pil.llm-classify] raw(${modelId}) maxOut=${dropMaxTokens ? "dropped" : maxOut} ` +
@@ -271,4 +272,196 @@ export function createLlmClassifier(factory, modelId) {
271
272
  }
272
273
  };
273
274
  }
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
+ 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
+ "Analyze the user's prompt and select one of the following ACTIONS:\n" +
377
+ '- "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' +
378
+ '- "ROTATE_SESSION": The user is starting a completely new topic or task unrelated to the active discussion (e.g. "let\'s switch to writing a python script", "forget the previous bug, show me how to..."). OR, if the session size (metadata) exceeds the rotation threshold and the active task is completed or the prompt starts a new focus, choose ROTATE_SESSION to prune/summarize the context.\n' +
379
+ '- "SPAWN_SUB_SESSION": The user wants to execute a multi-step task (e.g. "write tests for X and debug it", "refactor the storage layer", "implement feature Y", "fix all compile errors"). This requires running multiple tools (file edits, bash commands, searches).\n\n' +
380
+ "Response format: Reply with exactly one comma-separated line containing:\n" +
381
+ "<ACTION>,<CONFIDENCE>,<REASON>\n\n" +
382
+ "Examples:\n" +
383
+ '- "DIRECT_ANSWER,0.95,Simple explanation of how the DB migration works."\n' +
384
+ '- "ROTATE_SESSION,0.90,Complete shift to a different project/language."\n' +
385
+ '- "ROTATE_SESSION,0.95,Session size exceeds threshold and current request starts a new task."\n' +
386
+ '- "SPAWN_SUB_SESSION,0.98,Requires writing a test suite and fixing multiple files to get it green."\n' +
387
+ "No other text, only the comma-separated line.";
388
+ 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
+ }
394
+ const controller = new AbortController();
395
+ let timer;
396
+ try {
397
+ // Zero-hardcode: query models catalog for a cheap fast-tier model under the same provider.
398
+ const info = getModelInfo(modelId);
399
+ const provider = info?.provider;
400
+ const fastModel = provider ? getModelByTier("fast", provider) || getModelByTier("balanced", provider) : undefined;
401
+ const classificationModelId = fastModel?.id ?? modelId;
402
+ const runtime = resolveModelRuntime(factory, classificationModelId);
403
+ const isReasoning = runtime.modelInfo?.reasoning === true;
404
+ timer = setTimeout(() => controller.abort(), isReasoning ? REASONING_CLASSIFY_TIMEOUT_MS : LLM_CLASSIFY_TIMEOUT_MS);
405
+ const combinedSignal = signal
406
+ ? (AbortSignal.any?.([signal, controller.signal]) ?? controller.signal)
407
+ : controller.signal;
408
+ const dropMaxTokens = runtime.unsupportedParams?.includes("maxOutputTokens") === true;
409
+ const maxOut = isReasoning ? REASONING_MAX_OUTPUT_TOKENS : NONREASONING_MAX_OUTPUT_TOKENS;
410
+ let providerOptions = runtime.providerOptions;
411
+ if (isReasoning && runtime.modelInfo?.supportsReasoningEffort && runtime.modelInfo.provider) {
412
+ const lowEffort = getProviderCapabilities(runtime.modelInfo.provider).buildProviderOptions({
413
+ model: runtime.model,
414
+ reasoningEffort: "low",
415
+ });
416
+ providerOptions = mergeProviderOptions(runtime.providerOptions, lowEffort);
417
+ }
418
+ let promptWithContext = prompt.slice(0, 1000);
419
+ if (contextInfo) {
420
+ promptWithContext =
421
+ `[SESSION METADATA]\n` +
422
+ `Current session size: ${contextInfo.currentChars} characters.\n` +
423
+ `Rotation threshold: ${contextInfo.threshold} characters.\n\n` +
424
+ `[USER PROMPT]\n${promptWithContext}`;
425
+ }
426
+ const result = streamText({
427
+ model: runtime.model,
428
+ abortSignal: combinedSignal,
429
+ system: ROUTER_SYSTEM_PROMPT,
430
+ prompt: promptWithContext,
431
+ ...(dropMaxTokens ? {} : { maxOutputTokens: maxOut }),
432
+ ...(providerOptions ? { providerOptions } : {}),
433
+ });
434
+ let text = "";
435
+ let reasoningText = "";
436
+ for await (const part of result.fullStream) {
437
+ if (part.type === "text-delta")
438
+ text += part.textDelta ?? part.text ?? "";
439
+ else if (part.type === "reasoning-delta")
440
+ reasoningText += part.textDelta ?? part.text ?? "";
441
+ }
442
+ const rawResult = text.trim() || reasoningText.trim();
443
+ if (!rawResult)
444
+ return null;
445
+ const clean = rawResult.replace(/[`*"]/g, "").trim();
446
+ const firstLine = clean.split(/\r?\n/)[0] ?? "";
447
+ const parts = firstLine.split(",");
448
+ if (parts.length < 2)
449
+ return null;
450
+ const action = parts[0].trim().toUpperCase();
451
+ const confidence = Number(parts[1].trim()) || 0.8;
452
+ const reason = parts.slice(2).join(",").trim() || "No reason given";
453
+ if (action === "DIRECT_ANSWER" || action === "ROTATE_SESSION" || action === "SPAWN_SUB_SESSION") {
454
+ return { action, confidence, reason };
455
+ }
456
+ return null;
457
+ }
458
+ catch (err) {
459
+ console.error(`[pil.llm-classify] classifySubSessionAction failed: ${err?.message}`);
460
+ return null;
461
+ }
462
+ finally {
463
+ if (timer)
464
+ clearTimeout(timer);
465
+ }
466
+ }
274
467
  //# sourceMappingURL=llm-classify.js.map
@@ -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`). 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 \u2014 semantic recall over the Experience Engine brain. 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\". Cheaper than re-reading large files you already saw.\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- ee_health (brain reachable?), usage_forensics (why did it cost/fail?), lsp_query (semantic code intel), setup_guide (how to install/set up), selfverify_* (self-QA harness) \u2014 native self-diagnostics to reach for when something went wrong.\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\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
@@ -27,15 +27,16 @@ export const NATIVE_CAPABILITIES = `[NATIVE CAPABILITIES — you are an agent ru
27
27
 
28
28
  TOOLS (call directly):
29
29
  - read_file, grep — read/search source. Prefer a targeted read over broad greps.
30
- - bash — 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\`). Use background=true for servers/watchers, then process_logs / process_list / process_stop.
30
+ - bash — 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\`) — 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.
31
31
  - write_file, edit_file — must read a file before you overwrite/edit it.
32
- - ee_query — semantic recall over the Experience Engine brain. 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". Cheaper than re-reading large files you already saw.
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
+ - 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
+ - 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.
33
35
 
34
36
  EXPERIENCE ENGINE — record / recall / feedback (HIGHEST priority for learning; all NATIVE in-process tools):
35
37
  - 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.
36
38
  - 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.
37
39
  - On an ERROR, a FAILED verify/test, or after FINISHING a non-trivial task: recall first (ee_query), then record your verdict (ee_feedback) — this is how the CLI accumulates senior-level judgement. Prefer this loop over guessing.
38
- - ee_health (brain reachable?), usage_forensics (why did it cost/fail?), lsp_query (semantic code intel), setup_guide (how to install/set up), selfverify_* (self-QA harness) — native self-diagnostics to reach for when something went wrong.
39
40
 
40
41
  SUB-AGENTS (delegate instead of doing everything yourself):
41
42
  - task(agent="explore", ...) — 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 — steps are the dominant cost).
@@ -14,6 +14,7 @@
14
14
  * path returns a pristine context (Pitfall 4 from RESEARCH.md).
15
15
  */
16
16
  import { getCachedServerBaseUrl } from "../ee/auth.js";
17
+ import { getWhoAmIProfile, outputStyleFromProfile } from "../ee/bridge.js";
17
18
  import { getCachedEEClientMode } from "../ee/client-mode.js";
18
19
  import { classifyEeError, logEeFailure } from "../utils/ee-logger.js";
19
20
  import { DEFAULT_TOKEN_BUDGET } from "./budget.js";
@@ -21,6 +22,7 @@ import { appendPilLog } from "./budget-log.js";
21
22
  import { isDiscoveryEnabled } from "./config.js";
22
23
  import { scoreComplexitySize } from "./layer1_5-complexity-size.js";
23
24
  import { layer1Intent } from "./layer1-intent.js";
25
+ import { layer2_5Ponytail } from "./layer2_5-ponytail.js";
24
26
  import { layer2Personality } from "./layer2-personality.js";
25
27
  import { layer3EeInjection, surfaceCompactionArtifacts } from "./layer3-ee-injection.js";
26
28
  import { layer4Gsd } from "./layer4-gsd.js";
@@ -66,6 +68,7 @@ function pipelineTimeoutMs() {
66
68
  }
67
69
  const SKIPPED_LAYERS = [
68
70
  { timingName: "layer2-personality", deltaName: "personality-adaptation" },
71
+ { timingName: "layer2_5-ponytail", deltaName: "ponytail-mode" },
69
72
  { timingName: "layer3-ee-injection", deltaName: "ee-experience-injection" },
70
73
  { timingName: "layer4-gsd-structuring", deltaName: "gsd-workflow-structuring" },
71
74
  { timingName: "layer5-context-enrichment", deltaName: "context-enrichment" },
@@ -85,7 +88,11 @@ async function runLayers(ctx, options) {
85
88
  timings.push({ name, ms });
86
89
  layerSnapshots.push({ name, charsBefore, charsAfter, charsDelta: charsAfter - charsBefore, durationMs: ms });
87
90
  }
88
- await timed("layer1-intent", (c) => layer1Intent(c, { llmFallback: options?.llmFallback }));
91
+ // WhoAmI v4.0: derive the output-style baseline once from the device-local profile
92
+ // (cached, fail-open → null when EE/profile absent or privacy off). Passed into
93
+ // layer1 so the hot layer stays off the EE/profile import path (arch boundary).
94
+ const profileStyleBaseline = outputStyleFromProfile(getWhoAmIProfile());
95
+ await timed("layer1-intent", (c) => layer1Intent(c, { llmFallback: options?.llmFallback, profileStyleBaseline }));
89
96
  // Layer 1.5: deterministic complexity-size classification. Pure heuristic,
90
97
  // no LLM call, no network. Consumed by 4B (step ceiling matrix) and 4A
91
98
  // (scope-reminder cadence K). Mirrored into _intentTrace for forensics.
@@ -122,6 +129,11 @@ async function runLayers(ctx, options) {
122
129
  const discovery = await runDiscovery(ctx.raw, l1Result, process.cwd(), options?.interactionHandler ?? null, ctx.sessionId ?? null, options?.clarificationProposer ?? null, options?.recentTurnsSummary ?? null);
123
130
  ctx = { ...ctx, _discoveryResult: discovery };
124
131
  if (discovery.interviewed && discovery.accepted) {
132
+ // Build prefix with both the structured summary and the raw interview transcript
133
+ const transcriptLines = discovery.interviewTranscript.length > 0
134
+ ? "\n[Discovery Interview]\n" +
135
+ discovery.interviewTranscript.map((qa) => `Q: ${qa.question}\nA: ${qa.answer}`).join("\n")
136
+ : "";
125
137
  const discoveryPrefix = [
126
138
  `[Discovery] Intent: ${discovery.intentStatement}`,
127
139
  `[Discovery] Outcome: ${discovery.outcome}`,
@@ -129,6 +141,7 @@ async function runLayers(ctx, options) {
129
141
  discovery.feasibilityWarnings.length > 0
130
142
  ? `[Discovery] Warnings: ${discovery.feasibilityWarnings.join("; ")}`
131
143
  : "",
144
+ transcriptLines,
132
145
  ]
133
146
  .filter(Boolean)
134
147
  .join("\n");
@@ -145,6 +158,7 @@ async function runLayers(ctx, options) {
145
158
  }
146
159
  if (ctx.taskType !== null) {
147
160
  await timed("layer2-personality", layer2Personality);
161
+ await timed("layer2_5-ponytail", layer2_5Ponytail);
148
162
  // Issue #2: meta-analysis turns used to skip layer3 (EE recall) + layer5
149
163
  // (context) to cut overhead — but that starved exactly the self-evaluation
150
164
  // turns where behavioral/principle recall matters most. Run the full
@@ -116,4 +116,20 @@ export declare function shouldHaltOnResponseTool(steps: ReadonlyArray<{
116
116
  }>;
117
117
  }> | undefined): boolean;
118
118
  export declare function buildResponseTools(taskType: string): ToolSet;
119
+ /**
120
+ * Detect schema-mismatch in a buffered structured response and normalize
121
+ * taskType to 'general' when the model called a typed respond_<task> tool
122
+ * but sent a free-form `{ response: "..." }` payload.
123
+ *
124
+ * This happens when the tool was unavailable in the current turn's tool set
125
+ * (Zod didn't enforce the schema), so the model fell back to the general shape
126
+ * it learned from prior turns. The typed TUI renderer (e.g. case "analyze")
127
+ * would display an empty box because the expected schema fields (e.g. findings[])
128
+ * are absent. Normalizing to 'general' routes the payload to the plain-markdown
129
+ * renderer.
130
+ *
131
+ * Session 48d22fe436f6: respond_analyze called with { response: "..." } —
132
+ * analyze renderer showed empty findings list — answer swallowed.
133
+ */
134
+ export declare function normalizeStructuredResponseTaskType(taskType: string, data: Record<string, unknown>): string;
119
135
  export { AnalyzeSchema, DebugSchema, DocsSchema, GeneralSchema, GenerateSchema, PlanSchema, RefactorSchema };
@@ -157,5 +157,46 @@ export function buildResponseTools(taskType) {
157
157
  },
158
158
  };
159
159
  }
160
+ /**
161
+ * Detect schema-mismatch in a buffered structured response and normalize
162
+ * taskType to 'general' when the model called a typed respond_<task> tool
163
+ * but sent a free-form `{ response: "..." }` payload.
164
+ *
165
+ * This happens when the tool was unavailable in the current turn's tool set
166
+ * (Zod didn't enforce the schema), so the model fell back to the general shape
167
+ * it learned from prior turns. The typed TUI renderer (e.g. case "analyze")
168
+ * would display an empty box because the expected schema fields (e.g. findings[])
169
+ * are absent. Normalizing to 'general' routes the payload to the plain-markdown
170
+ * renderer.
171
+ *
172
+ * Session 48d22fe436f6: respond_analyze called with { response: "..." } —
173
+ * analyze renderer showed empty findings list — answer swallowed.
174
+ */
175
+ export function normalizeStructuredResponseTaskType(taskType, data) {
176
+ if (taskType === "general")
177
+ return taskType;
178
+ const hasResponseField = typeof data.response === "string" && data.response.trim().length > 0;
179
+ if (!hasResponseField)
180
+ return taskType;
181
+ const schemaKeyMissing = (() => {
182
+ switch (taskType) {
183
+ case "analyze":
184
+ return !Array.isArray(data.findings);
185
+ case "debug":
186
+ return typeof data.root_cause !== "string";
187
+ case "plan":
188
+ return !Array.isArray(data.steps);
189
+ case "refactor":
190
+ return !Array.isArray(data.changes);
191
+ case "documentation":
192
+ return typeof data.content !== "string";
193
+ case "generate":
194
+ return !Array.isArray(data.files);
195
+ default:
196
+ return false;
197
+ }
198
+ })();
199
+ return schemaKeyMissing ? "general" : taskType;
200
+ }
160
201
  export { AnalyzeSchema, DebugSchema, DocsSchema, GeneralSchema, GenerateSchema, PlanSchema, RefactorSchema };
161
202
  //# sourceMappingURL=response-tools.js.map
@@ -120,11 +120,15 @@ export declare const PipelineContextSchema: z.ZodObject<{
120
120
  t0_principles: z.ZodArray<z.ZodObject<{
121
121
  text: z.ZodString;
122
122
  score: z.ZodNumber;
123
+ id: z.ZodOptional<z.ZodString>;
124
+ collection: z.ZodOptional<z.ZodString>;
123
125
  }, z.core.$strip>>;
124
126
  t1_rules: z.ZodArray<z.ZodString>;
125
127
  t2_patterns: z.ZodArray<z.ZodObject<{
126
128
  text: z.ZodString;
127
129
  score: z.ZodNumber;
130
+ id: z.ZodOptional<z.ZodString>;
131
+ collection: z.ZodOptional<z.ZodString>;
128
132
  }, z.core.$strip>>;
129
133
  retrieval_skipped_reason: z.ZodNullable<z.ZodString>;
130
134
  }, z.core.$strip>>>;
@@ -163,11 +167,15 @@ export declare const PilContextResponseSchema: z.ZodObject<{
163
167
  t0_principles: z.ZodArray<z.ZodObject<{
164
168
  text: z.ZodString;
165
169
  score: z.ZodNumber;
170
+ id: z.ZodOptional<z.ZodString>;
171
+ collection: z.ZodOptional<z.ZodString>;
166
172
  }, z.core.$strip>>;
167
173
  t1_rules: z.ZodArray<z.ZodString>;
168
174
  t2_patterns: z.ZodArray<z.ZodObject<{
169
175
  text: z.ZodString;
170
176
  score: z.ZodNumber;
177
+ id: z.ZodOptional<z.ZodString>;
178
+ collection: z.ZodOptional<z.ZodString>;
171
179
  }, z.core.$strip>>;
172
180
  retrieval_skipped_reason: z.ZodNullable<z.ZodString>;
173
181
  cache_hit: z.ZodBoolean;
@@ -73,15 +73,36 @@ export const PipelineContextSchema = z.object({
73
73
  t1Rules: z.array(z.string()).optional(),
74
74
  _brainData: z
75
75
  .object({
76
- t0_principles: z.array(z.object({ text: z.string(), score: z.number() })),
76
+ // id/collection optional — mirrors ScoredText (PIL schema_version 1.1+).
77
+ t0_principles: z.array(z.object({
78
+ text: z.string(),
79
+ score: z.number(),
80
+ id: z.string().optional(),
81
+ collection: z.string().optional(),
82
+ })),
77
83
  t1_rules: z.array(z.string()),
78
- t2_patterns: z.array(z.object({ text: z.string(), score: z.number() })),
84
+ t2_patterns: z.array(z.object({
85
+ text: z.string(),
86
+ score: z.number(),
87
+ id: z.string().optional(),
88
+ collection: z.string().optional(),
89
+ })),
79
90
  retrieval_skipped_reason: z.string().nullable(),
80
91
  })
81
92
  .nullable()
82
93
  .optional(),
83
94
  });
84
- const ScoredText = z.object({ text: z.string(), score: z.number() });
95
+ // id + collection are optional (PIL schema_version 1.1+): present when the brain
96
+ // can attribute the retrieved point, which lets the unified injection path record
97
+ // it as rateable recall debt resolvable via ee_feedback(id, collection, verdict).
98
+ // Older servers omit them — they MUST be declared here regardless, because a bare
99
+ // z.object() strips undeclared keys at parse, which would silently drop the ids.
100
+ const ScoredText = z.object({
101
+ text: z.string(),
102
+ score: z.number(),
103
+ id: z.string().optional(),
104
+ collection: z.string().optional(),
105
+ });
85
106
  export const PilContextResponseSchema = z
86
107
  .object({
87
108
  // Classification
@@ -41,20 +41,20 @@ export function taskTypeToTier(taskType) {
41
41
  export function taskTypeToMaxTokens(taskType) {
42
42
  switch (taskType) {
43
43
  case "analyze":
44
- return 2_048;
44
+ return 4_096;
45
45
  case "documentation":
46
- return 3_072;
46
+ return 4_096;
47
47
  case "debug":
48
- return 3_072;
48
+ return 6_144;
49
49
  case "refactor":
50
- return 4_096;
50
+ return 6_144;
51
51
  case "plan":
52
- return 5_120;
52
+ return 8_192;
53
53
  case "generate":
54
54
  case "build":
55
- return 8_192;
55
+ return 12_288;
56
56
  default:
57
- return 2_048; // conversational — keep short
57
+ return 4_096; // conversational
58
58
  }
59
59
  }
60
60
  /**
@@ -110,8 +110,10 @@ export interface PipelineContext {
110
110
  * behavioral reflex status. Layer 6 appends them as MANDATORY RULES to the
111
111
  * output suffix so the model treats them as instructions, not just context.
112
112
  *
113
- * TODO(WhoAmI): when EE v4.0 Who Am I is implemented, merge project-level
114
- * t1Rules with user-level personality directives from the profile model.
113
+ * TODO(WhoAmI): user-level personality is now available via ../ee/who-am-i.ts
114
+ * (getWhoAmIProfile). A future enhancement can merge these project-level t1Rules
115
+ * with user-level personality directives in the Layer 6 suffix; today the profile
116
+ * is consumed as the L1 outputStyle baseline rather than as MANDATORY RULES.
115
117
  */
116
118
  t1Rules?: string[];
117
119
  /**
@@ -174,7 +176,7 @@ export interface IntentDetectionTrace {
174
176
  /** Pass 4 LLM fallback returned a parseable result. */
175
177
  pass4LlmSucceeded?: boolean;
176
178
  /** How the final outputStyle was resolved. */
177
- styleSource: "explicit-regex" | "brain-unified" | "brain-legacy" | "chitchat-default" | "classifier-default" | "none";
179
+ styleSource: "explicit-regex" | "brain-unified" | "brain-legacy" | "whoami-profile" | "chitchat-default" | "classifier-default" | "none";
178
180
  /** Final taskType emitted by Layer 1. */
179
181
  finalTaskType: string | null;
180
182
  /** Final confidence emitted by Layer 1. */
@@ -192,11 +194,15 @@ export interface BrainData {
192
194
  t0_principles: Array<{
193
195
  text: string;
194
196
  score: number;
197
+ id?: string;
198
+ collection?: string;
195
199
  }>;
196
200
  t1_rules: string[];
197
201
  t2_patterns: Array<{
198
202
  text: string;
199
203
  score: number;
204
+ id?: string;
205
+ collection?: string;
200
206
  }>;
201
207
  retrieval_skipped_reason: string | null;
202
208
  }