@sema-agent/core 7.51.2 → 7.52.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 (363) hide show
  1. package/CHANGELOG.md +504 -2
  2. package/dist/agents/agent-transcript-tool.d.ts +1 -1
  3. package/dist/agents/cascade.js +4 -0
  4. package/dist/agents/cumulative-stats.d.ts +3 -0
  5. package/dist/agents/cumulative-stats.js +3 -0
  6. package/dist/agents/list-agents-tool.d.ts +1 -1
  7. package/dist/agents/read-inbox-tool.d.ts +1 -1
  8. package/dist/agents/repair-loop.js +4 -0
  9. package/dist/agents/send-message-tool.d.ts +11 -16
  10. package/dist/agents/send-message-tool.js +11 -13
  11. package/dist/agents/subagent.js +6 -4
  12. package/dist/agents/tool-filter.d.ts +40 -13
  13. package/dist/agents/tool-filter.js +28 -14
  14. package/dist/bench/metrics.d.ts +1 -0
  15. package/dist/brain/anthropic.js +16 -12
  16. package/dist/brain/model-presets.d.ts +4 -5
  17. package/dist/brain/model-presets.js +4 -4
  18. package/dist/brain/open-responses.js +16 -12
  19. package/dist/brain/openai.js +16 -12
  20. package/dist/brain/request-params.d.ts +12 -33
  21. package/dist/brain/request-params.js +5 -2
  22. package/dist/brain/request-route.d.ts +9 -8
  23. package/dist/brain/request-route.js +1 -0
  24. package/dist/brain/route-adjudicator.d.ts +117 -47
  25. package/dist/brain/route-adjudicator.js +171 -42
  26. package/dist/brain/route-conformance.js +2 -2
  27. package/dist/brain/status-sink.d.ts +18 -0
  28. package/dist/brain/status-sink.js +7 -0
  29. package/dist/core/allow-entry.d.ts +40 -8
  30. package/dist/core/allow-entry.js +23 -16
  31. package/dist/core/auto-compaction.d.ts +23 -20
  32. package/dist/core/auto-compaction.js +37 -16
  33. package/dist/core/auto-promote.d.ts +2 -1
  34. package/dist/core/auto-promote.js +2 -2
  35. package/dist/core/caller-tool-name.d.ts +9 -0
  36. package/dist/core/caller-tool-name.js +13 -0
  37. package/dist/core/checkpoint-requirements.d.ts +7 -1
  38. package/dist/core/checkpoint-requirements.js +2 -0
  39. package/dist/core/checkpoint-store.d.ts +36 -12
  40. package/dist/core/checkpoint-store.js +1 -1
  41. package/dist/core/child-clamp-seats.d.ts +6 -0
  42. package/dist/core/child-clamp-seats.js +2 -1
  43. package/dist/core/credential-vocabulary.d.ts +33 -8
  44. package/dist/core/credential-vocabulary.js +32 -7
  45. package/dist/core/decision-receipt.d.ts +2 -2
  46. package/dist/core/delegation-frames.d.ts +9 -2
  47. package/dist/core/delegation-name.d.ts +18 -0
  48. package/dist/core/delegation-name.js +47 -0
  49. package/dist/core/engine-capabilities.d.ts +8 -1
  50. package/dist/core/engine-capabilities.js +1 -1
  51. package/dist/core/engine-notice.d.ts +36 -19
  52. package/dist/core/frontmatter-fence.d.ts +10 -0
  53. package/dist/core/frontmatter-fence.js +6 -0
  54. package/dist/core/gate-fold.js +5 -23
  55. package/dist/core/gate-lanes.js +356 -270
  56. package/dist/core/governance-codes.d.ts +9 -4
  57. package/dist/core/governance-codes.js +9 -3
  58. package/dist/core/hooks.d.ts +276 -734
  59. package/dist/core/hooks.js +97 -192
  60. package/dist/{tools/fs → core}/image-admission.d.ts +21 -3
  61. package/dist/{tools/fs → core}/image-admission.js +24 -6
  62. package/dist/core/mcp-connection-pool.d.ts +4 -1
  63. package/dist/core/mcp-connection-pool.js +7 -2
  64. package/dist/core/mcp-probe.d.ts +12 -9
  65. package/dist/core/mcp-probe.js +2 -2
  66. package/dist/core/mcp-server-spec.d.ts +16 -0
  67. package/dist/core/mcp.d.ts +11 -7
  68. package/dist/core/mcp.js +11 -5
  69. package/dist/core/memory-engine/data-plane.js +5 -1
  70. package/dist/core/memory-engine/distiller.js +16 -2
  71. package/dist/core/memory-engine/engine.d.ts +8 -11
  72. package/dist/core/memory-engine/engine.js +9 -5
  73. package/dist/core/memory-engine/frontmatter.d.ts +6 -0
  74. package/dist/core/memory-engine/frontmatter.js +19 -16
  75. package/dist/core/memory.d.ts +2 -2
  76. package/dist/core/mode-policy.d.ts +4 -0
  77. package/dist/core/mode-policy.js +7 -5
  78. package/dist/core/model-seat.d.ts +4 -1
  79. package/dist/core/mods/dollar.d.ts +109 -0
  80. package/dist/core/mods/dollar.js +154 -0
  81. package/dist/core/mods/host.d.ts +23 -0
  82. package/dist/core/mods/host.js +21 -0
  83. package/dist/core/mods/kernel/budget.d.ts +43 -0
  84. package/dist/core/mods/kernel/budget.js +83 -0
  85. package/dist/core/mods/kernel/dispatch.d.ts +100 -0
  86. package/dist/core/mods/kernel/dispatch.js +701 -0
  87. package/dist/core/mods/kernel/events.d.ts +242 -0
  88. package/dist/core/mods/kernel/events.js +210 -0
  89. package/dist/core/mods/kernel/index.d.ts +6 -0
  90. package/dist/core/mods/kernel/index.js +5 -0
  91. package/dist/core/mods/kernel/receive.d.ts +65 -0
  92. package/dist/core/mods/kernel/receive.js +123 -0
  93. package/dist/core/mods/kernel/registration.d.ts +131 -0
  94. package/dist/core/mods/kernel/registration.js +102 -0
  95. package/dist/core/mods/kernel/site-rules.d.ts +84 -0
  96. package/dist/core/mods/kernel/site-rules.js +104 -0
  97. package/dist/core/mods/stations.d.ts +350 -0
  98. package/dist/core/mods/stations.js +444 -0
  99. package/dist/core/own-property-receipt.js +11 -23
  100. package/dist/core/parent-spec-seat.d.ts +18 -7
  101. package/dist/core/parent-spec-seat.js +6 -2
  102. package/dist/core/path-identity.js +2 -1
  103. package/dist/core/permission-rule-syntax.d.ts +15 -0
  104. package/dist/core/permission-rule-syntax.js +24 -16
  105. package/dist/core/permission-rules.d.ts +7 -1
  106. package/dist/core/permission-rules.js +26 -15
  107. package/dist/core/prompt-section-seat.d.ts +15 -27
  108. package/dist/core/prompt-section-seat.js +73 -40
  109. package/dist/core/protocol-http-auth.d.ts +3 -1
  110. package/dist/core/protocol-http-auth.js +2 -0
  111. package/dist/core/reminder-mint.d.ts +2 -2
  112. package/dist/core/remote-env.d.ts +24 -12
  113. package/dist/core/remote-env.js +1 -0
  114. package/dist/core/resume-startup-cause.d.ts +16 -1
  115. package/dist/core/resume-startup-cause.js +4 -1
  116. package/dist/core/retired-keys.d.ts +4 -0
  117. package/dist/core/retired-keys.js +3 -0
  118. package/dist/core/runner/announce-once-ledger.d.ts +31 -1
  119. package/dist/core/runner/announce-once-ledger.js +22 -0
  120. package/dist/core/runner/assemble-result.d.ts +9 -0
  121. package/dist/core/runner/assemble-result.js +3 -1
  122. package/dist/core/runner/call-hook-stations.d.ts +23 -27
  123. package/dist/core/runner/call-hook-stations.js +58 -42
  124. package/dist/core/runner/caller-stop-gate.d.ts +25 -0
  125. package/dist/core/runner/caller-stop-gate.js +7 -0
  126. package/dist/core/runner/compaction-seams.d.ts +8 -22
  127. package/dist/core/runner/compaction-seams.js +28 -53
  128. package/dist/core/runner/construction-doors.js +11 -1
  129. package/dist/core/runner/contracts.d.ts +85 -83
  130. package/dist/core/runner/credential-origin-seat.d.ts +2 -0
  131. package/dist/core/runner/credential-origin-seat.js +19 -0
  132. package/dist/core/runner/extra-body-dropped-seat.d.ts +2 -6
  133. package/dist/core/runner/gate-exit.d.ts +47 -36
  134. package/dist/core/runner/gate-exit.js +8 -2
  135. package/dist/core/runner/image.js +1 -2
  136. package/dist/core/runner/inline-image.js +1 -1
  137. package/dist/core/runner/notice-seat-input.d.ts +11 -0
  138. package/dist/core/runner/notice-seat-input.js +1 -0
  139. package/dist/core/runner/person-path-rows.js +1 -0
  140. package/dist/core/runner/prepare-acquire-reconcile.js +5 -1
  141. package/dist/core/runner/prepare-ask-lane.d.ts +5 -7
  142. package/dist/core/runner/prepare-ask-lane.js +6 -15
  143. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
  144. package/dist/core/runner/prepare-caps-and-workflow.js +25 -8
  145. package/dist/core/runner/prepare-config-doors.d.ts +5 -0
  146. package/dist/core/runner/prepare-config-doors.js +9 -0
  147. package/dist/core/runner/prepare-defer-classify.js +3 -4
  148. package/dist/core/runner/prepare-gate-stations.d.ts +8 -11
  149. package/dist/core/runner/prepare-gate-stations.js +11 -10
  150. package/dist/core/runner/prepare-inherited-gate.d.ts +8 -12
  151. package/dist/core/runner/prepare-inherited-gate.js +8 -21
  152. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  153. package/dist/core/runner/prepare-park-ask.js +10 -14
  154. package/dist/core/runner/prepare-policy-chain.d.ts +17 -15
  155. package/dist/core/runner/prepare-policy-chain.js +95 -100
  156. package/dist/core/runner/prepare-project-context.js +7 -10
  157. package/dist/core/runner/prepare-prompt-assembly.d.ts +45 -40
  158. package/dist/core/runner/prepare-prompt-assembly.js +134 -101
  159. package/dist/core/runner/prepare-prompt-inputs.d.ts +18 -19
  160. package/dist/core/runner/prepare-prompt-inputs.js +5 -7
  161. package/dist/core/runner/prepare-protocol-tools.d.ts +6 -4
  162. package/dist/core/runner/prepare-protocol-tools.js +2 -2
  163. package/dist/core/runner/prepare-safety-scan.js +6 -10
  164. package/dist/core/runner/prepare-suspend-saga.d.ts +6 -0
  165. package/dist/core/runner/prepare-suspend-saga.js +7 -5
  166. package/dist/core/runner/prepare-task.js +33 -15
  167. package/dist/core/runner/prepare-turn-wiring.d.ts +13 -15
  168. package/dist/core/runner/prepare-turn-wiring.js +29 -27
  169. package/dist/core/runner/prepare-wiring-manifest.d.ts +5 -6
  170. package/dist/core/runner/prepare-wiring-manifest.js +7 -7
  171. package/dist/core/runner/resume-apply.d.ts +5 -2
  172. package/dist/core/runner/resume-apply.js +24 -42
  173. package/dist/core/runner/resume-checkpoint-screen.d.ts +1 -0
  174. package/dist/core/runner/resume-checkpoint-screen.js +9 -1
  175. package/dist/core/runner/resume-preflight.js +38 -16
  176. package/dist/core/runner/retired-runner-deps.js +3 -1
  177. package/dist/core/runner/run-brain-sinks.d.ts +3 -2
  178. package/dist/core/runner/run-brain-sinks.js +5 -1
  179. package/dist/core/runner/run-compaction-machinery.d.ts +7 -1
  180. package/dist/core/runner/run-compaction-machinery.js +7 -33
  181. package/dist/core/runner/run-harness-handlers.js +4 -2
  182. package/dist/core/runner/run-identity-wiring.d.ts +3 -1
  183. package/dist/core/runner/run-identity-wiring.js +3 -2
  184. package/dist/core/runner/run-leg.js +62 -84
  185. package/dist/core/runner/run-notification-lane.js +1 -0
  186. package/dist/core/runner/run-recovery-lanes.d.ts +3 -0
  187. package/dist/core/runner/run-recovery-lanes.js +11 -10
  188. package/dist/core/runner/run-settle-and-teardown.js +9 -28
  189. package/dist/core/runner/run-stop-and-final-verify.js +18 -25
  190. package/dist/core/runner/run-terminal-adoption.d.ts +3 -0
  191. package/dist/core/runner/run-terminal-adoption.js +33 -22
  192. package/dist/core/runner/run-tool-mount-facts.js +5 -3
  193. package/dist/core/runner/run-turn-boundary.js +23 -34
  194. package/dist/core/runner/runtask.d.ts +6 -7
  195. package/dist/core/runner/runtask.js +14 -72
  196. package/dist/core/runner/session-rule-policy.d.ts +5 -5
  197. package/dist/core/runner/session-rule-policy.js +13 -8
  198. package/dist/core/runner/side-call-account.d.ts +68 -0
  199. package/dist/core/runner/side-call-account.js +61 -0
  200. package/dist/core/runner/stream-halt-verbs.js +12 -17
  201. package/dist/core/runner/stream-lifecycle-verbs.js +8 -5
  202. package/dist/core/runner/stream-steer-verb.d.ts +1 -1
  203. package/dist/core/runner/stream-steer-verb.js +20 -38
  204. package/dist/core/runner/sub-agent-deny-lists.d.ts +121 -22
  205. package/dist/core/runner/sub-agent-deny-lists.js +228 -71
  206. package/dist/core/runner/tool-end-body.d.ts +5 -6
  207. package/dist/core/runner/tool-end-body.js +6 -4
  208. package/dist/core/runner/tool-not-executed.d.ts +15 -0
  209. package/dist/core/runner/tool-not-executed.js +30 -0
  210. package/dist/core/runner/tool-occurrence.d.ts +8 -7
  211. package/dist/core/runner/tool-occurrence.js +5 -5
  212. package/dist/core/runner/tool-result-media-seat.d.ts +1 -1
  213. package/dist/core/runner-deps.d.ts +20 -28
  214. package/dist/core/safety-merge-corpus.js +18 -2
  215. package/dist/core/secret-env.d.ts +88 -20
  216. package/dist/core/secret-env.js +192 -38
  217. package/dist/core/session-policy-store.d.ts +52 -16
  218. package/dist/core/session-policy-store.js +118 -28
  219. package/dist/core/session-reconcile.d.ts +4 -0
  220. package/dist/core/session-reconcile.js +2 -1
  221. package/dist/core/shell-read-silence.js +3 -32
  222. package/dist/core/side-query.d.ts +5 -3
  223. package/dist/core/skill-grant.d.ts +3 -2
  224. package/dist/core/skill-grant.js +17 -9
  225. package/dist/core/skills-directory.d.ts +31 -11
  226. package/dist/core/skills-directory.js +655 -104
  227. package/dist/core/task-event.d.ts +13 -3
  228. package/dist/core/task-result.d.ts +8 -0
  229. package/dist/core/task-spec.d.ts +20 -19
  230. package/dist/core/task-stream.d.ts +14 -4
  231. package/dist/core/tighten-task-spec.d.ts +4 -3
  232. package/dist/core/tighten-task-spec.js +2 -4
  233. package/dist/core/tool-check-reading.d.ts +74 -0
  234. package/dist/core/tool-check-reading.js +80 -0
  235. package/dist/core/tool-policy.d.ts +59 -18
  236. package/dist/core/tool-policy.js +77 -12
  237. package/dist/core/tool-registry.d.ts +20 -0
  238. package/dist/core/tool-registry.js +4 -0
  239. package/dist/core/tool-spec.d.ts +10 -6
  240. package/dist/core/tools.js +2 -0
  241. package/dist/core/trace.d.ts +51 -32
  242. package/dist/core/unc-spelling.d.ts +10 -0
  243. package/dist/core/unc-spelling.js +3 -0
  244. package/dist/core/untrusted-egress.d.ts +8 -0
  245. package/dist/core/untrusted-egress.js +4 -1
  246. package/dist/core/user-attachment.d.ts +12 -2
  247. package/dist/core/user-attachment.js +17 -2
  248. package/dist/core/wiring-manifest.d.ts +14 -13
  249. package/dist/core/wiring-manifest.js +2 -2
  250. package/dist/engine/compaction/utils.js +1 -2
  251. package/dist/engine/execution-env/node-execution-env.d.ts +4 -3
  252. package/dist/engine/execution-env/symlink-chain.js +1 -1
  253. package/dist/engine/harness/agent-harness.d.ts +1 -1
  254. package/dist/engine/harness/agent-harness.js +3 -3
  255. package/dist/engine/harness/types.d.ts +17 -16
  256. package/dist/engine/harness/types.js +7 -1
  257. package/dist/engine/llm/types.d.ts +12 -7
  258. package/dist/engine/loop/agent-loop.js +1 -1
  259. package/dist/engine/loop/types.d.ts +1 -1
  260. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  261. package/dist/engine/session/import-validate.js +3 -10
  262. package/dist/engine/session/session.d.ts +4 -4
  263. package/dist/engine/session/session.js +4 -4
  264. package/dist/index.d.ts +20 -16
  265. package/dist/index.js +13 -11
  266. package/dist/internal/harness.d.ts +1 -1
  267. package/dist/internal/harness.js +1 -1
  268. package/dist/orchestration/run-spec.d.ts +4 -6
  269. package/dist/orchestration/run-spec.js +39 -63
  270. package/dist/orchestration/run-workflow-tool.js +1 -2
  271. package/dist/orchestration/workflow.d.ts +11 -3
  272. package/dist/orchestration/workflow.js +11 -2
  273. package/dist/prompt-assembly/artifact-store.d.ts +37 -56
  274. package/dist/prompt-assembly/artifact-store.js +31 -49
  275. package/dist/prompt-assembly/artifact.d.ts +89 -76
  276. package/dist/prompt-assembly/artifact.js +167 -146
  277. package/dist/prompt-assembly/assemble.d.ts +34 -29
  278. package/dist/prompt-assembly/assemble.js +33 -220
  279. package/dist/prompt-assembly/bands.d.ts +20 -0
  280. package/dist/prompt-assembly/bands.js +18 -0
  281. package/dist/prompt-assembly/catalog/constitution.d.ts +23 -0
  282. package/dist/prompt-assembly/catalog/constitution.js +69 -0
  283. package/dist/prompt-assembly/catalog/core-behavior.d.ts +9 -0
  284. package/dist/prompt-assembly/catalog/core-behavior.js +85 -0
  285. package/dist/prompt-assembly/catalog/index.d.ts +11 -0
  286. package/dist/prompt-assembly/catalog/index.js +59 -0
  287. package/dist/prompt-assembly/catalog/modes.d.ts +15 -0
  288. package/dist/prompt-assembly/catalog/modes.js +137 -0
  289. package/dist/prompt-assembly/catalog/role.d.ts +10 -0
  290. package/dist/prompt-assembly/catalog/role.js +157 -0
  291. package/dist/prompt-assembly/catalog/schema.d.ts +124 -0
  292. package/dist/prompt-assembly/catalog/schema.js +25 -0
  293. package/dist/prompt-assembly/catalog/sections.d.ts +9 -0
  294. package/dist/prompt-assembly/catalog/sections.js +98 -0
  295. package/dist/prompt-assembly/catalog/team.d.ts +4 -0
  296. package/dist/prompt-assembly/catalog/team.js +258 -0
  297. package/dist/prompt-assembly/composer.d.ts +24 -28
  298. package/dist/prompt-assembly/composer.js +124 -46
  299. package/dist/prompt-assembly/epoch.d.ts +89 -79
  300. package/dist/prompt-assembly/epoch.js +115 -142
  301. package/dist/prompt-assembly/explain.d.ts +58 -34
  302. package/dist/prompt-assembly/explain.js +21 -24
  303. package/dist/prompt-assembly/overlay.d.ts +127 -0
  304. package/dist/prompt-assembly/overlay.js +301 -0
  305. package/dist/prompt-assembly/renderers.d.ts +21 -0
  306. package/dist/prompt-assembly/renderers.js +39 -0
  307. package/dist/prompt-assembly/section-usage.d.ts +3 -3
  308. package/dist/prompt-assembly/section-usage.js +1 -1
  309. package/dist/prompt-assembly/select.d.ts +56 -0
  310. package/dist/prompt-assembly/select.js +69 -0
  311. package/dist/prompt-assembly/sugar.d.ts +31 -0
  312. package/dist/prompt-assembly/sugar.js +20 -0
  313. package/dist/prompt-assembly/turn-snapshot.d.ts +3 -2
  314. package/dist/prompt-assembly/types.d.ts +45 -148
  315. package/dist/prompts/coordinator.d.ts +2 -21
  316. package/dist/prompts/coordinator.js +3 -255
  317. package/dist/prompts/cowork.d.ts +27 -16
  318. package/dist/prompts/cowork.js +2 -23
  319. package/dist/prompts/default.d.ts +38 -500
  320. package/dist/prompts/default.js +20 -285
  321. package/dist/prompts/supervisor.d.ts +6 -71
  322. package/dist/prompts/supervisor.js +6 -117
  323. package/dist/tools/fs/bash-readonly-classifier.d.ts +6 -5
  324. package/dist/tools/fs/dir-entries.d.ts +4 -2
  325. package/dist/tools/fs/dir-entries.js +16 -4
  326. package/dist/tools/fs/fs-bash.d.ts +1 -1
  327. package/dist/tools/fs/fs-bash.js +22 -11
  328. package/dist/tools/fs/fs-pdf.js +17 -13
  329. package/dist/tools/fs/fs-read.js +4 -3
  330. package/dist/tools/fs/fs-shared.d.ts +1 -10
  331. package/dist/tools/fs/fs-shared.js +3 -4
  332. package/dist/tools/fs/fs-write.js +2 -1
  333. package/dist/tools/fs/notebook.js +1 -1
  334. package/dist/tools/fs/pdf.d.ts +20 -10
  335. package/dist/tools/fs/pdf.js +19 -10
  336. package/dist/tools/fs/program-read-model.d.ts +68 -8
  337. package/dist/tools/fs/program-read-model.js +112 -33
  338. package/dist/tools/fs/program-read-model.rows.js +30 -10
  339. package/dist/tools/fs/read-deny-home.d.ts +25 -9
  340. package/dist/tools/fs/read-deny-home.js +28 -27
  341. package/dist/tools/fs/read-deny.d.ts +41 -11
  342. package/dist/tools/fs/read-deny.js +51 -5
  343. package/dist/tools/fs/safety.d.ts +4 -26
  344. package/dist/tools/fs/safety.js +10 -32
  345. package/dist/tools/fs/search.js +15 -10
  346. package/dist/tools/fs/shell-read-argv.d.ts +3 -2
  347. package/dist/tools/fs/shell-read-argv.js +118 -38
  348. package/dist/tools/fs/shell-read-establish.d.ts +5 -5
  349. package/dist/tools/fs/shell-read-establish.js +11 -61
  350. package/dist/tools/fs/shell-read-identity.js +6 -3
  351. package/dist/tools/fs/shell-read-judge.d.ts +13 -15
  352. package/dist/tools/fs/shell-read-judge.js +18 -4
  353. package/dist/tools/fs/shell-read-plan.d.ts +2 -2
  354. package/dist/tools/web.js +1 -1
  355. package/package.json +13 -1
  356. package/test/export-surface.snapshot.json +242 -99
  357. package/wire-changes/core@7.52.0.json +5859 -0
  358. package/dist/core/hook-seats.d.ts +0 -66
  359. package/dist/core/hook-seats.js +0 -37
  360. package/dist/prompt-assembly/packs/sema-default.d.ts +0 -2
  361. package/dist/prompt-assembly/packs/sema-default.js +0 -147
  362. package/dist/prompts/simple-sections.d.ts +0 -58
  363. package/dist/prompts/simple-sections.js +0 -43
@@ -1,9 +1,8 @@
1
1
  import { CROSS_SESSION_MESSAGE_TAG } from "../agents/cross-session-envelope.js";
2
2
  import { DEFAULT_CHARS_PER_TOKEN, DEFAULT_CLAMP_TOLERANCE, DEFAULT_COMPACTION_SETTINGS, CompactionError, compact, computeFileLists, dryRunSummarizationClamp, estimateContextTokens, estimateTokens, formatFileOperations, formatPersistedOutputRefs, prepareCompaction, shouldCompact, } from "../internal/harness.js";
3
- import { fileArgPath } from "../tools/fs/safety.js";
3
+ import { fileArgPath } from "./tool-registry.js";
4
4
  import { contextEditFrontier, resolveTriggerWindow } from "./context-edit.js";
5
5
  import { selectCompactionEpoch } from "../prompt-assembly/epoch.js";
6
- import { SEMA_DEFAULT_PACK } from "../prompt-assembly/packs/sema-default.js";
7
6
  import { brainToRuntime } from "./runtime.js";
8
7
  import { defuseFenceMarkers, sanitizeUntrustedText } from "./untrusted-text.js";
9
8
  import { createSafeNotifier } from "./safe-notify.js";
@@ -158,19 +157,42 @@ export async function maybeCompact(opts) {
158
157
  let providerSummary;
159
158
  if (opts.summaryProvider && !forceRealSummary && !prep.value.isSplitTurn) {
160
159
  const providerModifiedFiles = computeFileLists(prep.value.fileOps).modifiedFilesByRecency;
160
+ const signal = opts.signal;
161
+ const cut = Symbol("cut");
162
+ let release = () => undefined;
163
+ const cutByAbort = new Promise((resolve) => {
164
+ if (signal === undefined || signal.aborted)
165
+ return;
166
+ const onAbort = () => resolve(cut);
167
+ signal.addEventListener("abort", onAbort, { once: true });
168
+ release = () => signal.removeEventListener("abort", onAbort);
169
+ });
170
+ let consulted;
161
171
  try {
162
- const raw = await opts.summaryProvider({
163
- messagesToSummarize: prep.value.messagesToSummarize,
164
- previousSummary: prep.value.previousSummary,
165
- modifiedFiles: providerModifiedFiles,
166
- });
167
- const trimmed = typeof raw === "string" ? raw.trim() : "";
172
+ consulted =
173
+ signal?.aborted === true
174
+ ? cut
175
+ : await Promise.race([
176
+ Promise.resolve(opts.summaryProvider({
177
+ messagesToSummarize: prep.value.messagesToSummarize,
178
+ previousSummary: prep.value.previousSummary,
179
+ modifiedFiles: providerModifiedFiles,
180
+ })),
181
+ cutByAbort,
182
+ ]);
183
+ const trimmed = typeof consulted === "string" ? consulted.trim() : "";
168
184
  if (trimmed) {
169
185
  providerSummary = trimmed;
170
186
  }
171
187
  }
172
188
  catch {
173
189
  }
190
+ finally {
191
+ release();
192
+ }
193
+ if (consulted === cut) {
194
+ throw Object.assign(new CompactionError("aborted", "compaction cancelled while the summary provider was answering — nothing was persisted"), opts.manualCancelSignal?.aborted === true ? { [COMPACTION_MANUAL_CANCEL_FLAG]: true } : {});
195
+ }
174
196
  }
175
197
  let summary;
176
198
  let firstKeptEntryId;
@@ -448,18 +470,17 @@ export async function maybeCompact(opts) {
448
470
  for (const m of ctx.messages)
449
471
  preChars += estimateTokens(m, cpt);
450
472
  const ca = opts.centerAdoption;
451
- const restatedEpoch = selectCompactionEpoch((await opts.session.getPromptEpoch?.()) ?? undefined, SEMA_DEFAULT_PACK, ca?.declaredSections ?? opts.epochDeclaredSections, ca !== undefined
452
- ? ca.clear === true
453
- ? { clear: true }
454
- : { centerArtifactDigest: ca.centerArtifactDigest, ...(ca.sourceRevision !== undefined ? { sourceRevision: ca.sourceRevision } : {}) }
455
- : undefined);
473
+ const stored = await opts.session.getPromptEpoch?.();
474
+ const current = stored?.kind === "pin" ? stored.descriptor : undefined;
475
+ const identityNow = ca?.promptIdentity ?? opts.promptIdentity ?? (current !== undefined ? { layers: current.layers, ...(current.sourceRevision !== undefined ? { sourceRevision: current.sourceRevision } : {}) } : undefined);
476
+ const restatedEpoch = identityNow !== undefined ? selectCompactionEpoch(current, identityNow.layers, identityNow.sourceRevision) : undefined;
456
477
  const restatedListings = await opts.session.getAnnouncedListing().catch(() => undefined);
457
478
  if (opts.signal?.aborted === true) {
458
479
  throw Object.assign(new Error("compaction cancelled before commit — the abort signal fired during the summary call; nothing was persisted"), opts.manualCancelSignal?.aborted === true ? { [COMPACTION_MANUAL_CANCEL_FLAG]: true } : {});
459
480
  }
460
481
  await opts.session.appendCompaction(summaryWithAttachments, firstKeptEntryId, summaryTokensBefore, {
461
482
  ...(details ?? {}),
462
- promptEpoch: restatedEpoch,
483
+ ...(restatedEpoch !== undefined ? { promptEpoch: restatedEpoch } : {}),
463
484
  ...(restatedListings !== undefined ? { announcedListings: restatedListings } : {}),
464
485
  ...(opts.activeTools !== undefined && opts.activeTools.length > 0 ? { activeTools: [...opts.activeTools] } : {}),
465
486
  ...(opts.gitRestate !== undefined ? { gitAnnouncement: { kind: opts.gitRestate.pending.kind, hash: opts.gitRestate.pending.hash, pending: true } } : {}),
@@ -494,9 +515,9 @@ export async function maybeCompact(opts) {
494
515
  }
495
516
  catch {
496
517
  }
497
- if (ca !== undefined) {
518
+ if (ca !== undefined && restatedEpoch !== undefined) {
498
519
  try {
499
- ca.apply(restatedEpoch.artifactDigest);
520
+ ca.apply(restatedEpoch.identity);
500
521
  }
501
522
  catch {
502
523
  }
@@ -106,7 +106,8 @@ export declare const FROZEN_DENYLIST_FLOOR: ReadonlySet<string>;
106
106
  *
107
107
  * @param artifactText the artifact's raw text (markdown body included).
108
108
  * @param declared the artifact's declared tool list (the `SkillSpec` member the loader copies) — its `allowedTools`
109
- * entries, each read as a permission rule for the tool it names, are the symbol-drift baseline.
109
+ * entries, read by the list reader as a rule for the tool each names (one it reads as nothing names none), are the
110
+ * symbol-drift baseline.
110
111
  * @param profileTokens optional ADD-ONLY extra denylist tokens (UNIONed onto the frozen floor; cannot remove).
111
112
  */
112
113
  export declare function deriveTripwire(artifactText: string, declared: Pick<SkillSpec, "allowedTools">, profileTokens?: ReadonlySet<string>): TripwireResult;
@@ -1,5 +1,5 @@
1
1
  import { extractSymbols } from "../tools/fs/repo-map.js";
2
- import { parsePermissionRule } from "./permission-rules.js";
2
+ import { compileAllowList, compiledEntryName } from "./allow-entry.js";
3
3
  import { thrownText } from "./thrown-value.js";
4
4
  export function decideAutoPromote(i) {
5
5
  if (i.tripwire.escalate)
@@ -60,7 +60,7 @@ export function deriveTripwire(artifactText, declared, profileTokens) {
60
60
  const reasons = [];
61
61
  let escalate = false;
62
62
  try {
63
- const allow = new Set((declared.allowedTools ?? []).map((entry) => parsePermissionRule(entry).toolName));
63
+ const allow = new Set(compileAllowList(declared.allowedTools ?? [], "allow").rows.map((r) => compiledEntryName(r.compiled)));
64
64
  const symbols = extractSymbols(artifactText);
65
65
  for (const sym of symbols) {
66
66
  if (!allow.has(sym)) {
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Why `name` cannot be a caller tool's name or alias — or `undefined` when it can. Two clauses, in this order:
3
+ * - the name must be one a rule can name ({@link isNameableToolName}; a value that is not a string is none): a tool mounted
4
+ * under a name no list can write could be neither granted nor refused by name;
5
+ * - `__` is reserved for the protocol namespaces: a caller name carrying it is read as a peer's tool everywhere names are
6
+ * parsed (routing, policy, telemetry), and an alias carrying it would sit inside a peer's prefix domain (a refresh would
7
+ * classify or clear it as remote, and a remote tool minted under the same name would shadow the local one).
8
+ */
9
+ export declare function callerToolNameProblem(name: string): string | undefined;
@@ -0,0 +1,13 @@
1
+ import { NAMESPACED_NAME_SHAPES, carriesNamespaceSeparator } from "./protocol-table.js";
2
+ import { isNameableToolName } from "./permission-rule-syntax.js";
3
+ export function callerToolNameProblem(name) {
4
+ if (!isNameableToolName(name)) {
5
+ return (`a caller tool name or alias must be a name a rule can name — ASCII letters, digits and "_" "-" "." ":" "*", ` +
6
+ `starting with a letter, a digit or "_", not ending with "." or ":", and not the lone wildcard "*" — ` +
7
+ `or no allow or deny list could name the tool; rename it`);
8
+ }
9
+ if (carriesNamespaceSeparator(name)) {
10
+ return `"__" is reserved for the engine's protocol tool namespaces (${NAMESPACED_NAME_SHAPES}) and no caller tool name or alias may carry it`;
11
+ }
12
+ return undefined;
13
+ }
@@ -6,7 +6,7 @@ import { type StoreFidelity, type Checkpoint, type CheckpointFeature, type Check
6
6
  * had carried beside the one its word now names, and the members added after the table, each a capability a reader
7
7
  * must have. Downstream reads them for display only (`CheckpointError.detail.requires`).
8
8
  */
9
- export declare const REQUIREMENT_WORDS: readonly ["resource", "binding", "token", "orgAdmission", "f012", "realApproval", "face", "requirements_digest", "org_admission_inherited", "org_write_grant", "org_governed", "delegation_provenance", "skill_grants", "skill_card_binding", "hands_coordinates", "hands_home", "path_rule_anchors", "path_rule_installations", "permission_mode", "plan_mode_restore", "persisted_rule_mandate", "deployment_authored", "call_names", "write_face", "denial_limit_fallback", "leg_scope", "tool_ceiling", "tool_lists_judged"];
9
+ export declare const REQUIREMENT_WORDS: readonly ["resource", "binding", "token", "orgAdmission", "f012", "realApproval", "face", "requirements_digest", "org_admission_inherited", "org_write_grant", "org_governed", "delegation_provenance", "skill_grants", "skill_card_binding", "hands_coordinates", "hands_home", "path_rule_anchors", "path_rule_installations", "permission_mode", "plan_mode_restore", "persisted_rule_mandate", "deployment_authored", "call_names", "write_face", "denial_limit_fallback", "leg_scope", "tool_ceiling", "tool_lists_judged", "own_tool_lists"];
10
10
  export type RequirementWord = (typeof REQUIREMENT_WORDS)[number];
11
11
  /** Runtime twin of {@link RequirementWord}. */
12
12
  export declare function isRequirementWord(word: unknown): word is RequirementWord;
@@ -224,6 +224,9 @@ export declare const CHECKPOINT_STATE_REQUIREMENTS: {
224
224
  readonly toolListsJudged: {
225
225
  readonly word: "tool_lists_judged";
226
226
  };
227
+ readonly ownToolLists: {
228
+ readonly word: "own_tool_lists";
229
+ };
227
230
  };
228
231
  export declare const PENDING_ACTION_REQUIREMENTS: {
229
232
  readonly tool_approval: {
@@ -576,6 +579,9 @@ export declare const CHECKPOINT_REQUIREMENTS: {
576
579
  readonly toolListsJudged: {
577
580
  readonly word: "tool_lists_judged";
578
581
  };
582
+ readonly ownToolLists: {
583
+ readonly word: "own_tool_lists";
584
+ };
579
585
  };
580
586
  };
581
587
  readonly resourceLedger: {
@@ -30,6 +30,7 @@ export const REQUIREMENT_WORDS = Object.freeze([
30
30
  "leg_scope",
31
31
  "tool_ceiling",
32
32
  "tool_lists_judged",
33
+ "own_tool_lists",
33
34
  ]);
34
35
  export function isRequirementWord(word) {
35
36
  return typeof word === "string" && REQUIREMENT_WORDS.includes(word);
@@ -90,6 +91,7 @@ export const CHECKPOINT_STATE_REQUIREMENTS = {
90
91
  legScope: { word: "leg_scope" },
91
92
  toolCeiling: { word: "tool_ceiling" },
92
93
  toolListsJudged: { word: "tool_lists_judged" },
94
+ ownToolLists: { word: "own_tool_lists" },
93
95
  };
94
96
  export const PENDING_ACTION_REQUIREMENTS = {
95
97
  tool_approval: {
@@ -1338,7 +1338,9 @@ export interface CheckpointState {
1338
1338
  legScope?: string;
1339
1339
  /** The tool-selector layers this LEG was spawned under (`RunInternals.toolCeiling`), stamped at every mint: a resume that hands
1340
1340
  * no live ceiling restores it, so a resumed child can never use a tool its spawning run could not. Absent ⇒ the leg had no
1341
- * ceiling (a root run) or the row was minted before the member. A reader that lacks the word would run the leg unbounded. */
1341
+ * ceiling (a root run) or the row was minted before the member. A reader that lacks the word would run the leg unbounded.
1342
+ * Each entry is a tool name in its canonical spelling (`persistedToolNameList`, `src/agents/tool-filter.ts`): a row restored with
1343
+ * any other entry is refused before the claim (`checkpoint.config_refused`, `detail.code: config.tool_face_control`, `detail.field: inheritedGate`, the row pending). */
1342
1344
  toolCeiling?: ReadonlyArray<{
1343
1345
  readonly allow?: readonly string[];
1344
1346
  readonly deny: readonly string[];
@@ -1348,6 +1350,18 @@ export interface CheckpointState {
1348
1350
  * that hands different lists is judged again. Absent ⇒ the leg judged its own lists (or the row was minted before the member). A
1349
1351
  * reader that lacks the word would judge again a list judged against a wider universe, and refuse a leg that was valid. */
1350
1352
  toolListsJudged?: string;
1353
+ /** Whose lists this LEG's own are (`RunInternals.ownToolLists`: the delegation tool that spawned it, by its declared name, the
1354
+ * agent definition it was spawned as — absent ⇒ the tool's tool-level list — and `lists`, the digest of exactly the lists it wrote),
1355
+ * stamped at every mint while it holds: a resume that hands no internals restores it while its own lists digest to `lists`, so the
1356
+ * resumed leg asks its own lists of the same universe (which carries that tool's name — a name of its lineage, mounted or not at its
1357
+ * depth) and a refusal names the same list; a resume that hands another table reads it as the host's own `TaskSpec` seats. Absent ⇒ the
1358
+ * leg's lists were not written by a delegation tool (or the row was minted before the member): the leg judges them against its own
1359
+ * roster as before. A reader that lacks the word would refuse a list the leg's lineage wrote, and refuse a leg that was valid. */
1360
+ ownToolLists?: {
1361
+ readonly toolName: string;
1362
+ readonly definition?: string;
1363
+ readonly lists: string;
1364
+ };
1351
1365
  }
1352
1366
  /**
1353
1367
  * {@link CheckpointState} with **every** field made required-PRESENT, while each value keeps its original
@@ -2082,19 +2096,27 @@ export type CheckpointErrorReason = "version_newer" | "env_factory_missing" | "g
2082
2096
  /** On `resume.parent_constraint_mismatch`: a re-supplied chain entry whose path rules depend on the leg that installed it has
2083
2097
  * no installation record (a chain written before the record existed) / a record that does not cover the chain entry for
2084
2098
  * entry / a record member naming no absolute root. */
2085
- | "installation_record_absent" | "installation_record_misaligned" | "installation_record_invalid";
2099
+ | "installation_record_absent" | "installation_record_misaligned" | "installation_record_invalid"
2100
+ /** On `checkpoint.config_refused` with `detail.code` `config.tool_face_control` — the arm prepare's own refusal carries as its `detail.reason`:
2101
+ * a tool-name list the row recorded is not a list / has a member that is not a string / has a spelling no tool name can have / is not in
2102
+ * the one spelling a row records (`"not_a_list"`, `"not_a_string"`, `"unknown_name"`, `"unsupported_pattern"`); the record of the delegation tool that
2103
+ * wrote the leg's lists is not one (`"invalid_record"`); the roster the resume hands mounts a delegation tool under another name than it declares
2104
+ * (`"renamed_mount"`); the process-wide table of declared names is occupied by a value that is not the engine's (`"registry_occupied"`). */
2105
+ | "not_a_list" | "not_a_string" | "unknown_name" | "unsupported_pattern" | "invalid_record" | "renamed_mount" | "registry_occupied";
2086
2106
  /**
2087
- * The codes a RESUME's pre-claim configuration screen carries as `detail.code` of a `checkpoint.config_refused` — the eight
2088
- * words prepare's mode, output-style, approval-reach, invoked-skill, attachment and recorded-mode doors throw, held unchanged so one refusal
2107
+ * The codes a RESUME's pre-claim configuration screen carries as `detail.code` of a `checkpoint.config_refused` — the nine
2108
+ * words prepare's mode, output-style, approval-reach, invoked-skill, attachment, recorded-mode and tool-face doors throw, held unchanged so one refusal
2089
2109
  * reads the same on a fresh run (`TaskResult.errorCode`) and on a resume. `config.spec_retired_key`: a retired spec key;
2090
2110
  * `config.output_style_invalid`: a malformed output-style seat; `config.permission_mode_invalid`: a mode word outside the closed
2091
2111
  * set (the config's `permissionMode`, or one the row recorded); `config.shell_gate_value_retired`: a retired shell-floor word;
2092
2112
  * `config.approval_reach_invalid`: an `approvalReach` outside its set; `config.user_invoked_skill_unknown` / `skill_deny_unreadable`:
2093
2113
  * `userInvokedSkills` names a skill the config does not carry / one whose `disallowed-tools` entry the grammar reads as nothing;
2094
2114
  * `config.user_attachment_invalid`: the config declares `userAttachments` (a resume sends no new human message) or a malformed
2095
- * value there.
2115
+ * value there; `config.tool_face_control`: the tool names the row recorded (its ceiling, its frozen policy chain, the record of who wrote
2116
+ * its lists) are not readable as written, or the roster the resume hands mounts a delegation tool under another name than it declares
2117
+ * (`detail.reason` names which: {@link CheckpointErrorReason}).
2096
2118
  */
2097
- export declare const CHECKPOINT_CONFIG_REFUSAL_CODES: readonly ["config.spec_retired_key", "config.output_style_invalid", "config.permission_mode_invalid", "config.shell_gate_value_retired", "config.approval_reach_invalid", "config.user_invoked_skill_unknown", "config.skill_deny_unreadable", "config.user_attachment_invalid"];
2119
+ export declare const CHECKPOINT_CONFIG_REFUSAL_CODES: readonly ["config.spec_retired_key", "config.output_style_invalid", "config.permission_mode_invalid", "config.shell_gate_value_retired", "config.approval_reach_invalid", "config.user_invoked_skill_unknown", "config.skill_deny_unreadable", "config.user_attachment_invalid", "config.tool_face_control"];
2098
2120
  export type CheckpointConfigRefusalCode = (typeof CHECKPOINT_CONFIG_REFUSAL_CODES)[number];
2099
2121
  export declare const isCheckpointConfigRefusalCode: (word: unknown) => word is CheckpointConfigRefusalCode;
2100
2122
  /** A typed checkpoint-store error so callers branch on `code` (mirrors `SessionError`). */
@@ -2204,9 +2226,10 @@ export declare class CheckpointError extends Error {
2204
2226
  /** Parent effective-policy inheritance (shape check): the resume DID re-supply
2205
2227
  * `internals.inheritedGate.parentConstraints`, but its length differs from the checkpoint's recorded
2206
2228
  * `parentConstraintCount` — or (F-012 L1) its projection CONTENT digests differently from the
2207
- * recorded `constraintDigest` — a partial/mismatched re-supply would silently run the child under a
2208
- * thinner (or different) ancestor chain than it suspended with. Rejected pre-CAS (the checkpoint
2209
- * stays `pending`); re-resume with the full original chain. */
2229
+ * recorded `constraintDigest` — or a screening entry names a `tool.check` guard beside a policy the
2230
+ * constraint mint did not make (no chain to raise it on) — a partial/mismatched re-supply would silently run
2231
+ * the child under a thinner (or different) ancestor chain than it suspended with. Rejected pre-CAS (the
2232
+ * checkpoint stays `pending`); re-resume with the full original chain. */
2210
2233
  | "resume.parent_constraint_mismatch"
2211
2234
  /** #449 G1 (codex r2, pre-CAS entrance): a deployment usage-governance window for this resume's
2212
2235
  * ledger key (the config's principal, else the row's recorded one, else the shared bucket) is
@@ -2406,9 +2429,10 @@ export declare class CheckpointError extends Error {
2406
2429
  /** Parent effective-policy inheritance (shape check): the resume DID re-supply
2407
2430
  * `internals.inheritedGate.parentConstraints`, but its length differs from the checkpoint's recorded
2408
2431
  * `parentConstraintCount` — or (F-012 L1) its projection CONTENT digests differently from the
2409
- * recorded `constraintDigest` — a partial/mismatched re-supply would silently run the child under a
2410
- * thinner (or different) ancestor chain than it suspended with. Rejected pre-CAS (the checkpoint
2411
- * stays `pending`); re-resume with the full original chain. */
2432
+ * recorded `constraintDigest` — or a screening entry names a `tool.check` guard beside a policy the
2433
+ * constraint mint did not make (no chain to raise it on) — a partial/mismatched re-supply would silently run
2434
+ * the child under a thinner (or different) ancestor chain than it suspended with. Rejected pre-CAS (the
2435
+ * checkpoint stays `pending`); re-resume with the full original chain. */
2412
2436
  | "resume.parent_constraint_mismatch"
2413
2437
  /** #449 G1 (codex r2, pre-CAS entrance): a deployment usage-governance window for this resume's
2414
2438
  * ledger key (the config's principal, else the row's recorded one, else the shared bucket) is
@@ -305,7 +305,7 @@ export function summarizeCheckpoint(cp) {
305
305
  ...(hasBidi ? { hasBidiControls: true } : {}),
306
306
  };
307
307
  }
308
- export const CHECKPOINT_CONFIG_REFUSAL_CODES = Object.freeze(["config.spec_retired_key", "config.output_style_invalid", "config.permission_mode_invalid", "config.shell_gate_value_retired", "config.approval_reach_invalid", "config.user_invoked_skill_unknown", "config.skill_deny_unreadable", "config.user_attachment_invalid"]);
308
+ export const CHECKPOINT_CONFIG_REFUSAL_CODES = Object.freeze(["config.spec_retired_key", "config.output_style_invalid", "config.permission_mode_invalid", "config.shell_gate_value_retired", "config.approval_reach_invalid", "config.user_invoked_skill_unknown", "config.skill_deny_unreadable", "config.user_attachment_invalid", "config.tool_face_control"]);
309
309
  export const isCheckpointConfigRefusalCode = (word) => CHECKPOINT_CONFIG_REFUSAL_CODES.some((w) => w === word);
310
310
  export class CheckpointError extends Error {
311
311
  code;
@@ -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",
@@ -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
+ }
@@ -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"]);