@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
@@ -8,10 +8,8 @@
8
8
  * (green→`spec.not_red`、error→`spec.oracle_error`,均 fail-loud);捕获 baseline 计数。
9
9
  * 2. frozen deny policy 经 {@link combinePolicies} 合入部署基线(deny 短路不可被顶);绝不裸赋顶掉
10
10
  * `taskSpec.toolPolicy`(TRAP #1)。
11
- * 3. Hooks 多路复用:runSpec 的 stop gate 先跑(guard-restore → oracle 判)——red ⇒ block 短路(失败
12
- * 尾部经 `delimitUntrusted` 围栏后置入:oracle 输出是模型可影响面);green ⇒ **链式调用**用户 stop
13
- * (不吞其否决权);error ⇒ block 一次并注明 oracle 基础设施故障,**连续 2 次 error 放弃把关**走终态
14
- * 判定(防 oracle 自坏死循环)。其它 hook 槽原样透传。
11
+ * 3. stop gate = 任务座位上的一条注册(在调用方注册之前):red ⇒ block(失败尾部经 `delimitUntrusted` 围栏);green ⇒
12
+ * `next(e)` 交下游;error ⇒ block 一次,**连续 2 次 error 放弃把关**走终态判定。
15
13
  * 4. 收口:终态亲跑 oracle = 最终判定;`emitTaskOutcome`(mechanical):`oracleHadRedRun` = 任一
16
14
  * 「真跑过且判 red」的观察(preflight ∨ stop-gate ∨ 终态;error 永不置位)。durable pause
17
15
  * (suspended/needs_review)非终态,不发射(同 goal.ts 先例:无半事实、resume 不重复计数)。
@@ -34,8 +32,8 @@ import { type OracleBaseline, type OracleGateResult, type OracleVerdict, type Sp
34
32
  export interface RunSpecOptions {
35
33
  /** Workcopy root — the containment root for frozenPaths, oracle cwd, and `spec.path` resolution. */
36
34
  rootDir: string;
37
- /** Per-run base spec (model/tools/toolPolicy/hooks/limits/…). `objective` is owned by runSpec (the
38
- * spec framing); `toolPolicy` and `hooks` are COMPOSED with runSpec's, never replaced. */
35
+ /** Per-run base spec (model/tools/toolPolicy/mods/limits/…). `objective` is owned by runSpec (the
36
+ * spec framing); `toolPolicy` and `mods` are COMPOSED with runSpec's, never replaced. */
39
37
  taskSpec: Omit<TaskSpec, "objective">;
40
38
  /** Receives the oracle gates' once-per-process `config.secret_env_scrubbed` notice (`runOracle`'s `onNotice`);
41
39
  * absent ⇒ the console line. */
@@ -9,6 +9,8 @@ import { writeTargetPath } from "../tools/fs/safety.js";
9
9
  import { callTargetViewsOf } from "../core/effective-path-target.js";
10
10
  import { captureBaseline, resolveFrozenPaths, restoreFrozenPaths, runOracle, snapshotFrozenPaths, specError, } from "../core/spec-contract.js";
11
11
  import { isProtectedWrite } from "../core/tool-registry.js";
12
+ const RUN_SPEC_ORACLE_GATE = "run-spec-oracle-gate";
13
+ const RUN_SPEC_ORACLE_GATE_BUDGET_MS = 600_000;
12
14
  const CASE_INSENSITIVE_FS = process.platform === "darwin" || process.platform === "win32";
13
15
  const pathKey = (p) => {
14
16
  let n = p.replace(/\\/g, "/");
@@ -100,81 +102,55 @@ export async function runSpec(runner, contract, opts) {
100
102
  const frozenPolicy = frozenDenyPolicy(rootDir, frozenResolved);
101
103
  const policies = [deployBaseline?.toolPolicy, opts.taskSpec.toolPolicy, frozenPolicy].filter((p) => p !== undefined);
102
104
  const toolPolicy = policies.length === 1 ? policies[0] : combinePolicies(...policies);
103
- const userHooks = opts.taskSpec.hooks && deployBaseline?.hooks
104
- ? {
105
- preToolUse: (opts.taskSpec.hooks.preToolUse ?? deployBaseline.hooks.preToolUse)?.bind(opts.taskSpec.hooks.preToolUse ? opts.taskSpec.hooks : deployBaseline.hooks),
106
- ...((opts.taskSpec.hooks.preToolUse ? opts.taskSpec.hooks : deployBaseline.hooks).preToolUseObservational === true
107
- ? { preToolUseObservational: true }
108
- : {}),
109
- postToolUse: (opts.taskSpec.hooks.postToolUse ?? deployBaseline.hooks.postToolUse)?.bind(opts.taskSpec.hooks.postToolUse ? opts.taskSpec.hooks : deployBaseline.hooks),
110
- userPromptSubmit: (opts.taskSpec.hooks.userPromptSubmit ?? deployBaseline.hooks.userPromptSubmit)?.bind(opts.taskSpec.hooks.userPromptSubmit ? opts.taskSpec.hooks : deployBaseline.hooks),
111
- stop: (opts.taskSpec.hooks.stop ?? deployBaseline.hooks.stop)?.bind(opts.taskSpec.hooks.stop ? opts.taskSpec.hooks : deployBaseline.hooks),
112
- postToolUseFailure: (opts.taskSpec.hooks.postToolUseFailure ?? deployBaseline.hooks.postToolUseFailure)?.bind(opts.taskSpec.hooks.postToolUseFailure ? opts.taskSpec.hooks : deployBaseline.hooks),
113
- postToolBatch: (opts.taskSpec.hooks.postToolBatch ?? deployBaseline.hooks.postToolBatch)?.bind(opts.taskSpec.hooks.postToolBatch ? opts.taskSpec.hooks : deployBaseline.hooks),
114
- preCompact: (opts.taskSpec.hooks.preCompact ?? deployBaseline.hooks.preCompact)?.bind(opts.taskSpec.hooks.preCompact ? opts.taskSpec.hooks : deployBaseline.hooks),
115
- postCompact: (opts.taskSpec.hooks.postCompact ?? deployBaseline.hooks.postCompact)?.bind(opts.taskSpec.hooks.postCompact ? opts.taskSpec.hooks : deployBaseline.hooks),
116
- stopFailure: (opts.taskSpec.hooks.stopFailure ?? deployBaseline.hooks.stopFailure)?.bind(opts.taskSpec.hooks.stopFailure ? opts.taskSpec.hooks : deployBaseline.hooks),
117
- permissionDenied: (opts.taskSpec.hooks.permissionDenied ?? deployBaseline.hooks.permissionDenied)?.bind(opts.taskSpec.hooks.permissionDenied ? opts.taskSpec.hooks : deployBaseline.hooks),
118
- ...((opts.taskSpec.hooks.timeoutMs ?? deployBaseline.hooks.timeoutMs) !== undefined
119
- ? { timeoutMs: opts.taskSpec.hooks.timeoutMs ?? deployBaseline.hooks.timeoutMs }
120
- : {}),
121
- }
122
- : (opts.taskSpec.hooks ?? deployBaseline?.hooks);
123
105
  let guardRestores = 0;
124
106
  let consecutiveOracleErrors = 0;
125
107
  let gateAbandoned = false;
126
- const hooks = {
127
- ...(userHooks?.preToolUse && { preToolUse: userHooks.preToolUse.bind(userHooks) }),
128
- ...(userHooks?.preToolUse && userHooks.preToolUseObservational === true ? { preToolUseObservational: true } : {}),
129
- ...(userHooks?.postToolUse && { postToolUse: userHooks.postToolUse.bind(userHooks) }),
130
- ...(userHooks?.userPromptSubmit && { userPromptSubmit: userHooks.userPromptSubmit.bind(userHooks) }),
131
- ...(userHooks?.postToolUseFailure && { postToolUseFailure: userHooks.postToolUseFailure.bind(userHooks) }),
132
- ...(userHooks?.postToolBatch && { postToolBatch: userHooks.postToolBatch.bind(userHooks) }),
133
- ...(userHooks?.preCompact && { preCompact: userHooks.preCompact.bind(userHooks) }),
134
- ...(userHooks?.postCompact && { postCompact: userHooks.postCompact.bind(userHooks) }),
135
- ...(userHooks?.stopFailure && { stopFailure: userHooks.stopFailure.bind(userHooks) }),
136
- ...(userHooks?.permissionDenied && { permissionDenied: userHooks.permissionDenied.bind(userHooks) }),
137
- ...(userHooks?.timeoutMs !== undefined ? { timeoutMs: userHooks.timeoutMs } : {}),
138
- async stop(ctx) {
139
- guardRestores += restoreFrozenPaths(snapshot, rootDir);
140
- if (!gateAbandoned) {
141
- const gateSignal = ctx.signal !== undefined && opts.taskSpec.signal !== undefined ? AbortSignal.any([ctx.signal, opts.taskSpec.signal]) : (ctx.signal ?? opts.taskSpec.signal);
142
- const report = await runOracle(contract.oracle, rootDir, { baseline, ...(gateSignal !== undefined ? { signal: gateSignal } : {}), ...noticeSeat });
143
- if (ctx.signal?.aborted === true)
144
- return undefined;
145
- oracleRuns++;
146
- if (report.verdict === "red") {
147
- oracleHadRedRun = true;
148
- oracleRedRuns++;
149
- stopGateBlocks++;
150
- consecutiveOracleErrors = 0;
151
- return { block: redFeedback(report.gates) };
152
- }
153
- if (report.verdict === "error") {
154
- consecutiveOracleErrors++;
155
- if (consecutiveOracleErrors < 2) {
156
- const broken = report.gates.filter((g) => g.verdict === "error");
108
+ const oracleGate = {
109
+ name: RUN_SPEC_ORACLE_GATE,
110
+ uses: { events: ["classic.Stop"], calls: [] },
111
+ budgetMs: RUN_SPEC_ORACLE_GATE_BUDGET_MS,
112
+ register(on) {
113
+ on("classic.Stop", async (_$, e, next) => {
114
+ guardRestores += restoreFrozenPaths(snapshot, rootDir);
115
+ if (!gateAbandoned) {
116
+ const gateSignal = opts.taskSpec.signal !== undefined ? AbortSignal.any([next.signal, opts.taskSpec.signal]) : next.signal;
117
+ const report = await runOracle(contract.oracle, rootDir, { baseline, signal: gateSignal, ...noticeSeat });
118
+ if (next.signal.aborted)
119
+ return {};
120
+ oracleRuns++;
121
+ if (report.verdict === "red") {
122
+ oracleHadRedRun = true;
123
+ oracleRedRuns++;
157
124
  stopGateBlocks++;
158
- return {
159
- block: `The verification oracle itself FAILED TO RUN (${broken.map((g) => `gate "${g.name}": ${g.reason}`).join("; ")}). ` +
160
- `This is an infrastructure error, not a test failure — you may have broken the build/test environment. ` +
161
- `Restore it so the oracle can run.`,
162
- };
125
+ consecutiveOracleErrors = 0;
126
+ return { block: redFeedback(report.gates) };
127
+ }
128
+ if (report.verdict === "error") {
129
+ consecutiveOracleErrors++;
130
+ if (consecutiveOracleErrors < 2) {
131
+ const broken = report.gates.filter((g) => g.verdict === "error");
132
+ stopGateBlocks++;
133
+ return {
134
+ block: `The verification oracle itself FAILED TO RUN (${broken.map((g) => `gate "${g.name}": ${g.reason}`).join("; ")}). ` +
135
+ `This is an infrastructure error, not a test failure — you may have broken the build/test environment. ` +
136
+ `Restore it so the oracle can run.`,
137
+ };
138
+ }
139
+ gateAbandoned = true;
140
+ }
141
+ else {
142
+ consecutiveOracleErrors = 0;
163
143
  }
164
- gateAbandoned = true;
165
- }
166
- else {
167
- consecutiveOracleErrors = 0;
168
144
  }
169
- }
170
- return userHooks?.stop ? userHooks.stop(ctx) : undefined;
145
+ return next(e);
146
+ });
171
147
  },
172
148
  };
173
149
  const result = await runner.runTask({
174
150
  ...opts.taskSpec,
175
151
  objective: buildObjective(specText, contract),
176
152
  toolPolicy,
177
- hooks,
153
+ mods: [oracleGate, ...(opts.taskSpec.mods ?? [])],
178
154
  });
179
155
  guardRestores += restoreFrozenPaths(snapshot, rootDir);
180
156
  const final = await runOracle(contract.oracle, rootDir, { baseline, ...noticeSeat });
@@ -539,9 +539,8 @@ async function mountRunWorkflowTool(d) {
539
539
  ...((ctx.inheritedGateForChildren ?? d.inheritedGateForChildren) !== undefined
540
540
  ? { inheritedGate: (ctx.inheritedGateForChildren ?? d.inheritedGateForChildren)() }
541
541
  : {}),
542
- ...((ctx.toolSelector?.layers ?? d.parentToolCeiling) !== undefined ? { toolCeiling: (ctx.toolSelector?.layers ?? d.parentToolCeiling) } : {}),
543
542
  ...(autoModeReview !== undefined ? { autoModeReview } : {}),
544
- }, { workflowDepth: d.workflowDepth });
543
+ }, { workflowDepth: d.workflowDepth, ...((ctx.toolSelector?.layers ?? d.parentToolCeiling) !== undefined ? { toolCeiling: (ctx.toolSelector?.layers ?? d.parentToolCeiling) } : {}) });
545
544
  }
546
545
  catch (err) {
547
546
  return structuredError(thrownText(err));
@@ -153,6 +153,11 @@ export declare class WorkflowJournalAppendTimeoutError extends Error {
153
153
  */
154
154
  export interface WorkflowInternals {
155
155
  workflowDepth?: number;
156
+ /** The tool selector layers of the prepared run that launched this workflow (`ToolExecuteContext.toolSelector.layers`), threaded into
157
+ * EVERY spawned agent as its ceiling (`RunInternals.toolCeiling`) on both spawn legs. The run that holds them judged them where it
158
+ * wrote them, so they are not asked again here; a ceiling a host writes itself is {@link RunWorkflowOptions.toolCeiling}, which is.
159
+ * Given both, both bound every agent (these layers first) and only the host-written one is judged. */
160
+ toolCeiling?: readonly import("../core/tool-face.js").ToolSelectorLayer[];
156
161
  }
157
162
  export interface WorkflowBudget {
158
163
  /** The token ceiling, or null when none was set (then `remaining()` is Infinity). */
@@ -565,9 +570,12 @@ export interface RunWorkflowOptions {
565
570
  * `run_workflow` tool wiring; a directly-started workflow may pass its own. Absent ⇒ children run
566
571
  * under only their own gates (pre-seam behavior). TRUSTED: never a script/model argument. */
567
572
  inheritedGate?: import("../core/runner/contracts.js").InheritedGate;
568
- /** The HOST task's tool selector layers (`ToolExecuteContext.toolSelector.layers`), threaded into EVERY spawned agent's trusted
569
- * internals as its ceiling (`RunInternals.toolCeiling`) on both spawn legs: nothing a workflow agent's spec names can widen what
570
- * the host may use. Set by the `run_workflow` tool wiring; absent ⇒ the agents are bounded only by their own lists. TRUSTED. */
573
+ /** A tool selector ceiling the HOST writes, threaded into EVERY spawned agent's trusted internals as its ceiling
574
+ * (`RunInternals.toolCeiling`) on both spawn legs: nothing a workflow agent's spec names can widen it. Nobody judged what the host
575
+ * wrote, so each agent's spec is asked of it before it launches: another spelling of a tool the agent carries (a caller tool, the
576
+ * catalog, a listable delegation pool) refuses that agent — `config.tool_face_control`, `detail.reason: "near_miss"`. The ceiling of the
577
+ * prepared run that launched the workflow rides {@link WorkflowInternals.toolCeiling} instead; given both, both bound every agent and only
578
+ * this one is judged. Absent ⇒ the agents are bounded only by their own lists. */
571
579
  toolCeiling?: readonly import("../core/tool-face.js").ToolSelectorLayer[];
572
580
  /** RB-201 FO-3 (workflow lane) — the session's auto-mode classifier, consulted BEFORE each script-spawned
573
581
  * child starts (objective + toolset + output schema, finalized). The delegation-tool lane reviews its
@@ -20,7 +20,7 @@ import { boundInputHashOf } from "../core/canonical-json.js";
20
20
  import { boundedRedactedSummary, egressThrownText } from "../core/untrusted-egress.js";
21
21
  import { delimitUntrusted } from "../core/untrusted-text.js";
22
22
  import { OUTPUT_TOOL_NAME } from "../core/runner/synthetic-tools.js";
23
- import { deniedToolNamesOf } from "../core/runner/sub-agent-deny-lists.js";
23
+ import { deniedToolNamesOf, judgeHostToolCeiling } from "../core/runner/sub-agent-deny-lists.js";
24
24
  import { compileOutputSchema } from "../core/runner/strict-output-schema.js";
25
25
  import { WorkflowBudgetExceededError, WorkflowNestingError, WorkflowAgentBlockedError, WorkflowAgentParkedError, WorkflowAgentSchemaError, WorkflowAgentStalledError, WorkflowMaxAgentsError, WORKFLOW_SPAWN_BLOCKED_ERROR_CODE } from "./workflow-types.js";
26
26
  import { WorkflowScriptError } from "./workflow-meta.js";
@@ -705,6 +705,13 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
705
705
  o.close();
706
706
  };
707
707
  const sem = createSemaphore(concurrency);
708
+ const launchingCeiling = internals?.toolCeiling ?? undefined;
709
+ const hostCeiling = opts.toolCeiling ?? undefined;
710
+ const agentCeiling = launchingCeiling === undefined ? hostCeiling : hostCeiling === undefined ? launchingCeiling : [...launchingCeiling, ...hostCeiling];
711
+ const judgeHostCeiling = (spec) => {
712
+ if (hostCeiling !== undefined)
713
+ judgeHostToolCeiling(hostCeiling, spec, launchingCeiling);
714
+ };
708
715
  const spawnAttribution = {
709
716
  isDelegatedChild: true,
710
717
  ...(opts.questionFaceStripped === true ? { questionFaceStripped: true } : {}),
@@ -715,7 +722,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
715
722
  ...(opts.parentCenterSourceRevision !== undefined ? { parentCenterSourceRevision: opts.parentCenterSourceRevision } : {}),
716
723
  ...(opts.onForwardEvent ? { onForwardEvent: opts.onForwardEvent } : {}),
717
724
  ...(opts.inheritedGate !== undefined ? { inheritedGate: opts.inheritedGate } : {}),
718
- ...(opts.toolCeiling !== undefined ? { toolCeiling: opts.toolCeiling } : {}),
725
+ ...(agentCeiling !== undefined ? { toolCeiling: agentCeiling } : {}),
719
726
  ...((opts.rootSessionId ?? opts.originatingSessionId) !== undefined ? { rootSessionId: opts.rootSessionId ?? opts.originatingSessionId } : {}),
720
727
  ...(opts.placementRoot !== undefined ? { placementRoot: opts.placementRoot } : {}),
721
728
  ...(opts.originatingSessionId !== undefined ? { parentSessionId: opts.originatingSessionId } : {}),
@@ -1645,6 +1652,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1645
1652
  const preReviewSpec = agentOpts.schema
1646
1653
  ? { ...seatedSpec, ...authInherit, ...parkInherit, signal: effectiveSignal, outputSchema: agentOpts.schema }
1647
1654
  : { ...seatedSpec, ...authInherit, ...parkInherit, signal: effectiveSignal };
1655
+ judgeHostCeiling(preReviewSpec);
1648
1656
  const runSpec = await reviewSpawnBeforeLaunch("ctx.agent", label, callKey, preReviewSpec, effectiveSignal);
1649
1657
  const enrichedForward = opts.onForwardEvent !== undefined
1650
1658
  ? (e) => {
@@ -2010,6 +2018,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
2010
2018
  ? { ...seatedSpec, ...authInherit, ...parkInherit, signal: effectiveSignal, outputSchema: agentOpts.schema }
2011
2019
  : { ...seatedSpec, ...authInherit, ...parkInherit, signal: effectiveSignal };
2012
2020
  const preReviewSpec = childSessionId !== undefined ? { ...baseRunSpec, sessionId: childSessionId } : baseRunSpec;
2021
+ judgeHostCeiling(preReviewSpec);
2013
2022
  const runSpec = await reviewSpawnBeforeLaunch("ctx.agentStream", label, callKey, preReviewSpec, effectiveSignal);
2014
2023
  const enrichedForwardS = opts.onForwardEvent !== undefined
2015
2024
  ? (e) => {
@@ -1,28 +1,22 @@
1
- import { type PromptEpochArtifact, type PublishedPromptArtifactEnvelope } from "./artifact.js";
1
+ import { type ArtifactVerifyCode, type PromptArtifact, type PublishedPromptArtifact } from "./artifact.js";
2
2
  export interface PromptArtifactStore {
3
- /** Verified read by digest — undefined on miss OR on any verification failure of stored bytes. */
4
- get(artifactDigest: string, opts: {
5
- engineVersion: string;
6
- }): Promise<PublishedPromptArtifactEnvelope | undefined>;
7
- /** Idempotent immutable write (same digest ⇒ same bytes; the caller verified before putting). */
8
- put(envelope: PublishedPromptArtifactEnvelope): Promise<void>;
3
+ /** Verified read by digest — undefined on a miss OR on any verification failure of the stored bytes. */
4
+ get(artifactDigest: string): Promise<PublishedPromptArtifact | undefined>;
5
+ /** Write by digest (the caller verified before putting). */
6
+ put(artifact: PublishedPromptArtifact): Promise<void>;
9
7
  }
10
8
  export declare class MemoryPromptArtifactStore implements PromptArtifactStore {
11
9
  private readonly byDigest;
12
- get(artifactDigest: string, opts: {
13
- engineVersion: string;
14
- }): Promise<PublishedPromptArtifactEnvelope | undefined>;
15
- put(envelope: PublishedPromptArtifactEnvelope): Promise<void>;
10
+ get(artifactDigest: string): Promise<PublishedPromptArtifact | undefined>;
11
+ put(artifact: PublishedPromptArtifact): Promise<void>;
16
12
  }
17
- /** `artifacts/<hex>.json` under a caller-owned directory; atomic tmp+rename writes (§9.2). */
13
+ /** `artifacts/<hex>.json` under a caller-owned directory; atomic tmp+rename writes. */
18
14
  export declare class FilePromptArtifactStore implements PromptArtifactStore {
19
15
  private readonly dir;
20
16
  constructor(dir: string);
21
17
  private fileFor;
22
- get(artifactDigest: string, opts: {
23
- engineVersion: string;
24
- }): Promise<PublishedPromptArtifactEnvelope | undefined>;
25
- put(envelope: PublishedPromptArtifactEnvelope): Promise<void>;
18
+ get(artifactDigest: string): Promise<PublishedPromptArtifact | undefined>;
19
+ put(artifact: PublishedPromptArtifact): Promise<void>;
26
20
  }
27
21
  export type PromptSourceState = {
28
22
  state: "active";
@@ -49,60 +43,47 @@ export declare class FilePromptSourceStateStore implements PromptSourceStateStor
49
43
  load(): Promise<PromptSourceState | undefined>;
50
44
  save(state: PromptSourceState): Promise<void>;
51
45
  }
52
- /** The narrow face the Runner consumes (RunnerDeps.promptSource) — resolution only, no publish. */
46
+ /** The narrow face the Runner consumes (`RunnerDeps.promptSource`) — resolution only, no publish. */
53
47
  export interface PromptArtifactSource {
54
- /** The current validated candidate for NEW sessions, with its publish provenance
55
- * (undefined = bundled-only, today's shape). */
56
- current(): {
57
- artifact: PromptEpochArtifact;
58
- sourceRevision: string;
59
- } | undefined;
60
- /** Resolve a PINNED digest (resume path). Undefined = unavailable — the caller fails loud. */
61
- get(artifactDigest: string): Promise<PromptEpochArtifact | undefined>;
62
- /** RB-31 — the tri-state the adoption boundary keys on: `"disabled"` = an EXPLICIT
63
- * validated revocation (applyDisabled) ⇒ pinned sessions roll back to bundled at the next
64
- * compaction; `"active"` = a validated candidate is live; `"unavailable"` = no verified state
65
- * (never-configured face, store-miss boot) ⇒ conservative restate — an outage must never strip
66
- * policy, only an explicit revocation does. Optional (older sources read as "unavailable"). */
67
- sourceState?(): "active" | "disabled" | "unavailable";
48
+ /** The current verified candidate new sessions (and every top-level session at a compaction) adopt; undefined = none. */
49
+ current(): PublishedPromptArtifact | undefined;
50
+ /** Resolve a PINNED digest (the resume path). Undefined = unavailable — the caller fails loud. */
51
+ get(artifactDigest: string): Promise<PromptArtifact | undefined>;
52
+ /** The tri-state every adoption decision keys on: `"active"` = a verified candidate is live; `"disabled"` = an
53
+ * EXPLICIT verified revocation (`applyDisabled`) — the one state that empties a pinned center layer;
54
+ * `"unavailable"` = no verified state (never configured, or a store miss at boot) — an outage never strips policy,
55
+ * only an explicit revocation does. */
56
+ sourceState(): "active" | "disabled" | "unavailable";
68
57
  }
69
58
  /**
70
- * The candidate state machine (§9.2 full pipeline). Publish-side entry points:
71
- * - `applySnapshot(raw)` — a fetched effective-snapshot body: verify → store.put → persist
72
- * active state → atomic in-memory swap. Any verification failure leaves EVERYTHING unchanged.
73
- * - `applyDisabled(sourceRevision)` — an explicit, successful disable/delete response: persist
74
- * disabled state + drop the candidate. (Network failure/304 = simply don't call anything.)
75
- * - `restore()` — boot: re-resolve persisted active state through the verified store; a miss or
76
- * verify failure boots stateless (no candidate) without touching the persisted record.
59
+ * The candidate state machine. Publish-side entry points:
60
+ * - `applySnapshot(raw)` — a fetched published artifact: verify → store.put → persist active state → atomic
61
+ * in-memory swap. Any verification failure leaves EVERYTHING unchanged.
62
+ * - `applyDisabled(sourceRevision)` — an explicit, successful disable/delete response: persist disabled state +
63
+ * drop the candidate. (Network failure/304 = simply don't call anything.)
64
+ * - `restore()` — boot: re-resolve the persisted active state through the verified store; a miss or verify failure
65
+ * boots stateless (no candidate) without touching the persisted record.
77
66
  */
78
67
  export declare class CenterPromptSource implements PromptArtifactSource {
79
68
  private readonly store;
80
69
  private readonly stateStore;
81
- private readonly engineVersion;
82
70
  private candidate;
83
71
  private state;
84
- /** Hardening 2026-07-31 — serialization tail for the three STATE-MUTATING entry points. Each of
85
- * them is a multi-await sequence ending in a synchronous swap of (candidate, state); with two in
86
- * flight, an interleaving where B's `stateStore.save` resolves and swaps before A's leaves the
87
- * persisted record naming B's digest while the in-memory candidate names A's — `current()` then
88
- * serves A to every new session until the next `restore()` silently switches to B. `CenterPromptSource`
89
- * is a public export driven by a caller's poll loop, so two overlapping applies are an ordinary
90
- * schedule, not an exotic race. Serializing costs nothing (these are publish-rate operations) and
91
- * makes the durable record and the in-memory candidate agree by construction. */
72
+ /** Serialization tail for the three STATE-MUTATING entry points. Each is a multi-await sequence ending in a
73
+ * synchronous swap of (candidate, state); with two in flight, an interleaving where B's `stateStore.save`
74
+ * resolves and swaps before A's would leave the persisted record naming B's digest while the in-memory candidate
75
+ * names A's. `CenterPromptSource` is driven by a caller's poll loop, so overlapping applies are an ordinary
76
+ * schedule. Serializing costs nothing (publish-rate operations) and makes the durable record and the in-memory
77
+ * candidate agree by construction. */
92
78
  private tail;
93
- /** Run `fn` after every previously-queued mutation settles (success OR failure — a failed apply
94
- * must not wedge the queue). */
79
+ /** Run `fn` after every previously-queued mutation settles (success OR failure — a failed apply must not wedge the queue). */
95
80
  private exclusive;
96
81
  constructor(opts: {
97
82
  store: PromptArtifactStore;
98
83
  stateStore?: PromptSourceStateStore;
99
- engineVersion: string;
100
84
  });
101
- current(): {
102
- artifact: PromptEpochArtifact;
103
- sourceRevision: string;
104
- } | undefined;
105
- get(artifactDigest: string): Promise<PromptEpochArtifact | undefined>;
85
+ current(): PublishedPromptArtifact | undefined;
86
+ get(artifactDigest: string): Promise<PromptArtifact | undefined>;
106
87
  restore(): Promise<void>;
107
88
  sourceState(): "active" | "disabled" | "unavailable";
108
89
  applySnapshot(raw: unknown): Promise<{
@@ -110,7 +91,7 @@ export declare class CenterPromptSource implements PromptArtifactSource {
110
91
  artifactDigest: string;
111
92
  } | {
112
93
  ok: false;
113
- code: string;
94
+ code: ArtifactVerifyCode;
114
95
  reason: string;
115
96
  }>;
116
97
  applyDisabled(sourceRevision: string): Promise<void>;
@@ -1,29 +1,25 @@
1
1
  import { mkdirSync, promises as fs } from "node:fs";
2
2
  import path from "node:path";
3
- import { verifyPromptArtifact, } from "./artifact.js";
4
- function normalizedEnvelope(parsed, artifact) {
5
- return { ...parsed, artifact };
3
+ import { verifyPromptArtifact } from "./artifact.js";
4
+ function verifiedRead(bytes, artifactDigest) {
5
+ let parsed;
6
+ try {
7
+ parsed = JSON.parse(bytes);
8
+ }
9
+ catch {
10
+ return undefined;
11
+ }
12
+ const v = verifyPromptArtifact(parsed);
13
+ return v.ok && v.artifact.artifactDigest === artifactDigest ? v.artifact : undefined;
6
14
  }
7
15
  export class MemoryPromptArtifactStore {
8
16
  byDigest = new Map();
9
- async get(artifactDigest, opts) {
17
+ async get(artifactDigest) {
10
18
  const bytes = this.byDigest.get(artifactDigest);
11
- if (bytes === undefined)
12
- return undefined;
13
- let parsed;
14
- try {
15
- parsed = JSON.parse(bytes);
16
- }
17
- catch {
18
- return undefined;
19
- }
20
- const v = verifyPromptArtifact(parsed, opts);
21
- if (!v.ok || v.artifact.artifactDigest !== artifactDigest)
22
- return undefined;
23
- return normalizedEnvelope(parsed, v.artifact);
19
+ return bytes === undefined ? undefined : verifiedRead(bytes, artifactDigest);
24
20
  }
25
- async put(envelope) {
26
- this.byDigest.set(envelope.artifact.artifactDigest, JSON.stringify(envelope));
21
+ async put(artifact) {
22
+ this.byDigest.set(artifact.artifactDigest, JSON.stringify(artifact));
27
23
  }
28
24
  }
29
25
  export class FilePromptArtifactStore {
@@ -36,7 +32,7 @@ export class FilePromptArtifactStore {
36
32
  const m = /^sha256:([0-9a-f]{64})$/.exec(artifactDigest);
37
33
  return m ? path.join(this.dir, "artifacts", `${m[1]}.json`) : undefined;
38
34
  }
39
- async get(artifactDigest, opts) {
35
+ async get(artifactDigest) {
40
36
  const file = this.fileFor(artifactDigest);
41
37
  if (file === undefined)
42
38
  return undefined;
@@ -47,24 +43,14 @@ export class FilePromptArtifactStore {
47
43
  catch {
48
44
  return undefined;
49
45
  }
50
- let parsed;
51
- try {
52
- parsed = JSON.parse(bytes);
53
- }
54
- catch {
55
- return undefined;
56
- }
57
- const v = verifyPromptArtifact(parsed, opts);
58
- if (!v.ok || v.artifact.artifactDigest !== artifactDigest)
59
- return undefined;
60
- return normalizedEnvelope(parsed, v.artifact);
46
+ return verifiedRead(bytes, artifactDigest);
61
47
  }
62
- async put(envelope) {
63
- const file = this.fileFor(envelope.artifact.artifactDigest);
48
+ async put(artifact) {
49
+ const file = this.fileFor(artifact.artifactDigest);
64
50
  if (file === undefined)
65
- throw new Error(`prompt-artifact store: malformed digest ${JSON.stringify(envelope.artifact.artifactDigest).slice(0, 120)}`);
51
+ throw new Error(`prompt-artifact store: malformed digest ${JSON.stringify(artifact.artifactDigest).slice(0, 120)}`);
66
52
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
67
- await fs.writeFile(tmp, JSON.stringify(envelope), "utf8");
53
+ await fs.writeFile(tmp, JSON.stringify(artifact), "utf8");
68
54
  await fs.rename(tmp, file);
69
55
  }
70
56
  }
@@ -113,7 +99,6 @@ export class FilePromptSourceStateStore {
113
99
  export class CenterPromptSource {
114
100
  store;
115
101
  stateStore;
116
- engineVersion;
117
102
  candidate;
118
103
  state = "unavailable";
119
104
  tail = Promise.resolve();
@@ -125,16 +110,14 @@ export class CenterPromptSource {
125
110
  constructor(opts) {
126
111
  this.store = opts.store;
127
112
  this.stateStore = opts.stateStore ?? new MemoryPromptSourceStateStore();
128
- this.engineVersion = opts.engineVersion;
129
113
  }
130
114
  current() {
131
115
  return this.candidate;
132
116
  }
133
117
  async get(artifactDigest) {
134
- if (this.candidate?.artifact.artifactDigest === artifactDigest)
135
- return this.candidate.artifact;
136
- const env = await this.store.get(artifactDigest, { engineVersion: this.engineVersion });
137
- return env?.artifact;
118
+ if (this.candidate?.artifactDigest === artifactDigest)
119
+ return this.candidate;
120
+ return this.store.get(artifactDigest);
138
121
  }
139
122
  async restore() {
140
123
  return this.exclusive(async () => {
@@ -149,23 +132,22 @@ export class CenterPromptSource {
149
132
  this.state = "unavailable";
150
133
  return;
151
134
  }
152
- const env = await this.store.get(state.artifactDigest, { engineVersion: this.engineVersion });
153
- this.candidate = env !== undefined ? { artifact: env.artifact, sourceRevision: state.sourceRevision } : undefined;
154
- this.state = env !== undefined ? "active" : "unavailable";
135
+ const stored = await this.store.get(state.artifactDigest);
136
+ this.candidate = stored !== undefined ? { ...stored, sourceRevision: state.sourceRevision } : undefined;
137
+ this.state = stored !== undefined ? "active" : "unavailable";
155
138
  });
156
139
  }
157
140
  sourceState() {
158
141
  return this.state;
159
142
  }
160
143
  async applySnapshot(raw) {
161
- const v = verifyPromptArtifact(raw, { engineVersion: this.engineVersion });
144
+ const v = verifyPromptArtifact(raw);
162
145
  if (!v.ok)
163
146
  return v;
164
- const envelope = raw;
165
147
  return this.exclusive(async () => {
166
- await this.store.put(envelope);
167
- await this.stateStore.save({ state: "active", artifactDigest: v.artifact.artifactDigest, sourceRevision: envelope.sourceRevision });
168
- this.candidate = { artifact: v.artifact, sourceRevision: envelope.sourceRevision };
148
+ await this.store.put(v.artifact);
149
+ await this.stateStore.save({ state: "active", artifactDigest: v.artifact.artifactDigest, sourceRevision: v.artifact.sourceRevision });
150
+ this.candidate = v.artifact;
169
151
  this.state = "active";
170
152
  return { ok: true, artifactDigest: v.artifact.artifactDigest };
171
153
  });