@sema-agent/core 7.52.0 → 7.54.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 (357) hide show
  1. package/CHANGELOG.md +470 -0
  2. package/LICENSE +3 -1
  3. package/README.md +3 -1
  4. package/dist/agents/cross-session-envelope.d.ts +8 -0
  5. package/dist/agents/cross-session-envelope.js +6 -0
  6. package/dist/agents/cross-session-judge.d.ts +21 -1
  7. package/dist/agents/cross-session-judge.js +8 -0
  8. package/dist/agents/cross-session-ref.d.ts +5 -0
  9. package/dist/agents/cross-session-ref.js +1 -0
  10. package/dist/agents/org-delivery-gate.d.ts +122 -0
  11. package/dist/agents/org-delivery-gate.js +69 -0
  12. package/dist/agents/peer-held-queue.d.ts +9 -4
  13. package/dist/agents/peer-held-queue.js +6 -5
  14. package/dist/agents/peer-session-drain.d.ts +35 -6
  15. package/dist/agents/peer-session-drain.js +271 -182
  16. package/dist/agents/read-inbox-tool.d.ts +7 -0
  17. package/dist/agents/read-inbox-tool.js +5 -1
  18. package/dist/agents/send-message-tool.js +3 -4
  19. package/dist/agents/subagent.d.ts +6 -5
  20. package/dist/agents/subagent.js +117 -83
  21. package/dist/agents/tool-filter.d.ts +25 -4
  22. package/dist/agents/tool-filter.js +13 -3
  23. package/dist/brain/anthropic.d.ts +6 -1
  24. package/dist/brain/anthropic.js +4 -4
  25. package/dist/brain/model-presets.js +2 -1
  26. package/dist/brain/route-adjudicator.d.ts +6 -0
  27. package/dist/brain/routing.d.ts +24 -1
  28. package/dist/brain/routing.js +54 -19
  29. package/dist/brain/timeout.js +5 -4
  30. package/dist/core/a2a.d.ts +5 -2
  31. package/dist/core/a2a.js +33 -14
  32. package/dist/core/allow-entry.d.ts +3 -1
  33. package/dist/core/allow-entry.js +3 -2
  34. package/dist/core/approval-object.d.ts +87 -0
  35. package/dist/core/approval-object.js +85 -0
  36. package/dist/core/arg-summary.d.ts +3 -2
  37. package/dist/core/arg-summary.js +17 -11
  38. package/dist/core/ask-origin.d.ts +43 -27
  39. package/dist/core/ask-origin.js +20 -11
  40. package/dist/core/ask-question.d.ts +0 -1
  41. package/dist/core/ask-question.js +4 -67
  42. package/dist/core/ask-unresolvable-notice.d.ts +3 -2
  43. package/dist/core/auto-compaction.d.ts +106 -50
  44. package/dist/core/auto-compaction.js +69 -53
  45. package/dist/core/auto-mode-prompt.d.ts +4 -2
  46. package/dist/core/auto-mode-prompt.js +4 -3
  47. package/dist/core/canonical-json.d.ts +69 -0
  48. package/dist/core/canonical-json.js +130 -8
  49. package/dist/core/checkpoint-requirements.d.ts +13 -7
  50. package/dist/core/checkpoint-requirements.js +4 -1
  51. package/dist/core/checkpoint-store.d.ts +60 -36
  52. package/dist/core/checkpoint-store.js +7 -6
  53. package/dist/core/child-clamp-seats.d.ts +45 -6
  54. package/dist/core/child-clamp-seats.js +56 -4
  55. package/dist/core/compliance.js +3 -1
  56. package/dist/core/consolidate-scope.d.ts +1 -1
  57. package/dist/core/cross-boundary-taint.d.ts +213 -0
  58. package/dist/core/cross-boundary-taint.js +196 -0
  59. package/dist/core/decision-receipt.d.ts +44 -1
  60. package/dist/core/decision-receipt.js +16 -0
  61. package/dist/core/effective-path-target.d.ts +28 -6
  62. package/dist/core/effective-path-target.js +28 -2
  63. package/dist/core/engine-notice.d.ts +47 -4
  64. package/dist/core/engine-notice.js +17 -1
  65. package/dist/core/engine-storage-backend.d.ts +73 -0
  66. package/dist/core/engine-storage-backend.js +1 -0
  67. package/dist/core/file-history-store.d.ts +6 -2
  68. package/dist/core/file-history-store.js +1 -0
  69. package/dist/core/gate-fold.js +13 -4
  70. package/dist/core/gate-lanes.js +41 -34
  71. package/dist/core/gate-outcome.d.ts +18 -9
  72. package/dist/core/governance-codes.d.ts +9 -2
  73. package/dist/core/governance-codes.js +9 -0
  74. package/dist/core/hands-band-screen.d.ts +7 -0
  75. package/dist/core/hands-band-screen.js +32 -0
  76. package/dist/core/hooks.d.ts +21 -19
  77. package/dist/core/hooks.js +6 -5
  78. package/dist/core/locked-config.d.ts +110 -31
  79. package/dist/core/locked-config.js +155 -42
  80. package/dist/core/lsp.d.ts +1 -1
  81. package/dist/core/mcp-probe.js +1 -1
  82. package/dist/core/mcp-server-spec.d.ts +152 -17
  83. package/dist/core/mcp-server-spec.js +223 -40
  84. package/dist/core/mcp.d.ts +21 -14
  85. package/dist/core/mcp.js +59 -54
  86. package/dist/core/memory-engine/engine.d.ts +14 -19
  87. package/dist/core/memory-engine/engine.js +9 -6
  88. package/dist/core/memory-engine/export-bundle.d.ts +1 -1
  89. package/dist/core/memory-engine/export-bundle.js +1 -1
  90. package/dist/core/memory-engine/file-backend.d.ts +2 -6
  91. package/dist/core/memory-engine/file-backend.js +1 -12
  92. package/dist/core/memory.d.ts +3 -3
  93. package/dist/core/mode-policy.d.ts +16 -26
  94. package/dist/core/mode-policy.js +5 -18
  95. package/dist/core/mods/kernel/dispatch.js +13 -15
  96. package/dist/core/mods/kernel/events.d.ts +9 -6
  97. package/dist/core/mods/kernel/events.js +2 -2
  98. package/dist/core/mods/kernel/receive.d.ts +41 -11
  99. package/dist/core/mods/kernel/receive.js +124 -54
  100. package/dist/core/mods/kernel/site-rules.d.ts +80 -15
  101. package/dist/core/mods/kernel/site-rules.js +232 -40
  102. package/dist/core/mods/stations.d.ts +0 -6
  103. package/dist/core/mods/stations.js +0 -7
  104. package/dist/core/mounted-mcp.d.ts +57 -0
  105. package/dist/core/mounted-mcp.js +71 -2
  106. package/dist/core/own-property-receipt.d.ts +13 -0
  107. package/dist/core/own-property-receipt.js +3 -1
  108. package/dist/core/parent-spec-seat.d.ts +12 -15
  109. package/dist/core/parent-spec-seat.js +14 -6
  110. package/dist/core/pause-registry.d.ts +35 -1
  111. package/dist/core/pause-registry.js +10 -0
  112. package/dist/core/permission-rule-consent.d.ts +18 -5
  113. package/dist/core/permission-rule-consent.js +13 -8
  114. package/dist/core/permission-rule-model.d.ts +87 -15
  115. package/dist/core/permission-rule-model.js +87 -8
  116. package/dist/core/permission-rule-org.d.ts +200 -33
  117. package/dist/core/permission-rule-org.js +217 -91
  118. package/dist/core/permission-rule-session.js +2 -2
  119. package/dist/core/permission-rule-store.d.ts +8 -0
  120. package/dist/core/permission-rule-store.js +1 -0
  121. package/dist/core/permission-rule-sync.js +3 -2
  122. package/dist/core/permission-rules.d.ts +7 -1
  123. package/dist/core/permission-rules.js +37 -8
  124. package/dist/core/read-only-shell.d.ts +1 -1
  125. package/dist/core/read-only-shell.js +30 -9
  126. package/dist/core/remote-env.d.ts +41 -1
  127. package/dist/core/remote-env.js +18 -0
  128. package/dist/core/resume-startup-cause.d.ts +18 -0
  129. package/dist/core/resume-startup-cause.js +12 -0
  130. package/dist/core/retention.js +7 -2
  131. package/dist/core/retired-keys.d.ts +8 -2
  132. package/dist/core/retired-keys.js +12 -1
  133. package/dist/core/roles.js +60 -10
  134. package/dist/core/rule-lane-reads.js +1 -1
  135. package/dist/core/runner/approval-feedback.d.ts +46 -0
  136. package/dist/core/runner/approval-feedback.js +41 -0
  137. package/dist/core/runner/compaction-call-options.d.ts +3 -3
  138. package/dist/core/runner/compaction-call-options.js +2 -2
  139. package/dist/core/runner/contracts.d.ts +34 -41
  140. package/dist/core/runner/cross-boundary-lane.d.ts +87 -0
  141. package/dist/core/runner/cross-boundary-lane.js +190 -0
  142. package/dist/core/runner/decide-continuation.d.ts +4 -4
  143. package/dist/core/runner/decide-continuation.js +3 -1
  144. package/dist/core/runner/gate-exit.d.ts +32 -12
  145. package/dist/core/runner/gate-exit.js +77 -34
  146. package/dist/core/runner/inherited-ask-grants.js +2 -2
  147. package/dist/core/runner/mcp-redial.d.ts +52 -10
  148. package/dist/core/runner/mcp-redial.js +38 -9
  149. package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
  150. package/dist/core/runner/permission-rule-lanes.js +22 -10
  151. package/dist/core/runner/person-path-rows.d.ts +5 -3
  152. package/dist/core/runner/person-path-rows.js +2 -2
  153. package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -4
  154. package/dist/core/runner/prepare-acquire-reconcile.js +3 -3
  155. package/dist/core/runner/prepare-ask-lane.js +3 -3
  156. package/dist/core/runner/prepare-caps-and-workflow.d.ts +6 -5
  157. package/dist/core/runner/prepare-caps-and-workflow.js +3 -3
  158. package/dist/core/runner/prepare-config-doors.d.ts +58 -15
  159. package/dist/core/runner/prepare-config-doors.js +167 -146
  160. package/dist/core/runner/prepare-context-lane.js +6 -3
  161. package/dist/core/runner/prepare-defer-classify.js +4 -7
  162. package/dist/core/runner/prepare-delegation-surface.d.ts +5 -4
  163. package/dist/core/runner/prepare-delegation-surface.js +8 -7
  164. package/dist/core/runner/prepare-execution-env.d.ts +1 -2
  165. package/dist/core/runner/prepare-execution-env.js +2 -1
  166. package/dist/core/runner/prepare-gate-stations.d.ts +2 -0
  167. package/dist/core/runner/prepare-gate-stations.js +4 -3
  168. package/dist/core/runner/prepare-hands-readface.d.ts +3 -3
  169. package/dist/core/runner/prepare-hands-readface.js +3 -2
  170. package/dist/core/runner/prepare-inherited-gate.d.ts +2 -0
  171. package/dist/core/runner/prepare-inherited-gate.js +3 -2
  172. package/dist/core/runner/prepare-listings.d.ts +1 -1
  173. package/dist/core/runner/prepare-listings.js +4 -2
  174. package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
  175. package/dist/core/runner/prepare-memory-engine-session.js +19 -6
  176. package/dist/core/runner/prepare-memory.d.ts +3 -2
  177. package/dist/core/runner/prepare-memory.js +6 -2
  178. package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
  179. package/dist/core/runner/prepare-offload-wrappers.js +2 -1
  180. package/dist/core/runner/prepare-park-ask.d.ts +1 -1
  181. package/dist/core/runner/prepare-park-ask.js +9 -3
  182. package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
  183. package/dist/core/runner/prepare-policy-chain.js +14 -19
  184. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  185. package/dist/core/runner/prepare-project-context.js +6 -4
  186. package/dist/core/runner/prepare-prompt-assembly.d.ts +1 -1
  187. package/dist/core/runner/prepare-prompt-assembly.js +20 -16
  188. package/dist/core/runner/prepare-prompt-inputs.d.ts +12 -6
  189. package/dist/core/runner/prepare-prompt-inputs.js +6 -3
  190. package/dist/core/runner/prepare-protocol-tools.d.ts +7 -5
  191. package/dist/core/runner/prepare-protocol-tools.js +19 -12
  192. package/dist/core/runner/prepare-question-face.d.ts +4 -2
  193. package/dist/core/runner/prepare-question-face.js +4 -3
  194. package/dist/core/runner/prepare-safety-scan.d.ts +7 -2
  195. package/dist/core/runner/prepare-safety-scan.js +34 -27
  196. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -2
  197. package/dist/core/runner/prepare-suspend-saga.js +6 -2
  198. package/dist/core/runner/prepare-task.js +22 -19
  199. package/dist/core/runner/prepare-turn-wiring.d.ts +10 -5
  200. package/dist/core/runner/prepare-turn-wiring.js +14 -49
  201. package/dist/core/runner/prepare-wiring-manifest.d.ts +10 -5
  202. package/dist/core/runner/prepare-wiring-manifest.js +9 -6
  203. package/dist/core/runner/prepare-workspace-restore.js +2 -2
  204. package/dist/core/runner/resume-admission.d.ts +4 -1
  205. package/dist/core/runner/resume-admission.js +16 -14
  206. package/dist/core/runner/resume-apply.js +4 -4
  207. package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
  208. package/dist/core/runner/resume-internals-and-config.js +3 -8
  209. package/dist/core/runner/resume-policy-outcome.d.ts +2 -2
  210. package/dist/core/runner/resume-policy-outcome.js +18 -15
  211. package/dist/core/runner/resume-preflight.js +2 -2
  212. package/dist/core/runner/resume-review-outcome.js +3 -3
  213. package/dist/core/runner/retired-runner-deps.d.ts +5 -6
  214. package/dist/core/runner/retired-runner-deps.js +1 -4
  215. package/dist/core/runner/run-leg.js +97 -43
  216. package/dist/core/runner/run-recovery-lanes.js +5 -3
  217. package/dist/core/runner/run-settle-and-teardown.js +2 -0
  218. package/dist/core/runner/run-terminal-adoption.js +21 -9
  219. package/dist/core/runner/run-turn-boundary.js +9 -3
  220. package/dist/core/runner/runtask.js +1 -1
  221. package/dist/core/runner/session-file-state-replay.d.ts +5 -2
  222. package/dist/core/runner/session-file-state-replay.js +3 -2
  223. package/dist/core/runner/skills-seat.d.ts +15 -0
  224. package/dist/core/runner/skills-seat.js +57 -0
  225. package/dist/core/runner/stream-steer-verb.js +2 -2
  226. package/dist/core/runner/sub-agent-deny-lists.d.ts +13 -11
  227. package/dist/core/runner/sub-agent-deny-lists.js +7 -5
  228. package/dist/core/runner/synthetic-tools.d.ts +5 -2
  229. package/dist/core/runner/synthetic-tools.js +2 -12
  230. package/dist/core/runner/tool-face-overlay.d.ts +24 -6
  231. package/dist/core/runner/tool-face-overlay.js +24 -15
  232. package/dist/core/runner-deps.d.ts +37 -22
  233. package/dist/core/session-policy-store.d.ts +19 -0
  234. package/dist/core/session-policy-store.js +22 -2
  235. package/dist/core/session-store.d.ts +35 -16
  236. package/dist/core/session-store.js +20 -12
  237. package/dist/core/{shell-lexer.d.ts → shell-run-candidates.d.ts} +36 -12
  238. package/dist/core/{shell-lexer.js → shell-run-candidates.js} +145 -225
  239. package/dist/core/shell-wrapper-table.d.ts +5 -3
  240. package/dist/core/shell-wrapper-table.js +1 -1
  241. package/dist/core/store-contracts/checkpoint-store-contract.js +2 -2
  242. package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
  243. package/dist/core/store-contracts/session-store-contract.d.ts +49 -0
  244. package/dist/core/store-contracts/session-store-contract.js +639 -0
  245. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +12 -0
  246. package/dist/core/store-contracts/session-store-incarnation-contract.js +5 -2
  247. package/dist/core/task-event.d.ts +44 -6
  248. package/dist/core/task-notification.js +2 -2
  249. package/dist/core/task-registry-agent.js +1 -0
  250. package/dist/core/task-registry-shared.d.ts +5 -0
  251. package/dist/core/task-registry.d.ts +7 -0
  252. package/dist/core/task-registry.js +17 -0
  253. package/dist/core/task-result.d.ts +1 -1
  254. package/dist/core/task-spec.d.ts +7 -7
  255. package/dist/core/tighten-task-spec.d.ts +6 -4
  256. package/dist/core/tighten-task-spec.js +2 -2
  257. package/dist/core/tool-catalog-entries.d.ts +1 -1
  258. package/dist/core/tool-catalog-entries.js +52 -52
  259. package/dist/core/tool-face-reader.d.ts +49 -0
  260. package/dist/core/tool-face-reader.js +94 -0
  261. package/dist/core/tool-face.d.ts +17 -8
  262. package/dist/core/tool-face.js +1 -0
  263. package/dist/core/tool-policy.d.ts +67 -23
  264. package/dist/core/tool-policy.js +72 -60
  265. package/dist/core/tool-roster.d.ts +46 -28
  266. package/dist/core/tool-roster.js +91 -14
  267. package/dist/core/tool-spec-members.js +2 -2
  268. package/dist/core/tool-spec.d.ts +20 -4
  269. package/dist/core/tools.js +2 -0
  270. package/dist/core/trace.d.ts +24 -2
  271. package/dist/core/types.d.ts +3 -3
  272. package/dist/core/types.js +1 -1
  273. package/dist/core/untrusted-text.d.ts +23 -0
  274. package/dist/core/untrusted-text.js +10 -10
  275. package/dist/core/user-attachment.d.ts +56 -2
  276. package/dist/core/user-attachment.js +139 -56
  277. package/dist/core/wiring-manifest.d.ts +4 -2
  278. package/dist/engine/compaction/compaction.d.ts +2 -2
  279. package/dist/engine/compaction/utils.d.ts +2 -2
  280. package/dist/engine/harness/agent-harness.js +2 -1
  281. package/dist/engine/harness/types.d.ts +10 -4
  282. package/dist/engine/llm/types.d.ts +7 -2
  283. package/dist/engine/llm/types.js +2 -1
  284. package/dist/engine/loop/agent-loop.d.ts +12 -1
  285. package/dist/engine/loop/agent-loop.js +17 -5
  286. package/dist/engine/loop/types.d.ts +7 -1
  287. package/dist/engine/session/repo-utils.d.ts +5 -0
  288. package/dist/engine/session/repo-utils.js +9 -0
  289. package/dist/engine/session/storage-base.js +2 -2
  290. package/dist/index.d.ts +37 -17
  291. package/dist/index.js +31 -14
  292. package/dist/internal/harness.d.ts +1 -0
  293. package/dist/internal/harness.js +1 -0
  294. package/dist/internal/llm.d.ts +1 -1
  295. package/dist/internal/llm.js +1 -1
  296. package/dist/orchestration/goal.d.ts +24 -1
  297. package/dist/orchestration/goal.js +3 -2
  298. package/dist/orchestration/run-workflow-tool.d.ts +3 -0
  299. package/dist/orchestration/run-workflow-tool.js +1 -0
  300. package/dist/orchestration/workflow-governance.d.ts +1 -1
  301. package/dist/orchestration/workflow.d.ts +3 -0
  302. package/dist/orchestration/workflow.js +2 -1
  303. package/dist/prompt-assembly/artifact-store.d.ts +44 -9
  304. package/dist/prompt-assembly/artifact-store.js +38 -12
  305. package/dist/prompt-assembly/artifact.d.ts +12 -11
  306. package/dist/prompt-assembly/artifact.js +52 -21
  307. package/dist/prompt-assembly/assemble.d.ts +2 -0
  308. package/dist/prompt-assembly/assemble.js +2 -1
  309. package/dist/prompt-assembly/catalog/index.js +2 -1
  310. package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
  311. package/dist/prompt-assembly/catalog/memory.js +6 -0
  312. package/dist/prompt-assembly/catalog/schema.d.ts +19 -2
  313. package/dist/prompt-assembly/catalog/schema.js +3 -0
  314. package/dist/prompt-assembly/composer.d.ts +2 -0
  315. package/dist/prompt-assembly/composer.js +1 -1
  316. package/dist/prompt-assembly/overlay.d.ts +21 -11
  317. package/dist/prompt-assembly/overlay.js +57 -19
  318. package/dist/prompt-assembly/select.d.ts +21 -6
  319. package/dist/prompt-assembly/select.js +41 -4
  320. package/dist/prompts/default.d.ts +1 -12
  321. package/dist/prompts/default.js +0 -3
  322. package/dist/shell/lex.d.ts +87 -8
  323. package/dist/shell/lex.js +283 -49
  324. package/dist/stores/file/index.d.ts +8 -6
  325. package/dist/stores/file/permission-rule-store.d.ts +1 -1
  326. package/dist/stores/file/permission-rule-store.js +2 -1
  327. package/dist/tools/artifact/artifact-tool.js +14 -3
  328. package/dist/tools/fs/bash-program-position.d.ts +3 -15
  329. package/dist/tools/fs/bash-program-position.js +3 -10
  330. package/dist/tools/fs/bash-readonly-classifier.js +2 -0
  331. package/dist/tools/fs/fs-bash.d.ts +3 -3
  332. package/dist/tools/fs/fs-bash.js +72 -101
  333. package/dist/tools/fs/fs-read.d.ts +12 -0
  334. package/dist/tools/fs/fs-read.js +10 -9
  335. package/dist/tools/fs/fs-shared.d.ts +27 -31
  336. package/dist/tools/fs/fs-shared.js +12 -15
  337. package/dist/tools/fs/fs-write.js +1 -1
  338. package/dist/tools/fs/index.js +2 -2
  339. package/dist/tools/fs/read-deny-home.d.ts +1 -1
  340. package/dist/tools/fs/read-deny-home.js +5 -4
  341. package/dist/tools/fs/read-deny.d.ts +16 -3
  342. package/dist/tools/fs/read-deny.js +12 -9
  343. package/dist/tools/fs/safety.d.ts +7 -6
  344. package/dist/tools/fs/shell-read-bindings.d.ts +5 -3
  345. package/dist/tools/fs/shell-read-bindings.js +15 -16
  346. package/dist/tools/fs/shell-read-device.js +1 -1
  347. package/dist/tools/fs/shell-read-plan.js +36 -47
  348. package/dist/tools/fs/shell-read-word.d.ts +1 -6
  349. package/dist/tools/fs/shell-read-word.js +2 -20
  350. package/dist/tools/fs/shell-reentry-text.js +1 -1
  351. package/dist/tools/web.d.ts +2 -2
  352. package/package.json +4 -1
  353. package/test/export-surface.snapshot.json +5651 -5457
  354. package/wire-changes/core@7.53.0.json +1968 -0
  355. package/wire-changes/core@7.54.0.json +2870 -0
  356. package/dist/core/shell-scan.d.ts +0 -60
  357. package/dist/core/shell-scan.js +0 -183
@@ -3,6 +3,7 @@ import { teamRoleOf } from "../../agents/team-role.js";
3
3
  import { resolveCheckpointStore } from "../checkpoint-store.js";
4
4
  import { createHookEnvCapabilities, mintHookInvocationIdentity } from "../hooks.js";
5
5
  import { chainJudges } from "../mods/stations.js";
6
+ import { toolNamesOfServer } from "../mounted-mcp.js";
6
7
  import { isRemoteExecutionEnv, missingRestoreSurface } from "../remote-env.js";
7
8
  import { isVolatileOffloadStore } from "../tool-result-store.js";
8
9
  import { durableMandateSourceOf, isLiveApproverSeat } from "../tool-policy.js";
@@ -13,7 +14,7 @@ import { autoRunOnRecommendationEffective } from "./memory-consolidation-driver.
13
14
  import { GLOBAL_USAGE_KEY, usageRetryAfterMs, windowsGovernCost } from "../usage-window-store.js";
14
15
  import { LSP_CONTRACT_ID, askSeatEffective, countElicitOptIns, deriveHandsSeam, deriveLspSeam, deriveWiringManifest, resolveDeclaredDurability, resolveElicitSeam, resolveQuestionSeam, resolveSubagentTranscriptTier } from "../wiring-manifest.js";
15
16
  import { modePolicyOf } from "../mode-policy.js";
16
- export function mcpManifestEntries(entries, statuses) {
17
+ export function mcpManifestEntries(entries, statuses, rosterNames) {
17
18
  return (entries ?? []).map((entry) => {
18
19
  const status = statuses.find((s) => s.name === entry.name);
19
20
  const source = typeof entry.source === "string" && entry.source.length > 0 ? { source: inlineUntrusted(entry.source, 80) } : {};
@@ -21,7 +22,7 @@ export function mcpManifestEntries(entries, statuses) {
21
22
  if (status === undefined)
22
23
  return { name: entry.name, ...source, status: "skipped", toolCount: 0 };
23
24
  if (status.status === "connected")
24
- return { name: entry.name, ...source, status: "connected", toolCount: status.toolNames?.length ?? 0, ...liveness };
25
+ return { name: entry.name, ...source, status: "connected", toolCount: toolNamesOfServer(rosterNames, entry.name).length, ...liveness };
25
26
  return {
26
27
  name: entry.name,
27
28
  ...source,
@@ -116,13 +117,14 @@ function announceDurableGateUnavailable(args) {
116
117
  });
117
118
  }
118
119
  export function prepareWiringManifest(input) {
119
- const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, modBus, checkpointScope, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, legWriteGuard, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, sessionBox, harness, pausedRef, askSeat, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive, lspManagerWired, shellReadStationArmed, lspDiagnosticsLive, fileHistoryFact } = input;
120
+ const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, modBus, checkpointScope, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, legWriteGuard, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, sessionBox, harness, pausedRef, askSeat, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive, lspManagerWired, shellReadStationArmed, crossBoundaryStationEngaged, lspDiagnosticsLive, fileHistoryFact, memoryPollution } = input;
120
121
  const onAsk = askSeat.value;
121
122
  const handWriteTools = toolRoster.entries.filter((e) => e.mountedBy === "hands" && (e.effect === "write" || e.effect === "idempotent")).map((e) => e.name);
122
123
  const hasEffectAwareGate = policyLayers.length > 0 || chainJudges(modBus);
124
+ const rosterHolds = new Set(toolRoster.entries.map((e) => e.name));
123
125
  const peerWriteUngated = modePolicyOf(permissionMode.current).unstated === "ask"
124
126
  ? []
125
- : mcp.tools.filter((t) => t.permissionSeat === "passthrough" && !irreversibleTools.has(t.name) && !egressTools.has(t.name) && (toolEffects.get(t.name) ?? "write") !== "read").map((t) => t.name);
127
+ : mcp.tools.filter((t) => rosterHolds.has(t.name) && t.permissionSeat === "passthrough" && !irreversibleTools.has(t.name) && !egressTools.has(t.name) && (toolEffects.get(t.name) ?? "write") !== "read").map((t) => t.name);
126
128
  const firstPartyWriteUngated = (spec.tools ?? [])
127
129
  .map((t) => t.name)
128
130
  .filter((name) => !irreversibleTools.has(name) && !egressTools.has(name) && toolEffects.get(name) === "write");
@@ -213,7 +215,7 @@ export function prepareWiringManifest(input) {
213
215
  ...(modelGateManifest !== undefined ? { modelGate: modelGateManifest } : {}),
214
216
  autoMode: { ...autoModeArmReason() },
215
217
  permissionMode: permissionMode.receipt(),
216
- mcp: mcpManifestEntries(lockedPreflight.mcp, mcp.statuses),
218
+ mcp: mcpManifestEntries(lockedPreflight.mcp, mcp.statuses, toolRoster.entries.map((e) => e.name)),
217
219
  ...(writeProtection.mount !== undefined ? { writeProtectionTargetView: writeProtection.mount.targetView } : {}),
218
220
  readDenyBuiltinTiersActive,
219
221
  autoConsolidationOnRecommendation: autoRunOnRecommendationEffective(deps),
@@ -238,6 +240,7 @@ export function prepareWiringManifest(input) {
238
240
  settlement: frameSettlement,
239
241
  selfName: () => internals?.explicitAgentName,
240
242
  parked: () => pausedRef.current !== undefined,
243
+ markExternalContent: (reason) => memoryPollution?.()?.markPolluted(reason, "observed"),
241
244
  });
242
245
  frameSettlement.boxBacked = (payload) => peerLaneRefs.isBoxBacked?.(payload) ?? false;
243
246
  }
@@ -246,7 +249,7 @@ export function prepareWiringManifest(input) {
246
249
  modBus.hasHandlers("classic.PreToolUse") ||
247
250
  egressTools.size > 0 ||
248
251
  irreversibleTools.size > 0 ||
249
- shellReadStationArmed ||
252
+ shellReadStationArmed || crossBoundaryStationEngaged ||
250
253
  resourceSuspendEligible ||
251
254
  platformSuspendArmed ||
252
255
  spec.enablePlanMode === true;
@@ -1,4 +1,4 @@
1
- import { isRemoteExecutionEnv, missingRestoreSurface } from "../remote-env.js";
1
+ import { frozenHandleCopy, isRemoteExecutionEnv, missingRestoreSurface } from "../remote-env.js";
2
2
  import { remoteEnvFailureNote, restoreWorkspaceWithRetry } from "./remote-env-retry.js";
3
3
  import { rebaseWorkspacePathAcross } from "./workspace-path.js";
4
4
  export { remoteEnvFailureNote, restoreWorkspaceWithRetry } from "./remote-env-retry.js";
@@ -49,7 +49,7 @@ export async function prepareWorkspaceRestore(input) {
49
49
  refuseIdentityMismatch(ownedEnv.workspaceHandle());
50
50
  const { outcome: restored, attempts: restoreAttempts } = await restoreWorkspaceWithRetry(ownedEnv, handle.snapshotId, {
51
51
  abortSignal: restoreSignal,
52
- priorHandle: handle,
52
+ priorHandle: frozenHandleCopy(handle),
53
53
  });
54
54
  if (!restored.ok) {
55
55
  failResume(`resumeVM failed after ${restoreAttempts} attempt(s) (${restored.error.code}): ${restored.error.message}`, restored.error, remoteEnvFailureNote("resumeVM", restored.error, restoreAttempts));
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import { type Checkpoint, type CheckpointStore, type CheckpointToken, type PendingSteerEntry, type ResumeOutcome } from "../checkpoint-store.js";
14
14
  import type { InheritedGate, ResumeTaskConfig, RunInternals, RunnerDepsSeat } from "./contracts.js";
15
+ import type { SessionStore } from "../session.js";
15
16
  /** What the admission rung was called with. */
16
17
  export interface ResumeAdmissionInput<R> {
17
18
  /** borrowed-readonly — the checkpoint token the caller is redeeming. */
@@ -28,6 +29,8 @@ export interface ResumeAdmissionInput<R> {
28
29
  /** borrowed-readonly — the Runner's deployment deps, read LIVE through the Runner (the store resolution reads `checkpointStore`); the one home of why it is a
29
30
  * seat and not a captured object is {@link RunnerDepsSeat}. */
30
31
  runner: RunnerDepsSeat;
32
+ /** borrowed-readonly — the Runner's session store, fixed at its construction (unlike its deps): the retention capability door judges it. */
33
+ sessions: SessionStore;
31
34
  /** borrowed-readonly — the Runner's same-process parked-constraint registry; read for this token (never written here). */
32
35
  parentConstraintRegistry: ReadonlyMap<CheckpointToken, NonNullable<InheritedGate["parentConstraints"]>>;
33
36
  /** borrowed-readonly — the rung after admission, entered in this rung's last continuation with what it admitted. */
@@ -35,7 +38,7 @@ export interface ResumeAdmissionInput<R> {
35
38
  }
36
39
  /** What admission established — the constants every later rung reads. */
37
40
  export interface ResumeAdmissionResult {
38
- /** The caller's config, snapshotted once (own enumerable fields). */
41
+ /** The caller's config, snapshotted once (own enumerable fields), its MCP / A2A entries the frozen ones the doors judged. */
39
42
  config: ResumeTaskConfig;
40
43
  /** The trusted internals snapshot, with the parked parent chain re-supplied when this Runner spawned the leg. */
41
44
  internals: RunInternals | undefined;
@@ -1,16 +1,26 @@
1
1
  import { CheckpointError, readPendingSteerQueue, refuseRetiredModeSeed, resolveCheckpointStore, validatePendingSteer } from "../checkpoint-store.js";
2
- import { refuseResumeDoors } from "../mode-policy.js";
2
+ import { assertResumeConfigRecord, checkpointStoreSeat, refuseResumeDoors } from "./prepare-config-doors.js";
3
+ import { asResumeConfigRefusal } from "../mode-policy.js";
3
4
  import { describeSuppliedValue } from "./decide-continuation.js";
4
5
  import { detachSkillLists } from "../skill-grant.js";
6
+ import { isGateKind, PAUSE_REGISTRY } from "../pause-registry.js";
7
+ const DECIDE_ENTRY_BY_RESUME_GATE = {
8
+ policy_ask: "a `policy_ask` outcome (decision allow/deny bound to the pending tool call)",
9
+ dry_run_review: "a `dry_run_review` outcome (decision approve/reject)",
10
+ plan_review: "a `plan_review` outcome (decision approve/edit/reject)",
11
+ resource_limit: 'a `resource_limit` outcome (decision "continue")',
12
+ task_done: undefined,
13
+ };
5
14
  export async function resumeAdmission(input) {
6
- const { token, outcome, taskConfig, runner, parentConstraintRegistry } = input;
15
+ const { token, outcome, taskConfig, runner, sessions, parentConstraintRegistry } = input;
7
16
  let internals = input.internals;
8
17
  if (outcome === null || typeof outcome !== "object") {
9
18
  throw new CheckpointError("checkpoint.invalid_outcome", `resume outcome must be an object naming its gate (got ${outcome === null ? "null" : typeof outcome})`);
10
19
  }
11
- const config = typeof taskConfig === "object" && taskConfig !== null ? { ...taskConfig, ...(Array.isArray(taskConfig.skills) ? { skills: detachSkillLists(taskConfig.skills) } : {}) } : taskConfig;
20
+ asResumeConfigRefusal("taskConfig", () => assertResumeConfigRecord(taskConfig));
21
+ let config = { ...taskConfig, ...(Array.isArray(taskConfig.skills) ? { skills: detachSkillLists(taskConfig.skills) } : {}) };
12
22
  internals = internals !== undefined ? { ...internals } : undefined;
13
- const store = resolveCheckpointStore(config, runner.deps);
23
+ const store = asResumeConfigRefusal(checkpointStoreSeat(config), () => resolveCheckpointStore(config, runner.deps));
14
24
  if (!store) {
15
25
  throw new CheckpointError("checkpoint.not_found", "no CheckpointStore wired — cannot resume (set RunnerDeps.checkpointStore or taskConfig.checkpointStore)");
16
26
  }
@@ -39,20 +49,12 @@ export async function resumeAdmission(input) {
39
49
  const resumeSignal = config.signal;
40
50
  let suppliedMessage;
41
51
  refuseRetiredModeSeed(cp.state);
42
- refuseResumeDoors(config, cp.state.inheritedGate);
52
+ config = refuseResumeDoors(config, cp.state.inheritedGate, runner.deps, sessions);
43
53
  const parkedSteers = readPendingSteerQueue(cp.state);
44
54
  if (outcomeGate === "wake") {
45
55
  suppliedMessage = outcome.message;
46
56
  const gk = cp.gate.kind;
47
- const decideEntry = gk === "human" || gk === "irreversible_ask"
48
- ? 'a `policy_ask` outcome (decision allow/deny bound to the pending tool call)'
49
- : gk === "needs_review"
50
- ? 'a `dry_run_review` outcome (decision approve/reject)'
51
- : gk === "plan_review"
52
- ? 'a `plan_review` outcome (decision approve/edit/reject)'
53
- : gk === "resource_limit"
54
- ? 'a `resource_limit` outcome (decision "continue")'
55
- : undefined;
57
+ const decideEntry = isGateKind(gk) ? DECIDE_ENTRY_BY_RESUME_GATE[PAUSE_REGISTRY[gk].resume] : undefined;
56
58
  if (gk !== "task_done") {
57
59
  throw new CheckpointError("wake.gate_pending", `cannot wake: this checkpoint awaits a pending gate decision (gate "${gk}") — wake is not a decision ` +
58
60
  `channel; resume it with ${decideEntry ?? "its own gate outcome"} instead`);
@@ -13,7 +13,7 @@ import { orgVerdictBeforeClaim } from "./permission-rule-lanes.js";
13
13
  import { chainCannotJudge } from "./call-hook-stations.js";
14
14
  import { thrownText } from "../thrown-value.js";
15
15
  import { wireOf } from "../tool-name-readings.js";
16
- import { parkedSkillApprovalRefusal } from "../skill-grant.js";
16
+ import { judgeApprovalObject } from "../approval-object.js";
17
17
  import { SKILL_CONTENT_MAX_CHARS, SKILL_TOOL_NAME, normalizeSkills } from "./synthetic-tools.js";
18
18
  import { skillLoadReading } from "./skill-base-dir.js";
19
19
  export async function resumeApply(input) {
@@ -76,9 +76,9 @@ export async function resumeApply(input) {
76
76
  };
77
77
  if (plainPolicyOutcome?.decision === "allow" && cp.pendingAction.kind === "tool_approval") {
78
78
  const servedSkills = normalizeSkills(config.skills).filter((s) => skillLoadReading(s, SKILL_CONTENT_MAX_CHARS).loads);
79
- const skillRefusal = parkedSkillApprovalRefusal(cp.pendingAction, plainPolicyOutcome.updatedInput ?? cp.pendingAction.args, servedSkills, SKILL_TOOL_NAME);
80
- if (skillRefusal !== undefined)
81
- throw new CheckpointError("checkpoint.invalid_outcome", skillRefusal, { field: "boundGrantDigest" });
79
+ const claimed = judgeApprovalObject(cp.pendingAction, { args: plainPolicyOutcome.updatedInput ?? cp.pendingAction.args, skills: servedSkills, skillToolName: SKILL_TOOL_NAME }, "claim");
80
+ if (claimed !== "match")
81
+ throw new CheckpointError("checkpoint.invalid_outcome", claimed.message, { field: "boundGrantDigest" });
82
82
  }
83
83
  if (plainPolicyOutcome !== undefined &&
84
84
  plainPolicyOutcome.decision === "allow" &&
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The resume ladder's INTERNALS-AND-CONFIG rung (E7), verbatim from `Runner.resumeStream`:
3
- * the locked-policy guard on the resume-edit seat, the principal and placement identity-continuity rungs,
3
+ * the inherited constraints' retired-member door, the principal and placement identity-continuity rungs,
4
4
  * and the governance-window ENTRANCE check for a row that still owes a delivery.
5
5
  *
6
6
  * Synchronous by construction, with the ladder's ONE await at this rung handed back instead of taken: the
@@ -14,13 +14,13 @@ import type { ResumeTaskConfig, RunInternals, RunnerDepsSeat } from "./contracts
14
14
  export interface ResumeInternalsAndConfigInput {
15
15
  /** borrowed-readonly — the pending row (recorded principal, placement root, parked steers, background tasks). */
16
16
  cp: Checkpoint;
17
- /** borrowed-readonly — the config snapshot (`basePolicyForResumeEdit`, `principal`). */
17
+ /** borrowed-readonly — the config snapshot (`principal`). */
18
18
  config: ResumeTaskConfig;
19
19
  /** borrowed-readonly — the internals snapshot (`placementRoot`). */
20
20
  internals: RunInternals | undefined;
21
21
  /** borrowed-readonly — the ONE read of the outcome discriminant (a bare resource_limit continue owes nothing). */
22
22
  outcomeGate: ResumeOutcome["gate"];
23
- /** borrowed-readonly — the Runner's deployment deps, read LIVE through the Runner (reads `lockedConfig`, `usageWindowStore`, `usageWindows`); the one home of why it is a
23
+ /** borrowed-readonly — the Runner's deployment deps, read LIVE through the Runner (reads `usageWindowStore`, `usageWindows`); the one home of why it is a
24
24
  * seat and not a captured object is {@link RunnerDepsSeat}. */
25
25
  runner: RunnerDepsSeat;
26
26
  }
@@ -1,17 +1,12 @@
1
1
  import { CheckpointError, readPendingSteerQueue } from "../checkpoint-store.js";
2
+ import { asResumeConfigRefusal } from "../mode-policy.js";
2
3
  import { GLOBAL_USAGE_KEY, resolveUsageWindows, usageRetryAfterMs } from "../usage-window-store.js";
3
4
  import { placementValueOrAbsent } from "./checkpoint-scope.js";
4
- import { assertNoRetiredResumeSeats } from "./retired-runner-deps.js";
5
- import { resolveMicroCompactKnob } from "./prepare-config-doors.js";
5
+ import { assertNoRetiredInheritedConstraints } from "./retired-runner-deps.js";
6
6
  export function resumeInternalsAndConfig(input) {
7
7
  const { cp, config, internals, outcomeGate, runner } = input;
8
8
  let windowEntrance;
9
- assertNoRetiredResumeSeats(runner.deps, config, internals);
10
- resolveMicroCompactKnob(runner.deps.microCompact);
11
- if (runner.deps.lockedConfig?.keys?.includes("toolPolicy") === true && config.basePolicyForResumeEdit !== undefined) {
12
- throw new CheckpointError("checkpoint.invalid_outcome", "TaskSpec.basePolicyForResumeEdit is administratively locked by this deployment (locked key \"toolPolicy\") — a task-supplied " +
13
- "resume-edit policy is refused pre-CAS (the checkpoint stays pending); remove the field or change the deployment's lock configuration");
14
- }
9
+ asResumeConfigRefusal("deps", () => assertNoRetiredInheritedConstraints(internals));
15
10
  let recheckGovernanceWindow;
16
11
  {
17
12
  const rowPrincipal = cp.principal || undefined;
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * The resume ladder's APPROVAL-LANE capture and binding rung (E4), verbatim from
3
3
  * `Runner.resumeStream`: on a human / irreversible_ask row every deployment-supplied field of the
4
- * `policy_ask` decide is read exactly once into a plain twin (answer canonicalized, updatedInput cloned to the
5
- * JSON domain, the decision word, the refused keys, the host's decision facts and attribution, the deny note),
4
+ * `policy_ask` decide is read exactly once into a plain twin (answer and updatedInput by the one capture, in their
5
+ * JSON form, the decision word, the refused keys, the host's decision facts and attribution, the deny note),
6
6
  * then the decision-action binding (boundCallId, boundInputHash by version), the env_failed replay guard and
7
7
  * the content-ask answer binding. Synchronous; every refusal throws pre-CAS.
8
8
  */
@@ -1,7 +1,11 @@
1
- import { canonicalizeCapturedPlainData, classifyQuestionOutcome, isLiveQuestionFace } from "../ask-question.js";
1
+ import { classifyQuestionOutcome, isLiveQuestionFace } from "../ask-question.js";
2
+ import { capturedJsonOf } from "../canonical-json.js";
3
+ import { bindingRefusalOf } from "../tool-policy.js";
2
4
  import { CHECKPOINT_FEATURES, CheckpointError, checkpointVersionOf, winnerFromOutcome } from "../checkpoint-store.js";
3
- import { sanitizeUntrustedText } from "../untrusted-text.js";
5
+ import { isGateKind, resumeGateMatches } from "../pause-registry.js";
6
+ import { sanitizeUntrustedText, sentinelTagRefusal } from "../untrusted-text.js";
4
7
  import { assertOutcomeText, captureHostDecision, describeSuppliedValue, pendingContentAskCallId, refuseSuppliedKeys, sameWinner, SUPPLIED_RECORD_KEY } from "./decide-continuation.js";
8
+ import { refuseUnfitFeedback } from "./approval-feedback.js";
5
9
  const REFUSED_DECIDE_KEYS = [
6
10
  SUPPLIED_RECORD_KEY,
7
11
  ["settledBy", 'a retired key — the host supplies decision FACTS as hostDecision{decidedBy: "person" | "sla_timeout" | "policy", approver?} and core mints the settlement word from them'],
@@ -12,7 +16,8 @@ export function resumePolicyOutcome(input) {
12
16
  let suppliedAnswer;
13
17
  let redeemedAnswer;
14
18
  let plainPolicyOutcome;
15
- if (cp.gate.kind === "human" || cp.gate.kind === "irreversible_ask") {
19
+ const storedGateKind = cp.gate.kind;
20
+ if (isGateKind(storedGateKind) && resumeGateMatches(storedGateKind, "policy_ask")) {
16
21
  const decide = outcome;
17
22
  suppliedAnswer = decide.answer;
18
23
  if (suppliedAnswer !== undefined) {
@@ -25,17 +30,11 @@ export function resumePolicyOutcome(input) {
25
30
  }
26
31
  const updatedInputRaw = decide.updatedInput;
27
32
  let updatedInput;
28
- try {
29
- updatedInput = updatedInputRaw === undefined ? undefined : structuredClone(updatedInputRaw);
30
- }
31
- catch {
32
- throw new CheckpointError("checkpoint.invalid_outcome", "resume carried an `updatedInput` that could not be captured as plain data — refusing pre-CAS; the checkpoint stays pending");
33
- }
34
- if (Object.is(updatedInput, -0))
35
- updatedInput = 0;
36
- if (updatedInput !== undefined && !canonicalizeCapturedPlainData(updatedInput)) {
37
- throw new CheckpointError("checkpoint.invalid_outcome", "resume carried an `updatedInput` outside the plain-JSON value domain (a Map/Set/Date/buffer, a sparse or expando-carrying array, a non-finite number, or a cycle) — " +
38
- "such a value reads differently on the two sides of the durable store; refusing pre-CAS, the checkpoint stays pending");
33
+ if (updatedInputRaw !== undefined) {
34
+ const captured = capturedJsonOf(updatedInputRaw);
35
+ if (!captured.ok)
36
+ throw new CheckpointError("checkpoint.invalid_outcome", bindingRefusalOf(cp.pendingAction.kind === "tool_approval" ? cp.pendingAction.toolName : "the parked call", updatedInputRaw, captured.fault));
37
+ updatedInput = captured.value;
39
38
  }
40
39
  const decision = decide.decision;
41
40
  if (decision !== "allow" && decision !== "deny") {
@@ -45,6 +44,8 @@ export function resumePolicyOutcome(input) {
45
44
  const hostDecision = captureHostDecision(cp, decide.hostDecision, "policy_ask", { word: decision, allows: decision === "allow" });
46
45
  const reason = decide.reason;
47
46
  assertOutcomeText(reason, "reason");
47
+ const feedback = decide.feedback;
48
+ assertOutcomeText(feedback, "feedback");
48
49
  plainPolicyOutcome = {
49
50
  gate: "policy_ask",
50
51
  boundCallId: decide.boundCallId,
@@ -52,11 +53,13 @@ export function resumePolicyOutcome(input) {
52
53
  decision,
53
54
  ...(updatedInput !== undefined ? { updatedInput } : {}),
54
55
  ...(reason !== undefined ? { reason } : {}),
56
+ ...(feedback !== undefined ? { feedback } : {}),
55
57
  ...(redeemedAnswer !== undefined ? { answer: redeemedAnswer } : {}),
56
58
  hostDecision,
57
59
  };
60
+ refuseUnfitFeedback(plainPolicyOutcome);
58
61
  if (plainPolicyOutcome.decision === "deny" && plainPolicyOutcome.reason && sanitizeUntrustedText(plainPolicyOutcome.reason) !== plainPolicyOutcome.reason) {
59
- throw new CheckpointError("checkpoint.invalid_outcome", "resume deny/reject reason must not contain a </system-reminder> tag");
62
+ throw new CheckpointError("checkpoint.invalid_outcome", sentinelTagRefusal("resume deny/reject reason"));
60
63
  }
61
64
  }
62
65
  if (plainPolicyOutcome !== undefined) {
@@ -1,6 +1,6 @@
1
1
  import { CheckpointError } from "../checkpoint-store.js";
2
2
  import { MAX_TIMER_MS } from "../mods/kernel/index.js";
3
- import { hasDestroy } from "../remote-env.js";
3
+ import { frozenHandleCopy, hasDestroy } from "../remote-env.js";
4
4
  import { inlineUntrusted } from "../untrusted-text.js";
5
5
  import { describeSuppliedValue } from "./decide-continuation.js";
6
6
  import { settleTeardownLeg } from "./teardown-bounded.js";
@@ -63,7 +63,7 @@ export async function resumePreflight(input) {
63
63
  sessionId: cp.sessionId,
64
64
  ...(cp.state.placementRootSessionId !== undefined ? { placementRootSessionId: cp.state.placementRootSessionId } : {}),
65
65
  ...(cp.principal ? { principal: cp.principal } : {}),
66
- ...(cp.state.workspaceHandle !== undefined ? { workspaceHandle: structuredClone(cp.state.workspaceHandle) } : {}),
66
+ ...(cp.state.workspaceHandle !== undefined ? { workspaceHandle: frozenHandleCopy(cp.state.workspaceHandle) } : {}),
67
67
  gateKind: cp.gate.kind,
68
68
  };
69
69
  const refusalTail = "; the checkpoint stays pending and the same token is redeemable once the obstacle clears";
@@ -1,6 +1,6 @@
1
1
  import { CheckpointError } from "../checkpoint-store.js";
2
2
  import { isGateKind, PAUSE_REGISTRY, resumeGateMatches } from "../pause-registry.js";
3
- import { sanitizeUntrustedText } from "../untrusted-text.js";
3
+ import { sanitizeUntrustedText, sentinelTagRefusal } from "../untrusted-text.js";
4
4
  import { assertOutcomeText, captureHostDecision, describeSuppliedValue, refuseSuppliedKeys, SUPPLIED_RECORD_KEY } from "./decide-continuation.js";
5
5
  export function resumeReviewOutcome(input) {
6
6
  const { cp, outcome, outcomeGate, wakeMessage } = input;
@@ -49,13 +49,13 @@ export function resumeReviewOutcome(input) {
49
49
  if (plainReviewOutcome !== undefined) {
50
50
  const reason = plainReviewOutcome.reason;
51
51
  if (plainReviewOutcome.decision === "reject" && reason && sanitizeUntrustedText(reason) !== reason) {
52
- throw new CheckpointError("checkpoint.invalid_outcome", "resume deny/reject reason must not contain a </system-reminder> tag");
52
+ throw new CheckpointError("checkpoint.invalid_outcome", sentinelTagRefusal("resume deny/reject reason"));
53
53
  }
54
54
  const capturedPlan = plainReviewOutcome.gate === "plan_review" ? plainReviewOutcome.editedPlan : undefined;
55
55
  if (plainReviewOutcome.decision === "edit" &&
56
56
  capturedPlan &&
57
57
  sanitizeUntrustedText(capturedPlan) !== capturedPlan) {
58
- throw new CheckpointError("checkpoint.invalid_outcome", "resume editedPlan must not contain a </system-reminder> tag");
58
+ throw new CheckpointError("checkpoint.invalid_outcome", sentinelTagRefusal("resume editedPlan"));
59
59
  }
60
60
  if (cp.reopenReason === "env_failed") {
61
61
  const winner = cp.resolvedOutcome;
@@ -1,11 +1,10 @@
1
1
  import type { RunnerDeps } from "../types.js";
2
- import type { ResumeTaskConfig, RunInternals } from "./contracts.js";
2
+ import type { RunInternals } from "./contracts.js";
3
3
  /** Runs on the caller's own argument at `new Runner` (the only point that still sees an inherited seat — construction then
4
4
  * reads every own seat once into the plain copy the Runner keeps, `retainRunnerDeps`), and again in the pre-first-await
5
5
  * config-doors phase and pre-CAS on a resume. */
6
6
  export declare function assertNoRetiredRunnerDeps(deps: RunnerDeps): void;
7
- /** The resume ladder's pre-claim door: the retired seats of the deps, then the retired members of the caller policies this
8
- * resume installs (the prepare's own resolution, `callerPolicySeats`) and of the inherited constraints it is handed. The edit
9
- * re-check runs the resume-edit policy before the claim, and a refusal after the claim would burn the token on a store
10
- * without `reopen`. */
11
- export declare function assertNoRetiredResumeSeats(deps: RunnerDeps, config: ResumeTaskConfig, internals: RunInternals | undefined): void;
7
+ /** The resume ladder's pre-claim door over the inherited constraints a resume is handed: a retired member of one refuses before
8
+ * the claim (a refusal after it would burn the token on a store without `reopen`). The deps' retired seats and the caller
9
+ * policies' retired members are the config-door phase's, which a resume enters before the claim (`refuseResumeDoors`). */
10
+ export declare function assertNoRetiredInheritedConstraints(internals: RunInternals | undefined): void;
@@ -1,5 +1,4 @@
1
1
  import { assertNoRetiredKeys, assertNoRetiredToolPolicyKeys, RETIRED_HOOKS_REPLACEMENT } from "../retired-keys.js";
2
- import { assertCallerPoliciesCurrent, callerPolicySeats } from "../locked-config.js";
3
2
  const RETIRED_RUNNER_DEPS_KEYS = {
4
3
  hooks: RETIRED_HOOKS_REPLACEMENT,
5
4
  legacyRewindBoundaryProbe: "the rewind refusal always names both possibilities (never existed / retired whole-tree era); a deployment that holds that era's table answers the question on its own surface",
@@ -13,9 +12,7 @@ const RETIRED_RUNNER_DEPS_KEYS = {
13
12
  export function assertNoRetiredRunnerDeps(deps) {
14
13
  assertNoRetiredKeys(deps, RETIRED_RUNNER_DEPS_KEYS, "RunnerDeps");
15
14
  }
16
- export function assertNoRetiredResumeSeats(deps, config, internals) {
17
- assertNoRetiredRunnerDeps(deps);
18
- assertCallerPoliciesCurrent(callerPolicySeats(config, deps, deps.lockedConfig?.keys?.includes("toolPolicy") === true));
15
+ export function assertNoRetiredInheritedConstraints(internals) {
19
16
  for (const constraint of internals?.inheritedGate?.parentConstraints ?? [])
20
17
  assertNoRetiredToolPolicyKeys(constraint.policy);
21
18
  }