@sema-agent/core 7.55.0 → 7.56.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 (418) hide show
  1. package/CHANGELOG.md +513 -0
  2. package/dist/agents/cascade.js +1 -1
  3. package/dist/agents/cc-peer-directory.js +1 -0
  4. package/dist/agents/child-model-seat.d.ts +0 -11
  5. package/dist/agents/child-model-seat.js +0 -3
  6. package/dist/agents/list-agents-tool.d.ts +3 -1
  7. package/dist/agents/list-agents-tool.js +7 -7
  8. package/dist/agents/peer-directory.d.ts +22 -4
  9. package/dist/agents/peer-directory.js +24 -2
  10. package/dist/agents/peer-session-drain.js +2 -2
  11. package/dist/agents/repair-loop.js +2 -2
  12. package/dist/agents/send-message-tool.js +4 -4
  13. package/dist/agents/subagent.d.ts +6 -4
  14. package/dist/agents/subagent.js +64 -60
  15. package/dist/agents/tool-filter.d.ts +7 -5
  16. package/dist/agents/tool-filter.js +12 -9
  17. package/dist/agents/verify.d.ts +3 -2
  18. package/dist/agents/verify.js +3 -3
  19. package/dist/brain/anthropic.js +30 -73
  20. package/dist/brain/media-degrade.d.ts +18 -7
  21. package/dist/brain/media-degrade.js +13 -2
  22. package/dist/brain/model-capability.d.ts +37 -0
  23. package/dist/brain/model-capability.js +34 -0
  24. package/dist/brain/model-presets.d.ts +2 -8
  25. package/dist/brain/model-presets.js +1 -6
  26. package/dist/brain/open-responses.js +13 -26
  27. package/dist/brain/openai.js +14 -87
  28. package/dist/brain/reasoning-request.d.ts +96 -0
  29. package/dist/brain/reasoning-request.js +174 -0
  30. package/dist/brain/reasoning.d.ts +11 -11
  31. package/dist/brain/reasoning.js +4 -3
  32. package/dist/brain/request-params.d.ts +7 -4
  33. package/dist/brain/request-params.js +7 -4
  34. package/dist/brain/status-sink.d.ts +20 -0
  35. package/dist/brain/status-sink.js +7 -0
  36. package/dist/core/a2a.d.ts +2 -1
  37. package/dist/core/a2a.js +19 -13
  38. package/dist/core/agent-definition.d.ts +10 -0
  39. package/dist/core/allow-entry.d.ts +20 -13
  40. package/dist/core/allow-entry.js +26 -22
  41. package/dist/core/allow-rule-shadow.d.ts +3 -3
  42. package/dist/core/ask-origin.d.ts +64 -18
  43. package/dist/core/ask-origin.js +63 -23
  44. package/dist/core/ask-question.d.ts +51 -8
  45. package/dist/core/ask-question.js +3 -4
  46. package/dist/core/ask-unresolvable-notice.d.ts +8 -3
  47. package/dist/core/ask-unresolvable-notice.js +16 -2
  48. package/dist/core/checkpoint-generation.d.ts +53 -0
  49. package/dist/core/checkpoint-generation.js +35 -0
  50. package/dist/core/checkpoint-queries.d.ts +180 -0
  51. package/dist/core/checkpoint-queries.js +272 -0
  52. package/dist/core/checkpoint-requirements.d.ts +13 -1
  53. package/dist/core/checkpoint-requirements.js +4 -0
  54. package/dist/core/checkpoint-store.d.ts +88 -24
  55. package/dist/core/checkpoint-store.js +24 -9
  56. package/dist/core/cross-boundary-taint.d.ts +6 -5
  57. package/dist/core/cross-boundary-taint.js +1 -3
  58. package/dist/core/decision-receipt.d.ts +37 -3
  59. package/dist/core/decision-receipt.js +17 -17
  60. package/dist/core/delegation-not-started.d.ts +6 -0
  61. package/dist/core/delegation-not-started.js +17 -0
  62. package/dist/core/engine-attestation.d.ts +93 -0
  63. package/dist/core/engine-attestation.js +70 -0
  64. package/dist/core/engine-capabilities.d.ts +4 -1
  65. package/dist/core/engine-capabilities.js +1 -1
  66. package/dist/core/engine-notice.d.ts +30 -11
  67. package/dist/core/file-history-store.d.ts +90 -14
  68. package/dist/core/file-history-store.js +23 -15
  69. package/dist/core/gate-fold.d.ts +1 -1
  70. package/dist/core/gate-fold.js +22 -10
  71. package/dist/core/gate-lanes.js +73 -64
  72. package/dist/core/gate-outcome.d.ts +26 -5
  73. package/dist/core/gate-outcome.js +26 -0
  74. package/dist/core/governance-codes.d.ts +5 -1
  75. package/dist/core/governance-codes.js +6 -0
  76. package/dist/core/hooks.d.ts +17 -16
  77. package/dist/core/hooks.js +3 -1
  78. package/dist/core/host-floor.d.ts +128 -0
  79. package/dist/core/host-floor.js +206 -0
  80. package/dist/core/host-target.d.ts +38 -3
  81. package/dist/core/host-target.js +38 -5
  82. package/dist/core/mcp.d.ts +5 -1
  83. package/dist/core/mcp.js +67 -41
  84. package/dist/core/memory-engine/delegation-settlement.js +15 -24
  85. package/dist/core/memory-engine/engine.js +4 -4
  86. package/dist/core/memory-engine/layout.d.ts +60 -8
  87. package/dist/core/memory-engine/layout.js +65 -6
  88. package/dist/core/model-seat.d.ts +10 -3
  89. package/dist/core/mods/classic-events.d.ts +67 -0
  90. package/dist/core/mods/classic-events.js +1 -0
  91. package/dist/core/mods/dollar.d.ts +13 -0
  92. package/dist/core/mods/extension-call.d.ts +31 -0
  93. package/dist/core/mods/extension-call.js +43 -0
  94. package/dist/core/mods/kernel/dispatch.d.ts +20 -3
  95. package/dist/core/mods/kernel/dispatch.js +140 -69
  96. package/dist/core/mods/kernel/events.d.ts +47 -11
  97. package/dist/core/mods/kernel/events.js +66 -42
  98. package/dist/core/mods/kernel/index.d.ts +4 -4
  99. package/dist/core/mods/kernel/index.js +2 -2
  100. package/dist/core/mods/kernel/receive.d.ts +39 -5
  101. package/dist/core/mods/kernel/receive.js +290 -17
  102. package/dist/core/mods/kernel/registration.d.ts +33 -2
  103. package/dist/core/mods/kernel/registration.js +6 -7
  104. package/dist/core/mods/kernel/site-rules.d.ts +44 -16
  105. package/dist/core/mods/kernel/site-rules.js +24 -42
  106. package/dist/core/mods/spec-seats.d.ts +69 -0
  107. package/dist/core/mods/spec-seats.js +114 -0
  108. package/dist/core/mods/stations.d.ts +28 -8
  109. package/dist/core/mods/stations.js +29 -13
  110. package/dist/core/mods/tool-call.d.ts +79 -0
  111. package/dist/core/mods/tool-call.js +152 -0
  112. package/dist/core/namespaced-rule-name.d.ts +32 -38
  113. package/dist/core/namespaced-rule-name.js +29 -36
  114. package/dist/core/parent-spec-seat.d.ts +6 -1
  115. package/dist/core/parent-spec-seat.js +2 -0
  116. package/dist/core/park-selfcheck.js +1 -0
  117. package/dist/core/permission-rule-consent.d.ts +19 -0
  118. package/dist/core/permission-rule-consent.js +116 -26
  119. package/dist/core/permission-rule-model.d.ts +14 -3
  120. package/dist/core/permission-rule-model.js +39 -24
  121. package/dist/core/permission-rule-org.d.ts +6 -2
  122. package/dist/core/permission-rule-org.js +7 -3
  123. package/dist/core/permission-rule-provider.d.ts +5 -2
  124. package/dist/core/permission-rule-provider.js +41 -11
  125. package/dist/core/permission-rule-store.d.ts +3 -2
  126. package/dist/core/permission-rule-store.js +11 -2
  127. package/dist/core/permission-rule-sync.js +3 -2
  128. package/dist/core/permission-rule-syntax.d.ts +5 -4
  129. package/dist/core/permission-rule-syntax.js +2 -2
  130. package/dist/core/permission-rules.d.ts +4 -4
  131. package/dist/core/permission-rules.js +11 -20
  132. package/dist/core/persisted-rule-arms.d.ts +2 -2
  133. package/dist/core/persisted-rule-arms.js +10 -12
  134. package/dist/core/principal-name.d.ts +20 -0
  135. package/dist/core/principal-name.js +22 -0
  136. package/dist/core/prompt-section-seat.js +4 -6
  137. package/dist/core/protocol-http-auth.d.ts +26 -5
  138. package/dist/core/protocol-http-auth.js +137 -4
  139. package/dist/core/retired-keys.d.ts +16 -0
  140. package/dist/core/retired-keys.js +16 -4
  141. package/dist/core/rewrite-rejudge.d.ts +60 -0
  142. package/dist/core/rewrite-rejudge.js +36 -0
  143. package/dist/core/roles.d.ts +28 -1
  144. package/dist/core/roles.js +31 -19
  145. package/dist/core/rule-lane-reads.d.ts +20 -15
  146. package/dist/core/rule-lane-reads.js +45 -17
  147. package/dist/core/rule-owner.d.ts +3 -3
  148. package/dist/core/rule-owner.js +3 -2
  149. package/dist/core/runner/announce-once-ledger.d.ts +14 -0
  150. package/dist/core/runner/announce-once-ledger.js +5 -0
  151. package/dist/core/runner/assemble-result.d.ts +1 -0
  152. package/dist/core/runner/assemble-result.js +1 -1
  153. package/dist/core/runner/call-hook-stations.d.ts +3 -2
  154. package/dist/core/runner/caller-roster.d.ts +16 -4
  155. package/dist/core/runner/caller-roster.js +33 -6
  156. package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
  157. package/dist/core/runner/capability-withheld-seat.js +24 -0
  158. package/dist/core/runner/classifier-ladder.d.ts +7 -9
  159. package/dist/core/runner/classifier-ladder.js +3 -3
  160. package/dist/core/runner/construction-doors.js +3 -0
  161. package/dist/core/runner/contracts.d.ts +28 -25
  162. package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
  163. package/dist/core/runner/cross-boundary-lane.js +40 -27
  164. package/dist/core/runner/denial-limit-arms.d.ts +2 -2
  165. package/dist/core/runner/denial-limit-arms.js +1 -1
  166. package/dist/core/runner/file-history-request.d.ts +18 -0
  167. package/dist/core/runner/file-history-request.js +21 -13
  168. package/dist/core/runner/file-history-restore.d.ts +45 -0
  169. package/dist/core/runner/file-history-restore.js +46 -0
  170. package/dist/core/runner/gate-exit.d.ts +3 -3
  171. package/dist/core/runner/gate-exit.js +4 -3
  172. package/dist/core/runner/image.d.ts +7 -17
  173. package/dist/core/runner/image.js +9 -60
  174. package/dist/core/runner/permission-rule-lanes.d.ts +4 -4
  175. package/dist/core/runner/permission-rule-lanes.js +26 -10
  176. package/dist/core/runner/person-path-rows.d.ts +12 -9
  177. package/dist/core/runner/person-path-rows.js +18 -7
  178. package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
  179. package/dist/core/runner/prepare-ask-lane.js +5 -2
  180. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
  181. package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
  182. package/dist/core/runner/prepare-config-doors.d.ts +29 -38
  183. package/dist/core/runner/prepare-config-doors.js +42 -25
  184. package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
  185. package/dist/core/runner/prepare-defer-classify.js +7 -8
  186. package/dist/core/runner/prepare-file-history.d.ts +48 -8
  187. package/dist/core/runner/prepare-file-history.js +7 -39
  188. package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
  189. package/dist/core/runner/prepare-gate-stations.js +10 -1
  190. package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
  191. package/dist/core/runner/prepare-hands-readface.js +15 -14
  192. package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
  193. package/dist/core/runner/prepare-inherited-gate.js +5 -3
  194. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  195. package/dist/core/runner/prepare-park-ask.js +5 -5
  196. package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
  197. package/dist/core/runner/prepare-policy-chain.js +65 -72
  198. package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
  199. package/dist/core/runner/prepare-prompt-assembly.js +10 -8
  200. package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
  201. package/dist/core/runner/prepare-prompt-inputs.js +3 -5
  202. package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
  203. package/dist/core/runner/prepare-protocol-tools.js +3 -3
  204. package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
  205. package/dist/core/runner/prepare-safety-scan.js +0 -17
  206. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
  207. package/dist/core/runner/prepare-suspend-saga.js +5 -6
  208. package/dist/core/runner/prepare-task.d.ts +1 -1
  209. package/dist/core/runner/prepare-task.js +29 -20
  210. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
  211. package/dist/core/runner/prepare-tool-disclosure-mount.js +20 -16
  212. package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
  213. package/dist/core/runner/prepare-turn-wiring.js +2 -7
  214. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
  215. package/dist/core/runner/prepare-wiring-manifest.js +3 -3
  216. package/dist/core/runner/resume-admission.js +1 -1
  217. package/dist/core/runner/resume-apply.js +11 -12
  218. package/dist/core/runner/resume-checkpoint-screen.js +3 -0
  219. package/dist/core/runner/resume-claim.d.ts +4 -2
  220. package/dist/core/runner/resume-claim.js +15 -8
  221. package/dist/core/runner/retired-runner-deps.js +1 -0
  222. package/dist/core/runner/rewind-files.d.ts +15 -0
  223. package/dist/core/runner/rewind-files.js +132 -0
  224. package/dist/core/runner/run-attachment-seats.js +2 -1
  225. package/dist/core/runner/run-brain-sinks.d.ts +4 -1
  226. package/dist/core/runner/run-brain-sinks.js +4 -2
  227. package/dist/core/runner/run-harness-handlers.js +12 -4
  228. package/dist/core/runner/run-leg.d.ts +1 -1
  229. package/dist/core/runner/run-leg.js +30 -18
  230. package/dist/core/runner/run-settle-and-teardown.js +2 -1
  231. package/dist/core/runner/run-turn-boundary.js +1 -10
  232. package/dist/core/runner/runtask.d.ts +3 -0
  233. package/dist/core/runner/runtask.js +8 -9
  234. package/dist/core/runner/session-read-file-states.d.ts +15 -0
  235. package/dist/core/runner/session-read-file-states.js +28 -0
  236. package/dist/core/runner/session-rule-policy.js +4 -3
  237. package/dist/core/runner/shell-env-withheld.d.ts +33 -0
  238. package/dist/core/runner/shell-env-withheld.js +51 -0
  239. package/dist/core/runner/skills-seat.js +6 -2
  240. package/dist/core/runner/stream-settle-backstop.js +1 -1
  241. package/dist/core/runner/sub-agent-deny-lists.js +4 -7
  242. package/dist/core/runner/synthetic-tools.d.ts +6 -0
  243. package/dist/core/runner/synthetic-tools.js +4 -1
  244. package/dist/core/runner/tool-disclosure.d.ts +10 -12
  245. package/dist/core/runner/tool-disclosure.js +1 -3
  246. package/dist/core/runner/tool-end-body.d.ts +1 -1
  247. package/dist/core/runner/tool-end-body.js +10 -9
  248. package/dist/core/runner/tool-not-executed.d.ts +5 -0
  249. package/dist/core/runner/tool-not-executed.js +11 -0
  250. package/dist/core/runner/tool-occurrence.d.ts +8 -0
  251. package/dist/core/runner/tool-occurrence.js +7 -0
  252. package/dist/core/runner/turn-attachments.d.ts +33 -15
  253. package/dist/core/runner/turn-attachments.js +62 -37
  254. package/dist/core/runner-deps.d.ts +5 -5
  255. package/dist/core/safety-axis-vocab.d.ts +6 -4
  256. package/dist/core/safety-axis-vocab.js +6 -5
  257. package/dist/core/safety-merge-corpus.js +11 -3
  258. package/dist/core/secret-env.d.ts +26 -3
  259. package/dist/core/secret-env.js +44 -8
  260. package/dist/core/select-model.js +3 -3
  261. package/dist/core/session-policy-store.d.ts +27 -15
  262. package/dist/core/session-policy-store.js +156 -36
  263. package/dist/core/session-store.d.ts +29 -10
  264. package/dist/core/session-store.js +51 -19
  265. package/dist/core/session.d.ts +82 -16
  266. package/dist/core/session.js +53 -0
  267. package/dist/core/shell-read-silence.d.ts +11 -12
  268. package/dist/core/shell-read-silence.js +9 -5
  269. package/dist/core/shell-run-candidates.js +3 -1
  270. package/dist/core/shell-wrapper-projection.js +1 -1
  271. package/dist/core/shell-wrapper-table.d.ts +14 -7
  272. package/dist/core/shell-wrapper-table.js +5 -4
  273. package/dist/core/side-query.js +10 -1
  274. package/dist/core/skill-grant.d.ts +7 -2
  275. package/dist/core/skill-grant.js +5 -0
  276. package/dist/core/skills-directory.js +6 -2
  277. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
  278. package/dist/core/store-contracts/checkpoint-store-contract.js +140 -2
  279. package/dist/core/store-contracts/file-history-store-contract.js +31 -1
  280. package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
  281. package/dist/core/store-contracts/peer-directory-contract.js +14 -2
  282. package/dist/core/store-contracts/session-repo-contract.js +51 -0
  283. package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
  284. package/dist/core/store-contracts/session-store-contract.js +150 -14
  285. package/dist/core/stub-env.d.ts +2 -0
  286. package/dist/core/stub-env.js +1 -0
  287. package/dist/core/synthetic-read-verdict.js +3 -3
  288. package/dist/core/task-event.d.ts +32 -4
  289. package/dist/core/task-notification.d.ts +16 -12
  290. package/dist/core/task-registry.d.ts +9 -0
  291. package/dist/core/task-registry.js +11 -1
  292. package/dist/core/task-result.d.ts +18 -0
  293. package/dist/core/task-spec.d.ts +18 -13
  294. package/dist/core/tighten-task-spec.js +2 -1
  295. package/dist/core/tool-catalog-entries.d.ts +17 -0
  296. package/dist/core/tool-catalog-entries.js +13 -2
  297. package/dist/core/tool-check-reading.d.ts +11 -0
  298. package/dist/core/tool-check-reading.js +11 -6
  299. package/dist/core/tool-model-gate.d.ts +2 -2
  300. package/dist/core/tool-name-aliases.d.ts +16 -16
  301. package/dist/core/tool-name-aliases.js +13 -19
  302. package/dist/core/tool-name-readings.d.ts +5 -35
  303. package/dist/core/tool-name-readings.js +1 -9
  304. package/dist/core/tool-policy.d.ts +68 -198
  305. package/dist/core/tool-policy.js +149 -198
  306. package/dist/core/tool-result-store.js +3 -0
  307. package/dist/core/tool-roster.d.ts +14 -19
  308. package/dist/core/tool-roster.js +11 -44
  309. package/dist/core/tool-spec-members.js +7 -2
  310. package/dist/core/tool-spec.d.ts +19 -11
  311. package/dist/core/tools.js +49 -9
  312. package/dist/core/trace.d.ts +2 -2
  313. package/dist/core/types.d.ts +1 -1
  314. package/dist/core/user-attachment.d.ts +8 -1
  315. package/dist/core/user-attachment.js +64 -4
  316. package/dist/core/wiring-manifest.d.ts +9 -0
  317. package/dist/core/wiring-manifest.js +1 -0
  318. package/dist/core/workflow-journal-store.js +1 -1
  319. package/dist/engine/compaction/compaction.js +3 -2
  320. package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
  321. package/dist/engine/execution-env/node-execution-env.js +11 -2
  322. package/dist/engine/harness/agent-harness.d.ts +25 -1
  323. package/dist/engine/harness/agent-harness.js +54 -7
  324. package/dist/engine/harness/types.d.ts +29 -2
  325. package/dist/engine/llm/types.d.ts +28 -11
  326. package/dist/engine/loop/agent-loop.d.ts +22 -0
  327. package/dist/engine/loop/agent-loop.js +16 -26
  328. package/dist/engine/loop/types.d.ts +16 -6
  329. package/dist/engine/session/memory-repo.d.ts +9 -2
  330. package/dist/engine/session/memory-repo.js +11 -1
  331. package/dist/engine/session/repo-utils.d.ts +6 -5
  332. package/dist/engine/session/repo-utils.js +14 -6
  333. package/dist/index.d.ts +22 -10
  334. package/dist/index.js +15 -7
  335. package/dist/internal/harness-types.d.ts +1 -1
  336. package/dist/internal/llm.d.ts +1 -1
  337. package/dist/orchestration/run-workflow-tool.d.ts +6 -4
  338. package/dist/orchestration/run-workflow-tool.js +5 -3
  339. package/dist/orchestration/workflow.d.ts +3 -0
  340. package/dist/orchestration/workflow.js +36 -18
  341. package/dist/prompt-assembly/artifact.d.ts +2 -2
  342. package/dist/prompt-assembly/artifact.js +5 -3
  343. package/dist/prompt-assembly/assemble.d.ts +3 -2
  344. package/dist/prompt-assembly/assemble.js +1 -1
  345. package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
  346. package/dist/prompt-assembly/catalog/schema.js +34 -2
  347. package/dist/prompt-assembly/catalog/sections.js +0 -1
  348. package/dist/prompt-assembly/composer.d.ts +3 -1
  349. package/dist/prompt-assembly/composer.js +1 -1
  350. package/dist/prompt-assembly/event-registry.js +1 -0
  351. package/dist/prompt-assembly/overlay.js +3 -3
  352. package/dist/prompt-assembly/renderers.d.ts +1 -1
  353. package/dist/prompt-assembly/renderers.js +0 -3
  354. package/dist/prompt-assembly/role-base.d.ts +15 -0
  355. package/dist/prompt-assembly/role-base.js +9 -0
  356. package/dist/prompt-assembly/select.d.ts +39 -14
  357. package/dist/prompt-assembly/select.js +47 -16
  358. package/dist/prompt-assembly/sugar.d.ts +17 -11
  359. package/dist/prompt-assembly/sugar.js +8 -3
  360. package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
  361. package/dist/prompt-assembly/tool-catalog.js +114 -4
  362. package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
  363. package/dist/prompt-assembly/turn-snapshot.js +0 -3
  364. package/dist/prompt-assembly/types.d.ts +0 -7
  365. package/dist/scenarios/full-body.d.ts +11 -11
  366. package/dist/scenarios/full-body.js +4 -3
  367. package/dist/shell/lex.js +10 -1
  368. package/dist/stores/file/adoption/adopt.js +4 -3
  369. package/dist/stores/file/adoption/marker.js +3 -2
  370. package/dist/stores/file/checkpoint-store.d.ts +21 -0
  371. package/dist/stores/file/checkpoint-store.js +38 -6
  372. package/dist/stores/file/file-history-store.js +6 -7
  373. package/dist/stores/file/index.js +2 -1
  374. package/dist/stores/file/permission-rule-adopt.js +4 -3
  375. package/dist/stores/file/permission-rule-store.js +11 -5
  376. package/dist/stores/file/session-store.d.ts +29 -6
  377. package/dist/stores/file/session-store.js +42 -50
  378. package/dist/tools/artifact/artifact-tool.js +3 -2
  379. package/dist/tools/fs/bash-program-position.d.ts +19 -2
  380. package/dist/tools/fs/bash-program-position.js +56 -9
  381. package/dist/tools/fs/fs-bash.js +5 -5
  382. package/dist/tools/fs/fs-glob.d.ts +86 -0
  383. package/dist/tools/fs/fs-glob.js +226 -0
  384. package/dist/tools/fs/fs-read.js +14 -14
  385. package/dist/tools/fs/fs-search-tools.js +7 -7
  386. package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
  387. package/dist/tools/fs/pattern-kill-guard.js +397 -0
  388. package/dist/tools/fs/pdf.d.ts +9 -6
  389. package/dist/tools/fs/pdf.js +3 -3
  390. package/dist/tools/fs/program-read-model.d.ts +57 -7
  391. package/dist/tools/fs/program-read-model.js +11 -1
  392. package/dist/tools/fs/program-read-model.rows.js +78 -21
  393. package/dist/tools/fs/read-deny-home.js +3 -2
  394. package/dist/tools/fs/removal-targets.d.ts +17 -7
  395. package/dist/tools/fs/removal-targets.js +47 -20
  396. package/dist/tools/fs/search.d.ts +10 -0
  397. package/dist/tools/fs/search.js +20 -26
  398. package/dist/tools/fs/shell-read-argv.js +89 -12
  399. package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
  400. package/dist/tools/fs/shell-read-bindings.js +41 -0
  401. package/dist/tools/fs/shell-read-check.js +6 -19
  402. package/dist/tools/fs/shell-read-environment.d.ts +5 -1
  403. package/dist/tools/fs/shell-read-environment.js +3 -2
  404. package/dist/tools/fs/shell-read-establish.d.ts +15 -0
  405. package/dist/tools/fs/shell-read-establish.js +19 -20
  406. package/dist/tools/fs/shell-read-plan.js +24 -16
  407. package/dist/tools/fs/shell-read-start.d.ts +6 -1
  408. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
  409. package/dist/tools/fs/shell-read-write-targets.js +2 -3
  410. package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
  411. package/dist/tools/fs/shell-reentry-text.js +40 -2
  412. package/dist/tools/todo.js +63 -63
  413. package/dist/tools/web.d.ts +19 -14
  414. package/dist/tools/web.js +38 -55
  415. package/package.json +1 -1
  416. package/test/export-surface.snapshot.json +143 -5
  417. package/wire-changes/core@7.56.0.json +3891 -0
  418. package/wire-changes/mods-kernel@7.56.0.json +303 -0
@@ -1,8 +1,10 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { homedir } from "node:os";
3
3
  import { argsReadFrom, carryArgsReadFrom, withArgsReading } from "./effective-path-target.js";
4
+ import { editRewrittenSentence, readRejudge, rewriteChasedSentence } from "./rewrite-rejudge.js";
4
5
  import { brandPolicyAskClass } from "./ask-class.js";
5
6
  import { decisionAskClassesOf, headlessDenialMessage } from "./ask-origin.js";
7
+ import { attest, attestationOf, isEngineAttestation, mergeAttestation, mintAttestation, withAttestation } from "./engine-attestation.js";
6
8
  import { ownReadRootCandidate, readRootGrantSeat } from "./read-root-grant-screen.js";
7
9
  import { decidersNote, settledByDecider } from "./gate-outcome.js";
8
10
  import { unjudgedAllowRefused } from "./real-approval.js";
@@ -19,9 +21,9 @@ import { egressText, egressThrownText } from "./untrusted-egress.js";
19
21
  import { assertNoRetiredKeys, assertNoRetiredToolPolicyKeys, RETIRED_DECISION_MEMBERS, RETIRED_TOOL_POLICY_KEYS } from "./retired-keys.js";
20
22
  import { DECISION_MEMBER_ARMS, isEngineRefusal, nestedRecordsOf, receiveContract, receiveNestedRecords, refusedOutOfContract, screenContractValues } from "./decision-receipt.js";
21
23
  export { isEngineRefusal } from "./decision-receipt.js";
22
- import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "./permission-rules.js";
24
+ import { isCoveringRuleName, ruleNameCovers } from "./namespaced-rule-name.js";
23
25
  import { ruleContentOf } from "./permission-rule-model.js";
24
- import { wildcardPeerRefusalOf } from "./tool-name-aliases.js";
26
+ import { grantWildcardRefusalOf } from "./tool-name-aliases.js";
25
27
  import { ruleSpellingOf } from "./permission-rule-syntax.js";
26
28
  import { protocolOf } from "./protocol-table.js";
27
29
  import { anchorSpelling, isAbsoluteForFamily, normalizeAbsPathLexically, pathFamilyOf, writeTargetPath } from "../tools/fs/safety.js";
@@ -37,75 +39,7 @@ export function exemptRootsSeat(exemptRoots) {
37
39
  function settledByNobody(kind) {
38
40
  return { kind, who: { party: "none" }, when: Date.now() };
39
41
  }
40
- const ATTESTATION_GROUP_OF = {
41
- settlement: "answer",
42
- origin: "answer",
43
- classes: "answer",
44
- inputDigest: "answer",
45
- classifierCause: "classifierCause",
46
- classifierRound: "classifierRound",
47
- unresolvableCause: "unresolvableCause",
48
- foldedClasses: "foldedClasses",
49
- pathDenial: "pathDenial",
50
- bindingRefusal: "bindingRefusal",
51
- };
52
- const ATTESTATION_MEMBERS = Object.keys(ATTESTATION_GROUP_OF);
53
- const groupLead = (g) => ATTESTATION_MEMBERS.find((k) => ATTESTATION_GROUP_OF[k] === g);
54
- const ENGINE_ATTESTATIONS = new WeakSet();
55
- function detachedMember(v) {
56
- if (Array.isArray(v))
57
- return Object.freeze([...v]);
58
- if (typeof v !== "object" || v === null)
59
- return v;
60
- return Object.freeze(Object.fromEntries(Object.entries(v).map(([k, x]) => [k, typeof x === "object" && x !== null ? Object.freeze(Array.isArray(x) ? [...x] : { ...x }) : x])));
61
- }
62
- export function mintAttestation(call, members) {
63
- const record = { toolCallId: call.toolCallId, toolName: call.toolName };
64
- for (const k of ATTESTATION_MEMBERS)
65
- if (members[k] !== undefined)
66
- record[k] = detachedMember(members[k]);
67
- const minted = Object.freeze(record);
68
- ENGINE_ATTESTATIONS.add(minted);
69
- return minted;
70
- }
71
- export function isEngineAttestation(v) {
72
- return typeof v === "object" && v !== null && ENGINE_ATTESTATIONS.has(v);
73
- }
74
- const boundTo = (r, call) => isEngineAttestation(r) && r.toolCallId === call.toolCallId && r.toolName === call.toolName ? r : undefined;
75
- export function attestationOf(d, call) {
76
- if (typeof d !== "object" || d === null)
77
- return undefined;
78
- return boundTo(Object.getOwnPropertyDescriptor(d, "attestation")?.value, call);
79
- }
80
- export function mergeAttestation(call, earlier, later, scope = "all") {
81
- const a = boundTo(earlier, call);
82
- const b = boundTo(later, call);
83
- if (a === undefined)
84
- return b;
85
- const members = {};
86
- if (b !== undefined)
87
- for (const k of ATTESTATION_MEMBERS)
88
- if (b[k] !== undefined)
89
- members[k] = b[k];
90
- let filled = false;
91
- for (const g of new Set(Object.values(ATTESTATION_GROUP_OF))) {
92
- if ((scope === "answer" && g !== "answer") || members[groupLead(g)] !== undefined || a[groupLead(g)] === undefined)
93
- continue;
94
- for (const k of ATTESTATION_MEMBERS)
95
- if (ATTESTATION_GROUP_OF[k] === g && a[k] !== undefined)
96
- members[k] = a[k];
97
- filled = true;
98
- }
99
- if (!filled)
100
- return b;
101
- return mintAttestation(call, members);
102
- }
103
- export function attest(d, call, members) {
104
- return withAttestation(d, mergeAttestation(call, attestationOf(d, call), mintAttestation(call, members)));
105
- }
106
- export function withAttestation(d, record) {
107
- return record === undefined ? d : { ...d, attestation: record };
108
- }
42
+ export { attest, attestationOf, isEngineAttestation, mergeAttestation, mintAttestation, withAttestation } from "./engine-attestation.js";
109
43
  const UNASKED_SEAT_SETTLEMENTS = new Set(["task_aborted", "no_approver"]);
110
44
  function seatNeverAsked(settlement) {
111
45
  return settlement !== undefined && UNASKED_SEAT_SETTLEMENTS.has(settlement.kind);
@@ -196,21 +130,11 @@ export function toolPolicyWriteGuardRows(policies) {
196
130
  return undefined;
197
131
  return async (at) => (await Promise.all(sources.map((rowsOf) => rowsOf(at)))).flat();
198
132
  }
199
- export function namespacedCoveringEntries(entries, behavior) {
200
- return (entries ?? []).filter((entry) => isNamespacedCoveringRuleName(entry, behavior));
133
+ export function coveringRuleEntries(entries, behavior) {
134
+ return (entries ?? []).filter((entry) => isCoveringRuleName(entry, behavior));
201
135
  }
202
- function allowlistNameRefusal(who, entry, list) {
203
- if (typeof entry !== "string")
204
- return undefined;
205
- const sentence = wildcardPeerRefusalOf(ruleSpellingOf(entry)?.toolName ?? entry, "allow");
206
- if (sentence === undefined)
207
- return undefined;
208
- const e = new Error(`${who}: ${list} entry "${entry}" — ${sentence}`);
209
- e.code = "config.invalid_tool_name_set";
210
- return e;
211
- }
212
- export function namespacedCoveringHit(covering, call) {
213
- return covering.length > 0 && nameListHolds({ has: (name) => covering.some((e) => namespacedRuleNameCovers(e, name)) }, call);
136
+ export function coveringRuleHit(covering, call) {
137
+ return covering.length > 0 && nameListHolds({ has: (name) => covering.some((e) => ruleNameCovers(e, name)) }, call);
214
138
  }
215
139
  export function projectionToolNames(c) {
216
140
  return c.kind === "shell_command" ? { member: "tools", list: c.tools } : { member: "names", list: c.names };
@@ -219,13 +143,13 @@ export function checkToolPolicyProjection(projection, req) {
219
143
  const listed = (list) => heldBy("policy.projectionReplay", { has: (n) => list.includes(n) }, req);
220
144
  for (const c of projection.components) {
221
145
  if (c.kind === "tool_deny") {
222
- if (listed(c.names) || namespacedCoveringHit(namespacedCoveringEntries(c.names, "deny"), req)) {
146
+ if (listed(c.names) || coveringRuleHit(coveringRuleEntries(c.names, "deny"), req)) {
223
147
  return { action: "deny", message: `tool "${req.toolName}" is denied by a frozen inherited policy projection` };
224
148
  }
225
149
  continue;
226
150
  }
227
151
  if (c.kind === "tool_allowlist") {
228
- if (!listed(c.names) && !namespacedCoveringHit(namespacedCoveringEntries(c.names, "allow"), req)) {
152
+ if (!listed(c.names) && !coveringRuleHit(coveringRuleEntries(c.names, "allow"), req)) {
229
153
  return { action: "deny", message: `tool "${req.toolName}" is not in a frozen inherited policy projection's allowlist` };
230
154
  }
231
155
  continue;
@@ -300,6 +224,12 @@ const HOOK_SEAM_UNREAD = new Set(["decisionReason"]);
300
224
  const HOOK_SEAM_OPTIONAL = new Set(["action"]);
301
225
  const HOOK_RECEIPTS = new WeakSet();
302
226
  const ENGINE_RECEIPTS = new WeakSet();
227
+ function askOfAnotherCall(d, call) {
228
+ if (call === undefined || d.action !== "ask" || d.attestation === undefined || attestationOf(d, call) !== undefined)
229
+ return undefined;
230
+ return refusedOutOfContract(`a permission decision asks with the engine's record of another call — what the engine found about that call's question is not this call's; ` +
231
+ `a policy answers the call it is asked about (a cached or relayed ask is asked again); denied fail-closed rather than reading the findings as absent`);
232
+ }
303
233
  export function refuseOutOfContractDecision(d, opts) {
304
234
  const hookSeam = opts?.reasonIsNonInput === true;
305
235
  if (hookSeam && (d === null || d === undefined || Object.is(d, false)))
@@ -308,7 +238,7 @@ export function refuseOutOfContractDecision(d, opts) {
308
238
  return refusedOutOfContract(`a permission decision's "action" is absent (the decision is ${d === null || d === undefined ? String(d) : `a ${typeof d}`}, not an object) — the closed set is allow/deny/ask; denied fail-closed rather than reading a word outside it as an allow`);
309
239
  }
310
240
  if ((hookSeam ? HOOK_RECEIPTS : ENGINE_RECEIPTS).has(d) || isEngineRefusal(d))
311
- return d;
241
+ return askOfAnotherCall(d, opts?.call) ?? d;
312
242
  const decision = receiveContract(d, hookSeam ? HOOK_RESULT_MEMBERS : DECISION_MEMBERS, "", RETIRED_DECISION_MEMBERS);
313
243
  if (decision.kind === "refused")
314
244
  return decision.refused;
@@ -323,13 +253,9 @@ export function refuseOutOfContractDecision(d, opts) {
323
253
  : `a permission decision carries an "attestation" the engine did not mint — the member is an engine record (who settled the call, ` +
324
254
  `which question it answered); denied fail-closed rather than reading a caller's value as a settlement`);
325
255
  }
326
- const folded = contract.foldedAskClasses;
327
- const signed = attestation?.foldedClasses;
328
- if (folded !== undefined && !(signed !== undefined && Array.isArray(folded) && signed.length === folded.length && signed.every((c, i) => c === folded[i]))) {
329
- return refusedOutOfContract(`a permission decision carries "foldedAskClasses" that no policy fold of the engine attested on it — the member is ` +
330
- `engine-written (combinePolicies records the classes of the asks it collapsed); denied fail-closed rather than letting a ` +
331
- `class no station judged reach the class derivation`);
332
- }
256
+ const foreign = askOfAnotherCall({ action: contract.action, attestation }, opts?.call);
257
+ if (foreign !== undefined)
258
+ return foreign;
333
259
  if (hookSeam && contract.additionalContext !== undefined && typeof contract.additionalContext !== "string") {
334
260
  return refusedOutOfContract(`a PreToolUse hook result's "additionalContext" is not a string — the member is the text appended for the model; denied fail-closed rather than rendering a value this layer cannot classify`);
335
261
  }
@@ -387,86 +313,75 @@ export function toolPolicyNameSets(p) {
387
313
  const sets = p?.nameSets;
388
314
  return Array.isArray(sets) ? sets : [];
389
315
  }
390
- export function createAllowDenyPolicy(opts) {
391
- assertNoRetiredKeys(opts, RETIRED_ALLOW_DENY_POLICY_OPTIONS, "createAllowDenyPolicy");
392
- const invalid = [];
393
- const screen = (entries, list) => {
394
- if (entries === undefined)
395
- return undefined;
396
- const kept = [];
397
- const seen = new Set();
398
- for (const entry of entries) {
399
- const ns = protocolOf(entry);
400
- if (ns !== undefined) {
401
- const suffix = entry.slice(ns.prefix.length);
402
- const sep = suffix.indexOf("__");
403
- const malformed = suffix.length === 0 || sep === 0 || (sep > 0 && suffix.length === sep + 2);
404
- if (malformed) {
405
- const family = ns.id.toUpperCase();
406
- const lesson = `a malformed ${family} tool name (empty peer or tool segment) — it can never match any mounted tool. ` +
407
- `Use \`${ns.prefix}<peer>\` for every tool of a peer, or \`${ns.prefix}<peer>__<tool>\` for one tool.`;
408
- invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
409
- continue;
410
- }
411
- }
412
- const spelled = ruleSpellingOf(entry);
413
- if (spelled === undefined) {
414
- const lesson = `a spelling no tool name can have — the rule syntax reads no tool name in it, so a name set never names a tool by it. Fix the entry.`;
316
+ function screenToolNameList(entries, list, behavior, invalid) {
317
+ if (entries === undefined)
318
+ return undefined;
319
+ const kept = [];
320
+ const seen = new Set();
321
+ for (const entry of entries) {
322
+ const ns = protocolOf(entry);
323
+ if (ns !== undefined) {
324
+ const suffix = entry.slice(ns.prefix.length);
325
+ const sep = suffix.indexOf("__");
326
+ if (suffix.length === 0 || sep === 0 || (sep > 0 && suffix.length === sep + 2)) {
327
+ const lesson = `a malformed ${ns.id.toUpperCase()} tool name (empty peer or tool segment) — it can never match any mounted tool. ` +
328
+ `Use \`${ns.prefix}<peer>\` for every tool of a peer, or \`${ns.prefix}<peer>__<tool>\` for one tool.`;
415
329
  invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
416
330
  continue;
417
331
  }
418
- if (ruleContentOf(spelled) === undefined) {
419
- if (spelled.toolName === "*" && list === "deny") {
420
- const lesson = `the wildcard — \`*\` names no tool, and a deny entry reaches the tool it names, so this one would be kept and never match ` +
421
- `(a deny that reads protective and denies nothing). Name the tools to deny; to leave a run no tools, write an empty allow list.`;
422
- invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
423
- continue;
424
- }
425
- const wild = list === "allow" ? wildcardPeerRefusalOf(spelled.toolName, "allow") : undefined;
426
- if (wild !== undefined) {
427
- invalid.push({ entry, list, message: `"${entry}": ${wild}`, lesson: wild });
428
- continue;
429
- }
430
- if (!seen.has(spelled.toolName)) {
431
- seen.add(spelled.toolName);
432
- kept.push(spelled.toolName);
433
- }
434
- continue;
435
- }
332
+ }
333
+ const spelled = ruleSpellingOf(entry);
334
+ if (spelled === undefined) {
335
+ const lesson = `a spelling no tool name can have — the rule syntax reads no tool name in it, so a name set never names a tool by it. Fix the entry.`;
336
+ invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
337
+ continue;
338
+ }
339
+ if (ruleContentOf(spelled) !== undefined) {
436
340
  const lesson = `a rule CONTENT form, not a tool name — a name set matches raw tool names, so this entry ` +
437
341
  `can never match any mounted tool (in an allow list it removes the tool entirely). Use the tool NAME here, ` +
438
342
  `and route the narrowing through the lane that speaks this grammar: parameter rules via ` +
439
343
  `createPermissionRulePolicy, Bash command prefixes via the persisted allow-rule lane.`;
440
344
  invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
345
+ continue;
441
346
  }
442
- return kept;
443
- };
444
- const screenedAllow = screen(opts.allow, "allow");
445
- const screenedDeny = screen(opts.deny, "deny");
446
- if (invalid.length > 0) {
447
- if ((opts.onInvalidName ?? "throw") === "throw") {
448
- const byLesson = new Map();
449
- for (const i of invalid) {
450
- const group = byLesson.get(i.lesson) ?? [];
451
- group.push({ entry: i.entry, list: i.list });
452
- byLesson.set(i.lesson, group);
453
- }
454
- const e = new Error(`createAllowDenyPolicy: ${invalid.length} entr${invalid.length === 1 ? "y is" : "ies are"} not tool name(s):\n` +
455
- [...byLesson.entries()]
456
- .map(([lesson, group]) => ` Each of the following is ${lesson}\n` + group.map((g) => ` [${g.list}] "${g.entry}"`).join("\n"))
457
- .join("\n"));
458
- e.code = "config.invalid_tool_name_set";
459
- e.issues = invalid;
460
- throw e;
347
+ const wild = behavior === "allow" ? grantWildcardRefusalOf(spelled.toolName) : undefined;
348
+ if (wild !== undefined) {
349
+ invalid.push({ entry, list, message: `"${entry}": ${wild}`, lesson: wild });
350
+ continue;
461
351
  }
352
+ if (!seen.has(spelled.toolName)) {
353
+ seen.add(spelled.toolName);
354
+ kept.push(spelled.toolName);
355
+ }
356
+ }
357
+ return kept;
358
+ }
359
+ function toolNameSetRefusal(who, invalid) {
360
+ const byLesson = new Map();
361
+ for (const i of invalid)
362
+ byLesson.set(i.lesson, [...(byLesson.get(i.lesson) ?? []), { entry: i.entry, list: i.list }]);
363
+ const e = new Error(`${who}: ${invalid.length} entr${invalid.length === 1 ? "y is" : "ies are"} not tool name(s):\n` +
364
+ [...byLesson.entries()].map(([lesson, group]) => ` Each of the following is ${lesson}\n` + group.map((g) => ` [${g.list}] "${g.entry}"`).join("\n")).join("\n"));
365
+ e.code = "config.invalid_tool_name_set";
366
+ e.issues = invalid;
367
+ return e;
368
+ }
369
+ export function createAllowDenyPolicy(opts) {
370
+ assertNoRetiredKeys(opts, RETIRED_ALLOW_DENY_POLICY_OPTIONS, "createAllowDenyPolicy");
371
+ const invalid = [];
372
+ const screenedAllow = screenToolNameList(opts.allow, "allow", "allow", invalid);
373
+ const screenedDeny = screenToolNameList(opts.deny, "deny", "deny", invalid);
374
+ if (invalid.length > 0) {
375
+ if ((opts.onInvalidName ?? "throw") === "throw")
376
+ throw toolNameSetRefusal("createAllowDenyPolicy", invalid);
462
377
  for (const issue of invalid)
463
378
  opts.onInvalidNameIssue?.(issue);
464
379
  }
465
380
  opts = { ...opts, ...(screenedAllow ? { allow: screenedAllow } : {}), ...(screenedDeny ? { deny: screenedDeny } : {}) };
466
381
  const allow = opts.allow ? new Set(opts.allow) : undefined;
467
382
  const deny = new Set(opts.deny ?? []);
468
- const denyCovering = namespacedCoveringEntries(opts.deny, "deny");
469
- const allowCovering = namespacedCoveringEntries(opts.allow, "allow");
383
+ const denyCovering = coveringRuleEntries(opts.deny, "deny");
384
+ const allowCovering = coveringRuleEntries(opts.allow, "allow");
470
385
  return {
471
386
  projection: {
472
387
  components: [
@@ -477,10 +392,10 @@ export function createAllowDenyPolicy(opts) {
477
392
  },
478
393
  nameSets: [{ ...(opts.allow ? { allow: [...opts.allow] } : {}), ...(opts.deny ? { deny: [...opts.deny] } : {}) }],
479
394
  check(req) {
480
- if (nameListHolds(deny, req) || namespacedCoveringHit(denyCovering, req)) {
395
+ if (nameListHolds(deny, req) || coveringRuleHit(denyCovering, req)) {
481
396
  return { action: "deny", message: `tool "${req.toolName}" is denied by policy` };
482
397
  }
483
- if (allow && !nameListHolds(allow, req) && !namespacedCoveringHit(allowCovering, req)) {
398
+ if (allow && !nameListHolds(allow, req) && !coveringRuleHit(allowCovering, req)) {
484
399
  return { action: "deny", message: `tool "${req.toolName}" is not in the allowlist` };
485
400
  }
486
401
  return ALLOW;
@@ -497,19 +412,21 @@ export function createApprovalPolicy(opts) {
497
412
  if (opts.approvalTimeoutMs !== undefined && opts.approvalTimeoutMs > 2_147_483_647) {
498
413
  throw new Error(`createApprovalPolicy: approvalTimeoutMs must not exceed 2147483647ms (~24.8 days) (got ${opts.approvalTimeoutMs}) — a host timer truncates a larger delay and fires immediately, denying every request at once; omit it to wait indefinitely`);
499
414
  }
500
- for (const [list, entries] of [["autoAllow", opts.autoAllow ?? []], ["requireApproval", opts.denyByDefault === true ? opts.requireApproval : []]]) {
501
- for (const entry of entries) {
502
- const refusal = allowlistNameRefusal("createApprovalPolicy", entry, list);
503
- if (refusal !== undefined)
504
- throw refusal;
505
- }
506
- }
415
+ const invalid = [];
416
+ const requireApproval = screenToolNameList(opts.requireApproval, "requireApproval", "ask", invalid) ?? [];
417
+ const denied = screenToolNameList(opts.deny, "deny", "deny", invalid);
418
+ const autoAllow = screenToolNameList(opts.autoAllow, "autoAllow", "allow", invalid);
419
+ if (opts.denyByDefault === true)
420
+ screenToolNameList(requireApproval, "requireApproval", "allow", invalid);
421
+ if (invalid.length > 0)
422
+ throw toolNameSetRefusal("createApprovalPolicy", invalid);
423
+ opts = { ...opts, requireApproval, ...(denied !== undefined ? { deny: denied } : {}), ...(autoAllow !== undefined ? { autoAllow } : {}) };
507
424
  const need = new Set(opts.requireApproval);
508
425
  const deny = new Set(opts.deny ?? []);
509
426
  const auto = new Set(opts.autoAllow ?? []);
510
- const needCovering = namespacedCoveringEntries(opts.requireApproval, "ask");
511
- const denyCovering = namespacedCoveringEntries(opts.deny, "deny");
512
- const autoCovering = namespacedCoveringEntries(opts.autoAllow, "allow");
427
+ const needCovering = coveringRuleEntries(opts.requireApproval, "ask");
428
+ const denyCovering = coveringRuleEntries(opts.deny, "deny");
429
+ const autoCovering = coveringRuleEntries(opts.autoAllow, "allow");
513
430
  return {
514
431
  projection: {
515
432
  components: [
@@ -526,10 +443,10 @@ export function createApprovalPolicy(opts) {
526
443
  },
527
444
  ],
528
445
  async check(req, signal) {
529
- if (nameListHolds(deny, req) || namespacedCoveringHit(denyCovering, req)) {
446
+ if (nameListHolds(deny, req) || coveringRuleHit(denyCovering, req)) {
530
447
  return { action: "deny", message: `tool "${req.toolName}" is denied by policy` };
531
448
  }
532
- if (nameListHolds(need, req) || namespacedCoveringHit(needCovering, req)) {
449
+ if (nameListHolds(need, req) || coveringRuleHit(needCovering, req)) {
533
450
  const attestOver = (inputDigest) => (d, settlement, bindingRefusal) => ({ ...d, attestation: mintAttestation(req, { settlement, origin: "policy", ...(inputDigest !== undefined ? { inputDigest } : {}), ...(bindingRefusal !== undefined ? { bindingRefusal } : {}) }) });
534
451
  const unasked = unaskedSeatAnswer(req, signal, { aborted: `approval aborted for "${req.toolName}" (run or turn interrupted)`, unreachable: `approval for "${req.toolName}" was not requested: nobody can be asked about this call` }, "policy");
535
452
  if (unasked !== undefined)
@@ -592,7 +509,7 @@ export function createApprovalPolicy(opts) {
592
509
  }
593
510
  return attest({ action: "deny", message: `approval denied for "${req.toolName}"` }, settledByDecider("person", "refused", undefined));
594
511
  }
595
- if (nameListHolds(auto, req) || namespacedCoveringHit(autoCovering, req))
512
+ if (nameListHolds(auto, req) || coveringRuleHit(autoCovering, req))
596
513
  return ALLOW;
597
514
  if (opts.denyByDefault) {
598
515
  return { action: "deny", message: `tool "${req.toolName}" requires explicit allow` };
@@ -636,7 +553,6 @@ export function combinePolicies(...policies) {
636
553
  let asked;
637
554
  let current = Object.freeze({ ...req });
638
555
  let rewrite;
639
- let records;
640
556
  let ruleAskText;
641
557
  let probeMandateSeen = false;
642
558
  let mandateSeen = false;
@@ -644,25 +560,64 @@ export function combinePolicies(...policies) {
644
560
  let noRulingSeen;
645
561
  let authoredBySeen = false;
646
562
  const contributors = [];
647
- const settleDeny = (d) => {
563
+ const decisions = [];
564
+ const recordsExcept = (at) => decisions.reduce((acc, d, j) => (j !== at && d?.action === "allow" && d.attestation !== undefined ? mergeAttestation(req, acc, d.attestation) : acc), undefined);
565
+ const settleDeny = (d, at) => {
648
566
  const out = rewrite !== undefined ? refusalOf(d, current.args) : d;
567
+ const records = recordsExcept(at);
649
568
  if (records === undefined)
650
569
  return out;
651
570
  return { ...out, attestation: mergeAttestation(req, records, d.attestation) };
652
571
  };
653
572
  let seatDeny;
654
- for (const p of policies) {
655
- const d = refuseOutOfContractDecision(await p.check(current, signal));
573
+ const denied = (d, at) => {
574
+ decisions[at] = undefined;
575
+ if (!seatNeverAsked(attestationOf(d, current)?.settlement))
576
+ return settleDeny(d, at);
577
+ seatDeny ??= settleDeny(d, at);
578
+ return undefined;
579
+ };
580
+ let emitter = -1;
581
+ let personWrote = false;
582
+ for (const [at, p] of policies.entries()) {
583
+ const d = refuseOutOfContractDecision(await p.check(current, signal), { call: req });
656
584
  if (d.action === "deny") {
657
- if (!seatNeverAsked(attestationOf(d, current)?.settlement))
658
- return settleDeny(d);
659
- seatDeny ??= settleDeny(d);
585
+ const ended = denied(d, at);
586
+ if (ended !== undefined)
587
+ return ended;
660
588
  continue;
661
589
  }
662
- if (d.updatedInput !== undefined) {
590
+ decisions[at] = d;
591
+ if (readRejudge(current, current.args, d).kind === "rewritten") {
592
+ if (personWrote)
593
+ return settleDeny({ action: "deny", message: `${editRewrittenSentence(req.toolName)}, which a later policy layer wrote over a person's edit — denied fail-closed` }, at);
663
594
  current = Object.freeze(await withArgsReading(current, d.updatedInput, signal));
664
595
  rewrite = d;
596
+ emitter = at;
597
+ personWrote = attestationOf(d, current)?.settlement?.who.party === "person" && answeredFor(d, req, current.args);
598
+ }
599
+ }
600
+ for (let at = 0; at < emitter; at++) {
601
+ const p = policies[at];
602
+ const d = refuseOutOfContractDecision(await p.check(current, signal), { call: req });
603
+ if (d.action === "deny") {
604
+ const ended = denied(d, at);
605
+ if (ended !== undefined)
606
+ return ended;
607
+ continue;
665
608
  }
609
+ if (readRejudge(current, current.args, d).kind === "rewritten")
610
+ return settleDeny({ action: "deny", message: rewriteChasedSentence(req.toolName) }, at);
611
+ const { updatedInput: _sameBytes, ...asIs } = d;
612
+ const first = decisions[at];
613
+ decisions[at] = asIs.action === "allow" && first?.action === "allow" && first.attestation !== undefined ? withAttestation(asIs, mergeAttestation(req, first.attestation, asIs.attestation)) : asIs;
614
+ }
615
+ if (seatDeny !== undefined)
616
+ return seatDeny;
617
+ let records;
618
+ for (const d of decisions) {
619
+ if (d === undefined)
620
+ continue;
666
621
  if (d.action === "allow" && d.attestation !== undefined)
667
622
  records = mergeAttestation(req, records, d.attestation);
668
623
  if (d.action === "ask" && (asked === undefined || (d.requiresRealApproval === true && asked.requiresRealApproval !== true))) {
@@ -684,8 +639,6 @@ export function combinePolicies(...policies) {
684
639
  if (d.action === "ask")
685
640
  contributors.push(d);
686
641
  }
687
- if (seatDeny !== undefined)
688
- return seatDeny;
689
642
  if (asked) {
690
643
  const merged = rewrite?.updatedInput;
691
644
  const withRuleAsk = ruleAskText !== undefined && asked.matchedAskRule === undefined ? { ...asked, matchedAskRule: ruleAskText } : asked;
@@ -694,16 +647,15 @@ export function combinePolicies(...policies) {
694
647
  const withFallback = fallbackSeen !== undefined && withMandate.denialLimitFallback === undefined ? { ...withMandate, denialLimitFallback: fallbackSeen, requiresRealApproval: true } : withMandate;
695
648
  const withNoRuling = noRulingSeen !== undefined && withFallback.classifierNoRuling === undefined ? { ...withFallback, classifierNoRuling: noRulingSeen, requiresRealApproval: true } : withFallback;
696
649
  const withAuthor = authoredBySeen && withNoRuling.authoredBy === undefined ? { ...withNoRuling, authoredBy: "deployment" } : withNoRuling;
697
- const folded = new Set(withAuthor.foldedAskClasses ?? []);
650
+ const folded = new Set(attestationOf(asked, req)?.foldedClasses ?? []);
698
651
  for (const c of contributors)
699
652
  if (c !== asked)
700
- for (const k of decisionAskClassesOf(c))
653
+ for (const k of decisionAskClassesOf(c, req))
701
654
  folded.add(k);
702
655
  if (withNoRuling !== withMandate)
703
- for (const k of decisionAskClassesOf(asked))
656
+ for (const k of decisionAskClassesOf(asked, req))
704
657
  folded.add(k);
705
- const withClasses = folded.size > 0 ? { ...withAuthor, foldedAskClasses: [...folded] } : withAuthor;
706
- const out = merged !== undefined ? { ...withClasses, updatedInput: merged } : withClasses;
658
+ const out = merged !== undefined ? { ...withAuthor, updatedInput: merged } : withAuthor;
707
659
  return folded.size > 0 ? attest(out, req, { foldedClasses: [...folded] }) : out;
708
660
  }
709
661
  const allowed = rewrite ?? ALLOW;
@@ -780,17 +732,17 @@ export function createUnverifiableDeletePolicy(opts) {
780
732
  if (typeof command !== "string")
781
733
  return ALLOW;
782
734
  const removal = removalReadingOf(command, req, opts?.removalSeat, safeRoots);
783
- return removal === undefined ? ALLOW : removal.judge(signal).then((found) => (found === undefined ? ALLOW : removalAsk(found.guard, found.text)));
735
+ return removal === undefined ? ALLOW : removal.judge(signal).then((found) => (found === undefined ? ALLOW : removalAsk(req, found.guard, found.text)));
784
736
  },
785
737
  }, "external_authority");
786
738
  }
787
- function removalAsk(guard, text) {
739
+ function removalAsk(req, guard, text) {
788
740
  const messages = {
789
741
  dangerous_delete: `Dangerous removal: ${text}. No permission mode, allow rule or classifier clears this — only a person confirming this call does.`,
790
742
  unverifiable_delete: `Unverifiable recursive delete (fail-closed unless cleared): ${text}. Re-run the delete with the resolved literal path written into the command itself (or assign the variable a literal path in the same command, e.g. \`DIR=/exact/path; rm -rf "$DIR"\`) so the target can be verified.`,
791
- unverifiable_shell_text: `Unverifiable shell text (fail-closed unless cleared): ${text}. Write the text into the command itself (a \`-c\` string, a here-document or a here-string) and the engine reads it as it reads any command.`,
743
+ unverifiable_shell_text: `Unverifiable shell text (fail-closed unless cleared): ${text}.`,
792
744
  };
793
- return { action: "ask", decisionReason: "safety", requiresRealApproval: true, guards: [guard], message: messages[guard] };
745
+ return attest({ action: "ask", decisionReason: "safety", requiresRealApproval: true, message: messages[guard] }, req, { guards: [guard] });
794
746
  }
795
747
  function pathSegments(p) {
796
748
  return p.split(/[\\/]/).filter(Boolean);
@@ -859,16 +811,15 @@ export function createTranscriptIntegrityPolicy(opts) {
859
811
  }
860
812
  return false;
861
813
  };
862
- const askReason = (what) => ({
814
+ const askReason = (req, what) => attest({
863
815
  action: "ask",
864
816
  decisionReason: "safety",
865
817
  requiresRealApproval: true,
866
- guards: ["transcript_write"],
867
818
  message: `Session-transcript write (fail-closed unless cleared): ${what}. Session transcripts (the .jsonl files ` +
868
819
  `under the agent data dir's sessions/ directory) are harness-written session state, not agent working ` +
869
820
  `files — modifying or deleting them tampers with the run's own audit trail. Reading them (ls/cat/grep ` +
870
821
  `as a single simple command) is fine.`,
871
- });
822
+ }, req, { guards: ["transcript_write"] });
872
823
  return brandPolicyAskClass({
873
824
  check(req) {
874
825
  if (shellToolsListHolds(shellTools, req)) {
@@ -882,7 +833,7 @@ export function createTranscriptIntegrityPolicy(opts) {
882
833
  const parsed = parseLeadingCommandName(command);
883
834
  if ("name" in parsed && readAllow.has(parsed.name))
884
835
  return ALLOW;
885
- return askReason("name" in parsed
836
+ return askReason(req, "name" in parsed
886
837
  ? `\`${parsed.name}\` is not a read-only command${cwdInsideProtected ? " and the shell's working directory is inside the transcript directory" : ""}`
887
838
  : cwdInsideProtected
888
839
  ? "the shell's working directory is inside the transcript directory and this is not a single read-only command (fail-closed)"
@@ -892,7 +843,7 @@ export function createTranscriptIntegrityPolicy(opts) {
892
843
  if (writeTarget !== undefined && writeTarget.access !== "read") {
893
844
  const p = writeTargetPath(req);
894
845
  if (typeof p === "string" && inProtectedDir(p, req.cwd)) {
895
- return askReason(`"${p}" is inside the session-transcript directory`);
846
+ return askReason(req, `"${p}" is inside the session-transcript directory`);
896
847
  }
897
848
  }
898
849
  return ALLOW;
@@ -6,6 +6,7 @@ import { deliverEngineNotice } from "./types.js";
6
6
  import { TOOL_SEARCH_NAME } from "./runner/tool-disclosure.js";
7
7
  import { mountRuleFace, toolFace } from "./tool-catalog-entries.js";
8
8
  import { thrownText } from "./thrown-value.js";
9
+ import { carryNotStartedReceipt } from "./delegation-not-started.js";
9
10
  export const TOOL_RESULT_REF_CONFLICT_CODE = "tool_result.ref_conflict";
10
11
  export class ToolResultRefConflictError extends Error {
11
12
  ref;
@@ -239,6 +240,8 @@ export function withToolResultOffload(tool, store, thresholdChars, sessionId, re
239
240
  const wrappedExecute = async (toolCallId, params, signal, onUpdate) => {
240
241
  const res = await tool.execute(toolCallId, params, signal, onUpdate);
241
242
  const offloadedDetails = res.details === undefined ? undefined : await offloadOversizedDetailStrings(res.details, store, thresholdChars, sessionId, toolCallId, provenance);
243
+ if (offloadedDetails !== undefined)
244
+ carryNotStartedReceipt(res.details, offloadedDetails.value);
242
245
  const withDetails = (r) => offloadedDetails === undefined || offloadedDetails.value === res.details ? r : { ...r, details: offloadedDetails.value };
243
246
  if (totalTextChars(res.content) <= thresholdChars)
244
247
  return withDetails(res);