muonroi-cli 1.4.1 → 1.5.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 (172) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +122 -122
  3. package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
  4. package/dist/src/agent-harness/__tests__/mock-model.spec.js +48 -1
  5. package/dist/src/agent-harness/mock-model.d.ts +11 -0
  6. package/dist/src/agent-harness/mock-model.js +21 -0
  7. package/dist/src/cli/cost-forensics.js +12 -12
  8. package/dist/src/council/__tests__/clarification-prompt.test.js +51 -0
  9. package/dist/src/council/__tests__/clarifier-ready-gate.test.js +32 -0
  10. package/dist/src/council/__tests__/decisions-lock.test.js +17 -1
  11. package/dist/src/council/__tests__/oauth-reachable.test.d.ts +1 -0
  12. package/dist/src/council/__tests__/oauth-reachable.test.js +31 -0
  13. package/dist/src/council/__tests__/parse-outcome-fallback.test.js +11 -0
  14. package/dist/src/council/clarifier.js +9 -1
  15. package/dist/src/council/debate.js +5 -1
  16. package/dist/src/council/decisions-lock.js +3 -3
  17. package/dist/src/council/index.js +12 -5
  18. package/dist/src/council/leader.d.ts +0 -17
  19. package/dist/src/council/leader.js +22 -15
  20. package/dist/src/council/planner.js +1 -1
  21. package/dist/src/council/prompts.js +63 -57
  22. package/dist/src/council/types.d.ts +7 -0
  23. package/dist/src/ee/__tests__/ee-onboarding.test.d.ts +1 -0
  24. package/dist/src/ee/__tests__/ee-onboarding.test.js +32 -0
  25. package/dist/src/ee/auth.d.ts +9 -0
  26. package/dist/src/ee/auth.js +19 -0
  27. package/dist/src/ee/ee-onboarding.d.ts +5 -0
  28. package/dist/src/ee/ee-onboarding.js +76 -0
  29. package/dist/src/generated/version.d.ts +1 -1
  30. package/dist/src/generated/version.js +1 -1
  31. package/dist/src/headless/output.js +6 -4
  32. package/dist/src/headless/output.test.js +4 -3
  33. package/dist/src/index.js +20 -1
  34. package/dist/src/mcp/__tests__/auto-setup.test.js +74 -0
  35. package/dist/src/mcp/__tests__/client-pool.spec.d.ts +1 -0
  36. package/dist/src/mcp/__tests__/client-pool.spec.js +98 -0
  37. package/dist/src/mcp/__tests__/parallel-build.spec.d.ts +1 -0
  38. package/dist/src/mcp/__tests__/parallel-build.spec.js +67 -0
  39. package/dist/src/mcp/__tests__/smart-filter.test.js +56 -0
  40. package/dist/src/mcp/auto-setup.js +56 -2
  41. package/dist/src/mcp/client-pool.d.ts +46 -0
  42. package/dist/src/mcp/client-pool.js +212 -0
  43. package/dist/src/mcp/oauth-callback.js +2 -2
  44. package/dist/src/mcp/parse-headers.test.js +14 -14
  45. package/dist/src/mcp/runtime.d.ts +28 -0
  46. package/dist/src/mcp/runtime.js +117 -51
  47. package/dist/src/mcp/self-verify-runner.d.ts +14 -0
  48. package/dist/src/mcp/self-verify-runner.js +38 -0
  49. package/dist/src/mcp/setup-guide-text.d.ts +9 -0
  50. package/dist/src/mcp/setup-guide-text.js +84 -0
  51. package/dist/src/mcp/smart-filter.js +49 -0
  52. package/dist/src/mcp/smoke.test.js +43 -43
  53. package/dist/src/mcp/tools-server.d.ts +7 -0
  54. package/dist/src/mcp/tools-server.js +19 -22
  55. package/dist/src/models/catalog.json +349 -349
  56. package/dist/src/ops/__tests__/doctor-ee-health.test.js +21 -0
  57. package/dist/src/ops/doctor.d.ts +3 -2
  58. package/dist/src/ops/doctor.js +47 -11
  59. package/dist/src/ops/doctor.test.js +4 -3
  60. package/dist/src/orchestrator/__tests__/mcp-capability-block.test.d.ts +1 -0
  61. package/dist/src/orchestrator/__tests__/mcp-capability-block.test.js +39 -0
  62. package/dist/src/orchestrator/__tests__/project-stack.test.d.ts +1 -0
  63. package/dist/src/orchestrator/__tests__/project-stack.test.js +65 -0
  64. package/dist/src/orchestrator/batch-turn-runner.js +7 -11
  65. package/dist/src/orchestrator/message-processor.js +57 -27
  66. package/dist/src/orchestrator/orchestrator.js +26 -0
  67. package/dist/src/orchestrator/prompts.d.ts +51 -0
  68. package/dist/src/orchestrator/prompts.js +257 -134
  69. package/dist/src/orchestrator/scope-ceiling.js +6 -1
  70. package/dist/src/orchestrator/stream-runner.js +20 -15
  71. package/dist/src/orchestrator/text-tool-call-detector.test.js +13 -13
  72. package/dist/src/pil/__tests__/clarity-gate.test.js +24 -215
  73. package/dist/src/pil/__tests__/config.test.js +1 -17
  74. package/dist/src/pil/__tests__/discovery.test.js +144 -11
  75. package/dist/src/pil/__tests__/layer1-intent-trace.test.js +7 -2
  76. package/dist/src/pil/__tests__/layer1-intent.test.js +3 -0
  77. package/dist/src/pil/__tests__/layer16-clarity.test.js +32 -116
  78. package/dist/src/pil/__tests__/layer4-gsd.test.js +37 -0
  79. package/dist/src/pil/__tests__/layer6-output.test.js +137 -18
  80. package/dist/src/pil/__tests__/llm-classify.test.js +49 -2
  81. package/dist/src/pil/agent-operating-contract.d.ts +1 -1
  82. package/dist/src/pil/agent-operating-contract.js +2 -0
  83. package/dist/src/pil/agent-operating-contract.test.js +7 -2
  84. package/dist/src/pil/cheap-model-playbook.js +35 -35
  85. package/dist/src/pil/cheap-model-workbooks.js +16 -13
  86. package/dist/src/pil/clarity-gate.d.ts +21 -19
  87. package/dist/src/pil/clarity-gate.js +26 -153
  88. package/dist/src/pil/config.d.ts +9 -1
  89. package/dist/src/pil/config.js +15 -4
  90. package/dist/src/pil/discovery.js +211 -136
  91. package/dist/src/pil/layer1-intent.d.ts +12 -0
  92. package/dist/src/pil/layer1-intent.js +283 -38
  93. package/dist/src/pil/layer1-intent.test.js +210 -4
  94. package/dist/src/pil/layer16-clarity.d.ts +25 -11
  95. package/dist/src/pil/layer16-clarity.js +19 -306
  96. package/dist/src/pil/layer4-gsd.js +18 -6
  97. package/dist/src/pil/layer6-output.d.ts +2 -0
  98. package/dist/src/pil/layer6-output.js +137 -22
  99. package/dist/src/pil/llm-classify.d.ts +26 -0
  100. package/dist/src/pil/llm-classify.js +34 -5
  101. package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
  102. package/dist/src/pil/native-capabilities-workbook.js +82 -76
  103. package/dist/src/pil/schema.d.ts +8 -0
  104. package/dist/src/pil/schema.js +12 -1
  105. package/dist/src/pil/task-tier-map.js +4 -0
  106. package/dist/src/pil/types.d.ts +11 -1
  107. package/dist/src/product-loop/done-gate.js +3 -3
  108. package/dist/src/product-loop/loop-driver.js +18 -18
  109. package/dist/src/product-loop/progress-snapshot.js +4 -4
  110. package/dist/src/providers/auth/gemini-oauth.js +6 -15
  111. package/dist/src/providers/auth/grok-oauth.js +6 -15
  112. package/dist/src/providers/auth/openai-oauth.js +6 -15
  113. package/dist/src/providers/mcp-vision-bridge.js +48 -48
  114. package/dist/src/reporter/index.js +1 -1
  115. package/dist/src/scaffold/bb-ecosystem-apply.js +47 -47
  116. package/dist/src/scaffold/bb-quality-gate.js +5 -5
  117. package/dist/src/scaffold/continuation-prompt.js +60 -60
  118. package/dist/src/scaffold/init-new.js +453 -453
  119. package/dist/src/self-qa/__tests__/scenario-planner.test.js +3 -3
  120. package/dist/src/self-qa/agentic-loop.js +24 -19
  121. package/dist/src/self-qa/spec-emitter.js +26 -23
  122. package/dist/src/storage/__tests__/migrations.test.js +2 -2
  123. package/dist/src/storage/interaction-log.js +5 -5
  124. package/dist/src/storage/migrations.js +122 -122
  125. package/dist/src/storage/sessions.js +42 -42
  126. package/dist/src/storage/transcript.js +91 -84
  127. package/dist/src/storage/usage.js +14 -14
  128. package/dist/src/storage/workspaces.js +12 -12
  129. package/dist/src/tools/__tests__/native-tools.test.d.ts +1 -0
  130. package/dist/src/tools/__tests__/native-tools.test.js +53 -0
  131. package/dist/src/tools/git-safety.d.ts +61 -0
  132. package/dist/src/tools/git-safety.js +141 -0
  133. package/dist/src/tools/git-safety.test.d.ts +1 -0
  134. package/dist/src/tools/git-safety.test.js +111 -0
  135. package/dist/src/tools/native-tools.d.ts +31 -0
  136. package/dist/src/tools/native-tools.js +273 -0
  137. package/dist/src/tools/registry-git-safety.test.d.ts +7 -0
  138. package/dist/src/tools/registry-git-safety.test.js +92 -0
  139. package/dist/src/tools/registry.js +39 -4
  140. package/dist/src/ui/__tests__/markdown-render.test.d.ts +1 -0
  141. package/dist/src/ui/__tests__/markdown-render.test.js +48 -0
  142. package/dist/src/ui/app.js +0 -0
  143. package/dist/src/ui/components/message-view.js +4 -1
  144. package/dist/src/ui/components/structured-response-view.js +7 -3
  145. package/dist/src/ui/components/tool-group.js +7 -1
  146. package/dist/src/ui/markdown-render.d.ts +41 -0
  147. package/dist/src/ui/markdown-render.js +223 -0
  148. package/dist/src/ui/markdown.d.ts +10 -0
  149. package/dist/src/ui/markdown.js +12 -35
  150. package/dist/src/ui/slash/council-inspect.js +4 -4
  151. package/dist/src/ui/slash/export.js +4 -4
  152. package/dist/src/ui/utils/text.d.ts +8 -0
  153. package/dist/src/ui/utils/text.js +16 -0
  154. package/dist/src/ui/utils/text.test.d.ts +1 -0
  155. package/dist/src/ui/utils/text.test.js +23 -0
  156. package/dist/src/usage/ledger.js +48 -15
  157. package/dist/src/utils/__tests__/footprint-gitignore.test.d.ts +1 -0
  158. package/dist/src/utils/__tests__/footprint-gitignore.test.js +50 -0
  159. package/dist/src/utils/clipboard-image.js +23 -23
  160. package/dist/src/utils/open-url.d.ts +56 -0
  161. package/dist/src/utils/open-url.js +58 -0
  162. package/dist/src/utils/open-url.test.d.ts +1 -0
  163. package/dist/src/utils/open-url.test.js +86 -0
  164. package/dist/src/utils/settings.d.ts +12 -0
  165. package/dist/src/utils/settings.js +48 -0
  166. package/dist/src/utils/side-question.js +2 -2
  167. package/dist/src/utils/skills.js +3 -3
  168. package/dist/src/verify/__tests__/coverage-parsers.test.js +30 -30
  169. package/dist/src/verify/environment.js +2 -1
  170. package/package.json +1 -1
  171. package/dist/src/pil/layer16-clarity.test.js +0 -31
  172. /package/dist/src/{pil/layer16-clarity.test.d.ts → council/__tests__/clarification-prompt.test.d.ts} +0 -0
@@ -36,6 +36,7 @@ const TASK_TYPE_DEFAULT_STYLE = {
36
36
  analyze: "concise", // bullet findings, no narrative
37
37
  documentation: "balanced", // examples + explanation
38
38
  generate: "concise", // code speaks for itself
39
+ build: "concise", // greenfield code artifact — code speaks for itself (mirrors generate)
39
40
  refactor: "concise", // diff is the output
40
41
  general: "concise", // direct answer, no preamble
41
42
  };
@@ -78,19 +79,47 @@ const TASK_OUTPUT_BUDGET = {
78
79
  analyze: 600,
79
80
  documentation: 900,
80
81
  generate: 1200,
82
+ // build (greenfield) emits multiple complete files — same budget as generate.
83
+ build: 1200,
81
84
  // general is user-facing prose (not a code artifact). Higher budget + relaxed
82
85
  // style rules so the final answer reads naturally for humans instead of
83
86
  // machine-optimized telegraphic lists. See user report on over-constrained
84
87
  // freetext after Layer 6.
85
88
  general: 650,
86
89
  };
87
- // PIL-04 Tier 1.3 + PIL-L6 verbosity fix: ban preamble AND end-of-turn summary.
88
- // Old rule only covered openers (~30 tok saved). End-of-turn summaries
89
- // ("In summary...", "I have completed X, Y, Z", "Tóm tắt: ...") cost
90
- // 100-300 tokens/turn AND give the user nothing they can't read from the
91
- // diff. Bilingual EN+VN. Skipped for response-tools path (JSON has no
92
- // freeform surface).
93
- const NO_PREAMBLE_RULE = `\nFORBIDDEN OPENERS: do not start with "I'll", "I will", "Let me", "Here's", "Sure", "Of course", "Tôi sẽ", "Để tôi", "Vâng". Start directly with the answer content.\nFORBIDDEN END-OF-TURN SUMMARY: do not append a recap section ("In summary", "To summarize", "Tổng kết", "Tóm tắt", "Tóm lại", "Kết luận", "I have done X, Y, Z", "Now you have…", "Đã hoàn thành…"). The diff and command output already show what changed; the user can read them. End the response when the answer is complete.\nFORBIDDEN INTER-TOOL NARRATION: when chaining tool calls, do NOT emit content text between them. Skip phrases like "Now I'll check…", "Let me look at…", "Next, I need to…", "Tiếp theo tôi sẽ…", "Bây giờ tôi cần…". Emit the next tool call directly. Each round-trip of inter-tool narration costs the user ~100 output tokens that they do not need to read — the tool calls themselves are visible in the UI. Only emit content text for the FINAL answer or when surfacing a decision the user must make.`;
90
+ // PIL-04 Tier 1.3 (de-robotized): ban ONLY wasteful openers.
91
+ //
92
+ // Earlier this rule also banned end-of-turn summaries AND inter-tool narration.
93
+ // Both bans were REMOVED: they stripped the natural connective tissue that makes
94
+ // an answer read like a human wrote it, which is the root of the "máy móc" /
95
+ // telegraphic feel users complained about. Forbidding any recap or any sentence
96
+ // between tool calls forces curt, label-prefixed output even when a connecting
97
+ // line would help.
98
+ //
99
+ // Removing the text bans does NOT re-introduce context bloat or user-invisible
100
+ // spam:
101
+ // - Inter-tool narration is still removed STRUCTURALLY from message history by
102
+ // stripInterToolNarration() / NARRATION_PREFIX_REGEX in
103
+ // src/orchestrator/reasoning.ts. That runs unconditionally on every assistant
104
+ // message that has both text and a following tool-call, so it is far more
105
+ // reliable than a text directive budget models ignore (session 7dcf8fd7d6a4:
106
+ // 57/100 messages violated the text ban anyway).
107
+ // - OUTPUT BUDGET (below) remains the guard against padding, so a freed-up
108
+ // summary cannot balloon the answer.
109
+ //
110
+ // Openers ("I'll", "Let me", "Sure", "Tôi sẽ") stay banned: pure ~30-tok padding
111
+ // with zero conversational value. Bilingual EN+VN. Skipped for the response-tools
112
+ // path (JSON has no freeform surface).
113
+ const NO_PREAMBLE_RULE = `\nFORBIDDEN OPENERS: do not start with "I'll", "I will", "Let me", "Here's", "Sure", "Of course", "Tôi sẽ", "Để tôi", "Vâng". Start directly with the answer content.`;
114
+ // Anti-bookkeeping note for the NATURAL (non-response-tool) path — the response-
115
+ // tool path has the equivalent baked into humanNote. The Agent Operating Contract's
116
+ // REPORTING rule ("every fact must come from THIS turn; do not infer unopened
117
+ // files") is the model's operating discipline, but budget models RESTATE it as a
118
+ // user-facing provenance footer ("evidence only from this turn", "did not infer
119
+ // unopened files", "≤600 tokens"). That is invisible-to-the-reader compliance
120
+ // noise. Applied only to non-question turns — question turns already get the same
121
+ // guidance from the Layer 4 QUESTION directive (buildQuestion).
122
+ const NO_BOOKKEEPING_NOTE = `\nWRITE FOR THE READER: the answer is for the human who asked. Do NOT append a provenance / compliance footer (e.g. "evidence only from this turn", "did not infer unopened files", token-budget notes) and do NOT restate internal rule / contract / layer / tool names as compliance — those are your operating rules, invisible to the reader. End on the answer's last substantive point.`;
94
123
  const SUFFIXES = {
95
124
  refactor: {
96
125
  concise: `\nOUTPUT RULES (refactor): Show only changed code. Prefer unified diff or replacement function. No prose unless architecture changes. One sentence max if explanation needed. No preamble.`,
@@ -98,19 +127,19 @@ const SUFFIXES = {
98
127
  detailed: `\nOUTPUT RULES (refactor): Show changed code with full rationale. Explain why each change improves the code. Include before/after comparison when helpful. Unified diff preferred.`,
99
128
  },
100
129
  debug: {
101
- concise: `\nOUTPUT RULES (debug): Format = Hypothesis Root cause (1 line) Fix (code only) Verify command. No preamble. No "I think" hedging.`,
102
- balanced: `\nOUTPUT RULES (debug): Format = Hypothesis Root cause Fix (code) Verify command. Brief explanation of why the bug occurs. Keep prose minimal.`,
103
- detailed: `\nOUTPUT RULES (debug): Format = Hypothesis Root cause analysis Fix (code) Verify command Prevention. Explain the underlying mechanism and why this fix is correct.`,
130
+ concise: `\nOUTPUT RULES (debug): Lead with the root cause and the fix (code). Bring in the hypothesis and a verify command where they add value — you don't have to label every part or follow a fixed template. Be direct; skip "I think"/"maybe" hedging.`,
131
+ balanced: `\nOUTPUT RULES (debug): Give the root cause and the fix (code), with a short note on why the bug happens and how to verify it. Write it naturally — no rigid section labels needed.`,
132
+ detailed: `\nOUTPUT RULES (debug): Walk through the root cause, the fix (code), how to verify, and how to prevent recurrence. Explain the underlying mechanism so the reader understands why the fix is correct.`,
104
133
  },
105
134
  plan: {
106
- concise: `\nOUTPUT RULES (plan): Numbered steps only. Each step: action verb + acceptance criterion. No prose paragraphs. Add "Assumptions:" section only if needed.`,
107
- balanced: `\nOUTPUT RULES (plan): Numbered steps with brief rationale per step. Each step: action verb + acceptance criterion + why. Add "Assumptions:" and "Risks:" sections if applicable.`,
108
- detailed: `\nOUTPUT RULES (plan): Numbered steps with full rationale. Each step: action verb + acceptance criterion + why + alternatives considered. Include "Assumptions:", "Risks:", and "Trade-offs:" sections.`,
135
+ concise: `\nOUTPUT RULES (plan): Use numbered steps; each step should make the action and its done-criterion clear. A short framing sentence is fine when it helps — just skip filler. Note key assumptions if any matter.`,
136
+ balanced: `\nOUTPUT RULES (plan): Use numbered steps, each with its action, done-criterion, and a brief why. Add "Assumptions:" or "Risks:" notes when they matter. A short lead-in sentence is welcome.`,
137
+ detailed: `\nOUTPUT RULES (plan): Numbered steps with full rationale action, done-criterion, why, and alternatives considered. Include "Assumptions:", "Risks:", and "Trade-offs:" where relevant.`,
109
138
  },
110
139
  analyze: {
111
- concise: `\nOUTPUT RULES (analyze): Bullet findings with evidence (file:line or direct quote). Add severity label (High/Med/Low) when applicable. No filler sentences.`,
112
- balanced: `\nOUTPUT RULES (analyze): Bullet findings with evidence (file:line or direct quote). Add severity label and brief explanation. Context for each finding.`,
113
- detailed: `\nOUTPUT RULES (analyze): Bullet findings with evidence (file:line or direct quote). Add severity label, root cause analysis, and recommended action. Provide context and impact assessment.`,
140
+ concise: `\nOUTPUT RULES (analyze): Present findings as bullets, each backed by evidence (file:line or a direct quote). Add a severity label (High/Med/Low) where it helps prioritize. A brief lead-in is fine — just avoid padding.`,
141
+ balanced: `\nOUTPUT RULES (analyze): Present findings as bullets with evidence (file:line or quote), a severity label, and a brief explanation. Give enough context for each finding to stand on its own.`,
142
+ detailed: `\nOUTPUT RULES (analyze): Present findings as bullets with evidence (file:line or quote), severity, root-cause, and a recommended action. Include context and impact for each finding.`,
114
143
  },
115
144
  documentation: {
116
145
  concise: `\nOUTPUT RULES (documentation): Markdown only. Lead with a code example, then explanation. No "This function..." openers. All examples in fenced code blocks.`,
@@ -122,6 +151,11 @@ const SUFFIXES = {
122
151
  balanced: `\nOUTPUT RULES (generate): Complete, runnable code with brief explanation. Include all imports. Inline comments for key decisions. Short prose before code block explaining approach.`,
123
152
  detailed: `\nOUTPUT RULES (generate): Complete, runnable code with full explanation. Include all imports. Inline comments for logic and decisions. Explain design choices, alternatives considered, and trade-offs before the code.`,
124
153
  },
154
+ build: {
155
+ concise: `\nOUTPUT RULES (build): Scaffold the minimum runnable project/feature. Emit complete files (all imports), matching existing conventions. Wire it end-to-end; do not leave stubs. State the verify/run command in one line. No speculative extras.`,
156
+ balanced: `\nOUTPUT RULES (build): Scaffold a runnable project/feature with a short rationale for the structure. Emit complete files, follow existing conventions, wire it end-to-end, and give the build/run command. Avoid speculative features.`,
157
+ detailed: `\nOUTPUT RULES (build): Scaffold a runnable project/feature with full rationale — layout, key dependencies, and design choices. Emit complete files with all imports, wire everything end-to-end, give the build/run + verify commands. Note trade-offs; skip speculative scope.`,
158
+ },
125
159
  general: {
126
160
  // General answers should be highly readable. Encourage rich markdown
127
161
  // (bullets, headings, bold text) instead of forcing dense prose.
@@ -166,7 +200,7 @@ export function applyPilSuffix(systemPrompt, ctx, responseToolsActive = false) {
166
200
  // CI") just because the prompt looks ambiguous in isolation — session
167
201
  // 127140a47b56 hit this and the model spent 275 LLM calls being "thorough"
168
202
  // about a one-liner CI fix.
169
- const ACTION_TASKS = new Set(["debug", "refactor", "generate"]);
203
+ const ACTION_TASKS = new Set(["debug", "refactor", "generate", "build"]);
170
204
  const DETAIL_KEYWORDS = /\b(explain in detail|thorough analysis|walk me through|in depth|deeply|comprehensive)\b|giải thích chi tiết|phân tích kỹ|cặn kẽ|chi tiết hơn/i;
171
205
  const requestedStyle = ctx.outputStyle ?? "concise";
172
206
  const style = requestedStyle === "detailed" && ACTION_TASKS.has(ctx.taskType) && !DETAIL_KEYWORDS.test(ctx.raw)
@@ -195,6 +229,14 @@ export function applyPilSuffix(systemPrompt, ctx, responseToolsActive = false) {
195
229
  if (!isMetaAnalysis && !responseToolsActive) {
196
230
  result += NO_PREAMBLE_RULE;
197
231
  }
232
+ // E — keep the contract's REPORTING discipline from leaking into the answer as a
233
+ // provenance/compliance footer. Skip question turns (the L4 QUESTION directive
234
+ // already says it) to avoid duplicate steering. Phase 2b: consume the model's
235
+ // deliverable (answer = a question turn) when present; legacy regex otherwise.
236
+ const isQuestionTurn = ctx.deliverableKind ? ctx.deliverableKind === "answer" : isQuestionLike(ctx.raw);
237
+ if (!isQuestionTurn) {
238
+ result += NO_BOOKKEEPING_NOTE;
239
+ }
198
240
  // T1 behavioral rules (proven-tier EE points set by Layer 3). These are
199
241
  // project-specific reflexes the model MUST follow — injected as instructions,
200
242
  // not as context hints, so they carry imperative weight rather than suggestion weight.
@@ -225,18 +267,91 @@ const IMPLEMENTATION_INTENT_RE = /\b(implement|edit|wire(?:\s+up)?|rewrite|renam
225
267
  export function isImplementationIntent(raw) {
226
268
  return !!raw && IMPLEMENTATION_INTENT_RE.test(raw);
227
269
  }
270
+ /**
271
+ * Narrow response-tool gating (user-directed de-robotizing).
272
+ *
273
+ * For debug / analyze / plan the structured respond_* tool forces the answer into
274
+ * a rigid JSON schema (DebugSchema {hypothesis, root_cause, fix, verify}, etc.)
275
+ * which the UI then stamps with fixed labels ("hypothesis:", "root cause:",
276
+ * "[HIGH]", "done when:") in structured-response-view.tsx. For an ordinary
277
+ * QUESTION ("why does X fail?", "analyze the auth design") that reads robotic and
278
+ * even forces fabricated fields (DebugSchema.fix.file is required, so a
279
+ * non-codebase debug question must invent a file). So these task types now
280
+ * default to the NATURAL markdown path (softened OUTPUT RULES + openers-only
281
+ * NO_PREAMBLE) and only opt INTO the structured tool when the prompt's DELIVERABLE
282
+ * is genuinely a report / list / plan.
283
+ *
284
+ * Conservative positive gate (defaults to natural): only an explicit
285
+ * report/list/plan signal keeps respond_*. EN + VI. `general` is exempt — its
286
+ * renderer already shows plain markdown, so respond_general carries no robotic
287
+ * cost while still giving budget models a structural anchor.
288
+ */
289
+ const STRUCTURED_REPORT_RE = /\b(lists?|enumerate|table|report|audit|checklist|inventory|rank(?:ed|ing)?|prioriti[sz]e[ds]?|roadmap|step[-\s]?by[-\s]?step|milestones?|plan(?:s|ning)?)\b|liệt\s*kê|danh\s*sách|bảng|báo\s*cáo|kiểm\s*toán|rà\s*soát|lộ\s*trình|từng\s*bước|các\s*bước|kế\s*hoạch|xếp\s*hạng|ưu\s*tiên/i;
290
+ // Question-shape detector — shared by Layer 4 (GSD directive selection) and the
291
+ // narrow response-tool gate below. True when the prompt reads as a question or
292
+ // explanatory request rather than an imperative deliverable. Interrogative words
293
+ // only count at sentence start (so "list the steps" is NOT a question), plus
294
+ // "can/could/would/should + pronoun", a trailing "?", and VI markers. EN + VI.
295
+ const QUESTION_SHAPE_RE = /^\s*(?:why|how|what|when|where|who|whom|whose|which|explain|describe)\b|\b(?:can|could|would|should)\s+(?:you|i|we|it|they)\b|\?\s*$|tại\s*sao|vì\s*sao|(?:như\s*)?thế\s*nào|là\s*gì|ra\s*sao|ở\s*đâu|khi\s*nào|bao\s*nhiêu|có\s*phải|giải\s*thích|mô\s*tả/i;
296
+ // Vietnamese yes/no question frames — the most common VI question shape, and
297
+ // entirely absent from QUESTION_SHAPE_RE above (no "?" and no leading
298
+ // interrogative word). Live miss: session f6f7881a5fae — "bạn check xem dùng
299
+ // được mcp muonroi-docs không nhé" ("can you check whether the muonroi-docs MCP
300
+ // works?") was NOT seen as a question, so layer4-gsd emitted the STANDARD
301
+ // "implement directly" directive and discovery fabricated a build outcome,
302
+ // driving a 40-call code hunt instead of a one-line answer.
303
+ // Two interrogative tails:
304
+ // 1. "(được|đúng|phải) không" anywhere — "is it OK / right?".
305
+ // 2. a clause-final "không"/"chưa" (the yes/no particle), optionally trailed
306
+ // by a softener (nhé/vậy/à/…) or punctuation. Anchored to end so a
307
+ // mid-sentence negation ("không là hỏng" = "or it breaks") does NOT match.
308
+ const VI_YESNO_RE = /\b(?:được|đúng|phải)\s*không\b|\b(?:không|chưa)\s*(?:nhé|nhỉ|vậy|thế|ạ|à|hả|ko|nha)?\s*[?.…]*\s*$/i;
309
+ export function isQuestionLike(raw) {
310
+ return !!raw && (QUESTION_SHAPE_RE.test(raw) || VI_YESNO_RE.test(raw));
311
+ }
312
+ export function prefersStructuredReport(raw) {
313
+ if (!raw)
314
+ return false;
315
+ // A question that merely mentions "plan"/"list" — e.g. an interview quoting the
316
+ // phrase "state a 2-3 line plan" — must NOT be treated as a report request; it
317
+ // stays on the natural markdown path. Genuine delivery requests ("plan the
318
+ // migration", "list all X") are imperative, not question-shaped.
319
+ if (isQuestionLike(raw))
320
+ return false;
321
+ return STRUCTURED_REPORT_RE.test(raw);
322
+ }
228
323
  export function getResponseToolSet(ctx, providerId) {
229
324
  if (!ctx.taskType)
230
325
  return {};
326
+ // Chitchat: greetings/small-talk never want a structured answer block. Mirrors
327
+ // the chitchat short-circuits in applyPilSuffix / layer6Output.
328
+ if (ctx.intentKind === "chitchat")
329
+ return {};
231
330
  // PIL-04 Tier 1.1: gate JSON-structured output to list-shaped tasks where it
232
331
  // wins on tokens. Code-heavy tasks fall through to markdown OUTPUT RULES.
233
332
  if (!RESPONSE_TOOL_TASK_TYPES.has(ctx.taskType))
234
333
  return {};
235
- // Implementation/edit turns: the deliverable is file changes, not a structured
236
- // report. A terminal respond_<task> tool lets the model "answer" (state a plan)
237
- // and end the turn before the edits complete drop it for clear edit intent.
238
- if (isImplementationIntent(ctx.raw))
239
- return {};
334
+ // Phase 2b: when the model classified the deliverable, CONSUME it to decide
335
+ // structured-vs-natural output instead of re-deriving intent via regex:
336
+ // - code → file changes, not a report. A terminal respond_* lets the model
337
+ // "answer" (state a plan) and end the turn before edits finish.
338
+ // - answer → debug/analyze/plan QUESTIONS read robotic as labeled JSON →
339
+ // natural markdown path (general keeps its naturally-rendered tool).
340
+ // - report → keep the structured tool (its value IS the structure).
341
+ // Only when the model didn't emit a deliverable (null → legacy cascade / model
342
+ // omitted the word) do we fall back to the legacy regex predicates.
343
+ if (ctx.deliverableKind) {
344
+ if (ctx.deliverableKind === "code")
345
+ return {};
346
+ if (ctx.taskType !== "general" && ctx.deliverableKind !== "report")
347
+ return {};
348
+ }
349
+ else {
350
+ if (isImplementationIntent(ctx.raw))
351
+ return {};
352
+ if (ctx.taskType !== "general" && !prefersStructuredReport(ctx.raw))
353
+ return {};
354
+ }
240
355
  // Provider-aware gating: a provider may report it can't reliably emit
241
356
  // valid JSON tool input for this task type (e.g. DeepSeek leaks special
242
357
  // tokens into `general` responses). Drop the tool to avoid retry storms.
@@ -1,9 +1,35 @@
1
1
  import type { ProviderFactory } from "../providers/runtime.js";
2
2
  import type { OutputStyle, TaskType } from "./types.js";
3
+ /**
4
+ * What the user wants the turn to PRODUCE — decided by the model (Phase 2b) so
5
+ * the keyword-regex predicates in Layer 4 (`informational`) and Layer 6
6
+ * (`getResponseToolSet` / `applyPilSuffix`) are no longer the authority for
7
+ * output routing.
8
+ * - "code" — create/edit files (implement, fix, build, refactor, scaffold).
9
+ * - "report" — a structured list/plan/audit/roadmap is the deliverable.
10
+ * - "answer" — an explanation / review / question / meta answer (no edits).
11
+ * `null` when the model omits/garbles the word → Layer 4/6 fall back to their
12
+ * legacy regex predicates for that turn (graceful, never a wrong forced route).
13
+ */
14
+ export type DeliverableKind = "answer" | "code" | "report";
3
15
  export interface LlmClassifyResult {
4
16
  taskType: TaskType;
5
17
  outputStyle: OutputStyle | null;
6
18
  confidence: number;
19
+ /**
20
+ * Whether the prompt is a real request (task) or pure social chitchat
21
+ * (greeting / thanks / ack). Decided by the model so the regex chitchat
22
+ * shortcuts (isSocialPleasantry, ultra-short heuristic) are no longer the
23
+ * authority. Defaults to "task" when the model omits the signal — the
24
+ * keep-tools safe direction (a false "task" wastes ~1.5K tokens of tool
25
+ * schema; a false "chitchat" strips bash/read and BREAKS the turn).
26
+ */
27
+ intentKind: "task" | "chitchat";
28
+ /**
29
+ * Model-decided output deliverable (answer | code | report). null when the
30
+ * model omitted the word — consumers then fall back to their legacy regex.
31
+ */
32
+ deliverableKind: DeliverableKind | null;
7
33
  }
8
34
  export type LlmClassifyFn = (prompt: string, signal?: AbortSignal) => Promise<LlmClassifyResult | null>;
9
35
  /**
@@ -25,7 +25,10 @@ const LLM_CLASSIFY_TIMEOUT_MS = 2500;
25
25
  // The ceiling is a cap, not padding: the model still stops after two words, so a
26
26
  // generous headroom costs nothing when reasoning is short.
27
27
  const REASONING_CLASSIFY_TIMEOUT_MS = 8000;
28
- const NONREASONING_MAX_OUTPUT_TOKENS = 16;
28
+ // Four comma-separated words now (added <deliverable>) — ~10-14 tokens worst
29
+ // case ("documentation,balanced,task,report"). 24 keeps headroom over the
30
+ // prior 16-token cap without padding (the model still stops after four words).
31
+ const NONREASONING_MAX_OUTPUT_TOKENS = 24;
29
32
  const REASONING_MAX_OUTPUT_TOKENS = 2048;
30
33
  /**
31
34
  * Per-namespace shallow merge of providerOptions. The base already carries
@@ -55,9 +58,15 @@ const VALID_TASK_TYPES = new Set([
55
58
  "general",
56
59
  ]);
57
60
  const VALID_STYLES = new Set(["concise", "balanced", "detailed"]);
58
- const SYSTEM_PROMPT = "You classify user prompts for a coding assistant. Reply with ONE line of two lowercase words separated by a comma: <taskType>,<style>\n\n" +
61
+ const SYSTEM_PROMPT = "You classify user prompts for a coding assistant. Reply with ONE line of FOUR lowercase words separated by commas: <taskType>,<style>,<intent>,<deliverable>\n\n" +
59
62
  "taskType ∈ { refactor | debug | plan | analyze | documentation | generate | general }\n" +
60
- "style ∈ { concise | balanced | detailed }\n\n" +
63
+ "style ∈ { concise | balanced | detailed }\n" +
64
+ "intent ∈ { task | chat } — 'chat' ONLY for a pure greeting, thanks, or acknowledgement with NO work request (e.g. 'hi', 'cảm ơn nhé', 'ok great'). EVERYTHING else is 'task', including questions about code or the CLI, 'are you done?', and requests to call a tool. When unsure, choose 'task'.\n" +
65
+ "deliverable ∈ { answer | code | report } — what the user wants you to PRODUCE this turn:\n" +
66
+ "- code — CREATE or EDIT files: implement, fix, build, scaffold, refactor, wire, rename, apply a patch. The deliverable is changed code.\n" +
67
+ "- report — a STRUCTURED list / plan / audit / roadmap / checklist is the deliverable (its value IS the structure).\n" +
68
+ "- answer — everything else: explain, review, investigate, compare, a question about code or the CLI, a yes/no question, a meta/self-eval. The deliverable is a written answer, NO file edits.\n" +
69
+ " Pick by the PRIMARY thing the user asked you to produce. A question that merely mentions code is 'answer'. When unsure between answer and report, choose answer.\n\n" +
61
70
  "Rules (read carefully — Phase 4 4P-2 disambiguation):\n" +
62
71
  "- debug — fix a bug, CI/build/test failure, error, exception, crash, or any 'why is X broken' question.\n" +
63
72
  "- generate — create new code, scaffold, write a new file, add a feature from scratch, ADD A NEW TEST, CHANGE A DEFAULT VALUE, modify configuration, improve coverage.\n" +
@@ -82,7 +91,17 @@ const SYSTEM_PROMPT = "You classify user prompts for a coding assistant. Reply w
82
91
  "- documentation → balanced (examples + explanation)\n" +
83
92
  "- general → concise\n" +
84
93
  "Only output 'detailed' if the user prompt LITERALLY contains words like 'explain in detail', 'thorough analysis', 'walk me through', 'giải thích chi tiết', 'phân tích kỹ'.\n\n" +
85
- "Prompts may be Vietnamese, English, or mixed. Reply with exactly two words separated by one comma. No other text.";
94
+ "Intent + deliverable examples:\n" +
95
+ "- 'hi' → general,concise,chat,answer\n" +
96
+ "- 'cảm ơn bạn nhé' → general,concise,chat,answer\n" +
97
+ "- 'bạn thử call tool setup_guide xem được không' → general,concise,task,answer (wants info, not file edits)\n" +
98
+ "- 'bạn xong chưa' → general,concise,task,answer (a question — NOT chat)\n" +
99
+ "- 'fix CI failing on Windows' → debug,concise,task,code\n" +
100
+ "- 'rename function shouldInject to needsReminder' → refactor,concise,task,code\n" +
101
+ "- 'tại sao bash_output_get trả empty' → analyze,concise,task,answer (investigate → written answer)\n" +
102
+ "- 'liệt kê tất cả env var CLI đọc' → analyze,concise,task,report (structured list)\n" +
103
+ "- 'plan the migration to hooks' → plan,balanced,task,report\n\n" +
104
+ "Prompts may be Vietnamese, English, or mixed. Reply with exactly four words separated by commas. No other text.";
86
105
  function parseResponse(raw) {
87
106
  const cleaned = raw.trim().toLowerCase().replace(/[`*"]/g, "");
88
107
  const firstLine = cleaned.split(/\r?\n/)[0] ?? "";
@@ -97,7 +116,17 @@ function parseResponse(raw) {
97
116
  return null;
98
117
  const styleWord = parts[1];
99
118
  const style = styleWord && VALID_STYLES.has(styleWord) ? styleWord : null;
100
- return { taskType: taskWord, outputStyle: style, confidence: 0.75 };
119
+ // Third word is the chitchat-vs-task intent. Only an explicit "chat" marks
120
+ // chitchat; anything else (including a missing/garbled word) defaults to
121
+ // "task" — the keep-tools safe direction.
122
+ const intentWord = parts.find((p) => p === "chat" || p === "chitchat" || p === "task");
123
+ const intentKind = intentWord === "chat" || intentWord === "chitchat" ? "chitchat" : "task";
124
+ // Fourth word is the output deliverable. Parsed position-independently so a
125
+ // reordered/garbled reply still recovers it; null when absent → Layer 4/6 use
126
+ // their legacy regex predicates for this turn (never a wrong forced route).
127
+ const deliverableWord = parts.find((p) => p === "answer" || p === "code" || p === "report");
128
+ const deliverableKind = deliverableWord ?? null;
129
+ return { taskType: taskWord, outputStyle: style, confidence: 0.75, intentKind, deliverableKind };
101
130
  }
102
131
  /**
103
132
  * Build a closure the PIL pipeline can call. Reuses the orchestrator's already-
@@ -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\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`). 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]";
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