@sema-agent/core 7.51.2 → 7.53.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 (446) hide show
  1. package/CHANGELOG.md +698 -2
  2. package/README.md +3 -1
  3. package/dist/agents/agent-transcript-tool.d.ts +1 -1
  4. package/dist/agents/cascade.js +4 -0
  5. package/dist/agents/cross-session-envelope.d.ts +8 -0
  6. package/dist/agents/cross-session-envelope.js +6 -0
  7. package/dist/agents/cross-session-judge.d.ts +21 -1
  8. package/dist/agents/cross-session-judge.js +8 -0
  9. package/dist/agents/cross-session-ref.d.ts +5 -0
  10. package/dist/agents/cross-session-ref.js +1 -0
  11. package/dist/agents/cumulative-stats.d.ts +3 -0
  12. package/dist/agents/cumulative-stats.js +3 -0
  13. package/dist/agents/list-agents-tool.d.ts +1 -1
  14. package/dist/agents/org-delivery-gate.d.ts +122 -0
  15. package/dist/agents/org-delivery-gate.js +69 -0
  16. package/dist/agents/peer-held-queue.d.ts +9 -4
  17. package/dist/agents/peer-held-queue.js +6 -5
  18. package/dist/agents/peer-session-drain.d.ts +35 -5
  19. package/dist/agents/peer-session-drain.js +271 -180
  20. package/dist/agents/read-inbox-tool.d.ts +8 -1
  21. package/dist/agents/read-inbox-tool.js +5 -1
  22. package/dist/agents/repair-loop.js +4 -0
  23. package/dist/agents/send-message-tool.d.ts +11 -16
  24. package/dist/agents/send-message-tool.js +11 -13
  25. package/dist/agents/subagent.d.ts +3 -0
  26. package/dist/agents/subagent.js +105 -76
  27. package/dist/agents/tool-filter.d.ts +58 -13
  28. package/dist/agents/tool-filter.js +34 -14
  29. package/dist/bench/metrics.d.ts +1 -0
  30. package/dist/brain/anthropic.d.ts +6 -1
  31. package/dist/brain/anthropic.js +17 -13
  32. package/dist/brain/model-presets.d.ts +4 -5
  33. package/dist/brain/model-presets.js +6 -5
  34. package/dist/brain/open-responses.js +16 -12
  35. package/dist/brain/openai.js +16 -12
  36. package/dist/brain/request-params.d.ts +12 -33
  37. package/dist/brain/request-params.js +5 -2
  38. package/dist/brain/request-route.d.ts +9 -8
  39. package/dist/brain/request-route.js +1 -0
  40. package/dist/brain/route-adjudicator.d.ts +123 -47
  41. package/dist/brain/route-adjudicator.js +171 -42
  42. package/dist/brain/route-conformance.js +2 -2
  43. package/dist/brain/routing.d.ts +24 -1
  44. package/dist/brain/routing.js +54 -19
  45. package/dist/brain/status-sink.d.ts +18 -0
  46. package/dist/brain/status-sink.js +7 -0
  47. package/dist/brain/timeout.js +5 -4
  48. package/dist/core/a2a.d.ts +5 -2
  49. package/dist/core/a2a.js +30 -13
  50. package/dist/core/allow-entry.d.ts +42 -9
  51. package/dist/core/allow-entry.js +25 -18
  52. package/dist/core/auto-compaction.d.ts +80 -20
  53. package/dist/core/auto-compaction.js +65 -18
  54. package/dist/core/auto-promote.d.ts +2 -1
  55. package/dist/core/auto-promote.js +2 -2
  56. package/dist/core/caller-tool-name.d.ts +9 -0
  57. package/dist/core/caller-tool-name.js +13 -0
  58. package/dist/core/checkpoint-requirements.d.ts +7 -1
  59. package/dist/core/checkpoint-requirements.js +2 -0
  60. package/dist/core/checkpoint-store.d.ts +57 -24
  61. package/dist/core/checkpoint-store.js +3 -3
  62. package/dist/core/child-clamp-seats.d.ts +6 -0
  63. package/dist/core/child-clamp-seats.js +2 -1
  64. package/dist/core/compliance.js +3 -1
  65. package/dist/core/credential-vocabulary.d.ts +33 -8
  66. package/dist/core/credential-vocabulary.js +32 -7
  67. package/dist/core/decision-receipt.d.ts +2 -2
  68. package/dist/core/delegation-frames.d.ts +9 -2
  69. package/dist/core/delegation-name.d.ts +18 -0
  70. package/dist/core/delegation-name.js +47 -0
  71. package/dist/core/effective-path-target.d.ts +25 -6
  72. package/dist/core/effective-path-target.js +24 -2
  73. package/dist/core/engine-capabilities.d.ts +8 -1
  74. package/dist/core/engine-capabilities.js +1 -1
  75. package/dist/core/engine-notice.d.ts +49 -21
  76. package/dist/core/frontmatter-fence.d.ts +10 -0
  77. package/dist/core/frontmatter-fence.js +6 -0
  78. package/dist/core/gate-fold.js +8 -25
  79. package/dist/core/gate-lanes.js +358 -274
  80. package/dist/core/gate-outcome.d.ts +11 -6
  81. package/dist/core/governance-codes.d.ts +11 -4
  82. package/dist/core/governance-codes.js +12 -3
  83. package/dist/core/hands-band-screen.d.ts +7 -0
  84. package/dist/core/hands-band-screen.js +32 -0
  85. package/dist/core/hooks.d.ts +283 -739
  86. package/dist/core/hooks.js +100 -193
  87. package/dist/{tools/fs → core}/image-admission.d.ts +21 -3
  88. package/dist/{tools/fs → core}/image-admission.js +24 -6
  89. package/dist/core/locked-config.d.ts +84 -32
  90. package/dist/core/locked-config.js +128 -42
  91. package/dist/core/mcp-connection-pool.d.ts +4 -1
  92. package/dist/core/mcp-connection-pool.js +7 -2
  93. package/dist/core/mcp-probe.d.ts +12 -9
  94. package/dist/core/mcp-probe.js +3 -3
  95. package/dist/core/mcp-server-spec.d.ts +104 -10
  96. package/dist/core/mcp-server-spec.js +183 -33
  97. package/dist/core/mcp.d.ts +31 -20
  98. package/dist/core/mcp.js +66 -56
  99. package/dist/core/memory-engine/data-plane.js +5 -1
  100. package/dist/core/memory-engine/distiller.js +16 -2
  101. package/dist/core/memory-engine/engine.d.ts +22 -30
  102. package/dist/core/memory-engine/engine.js +16 -10
  103. package/dist/core/memory-engine/frontmatter.d.ts +6 -0
  104. package/dist/core/memory-engine/frontmatter.js +19 -16
  105. package/dist/core/memory.d.ts +2 -2
  106. package/dist/core/mode-policy.d.ts +5 -16
  107. package/dist/core/mode-policy.js +7 -19
  108. package/dist/core/model-seat.d.ts +4 -1
  109. package/dist/core/mods/dollar.d.ts +109 -0
  110. package/dist/core/mods/dollar.js +154 -0
  111. package/dist/core/mods/host.d.ts +23 -0
  112. package/dist/core/mods/host.js +21 -0
  113. package/dist/core/mods/kernel/budget.d.ts +43 -0
  114. package/dist/core/mods/kernel/budget.js +83 -0
  115. package/dist/core/mods/kernel/dispatch.d.ts +100 -0
  116. package/dist/core/mods/kernel/dispatch.js +699 -0
  117. package/dist/core/mods/kernel/events.d.ts +245 -0
  118. package/dist/core/mods/kernel/events.js +210 -0
  119. package/dist/core/mods/kernel/index.d.ts +6 -0
  120. package/dist/core/mods/kernel/index.js +5 -0
  121. package/dist/core/mods/kernel/receive.d.ts +94 -0
  122. package/dist/core/mods/kernel/receive.js +188 -0
  123. package/dist/core/mods/kernel/registration.d.ts +131 -0
  124. package/dist/core/mods/kernel/registration.js +102 -0
  125. package/dist/core/mods/kernel/site-rules.d.ts +149 -0
  126. package/dist/core/mods/kernel/site-rules.js +296 -0
  127. package/dist/core/mods/stations.d.ts +344 -0
  128. package/dist/core/mods/stations.js +437 -0
  129. package/dist/core/mounted-mcp.d.ts +57 -0
  130. package/dist/core/mounted-mcp.js +71 -2
  131. package/dist/core/own-property-receipt.d.ts +13 -0
  132. package/dist/core/own-property-receipt.js +13 -23
  133. package/dist/core/parent-spec-seat.d.ts +18 -7
  134. package/dist/core/parent-spec-seat.js +6 -2
  135. package/dist/core/path-identity.js +2 -1
  136. package/dist/core/permission-rule-model.d.ts +58 -9
  137. package/dist/core/permission-rule-model.js +81 -7
  138. package/dist/core/permission-rule-org.d.ts +163 -33
  139. package/dist/core/permission-rule-org.js +205 -71
  140. package/dist/core/permission-rule-syntax.d.ts +15 -0
  141. package/dist/core/permission-rule-syntax.js +24 -16
  142. package/dist/core/permission-rules.d.ts +14 -2
  143. package/dist/core/permission-rules.js +63 -23
  144. package/dist/core/prompt-section-seat.d.ts +15 -27
  145. package/dist/core/prompt-section-seat.js +73 -40
  146. package/dist/core/protocol-http-auth.d.ts +3 -1
  147. package/dist/core/protocol-http-auth.js +2 -0
  148. package/dist/core/reminder-mint.d.ts +2 -2
  149. package/dist/core/remote-env.d.ts +24 -12
  150. package/dist/core/remote-env.js +1 -0
  151. package/dist/core/resume-startup-cause.d.ts +16 -1
  152. package/dist/core/resume-startup-cause.js +4 -1
  153. package/dist/core/retention.js +7 -2
  154. package/dist/core/retired-keys.d.ts +12 -2
  155. package/dist/core/retired-keys.js +15 -1
  156. package/dist/core/roles.js +60 -10
  157. package/dist/core/rule-lane-reads.js +1 -1
  158. package/dist/core/runner/announce-once-ledger.d.ts +31 -1
  159. package/dist/core/runner/announce-once-ledger.js +22 -0
  160. package/dist/core/runner/assemble-result.d.ts +9 -0
  161. package/dist/core/runner/assemble-result.js +3 -1
  162. package/dist/core/runner/call-hook-stations.d.ts +23 -27
  163. package/dist/core/runner/call-hook-stations.js +58 -42
  164. package/dist/core/runner/caller-stop-gate.d.ts +25 -0
  165. package/dist/core/runner/caller-stop-gate.js +7 -0
  166. package/dist/core/runner/compaction-seams.d.ts +8 -22
  167. package/dist/core/runner/compaction-seams.js +28 -53
  168. package/dist/core/runner/construction-doors.js +11 -1
  169. package/dist/core/runner/contracts.d.ts +86 -83
  170. package/dist/core/runner/credential-origin-seat.d.ts +2 -0
  171. package/dist/core/runner/credential-origin-seat.js +19 -0
  172. package/dist/core/runner/extra-body-dropped-seat.d.ts +2 -6
  173. package/dist/core/runner/gate-exit.d.ts +47 -36
  174. package/dist/core/runner/gate-exit.js +12 -5
  175. package/dist/core/runner/image.js +1 -2
  176. package/dist/core/runner/inline-image.js +1 -1
  177. package/dist/core/runner/mcp-redial.d.ts +52 -10
  178. package/dist/core/runner/mcp-redial.js +38 -9
  179. package/dist/core/runner/notice-seat-input.d.ts +11 -0
  180. package/dist/core/runner/notice-seat-input.js +1 -0
  181. package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
  182. package/dist/core/runner/permission-rule-lanes.js +22 -10
  183. package/dist/core/runner/person-path-rows.d.ts +3 -1
  184. package/dist/core/runner/person-path-rows.js +3 -2
  185. package/dist/core/runner/prepare-acquire-reconcile.js +5 -1
  186. package/dist/core/runner/prepare-ask-lane.d.ts +5 -7
  187. package/dist/core/runner/prepare-ask-lane.js +6 -15
  188. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
  189. package/dist/core/runner/prepare-caps-and-workflow.js +25 -8
  190. package/dist/core/runner/prepare-config-doors.d.ts +52 -1
  191. package/dist/core/runner/prepare-config-doors.js +168 -143
  192. package/dist/core/runner/prepare-defer-classify.js +7 -11
  193. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
  194. package/dist/core/runner/prepare-delegation-surface.js +7 -5
  195. package/dist/core/runner/prepare-gate-stations.d.ts +8 -11
  196. package/dist/core/runner/prepare-gate-stations.js +11 -10
  197. package/dist/core/runner/prepare-hands-readface.d.ts +1 -1
  198. package/dist/core/runner/prepare-hands-readface.js +2 -1
  199. package/dist/core/runner/prepare-inherited-gate.d.ts +8 -12
  200. package/dist/core/runner/prepare-inherited-gate.js +10 -23
  201. package/dist/core/runner/prepare-listings.d.ts +1 -1
  202. package/dist/core/runner/prepare-listings.js +4 -2
  203. package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
  204. package/dist/core/runner/prepare-memory-engine-session.js +20 -7
  205. package/dist/core/runner/prepare-memory.d.ts +3 -2
  206. package/dist/core/runner/prepare-memory.js +6 -2
  207. package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
  208. package/dist/core/runner/prepare-offload-wrappers.js +2 -1
  209. package/dist/core/runner/prepare-park-ask.js +10 -14
  210. package/dist/core/runner/prepare-policy-chain.d.ts +17 -15
  211. package/dist/core/runner/prepare-policy-chain.js +104 -109
  212. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  213. package/dist/core/runner/prepare-project-context.js +11 -12
  214. package/dist/core/runner/prepare-prompt-assembly.d.ts +45 -40
  215. package/dist/core/runner/prepare-prompt-assembly.js +138 -101
  216. package/dist/core/runner/prepare-prompt-inputs.d.ts +28 -23
  217. package/dist/core/runner/prepare-prompt-inputs.js +11 -10
  218. package/dist/core/runner/prepare-protocol-tools.d.ts +11 -7
  219. package/dist/core/runner/prepare-protocol-tools.js +20 -13
  220. package/dist/core/runner/prepare-question-face.d.ts +4 -2
  221. package/dist/core/runner/prepare-question-face.js +4 -3
  222. package/dist/core/runner/prepare-safety-scan.js +6 -10
  223. package/dist/core/runner/prepare-suspend-saga.d.ts +6 -0
  224. package/dist/core/runner/prepare-suspend-saga.js +7 -5
  225. package/dist/core/runner/prepare-task.js +41 -23
  226. package/dist/core/runner/prepare-turn-wiring.d.ts +13 -15
  227. package/dist/core/runner/prepare-turn-wiring.js +29 -27
  228. package/dist/core/runner/prepare-wiring-manifest.d.ts +13 -9
  229. package/dist/core/runner/prepare-wiring-manifest.js +14 -11
  230. package/dist/core/runner/resume-admission.d.ts +4 -1
  231. package/dist/core/runner/resume-admission.js +7 -5
  232. package/dist/core/runner/resume-apply.d.ts +5 -2
  233. package/dist/core/runner/resume-apply.js +24 -42
  234. package/dist/core/runner/resume-checkpoint-screen.d.ts +1 -0
  235. package/dist/core/runner/resume-checkpoint-screen.js +9 -1
  236. package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
  237. package/dist/core/runner/resume-internals-and-config.js +3 -8
  238. package/dist/core/runner/resume-preflight.js +38 -16
  239. package/dist/core/runner/retired-runner-deps.d.ts +5 -6
  240. package/dist/core/runner/retired-runner-deps.js +4 -5
  241. package/dist/core/runner/run-brain-sinks.d.ts +3 -2
  242. package/dist/core/runner/run-brain-sinks.js +5 -1
  243. package/dist/core/runner/run-compaction-machinery.d.ts +7 -1
  244. package/dist/core/runner/run-compaction-machinery.js +7 -33
  245. package/dist/core/runner/run-harness-handlers.js +4 -2
  246. package/dist/core/runner/run-identity-wiring.d.ts +3 -1
  247. package/dist/core/runner/run-identity-wiring.js +3 -2
  248. package/dist/core/runner/run-leg.js +103 -95
  249. package/dist/core/runner/run-notification-lane.js +1 -0
  250. package/dist/core/runner/run-recovery-lanes.d.ts +3 -0
  251. package/dist/core/runner/run-recovery-lanes.js +14 -11
  252. package/dist/core/runner/run-settle-and-teardown.js +9 -28
  253. package/dist/core/runner/run-stop-and-final-verify.js +18 -25
  254. package/dist/core/runner/run-terminal-adoption.d.ts +3 -0
  255. package/dist/core/runner/run-terminal-adoption.js +34 -22
  256. package/dist/core/runner/run-tool-mount-facts.js +5 -3
  257. package/dist/core/runner/run-turn-boundary.js +32 -37
  258. package/dist/core/runner/runtask.d.ts +6 -7
  259. package/dist/core/runner/runtask.js +15 -73
  260. package/dist/core/runner/session-rule-policy.d.ts +5 -5
  261. package/dist/core/runner/session-rule-policy.js +13 -8
  262. package/dist/core/runner/side-call-account.d.ts +68 -0
  263. package/dist/core/runner/side-call-account.js +61 -0
  264. package/dist/core/runner/skills-seat.d.ts +15 -0
  265. package/dist/core/runner/skills-seat.js +57 -0
  266. package/dist/core/runner/stream-halt-verbs.js +12 -17
  267. package/dist/core/runner/stream-lifecycle-verbs.js +8 -5
  268. package/dist/core/runner/stream-steer-verb.d.ts +1 -1
  269. package/dist/core/runner/stream-steer-verb.js +20 -38
  270. package/dist/core/runner/sub-agent-deny-lists.d.ts +124 -23
  271. package/dist/core/runner/sub-agent-deny-lists.js +230 -71
  272. package/dist/core/runner/synthetic-tools.d.ts +5 -2
  273. package/dist/core/runner/synthetic-tools.js +2 -12
  274. package/dist/core/runner/tool-end-body.d.ts +5 -6
  275. package/dist/core/runner/tool-end-body.js +6 -4
  276. package/dist/core/runner/tool-not-executed.d.ts +15 -0
  277. package/dist/core/runner/tool-not-executed.js +30 -0
  278. package/dist/core/runner/tool-occurrence.d.ts +8 -7
  279. package/dist/core/runner/tool-occurrence.js +5 -5
  280. package/dist/core/runner/tool-result-media-seat.d.ts +1 -1
  281. package/dist/core/runner-deps.d.ts +43 -36
  282. package/dist/core/safety-merge-corpus.js +18 -2
  283. package/dist/core/secret-env.d.ts +88 -20
  284. package/dist/core/secret-env.js +192 -38
  285. package/dist/core/session-policy-store.d.ts +71 -16
  286. package/dist/core/session-policy-store.js +138 -28
  287. package/dist/core/session-reconcile.d.ts +4 -0
  288. package/dist/core/session-reconcile.js +2 -1
  289. package/dist/core/shell-read-silence.js +3 -32
  290. package/dist/core/side-query.d.ts +5 -3
  291. package/dist/core/skill-grant.d.ts +3 -2
  292. package/dist/core/skill-grant.js +17 -9
  293. package/dist/core/skills-directory.d.ts +31 -11
  294. package/dist/core/skills-directory.js +655 -104
  295. package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
  296. package/dist/core/task-event.d.ts +49 -3
  297. package/dist/core/task-notification.js +2 -2
  298. package/dist/core/task-result.d.ts +8 -0
  299. package/dist/core/task-spec.d.ts +20 -19
  300. package/dist/core/task-stream.d.ts +14 -4
  301. package/dist/core/tighten-task-spec.d.ts +4 -3
  302. package/dist/core/tighten-task-spec.js +2 -4
  303. package/dist/core/tool-check-reading.d.ts +74 -0
  304. package/dist/core/tool-check-reading.js +80 -0
  305. package/dist/core/tool-policy.d.ts +62 -18
  306. package/dist/core/tool-policy.js +86 -15
  307. package/dist/core/tool-registry.d.ts +20 -0
  308. package/dist/core/tool-registry.js +4 -0
  309. package/dist/core/tool-spec.d.ts +10 -6
  310. package/dist/core/tools.js +2 -0
  311. package/dist/core/trace.d.ts +51 -32
  312. package/dist/core/types.d.ts +2 -2
  313. package/dist/core/types.js +1 -1
  314. package/dist/core/unc-spelling.d.ts +10 -0
  315. package/dist/core/unc-spelling.js +3 -0
  316. package/dist/core/untrusted-egress.d.ts +8 -0
  317. package/dist/core/untrusted-egress.js +4 -1
  318. package/dist/core/untrusted-text.d.ts +16 -0
  319. package/dist/core/untrusted-text.js +7 -2
  320. package/dist/core/user-attachment.d.ts +25 -4
  321. package/dist/core/user-attachment.js +63 -42
  322. package/dist/core/wiring-manifest.d.ts +18 -15
  323. package/dist/core/wiring-manifest.js +2 -2
  324. package/dist/engine/compaction/utils.js +1 -2
  325. package/dist/engine/execution-env/node-execution-env.d.ts +4 -3
  326. package/dist/engine/execution-env/symlink-chain.js +1 -1
  327. package/dist/engine/harness/agent-harness.d.ts +1 -1
  328. package/dist/engine/harness/agent-harness.js +5 -4
  329. package/dist/engine/harness/types.d.ts +20 -16
  330. package/dist/engine/harness/types.js +7 -1
  331. package/dist/engine/llm/types.d.ts +12 -7
  332. package/dist/engine/loop/agent-loop.d.ts +12 -1
  333. package/dist/engine/loop/agent-loop.js +18 -6
  334. package/dist/engine/loop/types.d.ts +8 -2
  335. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  336. package/dist/engine/session/import-validate.js +3 -10
  337. package/dist/engine/session/session.d.ts +4 -4
  338. package/dist/engine/session/session.js +4 -4
  339. package/dist/index.d.ts +33 -23
  340. package/dist/index.js +23 -15
  341. package/dist/internal/harness.d.ts +2 -1
  342. package/dist/internal/harness.js +2 -1
  343. package/dist/orchestration/goal.d.ts +24 -1
  344. package/dist/orchestration/goal.js +3 -2
  345. package/dist/orchestration/run-spec.d.ts +4 -6
  346. package/dist/orchestration/run-spec.js +39 -63
  347. package/dist/orchestration/run-workflow-tool.js +1 -2
  348. package/dist/orchestration/workflow.d.ts +11 -3
  349. package/dist/orchestration/workflow.js +11 -2
  350. package/dist/prompt-assembly/artifact-store.d.ts +72 -56
  351. package/dist/prompt-assembly/artifact-store.js +60 -52
  352. package/dist/prompt-assembly/artifact.d.ts +90 -76
  353. package/dist/prompt-assembly/artifact.js +197 -145
  354. package/dist/prompt-assembly/assemble.d.ts +36 -29
  355. package/dist/prompt-assembly/assemble.js +34 -220
  356. package/dist/prompt-assembly/bands.d.ts +20 -0
  357. package/dist/prompt-assembly/bands.js +18 -0
  358. package/dist/prompt-assembly/catalog/constitution.d.ts +23 -0
  359. package/dist/prompt-assembly/catalog/constitution.js +69 -0
  360. package/dist/prompt-assembly/catalog/core-behavior.d.ts +9 -0
  361. package/dist/prompt-assembly/catalog/core-behavior.js +85 -0
  362. package/dist/prompt-assembly/catalog/index.d.ts +11 -0
  363. package/dist/prompt-assembly/catalog/index.js +60 -0
  364. package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
  365. package/dist/prompt-assembly/catalog/memory.js +6 -0
  366. package/dist/prompt-assembly/catalog/modes.d.ts +15 -0
  367. package/dist/prompt-assembly/catalog/modes.js +137 -0
  368. package/dist/prompt-assembly/catalog/role.d.ts +10 -0
  369. package/dist/prompt-assembly/catalog/role.js +157 -0
  370. package/dist/prompt-assembly/catalog/schema.d.ts +138 -0
  371. package/dist/prompt-assembly/catalog/schema.js +25 -0
  372. package/dist/prompt-assembly/catalog/sections.d.ts +9 -0
  373. package/dist/prompt-assembly/catalog/sections.js +98 -0
  374. package/dist/prompt-assembly/catalog/team.d.ts +4 -0
  375. package/dist/prompt-assembly/catalog/team.js +258 -0
  376. package/dist/prompt-assembly/composer.d.ts +26 -28
  377. package/dist/prompt-assembly/composer.js +124 -46
  378. package/dist/prompt-assembly/epoch.d.ts +89 -79
  379. package/dist/prompt-assembly/epoch.js +115 -142
  380. package/dist/prompt-assembly/explain.d.ts +58 -34
  381. package/dist/prompt-assembly/explain.js +21 -24
  382. package/dist/prompt-assembly/overlay.d.ts +137 -0
  383. package/dist/prompt-assembly/overlay.js +339 -0
  384. package/dist/prompt-assembly/renderers.d.ts +21 -0
  385. package/dist/prompt-assembly/renderers.js +39 -0
  386. package/dist/prompt-assembly/section-usage.d.ts +3 -3
  387. package/dist/prompt-assembly/section-usage.js +1 -1
  388. package/dist/prompt-assembly/select.d.ts +71 -0
  389. package/dist/prompt-assembly/select.js +106 -0
  390. package/dist/prompt-assembly/sugar.d.ts +31 -0
  391. package/dist/prompt-assembly/sugar.js +20 -0
  392. package/dist/prompt-assembly/turn-snapshot.d.ts +3 -2
  393. package/dist/prompt-assembly/types.d.ts +45 -148
  394. package/dist/prompts/coordinator.d.ts +2 -21
  395. package/dist/prompts/coordinator.js +3 -255
  396. package/dist/prompts/cowork.d.ts +27 -16
  397. package/dist/prompts/cowork.js +2 -23
  398. package/dist/prompts/default.d.ts +38 -511
  399. package/dist/prompts/default.js +20 -288
  400. package/dist/prompts/supervisor.d.ts +6 -71
  401. package/dist/prompts/supervisor.js +6 -117
  402. package/dist/stores/file/permission-rule-store.d.ts +1 -1
  403. package/dist/stores/file/permission-rule-store.js +2 -1
  404. package/dist/tools/artifact/artifact-tool.js +4 -3
  405. package/dist/tools/fs/bash-readonly-classifier.d.ts +6 -5
  406. package/dist/tools/fs/dir-entries.d.ts +4 -2
  407. package/dist/tools/fs/dir-entries.js +16 -4
  408. package/dist/tools/fs/fs-bash.d.ts +1 -1
  409. package/dist/tools/fs/fs-bash.js +22 -11
  410. package/dist/tools/fs/fs-pdf.js +17 -13
  411. package/dist/tools/fs/fs-read.js +4 -3
  412. package/dist/tools/fs/fs-shared.d.ts +1 -10
  413. package/dist/tools/fs/fs-shared.js +3 -4
  414. package/dist/tools/fs/fs-write.js +2 -1
  415. package/dist/tools/fs/notebook.js +1 -1
  416. package/dist/tools/fs/pdf.d.ts +20 -10
  417. package/dist/tools/fs/pdf.js +19 -10
  418. package/dist/tools/fs/program-read-model.d.ts +68 -8
  419. package/dist/tools/fs/program-read-model.js +112 -33
  420. package/dist/tools/fs/program-read-model.rows.js +30 -10
  421. package/dist/tools/fs/read-deny-home.d.ts +25 -9
  422. package/dist/tools/fs/read-deny-home.js +28 -27
  423. package/dist/tools/fs/read-deny.d.ts +41 -11
  424. package/dist/tools/fs/read-deny.js +51 -5
  425. package/dist/tools/fs/safety.d.ts +4 -26
  426. package/dist/tools/fs/safety.js +10 -32
  427. package/dist/tools/fs/search.js +15 -10
  428. package/dist/tools/fs/shell-read-argv.d.ts +3 -2
  429. package/dist/tools/fs/shell-read-argv.js +118 -38
  430. package/dist/tools/fs/shell-read-establish.d.ts +5 -5
  431. package/dist/tools/fs/shell-read-establish.js +11 -61
  432. package/dist/tools/fs/shell-read-identity.js +6 -3
  433. package/dist/tools/fs/shell-read-judge.d.ts +13 -15
  434. package/dist/tools/fs/shell-read-judge.js +18 -4
  435. package/dist/tools/fs/shell-read-plan.d.ts +2 -2
  436. package/dist/tools/web.js +1 -1
  437. package/package.json +13 -1
  438. package/test/export-surface.snapshot.json +306 -103
  439. package/wire-changes/core@7.52.0.json +5859 -0
  440. package/wire-changes/core@7.53.0.json +1946 -0
  441. package/dist/core/hook-seats.d.ts +0 -66
  442. package/dist/core/hook-seats.js +0 -37
  443. package/dist/prompt-assembly/packs/sema-default.d.ts +0 -2
  444. package/dist/prompt-assembly/packs/sema-default.js +0 -147
  445. package/dist/prompts/simple-sections.d.ts +0 -58
  446. package/dist/prompts/simple-sections.js +0 -43
@@ -130,6 +130,12 @@ export declare const CLAMP_SET: Readonly<{
130
130
  readonly script: false;
131
131
  readonly carrier: "specSeat";
132
132
  }>;
133
+ promptForm: Readonly<{
134
+ readonly law: "restricting";
135
+ readonly value: "minimal";
136
+ readonly script: false;
137
+ readonly carrier: "specSeat";
138
+ }>;
133
139
  }>;
134
140
  /** One row's seat name. */
135
141
  export type ClampSeat = keyof typeof CLAMP_SET;
@@ -101,6 +101,7 @@ export const CLAMP_SET = Object.freeze({
101
101
  oneShot: Object.freeze({ law: "restricting", value: true, script: true, carrier: "specSeat" }),
102
102
  memoryPersistenceCapable: Object.freeze({ law: "restricting", value: false, script: true, carrier: "specSeat" }),
103
103
  fileHistory: Object.freeze({ law: "restricting", value: "disabled", script: false, carrier: "specSeat" }),
104
+ promptForm: Object.freeze({ law: "restricting", value: "minimal", script: false, carrier: "specSeat" }),
104
105
  });
105
106
  const ROWS = Object.freeze(Object.entries(CLAMP_SET));
106
107
  export const CLAMP_SEATS = Object.freeze(ROWS.map(([seat]) => seat));
@@ -210,7 +211,7 @@ export const CHILD_CLAMP_SEATS_NOT_CARRIED = Object.freeze({
210
211
  shellGate: "travels on the inherited-gate lane (`InheritedGate.shellGate`, a trusted internals seat), not on the child spec — a spec-level copy would be a second source for the same clamp",
211
212
  permissionMode: "travels on the inherited-gate lane (`InheritedGate.permissionMode` / `permissionModeCeiling` — the parent's declared word and its LIVE seat): a child with no word of its own inherits that ceiling on every read, and a word it does declare is clamped under it; a spec-level copy would freeze the parent's word at spawn and be a second source for the same clamp",
212
213
  onAsk: "per-lane by construction: the delegation lane wraps the parent's approver with spawn provenance before it becomes the child's seat, and a lane with no approver must hand down none (a parent that declared nobody can be asked hands down no approver — its frozen seat is empty — and the declaration rides `approvalReach`)",
213
- hooks: "a deployment seat, not an inherited clamp — `tightenTaskSpec` refuses to merge two hook sets rather than composing them, so there is no tightening value to carry",
214
+ mods: "the task seat travels on the parent spec seat (a child dispatches it as its own, its events carrying the child's identity), not as a clamp — a registration adds a handler, it does not narrow a value",
214
215
  allowTools: "the tool selector's own layer — a parent bounds its children through the selector's ceiling (`RunInternals.toolCeiling`, a trusted internals seat every engine lane fills), not by copying its own list onto the child seat, which would be a second source for the same bound",
215
216
  excludeTools: "the deny half of the same layer as `allowTools` above, same reading: the parent's reaches its children through the ceiling",
216
217
  deferTools: "roster disclosure control rather than containment: the lanes that copy it do so beside these seats, and the workflow lane authors its child roster from the governance baseline instead of the host's",
@@ -1,3 +1,4 @@
1
+ import { describeRejectedValue } from "./tool-search-setting.js";
1
2
  export const COMPLIANCE_CAPABILITIES = Object.freeze(["mcp_servers", "workflows", "web_fetch", "org_memory_mount"]);
2
3
  export const BUILTIN_COMPLIANCE_DENIES = {
3
4
  hipaa: ["web_fetch", "org_memory_mount"],
@@ -26,7 +27,8 @@ export function resolveComplianceDenies(posture) {
26
27
  export function complianceCapabilityProblem(cap, owner) {
27
28
  if (COMPLIANCE_CAPABILITIES.some((member) => member === cap))
28
29
  return undefined;
29
- return (`${owner} contains "${String(cap)}", not a member of the closed capability set ` +
30
+ const shown = (typeof cap === "object" && cap !== null) || typeof cap === "function" ? describeRejectedValue(cap) : `"${String(cap)}"`;
31
+ return (`${owner} contains ${shown}, not a member of the closed capability set ` +
30
32
  `(${COMPLIANCE_CAPABILITIES.join(", ")}) — a misspelled deny must never silently not-enforce.`);
31
33
  }
32
34
  export const WEB_FETCH_TOOL_NAME = "WebFetch";
@@ -75,7 +75,13 @@ export interface CredentialVocabulary {
75
75
  readonly connectionStringName: RegExp;
76
76
  /** Credential env names, each also judged under the `INPUT_` prefix (a GitHub Actions input). */
77
77
  readonly exactEnvNames: readonly string[];
78
- /** Credential-shaped names that hold no credential: exact names, never a shape. */
78
+ /** Credential-shaped names that hold no credential: declared names, never a pattern over names (the one pattern is
79
+ * {@link CredentialVocabulary.nonSecretNameShape}). Three readings of the same list: the env-name view and the
80
+ * record-member reading ({@link isSensitiveRecordKey}) take each as the WHOLE name (`CACHE_KEY` holds a setting,
81
+ * `SECRET_CACHE_KEY` a secret, in an environment and in a config or detail record alike); the HTTP header-name
82
+ * reading ({@link isSensitiveHeaderName}) takes it as the whole name or the TAIL of a longer one whose front part names
83
+ * no credential word (`cf-aig-cache-key`, `X-Idempotency-Key`: a gateway's header for the same non-secret thing;
84
+ * `secret-cache-key` stays a secret). */
79
85
  readonly nonSecretExactNames: readonly string[];
80
86
  /** The one name shape that holds no credential whatever words it carries: git's `GIT_CONFIG_KEY_<n…>` names a
81
87
  * configuration key (its value sits in `GIT_CONFIG_VALUE_<n>`). Read by every name view, beside the exact names. */
@@ -93,6 +99,10 @@ export interface CredentialVocabulary {
93
99
  * seconds of synchronous CPU); the bound makes it linear and redacts no less on any URL.
94
100
  */
95
101
  export declare const URI_SCHEME_SOURCE: string;
102
+ /** The fewest characters a string can have and still be read as a credential: the floor of a vendor-prefixed token's body
103
+ * and of a bearer / authorization credential run in this table, and of the value rules of the env scrub. A shorter
104
+ * string names no secret, whoever holds it. */
105
+ export declare const CREDENTIAL_MIN_CHARS = 8;
96
106
  export declare const CREDENTIAL_VOCABULARY: CredentialVocabulary;
97
107
  /** The refuse-write label of a family: its id spelled with `_` (surfaced in the refusal; never the matched value). */
98
108
  export declare const refuseLabel: (id: string) => string;
@@ -123,19 +133,34 @@ export interface EnvNameView {
123
133
  export declare function envNameView(vocabulary: CredentialVocabulary): EnvNameView;
124
134
  /** `camelCase` / `PascalCase` read as `_`-separated words, `OAuth` and `NextAuth` kept whole. */
125
135
  export declare function splitCamelCase(name: string): string;
126
- /** The record-key view: what {@link CREDENTIAL_VOCABULARY} says about the names of a structured record's members (an HTTP
127
- * header, a config or detail member) — the credential words of the env-name view, each row's `recordKeys` spellings
128
- * besides, and a `separated` word standing alone (`pwd`, `pass`: a record has no shell variable of that name). The names
129
- * the vocabulary declares non-secret stay non-secret here too: one fact, one reading in every view. */
136
+ /** The record-key view: what {@link CREDENTIAL_VOCABULARY} says about the names a structured record carries — the member
137
+ * of a config or detail record and the HTTP header — the credential words of the env-name view, each row's `recordKeys`
138
+ * spellings besides, and a `separated` word standing alone (`pwd`, `pass`: a record has no shell variable of that name).
139
+ * The names the vocabulary declares non-secret stay non-secret here too, as the whole name; the header-name reading
140
+ * ({@link isSensitiveHeaderName}) alone also takes one as the tail of a longer name — a gateway prefixes the header it
141
+ * names the same non-secret thing with (`cf-aig-cache-key`), where a secret named `secret_cache_key` lives in a
142
+ * body or a config record and is read whole. */
130
143
  export interface RecordKeyView {
131
144
  /** A credential word in its position, case-insensitive. Applied to a key with `-` read as `_`, as written and
132
- * camel-split ({@link isSensitiveRecordKey}). */
145
+ * camel-split ({@link isSensitiveRecordKey}, {@link isSensitiveHeaderName}). */
133
146
  readonly credentialWord: RegExp;
134
147
  readonly nonSecretExactNames: ReadonlySet<string>;
135
148
  readonly nonSecretNameShape: RegExp;
136
149
  readonly nonCredentialPrefix: RegExp;
137
150
  }
138
151
  export declare function recordKeyView(vocabulary: CredentialVocabulary): RecordKeyView;
139
- /** Does `key`, the name of a record's member (`Proxy-Authorization`, `pwd`, `X_API_KEY`, `clientSecret`), name a credential?
140
- * Case does not matter, `-` and `_` are one. `view` is the vocabulary's record-key view unless a caller holds another. */
152
+ /** Does `key`, the name of a record's MEMBER (`Proxy-Authorization`, `pwd`, `X_API_KEY`, `clientSecret`), name a credential?
153
+ * Case does not matter, `-` and `_` are one. A name the vocabulary declares non-secret is none as the WHOLE name only
154
+ * (`partition_key`; `x_partition_key` and `secret_cache_key` are still read by their words): a
155
+ * secret is named by the system that holds it, and what this reading decides is whether a value is shown or kept out of
156
+ * a record. The HTTP header-name reading is {@link isSensitiveHeaderName}. `view` is the vocabulary's record-key view
157
+ * unless a caller holds another. */
141
158
  export declare function isSensitiveRecordKey(key: string, view?: RecordKeyView): boolean;
159
+ /** Does `name`, an HTTP header's name (`Authorization`, `X-Api-Key`, `cf-aig-cache-key`), name a credential? The
160
+ * record-key reading ({@link isSensitiveRecordKey}) plus one exemption: a declared non-secret name is none also as the
161
+ * TAIL of a longer name, at a `_` / `-` boundary, whose front part holds no credential word (`cf-aig-cache-key`,
162
+ * `X-Idempotency-Key`, `X-Partition-Key`; `secret-cache-key`, `clientAuth-cache-key` and `xcache-key`
163
+ * are still read by their words). A gateway prefixes the header it names the same non-secret thing with, and the reading
164
+ * that mistakes such a header for a credential drops the key that should have gone out. `view` is the vocabulary's
165
+ * record-key view unless a caller holds another. */
166
+ export declare function isSensitiveHeaderName(name: string, view?: RecordKeyView): boolean;
@@ -1,5 +1,6 @@
1
1
  export const URI_SCHEME_SOURCE = String.raw `[A-Za-z][A-Za-z0-9+.\-_]{0,63}`;
2
- const VENDOR_BODY = "[A-Za-z0-9_-]{8,}";
2
+ export const CREDENTIAL_MIN_CHARS = 8;
3
+ const VENDOR_BODY = `[A-Za-z0-9_-]{${CREDENTIAL_MIN_CHARS},}`;
3
4
  const VALUE_END = String.raw `\s"';|&`;
4
5
  const VALUE_CHAR = `[^${VALUE_END}]`;
5
6
  const ESCAPE_DEPTH = 63;
@@ -38,7 +39,7 @@ export const CREDENTIAL_VOCABULARY = {
38
39
  { id: "huggingface-token", kind: "prefixed-token", source: "arg-summary", confidence: "high", match: headed("hf_[A-Za-z0-9]{20,}"), strict: /\bhf_(?=[A-Za-z0-9]*[0-9])[A-Za-z0-9]{20,}\b/ },
39
40
  { id: "jwt", kind: "jwt", source: "arg-summary", confidence: "high", match: headed("eyJ[A-Za-z0-9._-]{20,}"), strict: /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]{16,}\b/ },
40
41
  { id: "private-key", kind: "private-key-block", source: "arg-summary", confidence: "high", match: /-----BEGIN[ A-Z0-9]*PRIVATE KEY(?: BLOCK)?-----[\s\S]*?(?:-----END[ A-Z0-9]*PRIVATE KEY(?: BLOCK)?-----|$)/g, strict: /-----BEGIN (?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?-----/ },
41
- { id: "bearer-token", kind: "bearer-token", source: "arg-summary", confidence: "high", match: headed(String.raw `()[Bb][Ee][Aa][Rr][Ee][Rr]\s+[A-Za-z0-9._~+/-]{8,}=*(?:${BEARER_TAIL})?`), strict: /\bAuthorization:\s*Bearer\s+(?=[A-Za-z0-9._~+/-]*[0-9])[A-Za-z0-9._~+/-]{20,}=*/ },
42
+ { id: "bearer-token", kind: "bearer-token", source: "arg-summary", confidence: "high", match: headed(String.raw `()[Bb][Ee][Aa][Rr][Ee][Rr]\s+[A-Za-z0-9._~+/-]{${CREDENTIAL_MIN_CHARS},}=*(?:${BEARER_TAIL})?`), strict: /\bAuthorization:\s*Bearer\s+(?=[A-Za-z0-9._~+/-]*[0-9])[A-Za-z0-9._~+/-]{20,}=*/ },
42
43
  { id: "authorization-header", kind: "authorization-header", source: "arg-summary", confidence: "high", match: headed(String.raw `(authorization(?:\\{0,${ESCAPE_DEPTH}}["'])?[ \t]*[=:][ \t]*(?:\\{0,${ESCAPE_DEPTH}}["'])?)${HEADER_VALUE}`, "gi") },
43
44
  { id: "azure-storage-account-key", kind: "prefixed-token", source: "arg-summary", confidence: "high", match: /(AccountKey=)[A-Za-z0-9+/]{40,}={0,2}/g, strict: /AccountKey=[A-Za-z0-9+/]{40,}={0,2}/ },
44
45
  { id: "keyword-value", kind: "keyword-value", source: "arg-summary", confidence: "medium", match: headed(String.raw `((?:token|secret|key|password|passwd|credential)["']?\s*[=:]\s*["']?)${VALUE_CHAR}{4,}${VALUE_RUN_END}`, "gi") },
@@ -82,7 +83,7 @@ export const CREDENTIAL_VOCABULARY = {
82
83
  "DEFAULT_WORKFLOW_TOKEN", "SSH_SIGNING_KEY",
83
84
  ],
84
85
  nonSecretExactNames: [
85
- "PARTITION_KEY", "SORT_KEY", "RANGE_KEY", "IDEMPOTENCY_KEY", "CACHE_KEY", "ROUTING_KEY",
86
+ "PARTITION_KEY", "SORT_KEY", "RANGE_KEY", "IDEMPOTENCY_KEY", "CACHE_KEY",
86
87
  "DB_FOREIGN_KEYS", "JSON_SORT_KEYS",
87
88
  "MAX_NEW_TOKENS", "MAX_COMPLETION_TOKENS", "AIDER_MAP_TOKENS", "AIDER_MAX_CHAT_HISTORY_TOKENS",
88
89
  "MAX_BATCH_PREFILL_TOKENS", "MAX_WAITING_TOKENS", "MAX_TOP_N_TOKENS", "RATE_LIMIT_TOKENS",
@@ -149,9 +150,33 @@ export function recordKeyView(vocabulary) {
149
150
  };
150
151
  }
151
152
  const RECORD_KEYS = recordKeyView(CREDENTIAL_VOCABULARY);
152
- export function isSensitiveRecordKey(key, view = RECORD_KEYS) {
153
- if (view.nonSecretExactNames.has(key.toUpperCase()) || view.nonSecretNameShape.test(key))
154
- return false;
155
- const words = key.replace(view.nonCredentialPrefix, "").replace(/-/g, "_");
153
+ function holdsCredentialWord(text, view) {
154
+ const words = text.replace(view.nonCredentialPrefix, "").replace(/-/g, "_");
156
155
  return view.credentialWord.test(words) || view.credentialWord.test(splitCamelCase(words));
157
156
  }
157
+ function isNonSecretRecordName(key, source, view) {
158
+ const spelled = key.replace(/-/g, "_");
159
+ const folded = spelled.toUpperCase();
160
+ if (view.nonSecretExactNames.has(folded))
161
+ return true;
162
+ if (source !== "header")
163
+ return false;
164
+ if (folded.length !== spelled.length)
165
+ return false;
166
+ for (const name of view.nonSecretExactNames) {
167
+ if (folded.endsWith(`_${name}`) && !holdsCredentialWord(spelled.slice(0, spelled.length - name.length - 1), view))
168
+ return true;
169
+ }
170
+ return false;
171
+ }
172
+ function readsAsCredential(key, source, view) {
173
+ if (view.nonSecretNameShape.test(key))
174
+ return false;
175
+ return holdsCredentialWord(key, view) && !isNonSecretRecordName(key, source, view);
176
+ }
177
+ export function isSensitiveRecordKey(key, view = RECORD_KEYS) {
178
+ return readsAsCredential(key, "member", view);
179
+ }
180
+ export function isSensitiveHeaderName(name, view = RECORD_KEYS) {
181
+ return readsAsCredential(name, "header", view);
182
+ }
@@ -1,7 +1,7 @@
1
1
  import type { PermissionResult } from "./tool-policy.js";
2
2
  export declare const refusedOutOfContract: (message: string) => PermissionResult;
3
- /** Is `d` a refusal the engine itself minted (by object identity — a look-alike `deny` a caller built is not one)? Public: the answer of
4
- * `receiveHookResult` is one of two things, and this tells them apart. */
3
+ /** Is `d` a refusal the engine itself minted (by object identity — a look-alike `deny` a caller built is not one)? The receipt's
4
+ * answer is one of two things (the engine's refusal or its detached copy), and this tells them apart. */
5
5
  export declare const isEngineRefusal: (d: unknown) => boolean;
6
6
  /** A decision's `decisionReason` — the closed set; the type is derived FROM this list, so a word added to either side is a
7
7
  * compile error rather than a drift between the type and the screen. Module-private (the package publishes the type).
@@ -98,13 +98,20 @@ export interface BackgroundChildEvent {
98
98
  * `w*` id. `parentTaskId` stays task-domain (the HOST task) so parent resolvers that only
99
99
  * forward resolved task rows keep working; workflow grouping/nesting is THIS annotation's job. */
100
100
  workflowRunId?: string;
101
- /** All kinds: the delegating Agent tool call's OWN `toolCallId` —
101
+ /** All kinds: the delegating tool call's OWN `toolCallId` —
102
102
  * the same identity {@link TaskEvent}'s `parentToolCallId` already carries on every forwarded child
103
103
  * content event (via `RunInternals.parentToolCallId`), extended to this SEPARATE observer/fleet
104
104
  * event family so a consumer does not have to reassemble parent attribution from spawn-frame
105
105
  * ordering alone (the exact gap a cross-repo consumer hit: FIFO-timing + shape-sniffing to guess
106
106
  * which spawn frame a tick/terminal belongs to). Present from spawn — known at birth like
107
- * {@link transcriptId} — not just on the terminal frame. */
107
+ * {@link transcriptId} — not just on the terminal frame.
108
+ *
109
+ * Which call that is depends on the lane. An `Agent` delegation (`a*` rows) carries the id of the
110
+ * `Agent` call that spawned the child. A workflow's agents (`wa*` rows: spawn, every tick and the terminal
111
+ * frame alike) carry the id of the `Workflow` call that launched the run — ONE id shared by every row of
112
+ * that run, so the relation is one card to N children and no two rows of a fan-out are told apart by this
113
+ * field (their own `taskId` is the per-child key). ABSENT, never invented, on a workflow started with no
114
+ * launching tool call. */
108
115
  parentToolCallId?: string;
109
116
  /** tick: the forwarded `task_progress` frame's own taskId (uuid domain; nested children carry theirs). */
110
117
  progressTaskId?: string;
@@ -0,0 +1,18 @@
1
+ /** The table cannot be had: the slot holds a value that is not the engine's table (a deployment reset it), or the slot cannot be written. Registrations would be lost
2
+ * and a renamed mount would read as a clean one — so this is a refusal (`config.tool_face_control`, `detail.reason: "registry_occupied"`), never a fresh table. */
3
+ export declare class DelegationRegistryOccupied extends Error {
4
+ readonly code: "config.tool_face_control";
5
+ readonly detail: {
6
+ reason: "registry_occupied";
7
+ };
8
+ constructor(why: string);
9
+ }
10
+ /** Binds `name` to `tool.execute` (the function that carries the delegation out) and returns the tool. */
11
+ export declare function bindDelegationName<T extends {
12
+ readonly execute: unknown;
13
+ }>(name: string, tool: T): T;
14
+ /** A product's wrapper around a bound `execute` is the same delegation: it answers to the name its source did. */
15
+ export declare function carryDelegationName(source: unknown, product: unknown): void;
16
+ /** The name the delegation tool this roster entry carries declared — or `undefined` (not a delegation tool the factory made, or its `execute` was wrapped by the host).
17
+ * An entry whose members cannot be read reads as undeclared (the roster snapshot refuses it); an occupied table throws {@link DelegationRegistryOccupied}. */
18
+ export declare function declaredDelegationNameOf(tool: unknown): string | undefined;
@@ -0,0 +1,47 @@
1
+ const DECLARED_NAMES = Symbol.for("sema.core.delegationDeclaredNames");
2
+ export class DelegationRegistryOccupied extends Error {
3
+ code = "config.tool_face_control";
4
+ detail = { reason: "registry_occupied" };
5
+ constructor(why) {
6
+ super(`The table of declared delegation-tool names (globalThis[Symbol.for("sema.core.delegationDeclaredNames")]) ${why} — a delegation tool mounted under another name than it declares could not be told from a clean mount, so the run does not start. Leave that slot to the engine.`);
7
+ }
8
+ }
9
+ const tableIfAny = () => {
10
+ const slot = Reflect.get(globalThis, DECLARED_NAMES);
11
+ if (slot instanceof WeakMap)
12
+ return slot;
13
+ if (slot !== undefined)
14
+ throw new DelegationRegistryOccupied("holds a value that is not the engine's table");
15
+ return undefined;
16
+ };
17
+ const tableToBind = () => {
18
+ const held = tableIfAny();
19
+ if (held !== undefined)
20
+ return held;
21
+ const fresh = new WeakMap();
22
+ if (!Reflect.set(globalThis, DECLARED_NAMES, fresh))
23
+ throw new DelegationRegistryOccupied("cannot be written");
24
+ return fresh;
25
+ };
26
+ export function bindDelegationName(name, tool) {
27
+ if (typeof tool.execute === "function")
28
+ tableToBind().set(tool.execute, name);
29
+ return tool;
30
+ }
31
+ export function carryDelegationName(source, product) {
32
+ const slot = Reflect.get(globalThis, DECLARED_NAMES);
33
+ const names = slot instanceof WeakMap ? slot : undefined;
34
+ const name = names !== undefined && typeof source === "function" ? names.get(source) : undefined;
35
+ if (name !== undefined && typeof product === "function")
36
+ names.set(product, name);
37
+ }
38
+ export function declaredDelegationNameOf(tool) {
39
+ const names = tableIfAny();
40
+ try {
41
+ const execute = typeof tool === "object" && tool !== null ? tool.execute : undefined;
42
+ return typeof execute === "function" ? names?.get(execute) : undefined;
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ }
@@ -245,17 +245,36 @@ export declare function readCallTarget(env: ExecutionEnv | undefined, call: Tool
245
245
  readonly root?: string | undefined;
246
246
  readonly cwd?: string | undefined;
247
247
  }, signal?: AbortSignal, leads?: ReadonlyMap<string, string | undefined>): Promise<CallTargetReading>;
248
+ /** The gate's entry records the loop's reading of this call's arguments against the face it stamps on the call. */
249
+ export declare function stampArgsReading(face: object, read: (args: unknown) => unknown): void;
248
250
  /**
249
- * `req` with its arguments replaced by `args` and — when `req` carries a reading of its own args — a reading of the NEW
250
- * args taken the same way (same environment, same root / cwd, same face). Every seat that rewrites a request's arguments
251
- * and hands it on (a composition's rewrite cascade, a re-judgment of the final or an edited form) goes through here, so the
252
- * next layer never judges a request its reading does not describe. `signal` is the CURRENT call's: a reading never carries
253
- * one call's cancellation into another's. `undefined` ⇒ nothing to re-read: use `{ ...req, args }`.
251
+ * `args` as the called tool will run them — its argument preparation and schema coercions, the reading the loop gave the
252
+ * model's call — for the call `req` belongs to; `args` itself when nothing was stamped (a bare request outside a Runner:
253
+ * a host judging a call reads it the tool's way first). Every seat that adopts a rewrite (a hook's, a policy's, a
254
+ * person's edit) takes it through here before anything judges it, so what is judged is what runs. A value the reading
255
+ * leaves as it is comes back as ITSELF (the same object: a target reading taken for it still describes it).
256
+ */
257
+ export declare function argsAsTheToolReads(req: {
258
+ readonly face?: object | undefined;
259
+ }, args: unknown): unknown;
260
+ /** `args` through one call's reading `read` (the face-less seat: the resumed call reads through its live tool): ITSELF when the
261
+ * reading leaves its bytes as they are, else the reading's value, recorded as read from `args`. */
262
+ export declare function argsReadBy(read: (args: unknown) => unknown, args: unknown): unknown;
263
+ /** The value `args` was read from, when a reading moved it; otherwise `args` itself. */
264
+ export declare function argsReadFrom(args: unknown): unknown;
265
+ /**
266
+ * `req` with its arguments replaced by `args` AS THE TOOL READS THEM ({@link argsAsTheToolReads}) and — when `req` carries
267
+ * a reading of its own target — a reading of the NEW args taken the same way (same environment, same root / cwd, same
268
+ * face). Every seat that rewrites a request's arguments and hands it on (a composition's rewrite cascade, a re-judgment of
269
+ * the final or an edited form) goes through here, so the next layer never judges a request its reading does not describe
270
+ * nor arguments the tool would run differently. `signal` is the CURRENT call's: a reading never carries one call's
271
+ * cancellation into another's.
254
272
  */
255
273
  export declare function withArgsReading<R extends {
256
274
  readonly args: unknown;
257
275
  readonly targetReading?: CallTargetReading | undefined;
258
- }>(req: R, args: unknown, signal: AbortSignal | undefined): Promise<R> | undefined;
276
+ readonly face?: object | undefined;
277
+ }>(req: R, args: unknown, signal: AbortSignal | undefined): Promise<R>;
259
278
  /** The request's target reading, when it describes the request's own `args` (the object it was taken for); otherwise
260
279
  * nothing — a rule lane then judges the lexical view it always judged. Every rule lane reads the reading through here. */
261
280
  export declare function callTargetReadingOf(req: {
@@ -3,6 +3,7 @@ import { declaredPathTargetOf, pathTargetValue, protectivePathTargetOf } from ".
3
3
  import { symlinkChainHops } from "./path-identity.js";
4
4
  import { DEFAULT_GATE_AWAIT_TIMEOUT_MS, withGateTimeout } from "./gate-bounded-await.js";
5
5
  import { thrownText } from "./thrown-value.js";
6
+ import { canonicalize } from "./canonical-json.js";
6
7
  export function pathTargetBaseOf(pt, bases) {
7
8
  return (pt?.base ?? "cwd") === "root" ? bases.root : (bases.cwd ?? bases.root);
8
9
  }
@@ -146,10 +147,31 @@ export async function readCallTarget(env, call, signal, leads) {
146
147
  REREAD.set(reading, (args, rereadSignal) => readCallTarget(env, { ...call, args }, rereadSignal, leads));
147
148
  return reading;
148
149
  }
149
- export function withArgsReading(req, args, signal) {
150
+ const ARGS_READING = new WeakMap();
151
+ export function stampArgsReading(face, read) {
152
+ ARGS_READING.set(face, read);
153
+ }
154
+ export function argsAsTheToolReads(req, args) {
155
+ const read = req.face === undefined ? undefined : ARGS_READING.get(req.face);
156
+ return read === undefined ? args : argsReadBy(read, args);
157
+ }
158
+ export function argsReadBy(read, args) {
159
+ const out = read(args);
160
+ if (out === args || canonicalize(out) === canonicalize(args))
161
+ return args;
162
+ if (typeof out === "object" && out !== null)
163
+ READ_FROM.set(out, args);
164
+ return out;
165
+ }
166
+ const READ_FROM = new WeakMap();
167
+ export function argsReadFrom(args) {
168
+ return typeof args === "object" && args !== null && READ_FROM.has(args) ? READ_FROM.get(args) : args;
169
+ }
170
+ export async function withArgsReading(req, args, signal) {
171
+ const read = argsAsTheToolReads(req, args);
150
172
  const reading = callTargetReadingOf(req);
151
173
  const reread = reading === undefined ? undefined : REREAD.get(reading);
152
- return reread === undefined ? undefined : reread(args, signal).then((targetReading) => ({ ...req, args, targetReading }));
174
+ return reread === undefined ? { ...req, args: read } : { ...req, args: read, targetReading: await reread(read, signal) };
153
175
  }
154
176
  function viewFrom(v) {
155
177
  if (v.lexical === undefined)
@@ -9,7 +9,14 @@
9
9
  * result (`"all"` and `"scrub"` alike), and an allow list naming one is refused (`inheritEnvPolicyProblem`; every
10
10
  * spawn throws it). The word speaks of INHERITANCE only: the engine process's own environment stays readable to
11
11
  * same-user processes on the host (`ps -E`), so a credential that never enters it remains the root fix.
12
+ * - `inherit_env.own_credential_values_withheld` — a child spawned on this host never inherits an env entry whose
13
+ * value equals a credential value the deployment declared or the engine holds: `declareWithheldEnv` takes one table
14
+ * `{ names, values }`, the engine adds the credentials it takes in, where it receives them (a first-party brain's
15
+ * `apiKey` and credential headers, a model entry's credential headers, a protocol peer's credential headers, the
16
+ * memory distiller's chat seat key), and `inheritedHostEnv` subtracts every entry whose value is one,
17
+ * compared whole, under every policy. A credential resolved per request (a per-model auth hook's answer) is not in
18
+ * it: the host that resolves it declares it. The same inheritance-only reading as the word above.
12
19
  */
13
- export declare const ENGINE_CAPABILITIES: readonly ["inherit_env.own_credentials_withheld"];
20
+ export declare const ENGINE_CAPABILITIES: readonly ["inherit_env.own_credentials_withheld", "inherit_env.own_credential_values_withheld"];
14
21
  /** One word of {@link ENGINE_CAPABILITIES}. */
15
22
  export type EngineCapability = (typeof ENGINE_CAPABILITIES)[number];
@@ -1 +1 @@
1
- export const ENGINE_CAPABILITIES = Object.freeze(["inherit_env.own_credentials_withheld"]);
1
+ export const ENGINE_CAPABILITIES = Object.freeze(["inherit_env.own_credentials_withheld", "inherit_env.own_credential_values_withheld"]);
@@ -68,7 +68,11 @@ export interface EngineNotice {
68
68
  * as usual. Audience `user`; once per prepared task for the skill and request lists (`detail.sessionId` present), once
69
69
  * per Runner for the deployment's (at construction, no session). `detail: { sessionId?, entries: [{ source, entry,
70
70
  * reason, skill?, list? }] }` (`source` ∈ `skill` / `request` / `deployment`; `skill` and `list` only on a skill's;
71
- * `reason` ∈ {@link import("./allow-entry.js").ALLOW_ENTRY_INERT_REASONS}).
71
+ * `reason` ∈ {@link import("./allow-entry.js").ALLOW_ENTRY_INERT_REASONS}; `entry` is the entry as written — the message spells it — when it is at most `NOTICE_RULE_TEXT_MAX` (1 024) code points; a longer one is cut to 1 024 plus the truncation mark, 1 025 in all).
72
+ * - `"mods.registration_refused"` — an extension registration was not mounted: a registration admitted before it
73
+ * answered `{ refuse }` on `plugin.register`, or failed while judging it (fail-closed). The run goes on without it.
74
+ * Audience `user` (the seat is in `detail`). Once per refused registration per run. `detail: { name, seat, tier,
75
+ * refusedBy, reason, sessionId }` (`seat` ∈ `deployment` / `task`).
72
76
  * - `"skills.listing_truncated"` — the `<skills>` disclosure block did not fit its byte budget, so
73
77
  * at least one skill is listed without its description (`nameOnly`) or, in the pathological case,
74
78
  * not listed at all (`dropped`); the `Skill` tool still serves every one of them. Audience
@@ -213,7 +217,7 @@ export interface EngineNotice {
213
217
  * the pairing pre-flight and the seat fell back to the primary model instead of sinking the
214
218
  * task; the notice is the loud half of that swap.
215
219
  * `detail: { seat, from, to, cause, fixHint, sessionId?, runId? }` — `cause` is the refusal code
216
- * (`route.credential_mismatch` / `route.credential_missing`); `sessionId` (#433, additive)
220
+ * (a `RouteRefusalCode` word, the verdict's own); `sessionId` (#433, additive)
217
221
  * rides when the adjudicating seat knows its session, and `runId` (#499, additive) names the
218
222
  * INVOCATION whose seats were being resolved — both correlation keys only, the audience stays
219
223
  * `"operator"` (see the registry's entitlement-not-routability note), and `runId` is what tells one
@@ -261,16 +265,17 @@ export interface EngineNotice {
261
265
  * classifier and the leg's own can carry two); not minted while the call is being aborted (a halt, or the run's end). Audience
262
266
  * `user`: on a lane with no approval face this line is the only place the user hears why the call did not
263
267
  * run. It is not a block — the denial limit does not count it.
264
- * - `"route.base_url_changed_key_unchanged"` (key↔URL pairing) — `Runner.swapDeps` moved a
265
- * same-name entry's `baseUrl` while its Model-visible credential half (auth-bearing headers)
266
- * did not change: legal (a provider changing domains), but worth one loud line — if the
267
- * PROVIDER changed, the credential reference needs the same update. Advisory only, never a
268
- * refusal; per-model-hook credentials are invisible to the catalog swap, so the notice is
269
- * deliberately conservative (it may fire when a hook-side credential DID change in lockstep).
270
- * One aggregated notice per swap; `detail: { entries: [{ modelId, from, to }], total,
271
- * occurrenceId }` (rendered list bounded, total always exact); the `occurrenceId` is minted at this
272
- * announcement, independently of the `config.models_swapped` line's own, because the bounded render
273
- * makes two swaps moving the same first entries identical. Dedup key: (code, occurrenceId).
268
+ * - `"route.credential_origin_mismatch"` (key↔URL pairing, `src/brain/route-adjudicator.ts`; announced by
269
+ * `src/core/runner/credential-origin-seat.ts`) — a request was REFUSED, nothing sent, because the per-model
270
+ * credential it would carry is bound to another origin: the law binds a per-model credential to the origin
271
+ * (scheme + host + port) of the first request sent carrying it, so an entry whose `baseUrl` moved to another
272
+ * host while its credential stayed the same is refused (same-origin path moves are not). The request's own
273
+ * failure carries the same code (`[invalid_request] route.credential_origin_mismatch: …`). Minted only for a
274
+ * request the gate refused (`routeRefusalError`): a pre-flight or read-face judgment reports nothing, and a derived
275
+ * seat refused this way falls back as `route.fallback_to_primary` names. Audience `user` — the person whose request
276
+ * failed hears why; the operator hears it through the sink. `detail: { modelId, boundOrigin, requestOrigin,
277
+ * sessionId, runId }` — the two origins in display spelling, never a credential or a digest of one. Once per
278
+ * run per (modelId, boundOrigin, requestOrigin).
274
279
  * - `"route.response_model_mismatch"` — the provider answered a turn naming a model that is NOT the id
275
280
  * the request was sent with (an alias, a pool or a gateway-side substitution looks exactly like this),
276
281
  * so it is advisory, never a refusal: the engine keeps asking for the catalog's id and reports the
@@ -380,12 +385,20 @@ export interface EngineNotice {
380
385
  * (`isolation`, `suspendable`, `canonicalPathAuthoritative`) with a non-boolean value; ABSENCE is a
381
386
  * supported reading of each and stays silent. Once per key per run; `detail: { key, valueType }`.
382
387
  * - `"config.secret_env_scrubbed"` (#1081) — the D1 fail-closed `scrub` policy, or the deployment's
383
- * declared own credentials (`declareWithheldEnv`), withheld one or more keys from a spawned child's
384
- * environment (a tool's shell, an oracle gate, or a language server).
388
+ * own credentials (`declareWithheldEnv`: a declared name, or a value equal to a declared or engine-held
389
+ * credential value), withheld one or more keys from a spawned child's environment (a tool's shell, an
390
+ * oracle gate, or a language server).
385
391
  * Once per PROCESS, shared by every scrub site ({@link import("./secret-env.js").announceSecretEnvScrub});
386
392
  * `detail: { names, ownCredentials? }` — every withheld key's name, never a value; `ownCredentials`, present
387
- * only when one was withheld, the subset withheld as declared own credentials (under any policy, `"all"`
388
- * included).
393
+ * only when one was withheld, the subset withheld as own credentials, by name or by value (under any policy,
394
+ * `"all"` included).
395
+ * - `"config.credential_not_withheld"` (#1816) — a credential value the engine was handed (a brain's key or credential
396
+ * header, a model entry's or a peer's credential header, a consolidation seat's key) is no credential (a placeholder
397
+ * such as `EMPTY`, fewer than eight characters, one character repeated): it is used as given, but a variable holding
398
+ * the same string is not withheld from a spawned child. Once per PROCESS per value
399
+ * ({@link import("./secret-env.js").holdOwnCredentialValues}); `detail: { reason }` — the kind, never the value. Delivered
400
+ * to `RunnerDeps.onNotice` from the `new Runner` receipt; the intakes with no structured seat (a brain's construction,
401
+ * a request's route reading, a peer's dial, a directly built distiller seat) print its line on `console.warn`.
389
402
  * - `"config.permission_mode_unavailable"` — the permission mode a task requested is not the mode the leg runs
390
403
  * under: the deployment denies it (`by: "operator_deny"` — `RuntimeCaps.bypassPermissions` / `autoMode` is
391
404
  * `false`), a requested `auto` has no classifier face (`by: "face_absent"` — neither the leg's deps nor its chain carry
@@ -426,7 +439,18 @@ export interface EngineNotice {
426
439
  * complete absolute path (only a foreign writer or a hand edit makes one; every engine write face refuses it): they
427
440
  * take no part in this run's checks — a deny or ask row among them protects nothing — until they are rewritten or
428
441
  * removed. Once per run, by whichever read met them first. `detail: { rows, count, sessionId, runId }` — `rows`
429
- * the first eight `{ rule, scopeRoot }` (each bounded), `count` all of them. Audience `user`.
442
+ * the first eight `{ rule, scopeRoot }`, `count` all of them; `rule` is the rule text as the store served it, through the same reading
443
+ * as `permission.allowed_tool_not_granted`'s `entries[].entry` (the original, not a spelling of it, when it is at most 1 024 code points;
444
+ * a longer one is cut to 1 024 plus the truncation mark, 1 025 in all), `scopeRoot` neutralized and bounded. Audience `user`.
445
+ * - `"config.session_rules_earlier_grammar"` — a session's stored permission rules (`RunnerDeps.sessionPolicyStore`) hold
446
+ * entries the rule grammar they were written in reads as nothing: an allow entry admits nothing, and a `toolDeny` entry
447
+ * this engine's grammar reads as no rule makes those rules refuse every call until they are rewritten. The message names
448
+ * the session, the bucket, the entries (the first five, the rest counted), the reader's word and the way out. Audience
449
+ * `user`. Once per distinct entry set per bucket per rule layer (the run's own rules, each ancestor's inherited ones).
450
+ * `detail: { bucket, storedGrammar, entries: [{ entry, reader }], rewrite: { by, stampsGrammar }, rulesSessionId,
451
+ * sessionId }` — `entries` every one, `entry` through the same reading as `permission.allowed_tool_not_granted`'s;
452
+ * `reader` ∈ `no_rule` / `named_no_tool`; `rewrite.by` = `operator_write_without_rev`; `rulesSessionId` the session
453
+ * whose rules they are (an ancestor's on a delegated child), `sessionId` the run that read them.
430
454
  * - `"config.durable_gate_unavailable"` — a durable-approval MANDATE is in force on a leg with NO
431
455
  * checkpoint store: the per-principal `forceDurableGate` entitlement, or the task's own
432
456
  * `durableApproval` opt-in with no live approver seat (`durableMandateSourceOf`, the predicate the
@@ -511,7 +535,9 @@ export interface EngineNotice {
511
535
  * refused) but the run's ending was not its doing: the run's own ending stands and the result will
512
536
  * NOT carry `haltedByUser` for it (the seat signs consumption, never acceptance). TWO mint points,
513
537
  * one fact, one spelling, disjoint: the VERB arm — the halt arrived while the run's ending was already
514
- * owned by its own abort (nothing cut, nothing stopped; once per such verb call, and only while no halt
538
+ * owned by its own abort, or after the loop's end (no turn cut, no boundary stopped — a compaction pass the
539
+ * run's tail was in is still cut, and says so on its own `compaction_outcome{mooted, reason:"cancelled"}`;
540
+ * once per such verb call, and only while no halt
515
541
  * has been ACCEPTED on the run — after one was, the settle arm alone speaks for the run);
516
542
  * the SETTLE arm — the halt was ACCEPTED (it may even have cut a live seat: `{turnCut:true}` +
517
543
  * `task.turn_interrupted`) but the run ended for its own reason before the machinery consumed it —
@@ -551,9 +577,11 @@ export interface EngineNotice {
551
577
  * taskId?, origin }` with `origin` ∈ `"interrupt"` (the verb) | `"walltime"` | `"turns"` |
552
578
  * `"signal"` (every other run-level abort: the task's own `signal`, a parent's cancel, a
553
579
  * `destroy()`, a refused preempt — the leg names the three it can tell apart and files the rest
554
- * here). Audience `"user"`. A stop that arrives
555
- * AFTER the loop's end is refused typed (`steering.not_running`, every verb alike) and mints
556
- * nothing: the refusal itself is the loud answer.
580
+ * here). Audience `"user"`. A stop that arrives AFTER the loop's end but before `done` aborted no
581
+ * live loop and mints nothing here: it is answered, the end-of-task compaction pass does not run past
582
+ * it (cut in flight — `compaction_outcome{mooted, reason:"cancelled"}` — or never started), and the
583
+ * loop's ending stands as it was. A stop that arrives once the result is out is refused typed (`steering.not_running`, every
584
+ * verb alike): the refusal itself is the loud answer.
557
585
  *
558
586
  * - `"approval.read_root_granted"` / `"approval.read_root_grant_rejected"` — an approver's `readRootGrant`
559
587
  * (`AskOutcome`). GRANTED: it equalled the card's `readRootCandidate.dir` beside `allow: true`; this run's READ
@@ -0,0 +1,10 @@
1
+ /** The fence text a writer emits. The reader below accepts exactly this, plus trailing blanks and a CR. */
2
+ export declare const FRONTMATTER_FENCE = "---";
3
+ /** The refusal sentence for a file that OPENS a frontmatter block and never reaches a closing fence. One wording for
4
+ * every reader that refuses such a file: the block exists and cannot be read, so reading the file as one with no
5
+ * frontmatter (and dropping what the block declared) is not an answer. */
6
+ export declare const UNCLOSED_FRONTMATTER_REASON = "opens with --- but is not closed by a whole-line ---";
7
+ /** True ⇔ `line` is exactly a frontmatter fence: {@link FRONTMATTER_FENCE}, then spaces / tabs only, then
8
+ * at most one CR. The line must not contain `\n` (callers split on it first). The SAME predicate judges
9
+ * the opening fence (line 0) and the closing fence (the first later line it accepts). */
10
+ export declare function isFrontmatterFence(line: string): boolean;
@@ -0,0 +1,6 @@
1
+ export const FRONTMATTER_FENCE = "---";
2
+ export const UNCLOSED_FRONTMATTER_REASON = "opens with --- but is not closed by a whole-line ---";
3
+ const FENCE_TAIL = /^[ \t]*\r?$/;
4
+ export function isFrontmatterFence(line) {
5
+ return line.startsWith(FRONTMATTER_FENCE) && FENCE_TAIL.test(line.slice(FRONTMATTER_FENCE.length));
6
+ }
@@ -8,18 +8,19 @@ import { createGateDeadline, awaitWriteProtectionJudgment, gateWaitFailureOf, wi
8
8
  import { shellReadFaceWords } from "../tools/fs/shell-read-face.js";
9
9
  import { failedJudgmentDeny } from "./runner/policy-throw.js";
10
10
  import { thrownText } from "./thrown-value.js";
11
- import { refuseOutOfContractDecision } from "./tool-policy.js";
11
+ import { argsAsTheToolReads } from "./effective-path-target.js";
12
+ import { foldHookAsk, refuseOutOfContractDecision } from "./tool-policy.js";
12
13
  import { applyUnansweredSilence, readStationAnswer, silencedBy } from "./shell-read-silence.js";
13
14
  import { asksUnstated, permissionSeatAt, unstatedAskMessage } from "./mode-policy.js";
14
15
  export async function runGateFold(pass) {
15
16
  const { input, toolName, toolCallId, callSignal, ledger, notifier, adjudicate } = pass;
16
17
  const boundedAwaitDeadlineMs = createGateDeadline(input, notifier);
17
- pass.req = { toolName, args: pass.currentInput, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) };
18
+ pass.req = Object.freeze({ toolName, args: pass.currentInput, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) });
18
19
  let unread;
19
20
  try {
20
21
  const stamped = input.stampCallTarget?.(pass.req, callSignal ?? input.abortSignal);
21
22
  if (stamped !== undefined)
22
- pass.req = await stamped;
23
+ pass.req = Object.freeze(await stamped);
23
24
  }
24
25
  catch (error) {
25
26
  unread = { error };
@@ -37,31 +38,13 @@ export async function runGateFold(pass) {
37
38
  pass.classifierRound = attributed;
38
39
  }
39
40
  if ((pass.decision.action === "allow" || pass.decision.action === "ask") && pass.decision.updatedInput !== undefined) {
40
- pass.policyRewrite = pass.decision.updatedInput;
41
+ pass.policyRewrite = argsAsTheToolReads(pass.req, pass.decision.updatedInput);
41
42
  }
42
43
  else if (pass.hookAsk?.updatedInput !== undefined) {
43
- pass.policyRewrite = pass.hookAsk.updatedInput;
44
+ pass.policyRewrite = argsAsTheToolReads(pass.req, pass.hookAsk.updatedInput);
44
45
  }
45
- if (pass.decision.action === "allow" && pass.hookAsk) {
46
- pass.decision = {
47
- action: "ask",
48
- ...(pass.hookAsk.message !== undefined ? { message: pass.hookAsk.message } : {}),
49
- decisionReason: "hook",
50
- ...(pass.hookAsk.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
51
- ...(pass.hookAsk.updatedInput !== undefined ? { updatedInput: pass.hookAsk.updatedInput } : {}),
52
- };
53
- }
54
- else if (pass.decision.action === "ask" && pass.hookAsk) {
55
- const hookMessage = pass.hookAsk.message;
56
- const foldedMessage = hookMessage !== undefined && hookMessage !== pass.decision.message
57
- ? `${pass.decision.message !== undefined ? `${pass.decision.message} ` : ""}(a PreToolUse hook also asks: ${hookMessage})`
58
- : pass.decision.message;
59
- pass.decision = {
60
- ...pass.decision,
61
- decisionReason: "hook",
62
- ...(foldedMessage !== undefined ? { message: foldedMessage } : {}),
63
- ...(pass.hookAsk.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
64
- };
46
+ if (pass.hookAsk !== undefined && pass.decision.action !== "deny") {
47
+ pass.decision = foldHookAsk(pass.decision, pass.hookAsk);
65
48
  }
66
49
  if ((pass.decision.action === "allow" || pass.decision.action === "ask") && input.shellReadCheck !== undefined) {
67
50
  const station = input.shellReadCheck;