ai-runtime-engine 1.3.0 → 2.8.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 (153) hide show
  1. package/CHANGELOG.md +638 -0
  2. package/dist/agents/admit.d.ts +69 -0
  3. package/dist/agents/admit.js +129 -0
  4. package/dist/agents/definition.d.ts +36 -0
  5. package/dist/agents/definition.js +9 -0
  6. package/dist/agents/envelope.d.ts +53 -0
  7. package/dist/agents/envelope.js +68 -0
  8. package/dist/agents/finding.d.ts +79 -0
  9. package/dist/agents/finding.js +80 -0
  10. package/dist/agents/roles.d.ts +36 -0
  11. package/dist/agents/roles.js +44 -0
  12. package/dist/agents/synthesize.d.ts +44 -0
  13. package/dist/agents/synthesize.js +60 -0
  14. package/dist/agents/task.d.ts +112 -0
  15. package/dist/agents/task.js +48 -0
  16. package/dist/agents/worker.d.ts +91 -0
  17. package/dist/agents/worker.js +377 -0
  18. package/dist/capabilities/capability.d.ts +117 -0
  19. package/dist/capabilities/capability.js +66 -0
  20. package/dist/capabilities/registry.d.ts +139 -0
  21. package/dist/capabilities/registry.js +413 -0
  22. package/dist/capabilities/vocabulary.d.ts +32 -0
  23. package/dist/capabilities/vocabulary.js +34 -0
  24. package/dist/cli/cli.js +55 -4
  25. package/dist/cli/commands/cleanup.js +29 -27
  26. package/dist/cli/commands/doctor.d.ts +14 -0
  27. package/dist/cli/commands/doctor.js +38 -8
  28. package/dist/cli/commands/executions.js +34 -25
  29. package/dist/cli/commands/info.d.ts +1 -0
  30. package/dist/cli/commands/info.js +11 -9
  31. package/dist/cli/commands/init.js +19 -0
  32. package/dist/cli/commands/inspect.d.ts +40 -1
  33. package/dist/cli/commands/inspect.js +157 -2
  34. package/dist/cli/commands/mcp.d.ts +45 -0
  35. package/dist/cli/commands/mcp.js +148 -0
  36. package/dist/cli/commands/route.js +21 -0
  37. package/dist/cli/commands/run.d.ts +1 -0
  38. package/dist/cli/commands/run.js +21 -2
  39. package/dist/cli/commands/skills.d.ts +2 -0
  40. package/dist/cli/commands/skills.js +29 -7
  41. package/dist/cli/interactive/ansi.d.ts +41 -0
  42. package/dist/cli/interactive/ansi.js +43 -0
  43. package/dist/cli/interactive/complete.d.ts +10 -0
  44. package/dist/cli/interactive/complete.js +19 -0
  45. package/dist/cli/interactive/lanes.d.ts +69 -0
  46. package/dist/cli/interactive/lanes.js +181 -0
  47. package/dist/cli/interactive/repl.d.ts +3 -0
  48. package/dist/cli/interactive/repl.js +91 -13
  49. package/dist/cli/interactive/session.d.ts +8 -0
  50. package/dist/cli/interactive/session.js +73 -2
  51. package/dist/cli/render.d.ts +7 -0
  52. package/dist/cli/render.js +10 -0
  53. package/dist/cli/runtimeSession.d.ts +11 -0
  54. package/dist/cli/runtimeSession.js +17 -0
  55. package/dist/config/defaults.d.ts +3 -1
  56. package/dist/config/defaults.js +2 -0
  57. package/dist/config/schema.d.ts +1 -0
  58. package/dist/config/schema.js +2 -2
  59. package/dist/context/lossVerifier.d.ts +24 -0
  60. package/dist/context/lossVerifier.js +45 -0
  61. package/dist/context/summarize.d.ts +19 -0
  62. package/dist/context/summarize.js +53 -0
  63. package/dist/core/fallback/fallback.d.ts +5 -0
  64. package/dist/core/fallback/fallback.js +3 -1
  65. package/dist/core/router/router.d.ts +3 -0
  66. package/dist/core/router/router.js +1 -0
  67. package/dist/executions/agentTasks.d.ts +627 -0
  68. package/dist/executions/agentTasks.js +149 -0
  69. package/dist/executions/checkpoint.d.ts +5 -1
  70. package/dist/executions/checkpoint.js +13 -1
  71. package/dist/executions/execution.d.ts +36 -2
  72. package/dist/executions/store.d.ts +37 -0
  73. package/dist/executions/store.js +33 -0
  74. package/dist/generation/generateAdapter.d.ts +14 -0
  75. package/dist/generation/generateAdapter.js +38 -0
  76. package/dist/generation/generateSkill.d.ts +26 -0
  77. package/dist/generation/generateSkill.js +51 -0
  78. package/dist/index.d.ts +47 -4
  79. package/dist/index.js +33 -2
  80. package/dist/mcp/client.d.ts +70 -0
  81. package/dist/mcp/client.js +221 -0
  82. package/dist/mcp/manager.d.ts +151 -0
  83. package/dist/mcp/manager.js +493 -0
  84. package/dist/mcp/protocol.d.ts +216 -0
  85. package/dist/mcp/protocol.js +149 -0
  86. package/dist/mcp/toolAdapter.d.ts +44 -0
  87. package/dist/mcp/toolAdapter.js +94 -0
  88. package/dist/mcp/transport.d.ts +109 -0
  89. package/dist/mcp/transport.js +383 -0
  90. package/dist/memory/embedders/hash.d.ts +12 -0
  91. package/dist/memory/embedders/hash.js +31 -0
  92. package/dist/memory/embedders/http.d.ts +25 -0
  93. package/dist/memory/embedders/http.js +48 -0
  94. package/dist/memory/memory.d.ts +19 -2
  95. package/dist/memory/memory.js +75 -11
  96. package/dist/memory/semantic.d.ts +17 -0
  97. package/dist/memory/semantic.js +29 -0
  98. package/dist/orchestration/budget.d.ts +30 -0
  99. package/dist/orchestration/budget.js +40 -0
  100. package/dist/orchestration/executor.d.ts +64 -1
  101. package/dist/orchestration/executor.js +104 -7
  102. package/dist/orchestration/orchestrator.d.ts +35 -1
  103. package/dist/orchestration/orchestrator.js +106 -8
  104. package/dist/orchestration/plan.d.ts +15 -1
  105. package/dist/orchestration/plan.js +23 -4
  106. package/dist/orchestration/planner.d.ts +19 -1
  107. package/dist/orchestration/planner.js +25 -5
  108. package/dist/plugin/ai.d.ts +4 -0
  109. package/dist/plugin/ai.js +9 -0
  110. package/dist/runtime/config.js +50 -6
  111. package/dist/runtime/intent/aiClassifier.d.ts +19 -0
  112. package/dist/runtime/intent/aiClassifier.js +74 -0
  113. package/dist/runtime/models/modelProfile.d.ts +61 -0
  114. package/dist/runtime/models/modelProfile.js +139 -0
  115. package/dist/runtime/planning/deriveCapabilities.d.ts +95 -0
  116. package/dist/runtime/planning/deriveCapabilities.js +146 -0
  117. package/dist/runtime/policy.d.ts +10 -0
  118. package/dist/runtime/policy.js +9 -2
  119. package/dist/runtime/runtime.d.ts +233 -0
  120. package/dist/runtime/runtime.js +1042 -60
  121. package/dist/runtime/types.d.ts +88 -2
  122. package/dist/security/redact.js +22 -10
  123. package/dist/skills/manifest.d.ts +3 -0
  124. package/dist/skills/manifest.js +24 -0
  125. package/dist/skills/registry.d.ts +16 -1
  126. package/dist/skills/registry.js +21 -1
  127. package/dist/skills/skill.d.ts +6 -1
  128. package/dist/store/area.d.ts +15 -1
  129. package/dist/store/area.js +19 -8
  130. package/dist/store/crypto.d.ts +21 -0
  131. package/dist/store/crypto.js +49 -0
  132. package/dist/store/paths.d.ts +5 -1
  133. package/dist/store/paths.js +6 -0
  134. package/dist/store/store.d.ts +15 -3
  135. package/dist/store/store.js +28 -7
  136. package/dist/telemetry/sinks/otlp.d.ts +31 -0
  137. package/dist/telemetry/sinks/otlp.js +76 -0
  138. package/dist/tools/builtins/filesystem.js +1 -0
  139. package/dist/tools/builtins/git.js +1 -0
  140. package/dist/tools/builtins/shell.js +1 -0
  141. package/dist/tools/permissions.d.ts +28 -0
  142. package/dist/tools/permissions.js +72 -0
  143. package/dist/tools/registry.d.ts +18 -2
  144. package/dist/tools/registry.js +22 -2
  145. package/dist/tools/tool.d.ts +4 -0
  146. package/dist/types.d.ts +5 -1
  147. package/dist/util/flatten.d.ts +11 -0
  148. package/dist/util/flatten.js +18 -0
  149. package/dist/util/hash.d.ts +19 -0
  150. package/dist/util/hash.js +39 -0
  151. package/dist/util/semaphore.d.ts +19 -0
  152. package/dist/util/semaphore.js +60 -0
  153. package/package.json +24 -9
@@ -3,6 +3,8 @@
3
3
  * a RuntimeContext, executes chat through `AI.run()`, and streams redacted lifecycle events. It never
4
4
  * routes or scores; all model selection stays in the one router. Unimplemented modes degrade to chat.
5
5
  */
6
+ import type { GenerateSkillResult } from '../generation/generateSkill.js';
7
+ import type { SkillManifest } from '../skills/manifest.js';
6
8
  import { AI } from '../plugin/ai.js';
7
9
  import type { AIOptions } from '../plugin/ai.js';
8
10
  import type { WorkspaceInfo } from './workspace/workspace.js';
@@ -14,8 +16,13 @@ import { ConversationStore } from '../conversations/conversations.js';
14
16
  import { MemoryStore } from '../memory/memory.js';
15
17
  import type { Tool, ToolResult } from '../tools/tool.js';
16
18
  import { resolvePermissions } from '../tools/permissions.js';
19
+ import { McpManager } from '../mcp/manager.js';
20
+ import type { McpServerStatus } from '../mcp/manager.js';
21
+ import { ActionCapabilityRegistry } from '../capabilities/registry.js';
22
+ import type { MissingCapabilityReport } from '../capabilities/capability.js';
17
23
  import type { Skill, SkillResult, SkillValidation, SkillPlan } from '../skills/skill.js';
18
24
  import type { SkillSource, LoadedSource } from '../skills/discovery.js';
25
+ import type { AgentDefinition } from '../agents/definition.js';
19
26
  import { ExecutionStore } from '../executions/store.js';
20
27
  import type { Execution } from '../executions/execution.js';
21
28
  import { ArtifactStore } from '../artifacts/artifacts.js';
@@ -23,6 +30,7 @@ import type { CompareInput } from '../comparison/comparator.js';
23
30
  import type { ComparisonResult } from '../comparison/comparison.js';
24
31
  import { LearningStore } from '../learning/learningStore.js';
25
32
  import type { FeedbackSignal } from '../learning/feedback.js';
33
+ import type { ModelProfile } from './models/modelProfile.js';
26
34
  import type { PermissionPolicy } from './policy.js';
27
35
  import type { RuntimeConfig, RuntimeResult, RuntimeRunInput, RuntimeSettings } from './types.js';
28
36
  export interface RuntimeOptions {
@@ -54,17 +62,50 @@ export declare class Runtime {
54
62
  private readonly _memory;
55
63
  private readonly _conversations;
56
64
  private readonly estimator;
65
+ /** ACTION-capability registry (Phase 3.1). Declared BEFORE the tool/skill registries so its
66
+ * ingest listeners are attached in time to capture the builtin registrations below. */
67
+ private readonly _capabilities;
68
+ /** MCP server lifecycle (Phase 3.2). Connection is LAZY: nothing is contacted until first use. */
69
+ private readonly _mcp;
70
+ private mcpConnected;
71
+ private readonly mcpToolIds;
72
+ private readonly mcpWarnings;
57
73
  private readonly _tools;
58
74
  private readonly _skills;
59
75
  private readonly _executions;
60
76
  private readonly _artifacts;
61
77
  private readonly _learning;
62
78
  private readonly workspaceRoot;
79
+ private readonly _modelProfile?;
63
80
  private readonly configPermissions;
81
+ /** The INJECTED clock. Agent deadlines are measured against it, never a real timer, so an offline
82
+ * test with a fake clock stays deterministic. */
83
+ private readonly clock;
84
+ /** Multi-agent core (Phase 3.4). False ⇒ every agent path is inert. */
85
+ private readonly agentsEnabled;
86
+ private readonly agentDefs;
87
+ /** Live runs, so a pause/cancel can abort the agent tasks actually in flight. Only ever populated
88
+ * when agents are enabled, so pause/cancel are unchanged with the flag off. */
89
+ private readonly liveRuns;
90
+ /** The config file's `budget:` ceilings, kept only so the 3.3 pre-pass can decline a model call. */
91
+ private readonly _configBudget?;
64
92
  private readonly approval?;
65
93
  private readonly _configFile?;
66
94
  private _loadedSkillSources;
67
95
  constructor(config?: RuntimeConfig, options?: RuntimeOptions, workspace?: WorkspaceInfo);
96
+ /**
97
+ * Build the memory embedder from `runtime.embedding` (Phase 14). Absent → undefined → BM25 keyword
98
+ * retrieval (the offline default). `local` = the zero-dep deterministic HashEmbedder; `openai-compatible`
99
+ * = the HTTP adapter (key by env NAME via `Credential`; a missing `baseUrl` yields no embedder → BM25).
100
+ */
101
+ private buildEmbedder;
102
+ /**
103
+ * Build the store cipher from `runtime.storage` (Phase 18). Absent / `encrypt:false` → undefined → a
104
+ * plaintext store (the default). `encrypt:true` resolves the key from the env var NAMED by `keyEnv` via
105
+ * `Credential` (never a value) and derives an AES-256 key; a missing key is a hard CONFIG error (silent
106
+ * plaintext would be a lie). The key lives only inside the returned codec — never logged or serialized.
107
+ */
108
+ private buildCipher;
68
109
  /** Build a Runtime from a workspace: load config (.ai-runtime/config.yaml > root fallback), detect workspace. */
69
110
  static load(options?: RuntimeOptions): Promise<Runtime>;
70
111
  /**
@@ -100,6 +141,15 @@ export declare class Runtime {
100
141
  * every hard gate (exclude/privacy/pin/capability/budget), which the router filter enforces.
101
142
  */
102
143
  private effectiveRouting;
144
+ /** The loaded `models.md` routing profile (per-mode/per-task model directives), or undefined if none. */
145
+ modelProfile(): ModelProfile | undefined;
146
+ /**
147
+ * Fold the `models.md` directive for this (mode, task) into the run — a soft prefer (universal, merged
148
+ * into routing), a strategy, or a hard pin (chat path, via the request escape hatch). Precedence is
149
+ * explicit per-run > models.md: the caller's own strategy/pin win, and prefer is unioned (never
150
+ * re-admitting an exclusion). No profile / no matching directive ⇒ the request is returned unchanged.
151
+ */
152
+ private applyModelProfile;
103
153
  /** Apply free-text feedback (e.g. "that worked" / "wrong root cause") to the most recent outcome. */
104
154
  feedback(text: string, opts?: {
105
155
  providerId?: string;
@@ -114,10 +164,79 @@ export declare class Runtime {
114
164
  tools(): Tool[];
115
165
  /** Register a skill. Chainable. */
116
166
  registerSkill(skill: Skill): this;
167
+ /**
168
+ * Register an agent definition (Phase 3.4). Chainable, and inert unless `runtime.agents.enabled` is
169
+ * set — registering a definition grants nothing on its own, exactly like adding an MCP server.
170
+ */
171
+ registerAgent(id: string, def: AgentDefinition): this;
172
+ /** The agent definition ids this runtime knows (registered or configured). */
173
+ agents(): string[];
174
+ /**
175
+ * This run's agent envelopes. THE ONLY call site of `narrowEnvelope` — never re-derive an inner
176
+ * catalog, a permission clamp, or a reservation anywhere else (see the header of agents/envelope.ts).
177
+ */
178
+ private agentEnvelopes;
179
+ /** The MCP server manager: `list()`, `status(id)`, `test(id)`, `addServer`, `removeServer`, `setEnabled`. */
180
+ mcp(): McpManager;
181
+ /**
182
+ * Connect every enabled MCP server, discover their tools, and register them. LAZY BY DESIGN: a one-shot
183
+ * CLI command that never touches MCP pays nothing, and a failing server records its state instead of
184
+ * breaking construction. Idempotent — the second call is a no-op.
185
+ */
186
+ connectMcp(): Promise<McpServerStatus[]>;
187
+ /** Whether any MCP server is configured at all (absent ⇒ MCP is entirely inert). */
188
+ hasMcpServers(): boolean;
189
+ /**
190
+ * Register one server's discovered tools as ordinary Runtime Tools (+ their namespaced action
191
+ * capabilities, via the tool registry's ingest listener). A generated id NEVER shadows an existing
192
+ * non-MCP tool: the collision is skipped and reported, because silently replacing `filesystem` would be
193
+ * a privilege swap.
194
+ */
195
+ private registerMcpTools;
196
+ /**
197
+ * The legacy declaration path (`AI.run({ mcp: true })`) — tools DECLARED to a model, never executed
198
+ * through here. It honors the same read/full split as execution (declaring a tool the executor would
199
+ * refuse just invites the model to plan around it) and is keyed by server id, so re-publishing with an
200
+ * empty list REVOKES it.
201
+ */
202
+ private publishMcpSource;
203
+ /** Drop a server's tools (removal / disable). */
204
+ private deregisterMcpTools;
205
+ /** Map a server's lifecycle state onto capability availability (the D7 derivation table). */
206
+ private mcpAvailability;
207
+ /** Warnings from MCP wiring (id collisions) plus the manager's own (invalid store files, etc.). */
208
+ mcpWarningsList(): string[];
209
+ /**
210
+ * Release long-lived resources — today: MCP stdio child processes. A one-shot CLI command and the REPL
211
+ * both call this on completion/exit; without it a spawned server keeps the event loop alive.
212
+ */
213
+ close(): Promise<void>;
117
214
  /** Skills whose required tools are all registered. */
118
215
  skills(): Skill[];
216
+ /**
217
+ * Scaffold a skill MANIFEST from a natural-language goal (Phase 21a). Drafts a `*.skill.yaml` via the
218
+ * model, validated by `parseManifest` + tool-membership + a dry compile. **Writes nothing** — pass the
219
+ * returned manifest to `saveScaffoldedSkill` on explicit confirm.
220
+ */
221
+ scaffoldSkill(goal: string): Promise<GenerateSkillResult>;
222
+ /**
223
+ * Write a scaffolded manifest into the consented `.ai-runtime/skills/` directory (Phase 21a). Only call
224
+ * this after the user has confirmed the drafted manifest. Returns the written path. The id was validated
225
+ * as kebab-case at generation; it is re-checked here so a hand-built manifest can't escape the skills dir.
226
+ */
227
+ saveScaffoldedSkill(manifest: SkillManifest): string;
228
+ /** The ACTION-capability registry (Phase 3.1): what this runtime can DO, and who provides it. */
229
+ capabilities(): ActionCapabilityRegistry;
119
230
  /** The resolved tool permissions for this runtime (config grants over deny-by-default defaults). */
120
231
  permissions(): ReturnType<typeof resolvePermissions>;
232
+ /**
233
+ * The ONE resolved-permission view for a run: config grants merged with a per-run override, with `mcp`
234
+ * merged by per-server MINIMUM so an override can only ever NARROW. Extracted from `toolContext`
235
+ * (Phase 3.3 / D9) so capability resolution and tool execution can never read different permissions.
236
+ * Never re-derive this merge at a call site: a plain `resolvePermissions({ ...config, ...override })`
237
+ * would let an override widen `read` to `full` and drop sibling servers.
238
+ */
239
+ private resolvedPermissions;
121
240
  private toolContext;
122
241
  /** Invoke a registered tool with the runtime's resolved permissions + host approval. */
123
242
  runTool(id: string, input: unknown, overrides?: {
@@ -128,6 +247,7 @@ export declare class Runtime {
128
247
  runSkill(id: string, input: unknown, overrides?: {
129
248
  permissions?: PermissionPolicy;
130
249
  signal?: AbortSignal;
250
+ ai?: AI;
131
251
  }): Promise<{
132
252
  plan: SkillPlan;
133
253
  result: SkillResult;
@@ -148,12 +268,73 @@ export declare class Runtime {
148
268
  executions(): Execution[];
149
269
  /** plan/execute/orchestrate/agent/debug: run the orchestrator and persist a resumable Execution. */
150
270
  private runOrchestration;
271
+ /**
272
+ * THE mid-run persistence sink (Phase 3.5) — the only thing that writes an execution while it runs.
273
+ *
274
+ * Invariant 18 says everything needed for resume is on disk before the next wave starts, and the
275
+ * non-obvious part is WHAT that includes. Committing the plan, the completed steps and the agent
276
+ * records is not enough: the resume gate is `!recon.drifted && !!exec.plan`, and `recon` defaults to
277
+ * DRIFTED whenever `checkpoints` is empty. Since checkpoints were captured only after orchestration
278
+ * returned, a crash mid-run always drifted, always replanned, and re-ran every completed agent task —
279
+ * the exact thing this phase exists to prevent. So the sink captures a checkpoint too.
280
+ *
281
+ * Every refusal from the funnel ABORTS the run. A refused commit means another owner now owns this
282
+ * execution's fate; carrying on would call the same tools and burn the same model calls twice while
283
+ * that owner re-runs the identical steps, and every result would be discarded at the end anyway.
284
+ */
285
+ private runPersistence;
151
286
  /** Run `fn` while heartbeating the execution lease so a long run never lets the lease expire. */
152
287
  private withHeartbeat;
153
288
  private orchestrateInput;
154
289
  /** Record an EXECUTED orchestration outcome for learning. plan-only, dry-run, and waiting states are
155
290
  * skipped — no skill ran, so there is no success/failure to learn (recording them would teach noise). */
156
291
  private recordOrchestration;
292
+ /**
293
+ * A capped, FENCED action-capability snapshot for the planner prompt (Phase 3.1, opt-in). Untrusted
294
+ * sources (anything not an in-tree builtin) have their descriptions fenced, and the block is bounded so
295
+ * a large catalog can never dominate the prompt.
296
+ */
297
+ private capabilityCatalogText;
298
+ /** Any call/cost ceiling declared in the config file's `budget:` block (router-level, not policy). */
299
+ private configBudget;
300
+ /** Deriver candidates: registry ids + one clamped label. Built by the SAME helper the CLI uses. */
301
+ private capabilityCandidates;
302
+ /**
303
+ * Derive the capabilities this goal needs and resolve them (Phase 3.3, opt-in). Offline BM25 first —
304
+ * free and deterministic — with ONE model call only when the offline rung finds nothing. ADVISORY: it
305
+ * never blocks a run and never grants anything; a gap is metadata plus a line in the planner prompt.
306
+ */
307
+ private capabilityPlanning;
308
+ /** The pre-rendered "Required capabilities" planner block (Phase 3.3) — clamped like the 3.1 catalog. */
309
+ private requiredCapabilitiesText;
310
+ /** A step's capability provider id. An MCP-backed tool ingests under `mcp:` (see the ingest hook). */
311
+ private providerIdForRef;
312
+ /**
313
+ * Resolve the capabilities the plan's OWN steps reference (Phase 3.3). ZERO model calls, purely
314
+ * additive metadata, and the only path that can surface a real `permission` gap with a concrete
315
+ * policyKey — the always-on validation path resolves namespaced MISSES, which have no providers and are
316
+ * therefore always reason 'unknown'. It never blocks: a gap here is advice, and the tool's own
317
+ * permission check remains the authority.
318
+ */
319
+ private checkPlanCapabilities;
320
+ /**
321
+ * Turn unregistered plan references into structured gaps (Phase 3.1's always-on upgrade), resolved
322
+ * against the RUN's permissions rather than the raw config (Phase 3.3 / D9) — so what resolution
323
+ * reports and what the executor will allow can never disagree.
324
+ */
325
+ private resolveMissingRefs;
326
+ /**
327
+ * The user-facing report for a set of required capability ids (Phase 3.1), against the runtime's
328
+ * CONFIGURED posture. A specific run's gaps use that run's merged permissions instead (see
329
+ * `resolveMissingRefs` and the capability-planning pre-pass); this entry point has no run in scope.
330
+ */
331
+ capabilityReport(required: string[]): MissingCapabilityReport;
332
+ /**
333
+ * Project an orchestration status onto a persisted execution status. EXHAUSTIVE on purpose (Phase
334
+ * 3.4): the previous catch-all silently persisted an unrecognized status as
335
+ * `waiting_for_clarification` — resumable, answerable with a text answer, and wrong. The mapping of
336
+ * the six existing members is unchanged.
337
+ */
157
338
  private execStatus;
158
339
  private mapOutcome;
159
340
  private resultFromExecution;
@@ -177,7 +358,59 @@ export declare class Runtime {
177
358
  approve?: boolean;
178
359
  signal?: AbortSignal;
179
360
  }): Promise<RuntimeResult>;
361
+ /**
362
+ * THE single source of step runners, used by both the fresh-run path and the resume-continue path.
363
+ * They used to drift: resume built its own pair with no agent runner, so a persisted plan containing
364
+ * an agent step would have failed every one of those steps.
365
+ */
180
366
  private orchestrateRunners;
367
+ /**
368
+ * A bounded, fenced brief of what the agents have already established (Phase 3.5).
369
+ *
370
+ * On drift the plan is thrown away and the goal is replanned — but validated findings are facts about
371
+ * the WORKSPACE, not about the plan's structure, so discarding them silently would make the run redo
372
+ * work it had already proved. They are agent-authored text, so they cross a prompt boundary fenced,
373
+ * exactly like every other untrusted string.
374
+ */
375
+ private findingsBrief;
376
+ /**
377
+ * Fingerprint the MCP tools a plan actually references (Phase 3.5). An MCP server is remote and
378
+ * mutable: while a plan sits paused it can change a tool's input schema, change what it does, or drop
379
+ * it entirely — and the plan would then be resumed against a tool that is no longer the tool it was
380
+ * planned for. Hashing the live declaration makes that visible as ordinary drift.
381
+ *
382
+ * Non-MCP tools are deliberately absent: they are in-tree code covered by the config/skill hashes.
383
+ */
384
+ private mcpToolHashes;
385
+ /**
386
+ * Crash / pause / cancel reconciliation (Phase 3.5). A record left `running` or `created` describes a
387
+ * worker that no longer exists — the process died, or the parent stopped it — so it goes back to
388
+ * `queued` with an auditable reason. An interruption is deliberately NOT a state: the lifecycle does
389
+ * not grow, only the explanation does.
390
+ *
391
+ * This runs on the RESUME path and inside pause/cancel. Resume alone is not enough: `cancelExecution`
392
+ * writes a terminal status and resume early-returns on terminal, so a cancelled execution's `running`
393
+ * records would stay `running` on disk forever, unstamped and unexplained.
394
+ *
395
+ * Records that fail validation are preserved in place, never dropped — reconciling is not a licence to
396
+ * delete what this version could not parse.
397
+ */
398
+ private reconcileAgentTasks;
399
+ /**
400
+ * FIRST-WINS PENDING. `Execution.pending` is a single slot but two agents can be waiting at once, so
401
+ * the earliest-created waiting task claims it. The others are not lost: once this one is answered and
402
+ * the run continues, the next resume re-elects whichever task is still waiting — rediscovery, rather
403
+ * than a queue that has to be kept in sync with the records that are already the source of truth.
404
+ */
405
+ private electWaitingAgent;
406
+ /**
407
+ * Which persisted task, if any, a plan step should CONTINUE. Bound by step-input hash, never by step
408
+ * id: plan step ids (`s1`, `auto1`) are model-authored and recur across replans, so an id match would
409
+ * hand one step's completed inner work to a different step with the same id and a different input.
410
+ */
411
+ private agentResumeLookup;
412
+ /** Abort a run that is in flight, recording WHY so a task can tell a pause from a cancellation. */
413
+ private abortLiveRun;
181
414
  /** Mark an execution paused (it can be resumed later). */
182
415
  pauseExecution(id: string): boolean;
183
416
  /** Cancel an execution (terminal). */