@sema-agent/core 5.19.0 → 5.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/CHANGELOG.md +102 -4
  2. package/dist/agents/agent-definition.d.ts +7 -0
  3. package/dist/agents/agent-transcript-tool.d.ts +30 -0
  4. package/dist/agents/builtin-agents.d.ts +60 -0
  5. package/dist/agents/cascade.d.ts +107 -0
  6. package/dist/agents/cumulative-stats.d.ts +56 -0
  7. package/dist/agents/observer.d.ts +162 -0
  8. package/dist/agents/peer-admission.d.ts +95 -0
  9. package/dist/agents/repair-loop.d.ts +226 -0
  10. package/dist/agents/retain-ledger.d.ts +141 -0
  11. package/dist/agents/roster-store.d.ts +105 -0
  12. package/dist/agents/roster-store.js +3 -0
  13. package/dist/agents/send-message-tool.d.ts +92 -0
  14. package/dist/agents/session-util.d.ts +5 -0
  15. package/dist/agents/subagent-steps.d.ts +66 -0
  16. package/dist/agents/subagent.d.ts +600 -0
  17. package/dist/agents/suspend-guard.d.ts +29 -0
  18. package/dist/agents/teacher.d.ts +75 -0
  19. package/dist/agents/team.d.ts +120 -1
  20. package/dist/agents/tool-filter.d.ts +34 -0
  21. package/dist/agents/verify.d.ts +198 -0
  22. package/dist/bench/metrics.d.ts +455 -0
  23. package/dist/brain/anthropic.d.ts +30 -0
  24. package/dist/brain/circuit-breaker.d.ts +33 -0
  25. package/dist/brain/circuit-breaker.js +14 -3
  26. package/dist/brain/context-overflow.d.ts +60 -3
  27. package/dist/brain/degrading.d.ts +67 -0
  28. package/dist/brain/errors.d.ts +42 -0
  29. package/dist/brain/failover.d.ts +15 -0
  30. package/dist/brain/media-degrade.d.ts +39 -0
  31. package/dist/brain/model-presets.d.ts +31 -0
  32. package/dist/brain/open-responses.d.ts +19 -0
  33. package/dist/brain/openai.d.ts +46 -0
  34. package/dist/brain/reasoning.d.ts +106 -1
  35. package/dist/brain/repetition.d.ts +83 -0
  36. package/dist/brain/request-params.d.ts +56 -0
  37. package/dist/brain/retry.d.ts +46 -0
  38. package/dist/brain/routing.d.ts +12 -0
  39. package/dist/brain/status-sink.d.ts +30 -1
  40. package/dist/brain/stream-engine.d.ts +147 -0
  41. package/dist/brain/stream-shared.d.ts +34 -0
  42. package/dist/brain/terminal-cause.d.ts +31 -0
  43. package/dist/brain/timeout.d.ts +108 -0
  44. package/dist/brain/timeout.js +11 -0
  45. package/dist/brain/tool-call-id.d.ts +20 -0
  46. package/dist/brain/tool-call-repair.d.ts +13 -0
  47. package/dist/config/catalog.d.ts +47 -0
  48. package/dist/config/defaults.d.ts +33 -0
  49. package/dist/core/a2a-task-state.d.ts +53 -0
  50. package/dist/core/a2a.d.ts +51 -0
  51. package/dist/core/arg-summary.d.ts +62 -0
  52. package/dist/core/ask-question.d.ts +272 -2
  53. package/dist/core/auto-compaction.d.ts +467 -0
  54. package/dist/core/auto-compaction.js +20 -6
  55. package/dist/core/auto-mode-prompt-assets.d.ts +8 -0
  56. package/dist/core/auto-mode-prompt.d.ts +27 -0
  57. package/dist/core/auto-mode.d.ts +54 -3
  58. package/dist/core/auto-promote.d.ts +100 -0
  59. package/dist/core/background-agent-store.d.ts +293 -0
  60. package/dist/core/background-agent-store.js +5 -0
  61. package/dist/core/background-shell.d.ts +110 -0
  62. package/dist/core/cache-break-detector.d.ts +34 -0
  63. package/dist/core/canonical-json.d.ts +57 -0
  64. package/dist/core/checkpoint-store.d.ts +1574 -16
  65. package/dist/core/compliance.d.ts +30 -0
  66. package/dist/core/consolidate-scope.d.ts +75 -0
  67. package/dist/core/context-edit.d.ts +99 -0
  68. package/dist/core/context-guard.d.ts +46 -0
  69. package/dist/core/exec-gate.d.ts +44 -0
  70. package/dist/core/exec-output-tail.d.ts +61 -0
  71. package/dist/core/file-snapshot-store.d.ts +104 -0
  72. package/dist/core/fs-write-gate-policy.d.ts +36 -0
  73. package/dist/core/git-worktree-env.d.ts +31 -0
  74. package/dist/core/governance-codes.d.ts +19 -0
  75. package/dist/core/hooks.d.ts +609 -1
  76. package/dist/core/human-input-projection.d.ts +37 -0
  77. package/dist/core/human-input-projection.js +13 -0
  78. package/dist/core/image-downsample.d.ts +74 -0
  79. package/dist/core/locked-config.d.ts +37 -0
  80. package/dist/core/lsp-diagnostics.d.ts +77 -0
  81. package/dist/core/lsp-protocol.d.ts +29 -0
  82. package/dist/core/lsp-session.d.ts +60 -1
  83. package/dist/core/lsp.d.ts +150 -1
  84. package/dist/core/mailbox-store.d.ts +57 -0
  85. package/dist/core/mailbox-store.js +2 -0
  86. package/dist/core/mcp.d.ts +385 -0
  87. package/dist/core/mcp.js +58 -11
  88. package/dist/core/media-byte-cap.d.ts +21 -0
  89. package/dist/core/memory-admission.d.ts +71 -0
  90. package/dist/core/memory-engine/content-origin.d.ts +64 -0
  91. package/dist/core/memory-engine/data-plane.d.ts +43 -0
  92. package/dist/core/memory-engine/dual-root.d.ts +24 -0
  93. package/dist/core/memory-engine/engine.d.ts +230 -0
  94. package/dist/core/memory-engine/engine.js +103 -35
  95. package/dist/core/memory-engine/file-backend.d.ts +155 -0
  96. package/dist/core/memory-engine/frontmatter.d.ts +16 -0
  97. package/dist/core/memory-engine/layout.d.ts +217 -0
  98. package/dist/core/memory-engine/memory-backend-contract.d.ts +12 -0
  99. package/dist/core/memory-engine/migrate.d.ts +9 -0
  100. package/dist/core/memory-engine/scan.d.ts +12 -0
  101. package/dist/core/memory-engine/scope-contract.d.ts +61 -1
  102. package/dist/core/memory-engine/sync-client.d.ts +87 -0
  103. package/dist/core/memory-engine/sync.d.ts +60 -0
  104. package/dist/core/memory-engine/tools.d.ts +41 -0
  105. package/dist/core/memory-engine/types.d.ts +188 -0
  106. package/dist/core/memory-recall.d.ts +141 -0
  107. package/dist/core/memory-vector.d.ts +20 -0
  108. package/dist/core/memory.d.ts +458 -0
  109. package/dist/core/message-utils.d.ts +6 -0
  110. package/dist/core/oracle-isolation.d.ts +69 -0
  111. package/dist/core/permission-rule-consent.d.ts +138 -0
  112. package/dist/core/permission-rule-model.d.ts +122 -0
  113. package/dist/core/permission-rule-store.d.ts +119 -3
  114. package/dist/core/permission-rules.d.ts +87 -1
  115. package/dist/core/present-plan-tool.d.ts +20 -0
  116. package/dist/core/pricing.d.ts +26 -0
  117. package/dist/core/property-harness.d.ts +86 -0
  118. package/dist/core/protocol-naming.d.ts +38 -0
  119. package/dist/core/protocol-table.d.ts +61 -0
  120. package/dist/core/push-queue.d.ts +1 -0
  121. package/dist/core/remote-env.d.ts +383 -1
  122. package/dist/core/retention-policy.d.ts +40 -0
  123. package/dist/core/retention-policy.js +21 -0
  124. package/dist/core/retention.d.ts +51 -0
  125. package/dist/core/roles.d.ts +59 -0
  126. package/dist/core/runner/active-skill-scope.d.ts +34 -0
  127. package/dist/core/runner/assemble-result.d.ts +134 -0
  128. package/dist/core/runner/compaction-call-options.d.ts +97 -1
  129. package/dist/core/runner/grounding-signal.d.ts +10 -0
  130. package/dist/core/runner/image.d.ts +17 -0
  131. package/dist/core/runner/image.js +29 -15
  132. package/dist/core/runner/memory-consolidation.d.ts +60 -0
  133. package/dist/core/runner/prepare-memory.d.ts +59 -0
  134. package/dist/core/runner/prepare-task.d.ts +1011 -2
  135. package/dist/core/runner/prepare-task.js +51 -14
  136. package/dist/core/runner/prompt-suggestions.d.ts +7 -0
  137. package/dist/core/runner/runtask.d.ts +304 -3
  138. package/dist/core/runner/runtask.js +17 -2
  139. package/dist/core/runner/session-file-state-replay.d.ts +49 -0
  140. package/dist/core/runner/session-rule-policy.d.ts +58 -0
  141. package/dist/core/runner/strict-output-schema.d.ts +18 -3
  142. package/dist/core/runner/synthetic-tools.d.ts +113 -0
  143. package/dist/core/runner/teardown-bounded.d.ts +34 -0
  144. package/dist/core/runner/tool-disclosure.d.ts +227 -0
  145. package/dist/core/runner/tool-output-projection.d.ts +6 -0
  146. package/dist/core/runner/turn-attachments.d.ts +634 -0
  147. package/dist/core/runner/usage-accounting.d.ts +32 -0
  148. package/dist/core/runtime.d.ts +9 -0
  149. package/dist/core/safe-notify.d.ts +64 -0
  150. package/dist/core/safety-axis-vocab.d.ts +23 -0
  151. package/dist/core/safety-merge-corpus.d.ts +37 -0
  152. package/dist/core/scheduler.d.ts +121 -0
  153. package/dist/core/secret-env.d.ts +32 -0
  154. package/dist/core/select-model.d.ts +15 -0
  155. package/dist/core/sensitive-path-policy.d.ts +42 -0
  156. package/dist/core/session-policy-store.d.ts +94 -0
  157. package/dist/core/session-reconcile.d.ts +80 -0
  158. package/dist/core/session-store.d.ts +85 -0
  159. package/dist/core/session.d.ts +153 -0
  160. package/dist/core/shared-memory/contract.d.ts +22 -0
  161. package/dist/core/shared-memory/normalize.d.ts +123 -2
  162. package/dist/core/shared-memory/tools.d.ts +14 -0
  163. package/dist/core/shared-memory/types.d.ts +105 -0
  164. package/dist/core/shutdown-debug.d.ts +6 -0
  165. package/dist/core/side-query.d.ts +38 -0
  166. package/dist/core/side-query.js +6 -1
  167. package/dist/core/skill-tool-specifier.d.ts +72 -0
  168. package/dist/core/skills-directory.d.ts +100 -1
  169. package/dist/core/spec-contract.d.ts +89 -0
  170. package/dist/core/store-contracts/background-agent-store-contract.d.ts +31 -0
  171. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +26 -0
  172. package/dist/core/store-contracts/contract-harness.d.ts +20 -0
  173. package/dist/core/store-contracts/contract-kit-version.d.ts +27 -0
  174. package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +8 -0
  175. package/dist/core/store-contracts/mailbox-store-contract.d.ts +42 -0
  176. package/dist/core/store-contracts/tool-result-store-contract.d.ts +13 -0
  177. package/dist/core/strategy-store.d.ts +37 -0
  178. package/dist/core/stub-env.d.ts +7 -0
  179. package/dist/core/surrogate-safe-slice.d.ts +35 -0
  180. package/dist/core/task-notification.d.ts +202 -0
  181. package/dist/core/task-outcome.d.ts +53 -0
  182. package/dist/core/task-registry-agent.d.ts +337 -1
  183. package/dist/core/task-registry-agent.js +2 -0
  184. package/dist/core/task-registry-monitor.d.ts +12 -0
  185. package/dist/core/task-registry-shared.d.ts +540 -0
  186. package/dist/core/task-registry.d.ts +343 -0
  187. package/dist/core/task-registry.js +13 -2
  188. package/dist/core/task-tool-shape.d.ts +44 -0
  189. package/dist/core/tighten-task-spec.d.ts +21 -0
  190. package/dist/core/tool-detach.d.ts +21 -0
  191. package/dist/core/tool-errors.d.ts +131 -0
  192. package/dist/core/tool-errors.js +4 -0
  193. package/dist/core/tool-name-aliases.d.ts +27 -0
  194. package/dist/core/tool-policy.d.ts +555 -0
  195. package/dist/core/tool-policy.js +3 -0
  196. package/dist/core/tool-result-budget.d.ts +32 -0
  197. package/dist/core/tool-result-store.d.ts +174 -1
  198. package/dist/core/tools.d.ts +45 -0
  199. package/dist/core/trace.d.ts +323 -0
  200. package/dist/core/types.d.ts +3859 -2
  201. package/dist/core/untrusted-egress.d.ts +8 -0
  202. package/dist/core/untrusted-text.d.ts +156 -0
  203. package/dist/core/usage-window-store.d.ts +95 -0
  204. package/dist/core/version.d.ts +1 -0
  205. package/dist/core/warm-resume.d.ts +17 -0
  206. package/dist/core/wiring-manifest.d.ts +169 -0
  207. package/dist/core/with-retry.d.ts +24 -0
  208. package/dist/core/workflow-journal-store.d.ts +160 -0
  209. package/dist/core/workflow-run-store-contract.d.ts +25 -0
  210. package/dist/core/workflow-run-store.d.ts +119 -0
  211. package/dist/core/workflow-run-store.js +2 -0
  212. package/dist/engine/compaction/compaction.d.ts +256 -1
  213. package/dist/engine/compaction/utils.d.ts +94 -0
  214. package/dist/engine/execution-env/kill-tree.d.ts +29 -0
  215. package/dist/engine/execution-env/node-execution-env.d.ts +94 -0
  216. package/dist/engine/harness/agent-harness.d.ts +116 -0
  217. package/dist/engine/harness/agent-harness.js +3 -14
  218. package/dist/engine/harness/messages.d.ts +15 -0
  219. package/dist/engine/harness/types.d.ts +464 -2
  220. package/dist/engine/llm/diagnostics.d.ts +4 -0
  221. package/dist/engine/llm/event-stream.d.ts +3 -0
  222. package/dist/engine/llm/index.d.ts +7 -0
  223. package/dist/engine/llm/types.d.ts +500 -3
  224. package/dist/engine/llm/validation.d.ts +3 -0
  225. package/dist/engine/loop/agent-loop.d.ts +87 -2
  226. package/dist/engine/loop/runtime-deps.d.ts +7 -0
  227. package/dist/engine/loop/types.d.ts +424 -0
  228. package/dist/engine/lsp/frame-decoder.d.ts +13 -0
  229. package/dist/engine/lsp/node-lsp-manager.d.ts +107 -0
  230. package/dist/engine/lsp/stdio-lsp-transport.d.ts +7 -0
  231. package/dist/engine/session/import-validate.d.ts +27 -0
  232. package/dist/engine/session/log-digest.d.ts +93 -0
  233. package/dist/engine/session/memory-repo.d.ts +6 -0
  234. package/dist/engine/session/memory-storage.d.ts +2 -0
  235. package/dist/engine/session/session.d.ts +75 -0
  236. package/dist/engine/session/storage-base.d.ts +8 -0
  237. package/dist/fixtures/index.d.ts +36 -0
  238. package/dist/index.d.ts +17 -2
  239. package/dist/index.js +1 -2
  240. package/dist/internal/harness-types.d.ts +6 -0
  241. package/dist/internal/harness.d.ts +11 -0
  242. package/dist/internal/llm.d.ts +6 -0
  243. package/dist/orchestration/builtin-workflows.d.ts +53 -0
  244. package/dist/orchestration/dev-vm-script-runner.d.ts +19 -0
  245. package/dist/orchestration/goal.d.ts +57 -0
  246. package/dist/orchestration/goal.js +3 -0
  247. package/dist/orchestration/run-spec.d.ts +42 -0
  248. package/dist/orchestration/run-spec.js +4 -0
  249. package/dist/orchestration/run-workflow-tool.d.ts +169 -0
  250. package/dist/orchestration/workflow-governance.d.ts +61 -0
  251. package/dist/orchestration/workflow-meta.d.ts +28 -0
  252. package/dist/orchestration/workflow-observe.d.ts +60 -0
  253. package/dist/orchestration/workflow-primitives.d.ts +23 -1
  254. package/dist/orchestration/workflow-sandbox-conformance.d.ts +38 -0
  255. package/dist/orchestration/workflow-script-runner.d.ts +88 -0
  256. package/dist/orchestration/workflow-script-store.d.ts +98 -0
  257. package/dist/orchestration/workflow-size-guideline.d.ts +67 -0
  258. package/dist/orchestration/workflow-types.d.ts +169 -2
  259. package/dist/orchestration/workflow.d.ts +358 -0
  260. package/dist/orchestration/workflow.js +13 -2
  261. package/dist/prompt-assembly/artifact-store.d.ts +33 -0
  262. package/dist/prompt-assembly/artifact.d.ts +25 -0
  263. package/dist/prompt-assembly/assemble.d.ts +20 -0
  264. package/dist/prompt-assembly/composer.d.ts +29 -0
  265. package/dist/prompt-assembly/epoch.d.ts +55 -1
  266. package/dist/prompt-assembly/event-registry.d.ts +35 -0
  267. package/dist/prompt-assembly/explain.d.ts +12 -0
  268. package/dist/prompt-assembly/tool-catalog.d.ts +38 -0
  269. package/dist/prompt-assembly/turn-snapshot.d.ts +40 -0
  270. package/dist/prompt-assembly/types.d.ts +115 -0
  271. package/dist/prompts/coordinator.d.ts +27 -0
  272. package/dist/prompts/default.d.ts +539 -0
  273. package/dist/prompts/simple-sections.d.ts +45 -0
  274. package/dist/prompts/supervisor.d.ts +66 -0
  275. package/dist/scenarios/env.d.ts +28 -0
  276. package/dist/scenarios/full-body.d.ts +50 -0
  277. package/dist/scenarios/scenario-registry.d.ts +60 -0
  278. package/dist/scenarios/teacher-quickstart.d.ts +27 -0
  279. package/dist/server/http.d.ts +17 -0
  280. package/dist/stores/cc/lockfile.d.ts +6 -0
  281. package/dist/stores/cc/mailbox-store.d.ts +8 -0
  282. package/dist/stores/cc/roster-adapter.d.ts +4 -0
  283. package/dist/stores/cc/sidecar-transcript.d.ts +66 -0
  284. package/dist/stores/file/background-agent-store.d.ts +24 -0
  285. package/dist/stores/file/background-agent-store.js +2 -1
  286. package/dist/stores/file/checkpoint-store.d.ts +38 -0
  287. package/dist/stores/file/file-snapshot-store.d.ts +25 -0
  288. package/dist/stores/file/fs-atomic.d.ts +155 -0
  289. package/dist/stores/file/index.d.ts +89 -0
  290. package/dist/stores/file/mailbox-store.d.ts +36 -0
  291. package/dist/stores/file/mailbox-store.js +2 -0
  292. package/dist/stores/file/memory-store.d.ts +82 -0
  293. package/dist/stores/file/permission-rule-store.d.ts +79 -0
  294. package/dist/stores/file/session-policy-store.d.ts +28 -0
  295. package/dist/stores/file/session-store.d.ts +40 -0
  296. package/dist/stores/file/shared-ledger.d.ts +83 -0
  297. package/dist/stores/file/tool-result-store.d.ts +11 -0
  298. package/dist/stores/file/usage-window-store.d.ts +18 -0
  299. package/dist/stores/file/workflow-journal-store.d.ts +100 -0
  300. package/dist/stores/file/workflow-run-store.d.ts +11 -0
  301. package/dist/stores/file/workflow-run-store.js +2 -0
  302. package/dist/tools/fs/bash-readonly-classifier.d.ts +282 -0
  303. package/dist/tools/fs/encoding.d.ts +60 -0
  304. package/dist/tools/fs/fs-bash.d.ts +133 -0
  305. package/dist/tools/fs/fs-pdf.d.ts +28 -0
  306. package/dist/tools/fs/fs-search-tools.d.ts +5 -0
  307. package/dist/tools/fs/fs-shared.d.ts +360 -0
  308. package/dist/tools/fs/fs-write.d.ts +16 -0
  309. package/dist/tools/fs/gh-rate-limit.d.ts +22 -0
  310. package/dist/tools/fs/index.d.ts +79 -0
  311. package/dist/tools/fs/notebook.d.ts +56 -0
  312. package/dist/tools/fs/pdf.d.ts +70 -0
  313. package/dist/tools/fs/pdf.js +8 -2
  314. package/dist/tools/fs/repo-map.d.ts +10 -0
  315. package/dist/tools/fs/safety.d.ts +376 -0
  316. package/dist/tools/fs/search.d.ts +131 -0
  317. package/dist/tools/loop-tick.d.ts +24 -0
  318. package/dist/tools/monitor.d.ts +55 -0
  319. package/dist/tools/scheduler-tools.d.ts +51 -0
  320. package/dist/tools/sql-adapters.d.ts +18 -0
  321. package/dist/tools/sql.d.ts +25 -0
  322. package/dist/tools/task-list.d.ts +77 -0
  323. package/dist/tools/todo.d.ts +8 -0
  324. package/dist/tools/web.d.ts +184 -0
  325. package/dist/tools/web.js +32 -5
  326. package/dist/tools/worktree.d.ts +81 -0
  327. package/package.json +2 -2
  328. package/dist/tools/gitea-issue.d.ts +0 -13
  329. package/dist/tools/gitea-issue.js +0 -75
@@ -1,18 +1,133 @@
1
+ /** A tool call presented to a policy before it executes. */
1
2
  export interface ToolCallRequest {
2
3
  toolName: string;
3
4
  args: unknown;
4
5
  toolCallId: string;
6
+ /**
7
+ * RB-108 — the LIVE working directory this call's RELATIVE path arguments will actually resolve
8
+ * against, read at adjudication time from the same tracked `cwdRef` the fs hand tools resolve with
9
+ * (design/64 §16.3: a resident shell's `cd` persists and moves the fs tools' relative base with it).
10
+ *
11
+ * WHY IT EXISTS: every path guard here (sensitive-path, fs-write gate, session rules, skill scope,
12
+ * transcript integrity) re-resolves the model's spelling itself, and each was handed a STATIC root at
13
+ * wiring time. After a `cd` the two sides of a single call disagreed about which file it was: the tool
14
+ * wrote `<liveCwd>/pre-commit` while the guard judged `<wiringRoot>/pre-commit` — measured on a host
15
+ * lane, `cd .git/hooks` + `Write("pre-commit")` landed a git hook past a guard that names `.git/hooks`.
16
+ * Reading THIS field makes the guard's resolution base the same value the tool will use.
17
+ *
18
+ * Applies to the call's TARGET only. A guard's own configured directories (accept/exempt domains,
19
+ * `allowDirs`, manifest `allowPaths`) are DEPLOYMENT text and keep resolving against the static root —
20
+ * a shell `cd` must never relocate an allow-domain.
21
+ *
22
+ * ABSENT when the run has no tracked cwd (read-only hands, no execution env) or when a policy is
23
+ * invoked directly outside a Runner: consumers then fall back to their own configured root, which is
24
+ * exactly the pre-RB-108 behavior. Read-only — a policy cannot move the shell by writing it back.
25
+ *
26
+ * RESIDUAL (recorded honestly — this is a snapshot of a mutable ref, not a frozen binding): the gate
27
+ * reads the ref when it adjudicates and the tool reads it again when it executes. No interleaving that
28
+ * moves the cwd in between is constructible on the current loop, and it is worth naming WHY, because
29
+ * the reason is a property of the tool declarations rather than of this field: the loop adjudicates a
30
+ * whole batch before executing it, but only calls classified concurrency-safe ever share a batch, and
31
+ * every cwd MOVER (a `cd`-bearing Bash — `cd` is not on the readonly allowlist and any shell operator
32
+ * disqualifies — plus the worktree enter/exit tools) and every path-confinable WRITE tool declares
33
+ * `effect: "write"`, which derives `executionMode: "sequential"`, which forces a batch of one. A
34
+ * deployment tool that declared itself read/parallel while moving the shared cwd would reopen the
35
+ * window — at that declaration, not here.
36
+ */
5
37
  cwd?: string;
38
+ /**
39
+ * design/80 D-E-core: read-only per-run budget snapshot so a STATELESS policy can self-limit against
40
+ * state that survives suspend/resume (a fresh in-memory counter would reset every leg — the supervisor
41
+ * escalation-budget gap). Built by core at prepare time from the DURABLE resource ledger
42
+ * ({@link import("./checkpoint-store.js").ResourceLedger}) + the durable suspend chain; the policy CANNOT
43
+ * widen it (no write-back). Present on every gated `check()` once the runner builds the gate; absent only
44
+ * when a policy is invoked directly (outside a Runner). A NORMAL-ask escalation policy reads it; a SAFETY
45
+ * ask (egress / irreversible) ignores it and ALWAYS asks (invariant #2 stays structural — core mints
46
+ * `irreversible_ask` for safety tools regardless of any budget).
47
+ */
6
48
  budget?: {
49
+ /**
50
+ * Durable resource $ this run may STILL spend (micro-USD); `undefined` = no $ ceiling configured. Frozen
51
+ * total, prior-wins → it monotonically SHRINKS across legs and is NEVER re-granted by a resume (a
52
+ * deny-resume continues with the same frozen remaining). **NEVER falsy-test** (`0` = exhausted, NOT
53
+ * "unlimited" — only `undefined` is unlimited).
54
+ */
7
55
  resourceRemainingMicroUsd?: number;
56
+ /** Durable cumulative resource $ already spent across all prior legs (micro-USD); accumulates, never refunded. */
8
57
  resourceSpentMicroUsd: number;
58
+ /** How many times this run has already suspended (the durable suspend chain). Lets the policy tighten as
59
+ * the chain grows — the precise complement to the unconditional `suspendLoopCap` backstop. */
9
60
  suspendCount: number;
10
61
  };
11
62
  }
63
+ /** Where a decision came from, for audit (design/37). */
12
64
  export type DecisionReason = "rule" | "mode" | "hook" | "safety" | "classifier" | "persisted_rule";
65
+ /**
66
+ * WHO (or what) ENDED an approval — the machine-readable twin of a settlement's human-readable text,
67
+ * so a consumer tells "a person decided this" from "nobody answered" without prose-matching a sentence.
68
+ * The sibling axis of {@link DecisionReason}, which says which LAYER produced a verdict; this one says
69
+ * what ended the WAIT.
70
+ *
71
+ * - `"human"` — a person, or the approver acting for one, returned a final verdict (allow or deny).
72
+ * - `"timeout"` — the configured approval window elapsed with no answer.
73
+ * - `"aborted"` — every other NON-HUMAN end: the task aborted, the approver threw or reported nobody
74
+ * reachable, the decision arrived out of contract, a store or transport gave way, retries ran out.
75
+ *
76
+ * The three words are exhaustive and mutually exclusive over the ways an approval can end, and the
77
+ * minimum discrimination a consumer needs — someone refused vs nobody answered — is `"human"` vs the
78
+ * other two.
79
+ *
80
+ * **Fill it AT the settlement site.** Each site knows its own cause and names it; deriving the value
81
+ * afterwards from whatever outcome happens to be at hand is exactly how a window that elapsed comes to
82
+ * be reported as a person's refusal.
83
+ *
84
+ * ABSENT means this settlement named no source: an older caller that predates the field, or a verdict
85
+ * that settled no wait at all (a policy POSTURE — headless auto-deny, a blanket bypass — where nobody
86
+ * was ever asked). A consumer MUST NOT read a semantic out of the absence; render the text instead.
87
+ */
13
88
  export type ApprovalSettledBy = "human" | "timeout" | "aborted";
89
+ /** The closed set above, for runtime domain checks at the seams that accept a caller-supplied value. */
14
90
  export declare const APPROVAL_SETTLED_BY_VALUES: readonly ApprovalSettledBy[];
91
+ /** True iff `v` is one of the three {@link ApprovalSettledBy} words. */
15
92
  export declare function isApprovalSettledBy(v: unknown): v is ApprovalSettledBy;
93
+ /**
94
+ * A three-state permission decision for a tool call (design/37). Upgrades the old two-state
95
+ * `{allow|deny}`:
96
+ * - `allow` may carry `updatedInput` — REWRITTEN args (redact a secret, clamp a path/value) that
97
+ * REPLACE the model's args before execution (re-validated against the tool schema first).
98
+ * `deny` may ALSO carry `updatedInput` (1.256 复审 MED-2): it never executes anything, but a
99
+ * combined-policy deny reports the ACCUMULATED pre-deny rewrite (policy A redacted → policy B
100
+ * denied) so a deny OBSERVER (`Hooks.permissionDenied`) sees the final post-rewrite args, not the
101
+ * stale un-redacted ones.
102
+ * - `ask` requests human confirmation; with no approver wired it resolves deterministically to deny
103
+ * (headless auto-deny, see `RunnerDeps.onAsk`). `requiresRealApproval: true` (RB-203 codex review,
104
+ * confirmed P1) additionally refuses to let a BLANKET `onAsk: "allow"` bypass clear it — that
105
+ * configuration is "no approver looked at this at all", indistinguishable from headless, for a rule
106
+ * whose whole point is that a blanket policy setting must not be the thing that clears it (see
107
+ * {@link resolveAsk}). A live auto-mode classifier verdict (tried earlier in the gate, if configured)
108
+ * or a genuine approver CALLBACK (actual judgment, even if it always says yes) still can.
109
+ * - `deny` blocks the call.
110
+ * Human-readable text is `message`; read it via {@link decisionText}.
111
+ *
112
+ * The two TERMINAL arms may also carry {@link ApprovalSettledBy} as `settledBy` — what ended the wait,
113
+ * when this verdict ended one. It is on `allow`/`deny` and deliberately NOT on `ask`: an `ask` has
114
+ * settled nothing yet, so a source there would name a decider who has not decided. A layer that never
115
+ * waited for anyone omits it (see the type's ABSENT clause).
116
+ * RB-479-B① (ruled 2026-08-02): the legacy `reason` field is REMOVED — one name for one thing.
117
+ *
118
+ * How far the TYPE carries that retirement (measured 2026-08-03, correcting this note's earlier claim
119
+ * that a policy returning `{reason}` "compiles red for TS consumers"): TypeScript's excess-property
120
+ * check fires only where the decision is a LITERAL in an ANNOTATED position — `const d: PermissionResult
121
+ * = {…}`, or a `check` written with an explicit `: PermissionResult` return annotation. The ordinary
122
+ * policy shape, `{ check: () => ({…}) }` with an INFERRED return type (also the method-syntax and
123
+ * assign-then-return forms), compiles GREEN with a stray `reason`. That is not a hole to plug in the
124
+ * type system — it is how contextual typing works — so the enforcement is at RUNTIME instead: every
125
+ * point that CONSUMES a decision REFUSES one carrying an own `reason` property, fail-closed (deny, with
126
+ * a migration message) — the {@link combinePolicies} fold, the PreToolUse hook face, and the durable
127
+ * resume-edit rechecks (see {@link refuseOutOfContractDecision}). Same doctrine as the strict `approve`
128
+ * / `onAsk` folds in this file: an out-of-contract value on the permission face is a loud rejection,
129
+ * never a best-effort read.
130
+ */
16
131
  export type PermissionResult = {
17
132
  action: "allow";
18
133
  updatedInput?: unknown;
@@ -32,87 +147,482 @@ export type PermissionResult = {
32
147
  decisionReason?: DecisionReason;
33
148
  settledBy?: ApprovalSettledBy;
34
149
  };
150
+ /** The human/model-readable text of a decision. */
35
151
  export declare function decisionText(d: PermissionResult): string | undefined;
152
+ /**
153
+ * Gates tool calls before they execute (the production safety layer for "processing/changing data").
154
+ *
155
+ * `check` runs before each tool call. Return `{ action: "deny", message }` to block it — the model
156
+ * receives an error tool result with the reason and can continue or report blocked. Return
157
+ * `{ action: "allow" }` to permit it.
158
+ *
159
+ * `check` may be async, which is also how **human-in-the-loop approval** works: a deployment can
160
+ * hold the promise open until an operator approves/denies. `signal` fires when the task aborts
161
+ * (timeout / max turns / cancel) — honor it to release a pending approval instead of hanging (F4).
162
+ * The Runner also races `check` against `signal` itself, so a policy that ignores it still cannot
163
+ * hang the worker past the deadline; passing it through just lets you clean up the wait early.
164
+ */
36
165
  export interface ToolPolicy {
37
166
  check(req: ToolCallRequest, signal?: AbortSignal): PermissionResult | Promise<PermissionResult>;
38
167
  }
168
+ /**
169
+ * Refuse a decision that speaks the retired `reason` dialect (RB-479-B①, tripwire ruled 2026-08-03).
170
+ *
171
+ * Applied at every point a decision is CONSUMED, because no single fold sees them all (ruled
172
+ * 2026-08-03): {@link combinePolicies} (the runner's gate path), the PreToolUse hook's result seam
173
+ * (`hooks.ts` — a hook result reaches the gate decision without ever passing through a fold), and the
174
+ * durable resume-edit rechecks (`runtask.ts` — direct `check()` calls on the caller's own policy). The
175
+ * wording is face-neutral for that reason: one construction point, three consumers. The export exists
176
+ * for those two engine modules only and is deliberately NOT re-exported from `src/index.ts`: this is an
177
+ * internal screen on inputs the engine receives, not a facility deployments call.
178
+ *
179
+ * Why this is a DENY and not a best-effort read of the old field: the retirement is settled, so the
180
+ * value is out-of-contract input to the permission face — the same class as an untyped `approve`
181
+ * returning a truthy non-`true`, which this file already refuses fail-closed. Reading the old name
182
+ * anyway would re-open the two-names-for-one-thing surface; ignoring it (the pre-tripwire behavior)
183
+ * silently dropped the policy's own text and returned the per-site generic default, so a deployment
184
+ * whose deny messages had quietly degraded looked healthy. The type system cannot carry this alone —
185
+ * excess-property checking does not reach an inferred `check` return (see {@link PermissionResult}).
186
+ *
187
+ * OWN property only (`hasOwnProperty`, not `in`): a decision whose PROTOTYPE happens to expose
188
+ * `reason` never wrote the retired field. A non-object decision is passed through untouched — reading
189
+ * `.action` off it is the caller's existing failure, and inventing a second failure mode here would
190
+ * change which error a broken policy raises.
191
+ *
192
+ * Any accumulated `updatedInput` is deliberately NOT carried onto this deny: it came from the same
193
+ * out-of-contract decision object, so it is not a rewrite this layer is willing to report as audited.
194
+ * (A rewrite from an EARLIER, contract-shaped policy still rides out — {@link combinePolicies} adds it
195
+ * on the deny path per the observer contract.)
196
+ */
39
197
  export declare function refuseOutOfContractDecision(d: PermissionResult): PermissionResult;
198
+ /** The raw tool-name lists a name-keyed policy was built from (audit feed, see block note above). */
40
199
  export interface ToolPolicyNameSets {
41
200
  readonly allow?: readonly string[];
42
201
  readonly deny?: readonly string[];
202
+ /** Names gated behind an approval decision ({@link createApprovalPolicy.requireApproval}) — a typo
203
+ * here silently WIDENS (the tool runs without ever asking), so it is audited too. */
43
204
  readonly ask?: readonly string[];
44
205
  }
206
+ /** A policy that exposes its name lists for the host-side pool audit. Composition-transparent:
207
+ * {@link combinePolicies} (and therefore {@link tightenTaskSpec}) unions children's groups onto the
208
+ * combined policy, so metadata survives the deployment's tighten/compose path. */
45
209
  export type NamedToolPolicy = ToolPolicy & {
46
210
  readonly nameSets: readonly ToolPolicyNameSets[];
47
211
  };
212
+ /** All name-set groups reachable on `p` — `[]` when it carries none (e.g. a custom closure policy,
213
+ * which simply opts out of the audit). */
48
214
  export declare function toolPolicyNameSets(p: ToolPolicy | undefined): readonly ToolPolicyNameSets[];
215
+ /**
216
+ * Name-based allow/deny. `deny` always wins. If `allow` is provided, only those tools are permitted
217
+ * (everything else denied). Without `allow`, everything not in `deny` is permitted.
218
+ * Carries {@link NamedToolPolicy.nameSets} so the host can audit the raw lists against the mounted
219
+ * pool ([c209-E] advisory); enforcement semantics are unchanged.
220
+ */
49
221
  export declare function createAllowDenyPolicy(opts: {
50
222
  allow?: string[];
51
223
  deny?: string[];
224
+ /**
225
+ * What to do with an entry that is not a tool NAME but a rule CONTENT form (`Bash(ps:*)`, `Edit(src/**)`).
226
+ * `"throw"` (default, matching {@link createPermissionRulePolicy}'s posture toward a rule it cannot
227
+ * compile) refuses at construction; `"skip"` drops the entry and reports it. Under BOTH, the entry never
228
+ * silently narrows the allowlist.
229
+ */
52
230
  onInvalidName?: "throw" | "skip";
231
+ /** Called once per dropped entry under `"skip"`. */
53
232
  onInvalidNameIssue?: (issue: {
54
233
  entry: string;
55
234
  list: "allow" | "deny";
56
235
  message: string;
57
236
  }) => void;
58
237
  }): NamedToolPolicy;
238
+ /**
239
+ * Human-in-the-loop approval for selected tools. Tools in `requireApproval` call `approve(req)` and
240
+ * are allowed only if it resolves true; tools in `deny` are always blocked; everything else is allowed
241
+ * (override with `denyByDefault: true` to allow only `requireApproval` + an explicit `autoAllow`).
242
+ */
59
243
  export declare function createApprovalPolicy(opts: {
244
+ /** Tools that need an approval decision. */
60
245
  requireApproval: string[];
246
+ /**
247
+ * The approval decision (e.g. await an operator). Resolve true to allow, false to deny. `signal`
248
+ * fires when the task aborts — race your wait against it (e.g. an OA approval callback) so a
249
+ * never-answered request is released at the deadline rather than holding the worker.
250
+ */
61
251
  approve: (req: ToolCallRequest, signal?: AbortSignal) => boolean | Promise<boolean>;
252
+ /** Always-denied tools. */
62
253
  deny?: string[];
254
+ /** Always-allowed tools (only meaningful with `denyByDefault`). */
63
255
  autoAllow?: string[];
256
+ /** When true, deny anything not in `requireApproval` or `autoAllow`. Default false. */
64
257
  denyByDefault?: boolean;
258
+ /**
259
+ * Optional self-contained deadline (ms): if `approve` hasn't resolved by then, deny. Belt-and-
260
+ * suspenders for **direct** callers — the Runner already races `check` against the task signal, so
261
+ * a Runner-driven task is bounded regardless; this protects a caller invoking `check()` without a
262
+ * signal. OMIT to wait indefinitely on `approve` — omission is the only spelling of "no deadline"
263
+ * (CLS-A-9): a written-down `0` is the tightest deadline (deny at once), and a non-finite value is
264
+ * refused at construction.
265
+ */
65
266
  approvalTimeoutMs?: number;
66
267
  }): NamedToolPolicy;
268
+ /**
269
+ * Combine policies with the three-state fold **deny > ask > allow** (design/37): the WORST outcome
270
+ * across all policies wins. A `deny` short-circuits (nothing can override it); an `ask` does NOT
271
+ * short-circuit — scanning continues, because a later policy may still `deny` (which outranks ask).
272
+ * With no deny, the first `ask` wins; with neither, `allow`.
273
+ *
274
+ * **Idempotency requirement:** because the fold continues past an `ask` to look for a later `deny`, a
275
+ * policy's `check()` can be invoked even after an earlier policy returned `ask`. `check()` MUST be
276
+ * idempotent — repeated calls with the same {@link ToolCallRequest} return the same decision and
277
+ * accumulate no side effects (e.g. don't fire a duplicate approval notification on each call).
278
+ */
67
279
  export declare function combinePolicies(...policies: ToolPolicy[]): ToolPolicy;
280
+ /**
281
+ * The shell tools whose `{ command }` arg a coarse command-name policy parses. Other tools are out of scope.
282
+ *
283
+ * RB-130 (2026-07-25, defect probe): `Monitor` belongs here. It takes a `command` and runs it through the
284
+ * SAME `env.spawnBackground` seam as Bash, and prepare-task's own note says so in as many words — "Monitor
285
+ * runs an arbitrary shell `command` through the SAME env seam — it must sit behind the SAME shellGate
286
+ * tighten (else it becomes a policy side-door around a gated Bash)". The shellGate half was implemented;
287
+ * this half — the two ALWAYS-ON, core-owned parity gates that a caller's policy cannot remove — was keyed
288
+ * on a list containing only "Bash". The probe drove the whole thing end to end: the identical
289
+ * `rm -rf $(cat targets)` was denied as Bash and executed as Monitor, deleting a real directory with no
290
+ * gate at all; the same substitution makes `rm -rf ~/.ai-agent/sessions` a way to erase the audit trail.
291
+ */
292
+ /**
293
+ * RB-153 (server [1708]): EXPORTED. A downstream governance layer keeps its own copy of this list so its
294
+ * per-command ask-list gates the same tools core does, and it had no way to read the real one — its guard
295
+ * had to probe a hand-written candidate list of names, which stays green for any name nobody thought to
296
+ * put in it. The list itself is the fact; publishing it removes the guess.
297
+ */
68
298
  export declare const COARSE_SHELL_TOOLS: string[];
299
+ /**
300
+ * design/center §10 — a COARSE allow/deny gate keyed on the LEADING command NAME (`argv[0]`) of a single
301
+ * simple shell command. It reuses the ONE shared simple-command parser
302
+ * ({@link import("../tools/fs/index.js").parseLeadingCommandName}) — it does NOT re-implement argv[0] parsing
303
+ * (a second parser would drift and open a bypass). For a `bash`/`bash_readonly` call it extracts the leading
304
+ * command name and:
305
+ * - if the name is in `deny` → `deny` (deny-wins, matching {@link createAllowDenyPolicy}; NOT last-match-wins,
306
+ * which would fight {@link combinePolicies}'s deny>ask>allow fold);
307
+ * - else if `allow` is provided and the name is NOT in it → `defaultAction` (`"ask"` default, or `"deny"`);
308
+ * - else → `allow`.
309
+ * A command the parser cannot reduce to a single bare name (it has shell operators / a path-prefix / a leading
310
+ * env-assignment) is treated by `defaultAction` (fail-toward-gate): such a command is exactly what would bypass
311
+ * an argv[0] filter, so it should not silently `allow`. NON-shell tools are out of scope → `allow` (this gate
312
+ * only speaks about shell command names; compose it with other policies for the rest).
313
+ *
314
+ * **core ships NO opinionated command list** — only this mechanism. The actual `allow`/`deny` rule set is
315
+ * injected by the profile/config/deployment.
316
+ *
317
+ * ⚠️ **NOT A SANDBOX — coarse filter / defense-in-depth only.** This matches `argv[0]` NAME and nothing else,
318
+ * so the bypass surface is large and the gate MUST NOT be relied on as containment:
319
+ * - command substitution / subshells (`$(curl …)`, backticks), pipes, redirects, `;`/`&&` chaining — all
320
+ * rejected as un-parseable here (→ `defaultAction`), so they don't sneak past `allow`, but that is a GATE
321
+ * not a guarantee of safety;
322
+ * - an indirection wrapper runs an arbitrary inner program under an allowlisted `argv[0]`: `sh -c '…'`,
323
+ * `env FOO=bar curl …`, `sudo rm …`, `timeout 5 curl …`, `xargs curl`, `find . -exec rm {} \;`,
324
+ * `python -c '…'`, `npm run <script>`, `git <subcommand>` — the inner action is INVISIBLE to an
325
+ * argv[0]-name filter. Allowlisting any such wrapper effectively allowlists everything it can launch.
326
+ * Real isolation is the deployment's sandboxed `executionEnv` (a remote/E2B container with no egress, a
327
+ * read-only FS, dropped capabilities). Use this only as a cheap first-line coarse filter layered over that.
328
+ *
329
+ * 🪤 **TRAP #1 — `TaskSpec.toolPolicy` OVERRIDES (does not merge) `RunnerDeps.toolPolicy`.** A consumer that
330
+ * sets `TaskSpec.toolPolicy = createCoarseCommandNamePolicy(…)` directly **silently discards the deployment's
331
+ * baseline policy** (the runner does `spec.toolPolicy ?? deps.toolPolicy`). To LAYER this on top of a baseline
332
+ * you MUST compose explicitly: `combinePolicies(deploymentBaseline, createCoarseCommandNamePolicy(…))`
333
+ * (deny-wins — both policies' denies still fire). {@link tightenTaskSpec} does this for you.
334
+ *
335
+ * 🪤 **TRAP #2 — under `TaskSpec.shellGate: "classify"`, a plain `ask` from this policy is promoted to a
336
+ * NON-budgetable `irreversible_ask`.** `shellGate:"classify"` statically marks `bash` `irreversibility:"maybe"`;
337
+ * the safety gate keys the checkpoint axis on that STATIC tool mark (not on `decisionReason`), so a `bash`
338
+ * command that doesn't prove reversible suspends as `irreversible_ask` — which a budget-aware escalation
339
+ * resolver will NEVER auto-approve. Net: combining this policy's `ask` with `shellGate:"classify"` does NOT
340
+ * give you a budgetable normal-ask on `bash`; it gives a hard human-approval suspend. Choose `shellGate` and a
341
+ * `defaultAction:"ask"` deliberately.
342
+ */
69
343
  export declare function createCoarseCommandNamePolicy(opts: {
344
+ /** Command names (argv[0]) explicitly allowed. If provided, a name NOT listed falls to `defaultAction`. */
70
345
  allow?: string[];
346
+ /** Command names (argv[0]) explicitly denied — `deny` always wins (checked before `allow`). */
71
347
  deny?: string[];
348
+ /** What to do for a command not matched by `allow` (or un-parseable): `"ask"` (default) or `"deny"`. */
72
349
  defaultAction?: "ask" | "deny";
350
+ /** Override the shell tool names this gate parses (default `Bash` — bash + bash_readonly share the CC name). */
73
351
  tools?: string[];
74
352
  }): ToolPolicy;
75
353
  export declare function findUnverifiableRecursiveDelete(command: string, safeVars?: ReadonlySet<string>): string | undefined;
354
+ /**
355
+ * CC 220 "Unverifiable Deletion Target" parity (auto-mode rule): ASK on a recursive+forced delete whose
356
+ * target is a variable / substitution that cannot be resolved from the command itself — fail-closed in the
357
+ * sense that with no live classifier/approver the ask degrades to deny (see {@link PermissionResult}'s
358
+ * `ask` doc), never to allow. See {@link findUnverifiableRecursiveDelete} for exact firing conditions. The
359
+ * message carries the CC-sanctioned remediation (re-run with the resolved LITERAL path written into the
360
+ * command, or assign the variable in the same command) — it doubles as the `askMessage` a classifier sees.
361
+ *
362
+ * RB-203 (2026-07-26): this used to be an unconditional `deny`, on the theory that the CC rule text forbids
363
+ * auto-allow («must be explicitly approved … cannot be auto-allowed by a permission rule»).
364
+ *
365
+ * RB-341 (2026-07-29) re-checked that citation against the 220 corpus and corrected it in BOTH directions.
366
+ * The RB-203 note claimed the phrase "traces to the 206 bundle; it does not appear anywhere in the 220
367
+ * corpus for THIS rule" — that sentence was wrong and is retracted. The phrase has 8 hits in 220, and two
368
+ * of them are this exact rule's own message text: `pretty220` 461365 (the `rm -rf $UNSET/*`
369
+ * variable-expansion arm, verbatim «e.g. `rm -rf $UNSET/*` becomes `rm -rf /*`. This requires explicit
370
+ * approval and cannot be auto-allowed by permission rules.») and 461444 (its command-substitution twin).
371
+ * Five more are the sibling deterministic `rm`/`rmdir` arms (457337/457364/457379/457387/457402) and one is
372
+ * an unrelated `find` rule (249564).
373
+ *
374
+ * The `ask` decision survives that correction, on a stronger anchor than the one RB-203 used:
375
+ *
376
+ * - **It is not a deny in 220 either.** Every one of those messages is built by the same constructor
377
+ * (`T7e`, 457298), whose `behavior` is literally `"ask"` — a deterministic gate that ASKS. The phrase
378
+ * scopes to permission RULES: no static allow rule may clear the gate. sema's equivalent is
379
+ * `combinePolicies`'s deny > ask > allow fold — an `allow` from any composed policy loses to this ask,
380
+ * in either composition order (pinned in tool-policy.test.ts).
381
+ * - **A live classifier MAY clear it, in 220 as here.** `T7e` marks the reason `classifierApprovable:
382
+ * false`, but pairs it with `circuitBreaker: "dangerousRemoval"`, and 220's auto-mode gate diverts an
383
+ * ask away from the classifier only when `!classifierApprovable && !(circuitBreaker !== undefined &&
384
+ * isAutoModePermissionSurface(ctx))` (604049-604053). The circuit-breaker arm exempts exactly this
385
+ * family, so on the auto-mode surface the classifier DOES adjudicate it. That is consistent with the
386
+ * rule's listing in the classifier prompt's **SOFT BLOCK** bucket ("destructive or irreversible — User
387
+ * Intent Rule CAN clear these", 519698 / rule text 519726), escapable when the user's own words (or an
388
+ * agent proposal they affirmed) name the exact target — the same design sema's classifier prompt already
389
+ * implements verbatim (`auto-mode-prompt-assets.ts`, unchanged). A `classifierApprovable:false` reason
390
+ * WITHOUT a `circuitBreaker` is the shape that genuinely forbids the classifier — e.g. the design-agent
391
+ * consent ASK at 480999/481016, which takes the fallback-to-human path this rule does not. This rule is
392
+ * not that shape, so "follow `classifierApprovable:false` literally" would be STRICTER than CC.
393
+ *
394
+ * So a hard `deny` was wrong twice over: it short-circuited `combinePolicies`'s fold before a live
395
+ * classifier ever ran, and CC's classifier does run here. `ask` reuses the existing generic per-ask
396
+ * classifier arm (`hooks.ts`, `decision.action === "ask"`): a `block` verdict still denies
397
+ * (`decisionReason: "classifier"`, fully audited), an `allow` verdict still requires a live classifier to
398
+ * have actually cleared it, and "no classifier configured" still means deny.
399
+ *
400
+ * codex review (confirmed P1): the one piece of NEW plumbing this DOES need — `requiresRealApproval: true`
401
+ * (see {@link PermissionResult}'s `ask` doc) — closes a real gap the first cut of this fix missed. A
402
+ * deployment using the documented `onAsk: "allow"` bypass mode (sandbox-is-the-boundary posture, the
403
+ * shape a sandboxed autonomy container runs) would otherwise have this rule's `ask` rubber-stamped by that blanket
404
+ * configuration with NO classifier ever consulted and NO judgment of any kind applied — silently WEAKER
405
+ * than the unconditional deny it replaced, for exactly the deployments that opted into the most permissive
406
+ * mode for OTHER, unrelated reasons. `requiresRealApproval` makes `resolveAsk` treat a blanket
407
+ * `onAsk:"allow"` as equivalent to no approver at all for this specific ask (deny, same as headless) while
408
+ * leaving every other path untouched: a live classifier (tried first, unaffected), a real approver
409
+ * CALLBACK (genuine per-call judgment, even one that usually says yes), and "no classifier + no approver"
410
+ * (already denied). Core wires this policy ALWAYS-ON in the runner's gate composition (prepare-task); it is
411
+ * exported so deployments can also compose/test it directly.
412
+ *
413
+ * RB-341: `requiresRealApproval` also turns out to be the correct sema analog of the one thing
414
+ * `classifierApprovable: false` still buys in 220 that a `circuitBreaker` does NOT take back — 220's
415
+ * bypassPermissions arm refuses to auto-allow an ask carrying `circuitBreaker === "dangerousRemoval"`
416
+ * (603856-603869), i.e. a blanket MODE setting cannot clear it, only judgment can. That is exactly the
417
+ * `onAsk:"allow"` refusal above, so no new hard bit is owed. The field's remaining 220 effects have no core
418
+ * surface to attach to: it suppresses the "always allow / don't ask again" affordance in the CC permission
419
+ * dialog (908517 / 909563) and re-attaches a matching user `ask` rule on the auto-mode surface (461507).
420
+ * Core has neither a persisted always-allow surface nor rule re-attachment — noted for whichever UI layer
421
+ * grows one.
422
+ */
76
423
  export declare function createUnverifiableDeletePolicy(opts?: {
424
+ /** Extra variable names treated as well-known-safe roots, ADDED to the default set
425
+ * `TMPDIR`/`HOME`/`PWD` ({@link UNVERIFIABLE_DELETE_SAFE_VARS} — RB-396-a: this doc used to claim
426
+ * the default was `TMPDIR` alone, reading STRICTER than the gate really is; `HOME`/`PWD` are a
427
+ * registered sema divergence from CC's temp-only carve-out, see the RB-340 note there). */
77
428
  safeVars?: readonly string[];
429
+ /** Override the shell tool names this gate parses (default `Bash`). */
78
430
  tools?: string[];
79
431
  }): ToolPolicy;
80
432
  export declare function createTranscriptIntegrityPolicy(opts?: {
433
+ /** Transcript directories to protect. Default: `($AGENT_DATA_DIR ?? ~/.ai-agent)/sessions`. */
81
434
  sessionsDirs?: readonly string[];
435
+ /** argv[0] allowlist for read-only access to the transcript dir (default {@link BASH_READONLY_DEFAULT_ALLOW}). */
82
436
  readAllow?: readonly string[];
437
+ /** Override the shell tool names this gate parses (default `Bash`). */
83
438
  tools?: string[];
84
439
  }): ToolPolicy;
440
+ /**
441
+ * Provenance of the DELEGATION whose child raised an ask (ruled 2026-08-04) — filled by the delegation
442
+ * tool when it forwards the parent run's approver into a child, never by the child itself (it rides the
443
+ * trusted `ToolExecuteContext.onAsk` seat, which no tool argument reaches).
444
+ *
445
+ * The INNERMOST (issuing) frame wins: a grandchild's ask carries the grandchild's own spawn facts, not
446
+ * the intermediate one's — each delegation forwards an already-stamped request verbatim.
447
+ *
448
+ * Relation to the sibling source-identity fields on {@link AskRequest}: `fromSubagent`/`sourceAgentName`
449
+ * answer "a delegated child asked, and this is its display identity" from the CHILD's own prepare; this
450
+ * one answers "which delegation CALL it belongs to" from the SPAWNER's side — the correlation an approver
451
+ * UI needs to attach the approval card to the Agent card the operator is already looking at.
452
+ */
85
453
  export interface AskDelegationProvenance {
454
+ /** The spawning tool call in the PARENT run (`ToolExecuteContext.toolCallId` at spawn time) — the
455
+ * delegation's stable identity, minted by the engine. */
86
456
  readonly parentToolCallId: string;
457
+ /** Delegation nesting depth of the ISSUING child: 1 = a child of the run that owns the approver,
458
+ * 2 = its grandchild, … (as counted by the delegation-tool tree that spawned it). */
87
459
  readonly depth: number;
460
+ /** The explicit spawn name / agent-definition name of the issuing child, when it has one.
461
+ * **UNTRUSTED-for-display** (the spawning model chooses `name`): redact + bound before rendering,
462
+ * never adjudication input — same posture as {@link AskRequest.sourceAgentName}. */
88
463
  readonly agentName?: string;
89
464
  }
465
+ /** The structured context an `onAsk` approver receives for an `ask` decision (design/37). */
90
466
  export interface AskRequest {
91
467
  toolName: string;
92
468
  toolCallId: string;
469
+ /** The (post-rewrite) args the tool would run with. */
93
470
  args: unknown;
471
+ /** [1245] — the tool's approval display projection of {@link args} (AgentTool.approvalPreview),
472
+ * clamped + control-char-sanitized by the gate. **UNTRUSTED, ADVISORY display metadata**: render
473
+ * with contextual escaping and show {@link args} alongside — the preview can misrepresent the
474
+ * executable action and never replaces args. Never adjudication input. */
94
475
  readonly preview?: unknown;
476
+ /** Canonical digest of {@link args} as presented in THIS ask, computed by the engine's one
477
+ * `boundInputHashOf` — the same digest a durable park binds its checkpoint to, so an aggregating
478
+ * approver can reconcile a synchronous ask row against a parked checkpoint row for the same call
479
+ * by `(toolCallId, hash)` equality. RECONCILIATION metadata only, never adjudication input: it
480
+ * repeats for two asks over identical args, and an `updatedInput` edit round re-mints it over the
481
+ * edited args. Filled at the `resolveAsk` chokepoint (present for every wired-approver call, so a
482
+ * mint site added later is covered by construction); optional on the type because a deployment may
483
+ * invoke its approver function directly. */
95
484
  readonly boundInputHash?: string;
485
+ /**
486
+ * design/179 §4 — the persistable allow-rule forms this exact call could be covered by, so a surface can
487
+ * offer "allow, and stop asking me this" with something concrete behind it. Present only when a
488
+ * persisted allow-rule lane is armed AND the call is one the lane can speak for: a compound, a
489
+ * redirection or a substitution yields NO suggestion, which is the honest answer rather than an option
490
+ * that would be refused on redemption.
491
+ *
492
+ * ADVISORY display metadata, never adjudication input, and never a rule by itself: minting one is a
493
+ * separate act that goes through the approval-record protocol, so a surface that ignores this field
494
+ * changes nothing about what is allowed.
495
+ */
96
496
  readonly ruleSuggestions?: readonly import("./permission-rule-model.js").RuleSuggestion[];
497
+ /** The human/model-readable prompt explaining what needs approval. */
97
498
  message: string;
499
+ /** Runner-filled source identity (design S1d §1): the end-user {@link AskRequest} issuing task's
500
+ * `principal` (design/62). An AGGREGATING `onAsk` (one approver fanning over N delegated workers)
501
+ * attributes asks per-user by this. Worker/tool cannot set it (not a tool arg). Undefined ⇒ no principal.
502
+ * A non-aggregating `onAsk` simply ignores it (additive, no-op). `readonly`: Runner-populated metadata,
503
+ * not a caller/worker-settable field. Populated ONLY on the synchronous `resolveAsk`/`onAsk` path — a
504
+ * durable suspend/checkpoint flow does NOT invoke `onAsk` on the suspend side, so v1 ask-aggregation
505
+ * requires `checkpointStore` unset (design S1d §1.4 P-a). */
98
506
  readonly principal?: string;
507
+ /** Runner-filled source-task identity (= the issuing task's session id). An aggregating `onAsk` uses it
508
+ * to tell which worker an ask came from (nested grandchildren each carry their own session id).
509
+ * **worker-unforgeable for Runner-created delegated subagents** (a child never sets sessionId — the
510
+ * Runner mints it); a top-level caller MAY continue its own session id via `TaskSpec.sessionId`, so this
511
+ * is NOT a global "never forgeable" run id — aggregation only aggregates delegated workers, the context
512
+ * where it holds (design S1d §1.3). `readonly` + same sync-path-only / P-a caveat as `principal`.
513
+ * Undefined ⇒ no source task id. **NOT a subagent discriminator** ([1546] MED-1: the HOST's own asks
514
+ * carry it too — it is always the issuing task's session id); "from a background agent" attribution
515
+ * keys on {@link fromSubagent}, never on this field's presence. */
99
516
  readonly sourceTaskId?: string;
517
+ /** design/153 §1 (RB-39②) — Runner-filled: present (`true`) exactly when the gate raising this ask
518
+ * belongs to a DELEGATED SUBAGENT (the prepareTask `isSubagent` fact — trusted `internals.parentTaskId`
519
+ * presence; a child cannot forge or suppress it, internals never ride a TaskSpec). Undefined ⇒ the
520
+ * host / a top-level task. THE explicit "from a background agent" discriminator (replaces presence-
521
+ * or equality-heuristics on {@link sourceTaskId}). `readonly`, sync-path-only, S1d posture. */
100
522
  readonly fromSubagent?: true;
523
+ /** design/153 §1 — Runner-filled: the issuing task's display identity (a subagent's explicit agent
524
+ * name, else its agent-type; undefined for the host and unnamed children). **UNTRUSTED-for-display**
525
+ * (the spawning model chooses names): redact + bound before rendering; never adjudication input.
526
+ * `readonly`, same posture as {@link fromSubagent}. */
101
527
  readonly sourceAgentName?: string;
528
+ /** RB-203 (codex review, confirmed P1) — carried from the originating {@link PermissionResult}'s ask
529
+ * variant of the same name: `true` ⇒ {@link resolveAsk} must not let a blanket `onAsk: "allow"`
530
+ * clear this ask (see that field's doc). `readonly`, filled by the gate from the decision, never a
531
+ * caller/worker-settable field. */
102
532
  readonly requiresRealApproval?: boolean;
533
+ /** Engine-judged risk axes of the action awaiting approval, for the human decision surface: a
534
+ * coarse `requiresRealApproval` cannot tell "cannot be undone" from "data leaves the machine",
535
+ * and those call for different scrutiny. Filled by the gate from the SAME resolved axes the
536
+ * safety tightens read (tool declarations + caller `toolAxes` folds) — never derived from tool
537
+ * names, never caller/worker-settable. `irreversible: true` covers both the declared-`"always"`
538
+ * and the `"maybe"` (unproven-reversible) tiers. ABSENT — the whole object or either member —
539
+ * means the engine did not judge that axis: render it as unjudged, never fold absence to `false`. */
103
540
  readonly riskAxes?: {
104
541
  readonly irreversible?: boolean;
105
542
  readonly egress?: boolean;
106
543
  };
544
+ /** ruled 2026-08-04 — present exactly when this ask was raised inside a DELEGATED child whose approver
545
+ * is the ancestor run's (the `ToolExecuteContext.onAsk` seat the delegation tool forwards). Additive:
546
+ * an approver that ignores it is unaffected; a durable park/suspend flow never invokes `onAsk` at all,
547
+ * so this — like `principal`/`sourceTaskId` — exists only on the synchronous resolution path.
548
+ * See {@link AskDelegationProvenance} for the trust posture of each member. */
107
549
  readonly delegation?: AskDelegationProvenance;
108
550
  }
551
+ /**
552
+ * How an `ask` decision is resolved when a policy/hook requests human confirmation (design/37):
553
+ * - `"deny"` (and the default when omitted) — **headless auto-deny**: no approver, so `ask` resolves
554
+ * deterministically to `deny` with a model-readable reason. The safe default for stateless automation.
555
+ * - `"allow"` — auto-approve every `ask` (e.g. a trusted batch run).
556
+ * - a function — await an operator's decision (true=allow, false=deny). `signal` fires when the task
557
+ * aborts; race your wait against it so an unanswered ask is released at the deadline, not hung.
558
+ * G1 three-value ([871]①): the function may also return `"unavailable"` — an affirmative "no operator
559
+ * is reachable for THIS ask right now" (judged PER-ASK inside the callback, not at wire time). It is a
560
+ * ROUTING verdict, not a decision: the gate re-routes the ask onto the durable park leg (same behavior
561
+ * as if no live approver were wired — checkpoint + suspend, the 1.293 fallback), and when no park
562
+ * facility is armed the ask falls to the headless auto-deny (fail-closed). This lets a durable
563
+ * deployment wire ONE callback that serves live synchronous three-choice cards while attached AND
564
+ * still lands asks in the durable approval inbox when the operator goes away.
565
+ *
566
+ * **Contract:** the function MUST be fail-closed (a throw → deny, surfacing the real cause), idempotent
567
+ * for a given request, and tolerant of being called after the task signal aborted. `"unavailable"` MUST
568
+ * only be returned when NO operator interaction happened (a partial interaction that then reported
569
+ * unavailable could double-resolve the same approval once the park re-surfaces it).
570
+ */
109
571
  export type OnAsk = "deny" | "allow" | ((req: AskRequest, signal?: AbortSignal) => AskOutcome | Promise<AskOutcome>);
572
+ /**
573
+ * What an `onAsk` approver may return ([1458]/[1462] object arm):
574
+ * - `boolean` — plain verdict (true=allow, false=deny). STRICT fold (RB-482 #17, server bridge
575
+ * zero-ripple confirmed): only the literal `true` approves; an out-of-contract truthy from an
576
+ * untyped bridge is a fail-closed deny naming the defect (the historical truthy leniency was a
577
+ * fail-open on the security face with no live producer).
578
+ * - `"unavailable"` — the G1 per-ask routing verdict (see {@link OnAsk}).
579
+ * - `{ allow, updatedInput? }` — verdict PLUS an operator EDIT of the presented args
580
+ * (whole-replacement form, e.g. ctrl+g "edit script in $EDITOR"): the human approved a MODIFIED
581
+ * action, and executing the un-edited args would betray that consent. `allow` folds STRICTLY
582
+ * (`allow === true`) — an object arm is a deliberate caller, so no truthy leniency — and
583
+ * `updatedInput` is honored only on allow (a deny edit never executes anything). The edit is
584
+ * applied as the resolved decision's own rewrite: the gate re-validates it against the tool
585
+ * schema exactly like a hook/policy rewrite.
586
+ */
110
587
  export type AskOutcome = boolean | "unavailable" | {
111
588
  allow: boolean;
112
589
  updatedInput?: unknown;
113
590
  };
591
+ /**
592
+ * ruled 2026-08-04 — forward an approver into a delegated child, stamping every ask it raises with the
593
+ * delegation it came from ({@link AskDelegationProvenance}).
594
+ *
595
+ * Only the FUNCTION form is wrapped: `"allow"`/`"deny"` are policy SETTINGS, not approvers, and
596
+ * {@link resolveAsk} reads them structurally — wrapping would invent an approver where the deployment
597
+ * declared a blanket mode.
598
+ *
599
+ * An ask that ALREADY carries provenance passes through untouched: chained down a delegation tree, the
600
+ * INNERMOST (actually issuing) frame is the one the approver must see, and each outer hop would
601
+ * otherwise overwrite it with its own shallower one.
602
+ */
114
603
  export declare function withDelegationProvenance(onAsk: OnAsk, delegation: AskDelegationProvenance): OnAsk;
604
+ /**
605
+ * ruled 2026-08-04 — the APPROVER BEHIND a possibly-forwarded `onAsk`: the identity that answers
606
+ * "is this the same human/UI?" across delegation hops.
607
+ *
608
+ * Consumers compare approvers by function reference to decide whether one consultation's consent covers
609
+ * another (the RB-40 duplicate-frame collapse). A provenance wrapper is a different function object but
610
+ * the same decision-maker, so a bare `===` would ask one operator the same question twice for one tool
611
+ * call. Never used for authority (it grants nothing); only for "these two consultations are the same
612
+ * consultation". A non-wrapper value (including `"allow"`/`"deny"`/undefined) is its own identity.
613
+ */
115
614
  export declare function askApproverIdentity(onAsk: unknown): unknown;
615
+ /** EXACT structural clone for the approval boundary (alias isolation) — fail-closed, never lossy,
616
+ * never identity: a JSON round-trip would silently DROP unclonable members (presented ≠ executing =
617
+ * consent misrepresentation) and an identity fallback would hand the approver the live executing
618
+ * object (in-place mutation + TOCTOU). Tool args are model-JSON in practice, so failure is exotic —
619
+ * and exotic means deny, not leak.
620
+ *
621
+ * Exported for the DURABLE half of the same boundary (the runner's park mint): a checkpoint row holds
622
+ * the args a human will approve and a resume will execute, so it needs exactly this snapshot — and
623
+ * exactly this refusal when the value cannot be one. Not part of the package's public surface
624
+ * (index.ts does not re-export it); one implementation so the two halves cannot drift on what
625
+ * "safely presentable" means. */
116
626
  export declare function tryCloneArgs<T>(v: T): {
117
627
  ok: true;
118
628
  value: T;
@@ -121,9 +631,54 @@ export declare function tryCloneArgs<T>(v: T): {
121
631
  reason: string;
122
632
  cause?: unknown;
123
633
  };
634
+ /**
635
+ * A label for a value that was THROWN at us, safe to put in a fail-closed refusal. Never coerces: `String(x)`
636
+ * throws on a null-prototype object or a hostile `toString`/`Symbol.toPrimitive`, and the thrower here is
637
+ * deployment-supplied (a getter inside the args can throw any object at `structuredClone`, an approver can
638
+ * throw one at the gate). A coercion failure inside the catch would escape `resolveAsk` as a raw TypeError —
639
+ * turning a classified fail-closed DENY into an unclassified crash, i.e. the failing input escaping the very
640
+ * classification the refusal exists to give.
641
+ *
642
+ * The result is CONTAINED, not just described. Every caller interpolates it into a refusal that reaches
643
+ * the model inside a `<system-reminder>` frame, and the text is not ours: a `DataCloneError` renders the
644
+ * offending value INTO its message (`structuredClone` of a function yields that function's SOURCE), and
645
+ * a deployment approver throws whatever it likes. A rewrite handing over a function whose body contains
646
+ * `</system-reminder>` would otherwise close the trusted frame and continue as instructions — the exact
647
+ * threat `inlineUntrusted` exists for. So the description is one line, neutralized and capped here, at
648
+ * the single point where a thrown value becomes prose; the RAW exception is unaffected and still reaches
649
+ * the deployment's own error face, which is where an operator reads the untruncated story.
650
+ *
651
+ * Exported for the durable half of the same boundary (the runner's park mint), which now has a SECOND
652
+ * way a deployment-supplied value can throw at capture time — the target backend's own codec refusing to
653
+ * encode it. One containment point, so the two refusals cannot differ on how much of a hostile value's
654
+ * text they let through. Not part of the package's public surface.
655
+ */
124
656
  export declare function describeThrown(err: unknown): string;
657
+ /**
658
+ * A {@link resolveAsk} result: always a TERMINAL `allow`/`deny` (never `ask`). `approverUnavailable`
659
+ * is the out-of-band G1 three-value marker: the live approver returned `"unavailable"` for this ask —
660
+ * the carried `deny` is the FAIL-CLOSED FALLBACK, and the gate may instead re-route the ask onto the
661
+ * durable park leg (the only consumer; everywhere else the result reads as a plain deny).
662
+ */
125
663
  export type ResolvedAsk = PermissionResult & {
126
664
  approverUnavailable?: true;
665
+ /** [1462] r5 — the EXACT data snapshot the approver was shown (the `structuredClone` of the
666
+ * presented args). On a plain approval (no edit) the gate EXECUTES this snapshot, not the original
667
+ * object: a stateful getter or an external alias must not be able to make the executed action
668
+ * differ from the approved one (shown == executed, by construction). Set only on the
669
+ * function-approver path (string modes present nothing). */
127
670
  presentedInput?: unknown;
128
671
  };
672
+ /**
673
+ * Resolve an `ask` decision to a terminal `allow`/`deny` via {@link OnAsk}. Centralizes the headless
674
+ * auto-deny default, fail-closed error handling, and stable deny reasons so every ask site is
675
+ * consistent. Never returns `ask`.
676
+ *
677
+ * Every arm that ENDED A WAIT names what ended it ({@link ApprovalSettledBy}, per-arm, at the arm):
678
+ * the approver's own verdicts are `"human"`, and the fail-closed ends around them (abort, a throw, an
679
+ * "unavailable" report, an unclonable presentation, an out-of-contract value) are `"aborted"`. The
680
+ * three POSTURE arms at the top — blanket `"allow"`, its `requiresRealApproval` refusal, and the
681
+ * headless auto-deny — carry NO source on purpose: nobody was asked, so there is no wait for anyone to
682
+ * have ended, and `decisionReason: "mode"` is already the honest word for what produced them.
683
+ */
129
684
  export declare function resolveAsk(req: AskRequest, onAsk: OnAsk | undefined, signal?: AbortSignal): Promise<ResolvedAsk>;