@sema-agent/core 5.19.0 → 5.21.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 (329) hide show
  1. package/CHANGELOG.md +102 -4
  2. package/dist/agents/agent-definition.d.ts +7 -0
  3. package/dist/agents/agent-transcript-tool.d.ts +30 -0
  4. package/dist/agents/builtin-agents.d.ts +60 -0
  5. package/dist/agents/cascade.d.ts +107 -0
  6. package/dist/agents/cumulative-stats.d.ts +56 -0
  7. package/dist/agents/observer.d.ts +162 -0
  8. package/dist/agents/peer-admission.d.ts +95 -0
  9. package/dist/agents/repair-loop.d.ts +226 -0
  10. package/dist/agents/retain-ledger.d.ts +141 -0
  11. package/dist/agents/roster-store.d.ts +105 -0
  12. package/dist/agents/roster-store.js +3 -0
  13. package/dist/agents/send-message-tool.d.ts +92 -0
  14. package/dist/agents/session-util.d.ts +5 -0
  15. package/dist/agents/subagent-steps.d.ts +66 -0
  16. package/dist/agents/subagent.d.ts +600 -0
  17. package/dist/agents/suspend-guard.d.ts +29 -0
  18. package/dist/agents/teacher.d.ts +75 -0
  19. package/dist/agents/team.d.ts +120 -1
  20. package/dist/agents/tool-filter.d.ts +34 -0
  21. package/dist/agents/verify.d.ts +198 -0
  22. package/dist/bench/metrics.d.ts +455 -0
  23. package/dist/brain/anthropic.d.ts +30 -0
  24. package/dist/brain/circuit-breaker.d.ts +33 -0
  25. package/dist/brain/circuit-breaker.js +14 -3
  26. package/dist/brain/context-overflow.d.ts +60 -3
  27. package/dist/brain/degrading.d.ts +67 -0
  28. package/dist/brain/errors.d.ts +42 -0
  29. package/dist/brain/failover.d.ts +15 -0
  30. package/dist/brain/media-degrade.d.ts +39 -0
  31. package/dist/brain/model-presets.d.ts +31 -0
  32. package/dist/brain/open-responses.d.ts +19 -0
  33. package/dist/brain/openai.d.ts +46 -0
  34. package/dist/brain/reasoning.d.ts +106 -1
  35. package/dist/brain/repetition.d.ts +83 -0
  36. package/dist/brain/request-params.d.ts +56 -0
  37. package/dist/brain/retry.d.ts +46 -0
  38. package/dist/brain/routing.d.ts +12 -0
  39. package/dist/brain/status-sink.d.ts +30 -1
  40. package/dist/brain/stream-engine.d.ts +147 -0
  41. package/dist/brain/stream-shared.d.ts +34 -0
  42. package/dist/brain/terminal-cause.d.ts +31 -0
  43. package/dist/brain/timeout.d.ts +108 -0
  44. package/dist/brain/timeout.js +11 -0
  45. package/dist/brain/tool-call-id.d.ts +20 -0
  46. package/dist/brain/tool-call-repair.d.ts +13 -0
  47. package/dist/config/catalog.d.ts +47 -0
  48. package/dist/config/defaults.d.ts +33 -0
  49. package/dist/core/a2a-task-state.d.ts +53 -0
  50. package/dist/core/a2a.d.ts +51 -0
  51. package/dist/core/arg-summary.d.ts +62 -0
  52. package/dist/core/ask-question.d.ts +272 -2
  53. package/dist/core/auto-compaction.d.ts +467 -0
  54. package/dist/core/auto-compaction.js +20 -6
  55. package/dist/core/auto-mode-prompt-assets.d.ts +8 -0
  56. package/dist/core/auto-mode-prompt.d.ts +27 -0
  57. package/dist/core/auto-mode.d.ts +54 -3
  58. package/dist/core/auto-promote.d.ts +100 -0
  59. package/dist/core/background-agent-store.d.ts +293 -0
  60. package/dist/core/background-agent-store.js +5 -0
  61. package/dist/core/background-shell.d.ts +110 -0
  62. package/dist/core/cache-break-detector.d.ts +34 -0
  63. package/dist/core/canonical-json.d.ts +57 -0
  64. package/dist/core/checkpoint-store.d.ts +1574 -16
  65. package/dist/core/compliance.d.ts +30 -0
  66. package/dist/core/consolidate-scope.d.ts +75 -0
  67. package/dist/core/context-edit.d.ts +99 -0
  68. package/dist/core/context-guard.d.ts +46 -0
  69. package/dist/core/exec-gate.d.ts +44 -0
  70. package/dist/core/exec-output-tail.d.ts +61 -0
  71. package/dist/core/file-snapshot-store.d.ts +104 -0
  72. package/dist/core/fs-write-gate-policy.d.ts +36 -0
  73. package/dist/core/git-worktree-env.d.ts +31 -0
  74. package/dist/core/governance-codes.d.ts +19 -0
  75. package/dist/core/hooks.d.ts +609 -1
  76. package/dist/core/human-input-projection.d.ts +37 -0
  77. package/dist/core/human-input-projection.js +13 -0
  78. package/dist/core/image-downsample.d.ts +74 -0
  79. package/dist/core/locked-config.d.ts +37 -0
  80. package/dist/core/lsp-diagnostics.d.ts +77 -0
  81. package/dist/core/lsp-protocol.d.ts +29 -0
  82. package/dist/core/lsp-session.d.ts +60 -1
  83. package/dist/core/lsp.d.ts +150 -1
  84. package/dist/core/mailbox-store.d.ts +57 -0
  85. package/dist/core/mailbox-store.js +2 -0
  86. package/dist/core/mcp.d.ts +385 -0
  87. package/dist/core/mcp.js +58 -11
  88. package/dist/core/media-byte-cap.d.ts +21 -0
  89. package/dist/core/memory-admission.d.ts +71 -0
  90. package/dist/core/memory-engine/content-origin.d.ts +64 -0
  91. package/dist/core/memory-engine/data-plane.d.ts +43 -0
  92. package/dist/core/memory-engine/dual-root.d.ts +24 -0
  93. package/dist/core/memory-engine/engine.d.ts +230 -0
  94. package/dist/core/memory-engine/engine.js +103 -35
  95. package/dist/core/memory-engine/file-backend.d.ts +155 -0
  96. package/dist/core/memory-engine/frontmatter.d.ts +16 -0
  97. package/dist/core/memory-engine/layout.d.ts +217 -0
  98. package/dist/core/memory-engine/memory-backend-contract.d.ts +12 -0
  99. package/dist/core/memory-engine/migrate.d.ts +9 -0
  100. package/dist/core/memory-engine/scan.d.ts +12 -0
  101. package/dist/core/memory-engine/scope-contract.d.ts +61 -1
  102. package/dist/core/memory-engine/sync-client.d.ts +87 -0
  103. package/dist/core/memory-engine/sync.d.ts +60 -0
  104. package/dist/core/memory-engine/tools.d.ts +41 -0
  105. package/dist/core/memory-engine/types.d.ts +188 -0
  106. package/dist/core/memory-recall.d.ts +141 -0
  107. package/dist/core/memory-vector.d.ts +20 -0
  108. package/dist/core/memory.d.ts +458 -0
  109. package/dist/core/message-utils.d.ts +6 -0
  110. package/dist/core/oracle-isolation.d.ts +69 -0
  111. package/dist/core/permission-rule-consent.d.ts +138 -0
  112. package/dist/core/permission-rule-model.d.ts +122 -0
  113. package/dist/core/permission-rule-store.d.ts +119 -3
  114. package/dist/core/permission-rules.d.ts +87 -1
  115. package/dist/core/present-plan-tool.d.ts +20 -0
  116. package/dist/core/pricing.d.ts +26 -0
  117. package/dist/core/property-harness.d.ts +86 -0
  118. package/dist/core/protocol-naming.d.ts +38 -0
  119. package/dist/core/protocol-table.d.ts +61 -0
  120. package/dist/core/push-queue.d.ts +1 -0
  121. package/dist/core/remote-env.d.ts +383 -1
  122. package/dist/core/retention-policy.d.ts +40 -0
  123. package/dist/core/retention-policy.js +21 -0
  124. package/dist/core/retention.d.ts +51 -0
  125. package/dist/core/roles.d.ts +59 -0
  126. package/dist/core/runner/active-skill-scope.d.ts +34 -0
  127. package/dist/core/runner/assemble-result.d.ts +134 -0
  128. package/dist/core/runner/compaction-call-options.d.ts +97 -1
  129. package/dist/core/runner/grounding-signal.d.ts +10 -0
  130. package/dist/core/runner/image.d.ts +17 -0
  131. package/dist/core/runner/image.js +29 -15
  132. package/dist/core/runner/memory-consolidation.d.ts +60 -0
  133. package/dist/core/runner/prepare-memory.d.ts +59 -0
  134. package/dist/core/runner/prepare-task.d.ts +1011 -2
  135. package/dist/core/runner/prepare-task.js +51 -14
  136. package/dist/core/runner/prompt-suggestions.d.ts +7 -0
  137. package/dist/core/runner/runtask.d.ts +304 -3
  138. package/dist/core/runner/runtask.js +17 -2
  139. package/dist/core/runner/session-file-state-replay.d.ts +49 -0
  140. package/dist/core/runner/session-rule-policy.d.ts +58 -0
  141. package/dist/core/runner/strict-output-schema.d.ts +18 -3
  142. package/dist/core/runner/synthetic-tools.d.ts +113 -0
  143. package/dist/core/runner/teardown-bounded.d.ts +34 -0
  144. package/dist/core/runner/tool-disclosure.d.ts +227 -0
  145. package/dist/core/runner/tool-output-projection.d.ts +6 -0
  146. package/dist/core/runner/turn-attachments.d.ts +634 -0
  147. package/dist/core/runner/usage-accounting.d.ts +32 -0
  148. package/dist/core/runtime.d.ts +9 -0
  149. package/dist/core/safe-notify.d.ts +64 -0
  150. package/dist/core/safety-axis-vocab.d.ts +23 -0
  151. package/dist/core/safety-merge-corpus.d.ts +37 -0
  152. package/dist/core/scheduler.d.ts +121 -0
  153. package/dist/core/secret-env.d.ts +32 -0
  154. package/dist/core/select-model.d.ts +15 -0
  155. package/dist/core/sensitive-path-policy.d.ts +42 -0
  156. package/dist/core/session-policy-store.d.ts +94 -0
  157. package/dist/core/session-reconcile.d.ts +80 -0
  158. package/dist/core/session-store.d.ts +85 -0
  159. package/dist/core/session.d.ts +153 -0
  160. package/dist/core/shared-memory/contract.d.ts +22 -0
  161. package/dist/core/shared-memory/normalize.d.ts +123 -2
  162. package/dist/core/shared-memory/tools.d.ts +14 -0
  163. package/dist/core/shared-memory/types.d.ts +105 -0
  164. package/dist/core/shutdown-debug.d.ts +6 -0
  165. package/dist/core/side-query.d.ts +38 -0
  166. package/dist/core/side-query.js +6 -1
  167. package/dist/core/skill-tool-specifier.d.ts +72 -0
  168. package/dist/core/skills-directory.d.ts +100 -1
  169. package/dist/core/spec-contract.d.ts +89 -0
  170. package/dist/core/store-contracts/background-agent-store-contract.d.ts +31 -0
  171. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +26 -0
  172. package/dist/core/store-contracts/contract-harness.d.ts +20 -0
  173. package/dist/core/store-contracts/contract-kit-version.d.ts +27 -0
  174. package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +8 -0
  175. package/dist/core/store-contracts/mailbox-store-contract.d.ts +42 -0
  176. package/dist/core/store-contracts/tool-result-store-contract.d.ts +13 -0
  177. package/dist/core/strategy-store.d.ts +37 -0
  178. package/dist/core/stub-env.d.ts +7 -0
  179. package/dist/core/surrogate-safe-slice.d.ts +35 -0
  180. package/dist/core/task-notification.d.ts +202 -0
  181. package/dist/core/task-outcome.d.ts +53 -0
  182. package/dist/core/task-registry-agent.d.ts +337 -1
  183. package/dist/core/task-registry-agent.js +2 -0
  184. package/dist/core/task-registry-monitor.d.ts +12 -0
  185. package/dist/core/task-registry-shared.d.ts +540 -0
  186. package/dist/core/task-registry.d.ts +343 -0
  187. package/dist/core/task-registry.js +13 -2
  188. package/dist/core/task-tool-shape.d.ts +44 -0
  189. package/dist/core/tighten-task-spec.d.ts +21 -0
  190. package/dist/core/tool-detach.d.ts +21 -0
  191. package/dist/core/tool-errors.d.ts +131 -0
  192. package/dist/core/tool-errors.js +4 -0
  193. package/dist/core/tool-name-aliases.d.ts +27 -0
  194. package/dist/core/tool-policy.d.ts +555 -0
  195. package/dist/core/tool-policy.js +3 -0
  196. package/dist/core/tool-result-budget.d.ts +32 -0
  197. package/dist/core/tool-result-store.d.ts +174 -1
  198. package/dist/core/tools.d.ts +45 -0
  199. package/dist/core/trace.d.ts +323 -0
  200. package/dist/core/types.d.ts +3859 -2
  201. package/dist/core/untrusted-egress.d.ts +8 -0
  202. package/dist/core/untrusted-text.d.ts +156 -0
  203. package/dist/core/usage-window-store.d.ts +95 -0
  204. package/dist/core/version.d.ts +1 -0
  205. package/dist/core/warm-resume.d.ts +17 -0
  206. package/dist/core/wiring-manifest.d.ts +169 -0
  207. package/dist/core/with-retry.d.ts +24 -0
  208. package/dist/core/workflow-journal-store.d.ts +160 -0
  209. package/dist/core/workflow-run-store-contract.d.ts +25 -0
  210. package/dist/core/workflow-run-store.d.ts +119 -0
  211. package/dist/core/workflow-run-store.js +2 -0
  212. package/dist/engine/compaction/compaction.d.ts +256 -1
  213. package/dist/engine/compaction/utils.d.ts +94 -0
  214. package/dist/engine/execution-env/kill-tree.d.ts +29 -0
  215. package/dist/engine/execution-env/node-execution-env.d.ts +94 -0
  216. package/dist/engine/harness/agent-harness.d.ts +116 -0
  217. package/dist/engine/harness/agent-harness.js +3 -14
  218. package/dist/engine/harness/messages.d.ts +15 -0
  219. package/dist/engine/harness/types.d.ts +464 -2
  220. package/dist/engine/llm/diagnostics.d.ts +4 -0
  221. package/dist/engine/llm/event-stream.d.ts +3 -0
  222. package/dist/engine/llm/index.d.ts +7 -0
  223. package/dist/engine/llm/types.d.ts +500 -3
  224. package/dist/engine/llm/validation.d.ts +3 -0
  225. package/dist/engine/loop/agent-loop.d.ts +87 -2
  226. package/dist/engine/loop/runtime-deps.d.ts +7 -0
  227. package/dist/engine/loop/types.d.ts +424 -0
  228. package/dist/engine/lsp/frame-decoder.d.ts +13 -0
  229. package/dist/engine/lsp/node-lsp-manager.d.ts +107 -0
  230. package/dist/engine/lsp/stdio-lsp-transport.d.ts +7 -0
  231. package/dist/engine/session/import-validate.d.ts +27 -0
  232. package/dist/engine/session/log-digest.d.ts +93 -0
  233. package/dist/engine/session/memory-repo.d.ts +6 -0
  234. package/dist/engine/session/memory-storage.d.ts +2 -0
  235. package/dist/engine/session/session.d.ts +75 -0
  236. package/dist/engine/session/storage-base.d.ts +8 -0
  237. package/dist/fixtures/index.d.ts +36 -0
  238. package/dist/index.d.ts +17 -2
  239. package/dist/index.js +1 -2
  240. package/dist/internal/harness-types.d.ts +6 -0
  241. package/dist/internal/harness.d.ts +11 -0
  242. package/dist/internal/llm.d.ts +6 -0
  243. package/dist/orchestration/builtin-workflows.d.ts +53 -0
  244. package/dist/orchestration/dev-vm-script-runner.d.ts +19 -0
  245. package/dist/orchestration/goal.d.ts +57 -0
  246. package/dist/orchestration/goal.js +3 -0
  247. package/dist/orchestration/run-spec.d.ts +42 -0
  248. package/dist/orchestration/run-spec.js +4 -0
  249. package/dist/orchestration/run-workflow-tool.d.ts +169 -0
  250. package/dist/orchestration/workflow-governance.d.ts +61 -0
  251. package/dist/orchestration/workflow-meta.d.ts +28 -0
  252. package/dist/orchestration/workflow-observe.d.ts +60 -0
  253. package/dist/orchestration/workflow-primitives.d.ts +23 -1
  254. package/dist/orchestration/workflow-sandbox-conformance.d.ts +38 -0
  255. package/dist/orchestration/workflow-script-runner.d.ts +88 -0
  256. package/dist/orchestration/workflow-script-store.d.ts +98 -0
  257. package/dist/orchestration/workflow-size-guideline.d.ts +67 -0
  258. package/dist/orchestration/workflow-types.d.ts +169 -2
  259. package/dist/orchestration/workflow.d.ts +358 -0
  260. package/dist/orchestration/workflow.js +13 -2
  261. package/dist/prompt-assembly/artifact-store.d.ts +33 -0
  262. package/dist/prompt-assembly/artifact.d.ts +25 -0
  263. package/dist/prompt-assembly/assemble.d.ts +20 -0
  264. package/dist/prompt-assembly/composer.d.ts +29 -0
  265. package/dist/prompt-assembly/epoch.d.ts +55 -1
  266. package/dist/prompt-assembly/event-registry.d.ts +35 -0
  267. package/dist/prompt-assembly/explain.d.ts +12 -0
  268. package/dist/prompt-assembly/tool-catalog.d.ts +38 -0
  269. package/dist/prompt-assembly/turn-snapshot.d.ts +40 -0
  270. package/dist/prompt-assembly/types.d.ts +115 -0
  271. package/dist/prompts/coordinator.d.ts +27 -0
  272. package/dist/prompts/default.d.ts +539 -0
  273. package/dist/prompts/simple-sections.d.ts +45 -0
  274. package/dist/prompts/supervisor.d.ts +66 -0
  275. package/dist/scenarios/env.d.ts +28 -0
  276. package/dist/scenarios/full-body.d.ts +50 -0
  277. package/dist/scenarios/scenario-registry.d.ts +60 -0
  278. package/dist/scenarios/teacher-quickstart.d.ts +27 -0
  279. package/dist/server/http.d.ts +17 -0
  280. package/dist/stores/cc/lockfile.d.ts +6 -0
  281. package/dist/stores/cc/mailbox-store.d.ts +8 -0
  282. package/dist/stores/cc/roster-adapter.d.ts +4 -0
  283. package/dist/stores/cc/sidecar-transcript.d.ts +66 -0
  284. package/dist/stores/file/background-agent-store.d.ts +24 -0
  285. package/dist/stores/file/background-agent-store.js +2 -1
  286. package/dist/stores/file/checkpoint-store.d.ts +38 -0
  287. package/dist/stores/file/file-snapshot-store.d.ts +25 -0
  288. package/dist/stores/file/fs-atomic.d.ts +155 -0
  289. package/dist/stores/file/index.d.ts +89 -0
  290. package/dist/stores/file/mailbox-store.d.ts +36 -0
  291. package/dist/stores/file/mailbox-store.js +2 -0
  292. package/dist/stores/file/memory-store.d.ts +82 -0
  293. package/dist/stores/file/permission-rule-store.d.ts +79 -0
  294. package/dist/stores/file/session-policy-store.d.ts +28 -0
  295. package/dist/stores/file/session-store.d.ts +40 -0
  296. package/dist/stores/file/shared-ledger.d.ts +83 -0
  297. package/dist/stores/file/tool-result-store.d.ts +11 -0
  298. package/dist/stores/file/usage-window-store.d.ts +18 -0
  299. package/dist/stores/file/workflow-journal-store.d.ts +100 -0
  300. package/dist/stores/file/workflow-run-store.d.ts +11 -0
  301. package/dist/stores/file/workflow-run-store.js +2 -0
  302. package/dist/tools/fs/bash-readonly-classifier.d.ts +282 -0
  303. package/dist/tools/fs/encoding.d.ts +60 -0
  304. package/dist/tools/fs/fs-bash.d.ts +133 -0
  305. package/dist/tools/fs/fs-pdf.d.ts +28 -0
  306. package/dist/tools/fs/fs-search-tools.d.ts +5 -0
  307. package/dist/tools/fs/fs-shared.d.ts +360 -0
  308. package/dist/tools/fs/fs-write.d.ts +16 -0
  309. package/dist/tools/fs/gh-rate-limit.d.ts +22 -0
  310. package/dist/tools/fs/index.d.ts +79 -0
  311. package/dist/tools/fs/notebook.d.ts +56 -0
  312. package/dist/tools/fs/pdf.d.ts +70 -0
  313. package/dist/tools/fs/pdf.js +8 -2
  314. package/dist/tools/fs/repo-map.d.ts +10 -0
  315. package/dist/tools/fs/safety.d.ts +376 -0
  316. package/dist/tools/fs/search.d.ts +131 -0
  317. package/dist/tools/loop-tick.d.ts +24 -0
  318. package/dist/tools/monitor.d.ts +55 -0
  319. package/dist/tools/scheduler-tools.d.ts +51 -0
  320. package/dist/tools/sql-adapters.d.ts +18 -0
  321. package/dist/tools/sql.d.ts +25 -0
  322. package/dist/tools/task-list.d.ts +77 -0
  323. package/dist/tools/todo.d.ts +8 -0
  324. package/dist/tools/web.d.ts +184 -0
  325. package/dist/tools/web.js +32 -5
  326. package/dist/tools/worktree.d.ts +81 -0
  327. package/package.json +2 -2
  328. package/dist/tools/gitea-issue.d.ts +0 -13
  329. package/dist/tools/gitea-issue.js +0 -75
@@ -1,19 +1,80 @@
1
+ /**
2
+ * Protocol namespace table (roadmap 2026-08-02, the non-additive precondition for a second protocol).
3
+ *
4
+ * design/108 ① established ONE namespaced family — `mcp__<server>__<tool>` — and six call sites grew
5
+ * their own hard-coded `"mcp__"` reads (origin projection, grouped display, permission-rule lanes,
6
+ * the `__` reservation message). Each new protocol would need a twin branch at every site. This table
7
+ * makes "which protocol owns this tool name" a lookup: a second protocol (e.g. A2A) lands by
8
+ * APPENDING one entry, and every table-driven site picks it up unchanged.
9
+ *
10
+ * Dependency-free by design (pure string logic) — `mcp.ts` re-exports {@link MCP_NAMESPACE}'s prefix
11
+ * as its public `MCP_PREFIX` face, never the other way around. The MINTING pipeline (charset
12
+ * normalization + the assembled-name budget, which needs a digest) lives in `protocol-naming.ts`, which
13
+ * imports this module's type; the dependency never runs the other way, so this file stays dependency-free.
14
+ */
15
+ /** The ids of every protocol the engine speaks. Doubles as the protocol slice of the tool-manifest
16
+ * `ToolOrigin` union — adding a protocol extends BOTH (tsc pairs the change). */
1
17
  export type ProtocolId = "mcp" | "a2a";
18
+ /** The (peer, tool) pair a namespaced wire name decomposes into. */
2
19
  export interface ProtocolPeerTool {
3
20
  peer: string;
4
21
  tool: string;
5
22
  }
23
+ /**
24
+ * One tool-name namespace owned by an external protocol (design/108 ① generalized).
25
+ *
26
+ * `P` carries the namespace's prefix as a LITERAL type so a public face re-exporting it (mcp.ts's
27
+ * `MCP_PREFIX`) keeps `"mcp__"` rather than widening to `string` — a widened prefix compiles fine
28
+ * here while breaking every downstream literal-typed position, and the export-surface snapshot
29
+ * (name → kind) cannot see that class of change at all.
30
+ */
6
31
  export interface ProtocolNamespace<P extends string = string> {
32
+ /** Stable protocol id — doubles as the tool-manifest origin tag (e.g. `"mcp"`). */
7
33
  readonly id: ProtocolId;
34
+ /** Global marker prefix (`mcp__`). A name in this namespace starts with it; no caller tool name may
35
+ * contain the `__` separator at all (prepare-task's reservation enforces the umbrella). */
8
36
  readonly prefix: P;
37
+ /**
38
+ * Compose the wire name for a (peer, tool) pair.
39
+ *
40
+ * NAME SHAPE ONLY — this is the namespace's spelling contract (prefix + separator placement), NOT the
41
+ * full minting pipeline: sanitizing and length-clamping the segments is `protocol-naming.ts`'s
42
+ * `mintNamespacedToolName`, which every protocol registering real tools goes through. Composing a raw,
43
+ * unsanitized pair here yields a syntactically valid name that no mint would have produced — use this
44
+ * leg for a name whose segments are already known-good (a test, a display form), the mint otherwise.
45
+ *
46
+ * NAMING CONSTRAINTS (enforced by a THROW, not a silent mangle): `peer` and `tool` must be non-empty and
47
+ * `peer` must not contain the `__` separator. A separator inside `peer` makes the name un-round-trippable
48
+ * — {@link parse} splits at the FIRST separator, so `("prod__db", "query")` reads back as peer `"prod"`,
49
+ * tool `"db__query"` — i.e. a name that silently denotes a different peer than the caller asked for.
50
+ * `tool` may contain the separator (it is the trailing remainder and round-trips verbatim).
51
+ */
9
52
  makeName(peer: string, tool: string): string;
53
+ /** Parse a wire name; `undefined` when the name is not in this namespace (or malformed inside it —
54
+ * empty peer segment or empty tool segment both count as malformed). */
10
55
  parse(name: string): ProtocolPeerTool | undefined;
56
+ /** Collapsed display key for grouped listings (`mcp__<server>__*`); identity for a malformed name. */
11
57
  displayGroupKey(name: string): string;
12
58
  }
13
59
  declare const MCP_PREFIX_NAME: "mcp__";
60
+ /** A2A's marker prefix. `a2a__<peer>__<skill>`: `peer` is the remote agent (whatever id the deployment
61
+ * knows it by), `skill` the capability that agent advertises — the same two-segment shape MCP uses, so
62
+ * every table-driven site (origin projection, grouped display, the caller-name reservation) reads it
63
+ * unchanged. Deliberately NOT a prefix of, nor prefixed by, `mcp__`. */
14
64
  declare const A2A_PREFIX_NAME: "a2a__";
15
65
  export declare const MCP_NAMESPACE: ProtocolNamespace<typeof MCP_PREFIX_NAME>;
66
+ /**
67
+ * The A2A tool namespace (roadmap 2026-08-03, appended for the A2A client/server work).
68
+ *
69
+ * NAME LAYER ONLY: this entry decides how an A2A tool name is SPELLED and how it decomposes. Nothing
70
+ * materializes A2A tools yet — until the client leg lands, no name in this namespace can exist at runtime,
71
+ * so appending the entry changes no live behavior. It exists first because every table-driven site
72
+ * (`protocolOf`, the grouped display key, the `ToolOrigin` union) then needs no change when it does.
73
+ */
16
74
  export declare const A2A_NAMESPACE: ProtocolNamespace<typeof A2A_PREFIX_NAME>;
75
+ /** Every protocol namespace the engine knows. APPEND-ONLY: adding a protocol must not change how any
76
+ * existing name resolves — prefixes must stay pairwise non-overlapping (pinned in the table test). */
17
77
  export declare const PROTOCOL_TABLE: readonly ProtocolNamespace[];
78
+ /** The namespace owning `name`, or `undefined` for a caller/first-party tool. */
18
79
  export declare function protocolOf(name: string): ProtocolNamespace | undefined;
19
80
  export {};
@@ -1,3 +1,4 @@
1
+ /** A minimal async iterable you can push values into and close. Backpressure-free (buffers). */
1
2
  export declare class PushQueue<T> implements AsyncIterable<T> {
2
3
  private buffer;
3
4
  private waiters;
@@ -1,29 +1,124 @@
1
+ /**
2
+ * Remote execution seam (design/48 §5) — the type-only contract a **remote/containerised** `ExecutionEnv`
3
+ * implementation (E2B/Firecracker, owned by the service control plane) must satisfy so the agent's "hand"
4
+ * (design/44) can act inside an isolated, *stateful*, *suspendable* workspace instead of the in-process
5
+ * `NodeExecutionEnv`.
6
+ *
7
+ * **This file is a SEAM, not an implementation.** The real `RemoteContainerExecutionEnv` (E2B SDK, warm
8
+ * pools, snapshot lifecycle, tier routing) lives in the service and is driven by real integration needs —
9
+ * exactly like `CheckpointStore` (design/45). Core owns the seam shape; service owns the backend.
10
+ *
11
+ * Design rulings folded in (design/48 §10/§11 DeepSeek council):
12
+ * - **#1 [blocker] interface extension, not capability probing**: `RemoteExecutionEnv extends ExecutionEnv`.
13
+ * The base {@link ExecutionEnv} is UNCHANGED — `NodeExecutionEnv`/`StubExecutionEnv` need zero edits, and a
14
+ * consumer that only needs buffered fs/shell keeps accepting the base type.
15
+ * - **#3 [major] do not overload `exec`**: `exec()` stays buffered; streaming is a NEW {@link execStream}.
16
+ * - **#4 [major] suspend × in-flight exec must not hang**: see {@link suspendVM}.
17
+ * - **#8 [major] post-resume consistency**: see {@link postResumeInit}.
18
+ * - **#10 naming**: the isolation level is `sandboxTier` (not `tier`) to avoid clashing with the existing
19
+ * timeout-/degradation-"tier" in the codebase.
20
+ * - **#16 suspend/resume disambiguation**: the VM-lifecycle methods are `suspendVM`/`resumeVM` to keep them
21
+ * distinct from the Runner gate-resume and design/45 wake/resume semantics.
22
+ *
23
+ * **Deferred (NOT modelled here — they are runtime, not seam):** actually suspending a running task and
24
+ * persisting the {@link WorkspaceHandle} into a design/45 `Checkpoint`; the `status:"suspended"` orchestrator
25
+ * mapping; tier *classification* (the static table + Tier1-safe allow-list + fail-closed routing) — all are
26
+ * service/design-45 implementation-time concerns. Core only declares the seam those will plug into.
27
+ */
1
28
  import type { ExecutionEnv } from "../internal/harness-types.js";
29
+ /** Snapshot identifier returned by {@link RemoteExecutionEnv.suspendVM}; opaque to core, resolved by the provider. */
2
30
  export type SnapshotId = string;
31
+ /**
32
+ * Token identifying a still-running remote session, used by {@link RemoteExecutionEnv.reconnect} to re-attach
33
+ * the control plane's transport after a control-plane replica crash/failover. The underlying VM state lives
34
+ * independently of any single control-plane TCP connection (a Firecracker process survives a dropped client),
35
+ * so reconnect re-binds rather than re-creates.
36
+ */
3
37
  export type SessionToken = string;
38
+ /** Isolation routing level (design/48 §2). v1 runs everything as Tier 2; classification is DEFERRED to service. */
4
39
  export type SandboxTier = 1 | 2;
40
+ /**
41
+ * Serializable identity of a remote workspace (design/48 §5 gap 1). The control plane persists this into its
42
+ * durable state (and design/45 `Checkpoint`) so a *different* replica can reconnect/resume the same workspace.
43
+ */
5
44
  export interface WorkspaceHandle {
45
+ /** Provider/VM/sandbox id (e.g. an E2B sandbox id). */
6
46
  sandboxId: string;
47
+ /** Provider identifier (e.g. `"e2b"`), so the control plane routes reconnect/destroy to the right backend. */
7
48
  provider: string;
49
+ /** Absolute mount path of the workspace root inside the remote env; remote paths normalize against this. */
8
50
  mountPath: string;
51
+ /** Set when this env was produced by resuming a snapshot ({@link RemoteExecutionEnv.resumeVM}), else undefined. */
9
52
  snapshotId?: SnapshotId;
53
+ /** Token for {@link RemoteExecutionEnv.reconnect} when the VM is still running (vs suspended to a snapshot). */
10
54
  sessionToken?: SessionToken;
55
+ /** How a checkpointed workspace is restored on resume (1.257.2 hardening, codex review of [500]②):
56
+ * `"park_only"` = durable-park-only suspend degrade (non-suspendable env; workspace persists on the
57
+ * target, resume skips `resumeVM`). Absent = legacy/snapshot handle — resume treats a MISSING
58
+ * `snapshotId` as corruption (fail-closed) unless the resumed env is itself non-suspendable
59
+ * (tolerance for park handles minted by 1.257.1 before this field existed). */
11
60
  restoreMode?: "park_only";
12
61
  }
62
+ /**
63
+ * A reference to a secret injected at {@link RemoteExecutionEnv.connect}/{@link RemoteExecutionEnv.postResumeInit}
64
+ * time (design/48 §5 gap 7) — never baked into the image. The control plane resolves {@link ref} to a value out of
65
+ * band; only the reference travels through core.
66
+ */
13
67
  export interface SecretRef {
68
+ /** Logical name the secret is exposed under (an env-var name in the remote env for `destination:"remote"`). */
14
69
  name: string;
70
+ /** Opaque locator the control plane resolves to a value (vault path, KMS key id, …). */
15
71
  ref: string;
72
+ /**
73
+ * Where the resolved secret is consumed (design/61 §9 B, council). Default `"remote"` (the original
74
+ * semantics): injected **into the remote env** as `name` (E2B env-var) — visible to code running there.
75
+ * `"adapter"`: used by the **adapter itself** to establish/authenticate the connection (an SSH private key,
76
+ * an ADB token) and **MUST NOT be injected into the target machine/device** — a credential that reaches an
77
+ * un-isolated target's environment is the lethal trifecta (design/53 §C). An adapter MUST honor this.
78
+ */
16
79
  destination?: "remote" | "adapter";
17
80
  }
81
+ /** Configuration for {@link RemoteExecutionEnv.connect}. */
18
82
  export interface RemoteConnectConfig {
83
+ /** Resume from this snapshot instead of provisioning a fresh workspace. */
19
84
  snapshotId?: SnapshotId;
85
+ /** Secrets to inject at connect time (design/48 §5 gap 7). */
20
86
  secrets?: SecretRef[];
87
+ /** Abort provisioning/connection. */
21
88
  abortSignal?: AbortSignal;
22
89
  }
90
+ /**
91
+ * Options for the VM-lifecycle ops {@link RemoteExecutionEnv.suspendVM} / {@link RemoteExecutionEnv.resumeVM}
92
+ * (design/49 v1.5, code-ready council BUG#2). Parity with {@link RemoteConnectConfig.abortSignal} /
93
+ * {@link ExecStreamOptions.signal}: without an abort hook a hung provider pause/restore (network partition)
94
+ * would pin the calling worker forever. The implementation races the op against this signal + an internal
95
+ * timeout; on abort it returns `{ok:false}` with code `"aborted"`.
96
+ */
23
97
  export interface VmLifecycleOptions {
98
+ /** Abort a hung pause/restore. */
24
99
  abortSignal?: AbortSignal;
100
+ /**
101
+ * [1461]④a (resume workspace-root fidelity) — the CHECKPOINTED {@link WorkspaceHandle} of the workspace
102
+ * being restored, passed by the engine on the `resumeVM` leg. An adapter SHOULD bind the restored
103
+ * workspace root (cwd / mount) to `priorHandle.mountPath` rather than its CURRENT deployment
104
+ * configuration: across a config-knob change window (e.g. a mount-path rotation) the resumed task's
105
+ * execs and artifacts must land in the root the task was checkpointed under, not the new one. An
106
+ * adapter that cannot honor the prior root MUST still return its ACTUAL `mountPath` in the restored
107
+ * handle (never echo `priorHandle.mountPath` unhonored) — the engine compares the two and surfaces a
108
+ * divergence observation. Absent on non-resume ops and from pre-1.360 engines (adapters treat absence
109
+ * as the legacy current-config behavior).
110
+ */
25
111
  priorHandle?: WorkspaceHandle;
26
112
  }
113
+ /**
114
+ * One chunk streamed from {@link RemoteExecutionEnv.execStream} (design/48 §5 gap 3, council BUG#3). A run is a
115
+ * sequence of `stdout`/`stderr` chunks terminated by exactly one `exit` chunk carrying the typed exit code.
116
+ *
117
+ * The async iterator THROWS a {@link RemoteExecutionError} if the stream fails before an `exit` chunk arrives
118
+ * (transport loss, or a {@link RemoteExecutionEnv.suspendVM} that aborts the in-flight command) — that is the
119
+ * streaming analogue of the base {@link ExecutionEnv}'s never-throw `Result` contract, and it guarantees a
120
+ * consumer is never left awaiting a chunk that will never come.
121
+ */
27
122
  export type OutputChunk = {
28
123
  type: "stdout";
29
124
  data: string;
@@ -34,28 +129,178 @@ export type OutputChunk = {
34
129
  type: "exit";
35
130
  exitCode: number;
36
131
  };
132
+ /** Options for {@link RemoteExecutionEnv.execStream}. */
37
133
  export interface ExecStreamOptions {
134
+ /**
135
+ * Isolation routing hint (design/48 §2; renamed from `tier` per §11 #10). The *classification* that decides
136
+ * a command's tier — static tool table + Tier1-safe sub-command allow-list, fail-closed to Tier 2 — is the
137
+ * env/control-plane's job and is DEFERRED; this param only lets a caller pass an explicit route when known.
138
+ */
38
139
  sandboxTier?: SandboxTier;
140
+ /** Working directory; relative paths resolve against the workspace root. */
39
141
  cwd?: string;
142
+ /** Extra environment variables for the command. */
40
143
  env?: Record<string, string>;
144
+ /**
145
+ * Total command wall-clock timeout in seconds. **🔴 Per-command — independent of the env/sandbox lifetime.**
146
+ * A remote adapter MUST NOT fall back to the sandbox lifetime when this is unset (service [45]: an E2B adapter
147
+ * that defaulted a missing per-command timeout to `cfg.timeoutMs` = the sandbox lifetime made a seconds-long
148
+ * command wait the *whole sandbox lifetime*, ~30 min, on a provider RPC hang). "No `timeout`" means "no
149
+ * wall-clock cap on a *making-progress* command" — NOT "wait until the env dies"; liveness is still bounded by
150
+ * {@link readTimeoutMs} (see below). Distinct concerns: `timeout` caps a slow-but-progressing command;
151
+ * `readTimeoutMs` catches a *hung/unreachable* one.
152
+ */
41
153
  timeout?: number;
154
+ /** Abort the command. Aborting ends the stream with a {@link RemoteExecutionError} (code `"aborted"`, no `exit` chunk). */
42
155
  signal?: AbortSignal;
156
+ /**
157
+ * Idle/liveness read timeout (ms). If no {@link OutputChunk} arrives within this window, `execStream` ends
158
+ * with a {@link RemoteExecutionError} (code `"timeout"`) instead of hanging. **Needed in practice for remote
159
+ * backends** (design/48 §5, service [7]): E2B issue #1128 — a *streaming* call sets no read timeout (only unary
160
+ * does), so an unreachable sandbox hangs the worker forever. Distinct from `timeout` (total wall-clock).
161
+ *
162
+ * 🔴 **Liveness contract (service [45]/[59]):** a remote adapter SHOULD enforce a default liveness bound even
163
+ * when this is unset (a missing idle timeout MUST NOT mean "wait forever / until the env dies"), and that bound
164
+ * MUST cover the **command-creation/handshake RPC**, not only the post-first-chunk loop — a provider hang
165
+ * typically occurs at creation, before any chunk arrives, so an idle timer started only after the first chunk
166
+ * misses it. On trigger, throw {@link RemoteExecutionError} with code `"timeout"` (retryable by the caller per
167
+ * the command's idempotency — the adapter MUST NOT blind-retry).
168
+ */
43
169
  readTimeoutMs?: number;
170
+ /** Per-call output cap (design/48 §5 gap 8): stop streaming after this many bytes to avoid a `find /` flooding the control plane. */
44
171
  maxOutputBytes?: number;
45
172
  }
46
- export type RemoteExecutionErrorCode = "suspended" | "command_in_flight" | "connect_failed" | "post_resume_failed" | "aborted" | "timeout" | "unsupported" | "auth_transient" | "auth_failed" | "transport_lost" | "unknown";
173
+ /** Stable error codes for the remote seam's lifecycle/streaming operations (design/48 §5/§11 BUG#2). */
174
+ export type RemoteExecutionErrorCode =
175
+ /** A lifecycle/exec op failed because the workspace is (or became) suspended. */
176
+ "suspended"
177
+ /** {@link RemoteExecutionEnv.suspendVM} refused because a command was still in flight (council #4). */
178
+ | "command_in_flight"
179
+ /** Connect/resume/reconnect failed to reach or provision the remote workspace. */
180
+ | "connect_failed"
181
+ /** A post-resume consistency step failed (design/48 §5/#8) — caller must destroy the env. */
182
+ | "post_resume_failed"
183
+ /** The command/stream was aborted via its `AbortSignal`. */
184
+ | "aborted"
185
+ /**
186
+ * A command's wall-clock {@link ExecStreamOptions.timeout} or liveness {@link ExecStreamOptions.readTimeoutMs}
187
+ * was exceeded — including a provider RPC hang at command creation (service [45]/[59]). **Retryable** by the
188
+ * caller per the command's idempotency (the adapter MUST NOT blind-retry). Distinct from `"aborted"` (a
189
+ * caller-driven `AbortSignal`) and `"connect_failed"` (workspace provisioning, not a per-command hang).
190
+ */
191
+ | "timeout"
192
+ /**
193
+ * The op is not supported by this adapter's capabilities (design/61 §9 A) — e.g. `suspendVM`/`resumeVM` on a
194
+ * non-suspendable SSH/ADB env. Permanent for this env; check {@link RemoteExecutionEnv.capabilities} first.
195
+ */
196
+ | "unsupported"
197
+ /**
198
+ * A **transient** authentication step that is expected to succeed on a retry (design/61 §9 C) — e.g. an ADB
199
+ * device awaiting first-time authorization (connect once → user authorizes → connect again succeeds).
200
+ * **Retryable** (typically retry-exactly-once). Distinct from {@link "auth_failed"} so a real rejection isn't
201
+ * retried and a bounded ADB retry doesn't false-kill an SSH transient.
202
+ */
203
+ | "auth_transient"
204
+ /**
205
+ * **Permanent** authentication failure (design/61 §9 C) — wrong/rejected SSH key, revoked token. **NEVER
206
+ * retry** (retrying burns the whole attempt budget and can lock accounts). The caller must surface it.
207
+ */
208
+ | "auth_failed"
209
+ /**
210
+ * The transport connection dropped mid-session (TCP RST, network partition, peer close) — design/61 §9 C/#14.
211
+ * **Retryable** by re-establishing the connection (idempotent for a persistent SSH/ADB session). An adapter
212
+ * MUST map raw transport errors (DNS `ENOTFOUND`, TCP RST) onto a typed code, not leave them as `"unknown"`,
213
+ * else a retry whitelist misses them.
214
+ */
215
+ | "transport_lost"
216
+ /** Unclassified provider/transport failure. */
217
+ | "unknown";
218
+ /**
219
+ * The RETRYABLE half of {@link RemoteExecutionErrorCode} — the codes whose own contract above says a retry
220
+ * can succeed (`auth_transient`: retry-exactly-once after the device is authorized; `connect_failed`: the
221
+ * workspace could not be reached/provisioned this attempt; `timeout`: a liveness bound tripped;
222
+ * `transport_lost`: re-establish the connection). Every OTHER code is permanent for this attempt
223
+ * (`auth_failed`/`unsupported`), caller-driven (`aborted`), or unclassifiable (`unknown`) — retrying them
224
+ * burns budget or, worse, re-drives a rejected credential.
225
+ *
226
+ * ONE list, two consumers, so a caller's retry decision and its DISCLOSURE can never disagree: the engine
227
+ * retries only IDEMPOTENT ops on these codes (see {@link withRetry}'s red line — a snapshot-taking
228
+ * `suspendVM` is never retried), and it stamps `retryable` on the failure it reports to the caller for the
229
+ * ops it does NOT retry, so a deployment can decide (refresh the credential and re-resume vs give up)
230
+ * without parsing prose.
231
+ */
47
232
  export declare const RETRYABLE_REMOTE_ERROR_CODES: readonly RemoteExecutionErrorCode[];
233
+ /** Is `code` in the {@link RETRYABLE_REMOTE_ERROR_CODES} family? */
48
234
  export declare function isRetryableRemoteErrorCode(code: RemoteExecutionErrorCode): boolean;
235
+ /**
236
+ * Error surfaced by {@link RemoteExecutionEnv} lifecycle ops and by {@link RemoteExecutionEnv.execStream}'s
237
+ * iterator. Mirrors the vendored `ExecutionError` shape but carries the remote-specific code set; it is kept
238
+ * separate from the vendored `ExecutionErrorCode` union deliberately — those codes only need to widen once the
239
+ * design/45 suspend/resume *runtime* lands and the Runner/orchestrator layer must thread `"suspended"`.
240
+ */
49
241
  export declare class RemoteExecutionError extends Error {
50
242
  readonly code: RemoteExecutionErrorCode;
51
243
  constructor(code: RemoteExecutionErrorCode, message: string, cause?: Error);
52
244
  }
245
+ /**
246
+ * A remote, stateful, suspendable {@link ExecutionEnv} (design/48 §5). Extends the base with workspace identity,
247
+ * connection lifecycle, streaming exec, and post-resume reconciliation. Every method follows the base contract:
248
+ * **never throw/reject** — encode failures in the returned `Result` (the one exception is {@link execStream},
249
+ * whose iterator may throw mid-stream; see {@link OutputChunk}).
250
+ *
251
+ * Lifecycle methods are typed but their RUNTIME wiring (task suspension, `Checkpoint` persistence of the
252
+ * {@link WorkspaceHandle}, cross-replica resume) is implemented with design/45 — see the file header.
253
+ *
254
+ * 🔴 **Universal liveness contract (service [45]/[59] class-fix) — applies to EVERY remote RPC**, not just
255
+ * `execStream`: the inherited {@link ExecutionEnv} filesystem ops (`readTextFile`/`writeFile`/`listDir`/…), the
256
+ * streaming/buffered exec, AND the VM-lifecycle ops below (`connect`/`reconnect`/`suspendVM`/`resumeVM`/
257
+ * `postResumeInit`/`destroy`). Each is a network round-trip to a provider that can hang. The contract:
258
+ * 1. **Every remote RPC SHOULD enforce a bounded default liveness/idle timeout** even when no `abortSignal`/
259
+ * timeout is given — a hung provider call MUST NOT wait until the env/sandbox lifetime expires (the
260
+ * service [45] bug, but generalized: it was found on `exec`, and `files.read`/`resumeVM`/etc. share the
261
+ * exact exposure). An optional `abortSignal` (where present) composes with, but does not replace, this default.
262
+ * 2. **🔴 Bound on LIVENESS (no progress), not a fixed short wall-clock** — distinguish *hung* from *slow but
263
+ * progressing* (search [60] / service [50] data-transfer sharpening). A **data-transfer** op — a large-workspace
264
+ * `suspendVM` snapshot, a big `writeFile`/`readTextFile` — may legitimately run for minutes; a fixed short
265
+ * wall-clock would false-kill the (durable-checkpoint *命门*) path. So such ops bound on an **idle/no-heartbeat**
266
+ * window (reset by observable progress), not total elapsed time. Cheap control RPCs (`isRunning`, a small
267
+ * `connect` handshake) may use a short wall-clock. The adapter sizes the bound per op class.
268
+ * 3. **A liveness breach surfaces as a typed, retryable error**: `RemoteExecutionError` code `"timeout"` for the
269
+ * lifecycle/stream ops; for the inherited filesystem ops (which return the vendored `Result<_, FileError>`),
270
+ * a `FileError` — but still **bounded, never an unbounded wait**. Retry is the caller's decision per the op's
271
+ * idempotency; the adapter MUST NOT blind-retry.
272
+ */
53
273
  export interface RemoteExecutionEnv extends ExecutionEnv {
274
+ /**
275
+ * What this adapter can actually do (design/61 §9 A, council). The seam was built for E2B (a full
276
+ * `{isolation:true, suspendable:true}` adapter); **partial-capability** adapters (SSH/ADB: `{false, false}`
277
+ * — a real machine/device, not snapshotable and not isolated) declare it here. **Required + explicit** so
278
+ * the orchestrator never has to guess: there is no safe default (assuming isolation when there is none is a
279
+ * security hole; assuming suspendable crashes on `suspendVM`). Use {@link isSuspendable}/{@link isIsolated}
280
+ * rather than the structural {@link isRemoteExecutionEnv} (method presence ≠ semantics — a stub `suspendVM`
281
+ * that returns `"unsupported"` still satisfies the structural check). Extensible: add fields as new
282
+ * partial-capability classes appear.
283
+ */
54
284
  readonly capabilities: {
285
+ /** True iff actions are contained (E2B microVM); false for a real target (SSH host / ADB device). The
286
+ * orchestrator tightens autonomy + the design/37 policy gate when this is false (design/53 zero-trust). */
55
287
  isolation: boolean;
288
+ /** True iff the env can be snapshot/`suspendVM`'d (E2B); false for SSH/ADB (durable suspend N/A).
289
+ *
290
+ * ⚠️ LOAD-BEARING INVARIANT (opus review 1.257.2): `suspendable:false` on a remote env also asserts
291
+ * the workspace is EXTERNALLY DURABLE — it persists on the target across the env object's lifetime
292
+ * (true for SSH hosts / ADB devices). The durable-park-only suspend degrade (service [500]②) rests
293
+ * on this: it skips `suspendVM` and trusts the factory to reconnect to the SAME workspace on resume.
294
+ * An adapter for a non-suspendable EPHEMERAL backend (e.g. a snapshot-less container torn down with
295
+ * the transport) must NOT be modeled as `suspendable:false` remote — it would silently take the
296
+ * park-only branch and resume onto a fresh empty workspace. Model such a backend as a per-task env
297
+ * without durable suspend instead (the human gate refuses it), or extend capabilities with an
298
+ * explicit workspace-durability flag before building one. */
56
299
  suspendable: boolean;
57
300
  };
301
+ /** Identity of the connected workspace (design/48 §5 gap 1). Synchronous: it is data the env already holds. */
58
302
  workspaceHandle(): WorkspaceHandle;
303
+ /** Provision/attach the remote workspace and inject secrets. Returns the resulting {@link WorkspaceHandle}. */
59
304
  connect(config?: RemoteConnectConfig): Promise<{
60
305
  ok: true;
61
306
  value: WorkspaceHandle;
@@ -63,6 +308,26 @@ export interface RemoteExecutionEnv extends ExecutionEnv {
63
308
  ok: false;
64
309
  error: RemoteExecutionError;
65
310
  }>;
311
+ /**
312
+ * Snapshot the workspace and (provider permitting) stop billing; returns the {@link SnapshotId} to resume from.
313
+ *
314
+ * **Council #4 — must not leave an in-flight command hung.** If a {@link Shell.exec}/{@link execStream} is in
315
+ * flight, an implementation MUST either (a) refuse with `RemoteExecutionError("command_in_flight")`, or (b)
316
+ * abort the in-flight command — buffered `exec` then resolves an `Err` and an in-flight {@link execStream}
317
+ * iterator throws `RemoteExecutionError("suspended")`. It must NOT silently snapshot and leave the command's
318
+ * promise/iterator pending forever.
319
+ *
320
+ * **🔴 Atomicity contract (design/49 v1.5, code-ready council BUG#1/#13).** This is the FIRST durable side
321
+ * effect of a remote durable-suspend, so its all-or-nothing semantics are load-bearing for the Runner's
322
+ * commit ordering:
323
+ * - `{ok:true}` ⇒ the VM is paused at `value` (a `SnapshotId`); the caller may now persist a checkpoint.
324
+ * - `{ok:false}` ⇒ the VM is left in its ORIGINAL (running) state, untouched — the caller can safely fall
325
+ * back to the synchronous `onAsk` gate as if no suspend was attempted (Runner: design/49 §4①).
326
+ * An implementation MUST NOT return `{ok:false}` after it has already paused/snapshotted the VM. The gate
327
+ * path means no command is in flight (the batch's prior calls are awaited, the gated call has not run), so
328
+ * `command_in_flight` should not arise; if it does, the Runner treats it as an ordinary `{ok:false}` and
329
+ * falls back to `onAsk` — see {@link RemoteExecutionErrorCode}.
330
+ */
66
331
  suspendVM(options?: VmLifecycleOptions): Promise<{
67
332
  ok: true;
68
333
  value: SnapshotId;
@@ -70,6 +335,9 @@ export interface RemoteExecutionEnv extends ExecutionEnv {
70
335
  ok: false;
71
336
  error: RemoteExecutionError;
72
337
  }>;
338
+ /** Restore the workspace from a snapshot. Idempotent + re-entrant (a replica that crashed mid-suspend can be
339
+ * superseded by another resuming the same {@link SnapshotId} without corruption — aligns with design/45 resolve-CAS).
340
+ * Pass `options.abortSignal` so a hung restore cannot pin the resuming worker (design/49 BUG#2). */
73
341
  resumeVM(snapshotId: SnapshotId, options?: VmLifecycleOptions): Promise<{
74
342
  ok: true;
75
343
  value: WorkspaceHandle;
@@ -77,6 +345,7 @@ export interface RemoteExecutionEnv extends ExecutionEnv {
77
345
  ok: false;
78
346
  error: RemoteExecutionError;
79
347
  }>;
348
+ /** Re-attach the control-plane transport to a still-running VM after a control-plane reconnect (design/48 §5 gap 4). */
80
349
  reconnect(sessionToken: SessionToken): Promise<{
81
350
  ok: true;
82
351
  value: WorkspaceHandle;
@@ -84,6 +353,18 @@ export interface RemoteExecutionEnv extends ExecutionEnv {
84
353
  ok: false;
85
354
  error: RemoteExecutionError;
86
355
  }>;
356
+ /**
357
+ * Re-establish consistency AFTER {@link resumeVM}/{@link reconnect} (design/48 §5 gap, council #8): re-fetch git
358
+ * remote refs + invalidate stale package/index caches, and re-inject secrets (short-lived credentials may have
359
+ * expired while suspended). Any failed step → `Err("post_resume_failed")` and the caller MUST destroy the env.
360
+ *
361
+ * Note: a resumed guest's network/long-lived connections (git remote / API / registry) are NOT guaranteed to
362
+ * survive the snapshot (clay decision 2), so this is also where the VM-internal agent rebuilds those.
363
+ *
364
+ * 🔴 Ordering red line (design/48 §5/#6): at-rest encryption of the memory snapshot must be ensured BEFORE
365
+ * secrets are injected — never let plaintext credentials land in an unencrypted snapshot. That encryption is a
366
+ * service-side property of the snapshot store; this method must fail-and-clean if it cannot be guaranteed.
367
+ */
87
368
  postResumeInit(): Promise<{
88
369
  ok: true;
89
370
  value: void;
@@ -91,18 +372,119 @@ export interface RemoteExecutionEnv extends ExecutionEnv {
91
372
  ok: false;
92
373
  error: RemoteExecutionError;
93
374
  }>;
375
+ /**
376
+ * Stream a command's output (design/48 §5 gap 3) — the standard path for long build/test runs. Distinct from
377
+ * the buffered base `exec()` (council #3: no overload). Yields `stdout`/`stderr` chunks then exactly one `exit`
378
+ * chunk; the iterator throws {@link RemoteExecutionError} if the stream fails before `exit` (see {@link OutputChunk}).
379
+ *
380
+ * 🔴 **Timeout/liveness contract (service [45]/[59]) — applies to BOTH `execStream` and the base `exec`:** a
381
+ * per-command timeout is **independent of the env/sandbox lifetime** and an adapter MUST NOT fall back to the
382
+ * lifetime when none is given (else a hung provider RPC pins the worker for the whole sandbox lifetime). An
383
+ * adapter SHOULD enforce a bounded default liveness/idle timeout that also covers the command-creation RPC, and
384
+ * surface a liveness/timeout breach as a typed, retryable {@link RemoteExecutionError} code `"timeout"`. See
385
+ * {@link ExecStreamOptions.timeout} / {@link ExecStreamOptions.readTimeoutMs}.
386
+ */
94
387
  execStream(command: string, options?: ExecStreamOptions): AsyncIterable<OutputChunk>;
388
+ /**
389
+ * Tear down the workspace and release provider resources. Best-effort; must never throw (like `cleanup`).
390
+ * **Must be idempotent** — safe to call more than once (the second call is a no-op). The Runner calls it
391
+ * once on task end, and `prepareTask` calls it on a prepare-time throw; a remote impl may also be reaped,
392
+ * so a defensive double-call must not error or double-bill.
393
+ *
394
+ * 飞轮 [519] contract note: on a NON-isolated env (no `capabilities.isolation` — host lane, SSH host),
395
+ * destroy() is workspace/object-level cleanup and must NOT reap still-running background processes —
396
+ * that is `disposeBackgroundShells`' job, which honours the timeout/session keep-alive except-list
397
+ * ([511]③ monitor timeout anchor). An isolated env (container/VM) naturally takes everything down;
398
+ * the Runner's envDying settle accounts for that with an accurate killed receipt beforehand.
399
+ */
95
400
  destroy(): Promise<void>;
96
401
  }
402
+ /** Context handed to an {@link ExecutionEnvFactory} for each task (design/48 §5 / §7 Q7). Deliberately minimal:
403
+ * per-task identity is enough to allocate/route a per-task container; richer routing (tenant/principal) is
404
+ * captured in the factory closure by the trusted control plane that builds it. */
97
405
  export interface ExecutionEnvFactoryContext {
406
+ /** Resolved session id for the task — the stable identity of its per-task workspace. */
98
407
  sessionId: string;
408
+ /** Caller-supplied task id, when set on the `TaskSpec`. */
99
409
  taskId?: string;
410
+ /**
411
+ * design/97 CORE-6 — per-task ISOLATION request threaded from the workflow's `ctx.agent({ isolation })` via
412
+ * the TRUSTED `RunInternals` channel (never from the untrusted `TaskSpec`). When `"worktree"`, a
413
+ * control-plane factory **MUST either mint a git-worktree-rooted env for this agent (e.g. via
414
+ * {@link addWorktree}) WITH a `destroy()` that removes the worktree, or THROW.** It MUST NOT silently
415
+ * return a non-isolated env (the shared base env, or a child rooted at `parentCwd`): the spawn may be
416
+ * governed by a relaxed write baseline (`WorkflowGovernanceBaseline.worktreeBase`) that is safe ONLY
417
+ * inside a worktree — a silent degrade would point those writes at the shared working tree. A factory
418
+ * throw fails the spawn (fail-closed: the child never starts) — the honest outcome. The engine
419
+ * additionally rejects the observable degrade shapes at its consumption point (no factory configured;
420
+ * the shared static env returned as-is; an in-process env rooted at the base root or the parent's cwd),
421
+ * but full worktree verification is the factory's contract — there is no receipt field on
422
+ * {@link ExecutionEnv}. Unset = default (the factory's normal per-task env).
423
+ */
100
424
  isolation?: "worktree";
425
+ /**
426
+ * Blackboard 2026-07-03 (clay dogfood — sub-agents landing in an EMPTY sandbox): the PARENT task's
427
+ * effective working root, threaded (like `isolation`) via the TRUSTED `RunInternals` channel when this
428
+ * task is a sub-agent (workflow `ctx.agent` / Task delegation). CC parity: a Task sub-agent inherits the
429
+ * main session's cwd. A single-user/TOC factory SHOULD root the child env here (unless `isolation`
430
+ * requests a worktree — that wins); a multi-tenant/TOB factory minting isolated containers may ignore
431
+ * it. Absent on top-level tasks. Static shared-`executionEnv` deployments need nothing — the child
432
+ * already shares the parent env (and its cwd).
433
+ */
101
434
  parentCwd?: string;
102
435
  }
436
+ /**
437
+ * A **trusted control-plane** factory that mints a per-task {@link ExecutionEnv} (design/48 §5 answers core
438
+ * gap-a / §7 Q7). Lives on `RunnerDeps` (deployment-level) — NOT on `TaskSpec` — so an untrusted caller can
439
+ * never inject its own env and escape the sandbox (design/44 §7 Q4 red line; clay decision 3: the Docker
440
+ * fast-lane must be control-plane-assigned, never task-selectable).
441
+ *
442
+ * The remote model is "one container per task", so the factory is invoked once per task. The Runner owns the
443
+ * lifetime of a factory-produced env: if it implements {@link RemoteExecutionEnv.destroy} (see {@link hasDestroy}),
444
+ * the Runner calls it when the task ends.
445
+ */
103
446
  export type ExecutionEnvFactory = (ctx: ExecutionEnvFactoryContext) => ExecutionEnv | Promise<ExecutionEnv>;
447
+ /** True when `env` exposes a lifecycle {@link RemoteExecutionEnv.destroy} the Runner should call on task end. */
104
448
  export declare function hasDestroy(env: ExecutionEnv): env is ExecutionEnv & Pick<RemoteExecutionEnv, "destroy">;
449
+ /** Structural check that `env` implements the remote seam (lifecycle + streaming surface + declared capabilities). */
105
450
  export declare function isRemoteExecutionEnv(env: ExecutionEnv): env is RemoteExecutionEnv;
451
+ /**
452
+ * The RESTORE half of the suspend contract — the methods the RESUME leg calls after a `suspendVM`
453
+ * ({@link RemoteExecutionEnv.resumeVM} + {@link RemoteExecutionEnv.postResumeInit}). Returns the names an
454
+ * adapter is MISSING (empty = complete).
455
+ *
456
+ * Split out from {@link isRemoteExecutionEnv} deliberately: that predicate answers "can this env be driven
457
+ * as a remote env at all" (a park-only SSH/ADB host legitimately never restores a VM and is checked with
458
+ * it), while THIS one answers "if I snapshot this env now, will the resume leg find a way back". Naming the
459
+ * missing methods lets the suspend-time guard say WHICH part of the adapter is absent instead of failing on
460
+ * the resume leg — a different process, hours later — with a bare `env.resumeVM is not a function`.
461
+ */
106
462
  export declare function missingRestoreSurface(env: ExecutionEnv): readonly ("resumeVM" | "postResumeInit")[];
463
+ /**
464
+ * Can this env be durably suspended/snapshotted (design/61 §9 A)? Use this — NOT the structural
465
+ * {@link isRemoteExecutionEnv} — before calling `suspendVM` (a non-suspendable SSH/ADB env declares
466
+ * `capabilities.suspendable: false` but still has the method, which returns `"unsupported"`). Non-remote
467
+ * (in-process) envs are not suspendable.
468
+ *
469
+ * A composite type guard (structural AND capability) so a `suspendVM` call site narrowed by THIS predicate
470
+ * gets the {@link RemoteExecutionEnv} type without a cast — `true` always implies the structural check too.
471
+ *
472
+ * RB-439-b: it also requires the RESTORE surface ({@link missingRestoreSurface}). A suspend is only durable
473
+ * if something can undo it; an adapter that offers `suspendVM` but no `resumeVM` used to pass this guard,
474
+ * take a real snapshot, commit a real checkpoint — and then blow up on the resume leg with an untyped
475
+ * TypeError. "Suspendable" now means the whole round trip, so a half-adapter is rejected at the suspend site
476
+ * where the deployment can still be told which method it owes.
477
+ *
478
+ * ⚠️ A capability-DECLARING but restore-incomplete adapter must NOT be re-routed to the durable-park-only
479
+ * degrade by this predicate returning false — park-only rests on the workspace being externally durable
480
+ * (see {@link RemoteExecutionEnv.capabilities}.suspendable), which a snapshot backend does not have. Call
481
+ * sites split the two cases on the DECLARED `capabilities.suspendable` flag, not on this predicate alone.
482
+ */
107
483
  export declare function isSuspendable(env: ExecutionEnv): env is RemoteExecutionEnv;
484
+ /**
485
+ * Is this env an isolated sandbox (design/61 §9 A, design/53)? `false` for a real SSH host / ADB device AND
486
+ * for any in-process env (the host process is not isolated). The orchestrator tightens autonomy + the
487
+ * design/37 policy gate when this is `false` (zero-trust on an un-isolated target). The safe default is
488
+ * `false` — isolation must be explicitly declared, never assumed.
489
+ */
108
490
  export declare function isIsolated(env: ExecutionEnv): boolean;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * knob-hygiene #98 — one validator for every RETENTION policy a bundled store accepts.
3
+ *
4
+ * These knobs share a property nothing else in the engine does: they are the only numbers whose job is
5
+ * to DELETE, so an unevaluable one is not merely ignored, it decides. The shapes actually reachable:
6
+ *
7
+ * - `keep` is consumed as `rows.slice(Math.max(0, keep))` / `i >= keep`. `Math.max(0, NaN)` is `NaN`
8
+ * and `slice(NaN)` means `slice(0)` — so a policy whose `keep` arrived as NaN (the ordinary
9
+ * `Number(cfg.keep)` on a missing or misspelled field) deleted EVERY terminal row instead of
10
+ * keeping N of them. A negative `keep` reaches the same place by a different route.
11
+ * - `maxAgeMs` on the roster feeds `now - createdAt <= maxAgeMs`, which is false for NaN — so every
12
+ * row reads as expired, the next write persists the survivors, and the whole roster is gone. A
13
+ * roster row is a durable ADDRESS; losing one turns a live agent unreachable.
14
+ * - the remaining `*MaxAgeMs` arms fail the other way (NaN comparisons are false ⇒ nothing is
15
+ * reaped), which is safe but equally silent: retention that quietly stopped running is how a disk
16
+ * fills up. They are validated for the same reason — an operator deserves the same answer either way.
17
+ *
18
+ * Fail-loud rather than fall back to a default: a retention policy is the deployment saying what it
19
+ * wants kept, and quietly substituting a different policy is exactly the class of silence this sweep
20
+ * exists to remove. Every store passes its options through here BEFORE touching a row, so no
21
+ * implementation can drift from another (the RB-74 / RB-87 / RB-111 history in the store family is
22
+ * three consecutive "fixed one of the two implementations" misses).
23
+ */
24
+ export interface RetentionPolicyKnobs {
25
+ /** Age bound in ms. */
26
+ maxAgeMs?: number;
27
+ /** Row-count bound, whole rows. */
28
+ keep?: number;
29
+ /** Age bound in ms for the stale-running flip arm. */
30
+ staleRunningMaxAgeMs?: number;
31
+ /** Row-count bound, whole rows (roster's write-time cap). */
32
+ maxEntries?: number;
33
+ }
34
+ /**
35
+ * Refuse a malformed retention policy at the door. `undefined` on any field keeps its documented
36
+ * meaning — that arm is simply not applied — so a deployment that sets nothing is untouched.
37
+ *
38
+ * @param label the caller's own name, so the error names the seam the operator configured.
39
+ */
40
+ export declare function assertRetentionPolicy(label: string, opts: RetentionPolicyKnobs | undefined): void;
@@ -0,0 +1,21 @@
1
+ function invalidPolicy(label, knob, value, requirement) {
2
+ const e = new Error(`${label}: ${knob} must be ${requirement} (got ${String(value)}) — a retention bound that cannot be evaluated silently decides what to delete instead of bounding it`);
3
+ e.code = "config.retention_policy_invalid";
4
+ throw e;
5
+ }
6
+ export function assertRetentionPolicy(label, opts) {
7
+ if (opts === undefined)
8
+ return;
9
+ for (const knob of ["maxAgeMs", "staleRunningMaxAgeMs"]) {
10
+ const v = opts[knob];
11
+ if (v !== undefined && (!Number.isFinite(v) || v < 0)) {
12
+ invalidPolicy(label, knob, v, "a finite, non-negative number of milliseconds");
13
+ }
14
+ }
15
+ for (const knob of ["keep", "maxEntries"]) {
16
+ const v = opts[knob];
17
+ if (v !== undefined && (!Number.isInteger(v) || v < 0)) {
18
+ invalidPolicy(label, knob, v, "a whole number of rows, 0 or more");
19
+ }
20
+ }
21
+ }