@aragon-agent/cli 0.6.38 → 0.6.40

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 (209) hide show
  1. package/CHANGELOG.md +263 -0
  2. package/README.md +544 -11
  3. package/dist/agent/controller.d.ts +245 -10
  4. package/dist/agent/controller.js +367 -22
  5. package/dist/agent/model-profile-settings.js +12 -1
  6. package/dist/agent/plan-prompt.d.ts +1 -3
  7. package/dist/agent/plan-prompt.js +13 -7
  8. package/dist/agent/reducer.d.ts +70 -2
  9. package/dist/agent/reducer.js +59 -6
  10. package/dist/agent/skill-triage-prompt.d.ts +42 -0
  11. package/dist/agent/skill-triage-prompt.js +74 -0
  12. package/dist/agent/system-prompt.d.ts +28 -2
  13. package/dist/agent/system-prompt.js +12 -4
  14. package/dist/cli.js +106 -32
  15. package/dist/commands/builtins.js +24 -3
  16. package/dist/commands/keys-command.d.ts +23 -0
  17. package/dist/commands/keys-command.js +38 -0
  18. package/dist/commands/registry.d.ts +39 -0
  19. package/dist/commands/skills.js +86 -1
  20. package/dist/commands/subagent-command.d.ts +25 -0
  21. package/dist/commands/subagent-command.js +242 -0
  22. package/dist/commands/task-command.d.ts +39 -0
  23. package/dist/commands/task-command.js +102 -0
  24. package/dist/compaction/command.js +16 -3
  25. package/dist/compaction/compactor.d.ts +25 -0
  26. package/dist/compaction/compactor.js +111 -10
  27. package/dist/compaction/digest.d.ts +24 -1
  28. package/dist/compaction/digest.js +139 -17
  29. package/dist/compaction/limits.d.ts +21 -0
  30. package/dist/compaction/limits.js +21 -0
  31. package/dist/compaction/reason-text.d.ts +36 -0
  32. package/dist/compaction/reason-text.js +78 -0
  33. package/dist/compaction/types.d.ts +82 -14
  34. package/dist/compaction/wiring.d.ts +13 -8
  35. package/dist/compaction/wiring.js +1 -0
  36. package/dist/config/cli-commands.d.ts +23 -0
  37. package/dist/config/cli-commands.js +36 -0
  38. package/dist/config/env.js +17 -4
  39. package/dist/config/load.js +55 -3
  40. package/dist/config/schema.d.ts +125 -10
  41. package/dist/config/schema.js +138 -14
  42. package/dist/config/store.js +23 -3
  43. package/dist/diagnostics/doctor.d.ts +9 -0
  44. package/dist/diagnostics/doctor.js +34 -0
  45. package/dist/diagnostics/info.d.ts +71 -0
  46. package/dist/diagnostics/info.js +91 -5
  47. package/dist/exec/bridge/caller-tools.d.ts +96 -0
  48. package/dist/exec/bridge/caller-tools.js +213 -0
  49. package/dist/exec/bridge/decisions.d.ts +78 -0
  50. package/dist/exec/bridge/decisions.js +116 -0
  51. package/dist/exec/bridge/human-answers.d.ts +38 -0
  52. package/dist/exec/bridge/human-answers.js +164 -0
  53. package/dist/exec/bridge/limits.d.ts +68 -0
  54. package/dist/exec/bridge/limits.js +68 -0
  55. package/dist/exec/bridge/ndjson.d.ts +17 -0
  56. package/dist/exec/bridge/ndjson.js +83 -0
  57. package/dist/exec/bridge/pending.d.ts +70 -0
  58. package/dist/exec/bridge/pending.js +132 -0
  59. package/dist/exec/bridge/protocol.d.ts +346 -0
  60. package/dist/exec/bridge/protocol.js +256 -0
  61. package/dist/exec/bridge/server.d.ts +142 -0
  62. package/dist/exec/bridge/server.js +502 -0
  63. package/dist/exec/bridge/source.d.ts +58 -0
  64. package/dist/exec/bridge/source.js +145 -0
  65. package/dist/exec/bridge/writer.d.ts +26 -0
  66. package/dist/exec/bridge/writer.js +156 -0
  67. package/dist/exec/cli-commands.js +30 -2
  68. package/dist/exec/emitter.d.ts +16 -2
  69. package/dist/exec/emitter.js +26 -6
  70. package/dist/exec/events.d.ts +465 -10
  71. package/dist/exec/events.js +47 -1
  72. package/dist/exec/hooks/dispatch.d.ts +76 -0
  73. package/dist/exec/hooks/dispatch.js +169 -0
  74. package/dist/exec/hooks/index.d.ts +83 -0
  75. package/dist/exec/hooks/index.js +205 -0
  76. package/dist/exec/hooks/limits.d.ts +56 -0
  77. package/dist/exec/hooks/limits.js +49 -0
  78. package/dist/exec/hooks/registry.d.ts +49 -0
  79. package/dist/exec/hooks/registry.js +91 -0
  80. package/dist/exec/hooks/tool-wrapper.d.ts +94 -0
  81. package/dist/exec/hooks/tool-wrapper.js +154 -0
  82. package/dist/exec/hooks/turn.d.ts +61 -0
  83. package/dist/exec/hooks/turn.js +59 -0
  84. package/dist/exec/hooks/validate.d.ts +85 -0
  85. package/dist/exec/hooks/validate.js +310 -0
  86. package/dist/exec/index.d.ts +130 -4
  87. package/dist/exec/index.js +501 -10
  88. package/dist/exec/options.d.ts +124 -2
  89. package/dist/exec/options.js +413 -6
  90. package/dist/exec/permission.d.ts +9 -1
  91. package/dist/exec/permission.js +7 -1
  92. package/dist/exec/request/limits.d.ts +51 -0
  93. package/dist/exec/request/limits.js +49 -0
  94. package/dist/exec/request/scope.d.ts +106 -0
  95. package/dist/exec/request/scope.js +149 -0
  96. package/dist/exec/result/limits.d.ts +74 -0
  97. package/dist/exec/result/limits.js +72 -0
  98. package/dist/exec/result/prompt.d.ts +28 -0
  99. package/dist/exec/result/prompt.js +74 -0
  100. package/dist/exec/result/schema.d.ts +99 -0
  101. package/dist/exec/result/schema.js +464 -0
  102. package/dist/exec/result/sink.d.ts +56 -0
  103. package/dist/exec/result/sink.js +50 -0
  104. package/dist/exec/result/tool.d.ts +37 -0
  105. package/dist/exec/result/tool.js +118 -0
  106. package/dist/exec/runner.d.ts +395 -1
  107. package/dist/exec/runner.js +860 -8
  108. package/dist/exec/threads/aggregate.d.ts +34 -0
  109. package/dist/exec/threads/aggregate.js +30 -0
  110. package/dist/exec/threads/capacity.d.ts +23 -0
  111. package/dist/exec/threads/capacity.js +38 -0
  112. package/dist/exec/threads/dispatch-source.d.ts +60 -0
  113. package/dist/exec/threads/dispatch-source.js +106 -0
  114. package/dist/exec/threads/execute-threads.d.ts +53 -0
  115. package/dist/exec/threads/execute-threads.js +234 -0
  116. package/dist/exec/threads/gate.d.ts +42 -0
  117. package/dist/exec/threads/gate.js +81 -0
  118. package/dist/exec/threads/identity.d.ts +36 -0
  119. package/dist/exec/threads/identity.js +67 -0
  120. package/dist/exec/threads/interrupt.d.ts +29 -0
  121. package/dist/exec/threads/interrupt.js +79 -0
  122. package/dist/exec/threads/limits.d.ts +58 -0
  123. package/dist/exec/threads/limits.js +35 -0
  124. package/dist/exec/threads/outcome.d.ts +47 -0
  125. package/dist/exec/threads/outcome.js +26 -0
  126. package/dist/exec/threads/registry.d.ts +81 -0
  127. package/dist/exec/threads/registry.js +427 -0
  128. package/dist/exec/threads/runtime.d.ts +107 -0
  129. package/dist/exec/threads/runtime.js +523 -0
  130. package/dist/exec/threads/thread-source.d.ts +20 -0
  131. package/dist/exec/threads/thread-source.js +134 -0
  132. package/dist/fast/limits.d.ts +54 -0
  133. package/dist/fast/limits.js +54 -0
  134. package/dist/fast/summary-call.d.ts +72 -0
  135. package/dist/fast/summary-call.js +133 -0
  136. package/dist/fast/summary-prompt.d.ts +106 -0
  137. package/dist/fast/summary-prompt.js +320 -0
  138. package/dist/fast/task-summary-types.d.ts +66 -0
  139. package/dist/fast/task-summary-types.js +17 -0
  140. package/dist/logging/logger.d.ts +1 -1
  141. package/dist/proc/limits.d.ts +7 -0
  142. package/dist/proc/limits.js +7 -0
  143. package/dist/proc/log-mirror.d.ts +21 -4
  144. package/dist/proc/log-mirror.js +29 -7
  145. package/dist/proc/output-streams.d.ts +50 -0
  146. package/dist/proc/output-streams.js +54 -0
  147. package/dist/skills/service.d.ts +41 -0
  148. package/dist/skills/service.js +62 -0
  149. package/dist/skills/triage.d.ts +194 -0
  150. package/dist/skills/triage.js +393 -0
  151. package/dist/team/forced-dispatch.d.ts +95 -0
  152. package/dist/team/forced-dispatch.js +208 -0
  153. package/dist/team/limits.d.ts +21 -1
  154. package/dist/team/limits.js +21 -1
  155. package/dist/team/normalize.d.ts +15 -0
  156. package/dist/team/normalize.js +21 -4
  157. package/dist/team/prompt.d.ts +6 -3
  158. package/dist/team/prompt.js +9 -5
  159. package/dist/team/runtime.d.ts +9 -0
  160. package/dist/team/runtime.js +8 -0
  161. package/dist/team/subagent.d.ts +15 -0
  162. package/dist/team/subagent.js +45 -1
  163. package/dist/team/task-tool.js +11 -7
  164. package/dist/tools/bash-tool.d.ts +10 -0
  165. package/dist/tools/bash-tool.js +71 -6
  166. package/dist/tools/human-input.d.ts +35 -2
  167. package/dist/tools/human-input.js +38 -0
  168. package/dist/tools/index.d.ts +93 -1
  169. package/dist/tools/index.js +112 -3
  170. package/dist/tools/plan-tools.d.ts +20 -12
  171. package/dist/tools/plan-tools.js +24 -17
  172. package/dist/tools/tool-gate.d.ts +100 -0
  173. package/dist/tools/tool-gate.js +87 -0
  174. package/dist/ui/App.js +238 -12
  175. package/dist/ui/Header.d.ts +28 -16
  176. package/dist/ui/Header.js +21 -19
  177. package/dist/ui/StatusBar.d.ts +1 -0
  178. package/dist/ui/StatusBar.js +1 -0
  179. package/dist/ui/Transcript.js +1 -1
  180. package/dist/ui/entries/CompactionCard.d.ts +11 -1
  181. package/dist/ui/entries/CompactionCard.js +65 -4
  182. package/dist/ui/interaction-hints.js +6 -0
  183. package/dist/ui/layout/OverlayFrame.d.ts +18 -0
  184. package/dist/ui/layout/OverlayFrame.js +19 -4
  185. package/dist/ui/layout/header-hints.d.ts +55 -62
  186. package/dist/ui/layout/header-hints.js +59 -166
  187. package/dist/ui/layout/header-left.d.ts +115 -0
  188. package/dist/ui/layout/header-left.js +206 -0
  189. package/dist/ui/layout/shortcut-panel-layout.d.ts +191 -0
  190. package/dist/ui/layout/shortcut-panel-layout.js +321 -0
  191. package/dist/ui/layout/status-detail-layout.js +5 -1
  192. package/dist/ui/layout/status-layout.d.ts +10 -0
  193. package/dist/ui/layout/status-layout.js +18 -1
  194. package/dist/ui/layout/task-summary-cell.d.ts +61 -0
  195. package/dist/ui/layout/task-summary-cell.js +65 -0
  196. package/dist/ui/overlays/HelpOverlay.d.ts +12 -0
  197. package/dist/ui/overlays/HelpOverlay.js +29 -2
  198. package/dist/ui/overlays/SettingsScreen.js +29 -5
  199. package/dist/ui/overlays/ShortcutPanel.d.ts +39 -0
  200. package/dist/ui/overlays/ShortcutPanel.js +106 -0
  201. package/dist/ui/overlays/TeamFanoutPage.d.ts +35 -0
  202. package/dist/ui/overlays/TeamFanoutPage.js +78 -0
  203. package/dist/ui/overlays/model-profile-state.d.ts +19 -1
  204. package/dist/ui/overlays/model-profile-state.js +12 -0
  205. package/dist/ui/overlays/team-fanout-state.d.ts +73 -0
  206. package/dist/ui/overlays/team-fanout-state.js +97 -0
  207. package/dist/ui/shortcuts.d.ts +81 -0
  208. package/dist/ui/shortcuts.js +221 -0
  209. package/package.json +2 -2
@@ -19,6 +19,8 @@ import type { CliConfig, CompactionConfig, FastConfig, RetryConfig, TeamConfig,
19
19
  import type { ModelRole } from '../config/model-profiles.js';
20
20
  import { ModelWindows } from '../config/model-windows.js';
21
21
  import { type ConfirmRequest } from '../tools/index.js';
22
+ import type { ToolGate } from '../tools/tool-gate.js';
23
+ import type { ToolHookRunner } from '../exec/hooks/tool-wrapper.js';
22
24
  import type { ToolPermission } from '../exec/permission.js';
23
25
  import { type ToolOutputListener } from '../tools/tool-output-store.js';
24
26
  import type { FilePatch } from '../tools/patch.js';
@@ -28,11 +30,13 @@ import { ProcSupervisor } from '../proc/supervisor.js';
28
30
  import type { ProcEventListener, ServiceSnapshot } from '../proc/types.js';
29
31
  import { type FastStatus } from '../fast/wiring.js';
30
32
  import type { FastEventListener, FastSnapshot } from '../fast/types.js';
33
+ import type { TaskSummaryOutcome } from '../fast/task-summary-types.js';
31
34
  import { ContextMeter, type ContextUsageListener } from '../compaction/meter.js';
32
35
  import type { CompactionEventListener, CompactionSnapshot, ContextUsageSnapshot } from '../compaction/types.js';
33
36
  import type { AcceptanceItem, TodoEventListener, TodoSnapshot } from '../todo/types.js';
34
37
  import { type HumanInputGate } from '../tools/human-input.js';
35
38
  import { SkillService, type ApprovalGate } from '../skills/service.js';
39
+ import type { SkillRoutingReport } from '../skills/triage.js';
36
40
  import { type ConversationResetOptions, type ConversationResetResult } from './conversation-reset.js';
37
41
  import type { AgentMode } from './agent-mode.js';
38
42
  import type { NoticeLevel } from './reducer.js';
@@ -100,6 +104,36 @@ export interface ControllerDeps {
100
104
  * `tools/index.ts`.
101
105
  */
102
106
  permission?: ToolPermission;
107
+ /**
108
+ * The caller's per-call approval gate (headless-host-bridge §2.3.3).
109
+ *
110
+ * FORWARDED INTO `createBuiltinTools` AND NOWHERE ELSE. Unlike `permission` it
111
+ * does NOT reach subagents in this round: every child builds its own tool array
112
+ * through `team/runtime.ts`, and a fan-out that asked "may I run bash?" once per
113
+ * child for one decision is an approval waterfall, not a control. Absent on
114
+ * every existing path, which is what keeps the tool array identical there.
115
+ */
116
+ toolGate?: ToolGate;
117
+ /**
118
+ * How long a decision may wait, added to the tool's own budget.
119
+ *
120
+ * SEE THE TWO-PHASE FORMULA AT `toolTimeoutOverrides`. The executor arms its
121
+ * timer BEFORE the approval wrapper runs, so a ceiling of `toolTimeoutMs` alone
122
+ * would give the tool less than its configured time by exactly however long the
123
+ * caller took to answer.
124
+ */
125
+ decisionBudgetMs?: number;
126
+ /**
127
+ * The gate each SUBAGENT gets, keyed by its label (headless-host-bridge
128
+ * section 2.3.7).
129
+ *
130
+ * A SEPARATE FIELD BECAUSE THE SCOPE DIFFERS, NOT BECAUSE THE GATE DOES: every
131
+ * child reports `{id, label, depth: 1}` so the caller can render "subagent A
132
+ * wants to run bash", while the lead reports `depth: 0`. One shared instance
133
+ * would attribute every child's request to the lead. Absent outside bridge mode,
134
+ * which keeps a child's tool array identical today.
135
+ */
136
+ toolGateForChild?: (label: string) => ToolGate;
103
137
  /**
104
138
  * `--append-system-prompt` text, appended verbatim to the composed prompt
105
139
  * (§4.1). Threaded through `composeSystemPrompt` so it survives every rebuild
@@ -107,6 +141,41 @@ export interface ControllerDeps {
107
141
  * once at construction and lost at the first `rebuildSystemPrompt()`.
108
142
  */
109
143
  appendSystemPrompt?: string;
144
+ /**
145
+ * `submit_result`, registered with the lead's toolset when the caller supplied
146
+ * `--result-schema` (headless-request-scope-and-typed-result section 2.3.9).
147
+ *
148
+ * FORWARDED INTO `createBuiltinTools` AND NOWHERE ELSE. It must NOT reach a
149
+ * subagent: a child's product is a report that goes back through `task`, and a
150
+ * second submitter inside one request would compete with the lead's schema for the
151
+ * one accepted value. The child's `createBuiltinTools` call site is
152
+ * `team/subagent.ts`, and it deliberately passes nothing here.
153
+ *
154
+ * Absent on every existing path (the TUI, `-p`, every subcommand), which is what
155
+ * keeps their tool arrays byte-identical (I-S2).
156
+ */
157
+ resultTool?: AgentTool;
158
+ /**
159
+ * The rendered `<structured_result>` block, or absent.
160
+ *
161
+ * SEE THE FIELD'S OWN COMMENT for why this is threaded through the controller
162
+ * rather than spliced once: the prompt is rebuilt, and a block that vanished on a
163
+ * rebuild would leave the model unaware of the contract it is being graded against.
164
+ */
165
+ structuredResultBlock?: string;
166
+ /**
167
+ * The caller's lifecycle hooks (headless-threads-and-lifecycle-hooks section 2.4.9).
168
+ *
169
+ * FORWARDED INTO `createBuiltinTools` AND NOWHERE ELSE, in the same shape `resultTool`
170
+ * is: absent on every existing path (the TUI, `-p`, every subcommand and every
171
+ * subagent), which is what keeps their tool arrays byte-identical.
172
+ *
173
+ * THE CHILD'S CALL SITE IS DELIBERATELY SILENT ABOUT IT. Hooks see the LEAD's tool calls;
174
+ * a subagent builds its own array in `team/subagent.ts` and a hook installed for tenant
175
+ * isolation on the lead must not silently become a hook on every child's identical
176
+ * `read_file` - that is a different security decision with its own design (section 9.5).
177
+ */
178
+ hookRunner?: ToolHookRunner;
110
179
  /**
111
180
  * The per-model window table from ~/.aragon-agent/model-windows.json.
112
181
  * Injectable so tests can hand the controller a table without writing into
@@ -115,22 +184,36 @@ export interface ControllerDeps {
115
184
  */
116
185
  modelWindows?: ModelWindows;
117
186
  }
118
- /** What `setAgentMode` actually adopted — see `AgentController.setAgentMode`. */
187
+ /**
188
+ * What `setAgentMode` actually adopted — see `AgentController.setAgentMode`.
189
+ *
190
+ * THIS IS ALSO WHAT `/plan status` REPORTS. A `PlanStatus extends AgentModeState`
191
+ * with `askRoundsUsed` / `maxAskRounds` existed until the round cap was deleted;
192
+ * keeping an empty sub-interface around would only leave a comment that every
193
+ * later reader has to work through to learn that nothing is missing.
194
+ */
119
195
  export interface AgentModeState {
120
196
  effective: AgentMode;
121
197
  /** Non-null only while a `plan -> build` switch is waiting for `agent_end`. */
122
198
  pending: AgentMode | null;
123
199
  }
124
- export interface PlanStatus extends AgentModeState {
125
- askRoundsUsed: number;
126
- maxAskRounds: number;
127
- }
128
200
  export interface PreflightResult {
129
201
  ok: boolean;
130
202
  message?: string;
131
203
  /** 'config' for a missing/invalid key or unusable provider. */
132
204
  kind?: 'config';
133
205
  }
206
+ /** Inputs for one task-label attempt (`AgentController.summarizeTask`). */
207
+ export interface SummarizeTaskOptions {
208
+ /**
209
+ * Cancels the call. The CALLER also owns the epoch guard
210
+ * (tui-shortcut-drawer-and-task-summary D-10): aborting frees the connection,
211
+ * the epoch decides correctness, and neither substitutes for the other.
212
+ */
213
+ signal?: AbortSignal;
214
+ /** The glyph a cut label ends with. ASCII by default so a headless caller is safe. */
215
+ ellipsis?: string;
216
+ }
134
217
  export declare class AgentController {
135
218
  private config;
136
219
  private readonly agent;
@@ -143,9 +226,34 @@ export declare class AgentController {
143
226
  private modelMetadataAbort;
144
227
  private disposed;
145
228
  private readonly tools;
229
+ /**
230
+ * Tools the CALLER serves, replaced on every `tool_register` (I-13).
231
+ *
232
+ * A SECOND ARRAY, NOT ONE GROWN ONE. `this.tools` is read by `listTools()`,
233
+ * `toolNames()`, `composeSystemPrompt()` and three "fixed at construction" flags
234
+ * (bash_output/bash_kill, task, todo_write). Growing it would silently change
235
+ * what those flags mean; keeping the caller's tools beside it gives one honest
236
+ * rule - the REGISTRY is the union, `this.tools` stays the host's own set.
237
+ */
238
+ private callerTools;
146
239
  private readonly skills;
147
240
  private readonly skillsEnabled;
148
241
  private onSkillsChanged?;
242
+ /**
243
+ * This turn's routing result, or `null` when triage is off or nothing scored.
244
+ *
245
+ * It also carries the task it was computed for (`SkillRoutingReport.task`), so
246
+ * there is no separate copy of the turn's text to keep in step with it.
247
+ */
248
+ private turnRouting;
249
+ /** The previous turn's routing, for `/skills route` with no argument. */
250
+ private lastSkillRouting;
251
+ /** Did this turn call `skill(name)` successfully? The only proof of adoption. */
252
+ private skillLoadedThisTurn;
253
+ /** Tool calls this turn, EXCLUDING `skill` / `skill_find` (see §4.2.7). */
254
+ private toolCallsThisTurn;
255
+ /** Skills already reported as "not loaded" — a session says it once (I-T5). */
256
+ private readonly skillTriageNoticed;
149
257
  /** Mutable session cwd — tools resolve relative paths against this. */
150
258
  private cwd;
151
259
  /**
@@ -157,9 +265,33 @@ export declare class AgentController {
157
265
  * Empty on every path but `aragon exec`.
158
266
  */
159
267
  private readonly appendSystemPrompt;
268
+ /**
269
+ * The `<structured_result>` block (headless-request-scope-and-typed-result
270
+ * section 2.3.8), or `''`.
271
+ *
272
+ * A FIELD FOR THE SAME REASON `appendSystemPrompt` IS ONE: `composeSystemPrompt()`
273
+ * runs again on every rebuild, so a value spliced once at construction would vanish
274
+ * at the first `/cwd` change, skills rescan or mode flip - and the model would then
275
+ * be asked to submit a result it had never been told about. Empty on every path but
276
+ * `aragon exec --result-schema`.
277
+ */
278
+ private readonly structuredResultBlock;
160
279
  private effectiveMode;
161
280
  private pendingMode;
162
- private askRounds;
281
+ /**
282
+ * Fingerprints of the question SETS the user ANSWERED in this turn. Bounded,
283
+ * and the bound is storage hygiene rather than a refusal rule — see
284
+ * `ASK_GUARD_LIMITS`.
285
+ *
286
+ * Replaces a numeric round counter that capped `ask_user` at four calls. There
287
+ * is no cap now; the only thing this prevents is the same batch of questions
288
+ * being put to the user twice, which is noise rather than information.
289
+ *
290
+ * Cleared in `prepareUserTurn` for a NEW turn only. A steer continuation is the
291
+ * same turn — clearing there would disable the guard exactly when a long turn
292
+ * most needs it (§4.1.6).
293
+ */
294
+ private readonly askedFingerprints;
163
295
  /** Static: whether this session could ever render a question overlay. */
164
296
  private readonly planInteractive;
165
297
  private readonly teamRegistered;
@@ -345,6 +477,24 @@ export declare class AgentController {
345
477
  * semantics depend on whether a notice happened to be pending.
346
478
  */
347
479
  private flushPendingNotices;
480
+ /**
481
+ * THE BOUNDARY OF ONE TURN — and there are TWO call sites, which is the reason
482
+ * this takes an explicit flag instead of resetting everything unconditionally.
483
+ *
484
+ * `startPrompt` passes `{ steering: false }`: the user typed something new, so
485
+ * this really is a new turn. `continue()` passes `{ steering: true }` with the
486
+ * CONCATENATED queued steering text, which resumes the SAME turn.
487
+ *
488
+ * A steer continuation must not re-triage (the candidates would change mid-turn,
489
+ * and rebuilding the prompt aborts an idle compaction for no gain) and must not
490
+ * clear the answered-question guard (a long turn interrupted by one steer is
491
+ * exactly when a repeat question is most likely). Hence per-turn state is
492
+ * initialised in ONE branch.
493
+ *
494
+ * `steering` is REQUIRED and positional-second so each call site states which
495
+ * kind of turn it is starting, rather than letting a default make "new turn" the
496
+ * thoughtless option.
497
+ */
348
498
  private prepareUserTurn;
349
499
  /** Cancel pending startup as well as any engine run already in progress. */
350
500
  abort(): void;
@@ -483,9 +633,53 @@ export declare class AgentController {
483
633
  */
484
634
  applyPendingMode(): AgentModeState | null;
485
635
  /** Named read surface for `/plan status`, so no command reaches into internals. */
486
- getPlanStatus(): PlanStatus;
487
- /** Spend one `ask_user` round. Called from the tool, never from the UI. */
488
- private takeAskRound;
636
+ getPlanStatus(): AgentModeState;
637
+ /**
638
+ * READ-ONLY guard probe, called by `ask_user` BEFORE it opens the overlay.
639
+ *
640
+ * No side effect of any kind: a check that also writes cannot be placed before
641
+ * the question without recording an answer that has not happened yet, and the
642
+ * "a cancelled round stays askable" rule would then be unimplementable.
643
+ */
644
+ private hasAnswered;
645
+ /**
646
+ * Record an ANSWERED question set, called by `ask_user` after a real answer.
647
+ *
648
+ * Evicts the oldest entry past `ASK_GUARD_LIMITS.maxRemembered`. That eviction
649
+ * is memory hygiene and NOT a refusal rule — a bounded rejection would be the
650
+ * deleted round cap wearing a bigger number.
651
+ */
652
+ private noteAnswered;
653
+ /** `/skills route` with no argument: the LAST turn's real routing result. */
654
+ getSkillRouting(): SkillRoutingReport | null;
655
+ /**
656
+ * One line when a confidently-matched skill was NOT loaded — and silence every
657
+ * other time (D-8).
658
+ *
659
+ * THE DISCIPLINE IS "SILENT ON SUCCESS, VISIBLE ON FAILURE". Announcing the
660
+ * candidates every turn would be ignored by the third day; announcing nothing
661
+ * ever would make the whole feature unfalsifiable. "A skill covered this task,
662
+ * you did the work anyway, and you never opened it" is precisely the failure this
663
+ * feature exists to fix, so it is the one case that speaks — and it names the
664
+ * command that explains it.
665
+ *
666
+ * SEVEN CONDITIONS, and the first one is the one that is easy to get wrong.
667
+ *
668
+ * 0. This turn was NOT aborted and NOT ended by an error.
669
+ * `agent_end` is emitted unconditionally from a `finally` block in
670
+ * `core/src/engine/agent.ts` and its payload carries no reason, no `aborted`
671
+ * and no `error` field — so "did this turn finish normally?" has to be read
672
+ * from this class's own state. `stopEngine()` sets `abortRequested` before it
673
+ * calls `agent.abort()` and `agent_start` clears it, which makes it an exact
674
+ * answer. Without this condition an Esc mis-touch would produce a line
675
+ * criticising the model for not loading a skill: commentary in response to an
676
+ * interruption.
677
+ *
678
+ * Conditions 5 and 0 are not redundant: 0 decides what counts as the end of a
679
+ * turn, 5 decides whether the turn did any work. With only 5, a tool call made
680
+ * before an abort would still trigger the notice.
681
+ */
682
+ private maybeReportSkillTriage;
489
683
  /**
490
684
  * Run `fn` with the idle watchdog paused.
491
685
  *
@@ -870,6 +1064,24 @@ export declare class AgentController {
870
1064
  * consumed by `App` too, and this round promised to be purely additive.
871
1065
  */
872
1066
  fastSnapshot(): FastSnapshot | null;
1067
+ /**
1068
+ * Summarise one user prompt into a header label, using the FAST tier only.
1069
+ *
1070
+ * NEVER REJECTS - the same contract `prompt()` has, and the reason `App` needs
1071
+ * no `.catch`. Every failure is folded into a discriminated
1072
+ * `TaskSummaryOutcome`, because a header label must not be able to produce an
1073
+ * unhandled rejection in a TUI that has nowhere to show one.
1074
+ *
1075
+ * THE CONTROLLER OWNS THE `AbortController` AND ABORTS IT UNCONDITIONALLY on the
1076
+ * way out: `runTaskSummaryCall` may return a `timeout` outcome while the request
1077
+ * is still open (it is forbidden to abort its own call - see that file's
1078
+ * header), so this `finally` is what actually releases the connection.
1079
+ *
1080
+ * EVERY `this.fast` READ IS BEHIND THE CLOSURE, exactly as the reviewer and the
1081
+ * overseer wiring do it: `complete` is only reached from inside the call, which
1082
+ * runs long after construction, so there is no use-before-assign.
1083
+ */
1084
+ summarizeTask(anchor: string, opts?: SummarizeTaskOptions): Promise<TaskSummaryOutcome>;
873
1085
  /**
874
1086
  * Subscribe to occupancy publications. Returns an unsubscribe function.
875
1087
  *
@@ -970,6 +1182,29 @@ export declare class AgentController {
970
1182
  * `subscribeTodos` and `subscribeFast` already set.
971
1183
  */
972
1184
  subscribeCompaction(listener: CompactionEventListener): () => void;
973
- /** List usable tools (name + description) for the /tools command. */
1185
+ /**
1186
+ * List usable tools (name + description) for the /tools command.
1187
+ *
1188
+ * THE UNION, SO THE VIEW AND THE REGISTRY CANNOT DISAGREE (I-13). `system/init`
1189
+ * builds `init.tools` from here, as do `/tools` and `/skills`; reporting only the
1190
+ * host's own set while the model is calling `db_query` is the exact failure that
1191
+ * invariant names - a caller reading "the model has no such tool" about a tool it
1192
+ * is watching run.
1193
+ */
974
1194
  listTools(): AgentTool[];
1195
+ /**
1196
+ * Replace the caller-served tool set. Called ONLY at a turn boundary.
1197
+ *
1198
+ * `Agent.setTools()` unregisters and re-registers entries in the LIVE registry.
1199
+ * This class already learned the lesson once: `submit_plan` mutates the mode from
1200
+ * INSIDE a tool execution, so rebuilding the array at that moment would mutate
1201
+ * the registry mid-iteration (see the comment on the plan tools). Hence the
1202
+ * refusal rather than a silently deferred write: a caller that registers
1203
+ * mid-turn gets an error it can act on, and the bridge defers the frame instead.
1204
+ *
1205
+ * `[]` is meaningful and not an omission: it means "restore the factory set".
1206
+ */
1207
+ applyCallerTools(tools: AgentTool[]): void;
1208
+ /** The names the caller currently serves, for `ack.tools`. */
1209
+ callerToolNames(): string[];
975
1210
  }