@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,15 +1,84 @@
1
+ /**
2
+ * Gate-1 — oracleIsolation (design/77 §1): the CORE SEAM + assertion for the out-of-process grader boundary,
3
+ * the 4th auto-promote gate. The whole auto-promote tier is **mandate-OFF** (design/77 §5/§7); this file only
4
+ * makes the seam EXIST so that auto-accept (`fixed`) becomes implementable once the SERVICE supplies the real
5
+ * isolated grader environment (an E2B/Kata container). SAFE-tier stays `candidate_only` regardless.
6
+ *
7
+ * **What core owns vs what the service owns** (mirrors {@link import("./remote-env.js").RemoteExecutionEnv} —
8
+ * core owns the seam shape; service owns the backend):
9
+ * - CORE: the {@link GraderEnv} provenance contract, the {@link assertOracleIsolation} assertion (3 fail-closed
10
+ * checks), and the {@link OracleIsolationVerdict}.isolationClass tiering that CAPS a non-isolated grader at
11
+ * `candidate_only` (never auto-accept).
12
+ * - SERVICE: the actually-isolated grader env (E2B microVM with `capabilities.isolation === true`), minted by
13
+ * the trusted control plane through {@link import("./types.js").RunnerDeps.graderEnvFactory}.
14
+ *
15
+ * 🔴 **Honest residual (design/77 §1 Residual + §9):** the bash write-probe is point-in-time and
16
+ * necessary-not-sufficient — core, running *inside the worker*, cannot prove a mount is truly immutable (it
17
+ * only observes that one write failed once; a candidate can `mount -o remount,rw` after the probe). And
18
+ * `capabilities.isolation` is self-declared by the adapter (a lying adapter can claim `true`). The REAL
19
+ * protection is the OUT-OF-PROCESS structural boundary (check B) on a control-plane-provisioned adapter — which
20
+ * is exactly why auto-promote stays mandate-OFF until the deployment contract is verified end-to-end (Slice-3).
21
+ */
1
22
  import type { ExecutionEnv } from "../internal/harness-types.js";
23
+ /**
24
+ * The verdict of {@link assertOracleIsolation}. `protected` is the fail-closed AND of all three checks
25
+ * (identity ∧ structural-class-acceptable ∧ write-probe). `isolationClass` is the load-bearing tiering that the
26
+ * (OFF) auto-accept path consults:
27
+ * - `"out_of_process"` — the grader is a real isolated sandbox (a remote env with `capabilities.isolation ===
28
+ * true`). ONLY this class is eligible for auto-accept (still mandate-OFF).
29
+ * - `"in_process_probe_only"` — the grader is non-remote or non-isolated; the bash write-probe is the only
30
+ * signal and it is necessary-not-sufficient → this CAPS the run at `candidate_only`, NEVER auto-accept (the
31
+ * 2-of-3 asymmetry, design/77 §1/§6: the oracle axis's real protection is the out-of-process boundary).
32
+ */
2
33
  export interface OracleIsolationVerdict {
3
34
  protected: boolean;
4
35
  isolationClass: "out_of_process" | "in_process_probe_only";
36
+ /** Set when `protected:false` (or when the class is downgraded) — the fail-closed reason, for observability. */
5
37
  reason?: string;
6
38
  }
39
+ /**
40
+ * The isolated grader environment, provisioned by the trusted control plane. `provenance` is settable ONLY at
41
+ * the {@link import("./types.js").RunnerDeps.graderEnvFactory} call site — it is NEVER reconstructed from
42
+ * worker-visible state (a worker that could mint a `{provenance:'control_plane'}` object would defeat the whole
43
+ * gate). `immutableOraclePaths` are the paths the oracle/spec is supposed to live behind (e.g. a hidden held-out
44
+ * test dir) that the worker must not be able to corrupt; the bash write-probe (check C) targets them.
45
+ */
7
46
  export interface GraderEnv {
47
+ /** The isolated env the oracle grades in (service-provisioned; a {@link import("./remote-env.js").RemoteExecutionEnv} in production). */
8
48
  env: ExecutionEnv;
49
+ /** Paths the oracle must be protected behind — probed for writability through the WORKER's bash bypass surface. */
9
50
  immutableOraclePaths: string[];
51
+ /** Provenance brand — ONLY the control-plane factory sets this. Never derived from worker state. */
10
52
  provenance: "control_plane";
11
53
  }
54
+ /** Options for {@link assertOracleIsolation}. */
12
55
  export interface AssertOracleIsolationOptions {
56
+ /** Abort the write-probe(s); an abort/timeout during the probe is fail-closed (protected:false). */
13
57
  signal?: AbortSignal;
14
58
  }
59
+ /**
60
+ * Assert that the grader env is isolated from the worker env so a positive oracle verdict is trustworthy
61
+ * (design/77 §1, the 4th auto-promote gate). THREE fail-closed checks — ANY failure ⇒ `protected:false`:
62
+ *
63
+ * **(A) IDENTITY** — `grader.env !== workerEnv` (reference inequality); when BOTH are remote envs, also require
64
+ * distinct `workspaceHandle().sandboxId`. A grader that IS the worker env (or the same sandbox) is grading in
65
+ * the very env the worker can corrupt.
66
+ *
67
+ * **(B) STRUCTURAL CLASS (the real protection)** — when `grader.env` is a {@link import("./remote-env.js").RemoteExecutionEnv}
68
+ * with `capabilities.isolation === true` ({@link isIsolated}, fail-closed default false) → `isolationClass =
69
+ * "out_of_process"` (the only class the OFF auto-accept path may consider). A non-remote / non-isolated grader →
70
+ * `"in_process_probe_only"`, which CAPS the run at `candidate_only` — never auto-accept. Note: a non-isolated
71
+ * grader is NOT itself a `protected:false` (the probe can still pass and the run can still be a legitimate
72
+ * `candidate_only`); the class is what gates auto-accept (the 2-of-3 asymmetry).
73
+ *
74
+ * **(C) BASH WRITE-PROBE (necessary-not-sufficient, cheap early signal)** — for each `immutableOraclePath`, run
75
+ * a write probe through the WORKER env's `exec` (the bash bypass surface — see {@link probeCommand}), against
76
+ * the path canonicalized via {@link canonicalizeTarget}. The probe PASSES only if the write returns a non-zero
77
+ * exit code or an exec error (read-only mount / permission denied / not supported). Any SUCCESS (RC 0) ⇒ the
78
+ * oracle dir is writable from the worker ⇒ `protected:false`. A probe THROW / abort / timeout ⇒ fail-closed
79
+ * (`protected:false`).
80
+ *
81
+ * The verdict is fail-closed: the function itself never throws — a thrown probe is caught and mapped to
82
+ * `protected:false` (so a flaky env can't turn into a silent pass).
83
+ */
15
84
  export declare function assertOracleIsolation(workerEnv: ExecutionEnv, grader: GraderEnv, opts?: AssertOracleIsolationOptions): Promise<OracleIsolationVerdict>;
@@ -1,10 +1,42 @@
1
+ /**
2
+ * design/179 §4/§7/§13 — the ONE consent protocol every rule takes to enter the store through the engine.
3
+ *
4
+ * Single card, settings import and starter batch all reduce to the same three steps:
5
+ *
6
+ * durable approval record (pending) → authenticated confirmation transfer (approved) → principal-bound redemption (redeemed)
7
+ *
8
+ * and only the third step reaches the core-private writer. A host holding a record id cannot redeem it
9
+ * while it is pending, cannot redeem another principal's record, and cannot redeem free text — the
10
+ * redemption face takes a ticket and nothing else, so there is no field to write a rule of one's own into.
11
+ *
12
+ * The record is DURABLE, not an in-memory ticket: a safety ask can park, and the approval that redeems it
13
+ * may arrive in another process at another time. An in-memory ticket loses exactly that case.
14
+ *
15
+ * ## Crash order, and why replay is safe
16
+ *
17
+ * The record moves to `redeemed` — carrying the dot it minted — BEFORE the writer applies. A crash in
18
+ * between leaves a redeemed record whose rule is not in the store; replaying the redemption re-applies the
19
+ * SAME delta with the SAME dot, which the store folds idempotently. One redemption mints exactly one dot,
20
+ * for as many replays as it takes. Deliberately re-adding a deleted rule is a different act: a new ask, a
21
+ * new record, a new dot.
22
+ *
23
+ * ## The boundary this does NOT claim
24
+ *
25
+ * The confirmation transfer is an in-process call. A deployment must reach it only from its authenticated
26
+ * approval channel, and a deployment that shares filesystem credentials with the user can bypass all of
27
+ * this by editing a file backend's file. That is the settings-file trust model, stated rather than
28
+ * defended against: for a file backend, host = user, no more and no less.
29
+ */
1
30
  import { type RuleScope, type RuleDot } from "./permission-rule-model.js";
2
31
  import type { PermissionRuleStoreProvider } from "./permission-rule-store.js";
32
+ /** One candidate rule inside an approval record: the exact text and where it would apply. */
3
33
  export interface RuleCandidate {
4
34
  rule: string;
5
35
  scope: RuleScope;
6
36
  }
37
+ /** What the approval record is for — it decides the provenance the minted adds carry. */
7
38
  export type RuleApprovalKind = "card" | "import" | "starter";
39
+ /** A durable record of one pending/settled human decision about minting rules. */
8
40
  export interface RuleApprovalRecord {
9
41
  id: string;
10
42
  principal: string;
@@ -12,38 +44,89 @@ export interface RuleApprovalRecord {
12
44
  state: "pending" | "approved" | "redeemed";
13
45
  candidates: RuleCandidate[];
14
46
  createdAt: string;
47
+ /** The ask this record was drawn from, for reconciliation. Advisory metadata; never adjudication input. */
15
48
  toolCallId?: string;
16
49
  boundInputHash?: string;
50
+ /** Monotonic revision of THIS record, bumped by every accepted transition. The compare-and-set key:
51
+ * comparing state alone cannot separate two different writes that both leave the state unchanged. */
17
52
  rev: number;
53
+ /**
54
+ * Which candidate the person actually chose, recorded by the confirmation transfer.
55
+ *
56
+ * A card offers alternatives — the exact command and, sometimes, a broader prefix — and a human picks
57
+ * ONE. Without this, confirming the card would authorize every option on it: a host could redeem the
58
+ * exact ticket, then later redeem the wider prefix ticket, and the second rule would exist without
59
+ * anyone ever having agreed to it. Absent on batch records, where the confirmation is over the whole
60
+ * previewed list by construction.
61
+ */
18
62
  selectedCandidate?: number;
63
+ /** Dots already minted for this record, keyed by candidate index — the replay anchor. */
19
64
  redeemedDots?: Record<number, RuleDot>;
20
65
  }
66
+ /**
67
+ * The durable home of approval records. A separate record type on purpose: it is not a checkpoint row and
68
+ * must not evolve with one.
69
+ */
21
70
  export interface RuleApprovalRecordStore {
22
71
  get(id: string): Promise<RuleApprovalRecord | undefined>;
72
+ /**
73
+ * Compare-and-set on the record's REVISION, not on its state.
74
+ *
75
+ * State alone is not a compare-and-set key: a batch's second candidate transitions redeemed → redeemed,
76
+ * so two concurrent retries would both find the state they expected, both mint a dot, and both write —
77
+ * one silently overwriting the other's `redeemedDots`, which is how one approval becomes two adds and a
78
+ * deleted rule comes back to life. `next.rev` must be `expectRev + 1`.
79
+ */
23
80
  cas(id: string, expectRev: number, next: RuleApprovalRecord): Promise<boolean>;
24
81
  create(record: RuleApprovalRecord): Promise<void>;
25
82
  }
83
+ /** Everything the consent lane needs wired. */
26
84
  export interface RuleConsentDeps {
27
85
  provider: PermissionRuleStoreProvider;
28
86
  approvals: RuleApprovalRecordStore;
87
+ /** Injectable clock/id for deterministic tests; defaults are the real ones. */
29
88
  now?: () => Date;
30
89
  newId?: () => string;
31
90
  }
91
+ /** In-memory approval records — the test backend and the reference CAS semantics. */
32
92
  export declare class InMemoryRuleApprovalRecordStore implements RuleApprovalRecordStore {
33
93
  private readonly rows;
34
94
  get(id: string): Promise<RuleApprovalRecord | undefined>;
35
95
  create(record: RuleApprovalRecord): Promise<void>;
36
96
  cas(id: string, expectRev: number, next: RuleApprovalRecord): Promise<boolean>;
97
+ /** Test/inspection helper — how many records exist. The principal negative pins read this. */
37
98
  size(): number;
38
99
  }
100
+ /** An opaque, single-purpose redemption ticket. Its only content is which record and which candidate. */
39
101
  export type RuleTicket = string;
40
102
  export declare function mintRuleTicket(recordId: string, candidateIndex: number): RuleTicket;
103
+ /**
104
+ * Create the pending record behind ONE approval card, and the tickets its options would redeem.
105
+ *
106
+ * The candidates are DERIVED here, from the call, by the same function that produced the options shown on
107
+ * the card — they are not an argument. That is the difference between the stated invariant and a wish:
108
+ * while this took a candidate list, a surface could display an approval for `git status` and build a
109
+ * record containing `Bash(rm:*)`, and every later step would faithfully honor the record. There is now no
110
+ * field in which to write a rule of one's own, on this entry as on the redemption entry.
111
+ *
112
+ * `toolCallId` and `boundInputHash` are recorded so an auditor can tie the record back to the exact ask,
113
+ * and a command the lane cannot speak for yields no record and no tickets at all.
114
+ *
115
+ * What this does NOT claim: that the command named here is the command that was displayed. A surface that
116
+ * shows one thing and says another is the same-layer trust §5 already states plainly — in an in-process
117
+ * deployment the host IS the user. What it closes is the gap where the rule TEXT never came from the
118
+ * engine at all.
119
+ */
41
120
  export declare function prepareCardApproval(opts: {
42
121
  principal: string;
122
+ /** The tool whose ask this card belongs to. Only the shell tool the rule lane speaks for is accepted. */
43
123
  toolName: string;
124
+ /** The command as adjudicated — the same bytes the ask carried. */
44
125
  command: string;
126
+ /** The ask's call id and argument digest, recorded for reconciliation. */
45
127
  toolCallId?: string;
46
128
  boundInputHash?: string;
129
+ /** Where a redeemed rule would apply. Defaults to global. */
47
130
  scope?: RuleScope;
48
131
  deps: RuleConsentDeps;
49
132
  }): Promise<{
@@ -51,19 +134,34 @@ export declare function prepareCardApproval(opts: {
51
134
  tickets: RuleTicket[];
52
135
  candidates: RuleCandidate[];
53
136
  } | undefined>;
137
+ /**
138
+ * The authenticated confirmation transfer: pending → approved.
139
+ *
140
+ * A deployment must reach this ONLY from the channel that actually carries a human decision — the same
141
+ * channel an approval card's yes travels. Nothing below this line can tell an authentic confirmation from
142
+ * a fabricated one, which is why the boundary is stated here rather than checked here.
143
+ */
54
144
  export declare function confirmRuleApproval(opts: {
55
145
  approvalId: string;
56
146
  principal: string;
147
+ /**
148
+ * REQUIRED for a card record: the index of the option the person chose. A card presents alternatives of
149
+ * different breadth, so "they said yes" is not an answer on its own — "they said yes to THIS one" is.
150
+ * Rejected on a batch record, whose confirmation covers the previewed list by construction.
151
+ */
57
152
  selectedCandidate?: number;
58
153
  deps: RuleConsentDeps;
59
154
  }): Promise<ConfirmResult>;
155
+ /** Why a confirmation did not land. A closed set so a host can branch (re-present, re-fetch, give up). */
60
156
  export type ConfirmRefusalReason = "record_not_found" | "selection_missing" | "selection_invalid" | "selection_mismatch" | "batch_takes_no_selection" | "not_pending" | "conflict";
157
+ /** The confirmation outcome: landed, or refused with a named reason. */
61
158
  export type ConfirmResult = {
62
159
  ok: true;
63
160
  } | {
64
161
  ok: false;
65
162
  reason: ConfirmRefusalReason;
66
163
  };
164
+ /** What a redemption produced. `alreadyRedeemed` marks the replay path — the same dot, no second rule. */
67
165
  export type RedeemResult = {
68
166
  status: "redeemed";
69
167
  rule: string;
@@ -75,18 +173,35 @@ export type RedeemResult = {
75
173
  status: "refused";
76
174
  reason: string;
77
175
  };
176
+ /**
177
+ * Redeem one ticket into one persisted rule.
178
+ *
179
+ * Takes a ticket and a verified principal, and nothing else. There is deliberately no field carrying rule
180
+ * text: what gets persisted is what the engine put in the record when it drew the card, so a host cannot
181
+ * turn a click on `git status` into a rule for something else.
182
+ */
78
183
  export declare function redeemRuleTicket(opts: {
79
184
  ticket: RuleTicket;
80
185
  principal: string;
81
186
  deps: RuleConsentDeps;
82
187
  }): Promise<RedeemResult>;
188
+ /** The three user-editable settings layers this version reads. */
83
189
  export type ImportedSettingsLayer = "userSettings" | "projectSettings" | "localSettings";
190
+ /** One layer to read. `root` is the canonical directory a project-layer rule is scoped to — taken from
191
+ * where the FILE actually lives, since the local layer is not always at a repository root. */
84
192
  export interface CcImportLayer {
85
193
  layer: ImportedSettingsLayer;
86
194
  path: string;
87
195
  root: string;
88
196
  readFile: (path: string) => Promise<string | undefined>;
89
197
  }
198
+ /**
199
+ * What the import WOULD do, shown before anyone confirms.
200
+ *
201
+ * `uncovered` is a two-key record, not a list: the two layers this version does not read are named in the
202
+ * TYPE, so an empty list, a missing member or a duplicate is not expressible. A preview that reported only
203
+ * the layers it read would be claiming completeness it does not have.
204
+ */
90
205
  export interface ImportPreview {
91
206
  candidates: RuleCandidate[];
92
207
  skipped: Array<{
@@ -103,6 +218,8 @@ export interface ImportPreview {
103
218
  policySettings: "not-imported-v1";
104
219
  };
105
220
  }
221
+ /** What the import ACTUALLY did — a different moment and a different contract from the preview, because
222
+ * dedup, concurrency and redemption-time validation can all move an entry between the two. */
106
223
  export interface ImportResult {
107
224
  persisted: RuleCandidate[];
108
225
  deduped: RuleCandidate[];
@@ -112,6 +229,13 @@ export interface ImportResult {
112
229
  }>;
113
230
  rev: number;
114
231
  }
232
+ /**
233
+ * Read the allow buckets of the user-editable settings layers and produce a preview plus a PENDING
234
+ * approval record. Nothing is stored until someone confirms that record and the batch is redeemed.
235
+ *
236
+ * Only the allow bucket is read. The deny/ask buckets are the tightening direction and have their own
237
+ * channel; importing them through a loosening lane would be the wrong door.
238
+ */
115
239
  export declare function prepareCcImport(opts: {
116
240
  layers: CcImportLayer[];
117
241
  principal: string;
@@ -120,7 +244,17 @@ export declare function prepareCcImport(opts: {
120
244
  preview: ImportPreview;
121
245
  approvalId: string;
122
246
  }>;
247
+ /**
248
+ * The factory-reviewed starter set, offered when there is nothing to import.
249
+ *
250
+ * Every entry is an EXACT read-only command whose behavior does not depend on repository or environment
251
+ * configuration. The version-control family is deliberately absent: repository configuration can make a
252
+ * subcommand invoke an external helper, which is the same reason this repository already declined a
253
+ * subcommand allowlist for it. Nothing here takes effect until someone confirms the batch.
254
+ */
123
255
  export declare const STARTER_RULES: readonly string[];
256
+ /** Prepare the starter batch as a pending approval record. Nothing takes effect without confirmation;
257
+ * an unconfirmed deployment simply starts with an empty rule set. */
124
258
  export declare function prepareStarterBatch(opts: {
125
259
  principal: string;
126
260
  deps: RuleConsentDeps;
@@ -128,6 +262,10 @@ export declare function prepareStarterBatch(opts: {
128
262
  preview: RuleCandidate[];
129
263
  approvalId: string;
130
264
  }>;
265
+ /**
266
+ * Redeem an approved BATCH record (import or starter) — every candidate, one dot each, reporting what
267
+ * actually landed rather than what was previewed.
268
+ */
131
269
  export declare function redeemRuleBatch(opts: {
132
270
  approvalId: string;
133
271
  principal: string;
@@ -1,66 +1,188 @@
1
+ /**
2
+ * design/179 §2 — the persisted ALLOW rule model and its matcher.
3
+ *
4
+ * A persisted allow rule is the standing form of ONE recorded human approval: the person confirmed a
5
+ * command once on an approval card and asked not to be asked again, and the rule is what that answer
6
+ * becomes. This module owns the rule's SHAPE (text grammar, canonical spelling, scope) and its MATCH
7
+ * semantics; who may mint one, where it is stored, and where in the gate it is consumed live in
8
+ * `permission-rule-store.ts`, `permission-rule-consent.ts` and `hooks.ts` respectively.
9
+ *
10
+ * ## The floor: only a single simple command can ever be matched
11
+ *
12
+ * Everything a shell can use to run a SECOND program behind an admitted first one — operators,
13
+ * substitution, subshells, backgrounding, and **redirection** — puts the command outside this lane
14
+ * entirely: it falls back to the pre-existing chain and asks. That includes redirection specifically,
15
+ * which is a deliberate registered divergence from upstream (upstream strips redirections before
16
+ * matching; with this repo's write gate not covering the shell tool, stripping would turn a rule as
17
+ * innocuous as `Bash(ls)` into a licence for `ls > ~/.ssh/authorized_keys`).
18
+ *
19
+ * The floor is `parseLeadingCommandName` — the one simple-command parser already shared by the
20
+ * read-only classifier, the reversibility probe, the coarse command-name policy and the skill tool
21
+ * specifier. A second tokenizer would drift, and drift on a loosening face shows up as a bypass rather
22
+ * than as a test failure.
23
+ *
24
+ * ## Normalization order is load-bearing
25
+ *
26
+ * Whitespace folding runs AFTER the shell-construct rejection, never before: folding first would
27
+ * swallow a newline and glue two commands into one string that then reads as a single simple command.
28
+ * Only space/tab runs fold; there is no case folding, no alias expansion (no shell alias view exists
29
+ * here) and no leading-env-assignment stripping (`FOO=1 git status` simply does not match
30
+ * `Bash(git status:*)`) — the last two are strict-side divergences from upstream, registered as such.
31
+ */
32
+ /** The one tool the v1 rule lane speaks for. The field exists on the rule so v2 can widen without a shape change. */
1
33
  export type PersistedRuleTool = "Bash";
34
+ /** v1 match forms. `"wildcard"` is reserved for v2 and is not a value this version ever produces. */
2
35
  export type PersistedRuleMatch = "exact" | "prefix";
36
+ /**
37
+ * Where a rule applies. A rule read out of a project-local settings layer applies ONLY inside that
38
+ * project's canonical root — project A's approval is not project B's. User-layer, starter and
39
+ * user-minted rules are global.
40
+ *
41
+ * `root` is expected to be already canonicalized (realpath) by whoever constructs the scope; the
42
+ * matcher compares with word-boundary containment, never a bare `startsWith` (`/a` must not reach `/ab`).
43
+ */
3
44
  export type RuleScope = {
4
45
  kind: "global";
5
46
  } | {
6
47
  kind: "project";
7
48
  root: string;
8
49
  };
50
+ /** The immutable causal identity of one add: a replica identity plus a monotonic counter. */
9
51
  export interface RuleDot {
10
52
  actor: string;
11
53
  counter: number;
12
54
  }
55
+ /** Where one add came from. Stored PER ADD — never folded across dots (a folded provenance cannot
56
+ * follow a dot that is later deleted on its own). */
13
57
  export type RuleAddOrigin = "user" | "imported-cc" | "starter";
58
+ /** One add of one logical rule, carrying its own dot and its own provenance. */
14
59
  export interface RuleAdd {
15
60
  dot: RuleDot;
16
61
  origin: RuleAddOrigin;
17
62
  createdAt: string;
18
63
  }
64
+ /**
65
+ * A persisted ALLOW rule for one tool.
66
+ *
67
+ * `adds` is a real set, not a scalar: two concurrently approved records for the same (rule, scope)
68
+ * each redeem their own dot, and a rule is live iff at least one of its adds survives the tombstones.
69
+ * Organization rules have the opposite polarity (deny/ask only) and never enter this type.
70
+ */
19
71
  export interface PersistedAllowRule {
72
+ /** Canonical rule text: `Bash(git status)` (exact) or `Bash(git status:*)` (prefix). */
20
73
  rule: string;
21
74
  tool: PersistedRuleTool;
22
75
  match: PersistedRuleMatch;
76
+ /** What the matcher compares against — parsed out of `rule`, stored so no consumer re-parses. */
23
77
  command: string;
24
78
  scope: RuleScope;
25
79
  adds: RuleAdd[];
26
80
  }
81
+ /**
82
+ * A delete intent, in observed-remove form: it carries EVERY add dot for its (rule, scope) that was
83
+ * visible to the deleting replica at delete time. A single-dot tombstone cannot delete cleanly —
84
+ * concurrent replicas add the same rule text under different dots, and a tombstone that names only one
85
+ * of them lets the deleted rule come back. The merge criterion is dot IDENTITY, not a causal-order
86
+ * comparison (single dots across replicas have no order to compare): an add is live iff its dot appears
87
+ * in no tombstone for the same (rule, scope).
88
+ */
27
89
  export interface RuleTombstone {
28
90
  rule: string;
29
91
  scope: RuleScope;
30
92
  removedDots: RuleDot[];
93
+ /** The delete operation's own dot — the operation's persistent identity. */
31
94
  deletedBy: RuleDot;
32
95
  }
96
+ /** Why a rule text was refused. Codes are stable so an import report can group by them. */
33
97
  export type RuleRejectCode = "invalid.grammar" | "invalid.empty_command" | "invalid.not_simple_command" | "invalid.bare_interpreter_prefix" | "invalid.unbalanced_quotes" | "invalid.too_long" | "unsupported.tool" | "unsupported.wildcard";
34
98
  export interface RuleReject {
35
99
  code: RuleRejectCode;
36
100
  message: string;
37
101
  }
102
+ /** The parsed, canonical shape of one rule text — everything but the scope and the provenance. */
38
103
  export interface ParsedAllowRule {
39
104
  rule: string;
40
105
  tool: PersistedRuleTool;
41
106
  match: PersistedRuleMatch;
42
107
  command: string;
43
108
  }
109
+ /** Upper bound on a rule text. Rules are human-authored one-liners; anything longer is a mistake or an
110
+ * attempt to make the store unreadable. */
44
111
  export declare const MAX_RULE_TEXT_CHARS = 512;
112
+ /**
113
+ * Interpreter names whose PREFIX form is refused everywhere a rule can enter the store (minting,
114
+ * import, file reload, every backend). `Bash(node:*)` reads as one narrow-looking rule and means "run
115
+ * any program you like" — that is not a shape a single click can be understood to have authorized.
116
+ *
117
+ * The check is on argv[0] of the prefix, not on the prefix being exactly one word: `node -e:*` is the
118
+ * same licence spelled longer. Deliberately strict-side — it costs the ability to persist a rule like
119
+ * `python manage.py migrate:*` (which an import reports as skipped rather than dropping silently), and
120
+ * an EXACT rule naming a whole interpreter command line stays legal, since it authorizes one command.
121
+ */
45
122
  export declare const BARE_INTERPRETER_NAMES: ReadonlySet<string>;
123
+ /**
124
+ * Parse one rule text into its canonical shape, or refuse it with a reason.
125
+ *
126
+ * This is the ONE validator every entry point shares — minting a suggestion, importing another
127
+ * product's settings, reloading a store file, and any future backend. A shape refused here cannot enter
128
+ * the store through any door.
129
+ */
46
130
  export declare function parseAllowRuleText(text: string): {
47
131
  rule: ParsedAllowRule;
48
132
  } | {
49
133
  reject: RuleReject;
50
134
  };
135
+ /** The canonical spelling of a rule for a (already folded) command and match form. */
51
136
  export declare function formatAllowRuleText(command: string, match: PersistedRuleMatch): string;
137
+ /**
138
+ * Does this rule's command pattern admit `command`?
139
+ *
140
+ * `command` is the raw tool argument: the floor and the folding happen HERE, in that order, so no
141
+ * caller can accidentally match a folded compound. Returns false for anything that is not a single
142
+ * simple command — including every redirection form.
143
+ */
52
144
  export declare function ruleAdmitsCommand(rule: Pick<PersistedAllowRule, "match" | "command">, command: string): boolean;
145
+ /**
146
+ * Is `path` inside (or equal to) `root`? Word-boundary containment on the path separator, so `/a` does
147
+ * not contain `/ab`. Both sides are expected to be canonical already.
148
+ */
53
149
  export declare function pathWithinRoot(path: string, root: string): boolean;
150
+ /** Does a rule's scope cover a task running in `cwd`? A project rule needs a cwd to compare against;
151
+ * without one it covers nothing (fail-closed). */
54
152
  export declare function scopeCoversCwd(scope: RuleScope, cwd: string | undefined): boolean;
153
+ /** Is this rule live — i.e. does it still carry at least one add? Deleted adds are removed by the store
154
+ * when tombstones are applied, so a rule with an empty `adds` is a rule that no longer exists. */
55
155
  export declare function isRuleLive(rule: PersistedAllowRule): boolean;
156
+ /**
157
+ * Find the rule that admits this command for a task in `cwd`, or `undefined`.
158
+ *
159
+ * Order is defined only for reporting (the first match wins and its text is what the decision names);
160
+ * no rule is stronger than another — they are all the same one answer, "the person already said yes to
161
+ * this".
162
+ */
56
163
  export declare function findAdmittingRule(rules: readonly PersistedAllowRule[], call: {
57
164
  tool: string;
58
165
  command: string;
59
166
  cwd: string | undefined;
60
167
  }): PersistedAllowRule | undefined;
168
+ /** A rule the engine offers to mint, as carried on an approval card. */
61
169
  export interface RuleSuggestion {
170
+ /** The canonical rule text the host would redeem. */
62
171
  rule: string;
63
172
  match: PersistedRuleMatch;
173
+ /** The command pattern in the rule, for a host that wants to render it without re-parsing. */
64
174
  command: string;
65
175
  }
176
+ /**
177
+ * The 1-2 candidates offered on an approval card for `command`.
178
+ *
179
+ * The exact form (this whole command line) is always offered when the command is matchable at all. A
180
+ * prefix form is offered only when it is a shape a person can read as narrow: the upstream multi-word
181
+ * convention (`git status`, `npm run`) is preferred over a bare program name, and no prefix at all is
182
+ * offered for an interpreter head — that candidate would be refused by the validator anyway, and
183
+ * offering a candidate the store will not accept is worse than offering one fewer.
184
+ *
185
+ * Returns an empty array for anything the rule lane cannot speak for (compounds, redirections,
186
+ * substitutions) — the card then simply carries no "don't ask again" option, which is the honest answer.
187
+ */
66
188
  export declare function suggestRulesForCommand(command: string): RuleSuggestion[];