@sema-agent/core 7.55.0 → 7.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/CHANGELOG.md +513 -0
  2. package/dist/agents/cascade.js +1 -1
  3. package/dist/agents/cc-peer-directory.js +1 -0
  4. package/dist/agents/child-model-seat.d.ts +0 -11
  5. package/dist/agents/child-model-seat.js +0 -3
  6. package/dist/agents/list-agents-tool.d.ts +3 -1
  7. package/dist/agents/list-agents-tool.js +7 -7
  8. package/dist/agents/peer-directory.d.ts +22 -4
  9. package/dist/agents/peer-directory.js +24 -2
  10. package/dist/agents/peer-session-drain.js +2 -2
  11. package/dist/agents/repair-loop.js +2 -2
  12. package/dist/agents/send-message-tool.js +4 -4
  13. package/dist/agents/subagent.d.ts +6 -4
  14. package/dist/agents/subagent.js +64 -60
  15. package/dist/agents/tool-filter.d.ts +7 -5
  16. package/dist/agents/tool-filter.js +12 -9
  17. package/dist/agents/verify.d.ts +3 -2
  18. package/dist/agents/verify.js +3 -3
  19. package/dist/brain/anthropic.js +30 -73
  20. package/dist/brain/media-degrade.d.ts +18 -7
  21. package/dist/brain/media-degrade.js +13 -2
  22. package/dist/brain/model-capability.d.ts +37 -0
  23. package/dist/brain/model-capability.js +34 -0
  24. package/dist/brain/model-presets.d.ts +2 -8
  25. package/dist/brain/model-presets.js +1 -6
  26. package/dist/brain/open-responses.js +13 -26
  27. package/dist/brain/openai.js +14 -87
  28. package/dist/brain/reasoning-request.d.ts +96 -0
  29. package/dist/brain/reasoning-request.js +174 -0
  30. package/dist/brain/reasoning.d.ts +11 -11
  31. package/dist/brain/reasoning.js +4 -3
  32. package/dist/brain/request-params.d.ts +7 -4
  33. package/dist/brain/request-params.js +7 -4
  34. package/dist/brain/status-sink.d.ts +20 -0
  35. package/dist/brain/status-sink.js +7 -0
  36. package/dist/core/a2a.d.ts +2 -1
  37. package/dist/core/a2a.js +19 -13
  38. package/dist/core/agent-definition.d.ts +10 -0
  39. package/dist/core/allow-entry.d.ts +20 -13
  40. package/dist/core/allow-entry.js +26 -22
  41. package/dist/core/allow-rule-shadow.d.ts +3 -3
  42. package/dist/core/ask-origin.d.ts +64 -18
  43. package/dist/core/ask-origin.js +63 -23
  44. package/dist/core/ask-question.d.ts +51 -8
  45. package/dist/core/ask-question.js +3 -4
  46. package/dist/core/ask-unresolvable-notice.d.ts +8 -3
  47. package/dist/core/ask-unresolvable-notice.js +16 -2
  48. package/dist/core/checkpoint-generation.d.ts +53 -0
  49. package/dist/core/checkpoint-generation.js +35 -0
  50. package/dist/core/checkpoint-queries.d.ts +180 -0
  51. package/dist/core/checkpoint-queries.js +272 -0
  52. package/dist/core/checkpoint-requirements.d.ts +13 -1
  53. package/dist/core/checkpoint-requirements.js +4 -0
  54. package/dist/core/checkpoint-store.d.ts +88 -24
  55. package/dist/core/checkpoint-store.js +24 -9
  56. package/dist/core/cross-boundary-taint.d.ts +6 -5
  57. package/dist/core/cross-boundary-taint.js +1 -3
  58. package/dist/core/decision-receipt.d.ts +37 -3
  59. package/dist/core/decision-receipt.js +17 -17
  60. package/dist/core/delegation-not-started.d.ts +6 -0
  61. package/dist/core/delegation-not-started.js +17 -0
  62. package/dist/core/engine-attestation.d.ts +93 -0
  63. package/dist/core/engine-attestation.js +70 -0
  64. package/dist/core/engine-capabilities.d.ts +4 -1
  65. package/dist/core/engine-capabilities.js +1 -1
  66. package/dist/core/engine-notice.d.ts +30 -11
  67. package/dist/core/file-history-store.d.ts +90 -14
  68. package/dist/core/file-history-store.js +23 -15
  69. package/dist/core/gate-fold.d.ts +1 -1
  70. package/dist/core/gate-fold.js +22 -10
  71. package/dist/core/gate-lanes.js +73 -64
  72. package/dist/core/gate-outcome.d.ts +26 -5
  73. package/dist/core/gate-outcome.js +26 -0
  74. package/dist/core/governance-codes.d.ts +5 -1
  75. package/dist/core/governance-codes.js +6 -0
  76. package/dist/core/hooks.d.ts +17 -16
  77. package/dist/core/hooks.js +3 -1
  78. package/dist/core/host-floor.d.ts +128 -0
  79. package/dist/core/host-floor.js +206 -0
  80. package/dist/core/host-target.d.ts +38 -3
  81. package/dist/core/host-target.js +38 -5
  82. package/dist/core/mcp.d.ts +5 -1
  83. package/dist/core/mcp.js +67 -41
  84. package/dist/core/memory-engine/delegation-settlement.js +15 -24
  85. package/dist/core/memory-engine/engine.js +4 -4
  86. package/dist/core/memory-engine/layout.d.ts +60 -8
  87. package/dist/core/memory-engine/layout.js +65 -6
  88. package/dist/core/model-seat.d.ts +10 -3
  89. package/dist/core/mods/classic-events.d.ts +67 -0
  90. package/dist/core/mods/classic-events.js +1 -0
  91. package/dist/core/mods/dollar.d.ts +13 -0
  92. package/dist/core/mods/extension-call.d.ts +31 -0
  93. package/dist/core/mods/extension-call.js +43 -0
  94. package/dist/core/mods/kernel/dispatch.d.ts +20 -3
  95. package/dist/core/mods/kernel/dispatch.js +140 -69
  96. package/dist/core/mods/kernel/events.d.ts +47 -11
  97. package/dist/core/mods/kernel/events.js +66 -42
  98. package/dist/core/mods/kernel/index.d.ts +4 -4
  99. package/dist/core/mods/kernel/index.js +2 -2
  100. package/dist/core/mods/kernel/receive.d.ts +39 -5
  101. package/dist/core/mods/kernel/receive.js +290 -17
  102. package/dist/core/mods/kernel/registration.d.ts +33 -2
  103. package/dist/core/mods/kernel/registration.js +6 -7
  104. package/dist/core/mods/kernel/site-rules.d.ts +44 -16
  105. package/dist/core/mods/kernel/site-rules.js +24 -42
  106. package/dist/core/mods/spec-seats.d.ts +69 -0
  107. package/dist/core/mods/spec-seats.js +114 -0
  108. package/dist/core/mods/stations.d.ts +28 -8
  109. package/dist/core/mods/stations.js +29 -13
  110. package/dist/core/mods/tool-call.d.ts +79 -0
  111. package/dist/core/mods/tool-call.js +152 -0
  112. package/dist/core/namespaced-rule-name.d.ts +32 -38
  113. package/dist/core/namespaced-rule-name.js +29 -36
  114. package/dist/core/parent-spec-seat.d.ts +6 -1
  115. package/dist/core/parent-spec-seat.js +2 -0
  116. package/dist/core/park-selfcheck.js +1 -0
  117. package/dist/core/permission-rule-consent.d.ts +19 -0
  118. package/dist/core/permission-rule-consent.js +116 -26
  119. package/dist/core/permission-rule-model.d.ts +14 -3
  120. package/dist/core/permission-rule-model.js +39 -24
  121. package/dist/core/permission-rule-org.d.ts +6 -2
  122. package/dist/core/permission-rule-org.js +7 -3
  123. package/dist/core/permission-rule-provider.d.ts +5 -2
  124. package/dist/core/permission-rule-provider.js +41 -11
  125. package/dist/core/permission-rule-store.d.ts +3 -2
  126. package/dist/core/permission-rule-store.js +11 -2
  127. package/dist/core/permission-rule-sync.js +3 -2
  128. package/dist/core/permission-rule-syntax.d.ts +5 -4
  129. package/dist/core/permission-rule-syntax.js +2 -2
  130. package/dist/core/permission-rules.d.ts +4 -4
  131. package/dist/core/permission-rules.js +11 -20
  132. package/dist/core/persisted-rule-arms.d.ts +2 -2
  133. package/dist/core/persisted-rule-arms.js +10 -12
  134. package/dist/core/principal-name.d.ts +20 -0
  135. package/dist/core/principal-name.js +22 -0
  136. package/dist/core/prompt-section-seat.js +4 -6
  137. package/dist/core/protocol-http-auth.d.ts +26 -5
  138. package/dist/core/protocol-http-auth.js +137 -4
  139. package/dist/core/retired-keys.d.ts +16 -0
  140. package/dist/core/retired-keys.js +16 -4
  141. package/dist/core/rewrite-rejudge.d.ts +60 -0
  142. package/dist/core/rewrite-rejudge.js +36 -0
  143. package/dist/core/roles.d.ts +28 -1
  144. package/dist/core/roles.js +31 -19
  145. package/dist/core/rule-lane-reads.d.ts +20 -15
  146. package/dist/core/rule-lane-reads.js +45 -17
  147. package/dist/core/rule-owner.d.ts +3 -3
  148. package/dist/core/rule-owner.js +3 -2
  149. package/dist/core/runner/announce-once-ledger.d.ts +14 -0
  150. package/dist/core/runner/announce-once-ledger.js +5 -0
  151. package/dist/core/runner/assemble-result.d.ts +1 -0
  152. package/dist/core/runner/assemble-result.js +1 -1
  153. package/dist/core/runner/call-hook-stations.d.ts +3 -2
  154. package/dist/core/runner/caller-roster.d.ts +16 -4
  155. package/dist/core/runner/caller-roster.js +33 -6
  156. package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
  157. package/dist/core/runner/capability-withheld-seat.js +24 -0
  158. package/dist/core/runner/classifier-ladder.d.ts +7 -9
  159. package/dist/core/runner/classifier-ladder.js +3 -3
  160. package/dist/core/runner/construction-doors.js +3 -0
  161. package/dist/core/runner/contracts.d.ts +28 -25
  162. package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
  163. package/dist/core/runner/cross-boundary-lane.js +40 -27
  164. package/dist/core/runner/denial-limit-arms.d.ts +2 -2
  165. package/dist/core/runner/denial-limit-arms.js +1 -1
  166. package/dist/core/runner/file-history-request.d.ts +18 -0
  167. package/dist/core/runner/file-history-request.js +21 -13
  168. package/dist/core/runner/file-history-restore.d.ts +45 -0
  169. package/dist/core/runner/file-history-restore.js +46 -0
  170. package/dist/core/runner/gate-exit.d.ts +3 -3
  171. package/dist/core/runner/gate-exit.js +4 -3
  172. package/dist/core/runner/image.d.ts +7 -17
  173. package/dist/core/runner/image.js +9 -60
  174. package/dist/core/runner/permission-rule-lanes.d.ts +4 -4
  175. package/dist/core/runner/permission-rule-lanes.js +26 -10
  176. package/dist/core/runner/person-path-rows.d.ts +12 -9
  177. package/dist/core/runner/person-path-rows.js +18 -7
  178. package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
  179. package/dist/core/runner/prepare-ask-lane.js +5 -2
  180. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
  181. package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
  182. package/dist/core/runner/prepare-config-doors.d.ts +29 -38
  183. package/dist/core/runner/prepare-config-doors.js +42 -25
  184. package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
  185. package/dist/core/runner/prepare-defer-classify.js +7 -8
  186. package/dist/core/runner/prepare-file-history.d.ts +48 -8
  187. package/dist/core/runner/prepare-file-history.js +7 -39
  188. package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
  189. package/dist/core/runner/prepare-gate-stations.js +10 -1
  190. package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
  191. package/dist/core/runner/prepare-hands-readface.js +15 -14
  192. package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
  193. package/dist/core/runner/prepare-inherited-gate.js +5 -3
  194. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  195. package/dist/core/runner/prepare-park-ask.js +5 -5
  196. package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
  197. package/dist/core/runner/prepare-policy-chain.js +65 -72
  198. package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
  199. package/dist/core/runner/prepare-prompt-assembly.js +10 -8
  200. package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
  201. package/dist/core/runner/prepare-prompt-inputs.js +3 -5
  202. package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
  203. package/dist/core/runner/prepare-protocol-tools.js +3 -3
  204. package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
  205. package/dist/core/runner/prepare-safety-scan.js +0 -17
  206. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
  207. package/dist/core/runner/prepare-suspend-saga.js +5 -6
  208. package/dist/core/runner/prepare-task.d.ts +1 -1
  209. package/dist/core/runner/prepare-task.js +29 -20
  210. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
  211. package/dist/core/runner/prepare-tool-disclosure-mount.js +20 -16
  212. package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
  213. package/dist/core/runner/prepare-turn-wiring.js +2 -7
  214. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
  215. package/dist/core/runner/prepare-wiring-manifest.js +3 -3
  216. package/dist/core/runner/resume-admission.js +1 -1
  217. package/dist/core/runner/resume-apply.js +11 -12
  218. package/dist/core/runner/resume-checkpoint-screen.js +3 -0
  219. package/dist/core/runner/resume-claim.d.ts +4 -2
  220. package/dist/core/runner/resume-claim.js +15 -8
  221. package/dist/core/runner/retired-runner-deps.js +1 -0
  222. package/dist/core/runner/rewind-files.d.ts +15 -0
  223. package/dist/core/runner/rewind-files.js +132 -0
  224. package/dist/core/runner/run-attachment-seats.js +2 -1
  225. package/dist/core/runner/run-brain-sinks.d.ts +4 -1
  226. package/dist/core/runner/run-brain-sinks.js +4 -2
  227. package/dist/core/runner/run-harness-handlers.js +12 -4
  228. package/dist/core/runner/run-leg.d.ts +1 -1
  229. package/dist/core/runner/run-leg.js +30 -18
  230. package/dist/core/runner/run-settle-and-teardown.js +2 -1
  231. package/dist/core/runner/run-turn-boundary.js +1 -10
  232. package/dist/core/runner/runtask.d.ts +3 -0
  233. package/dist/core/runner/runtask.js +8 -9
  234. package/dist/core/runner/session-read-file-states.d.ts +15 -0
  235. package/dist/core/runner/session-read-file-states.js +28 -0
  236. package/dist/core/runner/session-rule-policy.js +4 -3
  237. package/dist/core/runner/shell-env-withheld.d.ts +33 -0
  238. package/dist/core/runner/shell-env-withheld.js +51 -0
  239. package/dist/core/runner/skills-seat.js +6 -2
  240. package/dist/core/runner/stream-settle-backstop.js +1 -1
  241. package/dist/core/runner/sub-agent-deny-lists.js +4 -7
  242. package/dist/core/runner/synthetic-tools.d.ts +6 -0
  243. package/dist/core/runner/synthetic-tools.js +4 -1
  244. package/dist/core/runner/tool-disclosure.d.ts +10 -12
  245. package/dist/core/runner/tool-disclosure.js +1 -3
  246. package/dist/core/runner/tool-end-body.d.ts +1 -1
  247. package/dist/core/runner/tool-end-body.js +10 -9
  248. package/dist/core/runner/tool-not-executed.d.ts +5 -0
  249. package/dist/core/runner/tool-not-executed.js +11 -0
  250. package/dist/core/runner/tool-occurrence.d.ts +8 -0
  251. package/dist/core/runner/tool-occurrence.js +7 -0
  252. package/dist/core/runner/turn-attachments.d.ts +33 -15
  253. package/dist/core/runner/turn-attachments.js +62 -37
  254. package/dist/core/runner-deps.d.ts +5 -5
  255. package/dist/core/safety-axis-vocab.d.ts +6 -4
  256. package/dist/core/safety-axis-vocab.js +6 -5
  257. package/dist/core/safety-merge-corpus.js +11 -3
  258. package/dist/core/secret-env.d.ts +26 -3
  259. package/dist/core/secret-env.js +44 -8
  260. package/dist/core/select-model.js +3 -3
  261. package/dist/core/session-policy-store.d.ts +27 -15
  262. package/dist/core/session-policy-store.js +156 -36
  263. package/dist/core/session-store.d.ts +29 -10
  264. package/dist/core/session-store.js +51 -19
  265. package/dist/core/session.d.ts +82 -16
  266. package/dist/core/session.js +53 -0
  267. package/dist/core/shell-read-silence.d.ts +11 -12
  268. package/dist/core/shell-read-silence.js +9 -5
  269. package/dist/core/shell-run-candidates.js +3 -1
  270. package/dist/core/shell-wrapper-projection.js +1 -1
  271. package/dist/core/shell-wrapper-table.d.ts +14 -7
  272. package/dist/core/shell-wrapper-table.js +5 -4
  273. package/dist/core/side-query.js +10 -1
  274. package/dist/core/skill-grant.d.ts +7 -2
  275. package/dist/core/skill-grant.js +5 -0
  276. package/dist/core/skills-directory.js +6 -2
  277. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
  278. package/dist/core/store-contracts/checkpoint-store-contract.js +140 -2
  279. package/dist/core/store-contracts/file-history-store-contract.js +31 -1
  280. package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
  281. package/dist/core/store-contracts/peer-directory-contract.js +14 -2
  282. package/dist/core/store-contracts/session-repo-contract.js +51 -0
  283. package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
  284. package/dist/core/store-contracts/session-store-contract.js +150 -14
  285. package/dist/core/stub-env.d.ts +2 -0
  286. package/dist/core/stub-env.js +1 -0
  287. package/dist/core/synthetic-read-verdict.js +3 -3
  288. package/dist/core/task-event.d.ts +32 -4
  289. package/dist/core/task-notification.d.ts +16 -12
  290. package/dist/core/task-registry.d.ts +9 -0
  291. package/dist/core/task-registry.js +11 -1
  292. package/dist/core/task-result.d.ts +18 -0
  293. package/dist/core/task-spec.d.ts +18 -13
  294. package/dist/core/tighten-task-spec.js +2 -1
  295. package/dist/core/tool-catalog-entries.d.ts +17 -0
  296. package/dist/core/tool-catalog-entries.js +13 -2
  297. package/dist/core/tool-check-reading.d.ts +11 -0
  298. package/dist/core/tool-check-reading.js +11 -6
  299. package/dist/core/tool-model-gate.d.ts +2 -2
  300. package/dist/core/tool-name-aliases.d.ts +16 -16
  301. package/dist/core/tool-name-aliases.js +13 -19
  302. package/dist/core/tool-name-readings.d.ts +5 -35
  303. package/dist/core/tool-name-readings.js +1 -9
  304. package/dist/core/tool-policy.d.ts +68 -198
  305. package/dist/core/tool-policy.js +149 -198
  306. package/dist/core/tool-result-store.js +3 -0
  307. package/dist/core/tool-roster.d.ts +14 -19
  308. package/dist/core/tool-roster.js +11 -44
  309. package/dist/core/tool-spec-members.js +7 -2
  310. package/dist/core/tool-spec.d.ts +19 -11
  311. package/dist/core/tools.js +49 -9
  312. package/dist/core/trace.d.ts +2 -2
  313. package/dist/core/types.d.ts +1 -1
  314. package/dist/core/user-attachment.d.ts +8 -1
  315. package/dist/core/user-attachment.js +64 -4
  316. package/dist/core/wiring-manifest.d.ts +9 -0
  317. package/dist/core/wiring-manifest.js +1 -0
  318. package/dist/core/workflow-journal-store.js +1 -1
  319. package/dist/engine/compaction/compaction.js +3 -2
  320. package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
  321. package/dist/engine/execution-env/node-execution-env.js +11 -2
  322. package/dist/engine/harness/agent-harness.d.ts +25 -1
  323. package/dist/engine/harness/agent-harness.js +54 -7
  324. package/dist/engine/harness/types.d.ts +29 -2
  325. package/dist/engine/llm/types.d.ts +28 -11
  326. package/dist/engine/loop/agent-loop.d.ts +22 -0
  327. package/dist/engine/loop/agent-loop.js +16 -26
  328. package/dist/engine/loop/types.d.ts +16 -6
  329. package/dist/engine/session/memory-repo.d.ts +9 -2
  330. package/dist/engine/session/memory-repo.js +11 -1
  331. package/dist/engine/session/repo-utils.d.ts +6 -5
  332. package/dist/engine/session/repo-utils.js +14 -6
  333. package/dist/index.d.ts +22 -10
  334. package/dist/index.js +15 -7
  335. package/dist/internal/harness-types.d.ts +1 -1
  336. package/dist/internal/llm.d.ts +1 -1
  337. package/dist/orchestration/run-workflow-tool.d.ts +6 -4
  338. package/dist/orchestration/run-workflow-tool.js +5 -3
  339. package/dist/orchestration/workflow.d.ts +3 -0
  340. package/dist/orchestration/workflow.js +36 -18
  341. package/dist/prompt-assembly/artifact.d.ts +2 -2
  342. package/dist/prompt-assembly/artifact.js +5 -3
  343. package/dist/prompt-assembly/assemble.d.ts +3 -2
  344. package/dist/prompt-assembly/assemble.js +1 -1
  345. package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
  346. package/dist/prompt-assembly/catalog/schema.js +34 -2
  347. package/dist/prompt-assembly/catalog/sections.js +0 -1
  348. package/dist/prompt-assembly/composer.d.ts +3 -1
  349. package/dist/prompt-assembly/composer.js +1 -1
  350. package/dist/prompt-assembly/event-registry.js +1 -0
  351. package/dist/prompt-assembly/overlay.js +3 -3
  352. package/dist/prompt-assembly/renderers.d.ts +1 -1
  353. package/dist/prompt-assembly/renderers.js +0 -3
  354. package/dist/prompt-assembly/role-base.d.ts +15 -0
  355. package/dist/prompt-assembly/role-base.js +9 -0
  356. package/dist/prompt-assembly/select.d.ts +39 -14
  357. package/dist/prompt-assembly/select.js +47 -16
  358. package/dist/prompt-assembly/sugar.d.ts +17 -11
  359. package/dist/prompt-assembly/sugar.js +8 -3
  360. package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
  361. package/dist/prompt-assembly/tool-catalog.js +114 -4
  362. package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
  363. package/dist/prompt-assembly/turn-snapshot.js +0 -3
  364. package/dist/prompt-assembly/types.d.ts +0 -7
  365. package/dist/scenarios/full-body.d.ts +11 -11
  366. package/dist/scenarios/full-body.js +4 -3
  367. package/dist/shell/lex.js +10 -1
  368. package/dist/stores/file/adoption/adopt.js +4 -3
  369. package/dist/stores/file/adoption/marker.js +3 -2
  370. package/dist/stores/file/checkpoint-store.d.ts +21 -0
  371. package/dist/stores/file/checkpoint-store.js +38 -6
  372. package/dist/stores/file/file-history-store.js +6 -7
  373. package/dist/stores/file/index.js +2 -1
  374. package/dist/stores/file/permission-rule-adopt.js +4 -3
  375. package/dist/stores/file/permission-rule-store.js +11 -5
  376. package/dist/stores/file/session-store.d.ts +29 -6
  377. package/dist/stores/file/session-store.js +42 -50
  378. package/dist/tools/artifact/artifact-tool.js +3 -2
  379. package/dist/tools/fs/bash-program-position.d.ts +19 -2
  380. package/dist/tools/fs/bash-program-position.js +56 -9
  381. package/dist/tools/fs/fs-bash.js +5 -5
  382. package/dist/tools/fs/fs-glob.d.ts +86 -0
  383. package/dist/tools/fs/fs-glob.js +226 -0
  384. package/dist/tools/fs/fs-read.js +14 -14
  385. package/dist/tools/fs/fs-search-tools.js +7 -7
  386. package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
  387. package/dist/tools/fs/pattern-kill-guard.js +397 -0
  388. package/dist/tools/fs/pdf.d.ts +9 -6
  389. package/dist/tools/fs/pdf.js +3 -3
  390. package/dist/tools/fs/program-read-model.d.ts +57 -7
  391. package/dist/tools/fs/program-read-model.js +11 -1
  392. package/dist/tools/fs/program-read-model.rows.js +78 -21
  393. package/dist/tools/fs/read-deny-home.js +3 -2
  394. package/dist/tools/fs/removal-targets.d.ts +17 -7
  395. package/dist/tools/fs/removal-targets.js +47 -20
  396. package/dist/tools/fs/search.d.ts +10 -0
  397. package/dist/tools/fs/search.js +20 -26
  398. package/dist/tools/fs/shell-read-argv.js +89 -12
  399. package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
  400. package/dist/tools/fs/shell-read-bindings.js +41 -0
  401. package/dist/tools/fs/shell-read-check.js +6 -19
  402. package/dist/tools/fs/shell-read-environment.d.ts +5 -1
  403. package/dist/tools/fs/shell-read-environment.js +3 -2
  404. package/dist/tools/fs/shell-read-establish.d.ts +15 -0
  405. package/dist/tools/fs/shell-read-establish.js +19 -20
  406. package/dist/tools/fs/shell-read-plan.js +24 -16
  407. package/dist/tools/fs/shell-read-start.d.ts +6 -1
  408. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
  409. package/dist/tools/fs/shell-read-write-targets.js +2 -3
  410. package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
  411. package/dist/tools/fs/shell-reentry-text.js +40 -2
  412. package/dist/tools/todo.js +63 -63
  413. package/dist/tools/web.d.ts +19 -14
  414. package/dist/tools/web.js +38 -55
  415. package/package.json +1 -1
  416. package/test/export-surface.snapshot.json +143 -5
  417. package/wire-changes/core@7.56.0.json +3891 -0
  418. package/wire-changes/mods-kernel@7.56.0.json +303 -0
@@ -33,6 +33,8 @@ export const REQUIREMENT_WORDS = Object.freeze([
33
33
  "own_tool_lists",
34
34
  "approval_targets",
35
35
  "cross_boundary",
36
+ "mount_site",
37
+ "skill_scopes",
36
38
  ]);
37
39
  export function isRequirementWord(word) {
38
40
  return typeof word === "string" && REQUIREMENT_WORDS.includes(word);
@@ -74,6 +76,7 @@ export const CHECKPOINT_STATE_REQUIREMENTS = {
74
76
  readFace: { word: "face" },
75
77
  writeFace: { word: "write_face" },
76
78
  skillGrants: { word: "skill_grants" },
79
+ skillScopes: { word: "skill_scopes" },
77
80
  reminderMark: DECISION_READ,
78
81
  repairBundle: DECISION_READ,
79
82
  workspaceHandle: DECISION_READ,
@@ -128,6 +131,7 @@ export const PENDING_ACTION_REQUIREMENTS = {
128
131
  pathTarget: DECISION_READ,
129
132
  hostTarget: DECISION_READ,
130
133
  names: { word: "call_names" },
134
+ engineMounted: { word: "mount_site" },
131
135
  targets: { word: "approval_targets" },
132
136
  hasBidiControls: SHOWN,
133
137
  batchToolCallIds: DECISION_READ,
@@ -1,6 +1,8 @@
1
1
  import type { GateOutcome, HostDecisionFacts } from "./gate-outcome.js";
2
2
  import { type ExecutionOutcomeRecordWord } from "./checkpoint-execution-record.js";
3
+ import { type HolderJudge } from "./checkpoint-generation.js";
3
4
  import { type CheckpointPause } from "./pause-registry.js";
5
+ import { type CheckpointDeleteGuard, type CheckpointOverdueCursor, type CheckpointOverdueQuery, type CheckpointPage, type CheckpointRowRead, type CheckpointSessionCursor, type CheckpointSessionQuery } from "./checkpoint-queries.js";
4
6
  import type { SystemInjectionPriority } from "./task-notification.js";
5
7
  import { type SteerReplayFacet } from "./steer-replay.js";
6
8
  import type { QuestionAnswer } from "./ask-question.js";
@@ -898,6 +900,10 @@ export type PendingAction = {
898
900
  * them, as the live gate judged the original, and the resume re-mints its face under the spelling while it still
899
901
  * resolves to the row's tool. Absent on a row minted before it ⇒ the row's `toolName` alone. */
900
902
  names?: readonly string[];
903
+ /** `true` iff one of the engine's own mount sites mounted the parked tool (the roster entry's fact `ToolCallFace.engineMounted`
904
+ * carries): what the identity members above cannot say (a host-mounted engine definition has the same ones). The pre-CAS
905
+ * recheck rebuilds the face from the row (`parkedCallFaceOf`); absent ⇒ judged as an ordinary tool. Word `mount_site`. */
906
+ engineMounted?: true;
901
907
  /** The approval object's TARGETS (`approvalTargetsOf`): per reading of the path slot, where it resolved when the card
902
908
  * was asked; absent ⇒ not judged. A role resolving elsewhere at the execution vetoes the call (`resume.target_moved`). */
903
909
  targets?: import("./approval-object.js").ApprovalTargets;
@@ -1031,6 +1037,9 @@ export interface CheckpointState {
1031
1037
  };
1032
1038
  /** The grant rows the run grew ({@link import("./skill-grant.js").frozenSkillGrants}); absent = none, damaged = refused pre-CAS. */
1033
1039
  skillGrants?: import("./skill-grant.js").SkillGrantRecord[];
1040
+ /** The skills active on the leg whose hooks were open (`SkillSpec.mods`; {@link import("./mods/spec-seats.js").SkillScopes}`.frozen`):
1041
+ * the resumed leg reopens them at its admission. Absent = none; damaged = refused pre-CAS. */
1042
+ skillScopes?: string[];
1034
1043
  /**
1035
1044
  * design/319 (A ticket) — the session's reminder provenance mark
1036
1045
  * ({@link import("./reminder-mint.js").mintReminderMark}), persisted so a durable resume keeps
@@ -1655,8 +1664,17 @@ export { REOPEN_REASONS, type ReopenReason } from "./resume-startup-cause.js";
1655
1664
  * (legacy callers / direct store tests) → no OCC.
1656
1665
  */
1657
1666
  export interface ResolveExpectation {
1658
- /** The monotonic {@link Checkpoint.rev} the caller observed at `get()` (absent rev ⇒ legacy `0`). */
1667
+ /** The monotonic {@link Checkpoint.rev} the caller observed at `get()`, read through {@link checkpointRevOf} (absent rev ⇒ legacy `0`). */
1659
1668
  rev: number;
1669
+ /**
1670
+ * The deployment's credential for the claim the resolving run acts under (`RunInternals.holder`, carried verbatim — the engine
1671
+ * never judges, stores or prints it). Every member of this object is a precondition the store evaluates in the SAME atomic step
1672
+ * as the flip: the CAS wins only if the grant `holder` names is still the deployment's current one at that instant (no claim
1673
+ * transfer may commit between the judgement and the flip). Judged only by a store that declares {@link CheckpointStore.fence}
1674
+ * `holder`; any other store LOSES a CAS that carries one (never ignores it — `checkpointHolderMatches`). A miss is an ordinary
1675
+ * loss: the row is untouched, so it reads `pending` at the generation the caller validated.
1676
+ */
1677
+ holder?: string;
1660
1678
  }
1661
1679
  /** design/384 slice 2 / S-25-R1 — the terminal intents a claim can carry. Deliberately the
1662
1680
  * TERMINAL pair only: `resolve` and `expire` are the two verbs that race one pending row to
@@ -1671,16 +1689,17 @@ export type TerminalClaimIntent = {
1671
1689
  };
1672
1690
  /** design/384 slice 2 / S-25-R1 — the single-round-trip answer: EITHER the claim won, OR it lost and
1673
1691
  * the SAME atomic operation reports what the row is now. `current` reuses the row's own vocabulary
1674
- * (status / rev / resolvedOutcome) — no new value domain. `status:"pending"` on a loss is the OCC
1675
- * arm only (`expect.rev` mismatch): the row is still open — re-get + re-validate, zero backoff (a
1676
- * cleanly KNOWN state is never "unknown"). */
1692
+ * (status / rev / resolvedOutcome) — no new value domain. `status:"pending"` on a loss is one of the
1693
+ * two expectation arms: a `rev` other than `expect.rev` is the OCC arm (the row is still open — re-get +
1694
+ * re-validate, zero backoff; a cleanly KNOWN state is never "unknown"); `expect.rev` itself means the
1695
+ * row did not move and the claim holder (`expect.holder`) was not current. */
1677
1696
  export type TerminalClaimOutcome = {
1678
1697
  claimed: true;
1679
1698
  } | {
1680
1699
  claimed: false;
1681
1700
  current: {
1682
1701
  status: "pending" | "resolved" | "expired";
1683
- /** `(cp.rev ?? 0)` — the absent-rev-reads-as-0 rule the OCC key already uses. */
1702
+ /** {@link checkpointRevOf} — the absent-rev-reads-as-0 rule the OCC key already uses. */
1684
1703
  rev: number;
1685
1704
  /** Row-field PASSTHROUGH on every present status: the row PRESERVES it across `reopen`
1686
1705
  * (resolved→pending rows carry it), `expire` never clears it, and a winnerless resolve
@@ -1817,7 +1836,7 @@ export interface CheckpointRow {
1817
1836
  * key ({@link ResolveExpectation}): a resume reads it at `get()` and `resolve` requires the live `rev` to
1818
1837
  * still equal it, so any resolve/reopen cycle landing in the get→resolve window loses the CAS (fail-closed).
1819
1838
  * Unlike the 2-valued `reopenReason`, it cannot ABA back to a prior value. Absent ⇒ legacy `0` (a checkpoint
1820
- * minted before this field; treated as never mutated).
1839
+ * minted before this field; treated as never mutated) — read it through {@link checkpointRevOf}.
1821
1840
  */
1822
1841
  rev?: number;
1823
1842
  /**
@@ -2146,14 +2165,16 @@ export declare function summarizeCheckpoint(cp: Checkpoint, disclose?: (sentence
2146
2165
  * steer seat, which no worker version reads and the host decides itself, or a retired mode-seed member of
2147
2166
  * `inheritedGate`, which an engine at 7.38.x or earlier still reads once).
2148
2167
  * · `invalid_outcome` pre-CAS row-integrity arms: `"real_approval_damaged"`, `"real_approval_forged"`,
2149
- * `"read_face_damaged"`, `"read_face_forged"`, `"write_face_damaged"`, `"skill_grants_damaged"`, `"constraint_chain_missing"`, `"hands_coordinates_damaged"`, `"requirements_damaged"` (all terminal for the row's
2168
+ * `"read_face_damaged"`, `"read_face_forged"`, `"write_face_damaged"`, `"skill_grants_damaged"`, `"skill_scopes_damaged"`, `"constraint_chain_missing"`, `"hands_coordinates_damaged"`, `"requirements_damaged"` (all terminal for the row's
2150
2169
  * current bytes — no worker version redeems a damaged row).
2151
2170
  */
2152
2171
  export type CheckpointErrorReason = "version_newer" | "env_factory_missing" | "governed_unwired" | "origin_missing" | "ledger_event_unknown" | "seat_retired" | "real_approval_damaged" | "real_approval_forged" | "read_face_damaged" | "read_face_forged"
2153
2172
  /** `state.writeFace` is present but not a well-formed section. No `_forged` twin: the section is
2154
2173
  * legal-and-absent at every version, so there is no version to judge a fabrication against — and a
2155
2174
  * fabricated "open" still needs the LIVE resolution to say open too. */
2156
- | "write_face_damaged" | "skill_grants_damaged" | "constraint_chain_missing"
2175
+ | "write_face_damaged" | "skill_grants_damaged"
2176
+ /** `state.skillScopes` is present but not a list of skill names (the active skills whose hooks the resumed leg reopens). */
2177
+ | "skill_scopes_damaged" | "constraint_chain_missing"
2157
2178
  /** `state.handsRoot` / `state.handsHome` / `state.handsCwd` is present but not an absolute path (the row's hands' coordinates). */
2158
2179
  | "hands_coordinates_damaged"
2159
2180
  /** The row's reader-requirement list ({@link CheckpointRow.requires}) is missing on a v10 row, is not a list of words,
@@ -2187,13 +2208,13 @@ export type CheckpointErrorReason = "version_newer" | "env_factory_missing" | "g
2187
2208
  * read, so `resume_at.invalid_mode` is a fresh run's word only), the containment faces, the add-only seats and the MCP / A2A `toolAxes` (`config.invalid_argument`), an MCP server's `toolFaces` (`config.tool_face_invalid`), the three memory seats, the cross-boundary posture, the advisor switch and the advisor model's shape,
2188
2209
  * the auto-consolidation arming (its role key too, and the role seats and tier bindings it reads: `config.unknown_role`, `detail.reason` naming the arm), the materialize strategy and persistence flag, the lock layer (`config.locked_registry`,
2189
2210
  * `config.locked_key`), an MCP server's content class, the skills-listing seats (`config.skill_listing_budget_invalid`), the limits and the
2190
- * resource-suspend knobs, the attachment modes, the governance windows, the brain-call guardrail and the retention declaration over the stores the leg
2211
+ * resource-suspend knobs, the attachment modes, the governance windows, the brain-call guardrail, the host floor (`config.host_floor_invalid`) and the retention declaration over the stores the leg
2191
2212
  * would run on (`config.retention_policy`, `config.retention_capability`), and the checkpoint store seat itself (`config.invalid_checkpoint_store`: the
2192
2213
  * retired `null` spelling, a store that declares no execution outcome), and the skills seat and the hands band (`config.invalid_argument`;
2193
2214
  * a skill's `baseDir` by its own reader, `config.skill_base_dir_invalid`). A door not entered here (the leg's model, its rebuilt
2194
2215
  * roster, its answer face, the approval seat's value) still refuses after the claim, each for a stated reason (INTEGRATION-CORE, "A resume's two doors").
2195
2216
  */
2196
- export declare const CHECKPOINT_CONFIG_REFUSAL_CODES: readonly ["config.spec_retired_key", "config.output_style_invalid", "config.permission_mode_invalid", "config.shell_gate_value_retired", "config.approval_reach_invalid", "config.user_invoked_skill_unknown", "config.skill_deny_unreadable", "config.user_attachment_invalid", "config.tool_face_control", "config.deps_retired_key", "config.peer_presence_invalid", "config.tool_model_gate_invalid", "config.microcompact_invalid", "config.prompt_selector_invalid", "resume_at.conflicts_resume", "resume_at.mode_without_target", "config.read_face_invalid", "config.write_face_invalid", "config.invalid_argument", "config.tool_face_invalid", "config.memory_delegation_evidence", "config.memory_provenance", "config.memory_capture_policy", "config.cross_boundary_posture", "config.advisor_tool_invalid", "config.advisor_model_invalid", "config.auto_consolidation", "config.unknown_role", "config.tool_materialize_invalid", "config.memory_persistence_invalid", "config.tool_materialize_unreachable", "config.locked_registry", "config.locked_key", "config.mcp_content_class", "config.skill_listing_budget_invalid", "config.limit_unknown_key", "config.limit_invalid", "config.attachment_invalid", "config.usage_window_invalid", "config.brain_call_guardrail_invalid", "config.retention_policy", "config.retention_capability", "config.invalid_checkpoint_store", "config.skill_base_dir_invalid"];
2217
+ export declare const CHECKPOINT_CONFIG_REFUSAL_CODES: readonly ["config.spec_retired_key", "config.output_style_invalid", "config.permission_mode_invalid", "config.shell_gate_value_retired", "config.approval_reach_invalid", "config.user_invoked_skill_unknown", "config.skill_deny_unreadable", "config.user_attachment_invalid", "config.tool_face_control", "config.deps_retired_key", "config.peer_presence_invalid", "config.tool_model_gate_invalid", "config.microcompact_invalid", "config.prompt_selector_invalid", "resume_at.conflicts_resume", "resume_at.mode_without_target", "config.read_face_invalid", "config.write_face_invalid", "config.invalid_argument", "config.tool_face_invalid", "config.memory_delegation_evidence", "config.memory_provenance", "config.memory_capture_policy", "config.cross_boundary_posture", "config.advisor_tool_invalid", "config.advisor_model_invalid", "config.auto_consolidation", "config.unknown_role", "config.tool_materialize_invalid", "config.memory_persistence_invalid", "config.tool_materialize_unreachable", "config.locked_registry", "config.locked_key", "config.mcp_content_class", "config.skill_listing_budget_invalid", "config.limit_unknown_key", "config.limit_invalid", "config.attachment_invalid", "config.usage_window_invalid", "config.brain_call_guardrail_invalid", "config.retention_policy", "config.retention_capability", "config.invalid_checkpoint_store", "config.skill_base_dir_invalid", "config.host_floor_invalid"];
2197
2218
  export type CheckpointConfigRefusalCode = (typeof CHECKPOINT_CONFIG_REFUSAL_CODES)[number];
2198
2219
  export declare const isCheckpointConfigRefusalCode: (word: unknown) => word is CheckpointConfigRefusalCode;
2199
2220
  /** The words of a {@link CheckpointError}'s optional `detail.field` (what each means: the `detail` member's doc). A CLOSED SET with one home, registered in
@@ -2352,9 +2373,15 @@ export declare class CheckpointError extends Error {
2352
2373
  * parity) before this throw — the token is NOT redeemable, by the deployment's own permanent
2353
2374
  * verdict (a dead binding must not be redialed forever). */
2354
2375
  | "resume.preflight_rejected"
2376
+ /** The resume carried a claim holder ({@link ResolveExpectation.holder}) and lost its CAS while the row is still the one it
2377
+ * validated — same scope, `pending`, the same generation — so the holder was not the deployment's current grant: nothing was
2378
+ * applied and the row is unchanged by this resume. The run is superseded; do not retry it (the current holder delivers).
2379
+ * Read off the CAS's own loss answer on `claimTerminal`; on the two-step route off its diagnostic read (a later instant —
2380
+ * under a race the row's later state answers instead, fail-closed either way). */
2381
+ | "resume.holder_superseded"
2355
2382
  /** F-012 L3: the resume carried an approver EDIT (`updatedInput`) and a FROZEN inherited ancestor
2356
2383
  * constraint (the persisted projection chain) — or the deployment's resume-edit policy — DENIES the
2357
- * edited args. Refused PRE-CAS with fresh-redecision semantics: the checkpoint stays `pending` and
2384
+ * edited args, or the policy accepts them only rewritten (`detail.editRewritten` names that form). Refused PRE-CAS with fresh-redecision semantics: the checkpoint stays `pending` and
2358
2385
  * the same token remains decidable (approve as shown, deny, or edit differently) — the rejection
2359
2386
  * consumed the decision's INPUT, never the ask itself. */
2360
2387
  | "resume.constraint_rejected"
@@ -2404,6 +2431,9 @@ export declare class CheckpointError extends Error {
2404
2431
  * {@link SteerReplayFacet}, in that set's order; always present on that code, never empty). Absent on
2405
2432
  * every other code. The live verb's refusal carries the same value. */
2406
2433
  differs?: readonly SteerReplayFacet[];
2434
+ /** On `resume.constraint_rejected` ⇔ the resume-edit policy accepts the person's edit only rewritten: `acceptableForm`
2435
+ * is that form, the outlet a host may offer; a decide carrying it as `updatedInput` runs exactly those bytes. */
2436
+ editRewritten?: import("./rewrite-rejudge.js").EditRewritten;
2407
2437
  } | undefined;
2408
2438
  constructor(code: "checkpoint.already_exists" | "checkpoint.already_resolved" | "checkpoint.not_found"
2409
2439
  /** `runner.resume` was handed an {@link ResumeOutcome} whose `gate` arm does not match the
@@ -2556,9 +2586,15 @@ export declare class CheckpointError extends Error {
2556
2586
  * parity) before this throw — the token is NOT redeemable, by the deployment's own permanent
2557
2587
  * verdict (a dead binding must not be redialed forever). */
2558
2588
  | "resume.preflight_rejected"
2589
+ /** The resume carried a claim holder ({@link ResolveExpectation.holder}) and lost its CAS while the row is still the one it
2590
+ * validated — same scope, `pending`, the same generation — so the holder was not the deployment's current grant: nothing was
2591
+ * applied and the row is unchanged by this resume. The run is superseded; do not retry it (the current holder delivers).
2592
+ * Read off the CAS's own loss answer on `claimTerminal`; on the two-step route off its diagnostic read (a later instant —
2593
+ * under a race the row's later state answers instead, fail-closed either way). */
2594
+ | "resume.holder_superseded"
2559
2595
  /** F-012 L3: the resume carried an approver EDIT (`updatedInput`) and a FROZEN inherited ancestor
2560
2596
  * constraint (the persisted projection chain) — or the deployment's resume-edit policy — DENIES the
2561
- * edited args. Refused PRE-CAS with fresh-redecision semantics: the checkpoint stays `pending` and
2597
+ * edited args, or the policy accepts them only rewritten (`detail.editRewritten` names that form). Refused PRE-CAS with fresh-redecision semantics: the checkpoint stays `pending` and
2562
2598
  * the same token remains decidable (approve as shown, deny, or edit differently) — the rejection
2563
2599
  * consumed the decision's INPUT, never the ask itself. */
2564
2600
  | "resume.constraint_rejected"
@@ -2608,6 +2644,9 @@ export declare class CheckpointError extends Error {
2608
2644
  * {@link SteerReplayFacet}, in that set's order; always present on that code, never empty). Absent on
2609
2645
  * every other code. The live verb's refusal carries the same value. */
2610
2646
  differs?: readonly SteerReplayFacet[];
2647
+ /** On `resume.constraint_rejected` ⇔ the resume-edit policy accepts the person's edit only rewritten: `acceptableForm`
2648
+ * is that form, the outlet a host may offer; a decide carrying it as `updatedInput` runs exactly those bytes. */
2649
+ editRewritten?: import("./rewrite-rejudge.js").EditRewritten;
2611
2650
  } | undefined);
2612
2651
  }
2613
2652
  /**
@@ -2759,6 +2798,15 @@ export interface CheckpointStore {
2759
2798
  readonly execution: {
2760
2799
  readonly outcome: true;
2761
2800
  };
2801
+ /**
2802
+ * The CLAIM-HOLDER declaration: this store judges {@link ResolveExpectation.holder} in the same atomic step as the resolve's flip.
2803
+ * Same "declaration, never duck-typing" posture as {@link execution}: ABSENT reads as "does not judge holders", and a run handed a
2804
+ * holder over such a store is refused at its store seat (`config.invalid_checkpoint_store`) — a holder the store would ignore would
2805
+ * fence nothing while the deployment believed it fenced.
2806
+ */
2807
+ readonly fence?: {
2808
+ readonly holder: true;
2809
+ };
2762
2810
  /** Create-once. Throws {@link CheckpointError} `already_exists` on a token collision (never a silent
2763
2811
  * overwrite — a reused token would clobber a live suspension). */
2764
2812
  put(token: CheckpointToken, cp: Checkpoint): Promise<void>;
@@ -2993,10 +3041,21 @@ export interface CheckpointStore {
2993
3041
  * enumeration face `listByScope` lacks. A host keeping its own scope registry (e.g. a sidecar file for a
2994
3042
  * cross-scope inbox) can rebuild it from the data itself when the registry is lost/corrupt, instead of the
2995
3043
  * enumeration silently going empty and pending approvals turning invisible. Scoped to PENDING deliberately:
2996
- * it matches `listByScope`'s visible surface, so `listScopes() × listByScope()` is exactly the full inbox.
3044
+ * it matches `listByScope`'s visible surface, so `listScopes() × listByScope()` is exactly the full inbox,
3045
+ * and a member the summary does not project is read with `get(token)` on the listed token — the composition
3046
+ * a deployment's approval queue is, rather than a query of its own over the store's rows.
2997
3047
  * **OPTIONAL** like {@link listByScope}; the in-memory and file first-party impls provide it.
2998
3048
  */
2999
3049
  listScopes?(): Promise<string[]>;
3050
+ /** The PENDING rows of every scope past their deadline, one facet per call ({@link CheckpointOverdueQuery}; read by
3051
+ * `readCheckpointOverdueQuery`, keyset-paged, bounded). OPTIONAL, probed by presence; both first-party stores provide it. */
3052
+ listOverdue?(query: CheckpointOverdueQuery): Promise<CheckpointPage<CheckpointSummary, CheckpointOverdueCursor>>;
3053
+ /** The rows of ONE session in any status ({@link CheckpointSessionQuery}; read by `readCheckpointSessionQuery`, keyset-paged,
3054
+ * bounded; a damaged row of the session answers `unreadable`, never skipped — a row with no string session id belongs to no session and is left out, disclosed; the file replay drops a row with a non-string token, scope or status, disclosed there). OPTIONAL, probed by presence; both first-party stores provide it. */
3055
+ listBySession?(query: CheckpointSessionQuery): Promise<CheckpointPage<CheckpointRowRead, CheckpointSessionCursor>>;
3056
+ /** Delete the checkpoint rows of one session that exist when the call starts, in any status, when the guard admits it
3057
+ * ({@link CheckpointDeleteGuard}); answers the count. Present exactly when the store can judge the guard (a session head read). */
3058
+ deleteSessionCheckpoints?(sessionId: string, guard: CheckpointDeleteGuard): Promise<number>;
3000
3059
  }
3001
3060
  /**
3002
3061
  * The SINGLE resolution of "which CheckpointStore does this run use" (ruled 2026-08-04; re-homed
@@ -3093,15 +3152,6 @@ export declare function appendPendingSteer(state: Pick<CheckpointState, "pending
3093
3152
  * that backend's own correctness core and must never be absorbed into a shared abstraction).
3094
3153
  */
3095
3154
  export declare function checkpointRowMatches(cp: Checkpoint | undefined, scope: string, status: Checkpoint["status"]): cp is Checkpoint;
3096
- /**
3097
- * REF-A4 — THE optimistic-concurrency half of `resolve`'s CAS predicate (design/80 D-1), shared by every
3098
- * backend. The caller validated its reopen-by-reason guard against a `get()` snapshot; if a concurrent
3099
- * resolve/reopen cycle moved the monotonic `rev` in the get→resolve window, that validation is stale ⇒
3100
- * lose the CAS (fail-closed), forcing a re-get + re-validate. Keyed on `rev`, NOT on `reopenReason` — a
3101
- * 2-valued enum can ABA back to a prior value while the winner changed (round-2 BLOCKER fix). An absent
3102
- * expectation opts out of the guard entirely.
3103
- */
3104
- export declare function checkpointOccMatches(cp: Checkpoint, expect?: ResolveExpectation): boolean;
3105
3155
  /** Fault-injection mode for {@link InMemoryCheckpointStore.testInjectFault} (council #5). One-shot. */
3106
3156
  export type CheckpointFaultMode =
3107
3157
  /** `resolve` commits the CAS (status → resolved) then throws — simulates a crash *after* the commit
@@ -3140,13 +3190,25 @@ export declare class InMemoryCheckpointStore implements CheckpointStore {
3140
3190
  readonly execution: {
3141
3191
  readonly outcome: true;
3142
3192
  };
3193
+ /** Declared exactly when the store was built with a `holderIsCurrent` judge ({@link CheckpointStore.fence}). */
3194
+ readonly fence?: {
3195
+ readonly holder: true;
3196
+ };
3143
3197
  private cps;
3144
3198
  private fault;
3145
3199
  private readonly disclose;
3146
- /** `disclose` is the listing projection's own seat ({@link summarizeCheckpoint}'s): this store has no path, so it
3147
- * forwards the projection's sentence for a row read past a damage, called synchronously by {@link listByScope}. */
3200
+ private readonly holderIsCurrent;
3201
+ readonly deleteSessionCheckpoints?: (sessionId: string, guard: CheckpointDeleteGuard) => Promise<number>;
3202
+ /** `disclose` is the listing projections' own seat ({@link summarizeCheckpoint}'s and the listing faces'): this store has no
3203
+ * path, so it forwards each sentence for a row read past a damage, called synchronously by the listing that read it.
3204
+ * `sessionHeadOf` (a session store's `headOf`) is what {@link CheckpointStore.deleteSessionCheckpoints} judges its guard by.
3205
+ * `holderIsCurrent` ({@link HolderJudge}) is what a resolve's `expect.holder` is judged by. */
3148
3206
  constructor(opts?: {
3149
3207
  disclose?: (sentence: string) => void;
3208
+ sessionHeadOf?: (sessionId: string) => Promise<{
3209
+ readonly owner: string | null;
3210
+ } | undefined>;
3211
+ holderIsCurrent?: HolderJudge;
3150
3212
  });
3151
3213
  put(token: CheckpointToken, cp: Checkpoint): Promise<void>;
3152
3214
  get(token: CheckpointToken): Promise<Checkpoint | null>;
@@ -3205,6 +3267,8 @@ export declare class InMemoryCheckpointStore implements CheckpointStore {
3205
3267
  reap(scope: string, cutoff: number): Promise<number>;
3206
3268
  listByScope(scope: string): Promise<CheckpointSummary[]>;
3207
3269
  listScopes(): Promise<string[]>;
3270
+ listOverdue(query: CheckpointOverdueQuery): Promise<CheckpointPage<CheckpointSummary, CheckpointOverdueCursor>>;
3271
+ listBySession(query: CheckpointSessionQuery): Promise<CheckpointPage<CheckpointRowRead, CheckpointSessionCursor>>;
3208
3272
  /** Arm a one-shot fault on the next `resolve` (council #5: makes crash-recovery unit-testable). */
3209
3273
  testInjectFault(mode: CheckpointFaultMode | null): void;
3210
3274
  /** Test/inspection helper: number of stored checkpoints. */
@@ -6,7 +6,9 @@ import { isAutoModeFallbackCause, readDenialLimitFallback } from "./auto-mode.js
6
6
  import { isAskOrigin, isPersistedRuleMandate } from "./ask-origin.js";
7
7
  import { readBoundBinding } from "./skill-grant-binding.js";
8
8
  import { checkpointExecutionRecorded, executionRecordDisposition, ExecutionOutcomeConflictError, } from "./checkpoint-execution-record.js";
9
+ import { checkpointHolderMatches, checkpointOccMatches, checkpointRevOf } from "./checkpoint-generation.js";
9
10
  import { parkedApprovalCardOf } from "./pause-registry.js";
11
+ import { checkpointDeadlinePassed, deleteSessionRowsAtStart, readCheckpointOverdueQuery, readCheckpointSessionQuery, selectOverduePage, selectSessionPage } from "./checkpoint-queries.js";
10
12
  import { renderUntrustedCommandText, stripFormatCharacters } from "./permission-rule-model.js";
11
13
  import { egressText } from "./untrusted-egress.js";
12
14
  import { steerReplayRefusal } from "./steer-replay.js";
@@ -333,7 +335,7 @@ export function summarizeCheckpoint(cp, disclose) {
333
335
  ...(hasBidi ? { hasBidiControls: true } : {}),
334
336
  };
335
337
  }
336
- export const CHECKPOINT_CONFIG_REFUSAL_CODES = Object.freeze(["config.spec_retired_key", "config.output_style_invalid", "config.permission_mode_invalid", "config.shell_gate_value_retired", "config.approval_reach_invalid", "config.user_invoked_skill_unknown", "config.skill_deny_unreadable", "config.user_attachment_invalid", "config.tool_face_control", "config.deps_retired_key", "config.peer_presence_invalid", "config.tool_model_gate_invalid", "config.microcompact_invalid", "config.prompt_selector_invalid", "resume_at.conflicts_resume", "resume_at.mode_without_target", "config.read_face_invalid", "config.write_face_invalid", "config.invalid_argument", "config.tool_face_invalid", "config.memory_delegation_evidence", "config.memory_provenance", "config.memory_capture_policy", "config.cross_boundary_posture", "config.advisor_tool_invalid", "config.advisor_model_invalid", "config.auto_consolidation", "config.unknown_role", "config.tool_materialize_invalid", "config.memory_persistence_invalid", "config.tool_materialize_unreachable", "config.locked_registry", "config.locked_key", "config.mcp_content_class", "config.skill_listing_budget_invalid", "config.limit_unknown_key", "config.limit_invalid", "config.attachment_invalid", "config.usage_window_invalid", "config.brain_call_guardrail_invalid", "config.retention_policy", "config.retention_capability", "config.invalid_checkpoint_store", "config.skill_base_dir_invalid"]);
338
+ export const CHECKPOINT_CONFIG_REFUSAL_CODES = Object.freeze(["config.spec_retired_key", "config.output_style_invalid", "config.permission_mode_invalid", "config.shell_gate_value_retired", "config.approval_reach_invalid", "config.user_invoked_skill_unknown", "config.skill_deny_unreadable", "config.user_attachment_invalid", "config.tool_face_control", "config.deps_retired_key", "config.peer_presence_invalid", "config.tool_model_gate_invalid", "config.microcompact_invalid", "config.prompt_selector_invalid", "resume_at.conflicts_resume", "resume_at.mode_without_target", "config.read_face_invalid", "config.write_face_invalid", "config.invalid_argument", "config.tool_face_invalid", "config.memory_delegation_evidence", "config.memory_provenance", "config.memory_capture_policy", "config.cross_boundary_posture", "config.advisor_tool_invalid", "config.advisor_model_invalid", "config.auto_consolidation", "config.unknown_role", "config.tool_materialize_invalid", "config.memory_persistence_invalid", "config.tool_materialize_unreachable", "config.locked_registry", "config.locked_key", "config.mcp_content_class", "config.skill_listing_budget_invalid", "config.limit_unknown_key", "config.limit_invalid", "config.attachment_invalid", "config.usage_window_invalid", "config.brain_call_guardrail_invalid", "config.retention_policy", "config.retention_capability", "config.invalid_checkpoint_store", "config.skill_base_dir_invalid", "config.host_floor_invalid"]);
337
339
  export const isCheckpointConfigRefusalCode = (word) => CHECKPOINT_CONFIG_REFUSAL_CODES.some((w) => w === word);
338
340
  export class CheckpointError extends Error {
339
341
  code;
@@ -542,9 +544,6 @@ export function appendPendingSteer(state, entry) {
542
544
  export function checkpointRowMatches(cp, scope, status) {
543
545
  return cp !== undefined && cp.scope === scope && cp.status === status;
544
546
  }
545
- export function checkpointOccMatches(cp, expect) {
546
- return expect === undefined || (cp.rev ?? 0) === expect.rev;
547
- }
548
547
  export class InMemoryCheckpointStore {
549
548
  retention = "none";
550
549
  durability = "process-local";
@@ -554,8 +553,16 @@ export class InMemoryCheckpointStore {
554
553
  cps = new Map();
555
554
  fault = null;
556
555
  disclose;
556
+ holderIsCurrent;
557
557
  constructor(opts = {}) {
558
558
  this.disclose = opts.disclose;
559
+ this.holderIsCurrent = opts.holderIsCurrent;
560
+ if (opts.holderIsCurrent !== undefined)
561
+ this.fence = Object.freeze({ holder: true });
562
+ const headOf = opts.sessionHeadOf;
563
+ if (headOf !== undefined) {
564
+ this.deleteSessionCheckpoints = (sessionId, guard) => deleteSessionRowsAtStart(this.cps, sessionId, guard, headOf, (token, row) => this.cps.get(token) === row && this.cps.delete(token));
565
+ }
559
566
  }
560
567
  async put(token, cp) {
561
568
  if (this.cps.has(token)) {
@@ -574,7 +581,7 @@ export class InMemoryCheckpointStore {
574
581
  claimed: false,
575
582
  current: {
576
583
  status: cp.status,
577
- rev: cp.rev ?? 0,
584
+ rev: checkpointRevOf(cp),
578
585
  ...(cp.resolvedOutcome !== undefined ? { resolvedOutcome: structuredClone(cp.resolvedOutcome) } : {}),
579
586
  },
580
587
  };
@@ -587,10 +594,13 @@ export class InMemoryCheckpointStore {
587
594
  if (!checkpointOccMatches(cp, expect)) {
588
595
  return this.claimLossFrom(cp, scope);
589
596
  }
597
+ if (!checkpointHolderMatches(expect, this.holderIsCurrent)) {
598
+ return this.claimLossFrom(cp, scope);
599
+ }
590
600
  const winner = winnerFromOutcome(outcome);
591
601
  const winnerClone = winner ? structuredClone(winner) : undefined;
592
602
  cp.status = "resolved";
593
- cp.rev = (cp.rev ?? 0) + 1;
603
+ cp.rev = checkpointRevOf(cp) + 1;
594
604
  if (winnerClone)
595
605
  cp.resolvedOutcome = winnerClone;
596
606
  cp.reopenReason = undefined;
@@ -651,7 +661,7 @@ export class InMemoryCheckpointStore {
651
661
  return false;
652
662
  }
653
663
  cp.status = "pending";
654
- cp.rev = (cp.rev ?? 0) + 1;
664
+ cp.rev = checkpointRevOf(cp) + 1;
655
665
  cp.reopenReason = reason;
656
666
  return true;
657
667
  }
@@ -673,8 +683,7 @@ export class InMemoryCheckpointStore {
673
683
  async reap(scope, cutoff) {
674
684
  let n = 0;
675
685
  for (const cp of this.cps.values()) {
676
- const deadlinePassed = cp.deadline !== undefined && (Number.isFinite(cp.deadline) ? cp.deadline <= cutoff : true);
677
- if (cp.scope === scope && cp.status === "pending" && deadlinePassed) {
686
+ if (cp.scope === scope && cp.status === "pending" && checkpointDeadlinePassed(cp.deadline, cutoff)) {
678
687
  cp.status = "expired";
679
688
  n++;
680
689
  }
@@ -696,6 +705,12 @@ export class InMemoryCheckpointStore {
696
705
  out.add(cp.scope);
697
706
  return [...out];
698
707
  }
708
+ async listOverdue(query) {
709
+ return selectOverduePage(this.cps.entries(), readCheckpointOverdueQuery(query), (cp) => summarizeCheckpoint(cp, this.disclose), this.disclose);
710
+ }
711
+ async listBySession(query) {
712
+ return selectSessionPage(this.cps.entries(), readCheckpointSessionQuery(query), (cp) => structuredClone(cp), this.disclose);
713
+ }
699
714
  testInjectFault(mode) {
700
715
  this.fault = mode;
701
716
  }
@@ -58,6 +58,9 @@ export interface BoundaryLegsGiven {
58
58
  readonly externalContentTarget?: boolean;
59
59
  };
60
60
  }
61
+ /** What a leg's session is still owed when the leg ends: the legs each unfinished background task its access (the TaskOutput reach) delivers
62
+ * along, read as the poll the session's next leg — another tree — would make of it (`TaskRegistry.owedDeliveries`). */
63
+ export type OwedDeliveries = () => readonly BoundaryLegsGiven[];
61
64
  declare const CROSS_BOUNDARY_TREE_TOKEN: unique symbol;
62
65
  /** A run tree's cross-boundary IDENTITY — opaque and frozen, minted by the engine alone: a tool is handed it so a delegation or
63
66
  * workflow lane can join its children to the same tree and a registry handle can name the tree that spawned it, compared by
@@ -186,17 +189,15 @@ export declare function crossBoundaryPostureUndeclaredNotice(at: {
186
189
  /** Where a session record's write was owed: a leg's prepare, an exit before its call runs, a suspend before its row, a settle. */
187
190
  export type CrossBoundaryRecordPhase = "prepare" | "exit" | "suspend" | "settle";
188
191
  /** The one mint of `config.cross_boundary_record_unwritten`: a session record that could not be written and refused nothing — on a tree
189
- * that is not governed (no judgment reads the record), or at a governed leg's prepare / settle (no call to refuse; the next leg then
190
- * reads the content after the newest record as off-target). A governed exit refuses its call and a governed suspend its row instead.
191
- * `catchUp`: an earlier record of the same write landed and the one that carries the tree's newer bits did not — on a governed tree
192
- * that earlier record covers the content before it, so the sentence says the next leg may not route its device calls to a person.
192
+ * that is not governed (no judgment reads the record), or at a governed leg's prepare / settle (no call to refuse). On a governed tree
193
+ * the record stays owed: a prepare's by the leg's next write, and once none lands — a settle's failure is the leg's last — the next leg
194
+ * reads the content after the newest record as off-target. A governed exit refuses its call and a governed suspend its row instead.
193
195
  * Minted once per state a leg could not write. */
194
196
  export declare function crossBoundaryRecordUnwrittenNotice(at: {
195
197
  readonly sessionId: string;
196
198
  readonly runId: string;
197
199
  readonly phase: CrossBoundaryRecordPhase;
198
200
  readonly governed: boolean;
199
- readonly catchUp: boolean;
200
201
  readonly cause: string;
201
202
  }): EngineNotice;
202
203
  /** The face a protocol tool (an MCP tool, an A2A skill) carries for its JUDGED `toolAxes` entry (`readToolAxes`' copy): the empty leg
@@ -157,9 +157,7 @@ export function crossBoundaryRecordUnwrittenNotice(at) {
157
157
  message: `The session's cross-boundary record could not be written at ${at.phase} (${at.cause.slice(0, 300)}) — ` +
158
158
  (!at.governed
159
159
  ? "the tree is not governed: no judgment reads the record, so its failure refused nothing; the tree's growth, or the leg's end, writes next, and a failure of this same state is not reported again."
160
- : at.catchUp
161
- ? "the tree is governed, and an earlier record of this write landed: the catch-up record that carries the tree's newer bits has not been written. Until #2160 lands, the next leg on this session may read the content before that earlier record as covered and may not route its device calls to a person (KNOWN-LIMITS KL-469-c); the terminal shape is fail-closed."
162
- : "the tree is governed: the next leg on this session reads the content after its newest record as off-target, so its device calls are put to a person."),
160
+ : `the tree is governed: ${at.phase === "prepare" ? "the leg's next write (an exit before its call runs, a suspend before its row, its end) owes the record again; if none lands, " : ""}the next leg on this session reads the content after its newest record as off-target, so its device calls are put to a person.`),
163
161
  detail: { sessionId: at.sessionId, runId: at.runId, phase: at.phase, governed: at.governed, cause: at.cause.slice(0, 300) },
164
162
  };
165
163
  }
@@ -1,4 +1,4 @@
1
- import { type AssertAllKeysHandled } from "./ask-origin.js";
1
+ import type { AssertAllKeysHandled } from "./ask-origin.js";
2
2
  import type { DecisionMember, PermissionResult } from "./tool-policy.js";
3
3
  export declare const refusedOutOfContract: (message: string) => PermissionResult;
4
4
  /** Is `d` a refusal the engine itself minted (by object identity — a look-alike `deny` a caller built is not one)? The receipt's
@@ -47,14 +47,48 @@ export declare const DECISION_MEMBER_ARMS: Readonly<{
47
47
  readonly origin: readonly ["ask"];
48
48
  readonly askClass: readonly ["ask"];
49
49
  readonly classes: readonly ["ask"];
50
- readonly guards: readonly ["ask"];
51
50
  readonly ruleUnreadable: readonly ["ask"];
52
51
  readonly authoredBy: readonly ["ask"];
53
- readonly foldedAskClasses: readonly ["ask"];
52
+ readonly editRewritten: readonly ["ask"];
54
53
  }>;
55
54
  export type DecisionMemberArmsCoverTheUnion = AssertAllKeysHandled<{
56
55
  [M in DecisionMember]: Exclude<ArmOf<M>, (typeof DECISION_MEMBER_ARMS)[M][number]>;
57
56
  }[DecisionMember]>;
57
+ /**
58
+ * WHO writes each member of the decision union — one writer per fact, one table (fenced to the union like
59
+ * {@link DECISION_MEMBER_ARMS}: a member the union gains without a row is a type error):
60
+ * · `composer` — the policy's or hook's own statement about its question: received, and read as an input of the class derivation;
61
+ * · `record` — the engine's attestation record (`attestation`): taken by reference after its brand check, read for its call;
62
+ * · `stamp` — written by the gate after the receipt (the disclosed words of the classes the engine derives, the allow layer's
63
+ * and the rule lane's accounts): no composer writes one, so a decision that states one is refused by name.
64
+ */
65
+ export declare const DECISION_MEMBER_WRITERS: Readonly<{
66
+ readonly action: "composer";
67
+ readonly updatedInput: "composer";
68
+ readonly message: "composer";
69
+ readonly decisionReason: "composer";
70
+ readonly attestation: "record";
71
+ readonly requiresRealApproval: "composer";
72
+ readonly denialLimitFallback: "composer";
73
+ readonly classifierNoRuling: "composer";
74
+ readonly allowRuleShadowed: "stamp";
75
+ readonly probeReason: "composer";
76
+ readonly probeCause: "composer";
77
+ readonly probeMandated: "composer";
78
+ readonly crossBoundaryMandated: "composer";
79
+ readonly mandated: "composer";
80
+ readonly mandate: "stamp";
81
+ readonly probeReadRootCandidate: "composer";
82
+ readonly matchedAskRule: "composer";
83
+ readonly ruleEvidence: "stamp";
84
+ readonly segmentCoverage: "stamp";
85
+ readonly origin: "stamp";
86
+ readonly askClass: "stamp";
87
+ readonly classes: "stamp";
88
+ readonly ruleUnreadable: "composer";
89
+ readonly authoredBy: "composer";
90
+ readonly editRewritten: "composer";
91
+ }>;
58
92
  export declare const RETIRED_WINDOW_MEMBER_DENY_MESSAGE: string;
59
93
  export declare const carriesRetiredWindow: (fallback: unknown) => boolean;
60
94
  /**
@@ -1,5 +1,4 @@
1
1
  import { types } from "node:util";
2
- import { ASK_CLASSES, ASK_ORIGINS, isAskClass, isAskOrigin, isPersistedRuleMandate, PERSISTED_RULE_MANDATES } from "./ask-origin.js";
3
2
  import { AUTO_MODE_FALLBACK_CAUSES, isAutoModeFallbackCause, isDenialLimitBound } from "./auto-mode.js";
4
3
  import { thrownText } from "./thrown-value.js";
5
4
  const ENGINE_REFUSALS = new WeakSet();
@@ -11,7 +10,6 @@ export const refusedOutOfContract = (message) => {
11
10
  export const isEngineRefusal = (d) => typeof d === "object" && d !== null && ENGINE_REFUSALS.has(d);
12
11
  const DECISION_REASONS = Object.freeze(["rule", "mode", "hook", "safety", "classifier", "persisted_rule", "sandbox", "org_rule", "org_unavailable", "read_only", "skill", "deployment_rule", "request_rule"]);
13
12
  const DECISION_ACTIONS = Object.keys({ allow: 0, deny: 0, ask: 0 });
14
- const GUARDS = Object.keys({ dangerous_delete: 0, unverifiable_delete: 0, unverifiable_shell_text: 0, transcript_write: 0, artifact_shared_read: 0 });
15
13
  const RULE_UNREADABLE_WORDS = Object.keys({ content_deny: 0, content_ask: 0, persisted_call: 0, persisted_rows: 0 });
16
14
  const AUTHORED_BY_WORDS = Object.keys({ deployment: 0 });
17
15
  const memberOf = (words) => {
@@ -21,12 +19,6 @@ const memberOf = (words) => {
21
19
  const CLOSED_MEMBERS = [
22
20
  { member: "action", words: DECISION_ACTIONS, has: memberOf(DECISION_ACTIONS), required: true },
23
21
  { member: "decisionReason", words: DECISION_REASONS, has: memberOf(DECISION_REASONS) },
24
- { member: "origin", words: ASK_ORIGINS, has: isAskOrigin },
25
- { member: "askClass", words: ASK_CLASSES, has: isAskClass },
26
- { member: "classes", words: ASK_CLASSES, has: isAskClass, list: true },
27
- { member: "foldedAskClasses", words: ASK_CLASSES, has: isAskClass, list: true },
28
- { member: "mandate", words: PERSISTED_RULE_MANDATES, has: isPersistedRuleMandate },
29
- { member: "guards", words: GUARDS, has: memberOf(GUARDS), list: true },
30
22
  { member: "ruleUnreadable", words: RULE_UNREADABLE_WORDS, has: memberOf(RULE_UNREADABLE_WORDS) },
31
23
  { member: "authoredBy", words: AUTHORED_BY_WORDS, has: memberOf(AUTHORED_BY_WORDS) },
32
24
  { member: "classifierNoRuling", words: AUTO_MODE_FALLBACK_CAUSES, has: isAutoModeFallbackCause },
@@ -41,8 +33,17 @@ export const DECISION_MEMBER_ARMS = Object.freeze({
41
33
  action: EVERY_ARM, updatedInput: EVERY_ARM, message: EVERY_ARM, decisionReason: EVERY_ARM, attestation: EVERY_ARM,
42
34
  requiresRealApproval: ASK, denialLimitFallback: ASK, classifierNoRuling: ASK, allowRuleShadowed: ASK, probeReason: ASK, probeCause: ASK,
43
35
  probeMandated: ASK, crossBoundaryMandated: ASK, mandated: ASK, mandate: ASK, probeReadRootCandidate: ASK, matchedAskRule: ASK, ruleEvidence: ASK,
44
- segmentCoverage: ASK, origin: ASK, askClass: ASK, classes: ASK, guards: ASK, ruleUnreadable: ASK, authoredBy: ASK, foldedAskClasses: ASK,
36
+ segmentCoverage: ASK, origin: ASK, askClass: ASK, classes: ASK, ruleUnreadable: ASK, authoredBy: ASK,
37
+ editRewritten: ASK,
45
38
  });
39
+ export const DECISION_MEMBER_WRITERS = Object.freeze({
40
+ action: "composer", updatedInput: "composer", message: "composer", decisionReason: "composer", attestation: "record",
41
+ requiresRealApproval: "composer", denialLimitFallback: "composer", classifierNoRuling: "composer", allowRuleShadowed: "stamp", probeReason: "composer",
42
+ probeCause: "composer", probeMandated: "composer", crossBoundaryMandated: "composer", mandated: "composer", mandate: "stamp",
43
+ probeReadRootCandidate: "composer", matchedAskRule: "composer", ruleEvidence: "stamp", segmentCoverage: "stamp", origin: "stamp", askClass: "stamp",
44
+ classes: "stamp", ruleUnreadable: "composer", authoredBy: "composer", editRewritten: "composer",
45
+ });
46
+ const STAMP_MEMBERS = Object.keys(DECISION_MEMBER_WRITERS).filter((m) => DECISION_MEMBER_WRITERS[m] === "stamp");
46
47
  const RETIRED_WINDOW_MEMBER = "autoDenyAfterMs";
47
48
  export const RETIRED_WINDOW_MEMBER_DENY_MESSAGE = `a permission decision's "denialLimitFallback" carries "${RETIRED_WINDOW_MEMBER}" — the decision names the counts only; ` +
48
49
  `the auto-deny window is decided by the ask's route (a live approver arms it, every other route runs none) and cannot be ` +
@@ -59,6 +60,7 @@ const NESTED_CONTRACTS = [
59
60
  { holder: "", member: "probeCause", members: Object.keys({ code: 0, roots: 0, further: 0 }), required: Object.keys({ code: 0, roots: 0 }) },
60
61
  { holder: "probeCause.", member: "roots", members: OPERAND_MEMBERS, required: OPERAND_MEMBERS },
61
62
  { holder: "probeCause.", member: "further", members: OPERAND_MEMBERS, required: OPERAND_MEMBERS },
63
+ { holder: "", member: "editRewritten", members: Object.keys({ acceptableForm: 0 }), required: Object.keys({ acceptableForm: 0 }) },
62
64
  ];
63
65
  const nonNegativeInteger = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0;
64
66
  const NESTED_VALUE_FENCES = {
@@ -80,7 +82,12 @@ function renderForeignValue(v) {
80
82
  }
81
83
  }
82
84
  export function screenContractValues(contract, opts) {
83
- for (const { member, words, has, list, required } of CLOSED_MEMBERS) {
85
+ const stamped = STAMP_MEMBERS.find((m) => contract[m] !== undefined);
86
+ if (stamped !== undefined) {
87
+ return refusedOutOfContract(`a permission decision carries "${stamped}" — the member is written by the gate after a policy answers (the disclosed account of what the engine's own layers found); ` +
88
+ `a policy states its question through its own members (requiresRealApproval, authoredBy, matchedAskRule, …); denied fail-closed rather than carrying a value the gate replaces`);
89
+ }
90
+ for (const { member, words, has, required } of CLOSED_MEMBERS) {
84
91
  if (opts?.skip?.has(member) === true)
85
92
  continue;
86
93
  const v = contract[member];
@@ -89,13 +96,6 @@ export function screenContractValues(contract, opts) {
89
96
  return refusedOutOfContract(`a permission decision's "${member}" is absent — the closed set is ${words.join("/")}; denied fail-closed rather than reading a word outside it as an allow`);
90
97
  continue;
91
98
  }
92
- if (list === true) {
93
- const received = receiveList(v, member, words, has);
94
- if (received.kind === "refused")
95
- return received.refused;
96
- contract[member] = received.held;
97
- continue;
98
- }
99
99
  if (has(v))
100
100
  continue;
101
101
  return unrecognized(member, v, words);
@@ -0,0 +1,6 @@
1
+ /** The delegation factory's mint: `result`'s `details` object is a refusal before any child ran. Returns `result` as it is. */
2
+ export declare function notStartedResult<T extends object>(result: T): T;
3
+ /** An engine copy's carry: the engine's `copy` of a receipted object holds the receipt too. Anything else carries nothing. */
4
+ export declare function carryNotStartedReceipt(original: unknown, copy: unknown): void;
5
+ /** Is `result` one of the delegation tool's refusals before any child ran — by the receipt on its `details` object alone? */
6
+ export declare function isNotStartedDelegationResult(result: unknown): boolean;
@@ -0,0 +1,17 @@
1
+ const NOT_STARTED_RECEIPTS = new WeakSet();
2
+ export function notStartedResult(result) {
3
+ const details = result.details;
4
+ if (typeof details === "object" && details !== null)
5
+ NOT_STARTED_RECEIPTS.add(details);
6
+ return result;
7
+ }
8
+ export function carryNotStartedReceipt(original, copy) {
9
+ if (typeof original === "object" && original !== null && typeof copy === "object" && copy !== null && NOT_STARTED_RECEIPTS.has(original))
10
+ NOT_STARTED_RECEIPTS.add(copy);
11
+ }
12
+ export function isNotStartedDelegationResult(result) {
13
+ if (typeof result !== "object" || result === null)
14
+ return false;
15
+ const details = result.details;
16
+ return typeof details === "object" && details !== null && NOT_STARTED_RECEIPTS.has(details);
17
+ }