@sema-ai/core 1.275.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (962) hide show
  1. package/CHANGELOG.md +5433 -0
  2. package/LICENSE +27 -0
  3. package/NOTICE.md +30 -0
  4. package/README.md +1040 -0
  5. package/dist/agents/agent-definition.d.ts +10 -0
  6. package/dist/agents/agent-definition.d.ts.map +1 -0
  7. package/dist/agents/agent-definition.js +18 -0
  8. package/dist/agents/agent-definition.js.map +1 -0
  9. package/dist/agents/builtin-agents.d.ts +69 -0
  10. package/dist/agents/builtin-agents.d.ts.map +1 -0
  11. package/dist/agents/builtin-agents.js +177 -0
  12. package/dist/agents/builtin-agents.js.map +1 -0
  13. package/dist/agents/cascade.d.ts +101 -0
  14. package/dist/agents/cascade.d.ts.map +1 -0
  15. package/dist/agents/cascade.js +189 -0
  16. package/dist/agents/cascade.js.map +1 -0
  17. package/dist/agents/observer.d.ts +209 -0
  18. package/dist/agents/observer.d.ts.map +1 -0
  19. package/dist/agents/observer.js +495 -0
  20. package/dist/agents/observer.js.map +1 -0
  21. package/dist/agents/repair-loop.d.ts +236 -0
  22. package/dist/agents/repair-loop.d.ts.map +1 -0
  23. package/dist/agents/repair-loop.js +293 -0
  24. package/dist/agents/repair-loop.js.map +1 -0
  25. package/dist/agents/session-util.d.ts +8 -0
  26. package/dist/agents/session-util.d.ts.map +1 -0
  27. package/dist/agents/session-util.js +9 -0
  28. package/dist/agents/session-util.js.map +1 -0
  29. package/dist/agents/subagent-steps.d.ts +93 -0
  30. package/dist/agents/subagent-steps.d.ts.map +1 -0
  31. package/dist/agents/subagent-steps.js +206 -0
  32. package/dist/agents/subagent-steps.js.map +1 -0
  33. package/dist/agents/subagent.d.ts +441 -0
  34. package/dist/agents/subagent.d.ts.map +1 -0
  35. package/dist/agents/subagent.js +2492 -0
  36. package/dist/agents/subagent.js.map +1 -0
  37. package/dist/agents/suspend-guard.d.ts +35 -0
  38. package/dist/agents/suspend-guard.d.ts.map +1 -0
  39. package/dist/agents/suspend-guard.js +48 -0
  40. package/dist/agents/suspend-guard.js.map +1 -0
  41. package/dist/agents/teacher.d.ts +137 -0
  42. package/dist/agents/teacher.d.ts.map +1 -0
  43. package/dist/agents/teacher.js +575 -0
  44. package/dist/agents/teacher.js.map +1 -0
  45. package/dist/agents/team.d.ts +211 -0
  46. package/dist/agents/team.d.ts.map +1 -0
  47. package/dist/agents/team.js +293 -0
  48. package/dist/agents/team.js.map +1 -0
  49. package/dist/agents/tool-filter.d.ts +29 -0
  50. package/dist/agents/tool-filter.d.ts.map +1 -0
  51. package/dist/agents/tool-filter.js +50 -0
  52. package/dist/agents/tool-filter.js.map +1 -0
  53. package/dist/agents/verify.d.ts +177 -0
  54. package/dist/agents/verify.d.ts.map +1 -0
  55. package/dist/agents/verify.js +305 -0
  56. package/dist/agents/verify.js.map +1 -0
  57. package/dist/bench/metrics.d.ts +714 -0
  58. package/dist/bench/metrics.d.ts.map +1 -0
  59. package/dist/bench/metrics.js +618 -0
  60. package/dist/bench/metrics.js.map +1 -0
  61. package/dist/bin/sema-tb.d.ts +3 -0
  62. package/dist/bin/sema-tb.d.ts.map +1 -0
  63. package/dist/bin/sema-tb.js +516 -0
  64. package/dist/bin/sema-tb.js.map +1 -0
  65. package/dist/bin/tb-env.d.ts +13 -0
  66. package/dist/bin/tb-env.d.ts.map +1 -0
  67. package/dist/bin/tb-env.js +26 -0
  68. package/dist/bin/tb-env.js.map +1 -0
  69. package/dist/brain/anthropic.d.ts +46 -0
  70. package/dist/brain/anthropic.d.ts.map +1 -0
  71. package/dist/brain/anthropic.js +830 -0
  72. package/dist/brain/anthropic.js.map +1 -0
  73. package/dist/brain/circuit-breaker.d.ts +46 -0
  74. package/dist/brain/circuit-breaker.d.ts.map +1 -0
  75. package/dist/brain/circuit-breaker.js +173 -0
  76. package/dist/brain/circuit-breaker.js.map +1 -0
  77. package/dist/brain/degrading.d.ts +98 -0
  78. package/dist/brain/degrading.d.ts.map +1 -0
  79. package/dist/brain/degrading.js +249 -0
  80. package/dist/brain/degrading.js.map +1 -0
  81. package/dist/brain/errors.d.ts +31 -0
  82. package/dist/brain/errors.d.ts.map +1 -0
  83. package/dist/brain/errors.js +58 -0
  84. package/dist/brain/errors.js.map +1 -0
  85. package/dist/brain/failover.d.ts +18 -0
  86. package/dist/brain/failover.d.ts.map +1 -0
  87. package/dist/brain/failover.js +118 -0
  88. package/dist/brain/failover.js.map +1 -0
  89. package/dist/brain/model-presets.d.ts +36 -0
  90. package/dist/brain/model-presets.d.ts.map +1 -0
  91. package/dist/brain/model-presets.js +54 -0
  92. package/dist/brain/model-presets.js.map +1 -0
  93. package/dist/brain/openai.d.ts +43 -0
  94. package/dist/brain/openai.d.ts.map +1 -0
  95. package/dist/brain/openai.js +784 -0
  96. package/dist/brain/openai.js.map +1 -0
  97. package/dist/brain/reasoning.d.ts +138 -0
  98. package/dist/brain/reasoning.d.ts.map +1 -0
  99. package/dist/brain/reasoning.js +146 -0
  100. package/dist/brain/reasoning.js.map +1 -0
  101. package/dist/brain/repetition.d.ts +60 -0
  102. package/dist/brain/repetition.d.ts.map +1 -0
  103. package/dist/brain/repetition.js +121 -0
  104. package/dist/brain/repetition.js.map +1 -0
  105. package/dist/brain/request-params.d.ts +29 -0
  106. package/dist/brain/request-params.d.ts.map +1 -0
  107. package/dist/brain/request-params.js +78 -0
  108. package/dist/brain/request-params.js.map +1 -0
  109. package/dist/brain/retry.d.ts +18 -0
  110. package/dist/brain/retry.d.ts.map +1 -0
  111. package/dist/brain/retry.js +42 -0
  112. package/dist/brain/retry.js.map +1 -0
  113. package/dist/brain/routing.d.ts +19 -0
  114. package/dist/brain/routing.d.ts.map +1 -0
  115. package/dist/brain/routing.js +44 -0
  116. package/dist/brain/routing.js.map +1 -0
  117. package/dist/brain/status-sink.d.ts +46 -0
  118. package/dist/brain/status-sink.d.ts.map +1 -0
  119. package/dist/brain/status-sink.js +36 -0
  120. package/dist/brain/status-sink.js.map +1 -0
  121. package/dist/brain/stream-engine.d.ts +85 -0
  122. package/dist/brain/stream-engine.d.ts.map +1 -0
  123. package/dist/brain/stream-engine.js +391 -0
  124. package/dist/brain/stream-engine.js.map +1 -0
  125. package/dist/brain/timeout.d.ts +44 -0
  126. package/dist/brain/timeout.d.ts.map +1 -0
  127. package/dist/brain/timeout.js +41 -0
  128. package/dist/brain/timeout.js.map +1 -0
  129. package/dist/brain/tool-call-repair.d.ts +15 -0
  130. package/dist/brain/tool-call-repair.d.ts.map +1 -0
  131. package/dist/brain/tool-call-repair.js +67 -0
  132. package/dist/brain/tool-call-repair.js.map +1 -0
  133. package/dist/brain/walltime.d.ts +14 -0
  134. package/dist/brain/walltime.d.ts.map +1 -0
  135. package/dist/brain/walltime.js +14 -0
  136. package/dist/brain/walltime.js.map +1 -0
  137. package/dist/core/arg-summary.d.ts +19 -0
  138. package/dist/core/arg-summary.d.ts.map +1 -0
  139. package/dist/core/arg-summary.js +96 -0
  140. package/dist/core/arg-summary.js.map +1 -0
  141. package/dist/core/ask-question.d.ts +113 -0
  142. package/dist/core/ask-question.d.ts.map +1 -0
  143. package/dist/core/ask-question.js +246 -0
  144. package/dist/core/ask-question.js.map +1 -0
  145. package/dist/core/auto-compaction.d.ts +341 -0
  146. package/dist/core/auto-compaction.d.ts.map +1 -0
  147. package/dist/core/auto-compaction.js +495 -0
  148. package/dist/core/auto-compaction.js.map +1 -0
  149. package/dist/core/auto-promote.d.ts +126 -0
  150. package/dist/core/auto-promote.d.ts.map +1 -0
  151. package/dist/core/auto-promote.js +171 -0
  152. package/dist/core/auto-promote.js.map +1 -0
  153. package/dist/core/background-shell.d.ts +128 -0
  154. package/dist/core/background-shell.d.ts.map +1 -0
  155. package/dist/core/background-shell.js +42 -0
  156. package/dist/core/background-shell.js.map +1 -0
  157. package/dist/core/cache-break-detector.d.ts +63 -0
  158. package/dist/core/cache-break-detector.d.ts.map +1 -0
  159. package/dist/core/cache-break-detector.js +0 -0
  160. package/dist/core/cache-break-detector.js.map +1 -0
  161. package/dist/core/canonical-json.d.ts +45 -0
  162. package/dist/core/canonical-json.d.ts.map +1 -0
  163. package/dist/core/canonical-json.js +132 -0
  164. package/dist/core/canonical-json.js.map +1 -0
  165. package/dist/core/checkpoint-store.d.ts +1101 -0
  166. package/dist/core/checkpoint-store.d.ts.map +1 -0
  167. package/dist/core/checkpoint-store.js +514 -0
  168. package/dist/core/checkpoint-store.js.map +1 -0
  169. package/dist/core/consolidate-scope.d.ts +94 -0
  170. package/dist/core/consolidate-scope.d.ts.map +1 -0
  171. package/dist/core/consolidate-scope.js +158 -0
  172. package/dist/core/consolidate-scope.js.map +1 -0
  173. package/dist/core/context-edit.d.ts +82 -0
  174. package/dist/core/context-edit.d.ts.map +1 -0
  175. package/dist/core/context-edit.js +149 -0
  176. package/dist/core/context-edit.js.map +1 -0
  177. package/dist/core/context-guard.d.ts +43 -0
  178. package/dist/core/context-guard.d.ts.map +1 -0
  179. package/dist/core/context-guard.js +171 -0
  180. package/dist/core/context-guard.js.map +1 -0
  181. package/dist/core/dynamic-recall.d.ts +100 -0
  182. package/dist/core/dynamic-recall.d.ts.map +1 -0
  183. package/dist/core/dynamic-recall.js +108 -0
  184. package/dist/core/dynamic-recall.js.map +1 -0
  185. package/dist/core/exec-gate.d.ts +74 -0
  186. package/dist/core/exec-gate.d.ts.map +1 -0
  187. package/dist/core/exec-gate.js +143 -0
  188. package/dist/core/exec-gate.js.map +1 -0
  189. package/dist/core/exec-output-tail.d.ts +37 -0
  190. package/dist/core/exec-output-tail.d.ts.map +1 -0
  191. package/dist/core/exec-output-tail.js +63 -0
  192. package/dist/core/exec-output-tail.js.map +1 -0
  193. package/dist/core/file-snapshot-store.d.ts +137 -0
  194. package/dist/core/file-snapshot-store.d.ts.map +1 -0
  195. package/dist/core/file-snapshot-store.js +319 -0
  196. package/dist/core/file-snapshot-store.js.map +1 -0
  197. package/dist/core/git-worktree-env.d.ts +41 -0
  198. package/dist/core/git-worktree-env.d.ts.map +1 -0
  199. package/dist/core/git-worktree-env.js +64 -0
  200. package/dist/core/git-worktree-env.js.map +1 -0
  201. package/dist/core/hooks.d.ts +372 -0
  202. package/dist/core/hooks.d.ts.map +1 -0
  203. package/dist/core/hooks.js +269 -0
  204. package/dist/core/hooks.js.map +1 -0
  205. package/dist/core/lsp-diagnostics.d.ts +74 -0
  206. package/dist/core/lsp-diagnostics.d.ts.map +1 -0
  207. package/dist/core/lsp-diagnostics.js +125 -0
  208. package/dist/core/lsp-diagnostics.js.map +1 -0
  209. package/dist/core/lsp-protocol.d.ts +28 -0
  210. package/dist/core/lsp-protocol.d.ts.map +1 -0
  211. package/dist/core/lsp-protocol.js +179 -0
  212. package/dist/core/lsp-protocol.js.map +1 -0
  213. package/dist/core/lsp-session.d.ts +56 -0
  214. package/dist/core/lsp-session.d.ts.map +1 -0
  215. package/dist/core/lsp-session.js +185 -0
  216. package/dist/core/lsp-session.js.map +1 -0
  217. package/dist/core/lsp.d.ts +132 -0
  218. package/dist/core/lsp.d.ts.map +1 -0
  219. package/dist/core/lsp.js +147 -0
  220. package/dist/core/lsp.js.map +1 -0
  221. package/dist/core/mcp.d.ts +294 -0
  222. package/dist/core/mcp.d.ts.map +1 -0
  223. package/dist/core/mcp.js +992 -0
  224. package/dist/core/mcp.js.map +1 -0
  225. package/dist/core/media-byte-cap.d.ts +34 -0
  226. package/dist/core/media-byte-cap.d.ts.map +1 -0
  227. package/dist/core/media-byte-cap.js +76 -0
  228. package/dist/core/media-byte-cap.js.map +1 -0
  229. package/dist/core/memory-engine/data-plane.d.ts +103 -0
  230. package/dist/core/memory-engine/data-plane.d.ts.map +1 -0
  231. package/dist/core/memory-engine/data-plane.js +272 -0
  232. package/dist/core/memory-engine/data-plane.js.map +1 -0
  233. package/dist/core/memory-engine/dual-root.d.ts +40 -0
  234. package/dist/core/memory-engine/dual-root.d.ts.map +1 -0
  235. package/dist/core/memory-engine/dual-root.js +95 -0
  236. package/dist/core/memory-engine/dual-root.js.map +1 -0
  237. package/dist/core/memory-engine/engine.d.ts +161 -0
  238. package/dist/core/memory-engine/engine.d.ts.map +1 -0
  239. package/dist/core/memory-engine/engine.js +1110 -0
  240. package/dist/core/memory-engine/engine.js.map +1 -0
  241. package/dist/core/memory-engine/file-backend.d.ts +162 -0
  242. package/dist/core/memory-engine/file-backend.d.ts.map +1 -0
  243. package/dist/core/memory-engine/file-backend.js +948 -0
  244. package/dist/core/memory-engine/file-backend.js.map +1 -0
  245. package/dist/core/memory-engine/frontmatter.d.ts +24 -0
  246. package/dist/core/memory-engine/frontmatter.d.ts.map +1 -0
  247. package/dist/core/memory-engine/frontmatter.js +135 -0
  248. package/dist/core/memory-engine/frontmatter.js.map +1 -0
  249. package/dist/core/memory-engine/index.d.ts +13 -0
  250. package/dist/core/memory-engine/index.d.ts.map +1 -0
  251. package/dist/core/memory-engine/index.js +28 -0
  252. package/dist/core/memory-engine/index.js.map +1 -0
  253. package/dist/core/memory-engine/layout.d.ts +123 -0
  254. package/dist/core/memory-engine/layout.d.ts.map +1 -0
  255. package/dist/core/memory-engine/layout.js +643 -0
  256. package/dist/core/memory-engine/layout.js.map +1 -0
  257. package/dist/core/memory-engine/memory-backend-contract.d.ts +22 -0
  258. package/dist/core/memory-engine/memory-backend-contract.d.ts.map +1 -0
  259. package/dist/core/memory-engine/memory-backend-contract.js +271 -0
  260. package/dist/core/memory-engine/memory-backend-contract.js.map +1 -0
  261. package/dist/core/memory-engine/migrate.d.ts +17 -0
  262. package/dist/core/memory-engine/migrate.d.ts.map +1 -0
  263. package/dist/core/memory-engine/migrate.js +35 -0
  264. package/dist/core/memory-engine/migrate.js.map +1 -0
  265. package/dist/core/memory-engine/scan.d.ts +20 -0
  266. package/dist/core/memory-engine/scan.d.ts.map +1 -0
  267. package/dist/core/memory-engine/scan.js +84 -0
  268. package/dist/core/memory-engine/scan.js.map +1 -0
  269. package/dist/core/memory-engine/scope-contract.d.ts +104 -0
  270. package/dist/core/memory-engine/scope-contract.d.ts.map +1 -0
  271. package/dist/core/memory-engine/scope-contract.js +288 -0
  272. package/dist/core/memory-engine/scope-contract.js.map +1 -0
  273. package/dist/core/memory-engine/sync-client.d.ts +100 -0
  274. package/dist/core/memory-engine/sync-client.d.ts.map +1 -0
  275. package/dist/core/memory-engine/sync-client.js +328 -0
  276. package/dist/core/memory-engine/sync-client.js.map +1 -0
  277. package/dist/core/memory-engine/sync.d.ts +97 -0
  278. package/dist/core/memory-engine/sync.d.ts.map +1 -0
  279. package/dist/core/memory-engine/sync.js +91 -0
  280. package/dist/core/memory-engine/sync.js.map +1 -0
  281. package/dist/core/memory-engine/types.d.ts +279 -0
  282. package/dist/core/memory-engine/types.d.ts.map +1 -0
  283. package/dist/core/memory-engine/types.js +9 -0
  284. package/dist/core/memory-engine/types.js.map +1 -0
  285. package/dist/core/memory-recall.d.ts +261 -0
  286. package/dist/core/memory-recall.d.ts.map +1 -0
  287. package/dist/core/memory-recall.js +600 -0
  288. package/dist/core/memory-recall.js.map +1 -0
  289. package/dist/core/memory-vector.d.ts +24 -0
  290. package/dist/core/memory-vector.d.ts.map +1 -0
  291. package/dist/core/memory-vector.js +51 -0
  292. package/dist/core/memory-vector.js.map +1 -0
  293. package/dist/core/memory.d.ts +502 -0
  294. package/dist/core/memory.d.ts.map +1 -0
  295. package/dist/core/memory.js +881 -0
  296. package/dist/core/memory.js.map +1 -0
  297. package/dist/core/message-utils.d.ts +7 -0
  298. package/dist/core/message-utils.d.ts.map +1 -0
  299. package/dist/core/message-utils.js +10 -0
  300. package/dist/core/message-utils.js.map +1 -0
  301. package/dist/core/oracle-isolation.d.ts +85 -0
  302. package/dist/core/oracle-isolation.d.ts.map +1 -0
  303. package/dist/core/oracle-isolation.js +121 -0
  304. package/dist/core/oracle-isolation.js.map +1 -0
  305. package/dist/core/permission-rules.d.ts +102 -0
  306. package/dist/core/permission-rules.d.ts.map +1 -0
  307. package/dist/core/permission-rules.js +357 -0
  308. package/dist/core/permission-rules.js.map +1 -0
  309. package/dist/core/present-plan-tool.d.ts +28 -0
  310. package/dist/core/present-plan-tool.d.ts.map +1 -0
  311. package/dist/core/present-plan-tool.js +119 -0
  312. package/dist/core/present-plan-tool.js.map +1 -0
  313. package/dist/core/pricing.d.ts +48 -0
  314. package/dist/core/pricing.d.ts.map +1 -0
  315. package/dist/core/pricing.js +46 -0
  316. package/dist/core/pricing.js.map +1 -0
  317. package/dist/core/property-harness.d.ts +126 -0
  318. package/dist/core/property-harness.d.ts.map +1 -0
  319. package/dist/core/property-harness.js +192 -0
  320. package/dist/core/property-harness.js.map +1 -0
  321. package/dist/core/push-queue.d.ts +10 -0
  322. package/dist/core/push-queue.d.ts.map +1 -0
  323. package/dist/core/push-queue.js +42 -0
  324. package/dist/core/push-queue.js.map +1 -0
  325. package/dist/core/remote-env.d.ts +432 -0
  326. package/dist/core/remote-env.d.ts.map +1 -0
  327. package/dist/core/remote-env.js +77 -0
  328. package/dist/core/remote-env.js.map +1 -0
  329. package/dist/core/roles.d.ts +74 -0
  330. package/dist/core/roles.d.ts.map +1 -0
  331. package/dist/core/roles.js +272 -0
  332. package/dist/core/roles.js.map +1 -0
  333. package/dist/core/runner/active-skill-scope.d.ts +64 -0
  334. package/dist/core/runner/active-skill-scope.d.ts.map +1 -0
  335. package/dist/core/runner/active-skill-scope.js +197 -0
  336. package/dist/core/runner/active-skill-scope.js.map +1 -0
  337. package/dist/core/runner/assemble-result.d.ts +191 -0
  338. package/dist/core/runner/assemble-result.d.ts.map +1 -0
  339. package/dist/core/runner/assemble-result.js +250 -0
  340. package/dist/core/runner/assemble-result.js.map +1 -0
  341. package/dist/core/runner/call-cap.d.ts +130 -0
  342. package/dist/core/runner/call-cap.d.ts.map +1 -0
  343. package/dist/core/runner/call-cap.js +151 -0
  344. package/dist/core/runner/call-cap.js.map +1 -0
  345. package/dist/core/runner/grounding-signal.d.ts +12 -0
  346. package/dist/core/runner/grounding-signal.d.ts.map +1 -0
  347. package/dist/core/runner/grounding-signal.js +94 -0
  348. package/dist/core/runner/grounding-signal.js.map +1 -0
  349. package/dist/core/runner/image.d.ts +23 -0
  350. package/dist/core/runner/image.d.ts.map +1 -0
  351. package/dist/core/runner/image.js +151 -0
  352. package/dist/core/runner/image.js.map +1 -0
  353. package/dist/core/runner/memory-consolidation.d.ts +112 -0
  354. package/dist/core/runner/memory-consolidation.d.ts.map +1 -0
  355. package/dist/core/runner/memory-consolidation.js +372 -0
  356. package/dist/core/runner/memory-consolidation.js.map +1 -0
  357. package/dist/core/runner/prepare-task.d.ts +583 -0
  358. package/dist/core/runner/prepare-task.d.ts.map +1 -0
  359. package/dist/core/runner/prepare-task.js +3612 -0
  360. package/dist/core/runner/prepare-task.js.map +1 -0
  361. package/dist/core/runner/prompt-suggestions.d.ts +33 -0
  362. package/dist/core/runner/prompt-suggestions.d.ts.map +1 -0
  363. package/dist/core/runner/prompt-suggestions.js +116 -0
  364. package/dist/core/runner/prompt-suggestions.js.map +1 -0
  365. package/dist/core/runner/runtask.d.ts +274 -0
  366. package/dist/core/runner/runtask.d.ts.map +1 -0
  367. package/dist/core/runner/runtask.js +4606 -0
  368. package/dist/core/runner/runtask.js.map +1 -0
  369. package/dist/core/runner/session-rule-policy.d.ts +28 -0
  370. package/dist/core/runner/session-rule-policy.d.ts.map +1 -0
  371. package/dist/core/runner/session-rule-policy.js +110 -0
  372. package/dist/core/runner/session-rule-policy.js.map +1 -0
  373. package/dist/core/runner/strict-output-schema.d.ts +36 -0
  374. package/dist/core/runner/strict-output-schema.d.ts.map +1 -0
  375. package/dist/core/runner/strict-output-schema.js +365 -0
  376. package/dist/core/runner/strict-output-schema.js.map +1 -0
  377. package/dist/core/runner/synthetic-tools.d.ts +72 -0
  378. package/dist/core/runner/synthetic-tools.d.ts.map +1 -0
  379. package/dist/core/runner/synthetic-tools.js +203 -0
  380. package/dist/core/runner/synthetic-tools.js.map +1 -0
  381. package/dist/core/runner/tool-disclosure.d.ts +117 -0
  382. package/dist/core/runner/tool-disclosure.d.ts.map +1 -0
  383. package/dist/core/runner/tool-disclosure.js +0 -0
  384. package/dist/core/runner/tool-disclosure.js.map +1 -0
  385. package/dist/core/runner/turn-attachments.d.ts +381 -0
  386. package/dist/core/runner/turn-attachments.d.ts.map +1 -0
  387. package/dist/core/runner/turn-attachments.js +596 -0
  388. package/dist/core/runner/turn-attachments.js.map +1 -0
  389. package/dist/core/runner/usage-accounting.d.ts +35 -0
  390. package/dist/core/runner/usage-accounting.d.ts.map +1 -0
  391. package/dist/core/runner/usage-accounting.js +45 -0
  392. package/dist/core/runner/usage-accounting.js.map +1 -0
  393. package/dist/core/runtime.d.ts +9 -0
  394. package/dist/core/runtime.d.ts.map +1 -0
  395. package/dist/core/runtime.js +17 -0
  396. package/dist/core/runtime.js.map +1 -0
  397. package/dist/core/safety-axis-vocab.d.ts +33 -0
  398. package/dist/core/safety-axis-vocab.d.ts.map +1 -0
  399. package/dist/core/safety-axis-vocab.js +35 -0
  400. package/dist/core/safety-axis-vocab.js.map +1 -0
  401. package/dist/core/safety-merge-corpus.d.ts +48 -0
  402. package/dist/core/safety-merge-corpus.d.ts.map +1 -0
  403. package/dist/core/safety-merge-corpus.js +203 -0
  404. package/dist/core/safety-merge-corpus.js.map +1 -0
  405. package/dist/core/scheduler.d.ts +126 -0
  406. package/dist/core/scheduler.d.ts.map +1 -0
  407. package/dist/core/scheduler.js +54 -0
  408. package/dist/core/scheduler.js.map +1 -0
  409. package/dist/core/secret-env.d.ts +23 -0
  410. package/dist/core/secret-env.d.ts.map +1 -0
  411. package/dist/core/secret-env.js +35 -0
  412. package/dist/core/secret-env.js.map +1 -0
  413. package/dist/core/select-model.d.ts +26 -0
  414. package/dist/core/select-model.d.ts.map +1 -0
  415. package/dist/core/select-model.js +58 -0
  416. package/dist/core/select-model.js.map +1 -0
  417. package/dist/core/sensitive-path-policy.d.ts +24 -0
  418. package/dist/core/sensitive-path-policy.d.ts.map +1 -0
  419. package/dist/core/sensitive-path-policy.js +96 -0
  420. package/dist/core/sensitive-path-policy.js.map +1 -0
  421. package/dist/core/session-policy-store.d.ts +102 -0
  422. package/dist/core/session-policy-store.d.ts.map +1 -0
  423. package/dist/core/session-policy-store.js +177 -0
  424. package/dist/core/session-policy-store.js.map +1 -0
  425. package/dist/core/session-reconcile.d.ts +63 -0
  426. package/dist/core/session-reconcile.d.ts.map +1 -0
  427. package/dist/core/session-reconcile.js +71 -0
  428. package/dist/core/session-reconcile.js.map +1 -0
  429. package/dist/core/session-store.d.ts +99 -0
  430. package/dist/core/session-store.d.ts.map +1 -0
  431. package/dist/core/session-store.js +298 -0
  432. package/dist/core/session-store.js.map +1 -0
  433. package/dist/core/session.d.ts +144 -0
  434. package/dist/core/session.d.ts.map +1 -0
  435. package/dist/core/session.js +56 -0
  436. package/dist/core/session.js.map +1 -0
  437. package/dist/core/spec-contract.d.ts +147 -0
  438. package/dist/core/spec-contract.d.ts.map +1 -0
  439. package/dist/core/spec-contract.js +340 -0
  440. package/dist/core/spec-contract.js.map +1 -0
  441. package/dist/core/strategy-store.d.ts +50 -0
  442. package/dist/core/strategy-store.d.ts.map +1 -0
  443. package/dist/core/strategy-store.js +100 -0
  444. package/dist/core/strategy-store.js.map +1 -0
  445. package/dist/core/stub-env.d.ts +35 -0
  446. package/dist/core/stub-env.d.ts.map +1 -0
  447. package/dist/core/stub-env.js +69 -0
  448. package/dist/core/stub-env.js.map +1 -0
  449. package/dist/core/task-notification.d.ts +115 -0
  450. package/dist/core/task-notification.d.ts.map +1 -0
  451. package/dist/core/task-notification.js +247 -0
  452. package/dist/core/task-notification.js.map +1 -0
  453. package/dist/core/task-outcome.d.ts +80 -0
  454. package/dist/core/task-outcome.d.ts.map +1 -0
  455. package/dist/core/task-outcome.js +40 -0
  456. package/dist/core/task-outcome.js.map +1 -0
  457. package/dist/core/task-registry.d.ts +349 -0
  458. package/dist/core/task-registry.d.ts.map +1 -0
  459. package/dist/core/task-registry.js +1751 -0
  460. package/dist/core/task-registry.js.map +1 -0
  461. package/dist/core/tighten-task-spec.d.ts +27 -0
  462. package/dist/core/tighten-task-spec.d.ts.map +1 -0
  463. package/dist/core/tighten-task-spec.js +95 -0
  464. package/dist/core/tighten-task-spec.js.map +1 -0
  465. package/dist/core/tool-detach.d.ts +31 -0
  466. package/dist/core/tool-detach.d.ts.map +1 -0
  467. package/dist/core/tool-detach.js +62 -0
  468. package/dist/core/tool-detach.js.map +1 -0
  469. package/dist/core/tool-errors.d.ts +72 -0
  470. package/dist/core/tool-errors.d.ts.map +1 -0
  471. package/dist/core/tool-errors.js +194 -0
  472. package/dist/core/tool-errors.js.map +1 -0
  473. package/dist/core/tool-name-aliases.d.ts +5 -0
  474. package/dist/core/tool-name-aliases.d.ts.map +1 -0
  475. package/dist/core/tool-name-aliases.js +130 -0
  476. package/dist/core/tool-name-aliases.js.map +1 -0
  477. package/dist/core/tool-policy.d.ts +295 -0
  478. package/dist/core/tool-policy.d.ts.map +1 -0
  479. package/dist/core/tool-policy.js +567 -0
  480. package/dist/core/tool-policy.js.map +1 -0
  481. package/dist/core/tool-result-budget.d.ts +44 -0
  482. package/dist/core/tool-result-budget.d.ts.map +1 -0
  483. package/dist/core/tool-result-budget.js +140 -0
  484. package/dist/core/tool-result-budget.js.map +1 -0
  485. package/dist/core/tool-result-store.d.ts +136 -0
  486. package/dist/core/tool-result-store.d.ts.map +1 -0
  487. package/dist/core/tool-result-store.js +219 -0
  488. package/dist/core/tool-result-store.js.map +1 -0
  489. package/dist/core/tools.d.ts +14 -0
  490. package/dist/core/tools.d.ts.map +1 -0
  491. package/dist/core/tools.js +98 -0
  492. package/dist/core/tools.js.map +1 -0
  493. package/dist/core/trace.d.ts +340 -0
  494. package/dist/core/trace.d.ts.map +1 -0
  495. package/dist/core/trace.js +12 -0
  496. package/dist/core/trace.js.map +1 -0
  497. package/dist/core/types.d.ts +2828 -0
  498. package/dist/core/types.d.ts.map +1 -0
  499. package/dist/core/types.js +2 -0
  500. package/dist/core/types.js.map +1 -0
  501. package/dist/core/untrusted-egress.d.ts +32 -0
  502. package/dist/core/untrusted-egress.d.ts.map +1 -0
  503. package/dist/core/untrusted-egress.js +49 -0
  504. package/dist/core/untrusted-egress.js.map +1 -0
  505. package/dist/core/untrusted-text.d.ts +64 -0
  506. package/dist/core/untrusted-text.d.ts.map +1 -0
  507. package/dist/core/untrusted-text.js +119 -0
  508. package/dist/core/untrusted-text.js.map +1 -0
  509. package/dist/core/warm-resume.d.ts +23 -0
  510. package/dist/core/warm-resume.d.ts.map +1 -0
  511. package/dist/core/warm-resume.js +28 -0
  512. package/dist/core/warm-resume.js.map +1 -0
  513. package/dist/core/with-retry.d.ts +43 -0
  514. package/dist/core/with-retry.d.ts.map +1 -0
  515. package/dist/core/with-retry.js +59 -0
  516. package/dist/core/with-retry.js.map +1 -0
  517. package/dist/core/workflow-journal-store.d.ts +44 -0
  518. package/dist/core/workflow-journal-store.d.ts.map +1 -0
  519. package/dist/core/workflow-journal-store.js +47 -0
  520. package/dist/core/workflow-journal-store.js.map +1 -0
  521. package/dist/core/workflow-run-store-contract.d.ts +31 -0
  522. package/dist/core/workflow-run-store-contract.d.ts.map +1 -0
  523. package/dist/core/workflow-run-store-contract.js +191 -0
  524. package/dist/core/workflow-run-store-contract.js.map +1 -0
  525. package/dist/core/workflow-run-store.d.ts +149 -0
  526. package/dist/core/workflow-run-store.d.ts.map +1 -0
  527. package/dist/core/workflow-run-store.js +110 -0
  528. package/dist/core/workflow-run-store.js.map +1 -0
  529. package/dist/engine/compaction/compaction.d.ts +139 -0
  530. package/dist/engine/compaction/compaction.d.ts.map +1 -0
  531. package/dist/engine/compaction/compaction.js +1030 -0
  532. package/dist/engine/compaction/compaction.js.map +1 -0
  533. package/dist/engine/compaction/utils.d.ts +45 -0
  534. package/dist/engine/compaction/utils.d.ts.map +1 -0
  535. package/dist/engine/compaction/utils.js +203 -0
  536. package/dist/engine/compaction/utils.js.map +1 -0
  537. package/dist/engine/execution-env/kill-tree.d.ts +20 -0
  538. package/dist/engine/execution-env/kill-tree.d.ts.map +1 -0
  539. package/dist/engine/execution-env/kill-tree.js +183 -0
  540. package/dist/engine/execution-env/kill-tree.js.map +1 -0
  541. package/dist/engine/execution-env/node-execution-env.d.ts +133 -0
  542. package/dist/engine/execution-env/node-execution-env.d.ts.map +1 -0
  543. package/dist/engine/execution-env/node-execution-env.js +1031 -0
  544. package/dist/engine/execution-env/node-execution-env.js.map +1 -0
  545. package/dist/engine/harness/agent-harness.d.ts +174 -0
  546. package/dist/engine/harness/agent-harness.d.ts.map +1 -0
  547. package/dist/engine/harness/agent-harness.js +1053 -0
  548. package/dist/engine/harness/agent-harness.js.map +1 -0
  549. package/dist/engine/harness/messages.d.ts +17 -0
  550. package/dist/engine/harness/messages.d.ts.map +1 -0
  551. package/dist/engine/harness/messages.js +122 -0
  552. package/dist/engine/harness/messages.js.map +1 -0
  553. package/dist/engine/harness/types.d.ts +713 -0
  554. package/dist/engine/harness/types.d.ts.map +1 -0
  555. package/dist/engine/harness/types.js +100 -0
  556. package/dist/engine/harness/types.js.map +1 -0
  557. package/dist/engine/llm/diagnostics.d.ts +23 -0
  558. package/dist/engine/llm/diagnostics.d.ts.map +1 -0
  559. package/dist/engine/llm/diagnostics.js +32 -0
  560. package/dist/engine/llm/diagnostics.js.map +1 -0
  561. package/dist/engine/llm/event-stream.d.ts +25 -0
  562. package/dist/engine/llm/event-stream.d.ts.map +1 -0
  563. package/dist/engine/llm/event-stream.js +103 -0
  564. package/dist/engine/llm/event-stream.js.map +1 -0
  565. package/dist/engine/llm/index.d.ts +12 -0
  566. package/dist/engine/llm/index.d.ts.map +1 -0
  567. package/dist/engine/llm/index.js +12 -0
  568. package/dist/engine/llm/index.js.map +1 -0
  569. package/dist/engine/llm/types.d.ts +753 -0
  570. package/dist/engine/llm/types.d.ts.map +1 -0
  571. package/dist/engine/llm/types.js +2 -0
  572. package/dist/engine/llm/types.js.map +1 -0
  573. package/dist/engine/llm/validation.d.ts +8 -0
  574. package/dist/engine/llm/validation.d.ts.map +1 -0
  575. package/dist/engine/llm/validation.js +318 -0
  576. package/dist/engine/llm/validation.js.map +1 -0
  577. package/dist/engine/loop/agent-loop.d.ts +74 -0
  578. package/dist/engine/loop/agent-loop.d.ts.map +1 -0
  579. package/dist/engine/loop/agent-loop.js +1490 -0
  580. package/dist/engine/loop/agent-loop.js.map +1 -0
  581. package/dist/engine/loop/runtime-deps.d.ts +17 -0
  582. package/dist/engine/loop/runtime-deps.d.ts.map +1 -0
  583. package/dist/engine/loop/runtime-deps.js +21 -0
  584. package/dist/engine/loop/runtime-deps.js.map +1 -0
  585. package/dist/engine/loop/types.d.ts +609 -0
  586. package/dist/engine/loop/types.d.ts.map +1 -0
  587. package/dist/engine/loop/types.js +2 -0
  588. package/dist/engine/loop/types.js.map +1 -0
  589. package/dist/engine/lsp/frame-decoder.d.ts +16 -0
  590. package/dist/engine/lsp/frame-decoder.d.ts.map +1 -0
  591. package/dist/engine/lsp/frame-decoder.js +53 -0
  592. package/dist/engine/lsp/frame-decoder.js.map +1 -0
  593. package/dist/engine/lsp/node-lsp-manager.d.ts +105 -0
  594. package/dist/engine/lsp/node-lsp-manager.d.ts.map +1 -0
  595. package/dist/engine/lsp/node-lsp-manager.js +343 -0
  596. package/dist/engine/lsp/node-lsp-manager.js.map +1 -0
  597. package/dist/engine/lsp/stdio-lsp-transport.d.ts +37 -0
  598. package/dist/engine/lsp/stdio-lsp-transport.d.ts.map +1 -0
  599. package/dist/engine/lsp/stdio-lsp-transport.js +185 -0
  600. package/dist/engine/lsp/stdio-lsp-transport.js.map +1 -0
  601. package/dist/engine/session/import-validate.d.ts +44 -0
  602. package/dist/engine/session/import-validate.d.ts.map +1 -0
  603. package/dist/engine/session/import-validate.js +92 -0
  604. package/dist/engine/session/import-validate.js.map +1 -0
  605. package/dist/engine/session/memory-repo.d.ts +25 -0
  606. package/dist/engine/session/memory-repo.d.ts.map +1 -0
  607. package/dist/engine/session/memory-repo.js +59 -0
  608. package/dist/engine/session/memory-repo.js.map +1 -0
  609. package/dist/engine/session/memory-storage.d.ts +14 -0
  610. package/dist/engine/session/memory-storage.d.ts.map +1 -0
  611. package/dist/engine/session/memory-storage.js +17 -0
  612. package/dist/engine/session/memory-storage.js.map +1 -0
  613. package/dist/engine/session/repo-utils.d.ts +11 -0
  614. package/dist/engine/session/repo-utils.d.ts.map +1 -0
  615. package/dist/engine/session/repo-utils.js +40 -0
  616. package/dist/engine/session/repo-utils.js.map +1 -0
  617. package/dist/engine/session/session.d.ts +34 -0
  618. package/dist/engine/session/session.d.ts.map +1 -0
  619. package/dist/engine/session/session.js +227 -0
  620. package/dist/engine/session/session.js.map +1 -0
  621. package/dist/engine/session/storage-base.d.ts +38 -0
  622. package/dist/engine/session/storage-base.d.ts.map +1 -0
  623. package/dist/engine/session/storage-base.js +157 -0
  624. package/dist/engine/session/storage-base.js.map +1 -0
  625. package/dist/engine/session/timestamps.d.ts +3 -0
  626. package/dist/engine/session/timestamps.d.ts.map +1 -0
  627. package/dist/engine/session/timestamps.js +15 -0
  628. package/dist/engine/session/timestamps.js.map +1 -0
  629. package/dist/engine/session/uuid.d.ts +2 -0
  630. package/dist/engine/session/uuid.d.ts.map +1 -0
  631. package/dist/engine/session/uuid.js +50 -0
  632. package/dist/engine/session/uuid.js.map +1 -0
  633. package/dist/index.d.ts +160 -0
  634. package/dist/index.d.ts.map +1 -0
  635. package/dist/index.js +374 -0
  636. package/dist/index.js.map +1 -0
  637. package/dist/internal/harness.d.ts +26 -0
  638. package/dist/internal/harness.d.ts.map +1 -0
  639. package/dist/internal/harness.js +24 -0
  640. package/dist/internal/harness.js.map +1 -0
  641. package/dist/internal/llm.d.ts +9 -0
  642. package/dist/internal/llm.d.ts.map +1 -0
  643. package/dist/internal/llm.js +8 -0
  644. package/dist/internal/llm.js.map +1 -0
  645. package/dist/orchestration/builtin-workflows.d.ts +44 -0
  646. package/dist/orchestration/builtin-workflows.d.ts.map +1 -0
  647. package/dist/orchestration/builtin-workflows.js +165 -0
  648. package/dist/orchestration/builtin-workflows.js.map +1 -0
  649. package/dist/orchestration/dev-vm-script-runner.d.ts +24 -0
  650. package/dist/orchestration/dev-vm-script-runner.d.ts.map +1 -0
  651. package/dist/orchestration/dev-vm-script-runner.js +106 -0
  652. package/dist/orchestration/dev-vm-script-runner.js.map +1 -0
  653. package/dist/orchestration/goal.d.ts +97 -0
  654. package/dist/orchestration/goal.d.ts.map +1 -0
  655. package/dist/orchestration/goal.js +248 -0
  656. package/dist/orchestration/goal.js.map +1 -0
  657. package/dist/orchestration/run-spec.d.ts +63 -0
  658. package/dist/orchestration/run-spec.d.ts.map +1 -0
  659. package/dist/orchestration/run-spec.js +274 -0
  660. package/dist/orchestration/run-spec.js.map +1 -0
  661. package/dist/orchestration/run-workflow-tool.d.ts +187 -0
  662. package/dist/orchestration/run-workflow-tool.d.ts.map +1 -0
  663. package/dist/orchestration/run-workflow-tool.js +612 -0
  664. package/dist/orchestration/run-workflow-tool.js.map +1 -0
  665. package/dist/orchestration/workflow-governance.d.ts +70 -0
  666. package/dist/orchestration/workflow-governance.d.ts.map +1 -0
  667. package/dist/orchestration/workflow-governance.js +176 -0
  668. package/dist/orchestration/workflow-governance.js.map +1 -0
  669. package/dist/orchestration/workflow-meta.d.ts +41 -0
  670. package/dist/orchestration/workflow-meta.d.ts.map +1 -0
  671. package/dist/orchestration/workflow-meta.js +426 -0
  672. package/dist/orchestration/workflow-meta.js.map +1 -0
  673. package/dist/orchestration/workflow-observe.d.ts +77 -0
  674. package/dist/orchestration/workflow-observe.d.ts.map +1 -0
  675. package/dist/orchestration/workflow-observe.js +177 -0
  676. package/dist/orchestration/workflow-observe.js.map +1 -0
  677. package/dist/orchestration/workflow-primitives.d.ts +31 -0
  678. package/dist/orchestration/workflow-primitives.d.ts.map +1 -0
  679. package/dist/orchestration/workflow-primitives.js +104 -0
  680. package/dist/orchestration/workflow-primitives.js.map +1 -0
  681. package/dist/orchestration/workflow-sandbox-conformance.d.ts +34 -0
  682. package/dist/orchestration/workflow-sandbox-conformance.d.ts.map +1 -0
  683. package/dist/orchestration/workflow-sandbox-conformance.js +301 -0
  684. package/dist/orchestration/workflow-sandbox-conformance.js.map +1 -0
  685. package/dist/orchestration/workflow-script-runner.d.ts +127 -0
  686. package/dist/orchestration/workflow-script-runner.d.ts.map +1 -0
  687. package/dist/orchestration/workflow-script-runner.js +48 -0
  688. package/dist/orchestration/workflow-script-runner.js.map +1 -0
  689. package/dist/orchestration/workflow-script-store.d.ts +99 -0
  690. package/dist/orchestration/workflow-script-store.d.ts.map +1 -0
  691. package/dist/orchestration/workflow-script-store.js +133 -0
  692. package/dist/orchestration/workflow-script-store.js.map +1 -0
  693. package/dist/orchestration/workflow-size-guideline.d.ts +50 -0
  694. package/dist/orchestration/workflow-size-guideline.d.ts.map +1 -0
  695. package/dist/orchestration/workflow-size-guideline.js +78 -0
  696. package/dist/orchestration/workflow-size-guideline.js.map +1 -0
  697. package/dist/orchestration/workflow.d.ts +624 -0
  698. package/dist/orchestration/workflow.d.ts.map +1 -0
  699. package/dist/orchestration/workflow.js +1596 -0
  700. package/dist/orchestration/workflow.js.map +1 -0
  701. package/dist/prompts/default.d.ts +474 -0
  702. package/dist/prompts/default.d.ts.map +1 -0
  703. package/dist/prompts/default.js +676 -0
  704. package/dist/prompts/default.js.map +1 -0
  705. package/dist/prompts/supervisor.d.ts +60 -0
  706. package/dist/prompts/supervisor.d.ts.map +1 -0
  707. package/dist/prompts/supervisor.js +162 -0
  708. package/dist/prompts/supervisor.js.map +1 -0
  709. package/dist/scenarios/env.d.ts +41 -0
  710. package/dist/scenarios/env.d.ts.map +1 -0
  711. package/dist/scenarios/env.js +65 -0
  712. package/dist/scenarios/env.js.map +1 -0
  713. package/dist/scenarios/full-body.d.ts +47 -0
  714. package/dist/scenarios/full-body.d.ts.map +1 -0
  715. package/dist/scenarios/full-body.js +36 -0
  716. package/dist/scenarios/full-body.js.map +1 -0
  717. package/dist/scenarios/scenario-registry.d.ts +107 -0
  718. package/dist/scenarios/scenario-registry.d.ts.map +1 -0
  719. package/dist/scenarios/scenario-registry.js +192 -0
  720. package/dist/scenarios/scenario-registry.js.map +1 -0
  721. package/dist/scenarios/teacher-quickstart.d.ts +41 -0
  722. package/dist/scenarios/teacher-quickstart.d.ts.map +1 -0
  723. package/dist/scenarios/teacher-quickstart.js +32 -0
  724. package/dist/scenarios/teacher-quickstart.js.map +1 -0
  725. package/dist/server/http.d.ts +36 -0
  726. package/dist/server/http.d.ts.map +1 -0
  727. package/dist/server/http.js +144 -0
  728. package/dist/server/http.js.map +1 -0
  729. package/dist/stores/file/checkpoint-store.d.ts +62 -0
  730. package/dist/stores/file/checkpoint-store.d.ts.map +1 -0
  731. package/dist/stores/file/checkpoint-store.js +250 -0
  732. package/dist/stores/file/checkpoint-store.js.map +1 -0
  733. package/dist/stores/file/file-snapshot-store.d.ts +43 -0
  734. package/dist/stores/file/file-snapshot-store.d.ts.map +1 -0
  735. package/dist/stores/file/file-snapshot-store.js +374 -0
  736. package/dist/stores/file/file-snapshot-store.js.map +1 -0
  737. package/dist/stores/file/fs-atomic.d.ts +95 -0
  738. package/dist/stores/file/fs-atomic.d.ts.map +1 -0
  739. package/dist/stores/file/fs-atomic.js +415 -0
  740. package/dist/stores/file/fs-atomic.js.map +1 -0
  741. package/dist/stores/file/index.d.ts +98 -0
  742. package/dist/stores/file/index.d.ts.map +1 -0
  743. package/dist/stores/file/index.js +109 -0
  744. package/dist/stores/file/index.js.map +1 -0
  745. package/dist/stores/file/memory-store.d.ts +95 -0
  746. package/dist/stores/file/memory-store.d.ts.map +1 -0
  747. package/dist/stores/file/memory-store.js +393 -0
  748. package/dist/stores/file/memory-store.js.map +1 -0
  749. package/dist/stores/file/session-policy-store.d.ts +24 -0
  750. package/dist/stores/file/session-policy-store.d.ts.map +1 -0
  751. package/dist/stores/file/session-policy-store.js +123 -0
  752. package/dist/stores/file/session-policy-store.js.map +1 -0
  753. package/dist/stores/file/session-store.d.ts +34 -0
  754. package/dist/stores/file/session-store.d.ts.map +1 -0
  755. package/dist/stores/file/session-store.js +175 -0
  756. package/dist/stores/file/session-store.js.map +1 -0
  757. package/dist/stores/file/tool-result-store.d.ts +23 -0
  758. package/dist/stores/file/tool-result-store.d.ts.map +1 -0
  759. package/dist/stores/file/tool-result-store.js +61 -0
  760. package/dist/stores/file/tool-result-store.js.map +1 -0
  761. package/dist/stores/file/workflow-journal-store.d.ts +36 -0
  762. package/dist/stores/file/workflow-journal-store.d.ts.map +1 -0
  763. package/dist/stores/file/workflow-journal-store.js +157 -0
  764. package/dist/stores/file/workflow-journal-store.js.map +1 -0
  765. package/dist/stores/file/workflow-run-store.d.ts +58 -0
  766. package/dist/stores/file/workflow-run-store.d.ts.map +1 -0
  767. package/dist/stores/file/workflow-run-store.js +178 -0
  768. package/dist/stores/file/workflow-run-store.js.map +1 -0
  769. package/dist/stores/pg.d.ts +210 -0
  770. package/dist/stores/pg.d.ts.map +1 -0
  771. package/dist/stores/pg.js +652 -0
  772. package/dist/stores/pg.js.map +1 -0
  773. package/dist/tools/fs/encoding.d.ts +51 -0
  774. package/dist/tools/fs/encoding.d.ts.map +1 -0
  775. package/dist/tools/fs/encoding.js +74 -0
  776. package/dist/tools/fs/encoding.js.map +1 -0
  777. package/dist/tools/fs/gh-rate-limit.d.ts +19 -0
  778. package/dist/tools/fs/gh-rate-limit.d.ts.map +1 -0
  779. package/dist/tools/fs/gh-rate-limit.js +35 -0
  780. package/dist/tools/fs/gh-rate-limit.js.map +1 -0
  781. package/dist/tools/fs/index.d.ts +246 -0
  782. package/dist/tools/fs/index.d.ts.map +1 -0
  783. package/dist/tools/fs/index.js +2130 -0
  784. package/dist/tools/fs/index.js.map +1 -0
  785. package/dist/tools/fs/pdf.d.ts +106 -0
  786. package/dist/tools/fs/pdf.d.ts.map +1 -0
  787. package/dist/tools/fs/pdf.js +178 -0
  788. package/dist/tools/fs/pdf.js.map +1 -0
  789. package/dist/tools/fs/repo-map.d.ts +15 -0
  790. package/dist/tools/fs/repo-map.d.ts.map +1 -0
  791. package/dist/tools/fs/repo-map.js +251 -0
  792. package/dist/tools/fs/repo-map.js.map +1 -0
  793. package/dist/tools/fs/safety.d.ts +168 -0
  794. package/dist/tools/fs/safety.d.ts.map +1 -0
  795. package/dist/tools/fs/safety.js +479 -0
  796. package/dist/tools/fs/safety.js.map +1 -0
  797. package/dist/tools/fs/search.d.ts +118 -0
  798. package/dist/tools/fs/search.d.ts.map +1 -0
  799. package/dist/tools/fs/search.js +650 -0
  800. package/dist/tools/fs/search.js.map +1 -0
  801. package/dist/tools/gitea-issue.d.ts +39 -0
  802. package/dist/tools/gitea-issue.d.ts.map +1 -0
  803. package/dist/tools/gitea-issue.js +91 -0
  804. package/dist/tools/gitea-issue.js.map +1 -0
  805. package/dist/tools/monitor.d.ts +64 -0
  806. package/dist/tools/monitor.d.ts.map +1 -0
  807. package/dist/tools/monitor.js +135 -0
  808. package/dist/tools/monitor.js.map +1 -0
  809. package/dist/tools/scheduler-tools.d.ts +48 -0
  810. package/dist/tools/scheduler-tools.d.ts.map +1 -0
  811. package/dist/tools/scheduler-tools.js +449 -0
  812. package/dist/tools/scheduler-tools.js.map +1 -0
  813. package/dist/tools/sql-adapters.d.ts +32 -0
  814. package/dist/tools/sql-adapters.d.ts.map +1 -0
  815. package/dist/tools/sql-adapters.js +31 -0
  816. package/dist/tools/sql-adapters.js.map +1 -0
  817. package/dist/tools/sql.d.ts +36 -0
  818. package/dist/tools/sql.d.ts.map +1 -0
  819. package/dist/tools/sql.js +131 -0
  820. package/dist/tools/sql.js.map +1 -0
  821. package/dist/tools/task-list.d.ts +26 -0
  822. package/dist/tools/task-list.d.ts.map +1 -0
  823. package/dist/tools/task-list.js +352 -0
  824. package/dist/tools/task-list.js.map +1 -0
  825. package/dist/tools/todo.d.ts +11 -0
  826. package/dist/tools/todo.d.ts.map +1 -0
  827. package/dist/tools/todo.js +126 -0
  828. package/dist/tools/todo.js.map +1 -0
  829. package/dist/tools/web.d.ts +59 -0
  830. package/dist/tools/web.d.ts.map +1 -0
  831. package/dist/tools/web.js +607 -0
  832. package/dist/tools/web.js.map +1 -0
  833. package/dist/tools/worktree.d.ts +88 -0
  834. package/dist/tools/worktree.d.ts.map +1 -0
  835. package/dist/tools/worktree.js +434 -0
  836. package/dist/tools/worktree.js.map +1 -0
  837. package/docs/A1-ATTRIBUTION-ROUND1-2026-07-09.md +181 -0
  838. package/docs/AB-ORACLE-GATE-VERDICT-2026-07-10.md +100 -0
  839. package/docs/ANCHOR-GAP-INVENTORY-2026-07-09.md +143 -0
  840. package/docs/ARCHITECTURE.md +125 -0
  841. package/docs/BUGHUNT-2026-07-05-NIGHT.md +98 -0
  842. package/docs/BUILD.md +63 -0
  843. package/docs/CANCEL-ASYNC-ATTRIBUTION-2026-07-09.md +98 -0
  844. package/docs/CC-198-VS-201-DRIFT-2026-07-09.md +70 -0
  845. package/docs/CC-BASELINE-FAKE-ZERO-AUDIT-2026-07-09.md +51 -0
  846. package/docs/CC-DRIFT-198-206-AGENT-TYPES-2026-07-10.md +82 -0
  847. package/docs/CC-DRIFT-198-206-CHANGELOG-2026-07-10.md +82 -0
  848. package/docs/CC-DRIFT-198-206-REMINDERS-2026-07-10.md +96 -0
  849. package/docs/CC-DRIFT-198-206-ROADMAP-2026-07-10.md +110 -0
  850. package/docs/CC-DRIFT-198-206-TOOL-INVENTORY-2026-07-10.md +53 -0
  851. package/docs/CC-DRIFT-198-206-USAGE-CONSTANTS-2026-07-10.md +64 -0
  852. package/docs/CC-DRIFT-198-206-WORKFLOW-2026-07-10.md +83 -0
  853. package/docs/CC-PARITY-CHECKLIST.md +220 -0
  854. package/docs/CC-PARITY-DEEP-SWEEP-2026-07-07.md +149 -0
  855. package/docs/CC-SUBAGENT-PROMPT-STUDY-2026-07-09.md +219 -0
  856. package/docs/CC-TASK-REMINDER-CADENCE-STUDY-2026-07-09.md +396 -0
  857. package/docs/CC-TOOL-PARITY-SWEEP-2026-07.md +56 -0
  858. package/docs/CC-TOOL-PROMPT-DEEP-DIFF-2026-07-08.md +274 -0
  859. package/docs/CC-TOOLSURFACE-DEEP-DIVE-2026-07-07.md +197 -0
  860. package/docs/CC206-OBSERVER-ANCHORS-2026-07-11.md +463 -0
  861. package/docs/CC207-CORE-SWEEP-BACKLOG-2026-07-12.md +155 -0
  862. package/docs/CENTER-CONTROL-PLANE-SEAM.md +86 -0
  863. package/docs/CLEANUP-CONTRACT-ANCHOR-2026-07-09.md +83 -0
  864. package/docs/COLD-START-RSI-2026-07-09.md +72 -0
  865. package/docs/COMPACTION-LIVE-AUDIT-2026-07-09.md +114 -0
  866. package/docs/CONTEXT-lifecycle-extension-points-and-stop-attribution.md +71 -0
  867. package/docs/COREWARS-POLYGLOT-TRIAGE-2026-07-09.md +85 -0
  868. package/docs/DEADTARGET-OVERFULL-HBOX-2026-07-10.md +92 -0
  869. package/docs/DEADTARGET-PATH-TRACING-REVERSE-2026-07-10.md +87 -0
  870. package/docs/DEADTARGET-WINNING-AVG-COREWARS-2026-07-10.md +96 -0
  871. package/docs/DEEPSEEK-API-LIMITS-PROBE-2026-07-09.md +118 -0
  872. package/docs/DESIGN-140-MOCK-VERIFY-2026-07-11.md +79 -0
  873. package/docs/DESIGN-140-VERIFICATION-2026-07-11.md +43 -0
  874. package/docs/DESIGN-DRAFT-workflow-collab-2026-07-11.md +56 -0
  875. package/docs/DESIGN-ORACLE-GROUNDING-GATE-2026-07-10.md +167 -0
  876. package/docs/DESIGN-TFRAG-RECONCILE-SCAFFOLD-2026-07-09.md +102 -0
  877. package/docs/EXP-PA2-PE-DESIGN-2026-07-11.md +220 -0
  878. package/docs/EXT-DOGFOOD-2026-07-12.md +50 -0
  879. package/docs/FINAL-VERIFY-SURFACE-AUDIT-2026-07-09.md +44 -0
  880. package/docs/FRAG-RECON-INVESTIGATION-2026-07-09.md +183 -0
  881. package/docs/HANDOFF.md +121 -0
  882. package/docs/KNOWN-ISSUES.md +96 -0
  883. package/docs/LEGW-WINDOW-TAX-2026-07-10.md +82 -0
  884. package/docs/LIVE-PROBE-BATCH-2026-07-11.md +207 -0
  885. package/docs/M2-CERT-ATTRIBUTION-2026-07-10.md +61 -0
  886. package/docs/M25-LEG-VARIANCE-ATTRIBUTION-2026-07-10.md +81 -0
  887. package/docs/MAILMAN-TIMEOUT-ATTRIBUTION-2026-07-10.md +88 -0
  888. package/docs/MEMORY-BACKEND-DIALECT-NOTES.md +69 -0
  889. package/docs/MTEB-ESCAPE-HATCH-ATTRIBUTION-2026-07-09.md +57 -0
  890. package/docs/MTEB-LEADERBOARD-ATTRIBUTION-2026-07-10.md +134 -0
  891. package/docs/ORACLE-GATE-NEGATIVE-SAMPLE-2026-07-11.md +28 -0
  892. package/docs/PARITY-CONTEXT-TRANSACTIONS-2026-07-10.md +67 -0
  893. package/docs/PARITY-PROGRESS-MATRIX-2026-07-10.md +37 -0
  894. package/docs/PARITY-SPOT-AGENT-TYPES-2026-07-10.md +70 -0
  895. package/docs/PARITY-SPOT-REMINDERS-2026-07-10.md +144 -0
  896. package/docs/PARITY-SPOT-TOOL-INVENTORY-2026-07-10.md +61 -0
  897. package/docs/PARITY-SPOT-USAGE-CONSTANTS-2026-07-10.md +95 -0
  898. package/docs/PARITY-SPOT-WORKFLOW-2026-07-10.md +93 -0
  899. package/docs/PASSWORD-RECOVERY-PANEL-VERDICT-2026-07-10.md +62 -0
  900. package/docs/R8-R9-FINALIZE-COORDINATION-2026-07-09.md +124 -0
  901. package/docs/REPL-CODE-MODE-EVALUATION-2026-07-10.md +187 -0
  902. package/docs/REPORT-1249-TARGETED.md +48 -0
  903. package/docs/RESEARCH-3P-MEMORY-SWAP-2026-07-12.md +273 -0
  904. package/docs/ROADMAP.md +111 -0
  905. package/docs/RSI-CLOUD-DEPLOY-2026-07-06.md +289 -0
  906. package/docs/RSI-PROCESS-AI-COLDSTART-2026-07-11.md +68 -0
  907. package/docs/S18-THOROUGHNESS-AUDIT-2026-07-09.md +113 -0
  908. package/docs/SERVICE-INTEGRATION-GUIDE.md +298 -0
  909. package/docs/SUBAGENT-STREAM-RESILIENCE-PARITY-2026-07-10.md +118 -0
  910. package/docs/SWEBENCH-PRO-RECON-2026-07-11.md +31 -0
  911. package/docs/TB-EFFICIENCY-TELEMETRY-2026-07-08.md +114 -0
  912. package/docs/TB-FAILURE-AUTOPSY-2026-07-05-RERUN.md +67 -0
  913. package/docs/TB-FAIRNESS-AUDIT-2026-07-08.md +141 -0
  914. package/docs/TB-FULL-1257-2026-07-08.md +77 -0
  915. package/docs/TB-LEG-GAP-ATTRIBUTION-1261-1263-2026-07-11.md +154 -0
  916. package/docs/TB-REGRESSION-DAEMON-KILL-2026-07-08.md +58 -0
  917. package/docs/TB-RSI-CROSSCHECK-2026-07-06.md +68 -0
  918. package/docs/TB-RSI-LEDGER.md +30 -0
  919. package/docs/TB-STABLE-SET-2026-07-08.md +127 -0
  920. package/docs/TB21-RECON-2026-07-11.md +28 -0
  921. package/docs/TEST-DESIGN-BATCH-1-2-3.md +97 -0
  922. package/docs/THIRD-PARTY-INTEGRATION.md +45 -0
  923. package/docs/TOKEN-ESTIMATE-CALIBRATION-LIVE-2026-07-09.md +102 -0
  924. package/docs/audit-2026-06-10-/347/254/254/344/272/214/350/275/256-/347/251/272/347/231/275/345/214/272/344/270/216/345/277/230/346/216/245/347/272/277.md +147 -0
  925. package/docs/audit-2026-06-10-/350/256/241/347/256/227bug/346/211/253/346/217/217.md +163 -0
  926. package/docs/audit-2026-06-11-/344/277/256/345/244/215/345/244/215/345/256/241/344/270/216/345/233/236/345/275/222/344/270/223/346/211/253.md +95 -0
  927. package/docs/audit-2026-06-12-design71-P1/346/275/234/344/274/217/351/235/242/350/243/201/345/206/263/344/270/216/345/220/236/351/224/231/345/256/241/350/256/241.md +45 -0
  928. package/docs/audit-2026-06-12-/345/205/254/345/274/200/346/227/213/351/222/256/346/264/273/346/200/247/344/270/216vendored/346/255/273/350/267/257.md +63 -0
  929. package/docs/audit-2026-06-15/ADDENDUM-second-pass.md +88 -0
  930. package/docs/audit-2026-06-15/ARCHITECTURE-AND-ROADMAP.md +187 -0
  931. package/docs/audit-2026-06-15/DOC-CORRECTIONS.md +105 -0
  932. package/docs/audit-2026-06-15/INDEX.md +49 -0
  933. package/docs/audit-2026-06-15/ORCHESTRATION-STATUS.md +98 -0
  934. package/docs/audit-2026-06-15/PRODUCTION-ISSUES.md +189 -0
  935. package/docs/audit-2026-06-15/REFERENCES-literature.md +139 -0
  936. package/docs/audit-2026-06-15/VENDOR-REFACTOR-PLAN.md +96 -0
  937. package/docs/cc-probe-198/README.md +72 -0
  938. package/docs/cc-probe-198/STABILITY-AUDIT.md +118 -0
  939. package/docs/cc-probe-198/live-schema-monitor-worktree-2026-07-09.json +56 -0
  940. package/docs/cc-probe-198/mount-variants.json +536 -0
  941. package/docs/cc-probe-198/plan-mode-run.json +1 -0
  942. package/docs/cc-probe-198/probe-bash-bg.json +224 -0
  943. package/docs/cc-probe-198/probe-edit-mismatch.json +120 -0
  944. package/docs/cc-probe-198/probe-read-missing.json +62 -0
  945. package/docs/cc-probe-198/probe-search-empty.json +127 -0
  946. package/docs/cc-probe-198/probe-task-family.json +227 -0
  947. package/docs/cc-probe-198/probes.status +6 -0
  948. package/docs/cc-probe-198/raw-capture-interactive.json +948 -0
  949. package/docs/cc-probe-198/raw-capture-print.json +787 -0
  950. package/docs/cc-probe-198/raw-capture2-interactive.json +948 -0
  951. package/docs/cc-probe-198/raw-capture2-print.json +787 -0
  952. package/docs/cc-probe-198/system-prompt.txt +135 -0
  953. package/docs/cc-probe-198/tools-array.json +962 -0
  954. package/docs/durability-boundary.md +63 -0
  955. package/docs/fix-2026-06-10-/350/256/241/347/256/227bug/344/277/256/345/244/215-search/346/211/271.md +75 -0
  956. package/docs/fix-2026-06-11-/347/254/254/344/272/214/350/275/256-/344/277/256/345/244/215-search/346/211/271.md +62 -0
  957. package/docs/parity-sweep/REPORT-DYNAMIC.md +97 -0
  958. package/docs/parity-sweep/REPORT-STATIC-GGB.md +127 -0
  959. package/docs/parity-sweep/REPORT-STATIC-RWE.md +133 -0
  960. package/docs/vendor-history.md +385 -0
  961. package/docs/vendored-upstream-diff-2026-07.md +83 -0
  962. package/package.json +70 -0
@@ -0,0 +1,2828 @@
1
+ import type { TSchema } from "typebox";
2
+ import type { AgentTool, ThinkingLevel } from "../internal/harness.js";
3
+ import type { DocumentContent, ImageContent, Model, ResilienceOptions, StreamFn, TextContent } from "../internal/llm.js";
4
+ import type { TaskNotificationPayload } from "./task-notification.js";
5
+ /** A model reference: either a fully-formed Model, or a `"provider/id"` ref resolved via a catalog. */
6
+ export type ModelRef = string | Model;
7
+ /**
8
+ * Logical model roles, so a deployment declares its models once and every subsystem asks for its
9
+ * role instead of repeating a model name. Resolved against `RunnerDeps.roles` / `TaskSpec.roles`
10
+ * with a fallback chain (e.g. `summarize → default`, `synthesize → team → default`).
11
+ * - `default` — the main task model when `TaskSpec.model` is omitted.
12
+ * - `summarize` — between-turn compaction/summarization (aider's "weak model"); a cheap tier.
13
+ * - `subagent` — delegated sub-runs (`createSubagentTool` without an explicit model).
14
+ * - `team` / `synthesize` — team members / the neutral synthesizer.
15
+ * - `advisor` — the strong "teacher" a cheap student escalates to (`runWithTeacher`).
16
+ */
17
+ export type ModelRole = "default" | "summarize" | "subagent" | "team" | "synthesize" | "advisor" | "verifier";
18
+ /**
19
+ * A role's model: a `ModelRef`, or a config object that pins a `model`, **selects** one by
20
+ * capability/price (`select`, design/11 Layer 2), and/or sets a default `thinking` level.
21
+ */
22
+ export type RoleSpec = ModelRef | {
23
+ model?: ModelRef;
24
+ select?: import("./select-model.js").ModelCriteria;
25
+ thinking?: ThinkingLevel;
26
+ /**
27
+ * Optional preset system prompt for this role (e.g. {@link CODE_AGENT_PROMPT} for a dev role).
28
+ * Used only when the task does not supply its own `TaskSpec.systemPrompt`. Lets coding roles run
29
+ * a coding prompt while other roles keep the neutral default — without touching the global default.
30
+ */
31
+ systemPrompt?: string;
32
+ };
33
+ /** Map of role → model. `TaskSpec.roles` overrides `RunnerDeps.roles` per task/scenario. */
34
+ export type ModelRoles = Partial<Record<ModelRole, RoleSpec>>;
35
+ /** The "external brain": a streaming completion function plus a non-streaming one (auto-derived if omitted). */
36
+ export interface Brain {
37
+ /** Streaming completion. Must follow the AssistantMessageEvent stream contract (never throw post-invocation).
38
+ *
39
+ * NOTE: the return type is a union — `Stream | Promise<Stream>`. Third-party direct callers must
40
+ * normalize first (`const s = await brain.stream(...)`) before iterating or reading `.result()`,
41
+ * otherwise TS reports TS2339 on the union. The Runner already handles this internally. */
42
+ stream: StreamFn;
43
+ /**
44
+ * Optional non-streaming completion used by compaction/summarization.
45
+ * If omitted, it is derived from `stream` by consuming the stream to its final result.
46
+ *
47
+ * CONTRACT: a custom implementation must return the AssistantMessage with ALL fields intact —
48
+ * including `errorKind` (the compaction summary path keys its budget-escalation recovery on it)
49
+ * and `errorMessage`. Rebuilding the message with a field whitelist silently disables recovery.
50
+ */
51
+ complete?: (model: Model, context: {
52
+ systemPrompt?: string;
53
+ messages: unknown[];
54
+ }, options?: unknown) => Promise<unknown>;
55
+ }
56
+ /**
57
+ * Side-effect class of a tool. Used by wake/resume reconciliation: when a call was interrupted
58
+ * before its result was recorded, the outcome is unknown, so core must decide whether re-doing it
59
+ * is safe. See {@link reconcileInterruptedSession}.
60
+ * - `read` — no side effects (a query/lookup). Safe to call again.
61
+ * - `idempotent` — has a side effect, but repeating it with the same args is equivalent to doing it
62
+ * once (e.g. `PUT` a known key, set-to-value). Safe to call again.
63
+ * - `write` — a non-idempotent side effect (delete, append, charge, send). **Unsafe to repeat
64
+ * blindly.** This is the conservative default when `effect` is omitted.
65
+ */
66
+ export type ToolEffect = "read" | "write" | "idempotent";
67
+ /** A native tool the model can call. `parameters` is a typebox schema; `execute` does the work. */
68
+ export interface ToolSpec<TParams extends TSchema = TSchema> {
69
+ /**
70
+ * Model-facing tool name. MUST NOT contain `__` — that separator is reserved for the MCP namespace
71
+ * (`mcp__<server>__<tool>`); a caller tool name with `__` is rejected at prepare-time (`config.tool_name_invalid`)
72
+ * because the durable-resume name shim ({@link canonicalToolName}) would mis-namespace it across an upgrade.
73
+ */
74
+ name: string;
75
+ /**
76
+ * Backward-compatible model-facing names that should dispatch to this tool. New transcripts and tool rosters
77
+ * should use {@link name}; aliases exist only so old model calls / SDK payloads / resumed sessions don't strand
78
+ * across a canonical rename.
79
+ */
80
+ aliases?: string[];
81
+ description: string;
82
+ /**
83
+ * Human label for UIs. Defaults to `name`.
84
+ *
85
+ * ⚠️ Currently INERT (design/71 liveness sweep, 2026-06-12): mapped onto the tool object but no
86
+ * runtime path or emitted event reads it — the model and TaskStream consumers only ever see
87
+ * `name`. Kept for API stability; wire it into tool events or drop it before building on it.
88
+ */
89
+ label?: string;
90
+ /**
91
+ * G1 通告层 (CC `agent_listing_delta` parity): the delegation tool's agent-type roster (name + one-line
92
+ * description), filled by `createSubagentTool` so the Runner's turn-boundary announcer can surface the
93
+ * "Available agent types" reminder without reaching into the tool's closure. Deployment-authored tools
94
+ * normally leave it unset; the announcer only runs when `TaskSpec.attachments.agentListing` opts in.
95
+ */
96
+ agentListing?: ReadonlyArray<{
97
+ name: string;
98
+ description: string;
99
+ }>;
100
+ /**
101
+ * design/136 §2.1.c — OPTIONAL pre-validation compatibility shim for raw tool-call arguments (mirrors the
102
+ * engine `AgentTool.prepareArguments` seam it is forwarded onto): map a LEGACY argument shape onto the
103
+ * current schema BEFORE schema validation, so a persisted old-shape call (a pre-rename durable checkpoint's
104
+ * pendingAction replayed via {@link canonicalToolName}) doesn't fail the declared-schema check. MUST be
105
+ * idempotent and identity for already-canonical args (the engine path applies it before validation AND the
106
+ * defineTool wrapper applies it again before its own check). Consumer example: the Agent tool maps the
107
+ * retired Fork tool's `{directive}` onto `{prompt, subagent_type:"fork"}`.
108
+ */
109
+ prepareArguments?: (args: unknown) => unknown;
110
+ /**
111
+ * Side-effect class for wake/resume safety. Defaults to `write` (conservative) when omitted:
112
+ * an interrupted call of unknown effect is treated as possibly-applied and never auto-repeated.
113
+ */
114
+ effect?: ToolEffect;
115
+ /**
116
+ * design/70: marks a tool whose execution is an EXTERNAL write (egress) — an outward-visible,
117
+ * effectively-irreversible action (open a PR, push a branch, send) as opposed to an internal side
118
+ * effect. **Orthogonal to {@link effect}**: `effect` is the repeat-safety axis (wake/resume
119
+ * reconciliation), `egress` is the blast-radius axis (the design/37 gate); reconcile/wake ignore it.
120
+ * The gate NEVER auto-allows an egress tool: a surviving `allow` (default or policy) is tightened to
121
+ * `ask`, so execution always passes an explicit ask-resolution — synchronous `onAsk`, a durable
122
+ * suspend (design/45), or a deployment-authored approver. Headless stays deny (an external write
123
+ * never happens without explicit confirmation). An egress tool must be repeat-unsafe: declaring
124
+ * `effect: "read"`/`"idempotent"` with `egress: true` is a configuration error (fail-fast at
125
+ * prepare) — omitting `effect` is fine (the default IS `write`).
126
+ */
127
+ egress?: true;
128
+ /**
129
+ * design/77 §4 (Gate 4 — irreversibility axis): how reversible this tool's effect is. A THIRD axis,
130
+ * orthogonal to {@link effect} (repeat-safety) and {@link egress} (blast-radius). For office/finance
131
+ * primitives (send money, file a return, send an email) where a wrong action cannot be undone, this
132
+ * forces a durable human-approval suspend BEFORE the tool runs:
133
+ * - `"never"` — fully reversible; the gate leaves a surviving `allow` untouched (no ask).
134
+ * - `"maybe"` — reversibility depends on the args; the gate calls {@link reversibilityProbe} (when one is
135
+ * declared) on a surviving `allow` and tightens to `ask` UNLESS the probe reports reversible. A tool
136
+ * that declares a `reversibilityProbe` but omits `irreversibility` defaults to `"maybe"` (so it always
137
+ * enters the activation set and is gated).
138
+ * - `"always"` — irreversible; the gate ALWAYS tightens a surviving `allow` to `ask` (like {@link egress}).
139
+ *
140
+ * The tighten mirrors the egress tighten (it only ever tightens allow→ask; a `deny`/`ask` is untouched),
141
+ * runs immediately AFTER it, and routes through the SAME ask-resolution: synchronous `onAsk`, a durable
142
+ * suspend (a new `{kind:"irreversible_ask"}` checkpoint → `status:"suspended"`), or a deployment approver.
143
+ * Headless with no approver SUSPENDS durably (never a model-facing deny — that would be a reward-hack
144
+ * retry surface), so an irreversible action never runs unattended without explicit confirmation.
145
+ *
146
+ * **Note (deliberate redundancy):** `egress` already means "effectively-irreversible external write"; an
147
+ * `egress:true` + `irreversibility:"always"` tool is DOUBLE-tightened. Harmless (allow→ask is idempotent
148
+ * under the deny>ask fold) — the two axes overlap on purpose, they are NOT strictly disjoint.
149
+ */
150
+ irreversibility?: "never" | "maybe" | "always";
151
+ /**
152
+ * design/77 §4: optional deployment-injected probe for an `irreversibility:"maybe"` tool. Given the call's
153
+ * (post-hook) args, it reports whether THIS specific call is reversible. The gate calls it ONLY when the
154
+ * surviving decision is `allow` and `irreversibility` resolves to `"maybe"`; it is time-bounded (the
155
+ * approval timeout) and **fail-closed**: a non-`reversible` verdict, a timeout, or a throw all tighten to
156
+ * `ask`. Declaring this probe defaults `irreversibility` to `"maybe"`. It is read from the spec at
157
+ * prepare-time and captured in a closure — NOT a tool argument — so the model cannot monkey-patch it.
158
+ */
159
+ reversibilityProbe?: (args: unknown) => {
160
+ reversible: boolean;
161
+ } | Promise<{
162
+ reversible: boolean;
163
+ }>;
164
+ /**
165
+ * Batch execution mode (design/64 §1 P1, CC reads-parallel/writes-sequential partition). When omitted,
166
+ * `defineTool` derives it FAIL-CLOSED from `effect` (CC 2.1.206 `TOOL_DEFAULTS.isConcurrencySafe → false`):
167
+ * `read` → `"parallel"`; `write`/`idempotent`/UNDECLARED → `"sequential"` — an unannotated tool never
168
+ * silently rides a parallel batch, and two writes in one batch never race. Set explicitly to override.
169
+ */
170
+ executionMode?: "sequential" | "parallel";
171
+ /**
172
+ * design/120 P1.5 (CC `isConcurrencySafe(parsedInput)` parity): input-level concurrency
173
+ * refinement for a non-`"parallel"` tool — return `true` to let THIS CALL run in a parallel batch
174
+ * (and, under `streamingToolExecution`, start in-stream). An explicit `executionMode:"parallel"`
175
+ * needs no refinement (always safe); a throw = false (fail-closed). In the batch/stream paths the
176
+ * hook receives schema-VALIDATED (coerced) args — CC 206 `parsed.data` parity; a schema-invalid
177
+ * call is judged unsafe before the hook runs. Still treat defensively (direct callers may pass raw).
178
+ * The one real consumer is Bash's read-only classifier.
179
+ */
180
+ isConcurrencySafe?: (args: unknown) => boolean;
181
+ /** typebox schema for the tool arguments. */
182
+ parameters: TParams;
183
+ /**
184
+ * Large-result offload (design/30): set `false` to NEVER offload this tool's output (e.g. a file-read
185
+ * tool whose output IS the deliverable — offloading then immediately re-reading would just churn).
186
+ * Default: offload when the result exceeds the resolved threshold.
187
+ */
188
+ offload?: boolean;
189
+ /** Per-tool offload threshold (chars), overriding the global {@link RunnerDeps.toolResultThresholdChars}. */
190
+ offloadThresholdChars?: number;
191
+ /**
192
+ * Deferred disclosure (design/36): when `true`, this tool is NOT inlined with its full JSON Schema in
193
+ * every request. It appears as a lightweight placeholder (`{name, one-line hint, empty params}`) so
194
+ * the model knows it exists; the model must call the injected `tool_search` to activate it, at which
195
+ * point core materializes its full schema into the next request's `tools[]` (without disturbing the
196
+ * cache prefix). Use for large/MCP tool sets where inlining hundreds of schemas blows up turn-1 tokens
197
+ * and risks prefix-cache breakage. Default: not deferred (full schema inlined). See {@link RunnerDeps.deferMode}.
198
+ */
199
+ defer?: boolean;
200
+ /**
201
+ * Execute the tool. Return a string (becomes text content) or a structured result.
202
+ * Throw to signal failure (the loop encodes it as an error tool result).
203
+ */
204
+ execute: (args: unknown, ctx: ToolExecuteContext) => Promise<ToolReturn> | ToolReturn;
205
+ }
206
+ /** What a tool's execute may return. */
207
+ export type ToolReturn = string | {
208
+ content: Array<TextContent | ImageContent | DocumentContent> | string;
209
+ /** Arbitrary structured details for logs/UI (not shown to the model unless put in content).
210
+ * Producer side of the tool-result 双面契约: `content` is the MODEL face (may carry model-directed
211
+ * framing/trailers), `details` is the HOST face (per-tool structured Output). Hosts render from the
212
+ * structured face and never re-parse the model face — see the `tool_end.structured` JSDoc
213
+ * (CC 2.1.207 @765495, CC207-CORE-SWEEP P2-3) for the full contract. */
214
+ details?: unknown;
215
+ /** Hint the agent to stop after this tool batch. */
216
+ terminate?: boolean;
217
+ };
218
+ export interface ToolExecuteContext {
219
+ toolCallId: string;
220
+ signal?: AbortSignal;
221
+ /**
222
+ * The RUNNING task's effective working root (worktree-aware), Runner-filled — read-only context a
223
+ * delegation tool threads into its child's trusted internals so the child's env can inherit the
224
+ * parent's cwd (CC parity: a Task sub-agent works in the main session's directory). Undefined when
225
+ * the tool runs outside a Runner task.
226
+ */
227
+ parentCwd?: string;
228
+ /**
229
+ * Report usage spent in a nested run this tool spawned (e.g. a sub-agent). The Runner accumulates
230
+ * it into the parent task's `TaskResult.stats.nested`, so delegated cost — the multi-agent "~15×"
231
+ * — is visible at the top level. `createSubagentTool` calls this automatically.
232
+ */
233
+ reportUsage?: (usage: {
234
+ tokens: number;
235
+ turns: number;
236
+ tasks: number;
237
+ costUsd?: number;
238
+ costMicroUsd?: number;
239
+ }) => void;
240
+ /**
241
+ * The model the PARENT task is currently running on, **snapshotted at the moment this tool is called**
242
+ * (design/38 1B). A delegation tool reads it to let a sub-agent `inherit` the caller's model. If the
243
+ * parent later degrades, an already-started child is unaffected (it kept the snapshot). Undefined when
244
+ * the tool runs outside a Runner task.
245
+ */
246
+ model?: Model;
247
+ /**
248
+ * The PARENT task's current thinking level, snapshotted at call time — the {@link model} companion.
249
+ * A delegation tool threads it into the child so a sub-agent inherits the caller's thinking depth by
250
+ * default (an explicit agent-definition/script `thinking` wins). Undefined outside a Runner task.
251
+ */
252
+ thinkingLevel?: ThinkingLevel;
253
+ /**
254
+ * The running task's authenticated end-user {@link TaskSpec.principal} (design/62), **read-only** — the
255
+ * Runner fills it; a tool cannot change it. A delegation tool (`createSubagentTool`) propagates it
256
+ * verbatim to its child task so the end-user identity is inherited down the delegation tree (the worker
257
+ * cannot substitute a different principal — it is not a tool argument). Undefined when the task has no
258
+ * principal or the tool runs outside a Runner task.
259
+ */
260
+ principal?: string;
261
+ /**
262
+ * design/112 C1/C5 — read-only SNAPSHOT of the parent task's client-supplied USER facts (timeZone/userEmail),
263
+ * inherited verbatim down the delegation tree like `principal`, so a subagent/fork child's
264
+ * `# Environment` block localizes "today" to the SAME user zone (not the container's UTC) and names the same
265
+ * user. Runner-filled (NOT a tool argument). Undefined when the task carries no clientContext.
266
+ */
267
+ clientContext?: TaskSpec["clientContext"];
268
+ /**
269
+ * 🔴 design/77 §3 / §7 — read-only SNAPSHOT of the parent task's ACTIVE skill-manifest frames (the
270
+ * Gate-3 deny-narrowing scope, see {@link SkillManifest}), filled by the Runner. A delegation tool
271
+ * (`createSubagentTool`) reads it AT SPAWN TIME and propagates it into the child task so the child
272
+ * inherits the parent skill's tool/path restrictions (a child of a manifested skill is at most as
273
+ * capable as the manifest). Returns an opaque, frozen array of frames; an empty array = no manifest is
274
+ * active (the common case). The model/worker can neither read nor set it (it is not a tool argument).
275
+ * Undefined when the tool runs outside a Runner task. The returned frame objects are intentionally
276
+ * opaque to callers other than the Runner internals that re-seed them.
277
+ */
278
+ activeSkillScope?: () => readonly unknown[];
279
+ /**
280
+ * design/99 (nested-subagent live observability): the host run's stable taskId (`spec.taskId ?? sessionId`),
281
+ * filled by the Runner. A delegation tool (`createSubagentTool`) reads it AT SPAWN TIME and threads it into the
282
+ * child as the child's `parentTaskId`, so a UI can build the live nested-agent tree (child.parentTaskId === this
283
+ * taskId). Undefined when the tool runs outside a Runner task.
284
+ */
285
+ taskId?: string;
286
+ /** design/129: the host run's SESSION id (Runner-filled, read-only) — a session-scoped background child
287
+ * registers under it so later turns (fresh taskId) still reach the entry. */
288
+ sessionId?: string;
289
+ /** design/129: the host spec's `backgroundScope`, threaded read-only so delegation tools apply the
290
+ * deployment's background-lifetime policy (never a model argument). */
291
+ backgroundScope?: "task" | "session";
292
+ /** design/129-B: the process-level background-child observer ({@link RunnerDeps.onBackgroundChildEvent}),
293
+ * threaded read-only so the Agent tool's background lane reports spawn/tick/terminal for the child's
294
+ * whole lifetime (a per-leg sink goes stale when the leg settles; this one never does). */
295
+ onBackgroundChildEvent?: (event: BackgroundChildEvent) => void;
296
+ /**
297
+ * design/115 P3 — the run-local task-notification sink (the SAME lane runtask wires for workflow/bash
298
+ * completions). Injected by prepare-task's spec.tools wrapper so a caller-mounted delegation tool can
299
+ * fire background-agent completion notifications into the SOURCE task's next turn. TRUSTED, run-scoped.
300
+ */
301
+ onTaskNotification?: (n: import("./task-notification.js").TaskNotificationPayload, opts?: {
302
+ priority?: import("./task-notification.js").SystemInjectionPriority;
303
+ }) => void;
304
+ /**
305
+ * design/99 (nested-subagent live observability): the host run's OPT-IN display sink — a deployment sets it (via
306
+ * `RunInternals.onForwardEvent`) to receive a SUBAGENT's live `task_progress` ticks that otherwise stay in the
307
+ * child's ISOLATED stream. A delegation tool threads it to the child so nested progress bubbles to one sink. This
308
+ * is a DISPLAY channel ONLY — the child stream is NEVER merged into the parent's MODEL context, and nothing
309
+ * security-relevant consumes a forwarded event. Present ONLY when the deployment opted in; the Runner filters it
310
+ * to `task_progress` (a tool cannot push other event types). ⚠️ Forwarded ticks are UNTRUSTED display hints — any
311
+ * tool holding this ctx could forge one, so a consumer validates `parentTaskId` against its known runs.
312
+ */
313
+ forwardEvent?: (event: TaskEvent) => void;
314
+ /**
315
+ * Blackboard 2026-07-03 (subagent steer verb): the host run's opt-in SUBAGENT-STEER-HANDLE sink
316
+ * (threaded from `RunInternals.onSubagentSpawn`). When present, `createSubagentTool` runs each sync
317
+ * child via `runTaskStream` and emits a steer handle here; the deployment routes a human steer into
318
+ * the running child. The handle never reaches the model. Absent ⇒ children run non-steerable.
319
+ */
320
+ onSubagentSpawn?: (handle: import("../agents/subagent.js").SubagentSteerHandle) => void;
321
+ /**
322
+ * design/122 D1 — the parent run's subagent-retain LEDGER, present ONLY when the parent's
323
+ * {@link TaskSpec.retainSubagentSessions} is enabled. TRUSTED run-scoped state the Runner fills (never a
324
+ * tool argument): `createSubagentTool` registers each retained child here (pre-minted sessionId + a
325
+ * FROZEN plain spec snapshot — never the live ctx/spec-builder closures, r1-m5) and the Runner disposes
326
+ * the whole ledger (abort in-flight resumes + unpin + release every retained session) when the parent
327
+ * run ends (D4).
328
+ */
329
+ subagentRetain?: import("../agents/subagent.js").SubagentRetainLedger;
330
+ /**
331
+ * design/135 §0 — the TRUSTED per-call worktree-isolation lane for the Agent tool (CC
332
+ * `isolation: "worktree"`). The Runner fills it (prepare-task builds it over the run's ExecutionEnv +
333
+ * task root via `createSubagentWorktreeHelper`) for write-capable runs; a tool cannot forge it and the
334
+ * model only REQUESTS isolation via the Agent tool's `isolation` parameter — the capability itself is
335
+ * never a model argument. Absent ⇒ the deployment cannot mint worktrees (read-only run / outside a
336
+ * Runner) and the Agent tool reports isolation as honestly unavailable.
337
+ */
338
+ worktreeIsolation?: import("../agents/subagent.js").SubagentWorktreeIsolation;
339
+ /**
340
+ * design/135 §0 — TRUE when THIS run is itself a forked child ({@link RunInternals.insideFork}),
341
+ * threaded read-only so the Agent tool's built-in `subagent_type:"fork"` route can refuse nested forks
342
+ * (CC: "fork is not available inside a forked worker") even for a deployment-mounted Agent tool that
343
+ * flowed into the forked child via its tool list. Runner-filled; never a model argument.
344
+ */
345
+ insideFork?: boolean;
346
+ /**
347
+ * OBS-2 (CC 2.1.206 observer parity) — present iff this run's principal resolved
348
+ * {@link RuntimeCaps.allowObservers}` === true` (EXPLICIT opt-in, default OFF — see the polarity
349
+ * note there). The delegation tool honors {@link AgentDefinition.observer} declarations only under
350
+ * this flag; absent ⇒ declarations resolve to unobserved with NO warn (the gate, not a mistake).
351
+ * Runner-filled at call time (same closure posture as `forkAccess`); never a model argument.
352
+ */
353
+ observersAllowed?: true;
354
+ /**
355
+ * design/136 §6 盲点① — the Runner-computed fork-GOVERNANCE verdict for THIS run (from
356
+ * `forkGovernanceDenial(spec.enableFork, runtimeCaps.allowFork)`), threaded read-only so the Agent
357
+ * tool's built-in `subagent_type:"fork"` route enforces the SAME per-task/per-principal authorization
358
+ * as the standalone Fork tool's mount gate (pre-1.256, `allowFork:false` only prevented mounting Fork
359
+ * while Agent-fork ran ungoverned). Present ONLY when governance DENIES (`denied:"task"` =
360
+ * `enableFork:false`; `denied:"principal"` = `runtimeCaps.allowFork:false`) — absent means governance
361
+ * does not object (or the tool runs outside a Runner ⇒ capability checks only). Runner-filled; never a
362
+ * model argument.
363
+ */
364
+ forkAccess?: {
365
+ denied: "task" | "principal";
366
+ };
367
+ /**
368
+ * design/80 D-B — the general "a tool yields to a HUMAN review gate" primitive. A tool calls this to request
369
+ * that, at the next SAFE turn boundary, the engine pause with a durable `plan_review` checkpoint
370
+ * (`status:"needs_review"`) so a human approves/edits/rejects before the run continues. The tool still returns
371
+ * its `content` normally first (the plan/diff lives there → reaches the reviewer via the transcript). HONORED
372
+ * only when the deployment can actually pause (a `checkpointStore` is wired); otherwise the request is a silent
373
+ * no-op (read-only/headless degrade). The first-party `present_plan` tool (CC `ExitPlanMode` parity) is a thin
374
+ * caller of this; any tool may use it to gate a high-blast step on human review. Idempotent within a batch (the
375
+ * first request wins; the suspend fires once at the boundary). The Runner fills it; not a tool arg.
376
+ */
377
+ requestReview?: (opts?: {
378
+ reason?: string;
379
+ }) => void;
380
+ /**
381
+ * design/105 — request a CLEAN stop of THIS run after the current turn (NOT an abort: the loop finishes the
382
+ * turn, then exits gracefully — no orphan-[INTERRUPTED] reconcile). A thin binding to the harness's existing
383
+ * one-way `requestStopAfterTurn` flag (the same the human-suspend saga uses). Typical use: a tool that
384
+ * persisted a delayed self-wake intent (e.g. CronCreate with kind:"delay") ends the run cleanly so the
385
+ * daemon owns the re-wake ("end now, re-wake" — NOT "suspend-continue", see design/105 §3.4). Idempotent
386
+ * one-way flag; a no-op for tools that don't call it. The Runner fills it; not a tool arg. Absent outside a Runner.
387
+ */
388
+ requestStopAfterTurn?: () => void;
389
+ /**
390
+ * design/108 — enter mid-run READ-ONLY plan mode: the rest of THIS run rejects write-effect tool calls
391
+ * (`effect !== "read"`), while read/research tools and `present_plan` still run. A run-local one-way flag
392
+ * (NOT durable — a later approve-resume re-prepares with it clear, so the approved plan can write). The
393
+ * first-party `enter_plan_mode` tool (CC `EnterPlanMode` parity) is the only caller; the engine enforces the
394
+ * read-only restriction in a dedicated plan-mode tool-call check (separate from the safety gate — plan mode
395
+ * is a FIDELITY mode, not a security boundary; the real safety gates apply independently). Idempotent; a
396
+ * no-op for tools that don't call it. The Runner fills it; not a tool arg. Absent outside a Runner.
397
+ */
398
+ enterPlanMode?: () => void;
399
+ }
400
+ /**
401
+ * design/138 S2-C — the hands band's write-time CONTENT hook (single source; `src/tools/fs` re-exports
402
+ * these so its import surface is unchanged — moved here by design/141 件2 because `RunnerDeps.hands`
403
+ * carries the deployment-composable half of the hook). Called before EVERY `env.writeFile` in
404
+ * Write/Edit/NotebookEdit with the resolved containment key and the exact final text; `{ ok:false }`
405
+ * fails the tool with a structured error and NOTHING is written. A THROWING hook fails CLOSED.
406
+ */
407
+ export interface BeforeWriteRequest {
408
+ tool: "Write" | "Edit" | "NotebookEdit";
409
+ /** The model-supplied path argument (for the error-message coordinate the model knows). */
410
+ path: string;
411
+ /** The resolved canonical containment key — what the hook should judge. */
412
+ key: string;
413
+ /** The FINAL full text about to be written (Edit/NotebookEdit: after application). */
414
+ content: string;
415
+ }
416
+ export type BeforeWriteResult = {
417
+ ok: true;
418
+ } | {
419
+ ok: false;
420
+ code: string;
421
+ reason: string;
422
+ };
423
+ export type BeforeWriteHook = (req: BeforeWriteRequest) => BeforeWriteResult | undefined | Promise<BeforeWriteResult | undefined>;
424
+ /**
425
+ * design/141 件2 — the SAFE deployment-configurable subset of the hands toolkit ({@link RunnerDeps.hands}).
426
+ * Only fields whose injection is purely additive for a deployment are here; Runner-internal orchestration
427
+ * state (taskRegistry/detachHub/execClamp/cwdRef/mount coordination) is deliberately NOT configurable.
428
+ */
429
+ export interface HandsBandOptions {
430
+ /** Override the `bash_readonly` command allowlist (read-only band). Default: the built-in read-only set. */
431
+ bashReadonlyAllow?: readonly string[];
432
+ /** Co-Authored-By trailer for the bash git protocol; `false` disables it. Default: the built-in trailer. */
433
+ commitCoAuthor?: string | false;
434
+ /** Read-tool image downsampler: inject your own, or `false` to force-disable (deterministic no-sharp).
435
+ * Omitted ⇒ auto-detect sharp. Same contract as the MCP-side {@link import("./mcp.js").ImageDownsampler}. */
436
+ readImageDownsampler?: ((input: Buffer, mimeType: string) => Promise<import("./mcp.js").DownsampledImage | undefined>) | false;
437
+ /** Deployment write gate — COMPOSED with (never replacing) the engine's MemoryEngine write-scan gate:
438
+ * this hook judges first (a rejection short-circuits), the engine gate then still runs in full. */
439
+ beforeWrite?: BeforeWriteHook;
440
+ }
441
+ /**
442
+ * A declarative, reusable named sub-agent (design/38 1B). Hand a set to {@link createSubagentTool} and the
443
+ * model picks one (by `whenToUse`) to delegate to; the chosen definition's config builds the child task.
444
+ *
445
+ * **Deployment-side config, NOT user input** — `systemPrompt`/`allowTools` shape what the sub-agent can do
446
+ * and see, so they must be set by the deployment, never taken from an end-user message.
447
+ */
448
+ export interface AgentDefinition {
449
+ /** Stable identifier + the value the delegation tool's `agent` parameter selects. Must be unique. */
450
+ name: string;
451
+ /** Guidance shown to the model for WHEN to pick this agent (listed in the delegation tool's description). */
452
+ whenToUse?: string;
453
+ /**
454
+ * F4 (CC 2.1.198 parity, `whenToUseLean` — 锚 pretty.js:409174 `rbm` + selection `tIl` :453029
455
+ * `(lean && e.whenToUseLean) || e.whenToUse`): a SHORT variant of {@link whenToUse} preferred on
456
+ * lean-prompt surfaces. sema posture: the engine runs the CC lean-prompt arm wholesale (web.ts
457
+ * lean-card precedent), so roster listings/descriptions prefer this text whenever present;
458
+ * {@link whenToUse} remains the fallback. Optional — a single-text agent behaves exactly as before.
459
+ */
460
+ whenToUseLean?: string;
461
+ /** Tool allowlist over the delegation pool (`["*"]` = all). Replaces (does not merge with) the tool's
462
+ * own `allowTools`/`denyTools` when this agent is selected. F1 (CC parity): unlike the TOOL-level
463
+ * allow/deny (which never filters the nested delegation tool — that stays `maxDepth`-governed), a
464
+ * PER-AGENT allow/deny ALSO governs the nested delegation tool: an agent whose allow/deny excludes
465
+ * the delegation tool's name cannot re-delegate (CC Explore/Plan `disallowedTools` include Agent,
466
+ * pretty.js:409189/486948). */
467
+ allowTools?: string[];
468
+ /** Tool denylist (a deny always wins). See {@link allowTools} for the per-agent delegation-tool note. */
469
+ denyTools?: string[];
470
+ /**
471
+ * F7 (CC 2.1.198 parity, per-agent `skills` — 锚 pretty.js:422126 `e.skills ?? []`, GA/ungated in 198:
472
+ * CC preloads each named skill's prompt content into the child's opening messages, warning on misses).
473
+ * sema shape: full {@link SkillSpec} objects (sema has no ambient skill registry to resolve bare names
474
+ * against) threaded into the chosen child's `TaskSpec.skills` — disclosed in its `<skills>` block +
475
+ * invocable via the `skill` tool. Deployment-trusted, same trust tier as `systemPrompt`.
476
+ */
477
+ skills?: SkillSpec[];
478
+ /**
479
+ * F7 (CC 2.1.198 parity, per-agent `background` — 锚 pretty.js:453611 `H.background===!0` OR-ed into
480
+ * the background predicate, GA/ungated): `true` = this agent ALWAYS launches on the background lane
481
+ * (an omitted `run_in_background` no longer means sync, and the per-call parameter cannot force sync —
482
+ * CC-same OR semantics). Requires the delegation tool's `background` surface; without one the child
483
+ * runs synchronously (CC-same quiet fallback — CC's env kill-switch arm, :453611 `&& !sJt`).
484
+ */
485
+ background?: boolean;
486
+ /**
487
+ * F7 (CC 2.1.198 parity, per-agent `isolation` — 锚 pretty.js:453599 `z = a ?? H.isolation`, GA):
488
+ * default isolation for this agent; an explicit per-call `isolation` argument wins. sema supports
489
+ * `"worktree"` (CC's `"remote"` arm is a claude.ai-session concern, not ported).
490
+ */
491
+ isolation?: "worktree";
492
+ /** Model for this agent. **Omit to INHERIT the caller's current model** (design/38 1B finding 7) — the
493
+ * recommended default; a concrete `ModelRef` pins it instead. */
494
+ model?: ModelRef;
495
+ /** Thinking level for this agent. **Omit to INHERIT the caller's current thinking level** (the model
496
+ * companion above — a mid-run degrade/boost on the parent carries into new children); a concrete
497
+ * level pins it instead. */
498
+ thinking?: ThinkingLevel;
499
+ /** System prompt / persona for this agent. Falls back to the delegation tool's `systemPrompt`. */
500
+ systemPrompt?: string;
501
+ /** Per-agent turn cap. Falls back to the delegation tool's `limits.maxTurns`. */
502
+ maxTurns?: number;
503
+ /** Long-term memory scope for this agent (same shape as {@link TaskSpec.memory}). */
504
+ memory?: TaskSpec["memory"];
505
+ /**
506
+ * Observer agents (CC 2.1.206 parity — 逐字锚 docs/CC206-OBSERVER-ANCHORS-2026-07-11.md, schema
507
+ * 面 C @28385708): "Agent type auto-spawned as a background observer whenever this agent runs.
508
+ * The observer receives read-only activity digests and reports via the ObserverReport tool; it
509
+ * never participates in the task." Resolution is warn-and-unobserved on an unknown type and
510
+ * refuses chaining (an observer's own `observer` declaration is ignored). Gated by
511
+ * {@link RuntimeCaps.allowObservers} — EXPLICIT opt-in, default OFF (the sema seat of CC's
512
+ * default-unset env `CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS` + default-true statsig pair).
513
+ */
514
+ observer?: string;
515
+ /**
516
+ * CC 面 C: "Supplemental postamble appended (after the harness-owned default) to each activity
517
+ * digest sent to the observer. Blank values are ignored."
518
+ */
519
+ observerMessage?: string;
520
+ }
521
+ /** Definition of an MCP server to connect to for the duration of one task, then discard. */
522
+ export interface McpServerSpec {
523
+ /** Stable name; tool names are namespaced as `<name>__<tool>` to avoid collisions. */
524
+ name: string;
525
+ transport: {
526
+ kind: "stdio";
527
+ command: string;
528
+ args?: string[];
529
+ env?: Record<string, string>;
530
+ } | {
531
+ kind: "http";
532
+ url: string;
533
+ /** Static headers sent on every request (e.g. an auth bearer for the MCP server itself). */
534
+ headers?: Record<string, string>;
535
+ /**
536
+ * Per-task **end-user principal** header (design/62). When set, the Runner injects the running task's
537
+ * authenticated {@link TaskSpec.principal} as this header (e.g. `"X-Agent-Principal"`) on every call to
538
+ * this server's tools, so the MCP server can enforce per-user RBAC. Absent {@link TaskSpec.principal}
539
+ * ⇒ the header is **not** sent (the MCP server must default to deny/public, never admin). Overrides any
540
+ * same-named static `headers` entry. The principal is Runner-held and the model/worker can neither read
541
+ * nor set it (it is not a tool argument) — see {@link TaskSpec.principal}.
542
+ */
543
+ principalHeader?: string;
544
+ };
545
+ /** Optional allowlist of tool names to expose (others are dropped). */
546
+ allowTools?: string[];
547
+ /**
548
+ * design/99 §E23 — opt in to INBOUND elicitation for THIS server: when `true` AND a {@link RunnerDeps.onElicit}
549
+ * seam is wired, core advertises the `elicitation` capability to this server and registers a handler, so the
550
+ * server may send an `elicitation/create` request to ask the END USER for input mid-tool-call. **Default OFF
551
+ * (fail-closed)**: never advertise unless explicitly wired, so a hostile/over-eager server cannot pull a human
552
+ * into the loop. v1 is LIVE-ONLY — `onElicit` answers synchronously on the open connection (no durable
553
+ * suspend; a durable/cross-replica elicitation needs the deferred E22 longer-lived connection).
554
+ */
555
+ elicitation?: boolean;
556
+ /**
557
+ * Caller-side per-tool safety-axis overrides, keyed by the server's REMOTE (un-namespaced) tool name. The
558
+ * CALLER is the trust root: unlike a server's self-declared annotations (which may only TIGHTEN), a caller
559
+ * override is AUTHORITATIVE and may LOWER an effect (vouch a tool is `read`/`idempotent`) as well as raise it
560
+ * (`egress` / irreversible). This is the ONLY trusted way to drop an MCP tool below the fail-closed `write`
561
+ * default (design F). Folds over the server hints in prepare-task (caller > server hint > fail-closed write).
562
+ */
563
+ toolAxes?: Record<string, {
564
+ effect?: ToolEffect;
565
+ egress?: boolean;
566
+ irreversibility?: "always" | "never";
567
+ }>;
568
+ }
569
+ /**
570
+ * design/99 §E23 — an INBOUND MCP elicitation request (a connected server asking the END USER for input
571
+ * mid-tool-call). Handed to the deployment's {@link RunnerDeps.onElicit} seam. **UNTRUSTED**: `message` /
572
+ * `requestedSchema` / `url` are SERVER-controlled — core never interprets `requestedSchema`; a consumer that
573
+ * shows `message` to a human MUST fence it (`delimitUntrusted`).
574
+ */
575
+ export interface McpElicitRequest {
576
+ /** The {@link McpServerSpec.name} of the server that issued the request. */
577
+ server: string;
578
+ /** The server's human-facing prompt (UNTRUSTED — fence before display). */
579
+ message: string;
580
+ /** Form mode: the server's requested input schema (a flat object of scalars). OPAQUE to core. */
581
+ requestedSchema?: unknown;
582
+ /**
583
+ * URL mode: a server-controlled URL the user is asked to visit (UNTRUSTED — a phishing/social-engineering
584
+ * surface; a consumer MUST scrutinize/fence it before showing it). **Inactive in v1**: core advertises
585
+ * FORM mode only, so the SDK rejects url-mode requests before this seam — this field is reserved for a
586
+ * future url-mode opt-in and is never populated today.
587
+ */
588
+ url?: string;
589
+ /** The running task's authenticated end-user (design/62), if any — for routing the prompt to the right human. */
590
+ principal?: string;
591
+ }
592
+ /** design/99 §E23 — the deployment's answer to an {@link McpElicitRequest} (returned to the MCP server). */
593
+ export interface McpElicitResponse {
594
+ action: "accept" | "decline" | "cancel";
595
+ /** Submitted values (accept only); core passes them through opaquely, never validated against the schema. */
596
+ content?: Record<string, string | number | boolean | string[]>;
597
+ }
598
+ /**
599
+ * design/99 §E23 — the LIVE-ONLY inbound-elicitation seam. A deployment provides it (e.g. the sema shell
600
+ * prompts the user at the terminal) and returns the answer SYNCHRONOUSLY; core replies to the server on the
601
+ * still-open connection. Absent ⇒ no server is advertised the elicitation capability (fail-closed). Not a
602
+ * durable suspend — a crash/replica-change loses an in-flight elicitation (acceptable for an interactive shell).
603
+ *
604
+ * 🔴 THROTTLING IS THE DEPLOYMENT'S JOB: once a server is opted in, it may issue elicitations at any frequency
605
+ * (one per tool call, or many) — core imposes NO rate/count limit (an elicitation is not a tool call and does
606
+ * not ride the policy gate). `onElicit` is the choke point: throttle, aggregate, or `decline`/`cancel` an
607
+ * over-eager or hostile server here (the request's `AbortSignal` is forwarded so a deadline can cancel it).
608
+ */
609
+ export type OnElicit = (req: McpElicitRequest, signal?: AbortSignal) => Promise<McpElicitResponse>;
610
+ /**
611
+ * A per-skill runtime capability manifest (design/77 §3 Gate-3). When present, loading the skill
612
+ * SCOPES the rest of the invocation to ONLY these tools/paths via runtime deny-narrowing: a tool call
613
+ * not in `allowTools` (intersected across nested skill frames) is DENIED, and a write whose canonical
614
+ * target falls outside `allowPaths` is DENIED — regardless of how permissive the task policy is.
615
+ *
616
+ * 🔴 **Safe-by-construction:** a manifest can only SUBTRACT capability. The narrowing composes via the
617
+ * `deny > ask > allow` fold (`combinePolicies`) where `deny` short-circuits, so a manifest can never
618
+ * *grant* a tool the task policy withheld — an attacker who sets a manifest can only restrict further.
619
+ * Worst case (the model never pops the frame) = no narrowing, never widening — still ⊆ task policy.
620
+ *
621
+ * The manifest is CALLER-provided here (same trust level as the rest of `SkillSpec`); deriving it
622
+ * automatically (the auto-promote pipeline) is a separate, deferred concern (design/77 §5).
623
+ */
624
+ export interface SkillManifest {
625
+ /** The ONLY tool names the invocation may call while this skill's frame is active. */
626
+ allowTools: string[];
627
+ /**
628
+ * Optional path allowlist for WRITE tools (`write_file`/`edit_file`): a write whose canonicalized
629
+ * target is not inside one of these (path-segment-aware) prefixes is DENIED. Omit = no path narrowing
630
+ * (only `allowTools` applies). Reads are never path-narrowed (this gate restricts capability, not visibility).
631
+ *
632
+ * 🔴 **Fail-closed (MAJOR-2):** `allowPaths` can only confine tools whose write target is a parseable `path`
633
+ * argument (`write_file`/`edit_file`). While an `allowPaths` constraint is active, any OTHER mutating
634
+ * (effect:write/idempotent) allowlisted tool — notably `bash`, whose command can write anywhere — is DENIED
635
+ * outright, because its target cannot be path-confined. So a manifest that lists `bash` together with
636
+ * `allowPaths` does NOT let bash write/egress anywhere: bash is denied while the path constraint is active.
637
+ * Confine writes to specific paths via `write_file`/`edit_file` only.
638
+ */
639
+ allowPaths?: string[];
640
+ /** Reserved (design/77 §3): whether egress is permitted under this manifest. Carried through; v1 does
641
+ * not act on it beyond the allowTools intersection (egress tools must also be in `allowTools`). */
642
+ egress?: boolean;
643
+ /** Stable lineage id of the artifact this manifest came from — used in deny reasons + as the scope key. */
644
+ lineageId: string;
645
+ }
646
+ /** A skill made available to this task (passed as an object; not loaded from disk). */
647
+ export interface SkillSpec {
648
+ name: string;
649
+ description: string;
650
+ content: string;
651
+ /** Optional Gate-3 runtime capability manifest (design/77 §3) — see {@link SkillManifest}. */
652
+ manifest?: SkillManifest;
653
+ }
654
+ /** An image attached to the task's user message: either inline base64 or a URL to fetch. */
655
+ export type ImageInput = {
656
+ /** Base64-encoded image bytes (no data: prefix). */
657
+ data: string;
658
+ /** MIME type, e.g. "image/png" / "image/jpeg". */
659
+ mimeType: string;
660
+ } | {
661
+ /** URL the runner will fetch and inline as base64 before sending to the model. */
662
+ url: string;
663
+ };
664
+ /** A single self-contained task with its full configuration. */
665
+ export interface TaskSpec {
666
+ taskId?: string;
667
+ /** The instruction / latest user message for this turn. */
668
+ objective: string;
669
+ /**
670
+ * Authenticated **end-user principal** this task runs on behalf of (design/62) — an opaque identity string
671
+ * (user id, email, tenant-scoped subject) the **trusted caller** sets at task creation. The Runner holds it
672
+ * for the whole run and injects it into MCP requests for any server with a `principalHeader`
673
+ * ({@link McpServerSpec}), enabling per-user RBAC in the MCP server. Delegated child tasks (sub-agent / team /
674
+ * fan-out) inherit it.
675
+ *
676
+ * 🔴 **Trust contract (design/53 — authority stays in the control plane):** this is a control-plane value,
677
+ * **NOT model/worker input.** Set it only from the authenticated task-submission context; it is not exposed
678
+ * as a tool argument and the model cannot read or change it (a worker filling its own principal = a privilege
679
+ * bypass). Treat it as write-once for the run. The MCP server MUST trust this header only on the Runner's
680
+ * authenticated/TLS channel and default to deny/public when it is absent — never default-admin.
681
+ *
682
+ * 🔴🔴 **This is the GOVERNANCE key.** Per-principal entitlements are resolved off this value:
683
+ * {@link RunnerDeps.runtimeCapsResolver}`(spec.principal)` decides `allowWorkflows` (and thus whether
684
+ * self-orchestration / `RunWorkflow` is permitted). So a caller MUST set `spec.principal` to a
685
+ * **cryptographically VERIFIED** identity — **never a raw, spoofable request header**. A deployment that holds
686
+ * both an unverified header value AND a verified one (e.g. a "direct-door" path) MUST pass the VERIFIED one
687
+ * here: keying a gate on a spoofable principal is a multi-tenant governance BYPASS (a forged header would
688
+ * inherit another tenant's entitlements). Core cannot verify identity itself (no crypto context) — it trusts
689
+ * this value by contract; getting it wrong is a privilege-escalation hole, not a core bug.
690
+ */
691
+ principal?: string;
692
+ /** Optional images attached to this turn's user message (model must support vision). */
693
+ images?: ImageInput[];
694
+ /** Reuse an existing in-memory session for chat continuity; omit to start fresh. */
695
+ sessionId?: string;
696
+ /**
697
+ * design/114 Phase3 — with `sessionId` set, REQUIRE that session to already exist: if it is gone (e.g. a
698
+ * non-durable store lost it across a restart, or a typo'd id), the run FAILS LOUD (`resume.session_not_found`)
699
+ * instead of silently creating a fresh empty session and running with NO warm context. Use this for a
700
+ * reuse-style warm-resume (`runTask({sessionId, requireExistingSession: true})`) so "looks warm, actually
701
+ * fresh" can never happen. (The `fork`-first path via `warmResume` is already fail-loud without this flag.)
702
+ * Ignored when `sessionId` is absent. Default `false` = today's create-on-miss behavior.
703
+ */
704
+ requireExistingSession?: boolean;
705
+ /**
706
+ * design/112 C1/C5 — CLIENT-supplied USER facts (distinct from execution-env/container facts). In TOB the
707
+ * worker container runs UTC and has no idea who the user is or where they are; the client/REPL/gateway knows.
708
+ * It threads these so the `# Environment` block localizes "today" to the user's zone (else it annotates UTC)
709
+ * and names who the agent acts for. All optional; absent ⇒ current behavior (UTC date, no user line). This is
710
+ * the USER half of the env block — the WORKSPACE half (cwd/git/platform/shell) is probed THROUGH the
711
+ * ExecutionEnv (the container), never from here.
712
+ */
713
+ clientContext?: {
714
+ /** IANA time zone of the user (e.g. `Asia/Tokyo`) — localizes the env block's date. Invalid zones fall back
715
+ * to UTC (date AND annotation) rather than mislabeling — see `isValidTimeZone`. */
716
+ timeZone?: string;
717
+ /** The user's identity (e.g. email) — surfaced in the env block so the agent knows who it acts for. */
718
+ userEmail?: string;
719
+ };
720
+ /**
721
+ * design/99 §E18 (resume-at) — BRANCH the session at this prior entry BEFORE the turn: replay root→here,
722
+ * then run the new `objective` as the next turn (the shell's "rewind to this message, ask differently").
723
+ * Requires `sessionId`. **The id is a core `SessionTreeEntry.id`** — a persisted session-entry id — **NOT a
724
+ * live {@link TaskEventIdentity.eventId}** (eventIds are never persisted; a deployment that holds eventIds
725
+ * owns the eventId→entryId map). Must reference a `message`/`custom_message` entry, and NOT an assistant
726
+ * message that ends mid-tool-call (a SETTLED turn boundary — else the replay would orphan-close a done call).
727
+ * Non-destructive: recorded as a branch `leaf` entry, so prior leaves stay in the tree (re-resume any time).
728
+ * Mutually exclusive with a durable `runner.resume(...)` (the Runner rejects both at once).
729
+ */
730
+ resumeAt?: string;
731
+ /**
732
+ * Which model to run on. If omitted, resolved from the `modelRole` (default `"default"`) against
733
+ * `roles` / `RunnerDeps.roles`. Either `model` or a resolvable role must be available.
734
+ */
735
+ model?: ModelRef;
736
+ /** Which role to resolve when `model` is omitted. Default `"default"`. */
737
+ modelRole?: ModelRole;
738
+ /** Per-task/scenario role→model overrides (merged over `RunnerDeps.roles`, task wins). */
739
+ roles?: ModelRoles;
740
+ /** Optional cheaper model for compaction/summarization. Falls back to the `summarize` role if set. */
741
+ compactionModel?: ModelRef;
742
+ /** Thinking level. If omitted, a default from the resolved role's `RoleSpec.thinking` applies. */
743
+ thinking?: ThinkingLevel;
744
+ /** Preset system prompt for this task. */
745
+ systemPrompt?: string;
746
+ /**
747
+ * APPEND a caller block to the assembled system prompt, keeping the engine's base + harness/safety blocks
748
+ * (unlike `systemPrompt`, which REPLACES the base, and `promptProvider`, which rewrites the whole assembly).
749
+ * The lightweight user/scenario-extension seam (≈ CC `--append-system-prompt`): add task-specific rules,
750
+ * domain context, or a persona tweak without losing the neutral base, cyber/url safety, harness context, or
751
+ * memory discipline. CALLER-TRUSTED (same trust level as `systemPrompt`/`skills` — NOT user input). Composed
752
+ * as a STABLE block (prepare-time) at the END of the stable prefix, before the volatile `<user_memory>` tail,
753
+ * so it never breaks prefix-cache friendliness. Composes WITH `systemPrompt` (appended after it).
754
+ */
755
+ appendSystemPrompt?: string;
756
+ /**
757
+ * Per-task ROLE-LAYER prompt provider (overrides `RunnerDeps.promptProvider`). Lets one Runner serve
758
+ * different scenarios with different role prompts. 提示词主权批: `stableSystem` supplies the role base
759
+ * only — core appends the constitution (harness/safety/mode/memory blocks) structurally, so a provider
760
+ * cannot drop it by accident; `replaceAll: true` is the explicit full-replacement escape hatch.
761
+ * TRUST BOUNDARY: a provider is function-valued and therefore CODE — it can only be set by in-process
762
+ * deployment code, never by a wire-level (JSON) task submission; untrusted self-orchestration specs
763
+ * additionally have this field stripped by workflow governance. The `prompt.assembled` trace records
764
+ * which mode ran, so a `replaceAll` is always observable.
765
+ */
766
+ promptProvider?: import("../prompts/default.js").PromptProvider;
767
+ /**
768
+ * Enable long-term memory for this task. **design/138 S4 (BREAKING): requires `RunnerDeps.memoryBackend`**
769
+ * (the injection-first memory engine — materialize → file ops → harvest). With a backend configured the
770
+ * task gets the CC-verbatim `# Memory` instruction + fenced derived index and works memory through its
771
+ * ordinary file tools. WITHOUT a backend this field is INERT: the legacy `RunnerDeps.memoryStore` fallback
772
+ * (remember/recall tools + legacy `<user_memory>` injection) was retired — the task runs memory-less and
773
+ * one deprecation warning is emitted via `onError` (phase `"config"`).
774
+ *
775
+ * **design/84 Seam A** — single opaque scope → an **ordered, opaque scope list + a single writeScope**.
776
+ * The engine only does read-side **layered injection** (one `<user_memory>` block, a `<scope …>` subsection
777
+ * per scope, ordered by priority — the LAST scope is highest-priority and lands at the prompt TAIL) and
778
+ * write-side **single-point routing** (remember/consolidation only ever write `writeScope`; the model never
779
+ * picks a layer). Scope strings stay OPAQUE — the client/profile derives them (TOC: managed/user/project/
780
+ * agent/local; TOB: tenant hierarchy). All three fields are normalized to one canonical shape
781
+ * ({@link import("./memory.js").normalizeMemorySpec}) — `scope` → `[scope]`, `writeScope` defaults to the
782
+ * LAST scope — so the consumer side reads one array with zero narrowing.
783
+ *
784
+ * Cache discipline (§5, implemented in prepare-task): the scopes are injected in list order, so the
785
+ * caller places STABLE layers (managed/user/org — rarely change) FIRST (cacheable prefix) and VOLATILE
786
+ * layers (project/agent/local) LAST (only the tail re-computes). The stable prefix is byte-stable.
787
+ *
788
+ * Backward compatible: a plain `{ scope: "user:42" }` is unchanged (normalizes to `scopes:["user:42"]`,
789
+ * `writeScope:"user:42"`).
790
+ *
791
+ * The accepted shape is {@link import("./memory.js").MemorySpecInput} (the SAME type
792
+ * {@link import("./memory.js").normalizeMemorySpec} consumes) — DESIGN-2 (council): typed by import rather
793
+ * than re-declared inline so the input contract and its normalizer can never silently diverge. Per-field
794
+ * semantics: `scope` = single opaque LEGACY scope (`scopes` wins when both present); `scopes` = ordered
795
+ * opaque layering (STABLE first / VOLATILE last; last = highest priority); `writeScope` = the single layer
796
+ * all writes land in (default = last scope; explicit `null` = read-only — no `remember` tool, consolidation
797
+ * off); `enabled` = master switch (default true).
798
+ */
799
+ memory?: import("./memory.js").MemorySpecInput;
800
+ /**
801
+ * @deprecated design/138 S4 — legacy memory consolidation (design/41) rode the retired memoryStore
802
+ * path and no longer runs; this field is ignored. (The engine plane's consolidation re-mount is a
803
+ * separate design — see design/138 §7.) Type kept one major; removal is the next major.
804
+ */
805
+ memoryConsolidation?: MemoryConsolidationConfig;
806
+ /**
807
+ * design/100 §E12 — after the task COMPLETES, run ONE extra opt-in LLM pass to propose "next prompts" the
808
+ * user might send (the shell's follow-up suggestions). OFF/omitted = zero extra LLM calls, behavior unchanged.
809
+ * Fire-and-forget (never blocks the result); the suggestions are surfaced via {@link TaskStream.suggestions}
810
+ * and the (budget-excluded) cost via {@link TaskStats.suggestions}. `count` default 3, `role` default
811
+ * `"summarize"` (a cheap tier → falls back to the task model). The output is UNTRUSTED model text for the
812
+ * shell UI ONLY — never re-feed it to a model.
813
+ */
814
+ suggestNextPrompts?: boolean | {
815
+ count?: number;
816
+ role?: ModelRole;
817
+ };
818
+ /**
819
+ * design/101 §E19 — opt-in working-tree **rewind**: when this task uses {@link resumeAt} to branch at a prior
820
+ * message AND a snapshot was captured for that message, RESTORE the files to how they were at that message
821
+ * (pairs with E18: branch the session + restore the tree). Also makes every COMPLETED turn capture a
822
+ * snapshot keyed by its leaf `SessionTreeEntry.id`. Requires `RunnerDeps.fileSnapshotStore`. **v1 is
823
+ * LOCAL-only** — a remote ({@link RunnerDeps.executionEnvFactory}) env defers rewind to its own VM-snapshot
824
+ * backend behind the same seam. OFF/omitted = zero snapshot/restore work.
825
+ */
826
+ rewindFiles?: boolean;
827
+ /**
828
+ * design/101 §E19 + R8 (CC Rewind `code`-only mode) — restore the working tree to the snapshot captured at
829
+ * this prior message entryId WITHOUT forking the conversation (no {@link resumeAt} leaf-branch). This is CC's
830
+ * "Restore code" mode (vs "Restore code and conversation" = {@link resumeAt}+{@link rewindFiles}, and "Restore
831
+ * conversation" = {@link resumeAt} alone). Honored ONLY when {@link resumeAt} is ABSENT (with `resumeAt` set,
832
+ * that branch's own `rewindFiles` governs — they are different operations); a no-snapshot target is an
833
+ * expected no-op (same as `rewindFiles`). Requires `RunnerDeps.fileSnapshotStore`. The session leaf is
834
+ * untouched — the next turn continues the CURRENT conversation, only the files moved.
835
+ */
836
+ rewindFilesTo?: string;
837
+ /** Native tools available to this task. */
838
+ tools?: ToolSpec[];
839
+ /** Gate tool calls before they run (allow/deny/approval). Overrides `RunnerDeps.toolPolicy`. */
840
+ toolPolicy?: import("./tool-policy.js").ToolPolicy;
841
+ /** How `ask` decisions resolve for this task (headless auto-deny by default). Overrides `RunnerDeps.onAsk`. */
842
+ onAsk?: import("./tool-policy.js").OnAsk;
843
+ /** Content-ask seam (design/64 §5): routes an AskUserQuestion tool call to a real human/UI. When set, the
844
+ * AskUserQuestion tool is mounted. Overrides `RunnerDeps.onQuestion`. Distinct from `onAsk` (permission). */
845
+ onQuestion?: import("./ask-question.js").OnQuestion;
846
+ /** LSP code-intelligence seam (design/64 §13.1): when set, the `lsp` tool is mounted and routed to this
847
+ * manager. Overrides `RunnerDeps.lspManager`. Unset ⇒ no `lsp` tool (the model uses grep/read_file). */
848
+ lspManager?: import("./lsp.js").LspServerManager;
849
+ /**
850
+ * design/121 (CC 198 parity): after the agent edits a file, NEW language-server diagnostics are
851
+ * injected into the model (`<new-diagnostics>` context message, 10/file · 30 total · 4000-char cap)
852
+ * and emitted as a structured `diagnostics` event for the shell. **Default ON** whenever the
853
+ * preconditions hold — an LSP manager with a diagnostics registry is wired AND the roster has
854
+ * write-capable fs tools (CC's same gate); zero cost/behavior change otherwise. `false` opts out.
855
+ */
856
+ lspDiagnostics?: boolean;
857
+ /** In-process hooks (PreToolUse/PostToolUse/UserPromptSubmit) for this task. Overrides `RunnerDeps.hooks`. */
858
+ hooks?: import("./hooks.js").Hooks;
859
+ /**
860
+ * design/45 **durable suspend-on-approval** (F4). When set AND a `CheckpointStore` is wired
861
+ * (`checkpointStore` here or on `RunnerDeps`), a tool-policy `ask` is **persisted as a checkpoint** and
862
+ * the task ends `status:"suspended"` + `checkpointToken` instead of resolving synchronously through
863
+ * `onAsk` — resume later with `runner.resume(token, outcome)`. This is the cross-process / long /
864
+ * headless version of the `onAsk` gate. **opt-in, default-off**: unset → the 1.63 synchronous `onAsk`
865
+ * path (unchanged). Only safe at the top-level `runTask` (orchestrators fail-fast, §11 Q6).
866
+ */
867
+ durableApproval?: {
868
+ /** Multi-tenant isolation key, forced into the checkpoint + `resolve`/`reap` WHERE. Required. */
869
+ scope: string;
870
+ /** Optional awaiting-human TTL (ms). Past it a reaper CAS-expires the checkpoint (≈ deny). */
871
+ ttlMs?: number;
872
+ };
873
+ /**
874
+ * design/74: opt into resource-slice suspend. When a resource limit (maxTurns / budget / walltime) is hit
875
+ * AND the task is eligible (a `checkpointStore` + a remote, suspendable `executionEnvFactory` env), suspend
876
+ * as a resumable `resource_limit` checkpoint instead of failing (clay's "失败≠没做完" third state) — resume
877
+ * continues the run with the next slice's allowance. `scope` is the multi-tenant isolation key (like
878
+ * `durableApproval.scope`). Absent ⇒ a limit hit still FAILS (backward compatible). Independent of
879
+ * `durableApproval` (a run can have one, both, or neither).
880
+ */
881
+ resourceSuspend?: {
882
+ /** Multi-tenant isolation key, forced into the checkpoint + `resolve`/`reap` WHERE. Required. */
883
+ scope: string;
884
+ /**
885
+ * design/74 Slice 4: the task's TOTAL $ budget (USD) across the whole resume→re-suspend chain — the
886
+ * human's allocation, distinct from `maxCostUsd` (the per-SLICE window). Each slice may spend
887
+ * `min(maxCostUsd, total − alreadySpent)`; the ledger (carried on the checkpoint) accumulates spend so a
888
+ * resume can't refresh the budget. `undefined` ⇒ no $ ceiling on the whole task (each slice is bounded
889
+ * only by its own `maxCostUsd` / walltime). Set ONLY on the FIRST slice; later slices read the frozen
890
+ * total from the ledger. (Walltime has a sibling `totalWalltimeSec` on the ledger; not yet enforced.)
891
+ */
892
+ totalBudgetUsd?: number;
893
+ /**
894
+ * design/74 (search [136] HIGH-1): max resource SLICES (resume legs) before the run fails with
895
+ * `"suspend.loop"`. The resource-slice analogue of `maxSuspends`, but counted on the ledger's
896
+ * `sliceCount` and INDEPENDENT of the restart-loop `maxSuspends`: a legitimate long resource run must
897
+ * not be capped by the (low) restart-loop safety, and restart-loop suspends must not consume the slice
898
+ * allowance (the bug: both shared one `suspendCount` + `maxSuspends`). The cross-slice $ budget
899
+ * (`totalBudgetUsd`) is the PRIMARY bound; this is a backstop against a $0-progress slice loop. Default
900
+ * `DEFAULT_MAX_SLICES` (100, the design/74 spec's worker-suspend ceiling). The leader sizes it to budget/slice.
901
+ */
902
+ maxSlices?: number;
903
+ /**
904
+ * design/74 (search [136] HIGH-2): retention TTL (ms) stamped onto the resource checkpoint's `deadline`
905
+ * so the durable reaper can GC an orphaned (never-resumed) resource suspend. WITHOUT it the checkpoint
906
+ * has no `deadline`, both reapers filter on `deadline`, and the `pending` row (+ in-memory pin) leaks
907
+ * forever. Default `DEFAULT_RESOURCE_TTL_MS` (30 days, the spec `RESOURCE_SUSPEND_TTL_SEC`). A legitimate
908
+ * resume happens long before this; the deadline only reaps abandonment.
909
+ */
910
+ ttlMs?: number;
911
+ };
912
+ /**
913
+ * design/80 Seam #2 (external preempt/yield): the SCHEDULER raises this `AbortSignal` to PREEMPT this task —
914
+ * a graceful, RESUMABLE durable yield (free resources for a higher-priority task), NOT an abort (abort kills
915
+ * the run and loses its state). When raised, the task durably suspends at the next CLEAN turn boundary as a
916
+ * `resource_limit` checkpoint with reason `"preempt"` (the SAME mechanism as a budget/turns/walltime resource
917
+ * suspend — only the trigger differs), and is resumed later via `runner.resume(token, {gate:"resource_limit",
918
+ * decision:"continue"}, …)` exactly like any resource-limit resume (continue the work, no decision).
919
+ *
920
+ * **Eligibility (v1 reuses the resource-suspend opt-in):** preempt only fires when the task is eligible for
921
+ * durable suspend — i.e. it opted into {@link resourceSuspend} AND a durable `checkpointStore` is wired AND
922
+ * tool-results are durable AND the per-task env is a remote (suspendable) `RemoteExecutionEnv`. This is
923
+ * correct: a non-durable task cannot be preempted-AND-resumed anyway. If `preemptSignal` is raised on a task
924
+ * that is NOT resource-suspend-eligible, preempt is a SILENT NO-OP (the run continues normally to its natural
925
+ * end) — decoupling preempt's own opt-in from `resourceSuspend` is a future enhancement, not built here.
926
+ *
927
+ * **Re-supply on resume:** like `resourceSuspend`/`durableApproval`, this is part of the resume task config —
928
+ * a long task that is resumed may need re-preemption, so supply a FRESH `preemptSignal` (a new
929
+ * `AbortController.signal`) in the resume `taskConfig` to make the resumed leg preempt-able again.
930
+ */
931
+ preemptSignal?: AbortSignal;
932
+ /**
933
+ * design/131 (service [404] 拍) — per-task resilience overrides, INTENT-ONLY (no decorator
934
+ * topology on the spec; the deployment's brain stack stays the single owner). For bench/eval or
935
+ * critical tasks that need the provider's TRUE failure shape instead of a silent fallback:
936
+ * - `allowDegrade:false` — reactive model degrade is off for this task (failure passes through).
937
+ * - `allowFailover:false` — cross-gateway failover is off (only the primary brain is tried).
938
+ * - `bypassBreaker:true` — an open circuit breaker's fast-fail is waived for THIS task; outcomes
939
+ * are still recorded (shared observation undiminished). Operator-facing — deployments SHOULD
940
+ * NOT expose this to wire users directly (it defeats provider protection).
941
+ * All absent ⇒ exactly today's behavior. Threaded per-call as `StreamOptions.resilience`; the
942
+ * first-party degrading/failover/breaker decorators honor it, custom brains may ignore it.
943
+ */
944
+ resilience?: ResilienceOptions;
945
+ /**
946
+ * design/132 — final-verification gate (OPT-IN: `true` enables). When a task is about to end
947
+ * NATURALLY (inside budget) and this run made at least one non-`read` tool call, the engine
948
+ * injects a reminder to re-verify the final deliverable through its REAL entry point
949
+ * (execute it directly; don't trust earlier self-tests or shell redirections) before finishing.
950
+ * Oracle-grounding upgrade (docs/DESIGN-ORACLE-GROUNDING-GATE-2026-07-10.md §3.A): if the run's
951
+ * tool-call record carried a deterministic verifiable-structure signal (raw-byte read /
952
+ * structural parse / digest-reconciliation word-faces in shell commands — never a semantic scan
953
+ * of closing text) and the model ends AGAIN without headroom concerns, ONE grounding re-entry
954
+ * reminder is injected; total injections are hard-capped at 2, then the run always ends. A
955
+ * submitted structured output and the maxTurns-1 boundary always pass through un-gated.
956
+ * Evidence: TB full-run autopsy — the biggest shell-gap bucket (7-8 tasks) finished convinced by
957
+ * their own fake self-check; prompt discipline alone (1.242) had a low landing rate. Opt-in
958
+ * because the evidence is from AUTONOMOUS legs — turn it on for autonomous/benchmark scenarios
959
+ * (sema-tb defaults it ON); interactive deployments choose per scenario. Read-only / Q&A runs
960
+ * never trigger it. Telemetry: `stats.mechanisms.finalVerifyInjected`.
961
+ */
962
+ finalVerification?: boolean;
963
+ /**
964
+ * design/72 §2.2 (B): max times this task may durably suspend before the run fails with
965
+ * `"suspend.loop"` instead of minting another checkpoint. Caps a resume/restart loop (a model that
966
+ * re-issues the gated/egress call every resume, re-suspending forever). Counted across resume chains.
967
+ * Default 5 (loose — a real human-approval flow re-suspends rarely, so 5 separates a normal resume from a
968
+ * pathological loop; a deployment that genuinely needs more sets this). Overrides `RunnerDeps.maxSuspends`.
969
+ */
970
+ maxSuspends?: number;
971
+ /** Per-task {@link import("./checkpoint-store.js").CheckpointStore} for durable suspend/resume
972
+ * (design/45). Overrides `RunnerDeps.checkpointStore`. Needed (with `durableApproval`) to suspend. */
973
+ checkpointStore?: import("./checkpoint-store.js").CheckpointStore;
974
+ /**
975
+ * Restrict the injected "hand" band (design/44) to its effect:read tools for this task — read_file /
976
+ * grep / glob (+ `bash_readonly` when a shell is available); edit_file / write_file / `bash` are not
977
+ * mounted. This is the verifier read-only boundary (§6): an adversarial verifier inspects but must not
978
+ * modify the project. No effect unless an `executionEnv` is injected. Default false.
979
+ */
980
+ handsReadOnly?: boolean;
981
+ /**
982
+ * design/119 (CC --add-dir parity): extra directories the FILE tools may access in addition to the
983
+ * containment root — each is canonicalized into the containment allowlist and listed in the
984
+ * `# Environment` block so the model knows they're available. Same defense-in-depth caveat as the
985
+ * root: this bounds the file tools, not `bash` (OS-level containment is the env's job).
986
+ */
987
+ additionalDirectories?: string[];
988
+ /**
989
+ * design/80 D-B — opt in to PLAN MODE: mount the first-party `present_plan` tool (CC `ExitPlanMode` parity).
990
+ * The model calls it to present a plan; the engine then pauses with a durable `plan_review` checkpoint
991
+ * (`status:"needs_review"`) so a human approves/edits/rejects before any action. Typically paired with
992
+ * `handsReadOnly:true` (research read-only until the plan is approved, then the resume drops it). Default
993
+ * false — when unset the tool is NOT mounted, NOT disclosed, and a `ToolReturn.requestReview` is ignored, so
994
+ * a non-plan-mode task is byte-identical. Needs a `checkpointStore` wired to actually pause (else a
995
+ * `requestReview` is a no-op). The tool is a thin composition over the general `requestReview` primitive.
996
+ */
997
+ enablePlanMode?: boolean;
998
+ /**
999
+ * design/110 / design/136 §2.1.a (⚠️ BREAKING semantics change) — the per-task FORK governance gate for
1000
+ * `Agent(subagent_type:"fork")` (the standalone `Fork` tool was retired; the capability lives in the Agent
1001
+ * tool's `subagent_type` value domain — CC-exact shape). The fork spawns a child that INHERITS this
1002
+ * conversation's full context (vs the clean-context delegation) and shares the prompt-cache prefix.
1003
+ *
1004
+ * OPT-OUT default (flipped from the pre-136 opt-IN): `undefined`/`true` = fork is AVAILABLE, bounded by the
1005
+ * session capability (`hasSessionFork` durable store + a session id + not inside a fork — honest refusal
1006
+ * otherwise); an EXPLICIT `false` = fork is DENIED for this task with the honest `fork.disabled` result
1007
+ * (never a silent downgrade). Multi-tenant deployments that previously relied on `undefined` being OFF must
1008
+ * now send `enableFork: false` explicitly (or deny per-principal via `RuntimeCaps.allowFork`).
1009
+ */
1010
+ enableFork?: boolean;
1011
+ /**
1012
+ * design/80 D-2 (part-1): gate the injected `bash` hand tool, since a full shell can run egress (`curl`,
1013
+ * `git push`) and irreversible (`rm`) commands that the per-tool egress/irreversibility marks otherwise miss.
1014
+ * The §4-OQ4 doctrine: shell-in-presence ⇒ always-gate UNLESS a real parsed classifier is wired.
1015
+ * - `"off"` (default): `bash` is unmarked — the current behavior (subject only to the deployment's policy).
1016
+ * - `"always"`: every `bash` command tightens to an `irreversible_ask` durable suspend (fail-closed; the
1017
+ * correct default for an unattended/supervisor deployment with no classifier).
1018
+ * - `"classify"`: mark `bash` `irreversibility:"maybe"` with {@link import("../tools/fs/index.js").bashReversibilityProbe}
1019
+ * — a provably-benign single allowlisted read-only command (no operators) auto-allows; everything else
1020
+ * (writes, egress, pipes, unknown commands) tightens to ask. An egress command (e.g. `curl`) suspends under
1021
+ * the IRREVERSIBLE axis (the shell mark is irreversibility, not egress) — the kind is non-budgetable either
1022
+ * way, so the budget resolver still never auto-approves it; the axis label is informational.
1023
+ * No effect under `handsReadOnly` (that mounts `bash_readonly`, already allowlisted) or with no execution env.
1024
+ * **Re-supply on resume:** like `toolPolicy`/`tools`/`durableApproval`, `shellGate` is part of the resume
1025
+ * task config — a resume that omits it leaves the resumed run's SUBSEQUENT `bash` calls ungated (the approved
1026
+ * pending call itself runs once, having been adjudicated). Re-pass the same value the original task used.
1027
+ */
1028
+ shellGate?: "off" | "always" | "classify";
1029
+ /** Task-scoped MCP servers, materialized into tools then disposed. */
1030
+ mcp?: McpServerSpec[];
1031
+ /**
1032
+ * Task-scoped skills (object form). Two first-party halves (design/71 黑盒#5 fix): a stable
1033
+ * `<skills>` system-prompt block disclosing name+description (deterministic order, capped), and an
1034
+ * injected `skill` tool (effect:read) that returns the skill's full content as a tool result
1035
+ * (per-skill body cap with an honest truncation marker). Duplicate names: first wins. The name
1036
+ * `skill` becomes reserved when this field is non-empty (`config.reserved_tool_name`).
1037
+ *
1038
+ * Skill content is CALLER-trusted — same trust level as `systemPrompt`. Callers forwarding
1039
+ * end-user-authored skills are responsible for vetting them: a skill IS instructions by design.
1040
+ */
1041
+ skills?: SkillSpec[];
1042
+ /**
1043
+ * design/129 — lifetime scope for BACKGROUND children (Agent/Fork `run_in_background`). Default `"task"`:
1044
+ * the parent runTask's terminal reaps them (design/115 — no orphans burning tokens; [431] turn-end killed
1045
+ * frame). `"session"`: children OUTLIVE the turn (CC Backgrounded semantics) — registered under the
1046
+ * SESSION owner (cross-turn TaskOutput poll works), skipped by the parent-teardown reap, force-capped by
1047
+ * a default child timeout when none is given, and finally reapable via
1048
+ * `TaskRegistry.reapSessionBackground(sessionId, scope)` (call it from your session release/sweep).
1049
+ * CALLER-trusted (systemPrompt tier): never a model-facing parameter, never on the governed workflow
1050
+ * whitelist — a child's lifetime crossing the turn boundary is an isolation-contract surface.
1051
+ */
1052
+ backgroundScope?: "task" | "session";
1053
+ /**
1054
+ * 黑板 [435]/[442] A1 — structured SANDBOX facts for the `# Environment` block, so the agent knows what
1055
+ * toolchains the environment already carries (no blind reinstall), which package source installs go
1056
+ * through, and whether the network is reachable at all (egress=none ⇒ don't burn budget on downloads).
1057
+ * DEPLOYMENT-trusted (systemPrompt tier — the deployment knows its own sandbox binding): rendered
1058
+ * sanitized+bounded by prepare-task; never a model-facing parameter, never on the governed workflow
1059
+ * whitelist. All fields optional; absent ⇒ block unchanged.
1060
+ */
1061
+ envFacts?: {
1062
+ /** The bound sandbox image profile (e.g. `dev-mobile`). */
1063
+ profile?: string;
1064
+ /** Toolchains/capabilities the image carries (e.g. `android-sdk`, `gradle`). Rendered bounded. */
1065
+ capabilities?: readonly string[];
1066
+ /** Which package-source lane installs go through (e.g. `cn` | `global` | `custom`). */
1067
+ pkgSource?: string;
1068
+ /** Outbound-network posture. `none` renders an explicit "downloads will fail" caveat. */
1069
+ egress?: "none" | "allowlist" | "full";
1070
+ /** Session-specific scratch directory for temporary files (CC Scratchpad parity, 1.257.3): when set,
1071
+ * the environment block instructs the model to use this dir instead of `/tmp` — prevents parallel
1072
+ * tasks trampling each other's temp files and project-dir pollution. Unset ⇒ no section rendered. */
1073
+ scratchpadDir?: string;
1074
+ };
1075
+ limits?: {
1076
+ maxTurns?: number;
1077
+ timeoutSec?: number;
1078
+ /**
1079
+ * design/119 #2: per-REQUEST output-token cap (the provider `max_tokens` / `max_completion_tokens`
1080
+ * field). Distinct from `maxTokens` (the cumulative BUDGET cap): this bounds each model reply.
1081
+ * Unset ⇒ prior behavior (Anthropic: model.maxTokens; OpenAI family: provider default). A reply
1082
+ * that hits it stops with `length` and the loop's truncated-output auto-continue takes over.
1083
+ * HARD bound on Anthropic budget-thinking models too: a cap too small to host a legal thinking
1084
+ * budget (< 2048) skips thinking for the request rather than silently raising the cap.
1085
+ */
1086
+ maxOutputTokens?: number;
1087
+ /**
1088
+ * design/128 T1-2 — deadline awareness for `timeoutSec` (default ON). At each turn boundary the run
1089
+ * loop checks elapsed wall-clock against the budget and injects at most TWO one-shot
1090
+ * `<system-reminder>` nudges (at ~80%: "start converging"; at ~95% or budget−2min, whichever is
1091
+ * earlier: "deliver NOW") so the model converges BEFORE the hard abort instead of losing unfinished
1092
+ * work to it. `false` disables; `{at:[a,b]}` overrides the two ratios (0<a<b<1). No effect without
1093
+ * `timeoutSec`. Resource-suspend-eligible tasks never nudge (their timeoutSec is a SLICE boundary —
1094
+ * the clean suspend already is the convergence). Cost: at most two tail transcript reminders; the
1095
+ * stable system prefix (and thus the prompt cache) is untouched. Known limit: the check runs only at
1096
+ * turn boundaries — a single very long turn can sail past a threshold and see the nudge one boundary
1097
+ * late.
1098
+ */
1099
+ deadlineNudge?: false | {
1100
+ at?: [number, number];
1101
+ };
1102
+ /**
1103
+ * design/130 P1 — wall-clock-aware per-CALL output cap (default ON when `timeoutSec` is set).
1104
+ * Before each model call the runner shrinks the request's `max_tokens` to what the remaining
1105
+ * wall-clock can actually absorb (`remainingSec × measured-throughput × 0.5 safety`, EWMA from
1106
+ * this run's completed calls; a conservative prior before the first sample), clamped to
1107
+ * [1024, `maxOutputTokens` ?? model default]. SHRINK-ONLY: never raises the static ceiling.
1108
+ * Thinking contract (codex ①): a cap that lands in [1024, 2047] is raised to 2048 iff the
1109
+ * remaining budget can absorb it WITHOUT the safety margin; otherwise the cap stands and an
1110
+ * Anthropic budget-thinking call skips thinking for that request (design/119 semantics) — the
1111
+ * `brain.call` trace carries `callCap`/`capThinkingSkipped` either way. `false` disables.
1112
+ * Resource-suspend-eligible tasks never shrink (their timeoutSec is a SLICE boundary; a
1113
+ * per-slice opt-in is deferred). No effect without `timeoutSec`.
1114
+ */
1115
+ callCapByDeadline?: false;
1116
+ /**
1117
+ * design/130 P2 — graceful-finalize turn (default ON when `timeoutSec` is set). At a turn
1118
+ * boundary where the remaining wall-clock no longer fits one more full model-call + tool cycle
1119
+ * (EWMA of this run's call latencies + tool durations, ×1.25 headroom), the runner injects a
1120
+ * ONE-SHOT finalize instruction — "write your best current answer to the deliverable path NOW,
1121
+ * open no new work" — and suppresses any still-pending deadline nudges (one deadline-class
1122
+ * message per boundary, finalize wins — codex ②). The turn after finalize still runs under the
1123
+ * P1 cap with its floor raised to 2048 so the write-out isn't starved. `false` disables.
1124
+ * Resource-suspend-eligible tasks never finalize (clean slice suspend outranks it — codex ⑤).
1125
+ * v1 is instruction-only: the finalize turn's tool face is NOT narrowed (deferred; needs a
1126
+ * mid-run setTools surgery whose cache cost outweighs v1 value).
1127
+ *
1128
+ * design/130 P2b — deadline EXECUTION hardening (rides this same switch; the family is one
1129
+ * discipline). With finalize on, the runner additionally reserves a fixed write-out CUSHION
1130
+ * (15% of the budget, clamped to [10s, 75s]) and enforces a soft execution deadline
1131
+ * (`deadline − cushion`; the finalize turn itself gets `deadline − 5s`):
1132
+ * - the finalize boundary condition becomes `remaining < est + cushion` (the last work cycle
1133
+ * can no longer eat the write-out window), with a TAIL-AWARE est (decayed peak ∨ EWMA);
1134
+ * - first-party brains CUT a model call whose stream crosses the soft deadline (prefix
1135
+ * salvaged, one bounded write-out turn follows; exhausted ⇒ `timeout` + salvagedOutput);
1136
+ * - foreground shell timeouts are CLAMPED to the soft deadline (a long command times out
1137
+ * cleanly instead of riding into the hard abort).
1138
+ * `stats.mechanisms.callCutoffs`/`toolClamps` count the engagements. `false` disables all of it.
1139
+ */
1140
+ gracefulFinalize?: false;
1141
+ };
1142
+ /**
1143
+ * Blackboard 2026-07-03 (subagent viewing pane, clay dogfood): widen the opt-in display sink
1144
+ * (`RunInternals.onForwardEvent`) from `task_progress`-only to a SUBAGENT's live CONTENT events
1145
+ * (`text_delta` / `reasoning_delta` / `tool_start` / `tool_end`), so a UI can render a delegated
1146
+ * child's transcript live. Default OFF (progress-only, prior behavior). The child stream is still
1147
+ * NEVER merged into the parent's model context — this is purely a render channel; forwarded events
1148
+ * carry `parentToolCallId` (attribution) and the same UNTRUSTED-RAW contract as the main stream's
1149
+ * `tool_start.args`/`tool_end.output` (consumer MUST redact — design/99 §E1). Single-level: each
1150
+ * delegation level opts in for ITS direct children.
1151
+ */
1152
+ forwardSubagentEvents?: boolean;
1153
+ /**
1154
+ * design/122 D1 — RETAIN sync sub-agent sessions after they settle so an operator can RESUME (revive) a
1155
+ * finished child with a new prompt via {@link import("../agents/subagent.js").SubagentSteerHandle}'s
1156
+ * `resume` verb (CC `dfe` resumeAgentBackground parity). Default OFF = prior behavior byte-for-byte:
1157
+ * child sessions are throwaway (released eagerly after the delegation returns).
1158
+ *
1159
+ * ON (`true` or a config object): each SYNC delegation spawned while the deployment's
1160
+ * `RunInternals.onSubagentSpawn` sink is wired (the handle-emitting path — without a handle there is no
1161
+ * resume capability, so retaining would be a pure leak) pre-mints the child's sessionId, PINS it against
1162
+ * the store's idle sweep, and SKIPS the eager release. The session is retained in a parent-run-scoped
1163
+ * ledger until `ttlMs` after settle (default 30 min), eviction past `max` retained children (default 16),
1164
+ * or the PARENT run reaching a terminal state — whichever comes first; then it is unpinned + explicitly
1165
+ * released (throwaway semantics restored — a retained session never dangles to the store's 7-day TTL).
1166
+ * `run_in_background` children are OUT OF SCOPE (no handle, no retain — r1-M3; the bg lane's resume needs
1167
+ * durable support and is a separate item). Resume is reachable only while the parent run lives (the
1168
+ * ledger is run-scoped, not a durable registry — codex-B3).
1169
+ */
1170
+ retainSubagentSessions?: boolean | {
1171
+ ttlMs?: number;
1172
+ max?: number;
1173
+ };
1174
+ /**
1175
+ * design/120 P2: opt in to in-stream tool execution — safe tool calls start while the model is
1176
+ * still streaming its response instead of waiting for the full reply. Default OFF. Forwarded to
1177
+ * the harness, which additionally withholds it whenever a `tool_call` gate handler is registered
1178
+ * (policy / approval / egress runs — a gate could durably suspend, which is impossible
1179
+ * mid-stream), so setting this on a gated task is safe and simply has no effect. A run whose only
1180
+ * gate concern is resource-suspend does NOT register that handler (it stops at clean turn
1181
+ * boundaries), so in-stream execution stays available there.
1182
+ *
1183
+ * Known limitation (documented): with this ON, a tool's side effect can complete BEFORE the
1184
+ * assistant message persists; a hard process crash in that window leaves no transcript trace of
1185
+ * the call (wake reconcile cannot see an orphan that was never written). Prefer OFF for
1186
+ * deployments where crash-exactly-once accounting of tool effects matters more than latency.
1187
+ */
1188
+ streamingToolExecution?: boolean;
1189
+ /**
1190
+ * Hard cost ceiling in USD for this task (requires `model.cost` or `RunnerDeps.pricing`). Checked
1191
+ * pre-call and at each turn boundary; exceeding ends the task `failed` with `errorCode="budget.precall"`
1192
+ * (estimate rejected, nothing spent) or `"budget.exceeded"` (after spend). When set, `budgetStreamCancel`
1193
+ * defaults to `true`.
1194
+ *
1195
+ * NOTE: the pre-call check is **best-effort** — it estimates the first call's input from the objective
1196
+ * length only (it cannot see the assembled system prompt / history / memory), so it may under-estimate
1197
+ * and let an oversized first turn run; the turn-boundary gate then catches it as `budget.exceeded`.
1198
+ * Treat `budget.precall` as a fast-fail optimization, not a hard guarantee that no single call exceeds.
1199
+ */
1200
+ maxCostUsd?: number;
1201
+ /** Hard cap on cumulative prompt+completion tokens; exceeding ends `failed` + `"budget.exceeded"`. */
1202
+ maxTokens?: number;
1203
+ /** Cancel an in-flight stream the moment cumulative cost crosses `maxCostUsd`. Defaults to `true`
1204
+ * when `maxCostUsd` is set (hard control), `false` otherwise. */
1205
+ budgetStreamCancel?: boolean;
1206
+ /**
1207
+ * **Near-budget degradation** (1.39 v2, design/21 §5C). When cumulative cost reaches `atCostFraction`
1208
+ * of `maxCostUsd`, **switch the active model to the cheaper `to`** for the rest of the task to stretch
1209
+ * the remaining budget — accepting lower quality instead of stopping at `maxCostUsd`. One-way (never
1210
+ * switches back); sets `TaskResult.degraded = { …, reason: "budget" }`. Requires `maxCostUsd` (the
1211
+ * fraction is of it); ignored otherwise. This is the proactive, Runner-level complement to the
1212
+ * reactive brain-level `createDegradingBrain` (rate_limit / breaker-open).
1213
+ */
1214
+ degrade?: {
1215
+ to: ModelRef;
1216
+ atCostFraction: number;
1217
+ };
1218
+ /**
1219
+ * **Structured output** (1.41): constrain the task's FINAL result to this JSON schema (a typebox
1220
+ * object schema). Injects a built-in `submit_output` tool whose parameters ARE this schema; the model
1221
+ * calls it to finish, the validated object is surfaced as `TaskResult.structuredOutput`, and the task
1222
+ * ends. Provider-agnostic (it's just a tool). If the model can't produce a valid object within a few
1223
+ * tries the task fails with `errorCode="output.invalid"`. A caller tool named `submit_output` is
1224
+ * rejected (reserved). The model may still answer in prose (then `structuredOutput` is undefined) or
1225
+ * `report_blocked`. Cast the result with `Static<typeof yourSchema>`.
1226
+ */
1227
+ outputSchema?: TSchema;
1228
+ /**
1229
+ * How many times the model may **retry** a rejected `submit_output` before the task fails with
1230
+ * `errorCode="output.invalid"` (only meaningful when {@link outputSchema} is set). `0` = fail on the
1231
+ * first invalid submit (no in-loop retry); the caller decides whether to re-run. Default `2`
1232
+ * (3 total attempts). Clamped to a non-negative integer. This bounds only the *in-task* retry of a
1233
+ * malformed object — it is not an auto-fixer; pair it with a caller-side retry on `output.invalid`.
1234
+ */
1235
+ outputRetries?: number;
1236
+ /** Best-effort fire-and-forget trace sink (task/turn/brain/tool). Overrides `RunnerDeps.tracer`. */
1237
+ tracer?: import("./trace.js").TracerHook;
1238
+ /** Per-task override of the large-tool-result offload threshold (chars); see `RunnerDeps.toolResultThresholdChars`. */
1239
+ toolResultThresholdChars?: number;
1240
+ /**
1241
+ * Override auto-compaction thresholds for this task's session. Compaction (LLM summary, persisted
1242
+ * to the session) runs in two places sharing these settings: at every within-task turn boundary
1243
+ * (design/64 §25 (A) — the long-single-task case) and once at task end (the between-task case).
1244
+ * Defaults: enabled, reserveTokens 16384, keepRecentTokens 20000 — repaired automatically when
1245
+ * pathological for the model's window: threshold ≤ 0, keepRecent ≥ threshold, or a threshold above
1246
+ * the clearStale point (0.7×window — the prefix-cache "death band", design/64 §26.4) is clamped
1247
+ * down to it. The clamp applies to explicit values too (the clearStale point is not configurable,
1248
+ * so a threshold above it cannot express consistent intent); explicit values below all three
1249
+ * bounds are never overridden (see `sanitizeCompactionSettings`).
1250
+ * `instructions` is appended to the summarization prompt — use it to guarantee critical
1251
+ * facts survive (e.g. "preserve verbatim any codes, IDs, names, and explicit user instructions").
1252
+ * Scope caveat (design/141 examples 批实测): `instructions` rides the WHOLE-TURN summarization
1253
+ * request only; a split-turn cut point (mid-turn prefix summarization) uses the engine-owned
1254
+ * turn-prefix prompt and does not carry it (same A2 boundary as `RunnerDeps.summaryProvider`).
1255
+ * `withinTask: false` keeps end-of-task compaction but disables the within-task (turn-boundary)
1256
+ * trigger — the escape hatch for the §25 (A) control-flow change; the system prompt then stops
1257
+ * claiming mid-task summarization (§6.3 honesty).
1258
+ * `attachWorkingFiles` (LONGRUN-2; **default ON since 2026-07-03** — CC 198 hard-codes its
1259
+ * post-compact file restore, and LONGRUN-2 measured ≈2.3 extra read round-trips per compaction
1260
+ * without it): after each compaction, re-read the task's most recently READ files (CC
1261
+ * readFileState semantics; falls back to modified-by-recency when read tracking is absent) and
1262
+ * append their current contents to the summary (bounded: `maxFiles` default 3,
1263
+ * `maxCharsPerFile` default 16k chars ≈ 4k tokens, plus a total cap that self-scales to ~15% of
1264
+ * the model window). The `compacted` wire event carries the attached list as `attachedFiles`
1265
+ * (shell renders CC's post-compact Read cards). `false` opts out; an object customizes caps;
1266
+ * no-op when the task has no execution env (no hands, nothing to re-read).
1267
+ */
1268
+ compaction?: {
1269
+ enabled?: boolean;
1270
+ withinTask?: boolean;
1271
+ reserveTokens?: number;
1272
+ keepRecentTokens?: number;
1273
+ instructions?: string;
1274
+ attachWorkingFiles?: boolean | {
1275
+ maxFiles?: number;
1276
+ maxCharsPerFile?: number;
1277
+ };
1278
+ };
1279
+ /**
1280
+ * design/133 §R3 — turn-boundary attachment producers (CC `getContextAttachments` parity), ALL
1281
+ * OPT-IN. Same default-face judgment as design/132 `finalVerification` (B2/H2): the evidence for
1282
+ * these reminders comes from AUTONOMOUS long-task legs (weak-model drift safety net — CC's own
1283
+ * trigger counts proved unreproducible: the observed CC runs never mounted TodoWrite), so the
1284
+ * autonomy entrypoints (sema-tb) turn them on and interactive deployments stay byte-identical
1285
+ * until a behavior leg proves them neutral. At most ONE coalesced `<system-reminder>` steer per
1286
+ * clean turn boundary, lowest lane: finalize/deadline-nudge/diagnostics at the same boundary — and
1287
+ * the design/130 P2 / design/132 end-game latches — all suppress it.
1288
+ *
1289
+ * - `todoReminder`: CC 10/10 cadence — when TodoWrite (or the task tools; both mounted ⇒ the
1290
+ * task family wins, CC isTodoV2) hasn't been used for 10 assistant turns, re-surface the list
1291
+ * (thin projection; an all-completed list is cleared, never regurgitated). No tools mounted ⇒
1292
+ * permanently silent.
1293
+ * - `changedFiles`: boundary-time stat of ≤20 (or `maxFiles`) most-recently-READ files; a file
1294
+ * whose mtime moved past the recorded read time (+2s epsilon) is listed (path-only v1, "do not
1295
+ * blindly revert — re-read"). OFF ⇒ zero stat calls. Self-edits are immune (write-back
1296
+ * refreshes the read stamp); mtime skew on exotic fs remains a documented false-positive source.
1297
+ * - `planModeReminder`: while `enter_plan_mode` is active, re-surface the read-only constraint
1298
+ * every 5 assistant turns (full copy every 5th, sparse between) so a long plan phase doesn't
1299
+ * drift into write-deny thrash. Exiting plan mode stops it.
1300
+ * - `backgroundTasks` (G1 通告层, 黑板 [482] — CC /compact parity): after a compaction LANDS, the
1301
+ * next boundary announces this run's still pending/running background tasks (task registry
1302
+ * snapshot: id/description/status, CC three-state copy). ONE-SHOT per compaction — never
1303
+ * per-boundary nagging; no compaction ⇒ permanently silent.
1304
+ * - `toolsDelta` (G1 — CC deferred-tools boundary notice): when design/36 `tool_search`
1305
+ * materializes deferred tools mid-task (setTools + fingerprint refresh), the next boundary
1306
+ * announces the NEWLY available names once. Already-active and resume-reseeded tools are never
1307
+ * (re)announced; no deferred tools ⇒ permanently silent.
1308
+ * - `agentListing` (G1 续批 — CC `agent_listing_delta` parity): when a delegation tool built by
1309
+ * `createSubagentTool` is mounted, the FIRST collected boundary announces the full agent-type
1310
+ * roster ("Available agent types for the Agent tool:", CC-verbatim; + the concurrency note when
1311
+ * more than one type). Later boundaries announce only roster drift (adds/removals — static in
1312
+ * practice; the delta lane serves dynamic-registration deployments). A durable resume leg is
1313
+ * seeded as already-announced (the prior leg's listing is in the transcript — never replayed).
1314
+ * - `mcpInstructions` (G1 续批 — CC `mcp_instructions_delta` parity): the INITIAL server
1315
+ * instructions stay in the stable system prompt (`# MCP Server Instructions`, design/64 §17.3 —
1316
+ * deliberate CC deviation: CC injects them as reminders, sema's stable-prompt carrier is
1317
+ * prefix-cache-correct). This member announces only DELTAS: a mid-task disconnect of an
1318
+ * instruction-bearing server ("The following MCP servers have disconnected…", CC-verbatim), and
1319
+ * the add lane for a future dynamic-connect face. Added instruction text is UNTRUSTED server
1320
+ * text → fenced with `delimitUntrusted` (deliberate CC deviation: CC injects it raw).
1321
+ *
1322
+ * Telemetry: `steering_injected` (source `todo_reminder`/`task_reminder`/`changed_files`/
1323
+ * `plan_mode`/`background_tasks`/`tools_delta`/`agent_listing`/`mcp_instructions`) +
1324
+ * `stats.mechanisms.attachmentsInjected`.
1325
+ */
1326
+ attachments?: {
1327
+ todoReminder?: true;
1328
+ /**
1329
+ * task #51 口径③ — CC `r2o()` kill-switch parity (CC 198 pretty.js:479167-479171; both reminder
1330
+ * producers consume it as `if (r2o() === "off") return []`, :480232/:480268). `"off"` silences the
1331
+ * todo/task reminder lane even when `todoReminder` is wired on (the other attachment producers are
1332
+ * untouched — CC's nudge gate is lane-scoped); any other value (or absence) = CC `"baseline"`.
1333
+ * CC resolves this from env `CLAUDE_CODE_TODO_REMINDER_MODE` / the `tengu_soft_slate_nudge` gate;
1334
+ * sema keeps env resolution at the deployment shell (sema-tb: `TB_TODOREMIND=off`) — core reads no env.
1335
+ */
1336
+ todoReminderMode?: "baseline" | "off";
1337
+ changedFiles?: true | {
1338
+ maxFiles?: number;
1339
+ };
1340
+ planModeReminder?: true;
1341
+ /**
1342
+ * SR-3 (CC 198 `budget_usd` lane, producer QFm pretty.js:480424-480428 + renderer :600225): the
1343
+ * progressive $-budget readout `USD budget: $used/$total; $remaining remaining` (CC-verbatim
1344
+ * template). CC-exact activation: live ONLY while the task carries an effective cost ceiling
1345
+ * (`maxCostUsd`, or a resource-slice ledger remaining — CC `options.maxBudgetUsd`); no ceiling ⇒
1346
+ * permanently silent even when opted in. CC-exact cadence: NO threshold ladder and NO throttle —
1347
+ * CC mounts it on every main-agent attachment cycle (:479243-479245, gated `d = !t.agentId`), so
1348
+ * sema emits one line at every collected clean turn boundary; the "progression" is the numbers
1349
+ * advancing with spend. Recorded deviation (continuation gate): CC attaches at request assembly
1350
+ * and can never EXTEND a run, while a sema boundary steer revives an idle harness — so this lane
1351
+ * only rides boundaries whose turn resolved ≥1 tool call (a next request is already guaranteed);
1352
+ * a text-only final turn is never dragged past its natural end. Numbers ride the enforcement
1353
+ * coordinate (`stats.costMicroUsd` vs the effective ceiling, ÷1e6 → USD) so the readout never
1354
+ * disagrees with `budget.exceeded`.
1355
+ * NOTE: this deliberately relaxes the design/74 "no budget language reaches the model" default —
1356
+ * that judgment shaped the DEFAULT-OFF posture; an opted-in deployment chooses CC parity.
1357
+ */
1358
+ budgetUsd?: true;
1359
+ backgroundTasks?: true;
1360
+ toolsDelta?: true;
1361
+ agentListing?: true;
1362
+ mcpInstructions?: true;
1363
+ };
1364
+ /**
1365
+ * Inject a built-in `report_blocked` tool the agent can call when it cannot finish
1366
+ * (missing info, permission, ambiguity). When called, the task ends with status "blocked".
1367
+ * Default: true.
1368
+ */
1369
+ enableBlockedReport?: boolean;
1370
+ /**
1371
+ * **LLM self-orchestration** (design/98, S8). Allow THIS task's model to AUTHOR + RUN its own workflow
1372
+ * (a deterministic JS orchestration script) via the `run_workflow` tool. Default `false`.
1373
+ *
1374
+ * 🔴 REQUIRES a deployment-provided HARD sandbox AND a governance baseline:
1375
+ * `RunnerDeps.workflowScriptRunner.safeForUntrustedScripts === true` (an isolated-vm / separate-process
1376
+ * runner — the Node `vm` dev runner is NOT a security boundary) AND `RunnerDeps.workflowGovernanceBaseline`
1377
+ * (the deployment-trusted governance every spawned sub-agent inherits, tighten-only). With EITHER missing
1378
+ * the tool is NOT mounted and the orchestration prompt is NOT injected (FAIL-CLOSED) — core never runs an
1379
+ * LLM-authored script in the dev `vm`, and never lets a script-spawned agent run with no governed baseline.
1380
+ *
1381
+ * Recommended ONLY for strong models; weak models default-off (force-enableable, but the hard-sandbox +
1382
+ * baseline bar still applies — the gate is the deployment's sandbox/governance, NOT the model id). NOT
1383
+ * enforced by model id.
1384
+ */
1385
+ selfOrchestration?: boolean;
1386
+ /** Per-model auth. Returns the api key (and optional headers) for a given provider/model. */
1387
+ getApiKeyAndHeaders?: (model: Model) => Promise<{
1388
+ apiKey: string;
1389
+ headers?: Record<string, string>;
1390
+ } | undefined>;
1391
+ /**
1392
+ * External cancellation. When it aborts, the task aborts (the brain request is cancelled and any
1393
+ * pending tool-policy gate releases). Pass a parent tool's `ToolExecuteContext.signal` here so a
1394
+ * nested `runTask` stops the instant the parent does instead of running to its own `timeoutSec`.
1395
+ */
1396
+ signal?: AbortSignal;
1397
+ }
1398
+ /**
1399
+ * `"suspended"` (design/45) is a **non-terminal** outcome: the task hit a durable tool-policy gate
1400
+ * (`ask` with a `CheckpointStore` wired) and persisted a checkpoint instead of finishing — resume it
1401
+ * with `runner.resume(checkpointToken, outcome)`. v1 contract: it is only safe at the **top-level
1402
+ * `runTask` boundary**; the orchestrators (cascade/teacher/verify/team) map an unexpected `suspended`
1403
+ * to `failed` + `errorCode:"unexpected.suspended"` and pass the token up (§11 Q6, hard boundary).
1404
+ *
1405
+ * `"needs_review"` (design/76 §2.5, dry-run / shadow; design/80 D-B, plan-gate) is also a **non-terminal,
1406
+ * resumable** outcome, but a DISTINCT one: it is the REVIEW-PAUSE terminal a human/judge must clear. Two
1407
+ * disjoint gate kinds share it (carrying a `reviewRef`, errorCode `"review.pending"`): a `{kind:"needs_review"}`
1408
+ * checkpoint — a profile's dry-run interception produced a predicted state-diff to REVIEW before it is applied,
1409
+ * resumed with a `dry_run_review` outcome — and a `{kind:"plan_review"}` checkpoint (design/80 D-B) — a
1410
+ * profile's plan-gate produced a proposed PLAN a human must approve/edit/reject BEFORE any step runs, resumed
1411
+ * with a `plan_review` outcome. Both are DISJOINT from `"suspended"`: that is a PRE-ACTION approval of a TOOL
1412
+ * CALL (resumed with `policy_ask`); these are human REVIEWS (the distinct gate.kind picks the resume outcome).
1413
+ * Orchestrators that map an unexpected `suspended` should map an unexpected `needs_review` the same
1414
+ * hard-boundary way (it is, like `suspended`, only safe at the top-level `runTask` boundary).
1415
+ */
1416
+ export type TaskStatus = "completed" | "blocked" | "failed" | "timeout" | "suspended" | "needs_review";
1417
+ /** Result returned when a task finishes or gets stuck. Designed to be machine-readable for an external AI. */
1418
+ export interface TaskResult {
1419
+ taskId: string;
1420
+ /** Use this to continue the same conversation on the next call. */
1421
+ sessionId: string;
1422
+ status: TaskStatus;
1423
+ /** design/99 MF-25: the EFFECTIVE model id that served this task — the RESOLVED `Model.id`, not the requested
1424
+ * `TaskSpec.model` ref (which may be a role / name / `@mention`). Lets a UI echo "served by X" instead of the
1425
+ * requested ref. A mid-run degradation is observed separately (see the degraded-model fields). */
1426
+ model?: string;
1427
+ /** Final assistant text. */
1428
+ result: string;
1429
+ /**
1430
+ * Best-effort salvaged assistant text from a terminal FAILURE (design/39). Lets a caller recover work
1431
+ * a task produced before it failed at the very end, instead of discarding a `failed` result wholesale:
1432
+ * `const out = r.status === "completed" ? r.result : r.salvagedOutput;`. Its interpretation depends on
1433
+ * `errorCode` — for `"output.degenerate"` it is the model's text up to (and currently including) the
1434
+ * looped tail. **v1 fills it only on degenerate repetition**; a follow-up generalizes it to
1435
+ * timeout/max_turns and trims the degenerate tail. Undefined when there was nothing to salvage.
1436
+ */
1437
+ salvagedOutput?: string;
1438
+ /** Set when status is "blocked": why the agent could not finish. */
1439
+ blockedReason?: string;
1440
+ /**
1441
+ * Set when `status === "suspended"` (design/45) OR `status === "needs_review"` (design/76 §2.5 dry-run /
1442
+ * design/80 D-B plan-gate): the durable-checkpoint token to resume this task with via
1443
+ * `runner.resume(checkpointToken, outcome)` (a `policy_ask` outcome for `suspended`; for `needs_review`, a
1444
+ * `dry_run_review` outcome on a `needs_review` gate or a `plan_review` outcome on a `plan_review` gate —
1445
+ * read `checkpointGate.kind` to pick). Also passed up by an
1446
+ * orchestrator that mapped an unexpected `suspended` to `failed` (errorCode `"unexpected.suspended"`) so the
1447
+ * top-level caller can still resume. Branded `CheckpointToken`; **never log it or put it in a URL** (it is
1448
+ * the resume capability, §6). Undefined for every other status.
1449
+ */
1450
+ checkpointToken?: import("./checkpoint-store.js").CheckpointToken;
1451
+ /** Set with `checkpointToken`: who/what must resume (e.g. `{kind:"human", reason, toolName}`), so the
1452
+ * caller knows what decision the suspension is awaiting. */
1453
+ checkpointGate?: import("./checkpoint-store.js").CheckpointGate;
1454
+ /** Set when status is "failed"/"timeout". Human-readable. */
1455
+ errorMessage?: string;
1456
+ /**
1457
+ * Machine-readable failure code when the failure carried one — e.g. a `SessionError.code` such as
1458
+ * `"conflict"` (a cross-instance write lost the optimistic lock), or a Node error code. Lets a
1459
+ * caller branch programmatically (e.g. evict a stale cache + retry on `"conflict"`) instead of
1460
+ * matching `errorMessage` strings. Undefined when no code is available.
1461
+ *
1462
+ * 1.37+ terminal codes use a **dotted namespace** so a caller can prefix-match a whole class:
1463
+ * `"budget.precall"` / `"budget.exceeded"` / `"limit.max_turns"` / `"limit.timeout"`
1464
+ * (e.g. `errorCode.startsWith("budget.")`). 1.36 brain codes (`auth`/`network`/`rate_limit`/…)
1465
+ * and `"conflict"` remain flat (unchanged, to avoid breaking existing consumers).
1466
+ */
1467
+ errorCode?: string;
1468
+ /**
1469
+ * Present when the task was served — at least once — by a **degraded** (cheaper/different) model
1470
+ * because the primary was rate-limited, its circuit breaker was open, or — design/126 chain form —
1471
+ * it failed with a `server_error`/`last_resort` class error (1.39 + design/126, opt-in via
1472
+ * `createDegradingBrain`). Lets a caller know the result was produced at reduced quality and alert/
1473
+ * track it. Records the **first** degradation only (degradation is one-way within a task). Set even
1474
+ * when the fallback also failed — so `status:"failed"` + `degraded` means "primary down, fallback
1475
+ * down too". `reason="budget"` is reserved for the v2 near-budget trigger.
1476
+ */
1477
+ degraded?: {
1478
+ from: string;
1479
+ to: string;
1480
+ /** design/126 widens the union: `server_error` (5xx/529 escaped the retry budget) and `last_resort`
1481
+ * (404/other non-retryable statuses) — the CC 批 β fallback-chain triggers. Additive on this
1482
+ * OUTPUT field; consumers switching exhaustively should add the two arms. */
1483
+ reason: "breaker_open" | "rate_limit" | "budget" | "server_error" | "last_resort";
1484
+ /** design/126 — the fallback-chain model ids attempted after the primary, in order (absent on the
1485
+ * single-hop legacy path's pre-126 markers and on the budget path). */
1486
+ chain?: string[];
1487
+ /** 1-based turn during which degradation was triggered. Reactive (rate_limit/breaker): the turn the
1488
+ * cheaper model first served. Budget: the turn whose cumulative cost crossed the threshold (the
1489
+ * switch takes effect from the next turn). */
1490
+ atTurn: number;
1491
+ };
1492
+ /** The validated object the model submitted via `submit_output` when `TaskSpec.outputSchema` was set
1493
+ * (1.41). Undefined if the model answered in prose instead, or the task didn't finish via the output
1494
+ * tool. Cast it with `Static<typeof yourSchema>`. (Exhausting the output-retry cap → `failed` +
1495
+ * `errorCode="output.invalid"`, and this stays undefined.) */
1496
+ structuredOutput?: unknown;
1497
+ /**
1498
+ * `turns`/`tokens`/`costUsd` are this task's OWN model usage. `nested` is the summed usage of any
1499
+ * delegated sub-runs (sub-agents) it spawned — present only when it delegated. The true total
1500
+ * cost is `tokens + (nested?.tokens ?? 0)`; a large `nested` is the multi-agent "~15×" made visible.
1501
+ */
1502
+ stats: {
1503
+ turns: number;
1504
+ tokens: number;
1505
+ /** design/97 CORE-8 (②): total TOOL CALLS executed (one per `tool_start`) — distinct from `turns` (model
1506
+ * rounds; a turn may issue several parallel tool calls). For a CC-style "N tool calls" per-agent row.
1507
+ * **v1 fidelity (audit MINOR)**: counted in THIS run leg via the harness dispatch path, so on a DURABLE
1508
+ * RESUME it under-reports — the resumed gated call (executed by the resume engine, not the harness) and any
1509
+ * cross-slice resource-suspend legs are not folded (turns/tokens/cost ARE folded; toolCalls is per-leg, like
1510
+ * the compaction subtotal). OBSERVE-ONLY (never gates budget). The workflow display is unaffected (its agents
1511
+ * fail-on-suspend, never durably resume). A `spentToolCalls` ledger fold is a follow-on. */
1512
+ toolCalls?: number;
1513
+ /** Total prompt (input) tokens presented across the task's turns, normalized across providers
1514
+ * (Anthropic reports input excluding cache; OpenAI/vLLM include it). The denominator for
1515
+ * `cacheHitRate`. */
1516
+ promptTokens?: number;
1517
+ /** Prompt tokens served from the model's prefix cache (a cache HIT), summed over the task's
1518
+ * turns — when the gateway reports it (vLLM/OpenAI `prompt_tokens_details.cached_tokens`,
1519
+ * DeepSeek `prompt_cache_hit_tokens`, Anthropic `cache_read_input_tokens`). */
1520
+ cachedTokens?: number;
1521
+ /** Prompt tokens written to the cache (Anthropic `cache_creation_input_tokens`); 0 elsewhere. */
1522
+ cacheWriteTokens?: number;
1523
+ /** `cachedTokens / promptTokens` ∈ [0,1] — the prefix-cache hit rate for this task. Cost-critical;
1524
+ * a low value on a multi-turn task means the cacheable prefix is unstable (see `design/09`).
1525
+ * Track it per task and trend it per session. Undefined when the gateway reports no usage. */
1526
+ cacheHitRate?: number;
1527
+ /** Alias of `promptTokens` (the normalized total input incl. cache), named to match OTel
1528
+ * `gen_ai.usage.input_tokens`. Cost is computed from this. (Not a bug fix — `promptTokens` was
1529
+ * already the normalized total; this is the OTel-aligned name. See design/17 §11.5.) */
1530
+ totalInputTokens?: number;
1531
+ /** Completion (output) tokens summed over the task's turns. */
1532
+ outputTokens?: number;
1533
+ /** Cache-write tokens at the 1-hour TTL (Anthropic); 0 unless 1h caching is in use. */
1534
+ cacheWriteTokensLong?: number;
1535
+ /** Authoritative cost in **integer micro-USD** (1e-6 USD), computed in core from injected pricing
1536
+ * — integer to avoid float-accumulation error in billing. Prefer this over the float `costUsd`. */
1537
+ costMicroUsd?: number;
1538
+ /** @deprecated Float USD — accumulation error, and pre-1.37 overstated cache cost. Use
1539
+ * `costMicroUsd`. Kept for back-compat; removed in a later minor. */
1540
+ costUsd?: number;
1541
+ nested?: {
1542
+ tokens: number;
1543
+ turns: number;
1544
+ tasks: number;
1545
+ costUsd?: number;
1546
+ costMicroUsd?: number;
1547
+ };
1548
+ /**
1549
+ * Post-task memory-consolidation usage (design/41), when consolidation ran. Its own line item —
1550
+ * **kept out of `tokens`/`costMicroUsd` and excluded from the budget gate** — so a completed task is
1551
+ * never retroactively flipped to `budget.exceeded` by reconcile cost. `tokens` is 0 when every note
1552
+ * took a cheap (no-LLM) path; `applied` counts store mutations the pass made (cheap-path
1553
+ * UPDATE/DELETE + applied LLM decisions) so callers can observe reconcile efficacy without re-reading
1554
+ * the store. Absent when consolidation was disabled / no-op / produced no notes. Populated
1555
+ * asynchronously (consolidation is fire-and-forget) — see {@link TaskStream.consolidation}.
1556
+ */
1557
+ memory?: {
1558
+ tokens: number;
1559
+ costMicroUsd: number;
1560
+ applied: number;
1561
+ };
1562
+ /**
1563
+ * design/100 §E12 — the prompt-suggestion pass's usage, when it ran. Same budget-excluded side-observable
1564
+ * treatment as {@link memory}: **kept out of `tokens`/`costMicroUsd` and excluded from the budget gate**, so
1565
+ * the (fire-and-forget, post-completion) suggestion pass can never retroactively flip a done task to
1566
+ * `budget.exceeded`. Absent when `suggestNextPrompts` was off / produced nothing. Populated asynchronously —
1567
+ * see {@link TaskStream.suggestions}.
1568
+ */
1569
+ suggestions?: {
1570
+ tokens: number;
1571
+ costMicroUsd: number;
1572
+ };
1573
+ /**
1574
+ * TB telemetry B2 (service [397]): counters for the engine's wall-clock/deadline mechanisms, so a
1575
+ * bench/monitoring consumer can judge from the RESULT whether they actually engaged (refute-130
1576
+ * lesson: "did P1/P2 fire" was unanswerable from artifacts). Present only when at least one
1577
+ * mechanism engaged this leg; absent = none did (byte-compatible).
1578
+ */
1579
+ mechanisms?: {
1580
+ /** design/130 P2: the graceful-finalize instruction was injected this run. */
1581
+ finalizeInjected?: true;
1582
+ /** design/128 T1-2: number of deadline nudges dispatched at turn boundaries. */
1583
+ nudgesSent?: number;
1584
+ /** design/130 P1: number of model calls whose max_tokens was SHRUNK by the wall-clock cap. */
1585
+ capShrinks?: number;
1586
+ /** design/130 P2b: number of model calls the brain CUT at the soft wall-clock deadline
1587
+ * (deliberate stream cancel + prefix salvage — the pre-P2b shape was a mid-call hard kill). */
1588
+ callCutoffs?: number;
1589
+ /** design/130 P2b: number of foreground shell timeouts CLAMPED to the soft tool deadline
1590
+ * (a long command times out cleanly before the write-out window instead of riding past it). */
1591
+ toolClamps?: number;
1592
+ /** design/132: the natural-end final-verification reminder was injected this run. */
1593
+ finalVerifyInjected?: true;
1594
+ /** oracle-grounding gate (opus LOW 复审, additive): HOW MANY final-verification injections
1595
+ * fired this run — 1 = the R9 one-shot only, 2 = R9 + the grounding re-entry (hard cap).
1596
+ * Present iff `finalVerifyInjected` is (the boolean stays for compatibility). */
1597
+ finalVerifyInjections?: number;
1598
+ /** design/133: number of turn-boundary attachments injected this run (todo/task reminders,
1599
+ * changed-files notes, plan-mode re-reminders — each bundled block counts once). */
1600
+ attachmentsInjected?: number;
1601
+ /** Repetition telemetry (clay 2026-07-10, 2e1c161 observability): brain-side degenerate-repetition
1602
+ * stream CUTS this run (each pairs with an `output.degenerate`-classified turn). */
1603
+ repetitionCuts?: number;
1604
+ /** Repetitions that landed in a detection window but were SPARED by a 2e1c161 structural
1605
+ * allowance (code-line shape / divider run) — the raw material for judging the allowance. */
1606
+ repetitionSpared?: number;
1607
+ /** Per-event details (turn + rule + period/reps + a ≤120-char segment sample), capped at 20
1608
+ * entries — `repetitionCuts`/`repetitionSpared` keep the true totals past the cap. */
1609
+ repetitionEvents?: Array<{
1610
+ turn: number;
1611
+ action: "cut" | "spared";
1612
+ rule: "char-run" | "unit-loop";
1613
+ period: number;
1614
+ reps: number;
1615
+ segment: string;
1616
+ }>;
1617
+ };
1618
+ /**
1619
+ * design/91 — **human-review burden** (design/89 §2.4 C2 axis). The wall-clock time a task spent waiting
1620
+ * on a human at an approval gate, plus the count, bucketed by `gate.kind`. Both human-review paths are
1621
+ * captured: the **synchronous** `onAsk`/`resolveAsk` await (`t_return − t_call`) and the **durable**
1622
+ * suspend→resume wait (`resumedAt − checkpoint.suspendedAt`, including the human's offline time); a
1623
+ * multi-leg suspend/resume chain **accumulates across legs**. All timestamps come from {@link RunnerDeps.now}.
1624
+ *
1625
+ * **NOT an LLM cost (load-bearing, design/91 §1):** human-review time is wall-clock latency, not token
1626
+ * spend — it is **NEVER folded into `costMicroUsd`, `costBreakdown`, or the budget gate** (the same
1627
+ * budget-excluded side-observable treatment as {@link memory}). Adding human seconds to token µUSD is the
1628
+ * design/89 §2.1 "apples + oranges" trap; the supervisor Pareto frontier keeps `(token cost, human seconds,
1629
+ * correctness)` as three SEPARATE axes. Absent (`undefined`) when the task hit no approval gate OR no clock
1630
+ * is injectable to measure — byte-compatible with a task that never paused for a human.
1631
+ */
1632
+ humanReview?: {
1633
+ /** Number of human decisions awaited (each synchronous `resolveAsk` return + each durable resume of an
1634
+ * approval suspend). Equals `gates.length`. */
1635
+ count: number;
1636
+ /** Cumulative wall-clock the approval gates were alive (ms), summed across all legs. Equals `Σ gates[].waitMs`. */
1637
+ totalWaitMs: number;
1638
+ /** One entry per human decision, in order. `kind` = the gate's discriminant (`human` /
1639
+ * `irreversible_ask` for durable; `human` for a synchronous ask). `decision` = the adjudication when
1640
+ * known (`allow`/`deny`). design/99 MF-24 (Service AI [297]): `toolName` = the gated tool; `toolArg` = a
1641
+ * SHORT, SECRET-SCRUBBED one-line summary of its input (the same `primaryActivityArg` boundary as the MF-W
1642
+ * activity arg) — the permission-denial ledger's "denied: Bash(rm …)" display. `toolArg` is set on the
1643
+ * SYNCHRONOUS-ask path (the input is in scope); a durable-resume gate carries `toolName` only (its input is
1644
+ * not threaded onto the persisted gate — a documented follow-on). */
1645
+ gates: Array<{
1646
+ kind: string;
1647
+ waitMs: number;
1648
+ decision?: string;
1649
+ toolName?: string;
1650
+ toolArg?: string;
1651
+ }>;
1652
+ };
1653
+ /**
1654
+ * design/80 D-E-core: a thin FINANCE TAXONOMY of the LLM-derived costs the engine actually prices,
1655
+ * decomposing the task's spend into report categories (derived from existing cost sources — no new
1656
+ * persisted structure). **CORE = LLM-token-derived ONLY** — the deployment SERVICE adds the infra axes it
1657
+ * owns (tool-call / sandbox-walltime / egress; it has the k8s cost data) and composes them with this for
1658
+ * the supervisor surface. Each category is ≥ 0 and the LLM parts reconcile to the independently-summed
1659
+ * LLM total: `llmRootMicroUsd + nestedSubagentMicroUsd + compactionMicroUsd === costMicroUsd`
1660
+ * (`memoryConsolidationMicroUsd` is a separate, budget-excluded line — see `memory` — filled
1661
+ * asynchronously after consolidation, so it is NOT part of that identity). Present whenever stats are
1662
+ * assembled.
1663
+ */
1664
+ costBreakdown?: {
1665
+ /** Root-agent LLM cost (micro-USD) = `costMicroUsd − compactionMicroUsd` (the sub-category folded into
1666
+ * it). NOT minus nested — nested cost is never folded into `costMicroUsd` (it lands in `nested`).
1667
+ * ⚠️ APPROXIMATE on a multi-slice `resource_limit` RESUME (design/80 D-E-core, codex review #3): the
1668
+ * durable resource ledger persists only the AGGREGATE prior spend, not its compaction subtotal, so
1669
+ * prior slices' compaction folds in HERE rather than into `compactionMicroUsd`. The TOTAL (`costMicroUsd`)
1670
+ * stays exact; only this llmRoot-vs-compaction split is per-leg-approximate across resource slices. */
1671
+ llmRootMicroUsd: number;
1672
+ /** Delegated sub-agent (nested) LLM cost (micro-USD) = `nested?.costMicroUsd ?? 0`. */
1673
+ nestedSubagentMicroUsd: number;
1674
+ /** Post-task memory-consolidation LLM cost (micro-USD) = `memory?.costMicroUsd ?? 0`; filled
1675
+ * asynchronously after the consolidation pass (0 until then). A separate, budget-excluded line. */
1676
+ memoryConsolidationMicroUsd: number;
1677
+ /** design/100 §E12 — prompt-suggestion pass LLM cost (micro-USD) = `suggestions?.costMicroUsd ?? 0`; filled
1678
+ * asynchronously after the (post-completion) pass (0 until then). A separate, budget-excluded line. */
1679
+ suggestionsMicroUsd?: number;
1680
+ /** Within-task compaction LLM cost (micro-USD) — part of `costMicroUsd`, so subtracted from root.
1681
+ * ⚠️ See {@link llmRootMicroUsd}: under-reports prior slices' compaction on a multi-slice resource resume. */
1682
+ compactionMicroUsd: number;
1683
+ };
1684
+ };
1685
+ }
1686
+ /**
1687
+ * Identity fields carried by every CONTENT event of a task stream (design/99 §E2 — lightweight message
1688
+ * identity, service [241]/[242]). Both are OPTIONAL and ADDITIVE; a consumer that ignores them is unchanged.
1689
+ *
1690
+ * - `eventId` — a core-minted, time-sortable (uuidv7) unique id stamped on each emitted content event. Gives
1691
+ * a live UI a stable handle to correlate/dedup streamed events and to map its own client-side message ids
1692
+ * back to a core anchor. (The durable-anchor mapping for resume-at — which eventIds are restartable
1693
+ * transcript positions — is finalized by the E18 `resumeAt` seam; this field is the stable handle it builds on.)
1694
+ * - `parentToolCallId` — present ONLY when this task runs as a sub-agent spawned under a parent task's tool
1695
+ * call (threaded via the trusted `RunInternals.parentToolCallId`, sourced from the spawning tool's
1696
+ * `ToolExecuteContext.toolCallId`). Lets a consumer attribute streamed content to the delegation subtree it
1697
+ * belongs to WITHOUT core physically merging the child stream into the parent (the child's RESULT still
1698
+ * re-enters the parent MODEL context only through the `delimitUntrusted` fence — observability threading and
1699
+ * model-context isolation are kept separate, so prompt-cache and the injection boundary are untouched).
1700
+ */
1701
+ export interface TaskEventIdentity {
1702
+ eventId?: string;
1703
+ parentToolCallId?: string;
1704
+ /**
1705
+ * design/122 S2 (codex-M4 name: the `WorkflowRun.sourceTaskId` family, NOT a second `taskId` — that
1706
+ * field already exists on `task_progress` and a duplicate would bite consumers) — the ORIGINATING task's
1707
+ * canonical id (`spec.taskId ?? sessionId`), stamped ONLY on the content events of a task running AS A
1708
+ * SUB-AGENT (same condition as {@link parentToolCallId}). A consumer of the C1 forward channel
1709
+ * (`forwardSubagentEvents`) can key a child's content events by the child task directly, without an
1710
+ * alias table. A TOP-LEVEL task's own events carry NO `sourceTaskId` (absent = the consumer's current
1711
+ * task). Additive; a consumer that ignores it is unchanged.
1712
+ */
1713
+ sourceTaskId?: string;
1714
+ }
1715
+ /**
1716
+ * design/99 §E3/§E10 (service [241]/[242]) — a BRAIN-LAYER liveness phase, surfaced so a UI can show why a
1717
+ * turn is stalled (the brain otherwise absorbs these silently in its connect/retry loop). Provider-NEUTRAL:
1718
+ * carries only the graduated phase + a neutral hint, NEVER an HTTP status / provider taxonomy / stop_reason.
1719
+ * A CLOSED union (type-safe) covering the core brain layer; a deployment that surfaces its OWN states
1720
+ * (e.g. E25 token-refresh `authenticating`) does so on its own channel, not by widening this.
1721
+ */
1722
+ export type BrainStatusPhase = "rate_limited" | "retrying" | "reconnecting" | "circuit_open";
1723
+ /** design/99 §E3/§E10 — the payload of a {@link TaskEvent} `status` event (and the brain→runner signal). */
1724
+ export interface BrainStatus {
1725
+ phase: BrainStatusPhase;
1726
+ /** Optional neutral, human-readable hint (NO provider/HTTP detail). */
1727
+ detail?: string;
1728
+ /** Seconds until the brain's next retry attempt (from the honored backoff / `Retry-After`), when known. */
1729
+ retryInSec?: number;
1730
+ }
1731
+ /**
1732
+ * design/97 CORE-8 (③): one lightweight TOOL-ACTIVITY beat surfaced from a running task, for a per-agent live
1733
+ * "last N tool calls" drill-down. A trusted run-scoped sink ({@link RunInternals.onActivity}) receives one at
1734
+ * each tool start + end. Structural (name/phase/ids) + a SHORT redacted primary `arg` for display — NOT the full
1735
+ * ARGS or OUTPUT (those carry untrusted/host data; the workflow layer surfaces redacted prompt/output separately).
1736
+ */
1737
+ export interface ToolActivity {
1738
+ phase: "start" | "end";
1739
+ toolCallId: string;
1740
+ toolName: string;
1741
+ /** design/99 MF-W: a SHORT primary-arg summary for the monitor's `Read(path)` / `Bash(grep …)` display — the
1742
+ * single most salient input ABBREVIATED (command→name, path→basename, url→origin+path) + SECRET-SCRUBBED +
1743
+ * truncated (~80 code points). Set on `phase: "start"`. NOT the full args object, and NOT `redactHostLeaks`
1744
+ * (that over-redacts the path the monitor needs); the abbreviation + scrub is the leak boundary since the value
1745
+ * is persisted + SSE-forwarded (codex-reviewed). See `primaryActivityArg`. */
1746
+ arg?: string;
1747
+ /** Set on `phase: "end"` — whether the tool call errored. */
1748
+ isError?: boolean;
1749
+ }
1750
+ /** Streaming events surfaced from a running task (for live UIs). */
1751
+ export type TaskEvent = ({
1752
+ type: "text_delta";
1753
+ delta: string;
1754
+ } & TaskEventIdentity) | ({
1755
+ type: "reasoning_delta";
1756
+ delta: string;
1757
+ } & TaskEventIdentity) | ({
1758
+ type: "tool_start";
1759
+ toolCallId: string;
1760
+ toolName: string; /** {@link ToolSpec.label} when distinct from `toolName` (design/71 liveness); omitted otherwise. */
1761
+ label?: string;
1762
+ args: unknown;
1763
+ } & TaskEventIdentity) | ({
1764
+ type: "tool_end";
1765
+ toolCallId: string;
1766
+ toolName: string;
1767
+ /** {@link ToolSpec.label} when distinct from `toolName` (design/71 liveness); omitted otherwise. */
1768
+ label?: string;
1769
+ isError: boolean;
1770
+ /**
1771
+ * design/99 §E1 (service [241]/[242]) — the tool's MODEL-FACING result content, surfaced for a live UI
1772
+ * that renders tool output. It is the harness `AgentToolResult.content` the mapper already produced
1773
+ * (previously dropped here); the internal `details` payload is NOT exposed (e.g. a sub-agent tool's
1774
+ * `details` is the entire child `TaskResult`).
1775
+ *
1776
+ * **Type is `unknown` and intentionally non-uniform** — within size it passes through AS-IS to keep
1777
+ * structure a UI wants (a `string`, or `(TextContent|ImageContent)[]` blocks); when the serialized body
1778
+ * exceeds the core size cap it degrades to a single TRUNCATED STRING (see {@link truncated}). A consumer
1779
+ * must handle both shapes.
1780
+ *
1781
+ * **UNTRUSTED RAW + for OBSERVABILITY ONLY**: it is external tool output (file reads, shell stderr, API
1782
+ * bodies) and may carry secrets/paths/PII — core bounds only its SIZE; a consumer MUST redact and MAY
1783
+ * further bound before it persists or displays it (same contract as `tool_start.args`). It is for a live
1784
+ * UI / trace, NOT for re-feeding to a model: a truncated body would mislead an LLM, and the model already
1785
+ * has the full, untruncated result in its own context — build model prompts from the session, never by
1786
+ * replaying this field. Absent when the tool produced no content body.
1787
+ */
1788
+ output?: unknown;
1789
+ /**
1790
+ * design/116 [363] channel (b) — the tool's CC-shaped `toolUseResult` facts (`details.type` ∈ the
1791
+ * known card set: edit/create/update/bash/text/grep/glob/notebook-edit/mcp/multiedit), surfaced on
1792
+ * the live wire so a CC-faithful shell renders rich cards (red/green diff, stdout panes, file cards)
1793
+ * without re-parsing the model-facing string. Absent when the tool carries no CC card shape (a
1794
+ * subagent's child TaskResult is deliberately NOT exposed — the allowlist is the leak boundary) or
1795
+ * when the serialized card exceeds the size bound (omitted whole; a consumer falls back to `output`).
1796
+ * UNTRUSTED RAW like {@link output}: a consumer MUST redact before persisting or forwarding.
1797
+ *
1798
+ * **双面契约(CC 2.1.207 @765495 成文,`tool_use_result` describe;CC207-CORE-SWEEP P2-3)** — a tool
1799
+ * result has TWO faces that never substitute for each other:
1800
+ * - **模型面** = {@link output} / the tool_result text: the string the MODEL reads. It may carry
1801
+ * model-directed framing — e.g. a delegation tool's trailer (agentId / usage lines the model uses to
1802
+ * address SendMessage or budget itself). That framing is FOR THE MODEL; it is not a host data format.
1803
+ * - **宿主面** = this field: the tool's structured Output object, per-tool shaped, keyed by the matching
1804
+ * tool call's name. For a delegation/Agent-family tool the completed shape is the subagent's final
1805
+ * report WITHOUT the model-directed trailer, plus run totals (CC names it `AgentToolCompletedOutput`).
1806
+ * A host/shell MUST render from `structured` and MUST NOT parse the model-facing text back into data
1807
+ * (trailer wording is model-audience prose and may change without notice); symmetrically, core never
1808
+ * strips the trailer from the model face just because the structured face exists — the model still needs
1809
+ * it in-context. When `structured` is absent, the honest fallback is to display `output` as opaque text,
1810
+ * not to scrape it.
1811
+ */
1812
+ structured?: unknown;
1813
+ /**
1814
+ * design/99 §E1 — `true` when {@link output} was SIZE-bounded by core (the full body exceeded the cap and
1815
+ * was degraded to a truncated string). Lets a consumer detect truncation programmatically instead of
1816
+ * parsing the `…[+N chars truncated]` marker out of the string. Absent/false = `output` is the complete
1817
+ * content body. (The full untruncated result still lives in the model's context / `ToolResultStore`.)
1818
+ */
1819
+ truncated?: boolean;
1820
+ } & TaskEventIdentity) | ({
1821
+ type: "turn_end";
1822
+ /**
1823
+ * Per-turn token usage + cost (the turn that just ended), for live per-turn accounting / a trace UI
1824
+ * (service [41]). Re-priced in core from injected pricing (authoritative, like `TaskResult.stats`).
1825
+ * `inputTokens` is the normalized total input incl. cache (matches `stats.promptTokens` / the tracer's
1826
+ * `brain.call.promptTokens`). Absent only if the turn produced no assistant usage.
1827
+ */
1828
+ usage?: {
1829
+ inputTokens: number;
1830
+ outputTokens: number;
1831
+ cacheReadTokens: number;
1832
+ cacheWriteTokens: number;
1833
+ costMicroUsd: number;
1834
+ };
1835
+ /** TB 尸检 T1-5: set when the turn ended WITHOUT a provider usage frame (e.g. a degenerate-repetition
1836
+ * cutoff cancelled the stream before usage arrived). Consumers must treat the missing usage as
1837
+ * UNKNOWN — not zero (the provider still served the request; `stats` under-counts it honestly rather
1838
+ * than polluting the single-source accounting with an estimate). */
1839
+ usageMissing?: true;
1840
+ /** TB telemetry B1 (service [397]): the NORMALIZED finish reason of the turn's LAST model call —
1841
+ * the engine's `AssistantMessage.stopReason` (`StopReason`: `"stop"`/`"length"`/`"toolUse"`/
1842
+ * `"error"`/`"aborted"`). This is post-normalization: e.g. Anthropic `end_turn`/`stop_sequence`
1843
+ * both fold to `"stop"`, `max_tokens`→`"length"`; the raw provider reason is NOT preserved here.
1844
+ * The machine signal for "was this turn cut by max_tokens" (`"length"`) — previously stream+trace
1845
+ * double-blind, which made P1 cap-binding unjudgeable from artifacts. Absent when the turn produced
1846
+ * no assistant message. Typed `string` (not the internal `StopReason`) to keep the engine's union
1847
+ * private, but the value set is exactly those five tokens. */
1848
+ stopReason?: string;
1849
+ } & TaskEventIdentity) | {
1850
+ /** design/99 MF-18: a compaction boundary (or, since design/119 #1, mid-turn when the prompt-too-long recovery force-compacts between a failed request and its retry). `trigger` = what caused it: `"auto"` (the context-threshold
1851
+ * auto-compaction) or `"manual"` (the `TaskStream.compact` / `/compact` path). `tokensBefore` = the
1852
+ * pre-compaction context size. CC parity = `SDKCompactBoundary{trigger, pre_tokens, preserved_segment}`. */
1853
+ type: "compacted";
1854
+ trigger: "auto" | "manual";
1855
+ tokensBefore: number;
1856
+ /** TB telemetry B4 (service [397]): post-compaction context size in the TRIGGER-GATE coordinate
1857
+ * (`postTriggerTokens` = estimate + anchor-less overhead). Pairs with {@link triggerTokensBefore}
1858
+ * — NOT with `tokensBefore` (which is the CC `pre_tokens` value in prepareCompaction's coordinate,
1859
+ * lacking the overhead term; subtracting across the two coordinates would mis-state the delta,
1860
+ * the audit-B-1 / P-13 class). Absent when the post measurement failed (best-effort, never fails a
1861
+ * successful compaction). */
1862
+ tokensAfter?: number;
1863
+ /** TB telemetry B4: pre-compaction size in the SAME trigger-gate coordinate as {@link tokensAfter}
1864
+ * (`triggerTokens` — the exact quantity the compaction gate compared). `triggerTokensBefore −
1865
+ * tokensAfter` is the self-consistent freed delta. Absent on the legacy emitter. */
1866
+ triggerTokensBefore?: number;
1867
+ /** TB telemetry B4: wall time of the whole compaction pass (summary call included) — what the
1868
+ * boundary pause actually cost. Absent on legacy emitters. */
1869
+ durationMs?: number;
1870
+ /** CC `SDKCompactBoundary.preserved_segment` parity: `firstKeptEntryId` is the session-tree entry id where
1871
+ * the surviving KEPT TAIL begins after this compaction. A consumer maps it to a wire message via the
1872
+ * `entryId` carried on `message_committed` (message-identity Phase 1) — render the compaction divider just
1873
+ * before that message + relink the preserved tail. (The eventId↔entryId side map service keeps for resumeAt
1874
+ * also resolves it, but is no longer required.) Absent on a compaction that reported no kept-tail floor. */
1875
+ preserved_segment?: {
1876
+ firstKeptEntryId: string;
1877
+ };
1878
+ /** Blackboard 2026-07-03 (CC post-compact file-restore parity): the working files the engine
1879
+ * re-read into the summary (attachWorkingFiles), attachment order. A shell renders CC's
1880
+ * `Read {path} (…)` cards under the compaction divider from this. Absent when the feature is
1881
+ * off or nothing was attached. `truncated` = the content was clipped at the per-file cap. */
1882
+ attachedFiles?: Array<{
1883
+ path: string;
1884
+ chars: number;
1885
+ truncated: boolean;
1886
+ }>;
1887
+ } | ({
1888
+ /**
1889
+ * TB telemetry B3 (service [397]): the engine injected a SYSTEM steering message (a deadline nudge
1890
+ * or the design/130 P2 graceful-finalize instruction) into the model's next turn. Previously these
1891
+ * went through `harness.steer()` with no stream echo — a consumer literally could not tell whether
1892
+ * the finalize fired (the refute-130 attribution blind spot). Echo only; the model-facing message
1893
+ * is unchanged. `preview` is the injected text clipped to a display bound.
1894
+ *
1895
+ * design/133 (LOW-11/F11): the turn-boundary attachment producers ride the same echo — sources
1896
+ * `todo_reminder` / `task_reminder` / `changed_files` / `plan_mode` and the G1 [482]/续批 members
1897
+ * `background_tasks` / `tools_delta` / `agent_listing` / `mcp_instructions` (one event per
1898
+ * attachment; a multi-attachment boundary still coalesces into ONE steer message on the model lane).
1899
+ */
1900
+ type: "steering_injected";
1901
+ source: "deadline_nudge" | "finalize" | "todo_reminder" | "task_reminder" | "changed_files" | "plan_mode" | "budget_usd" | "background_tasks" | "tools_delta" | "agent_listing" | "mcp_instructions";
1902
+ preview: string;
1903
+ } & TaskEventIdentity) | ({
1904
+ /**
1905
+ * design/121 (CC 198 `<new-diagnostics>` parity): NEW LSP diagnostics that appeared after the
1906
+ * agent's edits, drained at a turn boundary. The SAME data was injected into the model as a
1907
+ * `<new-diagnostics>` context message; this frame is the shell's render source (CC's collapsed
1908
+ * `Found N new diagnostic issues in M files (ctrl+o to expand)` row). UNTRUSTED RAW (language-
1909
+ * server output over workspace files) — a consumer redacts/bounds before persisting (§E1).
1910
+ */
1911
+ type: "diagnostics";
1912
+ files: Array<{
1913
+ uri: string;
1914
+ diagnostics: Array<{
1915
+ message: string;
1916
+ /** LSP severity: 1=Error 2=Warning 3=Information 4=Hint. */
1917
+ severity?: number;
1918
+ range?: {
1919
+ start: {
1920
+ line: number;
1921
+ character: number;
1922
+ };
1923
+ end?: {
1924
+ line: number;
1925
+ character: number;
1926
+ };
1927
+ };
1928
+ code?: string | number;
1929
+ source?: string;
1930
+ }>;
1931
+ }>;
1932
+ isNew: true;
1933
+ } & TaskEventIdentity) | ({
1934
+ /**
1935
+ * message-identity Phase 1 (the CC `SDKCompactBoundary` parity enabler): a persisted session-tree entry was
1936
+ * just COMMITTED for a RENDERABLE message the consumer has already streamed. `entryId` = `SessionTreeEntry.id`
1937
+ * (uuidv7, persisted, replica-stable) — the SAME id space as `compacted.preserved_segment.firstKeptEntryId`,
1938
+ * E18 `resumeAt`, and E19 `rewindFiles`. `role` + (for a tool result) `toolCallId` let a consumer bind it to
1939
+ * the message it rendered: a tool result by its `toolCallId`; an assistant/user message by stream order (this
1940
+ * is the terminal boundary for the content just streamed, after its deltas and before its tool results). A
1941
+ * consumer builds its own `entryId → message` map from these to resolve `preserved_segment` WITHOUT the
1942
+ * eventId↔entryId side map. Terminal per-message boundary; additive + ignorable. ABSENT for a message that did
1943
+ * not persist (an empty-failure assistant) and for non-message entries (a compaction summary / model_change —
1944
+ * never a `message_committed`). The engine still holds no eventId→entryId map (the deployment owns it); this
1945
+ * only pushes the persisted id onto the wire, the constitution's primitive/profile split (cf. §E2 `eventId`).
1946
+ */
1947
+ type: "message_committed";
1948
+ entryId: string;
1949
+ role: "user" | "assistant" | "toolResult";
1950
+ /** Present iff `role === "toolResult"`: the exact join key to the `tool_start`/`tool_end` already rendered. */
1951
+ toolCallId?: string;
1952
+ } & TaskEventIdentity) | ({
1953
+ /**
1954
+ * design/99 §E3/§E10 (service [241]/[242]) — a live BRAIN-LAYER status the brain would otherwise absorb
1955
+ * silently (a 429 rate-limit / a 5xx or network retry / a reconnect / an open circuit breaker). Emitted
1956
+ * the moment the brain decides to wait/retry, carrying the graduated {@link BrainStatusPhase} + an
1957
+ * optional `retryInSec` so a UI can show "rate limited, retrying in Ns". EPHEMERAL — a pure liveness
1958
+ * signal, never persisted or replayed on resume. Provider-neutral (no HTTP status / stop_reason).
1959
+ * SCOPE: reflects THIS task's own (top-level) brain calls. A delegated sub-agent's brain liveness routes
1960
+ * to the SUB-AGENT's own stream (isolated, like every child event — §E2); a background internal brain
1961
+ * call (memory recall/consolidation) is intentionally not surfaced.
1962
+ */
1963
+ type: "status";
1964
+ } & BrainStatus & TaskEventIdentity) | ({
1965
+ /**
1966
+ * design/115 P2 core slice — SDK-side projection of a background task terminal notification. The model-facing
1967
+ * projection is the sibling `<task-notification>` XML injected through the runner's system-injection lane when
1968
+ * the originating harness is still running; durable idle wake/resume is a deployment transport concern.
1969
+ */
1970
+ type: "task_notification";
1971
+ notification: TaskNotificationPayload;
1972
+ } & TaskEventIdentity) | ({
1973
+ /**
1974
+ * design/99 MF-10 (Service AI [297]) — a SUBAGENT PROGRESS TICK: the delegated sub-run's usage ACCRUING
1975
+ * over time, emitted at each turn boundary WHILE it runs, so a parent UI animates the Task card's rollup
1976
+ * (tokens/tool-uses climbing). Emitted ONLY for a subagent (a task with `parentToolCallId`); a top-level
1977
+ * run's own usage is the consumer's own. `status:"running"` mid-run; the terminal usage is the `done` result.
1978
+ * Live/ephemeral — NOT persisted (a resumable trace re-derives usage from the result), like `status`.
1979
+ * Maps to CC `SDKTaskProgress` (camelCase here → snake_case `task_id`/`total_tokens`/`tool_uses`/`duration_ms`
1980
+ * at the SDK/service projection, the same convention as `toolCallId`→`tool_use_id`).
1981
+ */
1982
+ type: "task_progress";
1983
+ taskId: string;
1984
+ /** design/99 (nested-subagent live tree): the spawning run's taskId — present on a DEEPER-than-1 subagent tick
1985
+ * (a subagent spawned by another subagent), forwarded via `RunInternals.onForwardEvent` so a UI nests the
1986
+ * node directly (this.taskId under parentTaskId) without mapping `parentToolCallId` → owner. The top-level
1987
+ * run is known to the consumer; its direct children carry the top's taskId here. Absent on a top-level tick. */
1988
+ parentTaskId?: string;
1989
+ /** design/99 BC-2 (Service AI [§I]): a short, single-line HUMAN display name for the subagent — its explicit
1990
+ * `taskName` or the selected agent-type. So a Fleet child row shows a readable label instead of the raw
1991
+ * `taskId` (the stable row identity stays the taskId). ABSENT when the subagent carries neither a taskName
1992
+ * nor an agent-type — the child then keeps its taskId (NOT the raw objective, which could leak a delegated
1993
+ * secret to a progress-scoped consumer — dual-review Q2). Sanitized (control-char-stripped, length-capped). */
1994
+ name?: string;
1995
+ /** 黑板 [583] (#64 接线实证): the child's most recent tool intent as one human line ("Bash npm test",
1996
+ * "Edit src/x.ts") — the SAME source/value as the registry sink tick's `currentAction` (黑板 [558] B),
1997
+ * attached to the FORWARDED frame because every client wire projects this TaskEvent, not the sink
1998
+ * (service's three projection legs saw a permanently-absent field before this). UNTRUSTED display
1999
+ * hint — redact at the projection boundary (service [579]②). Absent until the child runs a tool. */
2000
+ currentAction?: string;
2001
+ usage: {
2002
+ totalTokens: number;
2003
+ toolUses: number;
2004
+ durationMs: number;
2005
+ };
2006
+ status: "running";
2007
+ } & TaskEventIdentity) | ({
2008
+ /**
2009
+ * design/99 §E13 (service [241]/[242]) — the task's tracked working directory CHANGED mid-run (a `bash`
2010
+ * `cd` moved it). Emitted live after the tool that moved it, carrying the new logical cwd, so a shell UI
2011
+ * can update its prompt/path display. The tracked cwd is the RAW logical path (a `cd` through a symlink
2012
+ * reports the raw path navigated, not the resolved target). Only fires when a real shell is mounted
2013
+ * (absent under `handsReadOnly` / no-exec). The initial cwd is NOT announced (it is the known root); only
2014
+ * subsequent changes are. A live observability signal — not persisted, and the tracked cwd RESETS to the
2015
+ * root across a suspend/resume (the per-leg execution cwd is not durable today — a pre-existing limitation
2016
+ * tracked with the E18/E19 execution-state durability work); within a leg, every `cd` move is reported.
2017
+ */
2018
+ type: "workspace_changed";
2019
+ cwd: string;
2020
+ } & TaskEventIdentity) | {
2021
+ type: "done";
2022
+ result: TaskResult;
2023
+ };
2024
+ /**
2025
+ * Outcome of a manual {@link TaskStream.compact} request (blackboard [496]③ — the enum names align with
2026
+ * the diagnosis decision tree's drain exits, so a consumer can tell "202 processed" states apart):
2027
+ * - `"compacted"` — a compaction landed at the boundary (the `compacted{trigger:"manual"}` event fired).
2028
+ * - `"failed"` — the attempt ran and threw (summarizer failure / empty summary / oversized summary;
2029
+ * `compaction.failed` trace frame + `Runner.onError(phase:"compaction")`), or the §17.4 breaker was
2030
+ * already open so the request was drained without an attempt (`compaction.failed` frame, no attempt).
2031
+ * - `"mooted"` — the request was processed but the run could no longer compact (dying loop: abort /
2032
+ * durable suspend / plan review in flight), or the task settled before any boundary arrived.
2033
+ * - `"noop"` — the attempt ran but there was nothing to compact (no valid cut point / empty history).
2034
+ * - `"blocked"` — a `preCompact` hook deliberately blocked this compaction (not a failure).
2035
+ * - `"disabled"` — compaction is disabled by the task spec (`compaction.enabled: false`).
2036
+ */
2037
+ export type CompactOutcome = "compacted" | "failed" | "mooted" | "noop" | "blocked" | "disabled";
2038
+ /** A running task you can iterate for live events and await for the final result. */
2039
+ export interface TaskStream extends AsyncIterable<TaskEvent> {
2040
+ result(): Promise<TaskResult>;
2041
+ /**
2042
+ * Resolves when the post-task memory-consolidation pass (design/41) settles — or immediately when none
2043
+ * ran. Consolidation is **fire-and-forget**: `result()`/`runTask()` never wait for it (result-first).
2044
+ * Await this ONLY when you need `stats.memory` populated (tests/metrics) or to know the background
2045
+ * reconcile finished. Best-effort: it never rejects (failures route to `onError(phase:"memory")`).
2046
+ */
2047
+ consolidation(): Promise<void>;
2048
+ /**
2049
+ * design/100 §E12 — resolves to the post-completion prompt **suggestions** (the shell's follow-up prompts),
2050
+ * or `[]` when `suggestNextPrompts` was off / the task did not complete / the pass produced nothing / it
2051
+ * failed. Like {@link consolidation}, the pass is **fire-and-forget**: `result()` never waits for it, so a
2052
+ * shell does `await stream.result()` THEN `await stream.suggestions()`. **Never rejects.** The strings are
2053
+ * UNTRUSTED model output for display ONLY — never re-feed them to a model.
2054
+ */
2055
+ suggestions(): Promise<string[]>;
2056
+ /**
2057
+ * Inject a mid-task **steering** message (design/47) that the running task sees at the start of its
2058
+ * next turn (delivered via the harness steering queue). Resolves once queued; **throws** (code
2059
+ * `steering.not_running`) if the task hasn't started yet or has already finished — never silently
2060
+ * dropped. By default the text enters as a normal **user** message (in an orchestration the caller IS
2061
+ * the task's user). Pass `trusted: true` ONLY for operator/system-level guidance: it is wrapped as a
2062
+ * `<system-reminder>` (elevated authority) — do NOT use it for caller/third-party content that could
2063
+ * carry a prompt injection. The seam gives the channel; the caller owns the judgement (design/43 §6).
2064
+ */
2065
+ steer(text: string, options?: {
2066
+ trusted?: boolean;
2067
+ }): Promise<void>;
2068
+ /**
2069
+ * Request a manual context **compaction** (design/99 MF-18 — the shell `/compact` button). Forces a
2070
+ * compaction at the NEXT safe turn boundary regardless of the auto-threshold (the only safe point — never
2071
+ * mid-turn, which would rewrite the session under an in-flight request); a `compacted` event with
2072
+ * `trigger:"manual"` is emitted when it actually compacts. Resolves once the request has been PROCESSED at
2073
+ * a boundary, or when the task ends first (whichever comes first — it never hangs). **Throws**
2074
+ * (`steering.not_running`) if the task hasn't started or has already finished. Idempotent-ish: concurrent
2075
+ * calls coalesce onto the next boundary (all waiters get the same outcome).
2076
+ *
2077
+ * ⚠️ BREAKING (blackboard [496]③, MF-18 processed-无-compacted): resolves with a {@link CompactOutcome}
2078
+ * instead of `void` — "processed" alone told a consumer nothing when the attempt failed or was mooted
2079
+ * (the 202-then-silence fingerprint). Every outcome also has a stream/trace counterpart:
2080
+ * `"compacted"` → the `compacted` event; `"failed"` → `compaction.failed` trace (+ `onError(phase:
2081
+ * "compaction")` when an attempt was burned); `"blocked"` → `compaction.blocked` trace; `"noop"` →
2082
+ * `compaction.noop` trace; `"disabled"` → `compaction.disabled` trace; `"mooted"` →
2083
+ * `compaction.mooted` trace — or the task simply settled before any boundary processed the request
2084
+ * (the run-end backstop resolves "mooted" without a frame; the task's terminal events are the signal).
2085
+ */
2086
+ compact(): Promise<CompactOutcome>;
2087
+ /**
2088
+ * design/116 detach(飞轮 [C],CC mid-flight ctrl+b)— move a RUNNING tool call to the background.
2089
+ * Today only a detach-capable Bash honors it (the env adopts the child as a background shell; the tool
2090
+ * settles early with "moved to background; task_id=b*", and the G2b completion notification takes over).
2091
+ * Fire-and-forget and race-safe: a request landing before the tool reads its signal still detaches; one
2092
+ * landing after the tool finished is a no-op. Unknown toolCallIds are a no-op (nothing to detach).
2093
+ */
2094
+ detach(toolCallId: string): void;
2095
+ /**
2096
+ * Hard-**interrupt** the running task — a real abort (not a best-effort hint), equivalent to firing the
2097
+ * task's `signal` (design/47). No-op if the task already finished. For a SOFT redirect that lets the
2098
+ * task keep running and adjust, use {@link steer} instead.
2099
+ */
2100
+ interrupt(): Promise<void>;
2101
+ /**
2102
+ * Reap this task's resources — **callable after it finished**, idempotent, never throws (design/50 §3,
2103
+ * design/51). The fan-out (v2) cancel primitive: an orchestrator's `cancelAll` is the shared
2104
+ * `AbortController.abort()` then `Promise.all(streams.map((s) => s.destroy()))`.
2105
+ *
2106
+ * - **still running** → hard-interrupts it; the run's own `finish()` tears down its execution env.
2107
+ * - **suspended** (`status:"suspended"`) → `finish()` SKIPPED env teardown (the remote env was
2108
+ * `suspendVM`-paused for a durable resume) and the checkpoint is committed → `destroy()` reaps BOTH:
2109
+ * it CAS-**expires** the checkpoint (`CheckpointStore.expire`, fencing any concurrent resume) and —
2110
+ * **only if it won that CAS** — destroys the paused env. So a cancelled fan-out worker never leaks a
2111
+ * paused container + orphan checkpoint, and is never resumed onto an env `destroy()` already tore down
2112
+ * (the expire/resolve CAS on the one `pending` row is mutually exclusive: exactly one of reap/resume
2113
+ * wins). If `expire` itself fails, the env is left intact (checkpoint + paused env stay a consistent,
2114
+ * still-resumable pair; the failure surfaces via `RunnerDeps.onError`, not a throw).
2115
+ * - **already completed / failed / already destroyed** → no-op.
2116
+ *
2117
+ * Idempotent at the promise level (repeat/concurrent calls await the same settled work).
2118
+ */
2119
+ destroy(): Promise<void>;
2120
+ }
2121
+ /**
2122
+ * Memory write-side consolidation (design/41 B-full): after a task ends, optionally make **one** LLM
2123
+ * call to reconcile the notes the model wrote this task against existing memory — Mem0-style
2124
+ * ADD/UPDATE/DELETE/NONE — so memory stays "few and accurate". **Opt-in, off by default**: the object's
2125
+ * mere presence does NOT enable it; `enabled` must be set `true` explicitly (so a config object can sit
2126
+ * in place pre-wired and be flipped on). Requires `RunnerDeps.memoryStore` to implement the
2127
+ * id-addressable trio (`searchScored`/`update`/`delete`); otherwise consolidation is a safe no-op.
2128
+ *
2129
+ * Cost lands in `TaskResult.stats.memory` (NOT in the task's own `tokens`/`cost`, and excluded from the
2130
+ * budget gate). Failures are best-effort: the notes the model already saved are kept, and the failure is
2131
+ * reported via `onError(phase:"memory")`.
2132
+ *
2133
+ * @deprecated design/138 S4 — the runner-integrated consolidation pass rode the retired legacy memoryStore
2134
+ * path and no longer runs (the config is ignored by the Runner). The standalone helpers
2135
+ * (`runMemoryConsolidation`/`consolidateScope`) still accept it for direct store-level use.
2136
+ */
2137
+ export interface MemoryConsolidationConfig {
2138
+ /** Master switch. `false`/omitted = no consolidation (zero extra LLM calls), unchanged behavior. */
2139
+ enabled: boolean;
2140
+ /** Model role for the reconcile LLM call. Default `"summarize"` (a cheap tier; falls back to `default`). */
2141
+ role?: ModelRole;
2142
+ /**
2143
+ * Vector-distance reconcile band over `searchScored` candidates (see {@link ScoredMemory} — cosine
2144
+ * distance ∈ [0, 2], 0 = identical). A new note's NEAREST existing candidate decides its path:
2145
+ * `< lo` = near-duplicate → cheap UPDATE, no LLM; `[lo, hi]` = possibly refines/contradicts → batched
2146
+ * into the LLM call; `> hi` = genuinely new → kept as-is, no LLM. Default `{ lo: 0.05, hi: 0.30 }`.
2147
+ *
2148
+ * These defaults are effectively the **5th / 95th percentile** of a typical embedding model's distance
2149
+ * distribution — **calibrate them per embedding model**: a different model's distances live on a
2150
+ * different scale, and an un-recalibrated band silently degrades to pass-through (everything ADDs) or
2151
+ * over-merges (everything reconciles).
2152
+ */
2153
+ band?: {
2154
+ lo: number;
2155
+ hi: number;
2156
+ };
2157
+ /** Top-k candidates `searchScored` fetches per new note. Default 20 (bounds the LLM input). */
2158
+ searchLimit?: number;
2159
+ /** Cap on this-task notes consolidated in one batch (bounds the LLM input). Default 50. */
2160
+ maxNotesPerTask?: number;
2161
+ /** Independent wall-clock timeout (seconds) for the whole consolidation pass. Default 30. */
2162
+ timeoutSec?: number;
2163
+ }
2164
+ /**
2165
+ * design/98 §E.2 / §2.5 (S8b) — the deployment-trusted governance that EVERY sub-agent an LLM-authored
2166
+ * workflow script spawns INHERITS (tighten-only). The child spec is BUILT from this baseline + a strict
2167
+ * WHITELIST of safe work-fields the script may set — `{ ...base, ...pick(scriptSpec, WHITELIST_KEYS) }` then
2168
+ * `tightenTaskSpec(base, child)` (codex BLOCKER2: default-deny / complete-by-construction, NOT a blacklist
2169
+ * strip — a missed control-plane field would otherwise leak). It is captured from `RunnerDeps` (trusted,
2170
+ * never LLM-influenced), NEVER from the LLM-influenced initiating task spec.
2171
+ *
2172
+ * Why an EXPLICIT field (codex Q1/Q2 arbitration): `RunnerDeps` has no `tools`/`mcp`/`skills`/`principal`
2173
+ * (those are TaskSpec-only), so the capability a workflow child gets cannot be auto-derived from deps —
2174
+ * the deployment must DECLARE it here. Unset ⇒ self-orchestration is FAIL-CLOSED (the `run_workflow` tool is
2175
+ * not mounted, same hard deploy gate as a missing sandbox): a script-spawned agent must never run without a
2176
+ * governed baseline.
2177
+ */
2178
+ export interface WorkflowGovernanceBaseline {
2179
+ /**
2180
+ * The deployment's trusted control-plane the child inherits — toolPolicy / onAsk / onQuestion / hooks /
2181
+ * principal / tools / mcp / skills / lspManager / checkpointStore / getApiKeyAndHeaders / promptProvider /
2182
+ * handsReadOnly / shellGate / limits / maxCostUsd / maxTokens, etc. Snapshotted into each child spec FIRST,
2183
+ * so every governance field comes from here; only whitelisted work-fields overlay it.
2184
+ */
2185
+ base: Partial<TaskSpec>;
2186
+ /**
2187
+ * The allowed model NAMES an LLM-authored script may pick (design/98 §2.5, codex 新洞2). A script gives a
2188
+ * `modelName` string (never a `Model` object — that carries `baseUrl`/`headers` = exfil); the engine
2189
+ * resolves it against this list to a deploy-configured `Model` (the script never sees the object).
2190
+ * **FAIL-CLOSED**: `undefined`/empty ⇒ the script CANNOT pick a model (its `modelName` is rejected → the
2191
+ * child falls back to the workflow's default role). NEVER fail-open to the whole `models` catalog for an
2192
+ * LLM-authored workflow.
2193
+ */
2194
+ workflowModelAllowlist?: string[];
2195
+ }
2196
+ /**
2197
+ * design/99 §K — the per-principal runtime ENTITLEMENTS the engine enforces server-side, resolved by a
2198
+ * deployment via {@link RunnerDeps.runtimeCapsResolver} from center's `GET /api/config/effective?principal=`.
2199
+ * Every field is TIGHTEN-ONLY (a cap only ever DENIES or FORCES; `undefined` = no per-principal restriction).
2200
+ * Only the two caps the ENGINE can enforce live here; `allowUltracode`/`allowBypassPermissions` are
2201
+ * shell-UX / service-settings-layer concerns (see {@link RunnerDeps.runtimeCapsResolver}).
2202
+ */
2203
+ export interface RuntimeCaps {
2204
+ /** `false` DENIES workflow self-orchestration for this principal server-side — even on a deployment that is
2205
+ * capable ({@link RunnerDeps.workflowScriptRunner} + governance). The third stage of the workflows gate.
2206
+ * `undefined`/`true` = no per-principal restriction (the deployment capability still governs). */
2207
+ allowWorkflows?: boolean;
2208
+ /** `false` DENIES fork (`Agent(subagent_type:"fork")` — design/136: the only fork face since the standalone
2209
+ * tool was retired; the deny is the honest `fork.disabled` result, and since 1.256 it binds the Agent-fork
2210
+ * route too, closing the 1.254 governance bypass) for this principal server-side — even on a fork-capable
2211
+ * (durable-store) deployment. Fork is a compute-amplification primitive (a principal spawns
2212
+ * context-inheriting children, each spending on its own quota), so a multi-tenant operator gates it
2213
+ * per-principal the SAME way as {@link allowWorkflows}. `undefined`/`true` = no per-principal restriction
2214
+ * (the task `enableFork` + durable-store capability still govern). Tighten-only: it can DENY a capable
2215
+ * deployment, never GRANT beyond it. */
2216
+ allowFork?: boolean;
2217
+ /**
2218
+ * Observer agents (CC 2.1.206 parity, docs/CC206-OBSERVER-ANCHORS-2026-07-11.md §6): honor
2219
+ * {@link AgentDefinition.observer} auto-spawn declarations. **POLARITY NOTE — unlike
2220
+ * `allowWorkflows`/`allowFork` (`undefined` = unrestricted), this one is `=== true` EXPLICIT
2221
+ * opt-in, default OFF**: CC's gate pair is a default-UNSET experimental env var
2222
+ * (`CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS`) ANDed with a default-true statsig gate — the
2223
+ * composite ships dark. `undefined`/`false` ⇒ declarations resolve to unobserved (no warn: the
2224
+ * gate, not a config mistake).
2225
+ */
2226
+ allowObservers?: boolean;
2227
+ /** `true` FORCES this principal's run onto the durable-approval path: the engine synthesizes a
2228
+ * `durableApproval{scope: principal}` so a policy `ask` suspends to the wire (a per-tool CC-faithful gate)
2229
+ * even when the caller did not opt in — center's fleet-wide "interactive runs gate" mandate. A
2230
+ * caller-supplied `TaskSpec.durableApproval` always wins (it may carry a tighter scope/ttl). */
2231
+ forceDurableGate?: boolean;
2232
+ }
2233
+ /**
2234
+ * design/129-B(黑板 [444])— one lifecycle event of a BACKGROUND delegation child, delivered to the
2235
+ * process-level {@link RunnerDeps.onBackgroundChildEvent} observer. Keys: `taskId` is the registry handle
2236
+ * (`a*` domain — the TaskOutput/TaskStop key); `progressTaskId`/`sessionId` are the child RUN's id (uuid
2237
+ * domain — the same key `task_progress` frames carry, [434] anchor).
2238
+ */
2239
+ export interface BackgroundChildEvent {
2240
+ kind: "spawn" | "tick" | "terminal";
2241
+ /** Registry handle id (`a*` domain). Stable across all three kinds — the row key. */
2242
+ taskId: string;
2243
+ /** design/129: `true` when the child outlives its parent turn (session-scoped). */
2244
+ sessionScoped: boolean;
2245
+ /** Registry owner key (task-scoped: the host taskId; session-scoped: the sessionId). */
2246
+ owner?: string;
2247
+ /** Registry scope (tenant/principal isolation key). */
2248
+ scope?: string;
2249
+ /** spawn: the child's short description (bounded, display-safe). */
2250
+ description?: string;
2251
+ /** spawn: the HOST task's canonical taskId (parent attribution). */
2252
+ parentTaskId?: string;
2253
+ /** tick: the forwarded `task_progress` frame's own taskId (uuid domain; nested children carry theirs). */
2254
+ progressTaskId?: string;
2255
+ /** tick: the forwarded frame's parentTaskId (nested attribution) · terminal: absent. */
2256
+ progressParentTaskId?: string;
2257
+ /** tick: the child's display name, when the frame carried one. */
2258
+ name?: string;
2259
+ /**
2260
+ * tick (黑板 [558] B): the child's most recent tool intent as one human line ("Bash npm test",
2261
+ * "Edit src/x.ts") — derived from the last `tool_start` on the child's stream, so a parent can show
2262
+ * "what is it doing right now" with zero polling of the child. Absent until the child runs a tool.
2263
+ */
2264
+ currentAction?: string;
2265
+ /** terminal: the child RUN's session id (uuid domain) when known. */
2266
+ sessionId?: string;
2267
+ /**
2268
+ * terminal (黑板 [558] C): a handle to the child's persisted transcript — the child RUN's session id
2269
+ * (uuid domain). A parent reads the last N steps on demand via the `AgentTranscript` tool (pull model:
2270
+ * it does NOT inflate the parent's context). Mirror of {@link sessionId} for terminal events; named
2271
+ * distinctly so a consumer keys "how do I read this child's history" without conflating it with routing.
2272
+ */
2273
+ transcriptId?: string;
2274
+ /**
2275
+ * terminal (黑板 [558] A): the child's last ≤10 completed tool steps ({tool, target, outcome}) — the
2276
+ * residual a parent needs to write a PRECISE resume prompt ("you stopped at file X, step Y") for a
2277
+ * child that was stopped/killed mid-flight, WITHOUT reading the transcript. Bounded; absent if the
2278
+ * child ran no tools.
2279
+ */
2280
+ recentSteps?: import("../agents/subagent-steps.js").SubagentStep[];
2281
+ /**
2282
+ * terminal (黑板 [558] D — core half): files the child mutated (Write/Edit/MultiEdit/NotebookEdit)
2283
+ * with edit counts. The LSP-aggregated `<new-diagnostics>` projection is the shell's half; core
2284
+ * supplies only the edited-file list. Bounded; absent if the child edited nothing.
2285
+ */
2286
+ editedFiles?: import("../agents/subagent-steps.js").SubagentEditedFile[];
2287
+ /**
2288
+ * terminal (黑板 [558] E): `true` when the child can be revived with `SendMessage` (its session is
2289
+ * retained and it was not stopped by the user); `false` for a user-stopped / non-resumable child.
2290
+ * Lets a parent's orchestration logic decide "continue it" vs "start fresh" without trial-and-error.
2291
+ */
2292
+ resumable?: boolean;
2293
+ /** terminal: the settled status. */
2294
+ status?: "completed" | "killed" | "failed";
2295
+ /** terminal, killed only (design/134 §3.3): who stopped it. MIRROR of task-registry `StopSource`
2296
+ * (the single source; inlined to avoid an import cycle — task-registry imports types.ts; third
2297
+ * mirror: task-notification.ts `TaskNotificationPayload.stoppedBy` — keep all three in sync).
2298
+ * OPEN ENUM: consumers must tolerate unknown values (a future "timeout" is not breaking). */
2299
+ stoppedBy?: "user" | "parent" | "system" | (string & {});
2300
+ /** terminal: bounded human summary (same text the task_notification carries). */
2301
+ summary?: string;
2302
+ /** tick: live rollup (`task_progress.usage`) · terminal: final `{tokens, turns, costMicroUsd}`. */
2303
+ usage?: {
2304
+ totalTokens?: number;
2305
+ toolUses?: number;
2306
+ durationMs?: number;
2307
+ tokens?: number;
2308
+ turns?: number;
2309
+ costMicroUsd?: number;
2310
+ };
2311
+ }
2312
+ /**
2313
+ * parity-204 — structured `RunnerDeps.loadProjectMemory` return (backward-compatible: a bare
2314
+ * `string | null` keeps its exact historical meaning). Adds the CC 2.1.204 `seededFromContext`
2315
+ * seam (cc204-bundle @17917159: CC preloads readFileState for CLAUDE.md/nested-memory files it
2316
+ * placed in context, and a DEFAULT whole-file Read of an unchanged seeded file answers with the
2317
+ * already-in-context reminder instead of re-transmitting the body — token economy, GA in 204).
2318
+ */
2319
+ export interface ProjectMemoryLoad {
2320
+ /** The project-context text to inject — same semantics as returning a bare string (null/blank ⇒ no injection). */
2321
+ content: string | null;
2322
+ /**
2323
+ * Files whose FULL, disk-verbatim text the deployment has placed in the model's context (e.g. the
2324
+ * CLAUDE.md that `content` embeds). The Runner pre-seeds the hands' read state (through the same
2325
+ * resolveKey containment as a real Read — an out-of-root path is silently skipped), so a default
2326
+ * whole-file Read of an UNCHANGED seeded file returns the CC-verbatim reminder
2327
+ * (`This file is already in your context (see "Contents of <path>" above) and has not changed on
2328
+ * disk…`) instead of the body. `content` here MUST be the file's exact disk text at load time —
2329
+ * the unchanged check hashes it; never declare a truncated/annotated variant (CC's `isPartialView`
2330
+ * exemption). A file that later changes on disk always reads normally (hash mismatch bypasses the
2331
+ * dedup and disarms it). Requires hands (an executionEnv); ignored on a hands-less task.
2332
+ */
2333
+ seededFiles?: ReadonlyArray<{
2334
+ path: string;
2335
+ content: string;
2336
+ }>;
2337
+ }
2338
+ /** Runtime dependencies shared across tasks. */
2339
+ export interface RunnerDeps {
2340
+ brain: Brain;
2341
+ /** Catalog used to resolve string ModelRefs to Model objects. */
2342
+ models?: Record<string, Model>;
2343
+ /**
2344
+ * 模型档位绑定(clay 拍 2026-07-11):sema 档位词(`max`/`pro`/`flash`/`lite`,`ultra` 预留)→ 具体模型
2345
+ * (catalog 名或 Model)。Runner 构造时经 `expandTiers` 增广进 catalog,使档位词与 CC alias
2346
+ * (`fable`/`mythos`/`opus`/`sonnet`/`haiku`,内置固定映射)在全部模型寻址面直接可用(TaskSpec.model /
2347
+ * roles / Agent 工具 model / workflow agent() / `@model` mention)。无绑定档沿 DEFAULT_TIER_ORDER 降档;
2348
+ * 与部署 catalog 同名键时 catalog WINS(SHADOW)。center 经配置域下发/覆写此表。
2349
+ */
2350
+ tiers?: Record<string, ModelRef>;
2351
+ /**
2352
+ * F4 agentType 注册表(2026-07-11):部署声明的 {@link AgentDefinition} 集,workflow `agent(…,{agentType})`
2353
+ * 经此解析(内置 Explore/Plan 之上 SHADOW)。design/141 件A:Agent 工具 lane(`createSubagentTool`)未显式
2354
+ * 传 `agents` 时经 `Runner.agentCatalog` 自动取此表——同一 Runner 两 lane 单源;显式传参仍 WINS。
2355
+ */
2356
+ agents?: AgentDefinition[];
2357
+ /** `false` 从 workflow agentType 注册表移除内置 Explore/Plan(镜像 createSubagentTool 同名开关)。 */
2358
+ builtinAgents?: boolean;
2359
+ /**
2360
+ * design/141 件2 — hands 工具带(Read/Write/Edit/Bash…)的部署方窄配置面。刻意不导出
2361
+ * `createHandsToolkit` 整厂(部署自装配塞 `spec.tools` 会被 Runner 的自动装配同名覆盖=反模式;
2362
+ * CC 亦无 options-bag 开放面,走单例+hook)。只开放安全子集,Runner 装配时合成:
2363
+ * - `beforeWrite` 与引擎的 MemoryEngine 写扫描门 **COMPOSE 而非替换**(部署 hook 先判,拒即拒;
2364
+ * 放行后引擎门仍全量生效——写保护不可能被部署配置绕过)。
2365
+ * Runner 私有编排字段(taskRegistry/detachHub/execClamp/cwdRef/…)不在此面,永不开放。
2366
+ */
2367
+ hands?: HandsBandOptions;
2368
+ /**
2369
+ * design/96 §20 (P1a) — DEPLOYMENT-DECLARED training knowledge cutoff per model id (e.g.
2370
+ * `{ "qwen-3.5-35b": "2025-01", "deepseek-pro": "2024-07" }`). When the resolved model id is present, the
2371
+ * `# Environment` block shows `Knowledge cutoff: <value>` so the agent reasons about what it may not know.
2372
+ * Deployment-owned ON PURPOSE: core hardcodes no model→date map (a stale cutoff = a §25 honesty breach, and
2373
+ * the model catalog is a deployment/profile concern). Omitted ⇒ no cutoff line (honest absence). Optional.
2374
+ */
2375
+ modelKnowledgeCutoffs?: Record<string, string>;
2376
+ /**
2377
+ * Default model roles: declare your models once and let every subsystem (main task, compaction,
2378
+ * subagent, team) resolve its role instead of repeating a model name. `TaskSpec.roles` overrides
2379
+ * per task/scenario. e.g. `{ default: "strong", summarize: "cheap", subagent: "cheap" }`.
2380
+ */
2381
+ roles?: ModelRoles;
2382
+ /**
2383
+ * Session lifecycle/persistence backend. Defaults to `TtlSessionStore` (in-memory, 7-day idle TTL
2384
+ * — lost on restart). For **durable** sessions (a "session center" that survives restarts and is
2385
+ * shared across stateless replicas), supply a `TtlSessionStore` over a durable `SessionRepo`
2386
+ * (e.g. TiDB-backed), or a fully custom `SessionStore`. See `design/10-会话持久化与会话中心.md`.
2387
+ */
2388
+ sessionStore?: import("./session.js").SessionStore;
2389
+ /**
2390
+ * Durable-checkpoint backend for suspend/resume (design/45). A task with `durableApproval` set
2391
+ * persists its awaiting-human checkpoints here and ends `status:"suspended"`; `runner.resume()` reads
2392
+ * them back — cross-replica when this is durable (service's approval/run-store). A task's own
2393
+ * `checkpointStore` overrides this. Omitted → no durable suspension (policy `ask` stays synchronous).
2394
+ */
2395
+ checkpointStore?: import("./checkpoint-store.js").CheckpointStore;
2396
+ /**
2397
+ * design/101 §E19 — working-tree snapshot backend for {@link TaskSpec.rewindFiles}. A task with
2398
+ * `rewindFiles` captures a snapshot per completed turn (keyed by the leaf `SessionTreeEntry.id`) and, when it
2399
+ * also branches via {@link TaskSpec.resumeAt}, restores the snapshot for that entry. Omitted ⇒ rewind is OFF
2400
+ * (no snapshot/restore work). The default reference impl is {@link InMemoryFileSnapshotStore}; a deployment
2401
+ * supplies a durable / git / VM-snapshot backend behind the same seam (v1 restore is LOCAL-only).
2402
+ */
2403
+ fileSnapshotStore?: import("./file-snapshot-store.js").FileSnapshotStore;
2404
+ /**
2405
+ * design/99 §E6 — DURABLE per-session permission rules (a deny-narrowing folded into the task-time tool
2406
+ * policy). Omitted ⇒ the feature is OFF (no rules read, zero behavior change). A deployment supplies a
2407
+ * cross-replica backend whose CAS-rev + tighten-only semantics match the core
2408
+ * {@link import("./session-policy-store.js").InMemorySessionPolicyStore}. Rules are read at prepare time for a
2409
+ * task carrying its own `sessionId` (a delegated subagent inherits none) and composed BEFORE the caller
2410
+ * policy, so they can only SUBTRACT capability. core does NOT verify owner/operator identity — the store
2411
+ * honors the `operator` flag the (service) caller freezes from a verified principal.
2412
+ */
2413
+ sessionPolicyStore?: import("./session-policy-store.js").SessionPolicyStore;
2414
+ /**
2415
+ * design/99 §K (service [305]/center [318]) — resolve the **per-principal runtime ENTITLEMENTS** the engine
2416
+ * ENFORCES server-side, keyed by `spec.principal`. A deployment (the SERVICE) implements it over center's
2417
+ * `GET /api/config/effective?principal=` `runtimeCaps`. Resolved once at prepare time.
2418
+ *
2419
+ * 🔐 This is a TRUSTED deployment seam, NOT a caller-facing `TaskSpec` field: entitlements are purely
2420
+ * server-governed — an untrusted caller must never be able to self-grant a capability. `undefined` (no
2421
+ * resolver, or an unset cap) = NO per-principal restriction (TIGHTEN-ONLY: a cap can only ever DENY or
2422
+ * FORCE; absence falls back to the deployment-level default). Symmetric with {@link sessionPolicyStore}.
2423
+ *
2424
+ * core enforces only the caps it CAN enforce in the engine: `allowWorkflows` (the third stage of the
2425
+ * workflows gate — task opt-in ∧ deployment capability ∧ this) and `forceDurableGate` (forces a run onto
2426
+ * the durable-approval path so a policy `ask` suspends to the wire). `allowUltracode` is a shell/UX concern
2427
+ * (reasoning-tier, not a core primitive); `allowBypassPermissions` is enforced at the service settings-
2428
+ * resolution layer (the engine sees only a resolved policy, never a "this allow came from bypass" signal).
2429
+ */
2430
+ runtimeCapsResolver?: (principal: string | undefined) => RuntimeCaps | undefined | Promise<RuntimeCaps | undefined>;
2431
+ /**
2432
+ * design/129-B(黑板 [444])— PROCESS-level observer for background delegation children (Agent/Fork
2433
+ * `run_in_background`): `spawn` (at registry registration) / `tick` (every forwarded `task_progress`)
2434
+ * / `terminal` (after the registry settle), for the child's WHOLE lifetime. Motivation: every per-leg
2435
+ * sink (`RunInternals.onForwardEvent` etc.) carries the SPAWNING turn's lifecycle — correct for sync
2436
+ * children, structurally wrong for a session-scoped background child that outlives the turn (the
2437
+ * deployment rightly freezes per-leg publishers at leg settle, which silences the child). This seam is
2438
+ * keyed to nothing but the process: wire it once at Runner construction and publish fleet rows /
2439
+ * completion pushes from it. Observability only — a throwing observer is swallowed, never faults a run.
2440
+ */
2441
+ onBackgroundChildEvent?: (event: BackgroundChildEvent) => void;
2442
+ /**
2443
+ * design/98 (S8) — the HARD sandbox seam for LLM-AUTHORED workflow scripts (`TaskSpec.selfOrchestration`).
2444
+ * A deployment supplies an isolated-vm / separate-process runner whose `safeForUntrustedScripts === true`;
2445
+ * core does NOT ship one (the Node `vm` dev runner is NOT a security boundary). With this unset (or
2446
+ * `safeForUntrustedScripts:false`), `selfOrchestration` is FAIL-CLOSED: the `run_workflow` tool is not
2447
+ * mounted and the orchestration prompt is not injected. See {@link WorkflowGovernanceBaseline}.
2448
+ */
2449
+ workflowScriptRunner?: import("../orchestration/workflow-script-runner.js").WorkflowScriptRunner;
2450
+ /**
2451
+ * design/98 §2.5 (S8b) — the deployment-trusted governance every workflow-spawned sub-agent inherits
2452
+ * (tighten-only). REQUIRED (alongside a hard `workflowScriptRunner`) for `selfOrchestration` to activate:
2453
+ * unset ⇒ FAIL-CLOSED (the `run_workflow` tool is not mounted — a script-spawned agent must never run
2454
+ * without a governed baseline). See {@link WorkflowGovernanceBaseline}.
2455
+ */
2456
+ workflowGovernanceBaseline?: WorkflowGovernanceBaseline;
2457
+ /** design/98 §D.6 (S8c) — deployment hard CEILINGS for an LLM-authored workflow (script length / agent
2458
+ * count / timeouts / per-child cost+token caps / budget / result+log size). Defaults bound a runaway. */
2459
+ workflowLimits?: import("../orchestration/run-workflow-tool.js").WorkflowLimits;
2460
+ /** design/98 §D.5 (S8c) — re-invoke seam: called once when an LLM-authored workflow completes, with a
2461
+ * redacted, bounded summary. Unset ⇒ the run still completes + is queryable; the originator just isn't
2462
+ * pushed a notification. */
2463
+ workflowCompletionNotifier?: import("../orchestration/run-workflow-tool.js").WorkflowCompletionNotifier;
2464
+ /** design/97 S1b / design/98 §D.5 — persist LLM-authored workflow runs here for cross-replica `/workflows`
2465
+ * history (opt-in; in-process runs are still subscribable without it). */
2466
+ workflowRunStore?: import("./workflow-run-store.js").WorkflowRunStore;
2467
+ /** design/97 CORE-9 (Part A) — the LOAD-BEARING resume journal for LLM-authored (`run_workflow` tool) workflows
2468
+ * (the twin of `workflowRunStore`; service ships a durable Postgres/TiDB one). Wired into the auto-mounted
2469
+ * run_workflow tool so a tool-launched workflow can durably RESUME across a replica crash. Opt-in. */
2470
+ workflowJournalStore?: import("./workflow-journal-store.js").WorkflowJournalStore;
2471
+ /** B5/F2 + design/140 §6 1a — the script-persistence / named-registry seam, threaded into the auto-mounted
2472
+ * run_workflow tool: every invocation's resolved script is persisted (iterate via `{scriptPath}`), `{name}`
2473
+ * resolves a saved workflow, and a registration's `defaultArgs` merge under the call-time args. Opt-in
2474
+ * (absent ⇒ inline `script` + built-in names only). */
2475
+ workflowScriptStore?: import("../orchestration/workflow-script-store.js").WorkflowScriptStore;
2476
+ /** design/140 §6 1c — `false` removes the BUILT-IN named workflows (`team-discussion`, …) from the
2477
+ * auto-mounted run_workflow tool (the `builtinAgents:false` analog; default ON). A deployment
2478
+ * `workflowScriptStore` registration of the same name shadows a built-in regardless. */
2479
+ builtinWorkflows?: boolean;
2480
+ /**
2481
+ * design/97 CORE-9 (Part B) — a TRUSTED deployment sink for the steerable handle of every agent an LLM-authored
2482
+ * (`run_workflow` tool) workflow spawns. When set, the tool's `agent()` primitive runs each agent STEERABLE and
2483
+ * emits its {@link import("../orchestration/workflow.js").WorkflowAgentHandle} here (the script never receives
2484
+ * the handle — no host-context leak into the runner); the deployment registers it by `runId`+`label` to route a
2485
+ * human/cross-replica steer to `handle.steer(...)`. Unset ⇒ agents run non-steerable (no overhead). Opt-in.
2486
+ *
2487
+ * **Interaction with {@link workflowJournalStore} (audit note)**: a steerable agent runs via `agentStream`,
2488
+ * which is NOT journaled (a finished result can't be steered). So with BOTH set, a steerable workflow's
2489
+ * `resumeFromRunId` finds an empty journal and re-runs all agents LIVE — correct, but with no caching benefit
2490
+ * (durable resume re-executes rather than skips). Journal-able steerable agents are a follow-on.
2491
+ */
2492
+ onWorkflowAgentSpawn?: (handle: import("../orchestration/workflow.js").WorkflowAgentHandle) => void;
2493
+ /** design/72 §2.2 (B): deployment default for the suspend-loop cap (see `TaskSpec.maxSuspends`).
2494
+ * Default 5 (loose — human-approval flows re-suspend rarely). A task's own `maxSuspends` overrides. */
2495
+ maxSuspends?: number;
2496
+ /**
2497
+ * design/91: injectable wall-clock source for **human-review timing** (and `Checkpoint.suspendedAt`).
2498
+ * Defaults to `Date.now`. The Runner reads EVERY human-time timestamp through this — the synchronous
2499
+ * `resolveAsk` wait (`t1 − t0`), the durable suspend's `suspendedAt`, and the resume's derived human
2500
+ * latency (`now() − suspendedAt`) — so a test can inject a controllable clock (`let t = 0; now = () => t`)
2501
+ * and assert `stats.humanReview` deterministically (design/87 §4.3 flaky-guard: no bare `Date.now()` in a
2502
+ * hard-gate test). **Scope = human-time only**: this is NOT a general clock for token/cost/turn accounting
2503
+ * (those keep `Date.now`); `humanReview` is a budget-EXCLUDED side observable, never folded into cost. */
2504
+ now?: () => number;
2505
+ /** @deprecated design/138 S4 (BREAKING) — the legacy MemoryStore runner path is RETIRED: with this set,
2506
+ * the Runner mounts NO remember/recall tools, injects NO `<user_memory>` block, and runs NO legacy
2507
+ * consolidation/selective/dynamic recall — it only emits a one-shot deprecation warning per prepared
2508
+ * task (`onError`, phase `"config"`). Migrate to {@link memoryBackend} (the injection-first memory
2509
+ * engine). The TYPE and the store implementations (InMemory/File/Pg) remain exported — a FileBackend
2510
+ * 等 store 仍可独立使用; this dep just no longer drives the runner. Field removal is the next major. */
2511
+ memoryStore?: import("./memory.js").MemoryStore;
2512
+ /**
2513
+ * design/138 S1 — the NEW-ARCHITECTURE memory seam (MemoryEngine over a {@link import("./memory-engine/types.js").MemoryBackend}).
2514
+ * When set AND `spec.memory.enabled`, the task runs the INJECTION-FIRST file-based memory lifecycle
2515
+ * (materialize → session file ops → harvest with the full gate set), the CC-verbatim `# Memory`
2516
+ * instruction + fenced derived index replace the legacy `<user_memory>` block, and NO remember/recall
2517
+ * tools are mounted (memory = the model's ordinary file skills). **S4 (codex 1.258 F6 doc fix): unset ⇒
2518
+ * the task runs MEMORY-LESS** — the legacy `memoryStore` runtime path was retired (one deprecation
2519
+ * warning via `onError` phase `"config"`); this field is the ONLY live memory seam.
2520
+ */
2521
+ memoryBackend?: import("./memory-engine/types.js").MemoryBackend;
2522
+ /**
2523
+ * design/138 §2.7 — the memory-engine directory CONFIG ROOT used when {@link memoryBackend} does not
2524
+ * pin its own directory (a {@link import("./memory-engine/file-backend.js").FileMemoryEngineBackend}
2525
+ * exposes `directoryRoot` and wins). The per-repo memory dir derives as `<root>/<repoKey>/memory`
2526
+ * (repoKey = CC-style slug of the task root). Default: `AGENT_DATA_DIR` env or `~/.ai-agent`.
2527
+ * Location is PURE CONFIG (§2.7 r2.1): a deployment may equally construct the FileBackend over an
2528
+ * IN-REPO git-tracked directory for a project scope.
2529
+ */
2530
+ memoryEngineDir?: string;
2531
+ /**
2532
+ * design/138 S2-B (O-F7/C-F3) — the Runner-owned harvest-report sink. Both harvest boundaries
2533
+ * (the checkpoint mint inside commitSuspendSaga, `phase: "checkpoint"`, and the task terminal in
2534
+ * runtask, `phase: "terminal"`) deliver their {@link import("./memory-engine/types.js").HarvestReport}
2535
+ * here instead of dropping it — trace/accounting/alerting is the deployment's call. Swallow-guarded:
2536
+ * a throwing consumer never fails the boundary. (The model-facing announcement lane is separate:
2537
+ * the engine enqueues gate events at its harvest tail; the NEXT session's first injection drains
2538
+ * them — 时机①.) Optional; unset ⇒ no behavior change beyond the report no longer being discarded.
2539
+ */
2540
+ onMemoryHarvestReport?: (report: import("./memory-engine/types.js").HarvestReport, info: {
2541
+ sessionId: string;
2542
+ phase: "checkpoint" | "terminal";
2543
+ }) => void;
2544
+ /**
2545
+ * design/113 C4 — proactive project startup. The Runner calls this once during `prepareTask` (every prepare,
2546
+ * incl. durable resume — design/113 §4 H8) and injects the returned text as a READ-ONLY, FENCED, virtual
2547
+ * `"project"` memory layer at the TAIL (so the agent "sees" what project it is in from turn 1, like CC's
2548
+ * CLAUDE.md/git injection — the cure for "say hi → only greets"). The deployment/profile owns the CONTENT
2549
+ * (read CLAUDE.md / `.claude/` + fold in `git log -5`/status + a byte budget); core owns the seam + fence +
2550
+ * cache placement and NEVER hardcodes a filename (same trust posture as {@link executionEnvFactory}/
2551
+ * {@link promptProvider}/{@link modelKnowledgeCutoffs}). A RunnerDeps FUNCTION, not a `TaskSpec` field: it is
2552
+ * unserializable (durable resume) and reading files for an UNTRUSTED caller would be a confused-deputy hole
2553
+ * (design/44 §7 Q4). DECOUPLED from `memoryStore` — injects even with NO long-term memory configured (H5).
2554
+ *
2555
+ * `undefined` (default) ⇒ the whole path is skipped = byte-identical to today (full parity, H3). Returning
2556
+ * `null`/blank ⇒ no injection (also byte-identical). The content is fenced/sanitized like every other memory
2557
+ * layer (repo-controlled CLAUDE.md is UNTRUSTED data, not an instruction — H2). The ctx lets a profile tailor
2558
+ * or suppress: `handsEnabled:false` = a hands-less chat with no real project (return null); `isSubagent` =
2559
+ * a delegated child (a profile may trim CLAUDE.md for a cheap "grep this" subagent — H7).
2560
+ */
2561
+ loadProjectMemory?: (ctx: {
2562
+ /** The task's working directory (= the execution env's cwd; a worktree task = its worktree root). */
2563
+ cwd: string;
2564
+ /** False ⇒ a hands-less chat (no real filesystem/project) — a profile typically returns null. */
2565
+ handsEnabled: boolean;
2566
+ /** True ⇒ a delegated subagent run (a profile may trim/suppress project content to control cost). */
2567
+ isSubagent: boolean;
2568
+ /** The subagent's type name, when `isSubagent` — lets a profile tailor content per agent type. */
2569
+ agentName?: string;
2570
+ }) => Promise<string | null | ProjectMemoryLoad> | string | null | ProjectMemoryLoad;
2571
+ /**
2572
+ * design/77 §2 Gate-2: the profile-injected predicate that decides whether a promotable artifact's
2573
+ * (opaque) outcome statistics clear the promotion bar. Core enforces the gate's *presence* (a promotable
2574
+ * write needs a verdict); this predicate supplies the *positivity* definition (the taxonomy/threshold
2575
+ * stays in the profile). **Unwired ⇒ promotable writes fail closed** (an absent gate never auto-passes).
2576
+ */
2577
+ utilityGate?: import("./memory.js").UtilityGate;
2578
+ /**
2579
+ * @deprecated design/138 S4 — legacy memory consolidation (design/41) rode the retired memoryStore path
2580
+ * and no longer runs; ignored. (Engine-plane consolidation re-mount = design/138 §7, another稿.)
2581
+ * Type kept one major; removal is the next major.
2582
+ */
2583
+ memoryConsolidation?: MemoryConsolidationConfig;
2584
+ /**
2585
+ * @deprecated design/138 S4 — selective recall (design/65 §2.2) served ONLY the retired legacy
2586
+ * `<user_memory>` injection path; ignored. The memory engine injects a bounded derived index instead
2587
+ * (MEMORY.md, CC parameters) and the model reads topic files on demand. Removal is the next major.
2588
+ */
2589
+ memoryRecall?: {
2590
+ enabled?: boolean;
2591
+ /** Memory size (bytes) above which selective recall activates. Default 8000. */
2592
+ thresholdBytes?: number;
2593
+ /** Override the side-query selector; default = main-brain sub-query. */
2594
+ select?: import("./memory-recall.js").MemorySelector;
2595
+ /** Model for the default selector (default = the task's model). */
2596
+ selectorModel?: ModelRef;
2597
+ /** Max notes the side-query may select (default 5). */
2598
+ maxSelected?: number;
2599
+ /** Max 1-hop `[[name]]` link-followed notes appended after the selected ones (design/65 P3).
2600
+ * `0` disables link-following. Default 3. */
2601
+ maxLinked?: number;
2602
+ /** Side-query hard timeout (ms, default 5000). */
2603
+ timeoutMs?: number;
2604
+ };
2605
+ /** Override system-prompt assembly. Defaults to `defaultPromptProvider`. */
2606
+ promptProvider?: import("../prompts/default.js").PromptProvider;
2607
+ /**
2608
+ * design/99 §E23 — the LIVE-ONLY inbound-elicitation seam (an MCP server asking the END USER for input
2609
+ * mid-tool-call). Wired ONLY for servers that opted in via {@link McpServerSpec.elicitation}; absent ⇒ core
2610
+ * advertises no elicitation capability (fail-closed). The deployment answers synchronously (e.g. prompts the
2611
+ * terminal user); core replies to the server on the open connection.
2612
+ */
2613
+ onElicit?: OnElicit;
2614
+ /**
2615
+ * design/116 CONFIRM-1 (clay 拍 加 seam 保体验): resize an over-limit MCP image so the model still SEES a
2616
+ * degraded image instead of a spill-to-disk note. Absent ⇒ core auto-detects `sharp` (dynamic import;
2617
+ * turnkey deployments with sharp installed get the CC experience with zero config) and otherwise spills.
2618
+ */
2619
+ mcpImageResizer?: import("./mcp.js").McpImageResizer;
2620
+ /** Default tool-call gate for all tasks (a task's own `toolPolicy` overrides this). */
2621
+ toolPolicy?: import("./tool-policy.js").ToolPolicy;
2622
+ /**
2623
+ * How `ask` decisions resolve when a policy/hook requests human confirmation (design/37). Default
2624
+ * (omitted) = `"deny"`: **headless auto-deny** — no approver, so `ask` resolves deterministically to
2625
+ * deny with a model-readable reason (the safe default for stateless automation). `"allow"` to
2626
+ * auto-approve, or a fail-closed approver function. A task's own `onAsk` overrides this.
2627
+ */
2628
+ onAsk?: import("./tool-policy.js").OnAsk;
2629
+ /** Content-ask seam (design/64 §5): when set, every task mounts an AskUserQuestion tool that routes a
2630
+ * model-issued question to this callback (a real human/UI). Distinct from `onAsk` (permission). A task's
2631
+ * own `onQuestion` overrides this. Unset ⇒ the tool is not mounted (the model can't ask). */
2632
+ onQuestion?: import("./ask-question.js").OnQuestion;
2633
+ /** LSP code-intelligence seam (design/64 §13.1): when set, every task mounts an `lsp` tool routed to this
2634
+ * manager (a deployment-provided language-server bridge, e.g. an E2B LSP sidecar). The manager returns
2635
+ * `undefined` for a file whose language has no server, and the tool degrades to "fall back to grep". A
2636
+ * task's own `lspManager` overrides this. Unset ⇒ no `lsp` tool. */
2637
+ lspManager?: import("./lsp.js").LspServerManager;
2638
+ /**
2639
+ * Default in-process hooks for all tasks (design/37): PreToolUse (rewrite/restrict args + inject
2640
+ * context), PostToolUse (rewrite output + inject context), UserPromptSubmit (block/inject before the
2641
+ * objective becomes a message). A task's own `hooks` overrides this. A PreToolUse hook's `allow`
2642
+ * never bypasses `toolPolicy` — the policy is always the final say.
2643
+ */
2644
+ hooks?: import("./hooks.js").Hooks;
2645
+ /**
2646
+ * Policy for remote image URLs (`TaskSpec.images[].url`). Return false to reject. When set it
2647
+ * **replaces** the built-in SSRF guard (https-only + private/reserved-host block) — e.g. supply a
2648
+ * CDN allowlist, or a stricter resolve-and-pin check. Omit to use the safe default.
2649
+ */
2650
+ allowImageUrl?: (url: string) => boolean;
2651
+ /**
2652
+ * Optional sink for best-effort background errors/warnings that are otherwise swallowed:
2653
+ * - `"compaction"` — a compaction failure (F8); a persistently failing one (flaky gateway, empty
2654
+ * summaries) is invisible without this and lets a session grow until it tops the window.
2655
+ * - `"prompt-cache"` — a legacy `PromptProvider.system` assembled a cache-hostile prompt (volatile
2656
+ * memory not at the tail); the prefix cache will miss every turn. Log/alert on both.
2657
+ * - `"prompt-constitution"` — a `stableSystem` provider returned an ALREADY-assembled prompt
2658
+ * (constitution anchor found); core passed it through un-doubled. Upgrade the provider to return
2659
+ * only the role base (or set `replaceAll: true` to own the whole base).
2660
+ * - `"memory"` — a post-task memory-consolidation pass failed or skipped a malformed reconcile
2661
+ * decision (design/41). Best-effort: the notes the model saved are kept; the task still succeeds.
2662
+ * - `"mcp"` — an MCP server failed to connect / list its tools and was skipped (fail-open, design/29);
2663
+ * the task runs with the remaining servers' tools. One call per failed server.
2664
+ */
2665
+ onError?: (err: unknown, context: {
2666
+ phase: "compaction" | "prompt-cache" | "prompt-constitution" | "degraded" | "config" | "memory" | "mcp" | "interrupt-reconcile" | "suggestions" | "rewind" | "hook";
2667
+ sessionId: string;
2668
+ /**
2669
+ * Machine-readable sub-classification when the phase has one — currently the design/31
2670
+ * cache-break detector's root cause (`"model-switch" | "tool-schema" | "tool-set" |
2671
+ * "system-prefix" | "server-or-ttl"`). Lets the host pick its own log level: `"server-or-ttl"`
2672
+ * is usually benign in agentic tasks (slow tools ⇒ 5min+ request gaps expire provider caches —
2673
+ * service[64] flag②) and warrants info/warn, while the prefix-bug causes warrant attention.
2674
+ */
2675
+ classification?: string;
2676
+ }) => void;
2677
+ /** Best-effort fire-and-forget trace sink (task/turn/brain/tool); `TaskSpec.tracer` overrides per task. */
2678
+ tracer?: import("./trace.js").TracerHook;
2679
+ /**
2680
+ * design/73 §1 v1 — fire-and-forget sink for {@link import("./task-outcome.js").TaskOutcome} facts
2681
+ * (the feedback ledger's core seam; tracer/onError posture — swallow-guarded, a throwing sink never
2682
+ * affects the run). 🔴 Red lines: core emits ONLY the `mechanical` tier (objective-oracle results —
2683
+ * llm_assisted/self-report never enter v1); every outcome carries `oracleHadRedRun`; ONE emission
2684
+ * point — `runGoal`'s terminal state (goal `doneCheck` = the natural mechanical oracle) plus explicit
2685
+ * `emitTaskOutcome` from harnesses that own a real oracle. Plain `runTask` never auto-emits (no
2686
+ * objective oracle → no fact). core emits facts only; aggregation/policy live in the service ledger.
2687
+ */
2688
+ onTaskOutcome?: (outcome: import("./task-outcome.js").TaskOutcome) => void;
2689
+ /** Per-model pricing (per-1M absolute USD) keyed by model id; falls back to each `Model.cost`. */
2690
+ pricing?: Record<string, import("./pricing.js").ModelPricing>;
2691
+ /**
2692
+ * The execution environment the agent's "hand" acts on (design/44) — file system + shell. Default:
2693
+ * `StubExecutionEnv` (no real I/O, current behavior). Inject `NodeExecutionEnv` for local fs/shell, or
2694
+ * a sandboxed/remote impl for multi-tenant isolation. **Injecting a non-stub env is the opt-in** that
2695
+ * activates the file tool band. ⚠️ A bare `NodeExecutionEnv` is unsandboxed — a multi-tenant deployment
2696
+ * MUST inject a chroot/container/per-principal-scoped impl; do not expose raw `NodeExecutionEnv`.
2697
+ */
2698
+ executionEnv?: import("../internal/harness.js").ExecutionEnv;
2699
+ /**
2700
+ * design/48 remote seam — a **trusted control-plane** factory that mints a FRESH execution env per
2701
+ * task (e.g. one isolated container per task in the remote model). Called once at task start; the env
2702
+ * it returns is owned by that task and released on task end. **Wins over** the shared static
2703
+ * `executionEnv`. Injecting it also activates the hand tool band (design/44), exactly like
2704
+ * `executionEnv`. This is the ONLY per-task env injection point — `TaskSpec` deliberately has no
2705
+ * `executionEnv`, so an untrusted caller can't swap the sandbox (design/44 §7 Q4); the trusted
2706
+ * deployment wires the factory.
2707
+ */
2708
+ executionEnvFactory?: import("./remote-env.js").ExecutionEnvFactory;
2709
+ /**
2710
+ * design/77 §1 Gate-1 (oracleIsolation) — a **DISTINCT** trusted control-plane factory that mints the
2711
+ * ISOLATED grader env an out-of-process oracle grades in (the 4th auto-promote gate). It is a SIBLING of
2712
+ * {@link executionEnvFactory}, never the same env: the worker runs in `executionEnvFactory`'s env, the
2713
+ * grader in `graderEnvFactory`'s — so a worker can't corrupt the env that judges it. It inherits the exact
2714
+ * same trust contract: `TaskSpec` deliberately has NO env field (design/44 §7 Q4), so an untrusted caller
2715
+ * can never inject/swap a grader env and grade itself; only the trusted deployment wires this factory. The
2716
+ * env it mints is wrapped in a {@link import("./oracle-isolation.js").GraderEnv} (with the control-plane
2717
+ * `provenance` brand) at the call site, and asserted via
2718
+ * {@link import("./oracle-isolation.js").assertOracleIsolation} before any positive oracle verdict.
2719
+ * **Auto-promote stays mandate-OFF until the four gates are implemented + verified end-to-end** (design/77
2720
+ * §7); this seam only makes auto-accept implementable — it does not turn it on.
2721
+ */
2722
+ graderEnvFactory?: import("./remote-env.js").ExecutionEnvFactory;
2723
+ /**
2724
+ * Containment root for the file tools (design/44 §4 invariant 7): every path must resolve within it,
2725
+ * else the tool rejects (`PathNotInRoot`). Default `process.cwd()`. A defense-in-depth guard rail at the
2726
+ * tool layer — NOT a sandbox (it does not constrain `bash`; that needs OS-level containment) and not a
2727
+ * substitute for an isolated `executionEnv`.
2728
+ */
2729
+ rootPath?: string;
2730
+ /**
2731
+ * Backing store for offloaded large tool results (design/30). Default: a task-scoped
2732
+ * `InMemoryToolResultStore` (no cross-wake durability). Inject a durable store (keyed by ref) so an
2733
+ * offloaded result survives wake/resume.
2734
+ */
2735
+ toolResultStore?: import("./tool-result-store.js").ToolResultStore;
2736
+ /**
2737
+ * Offload a tool result to the store + leave a preview when its text exceeds this many chars. Default
2738
+ * ~20000; set `0` or `Infinity` to disable offloading. Per-tool override via `ToolSpec.offloadThresholdChars`.
2739
+ */
2740
+ toolResultThresholdChars?: number;
2741
+ /**
2742
+ * Two-phase prefix-cache-break detection (design/31): per turn, fingerprint the prefix and, on a
2743
+ * confirmed `cacheRead` drop, emit a root-cause finding via `onError(phase:"prompt-cache")`. Cheap
2744
+ * (hashes only) and only fires on a detected break. Default **on**; set `false` to disable.
2745
+ */
2746
+ cacheBreakDetection?: boolean;
2747
+ /**
2748
+ * Aggregate inline-MEDIA (image) byte budget for the request (batch-C/§17.2 sibling of the text budget;
2749
+ * CC 2.1.196 `tengu_media_byte_cap` parity). Image reads (`Read` → ImageContent) are per-image-capped but
2750
+ * accumulate across turns; this bounds the SUM in the request by stripping the OLDEST images (replaced with a
2751
+ * marker) — request-only, non-destructive (the durable session keeps the image; the model can re-Read it).
2752
+ * Default {@link AGGREGATE_MEDIA_BUDGET_BYTES}; set `Infinity`/`0` to disable.
2753
+ */
2754
+ mediaByteCapBytes?: number;
2755
+ /** Optional telemetry fired when {@link mediaByteCapBytes} strips media in a request (CC's
2756
+ * `tengu_media_byte_cap_stripped` fields). Pure observability — no effect on the request. */
2757
+ onMediaStripped?: (info: {
2758
+ totalBytes: number;
2759
+ limitBytes: number;
2760
+ removedCount: number;
2761
+ removedBytes: number;
2762
+ }) => void;
2763
+ /**
2764
+ * Deferred-tool disclosure policy (design/36). Default (omitted): deterministic per-tool — only tools
2765
+ * with `ToolSpec.defer === true` (and MCP tools, which default to deferred) are deferred, so the same
2766
+ * `TaskSpec` always yields the same `tools[]`. `"auto"`: additionally auto-defer tools when the total
2767
+ * inlined schema size would exceed a fraction of the model's context window. Auto is an explicit opt-in
2768
+ * (council minor #6) because an implicit threshold makes `tools[]` depend on the model/context, which
2769
+ * callers find hard to predict; explicit `defer` flags always win regardless of this setting.
2770
+ */
2771
+ deferMode?: "auto";
2772
+ /**
2773
+ * design/84 Seam C — compact-boundary COST optimization (data-gated, default OFF). A FUNCTION seam (a
2774
+ * trusted control-plane injection), so it lives on `RunnerDeps` — NOT `TaskSpec`: `TaskSpec` is the
2775
+ * serializable, untrusted-caller, durable-resume-round-trippable per-task config (a function can be
2776
+ * neither serialized nor durably checkpointed, and the sandbox/env-class injections deliberately sit on
2777
+ * `RunnerDeps` for the same trust reason). Same placement as `memoryRecall.select` / `promptProvider` /
2778
+ * `executionEnvFactory`.
2779
+ *
2780
+ * When `summaryProvider` is set, BOTH compaction call sites (the within-task turn boundary AND `finish()`
2781
+ * at task end) consult it: a NON-EMPTY string is reused verbatim (the real `generateSummary` LLM call is
2782
+ * skipped); `null`/`undefined`/blank falls back to the existing LLM path (byte-identical to today).
2783
+ * `onCompaction` is a pure post-compaction observer. `maxConsecutiveProviderReuse` (default 3, CC parity)
2784
+ * forces a real summary after N consecutive reuses to bound drift; the Runner OWNS the consecutive-reuse
2785
+ * counter across both call sites for the task (reset on a real summary, incremented on a reused one), so
2786
+ * the caller does not have to thread it back. **Absent (default) ⇒ no behavior change whatsoever.**
2787
+ *
2788
+ * SCOPE (design/141 examples 批实测): the seam covers the whole-turn compaction sites only. A
2789
+ * SPLIT-TURN cut point (mid-turn prefix summarization — the common shape inside a long single-user-
2790
+ * message tool loop) bypasses the provider by design (A2 algorithm sovereignty): the turn-prefix
2791
+ * summary is engine-owned. Deployments needing a clean provider-visible boundary should shape work
2792
+ * as separate tasks sharing `sessionId`.
2793
+ */
2794
+ summaryProvider?: import("./auto-compaction.js").MaybeCompactOptions["summaryProvider"];
2795
+ /** design/84 Seam C — pure post-compaction observer (fires only on a real compaction, never a no-op).
2796
+ * Consumed ONLY when `summaryProvider` is also set (the Seam C options early-return otherwise) — a
2797
+ * pure-observer deployment passes a provider that always returns `null` (keeps the LLM path intact). */
2798
+ onCompaction?: import("./auto-compaction.js").MaybeCompactOptions["onCompaction"];
2799
+ /** design/84 Seam C — force a real `generateSummary` after this many consecutive provider reuses (default
2800
+ * 3, CC parity). The Runner tracks the consecutive-reuse counter per task across both compaction sites. */
2801
+ maxConsecutiveProviderReuse?: number;
2802
+ /**
2803
+ * design/86 §3 缺口 A — DYNAMIC memory re-recall (CC `processSessionStartHooks('compact')` parity),
2804
+ * **opt-in & default OFF** (data-gated, like Seam C `summaryProvider`). Absent/`enabled:false` ⇒ NO behavior
2805
+ * change whatsoever: memory is the one-shot snapshot taken at task start (the stable prefix), exactly as today.
2806
+ *
2807
+ * When enabled, AFTER each REAL within-task compaction the Runner re-runs the EXISTING memory selector against
2808
+ * the CURRENT conversation (the most-recent messages), de-dups against everything already surfaced (the same
2809
+ * `priorSurfacedIds`/`priorSurfacedKeys` machinery the initial recall uses, seeded from the initial recall),
2810
+ * and injects any NEW relevant notes as a TAIL attachment user message (`harness.steer` → next request's tail).
2811
+ * It NEVER touches the stable system prefix (the prefix-cache the whole design rests on) and NEVER re-injects
2812
+ * an already-shown note. It needs a selective-capable store (`listStructuredNotes`/`getByIds`) + a selector
2813
+ * (the `memoryRecall.select` override, else the default brain sub-query); on selector failure/timeout it injects
2814
+ * nothing (no inject-all fallback mid-task). A FUNCTION/observer seam, so it lives on `RunnerDeps`, NOT `TaskSpec`
2815
+ * (the same trust placement as `memoryRecall.select` / `summaryProvider` / `executionEnvFactory`).
2816
+ *
2817
+ * Why compaction-triggered (not every turn): compaction is when fine detail is actually lost (the highest-value
2818
+ * moment to reground, CC parity); firing only post-compaction also bounds the extra selector LLM call (whether
2819
+ * the cost is worth it is a design/82 cost-per-truly-correct data-gated question — this is a THIN seam, no
2820
+ * provider/policy beyond the trigger is built in).
2821
+ *
2822
+ * @deprecated design/138 S4 — the dynamic re-recall seam served ONLY the retired legacy memoryStore
2823
+ * injection path; ignored (prepareTask never wires the seam state anymore). Removal is the next major.
2824
+ */
2825
+ dynamicRecall?: import("./dynamic-recall.js").DynamicRecallConfig;
2826
+ }
2827
+ export type { AgentTool, Model, StreamFn, ThinkingLevel };
2828
+ //# sourceMappingURL=types.d.ts.map