@sema-agent/core 7.55.0 → 7.57.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 (502) hide show
  1. package/CHANGELOG.md +1054 -0
  2. package/LICENSE +1 -1
  3. package/dist/agents/cascade.js +1 -1
  4. package/dist/agents/cc-peer-directory.js +1 -0
  5. package/dist/agents/child-model-seat.d.ts +0 -11
  6. package/dist/agents/child-model-seat.js +0 -3
  7. package/dist/agents/list-agents-tool.d.ts +3 -1
  8. package/dist/agents/list-agents-tool.js +7 -7
  9. package/dist/agents/org-delivery-gate.js +3 -4
  10. package/dist/agents/peer-directory.d.ts +22 -4
  11. package/dist/agents/peer-directory.js +24 -2
  12. package/dist/agents/peer-held-queue.d.ts +69 -49
  13. package/dist/agents/peer-held-queue.js +255 -106
  14. package/dist/agents/peer-session-drain.js +65 -45
  15. package/dist/agents/repair-loop.js +2 -2
  16. package/dist/agents/send-message-tool.js +7 -6
  17. package/dist/agents/subagent.d.ts +6 -4
  18. package/dist/agents/subagent.js +72 -68
  19. package/dist/agents/tool-filter.d.ts +7 -5
  20. package/dist/agents/tool-filter.js +12 -9
  21. package/dist/agents/verify.d.ts +3 -2
  22. package/dist/agents/verify.js +3 -3
  23. package/dist/brain/anthropic.js +45 -80
  24. package/dist/brain/media-degrade.d.ts +18 -7
  25. package/dist/brain/media-degrade.js +13 -2
  26. package/dist/brain/model-capability.d.ts +37 -0
  27. package/dist/brain/model-capability.js +34 -0
  28. package/dist/brain/model-presets.d.ts +2 -8
  29. package/dist/brain/model-presets.js +1 -6
  30. package/dist/brain/open-responses.js +23 -34
  31. package/dist/brain/openai.js +25 -96
  32. package/dist/brain/provider-dialect.d.ts +3 -2
  33. package/dist/brain/provider-dialect.js +2 -2
  34. package/dist/brain/reasoning-request.d.ts +96 -0
  35. package/dist/brain/reasoning-request.js +174 -0
  36. package/dist/brain/reasoning.d.ts +11 -11
  37. package/dist/brain/reasoning.js +4 -3
  38. package/dist/brain/request-params.d.ts +13 -4
  39. package/dist/brain/request-params.js +21 -5
  40. package/dist/brain/status-sink.d.ts +20 -0
  41. package/dist/brain/status-sink.js +7 -0
  42. package/dist/brain/stream-engine.d.ts +9 -0
  43. package/dist/brain/stream-engine.js +24 -10
  44. package/dist/brain/stream-shared.d.ts +5 -4
  45. package/dist/brain/stream-shared.js +4 -4
  46. package/dist/core/a2a.d.ts +2 -1
  47. package/dist/core/a2a.js +19 -13
  48. package/dist/core/agent-definition.d.ts +10 -0
  49. package/dist/core/allow-entry.d.ts +23 -23
  50. package/dist/core/allow-entry.js +42 -46
  51. package/dist/core/allow-rule-shadow.d.ts +3 -3
  52. package/dist/core/approval-object.d.ts +21 -5
  53. package/dist/core/approval-object.js +44 -17
  54. package/dist/core/ask-origin.d.ts +66 -20
  55. package/dist/core/ask-origin.js +63 -23
  56. package/dist/core/ask-question.d.ts +51 -8
  57. package/dist/core/ask-question.js +3 -4
  58. package/dist/core/ask-unresolvable-notice.d.ts +8 -3
  59. package/dist/core/ask-unresolvable-notice.js +16 -2
  60. package/dist/core/auto-compaction.d.ts +71 -6
  61. package/dist/core/auto-compaction.js +42 -26
  62. package/dist/core/background-agent-store.d.ts +6 -2
  63. package/dist/core/background-agent-store.js +1 -1
  64. package/dist/core/checkpoint-generation.d.ts +53 -0
  65. package/dist/core/checkpoint-generation.js +35 -0
  66. package/dist/core/checkpoint-queries.d.ts +180 -0
  67. package/dist/core/checkpoint-queries.js +272 -0
  68. package/dist/core/checkpoint-requirements.d.ts +19 -1
  69. package/dist/core/checkpoint-requirements.js +6 -0
  70. package/dist/core/checkpoint-store.d.ts +105 -53
  71. package/dist/core/checkpoint-store.js +43 -20
  72. package/dist/core/cross-boundary-taint.d.ts +6 -5
  73. package/dist/core/cross-boundary-taint.js +5 -5
  74. package/dist/core/decision-receipt.d.ts +37 -3
  75. package/dist/core/decision-receipt.js +17 -17
  76. package/dist/core/delegation-not-started.d.ts +6 -0
  77. package/dist/core/delegation-not-started.js +17 -0
  78. package/dist/core/engine-attestation.d.ts +93 -0
  79. package/dist/core/engine-attestation.js +70 -0
  80. package/dist/core/engine-capabilities.d.ts +4 -1
  81. package/dist/core/engine-capabilities.js +1 -1
  82. package/dist/core/engine-notice.d.ts +32 -12
  83. package/dist/core/engine-notice.js +6 -0
  84. package/dist/core/file-history-store.d.ts +104 -22
  85. package/dist/core/file-history-store.js +37 -19
  86. package/dist/core/gate-fold.d.ts +1 -1
  87. package/dist/core/gate-fold.js +22 -10
  88. package/dist/core/gate-lanes.js +73 -65
  89. package/dist/core/gate-outcome.d.ts +26 -5
  90. package/dist/core/gate-outcome.js +26 -0
  91. package/dist/core/governance-codes.d.ts +5 -1
  92. package/dist/core/governance-codes.js +6 -0
  93. package/dist/core/hooks.d.ts +19 -18
  94. package/dist/core/hooks.js +3 -1
  95. package/dist/core/host-floor.d.ts +128 -0
  96. package/dist/core/host-floor.js +206 -0
  97. package/dist/core/host-target.d.ts +38 -3
  98. package/dist/core/host-target.js +38 -5
  99. package/dist/core/mailbox-store.d.ts +62 -1
  100. package/dist/core/mailbox-store.js +59 -0
  101. package/dist/core/mcp-name-judge.d.ts +46 -0
  102. package/dist/core/mcp-name-judge.js +61 -0
  103. package/dist/core/mcp-probe.d.ts +1 -1
  104. package/dist/core/mcp-probe.js +2 -5
  105. package/dist/core/mcp.d.ts +5 -1
  106. package/dist/core/mcp.js +70 -64
  107. package/dist/core/memory-engine/consolidation-driver.js +4 -3
  108. package/dist/core/memory-engine/delegation-settlement.js +15 -24
  109. package/dist/core/memory-engine/distiller.js +26 -17
  110. package/dist/core/memory-engine/engine.js +4 -4
  111. package/dist/core/memory-engine/layout.d.ts +60 -8
  112. package/dist/core/memory-engine/layout.js +70 -8
  113. package/dist/core/model-seat.d.ts +10 -3
  114. package/dist/core/mods/classic-events.d.ts +67 -0
  115. package/dist/core/mods/classic-events.js +1 -0
  116. package/dist/core/mods/dollar.d.ts +13 -0
  117. package/dist/core/mods/extension-call.d.ts +31 -0
  118. package/dist/core/mods/extension-call.js +43 -0
  119. package/dist/core/mods/kernel/dispatch.d.ts +20 -3
  120. package/dist/core/mods/kernel/dispatch.js +140 -69
  121. package/dist/core/mods/kernel/events.d.ts +47 -11
  122. package/dist/core/mods/kernel/events.js +66 -42
  123. package/dist/core/mods/kernel/index.d.ts +4 -4
  124. package/dist/core/mods/kernel/index.js +2 -2
  125. package/dist/core/mods/kernel/receive.d.ts +39 -5
  126. package/dist/core/mods/kernel/receive.js +290 -17
  127. package/dist/core/mods/kernel/registration.d.ts +33 -2
  128. package/dist/core/mods/kernel/registration.js +6 -7
  129. package/dist/core/mods/kernel/site-rules.d.ts +44 -16
  130. package/dist/core/mods/kernel/site-rules.js +24 -42
  131. package/dist/core/mods/spec-seats.d.ts +69 -0
  132. package/dist/core/mods/spec-seats.js +114 -0
  133. package/dist/core/mods/stations.d.ts +28 -8
  134. package/dist/core/mods/stations.js +29 -13
  135. package/dist/core/mods/tool-call.d.ts +79 -0
  136. package/dist/core/mods/tool-call.js +152 -0
  137. package/dist/core/namespaced-rule-name.d.ts +32 -38
  138. package/dist/core/namespaced-rule-name.js +29 -36
  139. package/dist/core/parent-spec-seat.d.ts +6 -1
  140. package/dist/core/parent-spec-seat.js +2 -0
  141. package/dist/core/park-selfcheck.js +3 -0
  142. package/dist/core/permission-rule-consent.d.ts +24 -3
  143. package/dist/core/permission-rule-consent.js +136 -41
  144. package/dist/core/permission-rule-model.d.ts +57 -5
  145. package/dist/core/permission-rule-model.js +90 -31
  146. package/dist/core/permission-rule-org.d.ts +6 -2
  147. package/dist/core/permission-rule-org.js +8 -4
  148. package/dist/core/permission-rule-provider.d.ts +5 -2
  149. package/dist/core/permission-rule-provider.js +41 -11
  150. package/dist/core/permission-rule-store.d.ts +3 -2
  151. package/dist/core/permission-rule-store.js +11 -2
  152. package/dist/core/permission-rule-sync.js +3 -2
  153. package/dist/core/permission-rule-syntax.d.ts +5 -4
  154. package/dist/core/permission-rule-syntax.js +2 -2
  155. package/dist/core/permission-rules.d.ts +4 -4
  156. package/dist/core/permission-rules.js +11 -20
  157. package/dist/core/persisted-rule-arms.d.ts +2 -2
  158. package/dist/core/persisted-rule-arms.js +10 -12
  159. package/dist/core/principal-name.d.ts +20 -0
  160. package/dist/core/principal-name.js +22 -0
  161. package/dist/core/prompt-section-seat.js +4 -6
  162. package/dist/core/protocol-http-auth.d.ts +40 -5
  163. package/dist/core/protocol-http-auth.js +168 -4
  164. package/dist/core/protocol-naming.d.ts +20 -0
  165. package/dist/core/protocol-naming.js +20 -3
  166. package/dist/core/read-only-shell.d.ts +20 -5
  167. package/dist/core/read-only-shell.js +29 -14
  168. package/dist/core/remote-env.d.ts +37 -1
  169. package/dist/core/remote-env.js +11 -0
  170. package/dist/core/resume-startup-cause.d.ts +24 -2
  171. package/dist/core/resume-startup-cause.js +20 -1
  172. package/dist/core/retired-keys.d.ts +16 -0
  173. package/dist/core/retired-keys.js +16 -4
  174. package/dist/core/rewrite-rejudge.d.ts +60 -0
  175. package/dist/core/rewrite-rejudge.js +36 -0
  176. package/dist/core/roles.d.ts +28 -1
  177. package/dist/core/roles.js +81 -26
  178. package/dist/core/rule-lane-reads.d.ts +20 -15
  179. package/dist/core/rule-lane-reads.js +45 -17
  180. package/dist/core/rule-owner.d.ts +3 -3
  181. package/dist/core/rule-owner.js +3 -2
  182. package/dist/core/runner/announce-once-ledger.d.ts +14 -0
  183. package/dist/core/runner/announce-once-ledger.js +5 -0
  184. package/dist/core/runner/assemble-result.d.ts +1 -0
  185. package/dist/core/runner/assemble-result.js +1 -1
  186. package/dist/core/runner/call-hook-stations.d.ts +3 -2
  187. package/dist/core/runner/caller-roster.d.ts +16 -4
  188. package/dist/core/runner/caller-roster.js +33 -6
  189. package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
  190. package/dist/core/runner/capability-withheld-seat.js +24 -0
  191. package/dist/core/runner/classifier-ladder.d.ts +7 -9
  192. package/dist/core/runner/classifier-ladder.js +3 -3
  193. package/dist/core/runner/compact-session.d.ts +10 -0
  194. package/dist/core/runner/compact-session.js +202 -0
  195. package/dist/core/runner/compaction-call-options.d.ts +2 -2
  196. package/dist/core/runner/compaction-seams.d.ts +21 -1
  197. package/dist/core/runner/compaction-seams.js +11 -8
  198. package/dist/core/runner/construction-doors.js +3 -0
  199. package/dist/core/runner/contracts.d.ts +50 -40
  200. package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
  201. package/dist/core/runner/cross-boundary-lane.js +40 -27
  202. package/dist/core/runner/denial-limit-arms.d.ts +2 -2
  203. package/dist/core/runner/denial-limit-arms.js +1 -1
  204. package/dist/core/runner/derived-route-fallback.d.ts +13 -0
  205. package/dist/core/runner/derived-route-fallback.js +6 -0
  206. package/dist/core/runner/env-capability-census.d.ts +3 -2
  207. package/dist/core/runner/env-capability-census.js +9 -3
  208. package/dist/core/runner/file-history-request.d.ts +18 -0
  209. package/dist/core/runner/file-history-request.js +21 -13
  210. package/dist/core/runner/file-history-restore.d.ts +45 -0
  211. package/dist/core/runner/file-history-restore.js +46 -0
  212. package/dist/core/runner/gate-exit.d.ts +3 -3
  213. package/dist/core/runner/gate-exit.js +4 -3
  214. package/dist/core/runner/image.d.ts +7 -17
  215. package/dist/core/runner/image.js +9 -60
  216. package/dist/core/runner/permission-rule-lanes.d.ts +11 -11
  217. package/dist/core/runner/permission-rule-lanes.js +39 -17
  218. package/dist/core/runner/person-path-rows.d.ts +12 -9
  219. package/dist/core/runner/person-path-rows.js +18 -7
  220. package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -0
  221. package/dist/core/runner/prepare-acquire-reconcile.js +2 -1
  222. package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
  223. package/dist/core/runner/prepare-ask-lane.js +5 -2
  224. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
  225. package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
  226. package/dist/core/runner/prepare-config-doors.d.ts +35 -38
  227. package/dist/core/runner/prepare-config-doors.js +46 -28
  228. package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
  229. package/dist/core/runner/prepare-defer-classify.js +7 -8
  230. package/dist/core/runner/prepare-file-history.d.ts +48 -8
  231. package/dist/core/runner/prepare-file-history.js +7 -39
  232. package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
  233. package/dist/core/runner/prepare-gate-stations.js +10 -1
  234. package/dist/core/runner/prepare-hands-readface.d.ts +5 -9
  235. package/dist/core/runner/prepare-hands-readface.js +17 -14
  236. package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
  237. package/dist/core/runner/prepare-inherited-gate.js +5 -3
  238. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  239. package/dist/core/runner/prepare-park-ask.d.ts +2 -0
  240. package/dist/core/runner/prepare-park-ask.js +7 -7
  241. package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
  242. package/dist/core/runner/prepare-policy-chain.js +67 -76
  243. package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
  244. package/dist/core/runner/prepare-prompt-assembly.js +10 -8
  245. package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
  246. package/dist/core/runner/prepare-prompt-inputs.js +3 -5
  247. package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
  248. package/dist/core/runner/prepare-protocol-tools.js +3 -3
  249. package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
  250. package/dist/core/runner/prepare-safety-scan.js +0 -17
  251. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
  252. package/dist/core/runner/prepare-suspend-saga.js +5 -6
  253. package/dist/core/runner/prepare-task.d.ts +5 -2
  254. package/dist/core/runner/prepare-task.js +48 -43
  255. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +20 -4
  256. package/dist/core/runner/prepare-tool-disclosure-mount.js +33 -23
  257. package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
  258. package/dist/core/runner/prepare-turn-wiring.js +2 -7
  259. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
  260. package/dist/core/runner/prepare-wiring-manifest.js +3 -3
  261. package/dist/core/runner/resume-admission.js +1 -1
  262. package/dist/core/runner/resume-apply.js +11 -12
  263. package/dist/core/runner/resume-checkpoint-screen.js +3 -0
  264. package/dist/core/runner/resume-claim.d.ts +4 -2
  265. package/dist/core/runner/resume-claim.js +15 -8
  266. package/dist/core/runner/retired-runner-deps.js +1 -0
  267. package/dist/core/runner/rewind-files.d.ts +12 -0
  268. package/dist/core/runner/rewind-files.js +90 -0
  269. package/dist/core/runner/run-attachment-seats.js +2 -1
  270. package/dist/core/runner/run-brain-sinks.d.ts +4 -1
  271. package/dist/core/runner/run-brain-sinks.js +4 -2
  272. package/dist/core/runner/run-harness-handlers.js +12 -4
  273. package/dist/core/runner/run-leg.d.ts +1 -1
  274. package/dist/core/runner/run-leg.js +40 -39
  275. package/dist/core/runner/run-notification-lane.d.ts +2 -0
  276. package/dist/core/runner/run-notification-lane.js +2 -2
  277. package/dist/core/runner/run-recovery-lanes.js +3 -4
  278. package/dist/core/runner/run-settle-and-teardown.js +7 -12
  279. package/dist/core/runner/run-terminal-adoption.js +3 -4
  280. package/dist/core/runner/run-turn-boundary.js +4 -15
  281. package/dist/core/runner/runtask.d.ts +10 -0
  282. package/dist/core/runner/runtask.js +35 -42
  283. package/dist/core/runner/send-message-continuation.js +1 -1
  284. package/dist/core/runner/session-read-file-states.d.ts +15 -0
  285. package/dist/core/runner/session-read-file-states.js +28 -0
  286. package/dist/core/runner/session-rule-policy.js +4 -3
  287. package/dist/core/runner/session-verb-doors.d.ts +28 -0
  288. package/dist/core/runner/session-verb-doors.js +48 -0
  289. package/dist/core/runner/session-write-ledger.d.ts +30 -0
  290. package/dist/core/runner/session-write-ledger.js +101 -0
  291. package/dist/core/runner/shell-env-withheld.d.ts +33 -0
  292. package/dist/core/runner/shell-env-withheld.js +51 -0
  293. package/dist/core/runner/skills-seat.js +6 -2
  294. package/dist/core/runner/stream-settle-backstop.js +12 -15
  295. package/dist/core/runner/sub-agent-deny-lists.d.ts +25 -3
  296. package/dist/core/runner/sub-agent-deny-lists.js +25 -17
  297. package/dist/core/runner/synthetic-tools.d.ts +6 -0
  298. package/dist/core/runner/synthetic-tools.js +4 -1
  299. package/dist/core/runner/teardown-bounded.d.ts +1 -0
  300. package/dist/core/runner/teardown-bounded.js +1 -0
  301. package/dist/core/runner/tool-disclosure.d.ts +10 -12
  302. package/dist/core/runner/tool-disclosure.js +1 -3
  303. package/dist/core/runner/tool-end-body.d.ts +1 -1
  304. package/dist/core/runner/tool-end-body.js +10 -9
  305. package/dist/core/runner/tool-not-executed.d.ts +5 -0
  306. package/dist/core/runner/tool-not-executed.js +11 -0
  307. package/dist/core/runner/tool-occurrence.d.ts +8 -0
  308. package/dist/core/runner/tool-occurrence.js +7 -0
  309. package/dist/core/runner/turn-attachments.d.ts +33 -15
  310. package/dist/core/runner/turn-attachments.js +62 -37
  311. package/dist/core/runner-deps.d.ts +7 -7
  312. package/dist/core/safety-axis-vocab.d.ts +6 -4
  313. package/dist/core/safety-axis-vocab.js +6 -5
  314. package/dist/core/safety-merge-corpus.js +11 -3
  315. package/dist/core/secret-env.d.ts +30 -3
  316. package/dist/core/secret-env.js +47 -8
  317. package/dist/core/select-model.js +3 -3
  318. package/dist/core/session-policy-store.d.ts +32 -15
  319. package/dist/core/session-policy-store.js +156 -36
  320. package/dist/core/session-store.d.ts +29 -10
  321. package/dist/core/session-store.js +51 -19
  322. package/dist/core/session.d.ts +82 -16
  323. package/dist/core/session.js +53 -0
  324. package/dist/core/shell-read-silence.d.ts +11 -12
  325. package/dist/core/shell-read-silence.js +9 -5
  326. package/dist/core/shell-run-candidates.js +3 -1
  327. package/dist/core/shell-wrapper-projection.d.ts +1 -1
  328. package/dist/core/shell-wrapper-projection.js +1 -1
  329. package/dist/core/shell-wrapper-table.d.ts +14 -7
  330. package/dist/core/shell-wrapper-table.js +5 -4
  331. package/dist/core/side-query.js +10 -1
  332. package/dist/core/skill-grant.d.ts +7 -2
  333. package/dist/core/skill-grant.js +5 -0
  334. package/dist/core/skills-directory.js +6 -2
  335. package/dist/core/store-contracts/background-agent-store-contract.js +1 -0
  336. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
  337. package/dist/core/store-contracts/checkpoint-store-contract.js +141 -2
  338. package/dist/core/store-contracts/file-history-store-contract.js +40 -1
  339. package/dist/core/store-contracts/mailbox-store-contract.js +49 -1
  340. package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
  341. package/dist/core/store-contracts/peer-directory-contract.js +14 -2
  342. package/dist/core/store-contracts/session-repo-contract.js +51 -0
  343. package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
  344. package/dist/core/store-contracts/session-store-contract.js +150 -14
  345. package/dist/core/stub-env.d.ts +2 -0
  346. package/dist/core/stub-env.js +1 -0
  347. package/dist/core/synthetic-read-verdict.js +3 -3
  348. package/dist/core/task-event.d.ts +32 -4
  349. package/dist/core/task-notification.d.ts +16 -12
  350. package/dist/core/task-registry-agent.d.ts +8 -4
  351. package/dist/core/task-registry-agent.js +14 -8
  352. package/dist/core/task-registry-shared.d.ts +35 -6
  353. package/dist/core/task-registry-shared.js +11 -0
  354. package/dist/core/task-registry.d.ts +10 -1
  355. package/dist/core/task-registry.js +12 -2
  356. package/dist/core/task-result.d.ts +18 -0
  357. package/dist/core/task-spec.d.ts +18 -13
  358. package/dist/core/tighten-task-spec.js +2 -1
  359. package/dist/core/tool-catalog-entries.d.ts +23 -0
  360. package/dist/core/tool-catalog-entries.js +14 -2
  361. package/dist/core/tool-check-reading.d.ts +11 -0
  362. package/dist/core/tool-check-reading.js +11 -6
  363. package/dist/core/tool-model-gate.d.ts +2 -2
  364. package/dist/core/tool-name-aliases.d.ts +48 -18
  365. package/dist/core/tool-name-aliases.js +36 -19
  366. package/dist/core/tool-name-readings.d.ts +6 -32
  367. package/dist/core/tool-name-readings.js +2 -9
  368. package/dist/core/tool-policy.d.ts +78 -204
  369. package/dist/core/tool-policy.js +152 -204
  370. package/dist/core/tool-result-store.js +3 -0
  371. package/dist/core/tool-roster.d.ts +14 -19
  372. package/dist/core/tool-roster.js +11 -44
  373. package/dist/core/tool-spec-members.js +7 -2
  374. package/dist/core/tool-spec.d.ts +19 -11
  375. package/dist/core/tools.js +49 -9
  376. package/dist/core/trace.d.ts +6 -3
  377. package/dist/core/trace.js +2 -1
  378. package/dist/core/types.d.ts +1 -1
  379. package/dist/core/untrusted-egress.d.ts +20 -0
  380. package/dist/core/untrusted-egress.js +77 -3
  381. package/dist/core/user-attachment.d.ts +8 -1
  382. package/dist/core/user-attachment.js +64 -4
  383. package/dist/core/wiring-manifest.d.ts +9 -0
  384. package/dist/core/wiring-manifest.js +1 -0
  385. package/dist/core/workflow-journal-store.js +1 -1
  386. package/dist/engine/compaction/compaction.js +3 -2
  387. package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
  388. package/dist/engine/execution-env/node-execution-env.js +11 -2
  389. package/dist/engine/harness/agent-harness.d.ts +32 -6
  390. package/dist/engine/harness/agent-harness.js +65 -9
  391. package/dist/engine/harness/types.d.ts +29 -2
  392. package/dist/engine/llm/types.d.ts +28 -11
  393. package/dist/engine/loop/agent-loop.d.ts +23 -4
  394. package/dist/engine/loop/agent-loop.js +42 -30
  395. package/dist/engine/loop/types.d.ts +16 -6
  396. package/dist/engine/session/memory-repo.d.ts +9 -2
  397. package/dist/engine/session/memory-repo.js +11 -1
  398. package/dist/engine/session/repo-utils.d.ts +6 -5
  399. package/dist/engine/session/repo-utils.js +14 -6
  400. package/dist/index.d.ts +34 -17
  401. package/dist/index.js +22 -11
  402. package/dist/internal/harness-types.d.ts +1 -1
  403. package/dist/internal/harness.d.ts +2 -1
  404. package/dist/internal/harness.js +1 -0
  405. package/dist/internal/llm.d.ts +1 -1
  406. package/dist/orchestration/run-workflow-tool.d.ts +6 -4
  407. package/dist/orchestration/run-workflow-tool.js +5 -3
  408. package/dist/orchestration/workflow.d.ts +3 -0
  409. package/dist/orchestration/workflow.js +36 -18
  410. package/dist/primitives/credential-ref.d.ts +89 -0
  411. package/dist/primitives/credential-ref.js +125 -0
  412. package/dist/primitives/index.d.ts +2 -0
  413. package/dist/primitives/index.js +1 -0
  414. package/dist/prompt-assembly/artifact.d.ts +2 -2
  415. package/dist/prompt-assembly/artifact.js +5 -3
  416. package/dist/prompt-assembly/assemble.d.ts +3 -2
  417. package/dist/prompt-assembly/assemble.js +1 -1
  418. package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
  419. package/dist/prompt-assembly/catalog/schema.js +34 -2
  420. package/dist/prompt-assembly/catalog/sections.js +0 -1
  421. package/dist/prompt-assembly/composer.d.ts +3 -1
  422. package/dist/prompt-assembly/composer.js +1 -1
  423. package/dist/prompt-assembly/event-registry.js +1 -0
  424. package/dist/prompt-assembly/overlay.js +3 -3
  425. package/dist/prompt-assembly/renderers.d.ts +1 -1
  426. package/dist/prompt-assembly/renderers.js +0 -3
  427. package/dist/prompt-assembly/role-base.d.ts +15 -0
  428. package/dist/prompt-assembly/role-base.js +9 -0
  429. package/dist/prompt-assembly/select.d.ts +39 -14
  430. package/dist/prompt-assembly/select.js +47 -16
  431. package/dist/prompt-assembly/sugar.d.ts +17 -11
  432. package/dist/prompt-assembly/sugar.js +8 -3
  433. package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
  434. package/dist/prompt-assembly/tool-catalog.js +114 -4
  435. package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
  436. package/dist/prompt-assembly/turn-snapshot.js +0 -3
  437. package/dist/prompt-assembly/types.d.ts +0 -7
  438. package/dist/scenarios/full-body.d.ts +11 -11
  439. package/dist/scenarios/full-body.js +4 -3
  440. package/dist/shell/lex.js +10 -1
  441. package/dist/stores/file/adoption/adopt.js +4 -3
  442. package/dist/stores/file/adoption/marker.js +3 -2
  443. package/dist/stores/file/checkpoint-store.d.ts +21 -4
  444. package/dist/stores/file/checkpoint-store.js +38 -7
  445. package/dist/stores/file/file-history-store.js +18 -11
  446. package/dist/stores/file/index.js +2 -1
  447. package/dist/stores/file/mailbox-store.d.ts +2 -1
  448. package/dist/stores/file/mailbox-store.js +26 -1
  449. package/dist/stores/file/permission-rule-adopt.js +4 -3
  450. package/dist/stores/file/permission-rule-store.js +11 -5
  451. package/dist/stores/file/session-store.d.ts +29 -6
  452. package/dist/stores/file/session-store.js +42 -50
  453. package/dist/tools/artifact/artifact-tool.js +3 -2
  454. package/dist/tools/fs/bash-program-position.d.ts +19 -2
  455. package/dist/tools/fs/bash-program-position.js +56 -9
  456. package/dist/tools/fs/bash-readonly-classifier.d.ts +15 -19
  457. package/dist/tools/fs/bash-readonly-classifier.js +5 -10
  458. package/dist/tools/fs/fs-bash.js +15 -8
  459. package/dist/tools/fs/fs-glob.d.ts +86 -0
  460. package/dist/tools/fs/fs-glob.js +226 -0
  461. package/dist/tools/fs/fs-read.js +14 -14
  462. package/dist/tools/fs/fs-search-tools.js +7 -7
  463. package/dist/tools/fs/pattern-kill-guard.d.ts +23 -0
  464. package/dist/tools/fs/pattern-kill-guard.js +429 -0
  465. package/dist/tools/fs/pdf.d.ts +9 -6
  466. package/dist/tools/fs/pdf.js +3 -3
  467. package/dist/tools/fs/program-read-model.d.ts +57 -7
  468. package/dist/tools/fs/program-read-model.js +11 -1
  469. package/dist/tools/fs/program-read-model.rows.js +78 -21
  470. package/dist/tools/fs/read-deny-home.js +3 -2
  471. package/dist/tools/fs/removal-targets.d.ts +17 -7
  472. package/dist/tools/fs/removal-targets.js +47 -20
  473. package/dist/tools/fs/search.d.ts +10 -0
  474. package/dist/tools/fs/search.js +20 -26
  475. package/dist/tools/fs/shell-read-argv.js +89 -12
  476. package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
  477. package/dist/tools/fs/shell-read-bindings.js +41 -0
  478. package/dist/tools/fs/shell-read-check.d.ts +10 -0
  479. package/dist/tools/fs/shell-read-check.js +13 -20
  480. package/dist/tools/fs/shell-read-environment.d.ts +5 -1
  481. package/dist/tools/fs/shell-read-environment.js +3 -2
  482. package/dist/tools/fs/shell-read-establish.d.ts +15 -0
  483. package/dist/tools/fs/shell-read-establish.js +19 -20
  484. package/dist/tools/fs/shell-read-identity.d.ts +12 -9
  485. package/dist/tools/fs/shell-read-identity.js +9 -4
  486. package/dist/tools/fs/shell-read-plan.js +24 -16
  487. package/dist/tools/fs/shell-read-start.d.ts +6 -1
  488. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
  489. package/dist/tools/fs/shell-read-write-targets.js +2 -3
  490. package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
  491. package/dist/tools/fs/shell-reentry-text.js +40 -2
  492. package/dist/tools/todo.js +63 -63
  493. package/dist/tools/web.d.ts +19 -14
  494. package/dist/tools/web.js +46 -61
  495. package/package.json +1 -1
  496. package/test/export-surface.snapshot.json +221 -7
  497. package/wire-changes/core-stores-sql@7.57.0.json +29 -0
  498. package/wire-changes/core@7.56.0.json +3891 -0
  499. package/wire-changes/core@7.57.0.json +1487 -0
  500. package/wire-changes/mods-kernel@7.56.0.json +303 -0
  501. package/wire-changes/mods-kernel@7.57.0.json +29 -0
  502. package/wire-changes/primitives@7.57.0.json +245 -0
@@ -1,4 +1,6 @@
1
- import { credentialHeaderValues, holdOwnCredentialValues } from "./secret-env.js";
1
+ import { authSchemeCredentials, credentialHeaderValues, holdOwnCredentialValues } from "./secret-env.js";
2
+ import { readMember } from "./thrown-value.js";
3
+ import { egressText, redactionMarkerSpans } from "./untrusted-egress.js";
2
4
  import { inlineUntrusted } from "./untrusted-text.js";
3
5
  export function headerOwnershipCollision(t) {
4
6
  const owners = new Map();
@@ -30,12 +32,174 @@ export function underDeclaredHeaders(defaults, declared) {
30
32
  const owned = new Set(Object.keys(declared ?? {}).map((k) => k.toLowerCase()));
31
33
  return { ...Object.fromEntries(Object.entries(defaults).filter(([k]) => !owned.has(k.toLowerCase()))), ...declared };
32
34
  }
35
+ const httpTrimmed = (value) => value.replace(/^[\t\n\r ]+|[\t\n\r ]+$/g, "");
36
+ export function declaredHeaderValues(transport, principal) {
37
+ const out = new Set();
38
+ try {
39
+ const headers = readMember(transport, "headers");
40
+ if (typeof headers === "object" && headers !== null) {
41
+ for (const value of Object.values(headers))
42
+ if (typeof value === "string")
43
+ out.add(value);
44
+ }
45
+ }
46
+ catch {
47
+ }
48
+ const principalHeader = readMember(transport, "principalHeader");
49
+ if (typeof principalHeader === "string" && principalHeader !== "" && principal !== undefined)
50
+ out.add(principal);
51
+ out.delete("");
52
+ return [...out];
53
+ }
54
+ function percentEncoded(value) {
55
+ try {
56
+ return encodeURIComponent(value);
57
+ }
58
+ catch {
59
+ return value;
60
+ }
61
+ }
62
+ const formEncoded = (value) => new URLSearchParams([["v", value]]).toString().slice(2);
63
+ function requestEchoSpellings(value) {
64
+ const sent = httpTrimmed(value);
65
+ const rest = authSchemeCredentials(sent);
66
+ const spellings = new Set();
67
+ for (const base of rest === undefined ? [value, sent] : [value, sent, rest]) {
68
+ const json = JSON.stringify(base).slice(1, -1);
69
+ const component = percentEncoded(base);
70
+ const form = formEncoded(base);
71
+ for (const spelling of [base, json, json.replace(/\//g, "\\/"), base.replace(/ /g, "+"), component, component.replace(/%20/g, "+"), form.replace(/\+/g, "%20"), form])
72
+ spellings.add(spelling);
73
+ }
74
+ return [...spellings];
75
+ }
76
+ const ECHO_MARKER = "[redacted]";
77
+ const COOKIE_START = String.raw `(?<![\w-])(?<cookie>(?:[Ss][Ee][Tt]-)?[Cc][Oo][Oo][Kk][Ii][Ee])(?<quote>["']?)[ \t]*:`;
78
+ function stringEnd(text, at) {
79
+ for (let i = at + 1; i < text.length; i++) {
80
+ if (text[i] === "\\")
81
+ i++;
82
+ else if (text[i] === text[at])
83
+ return i + 1;
84
+ }
85
+ return text.length;
86
+ }
87
+ function structuredEnd(text, at) {
88
+ const c = text[at];
89
+ if (c === '"' || c === "'")
90
+ return stringEnd(text, at);
91
+ if (c !== "[" && c !== "{") {
92
+ let i = at;
93
+ while (i < text.length && !",}]\r\n".includes(text[i]))
94
+ i++;
95
+ return i;
96
+ }
97
+ let depth = 0;
98
+ for (let i = at; i < text.length; i++) {
99
+ const d = text[i];
100
+ if (d === '"' || d === "'")
101
+ i = stringEnd(text, i) - 1;
102
+ else if (d === "[" || d === "{")
103
+ depth++;
104
+ else if ((d === "]" || d === "}") && --depth === 0)
105
+ return i + 1;
106
+ }
107
+ return text.length;
108
+ }
109
+ export function scrubRequestEcho(text, declared) {
110
+ const removed = requestEchoRanges(text, declared);
111
+ if (removed.length === 0)
112
+ return text;
113
+ removed.sort((a, b) => a[0] - b[0] || b[1] - a[1]);
114
+ let out = "";
115
+ let kept = 0;
116
+ for (const [start, end] of removed) {
117
+ if (start < kept) {
118
+ kept = Math.max(kept, end);
119
+ continue;
120
+ }
121
+ out += text.slice(kept, start) + ECHO_MARKER;
122
+ kept = end;
123
+ }
124
+ return out + text.slice(kept);
125
+ }
126
+ function requestEchoRanges(text, declared) {
127
+ const forms = new Set();
128
+ for (const value of declared)
129
+ for (const spelling of requestEchoSpellings(value))
130
+ forms.add(spelling);
131
+ forms.delete("");
132
+ const members = cookieMembers(text);
133
+ const removed = members.map(([, from, end]) => [from, end]);
134
+ const markers = redactionMarkerSpans(text);
135
+ for (const hit of valueHits(text, [...forms])) {
136
+ if (members.some(([name, from]) => hit[0] >= name && hit[1] <= from))
137
+ continue;
138
+ if (markers.some(([from, end]) => hit[0] >= from && hit[1] <= end))
139
+ continue;
140
+ const reach = markers.filter(([from, end]) => hit[0] < end && hit[1] > from);
141
+ removed.push([Math.min(hit[0], ...reach.map(([from]) => from)), Math.max(hit[1], ...reach.map(([, end]) => end))]);
142
+ }
143
+ return removed;
144
+ }
145
+ function vocabularyValues(text) {
146
+ const report = { findings: [] };
147
+ egressText("same-principal", text, report);
148
+ return report.findings.map(({ span: [from, end] }) => {
149
+ const found = text.slice(from, end);
150
+ const rendered = egressText("same-principal", found);
151
+ let head = 0;
152
+ while (head < found.length && head < rendered.length && found[head] === rendered[head])
153
+ head++;
154
+ let tail = 0;
155
+ while (tail < found.length - head && tail < rendered.length - head && found[found.length - 1 - tail] === rendered[rendered.length - 1 - tail])
156
+ tail++;
157
+ const value = found.slice(head, found.length - tail);
158
+ return value === "" ? found : value;
159
+ });
160
+ }
161
+ export function remoteWords(text, declared) {
162
+ if (requestEchoRanges(text, declared).length === 0)
163
+ return egressText("same-principal", text);
164
+ return egressText("same-principal", scrubRequestEcho(text, [...declared, ...vocabularyValues(text)]));
165
+ }
166
+ function cookieMembers(text) {
167
+ const members = [];
168
+ const pattern = new RegExp(COOKIE_START, "g");
169
+ for (let m = pattern.exec(text); m !== null; m = pattern.exec(text)) {
170
+ const structured = m.groups?.quote !== "";
171
+ let from = pattern.lastIndex;
172
+ while (from < text.length && (structured ? /\s/ : /[ \t]/).test(text[from]))
173
+ from++;
174
+ let end = from;
175
+ if (structured)
176
+ end = structuredEnd(text, from);
177
+ else
178
+ while (end < text.length && text[end] !== "\r" && text[end] !== "\n")
179
+ end++;
180
+ members.push([m.index, from, end]);
181
+ pattern.lastIndex = end;
182
+ }
183
+ return members;
184
+ }
185
+ function valueHits(text, forms) {
186
+ if (forms.length === 0 || text === "")
187
+ return [];
188
+ const alternatives = [...forms].sort((a, b) => b.length - a.length).map((f) => f.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
189
+ const hits = [];
190
+ try {
191
+ const pattern = new RegExp(alternatives.join("|"), "gi");
192
+ for (let m = pattern.exec(text); m !== null; m = pattern.exec(text))
193
+ hits.push([m.index, pattern.lastIndex]);
194
+ }
195
+ catch {
196
+ return [[0, text.length]];
197
+ }
198
+ return hits;
199
+ }
33
200
  export function carriesDeclaredHeaders(headers) {
34
201
  return headers !== undefined && Object.keys(headers).length > 0;
35
202
  }
36
- export function redirectPolicy(headers) {
37
- return carriesDeclaredHeaders(headers) ? "manual" : "follow";
38
- }
39
203
  export function assertEndpointBound(protocol, peer, endpoint, declared, headers) {
40
204
  if (!carriesDeclaredHeaders(headers))
41
205
  return;
@@ -60,6 +60,26 @@ export declare function findNamespacePrefixCollision(ns: ProtocolNamespace, peer
60
60
  prefix: string;
61
61
  peers: [string, string];
62
62
  } | undefined;
63
+ /**
64
+ * EVERY peer in `peers` that mints a {@link mintNamespacePrefix} an earlier peer already minted, in list order, each paired with the
65
+ * FIRST peer that holds the prefix — empty when every peer owns its own. {@link findNamespacePrefixCollision} is its first row: one
66
+ * piece of arithmetic answers both the question "is there a collision" and the question "which names, all of them".
67
+ */
68
+ export declare function findNamespacePrefixCollisions(ns: ProtocolNamespace, peers: readonly string[]): Array<{
69
+ prefix: string;
70
+ peers: [string, string];
71
+ }>;
72
+ /**
73
+ * One peer's claim ledger for tool names: the function it returns takes a REMOTE tool name, mints its wire name
74
+ * ({@link mintNamespacedToolName}) and answers `{ minted }` when the name is free, or `{ minted, heldBy }` when an earlier call
75
+ * already minted it — `heldBy` is the RAW name that took it first (it keeps the name; the ledger never re-binds). A listing's
76
+ * intake and a judge over declared names ask the same ledger; `heldBy === tool` (the same raw name again) stays distinguishable
77
+ * from two different raw names that folded together.
78
+ */
79
+ export declare function createToolNameClaims(ns: ProtocolNamespace, peer: string): (tool: string) => {
80
+ minted: string;
81
+ heldBy?: string;
82
+ };
63
83
  /**
64
84
  * The full registered name for `(peer, tool)` in `ns`. Always starts with {@link mintNamespacePrefix}'s
65
85
  * answer for the same peer (the invariant ticket #9's pins hold), and never exceeds
@@ -27,15 +27,32 @@ export function mintNamespacePrefix(ns, peer) {
27
27
  return `${ns.prefix}${settlePeerSegment(clampNameSegment(normalizeNameSegment(peer), peerBudget))}${NAME_SEP}`;
28
28
  }
29
29
  export function findNamespacePrefixCollision(ns, peers) {
30
+ return findNamespacePrefixCollisions(ns, peers)[0];
31
+ }
32
+ export function findNamespacePrefixCollisions(ns, peers) {
30
33
  const seen = new Map();
34
+ const collisions = [];
31
35
  for (const peer of peers) {
32
36
  const prefix = mintNamespacePrefix(ns, peer);
33
37
  const first = seen.get(prefix);
34
- if (first !== undefined)
35
- return { prefix, peers: [first, peer] };
38
+ if (first !== undefined) {
39
+ collisions.push({ prefix, peers: [first, peer] });
40
+ continue;
41
+ }
36
42
  seen.set(prefix, peer);
37
43
  }
38
- return undefined;
44
+ return collisions;
45
+ }
46
+ export function createToolNameClaims(ns, peer) {
47
+ const held = new Map();
48
+ return (tool) => {
49
+ const minted = mintNamespacedToolName(ns, peer, tool);
50
+ const heldBy = held.get(minted);
51
+ if (heldBy !== undefined)
52
+ return { minted, heldBy };
53
+ held.set(minted, tool);
54
+ return { minted };
55
+ };
39
56
  }
40
57
  export function mintNamespacedToolName(ns, peer, tool) {
41
58
  const prefix = mintNamespacePrefix(ns, peer);
@@ -8,6 +8,20 @@ export type ReadOnlyShellVerdict = {
8
8
  readonly readOnly: false;
9
9
  readonly reason: string;
10
10
  };
11
+ /** How a caller asks: a shape it already read, the session's working directory, the whole line's descriptor
12
+ * bindings when it judges one segment of a longer line, and the deployment's programs. */
13
+ export interface ReadOnlyShellOptions {
14
+ /** The command already read with {@link readShellCommand} (the gate reads every shell command once). */
15
+ readonly shape?: ShellCommandShape | undefined;
16
+ /** Where the session stands: a `cd` beside a `git` that lands here is no line objection. */
17
+ readonly cwd?: string | undefined;
18
+ /** The descriptor bindings of the WHOLE line, for a caller that judges one segment of it. */
19
+ readonly bound?: LineDescriptors | (() => LineDescriptors) | undefined;
20
+ /** The programs a deployment lets a face run: every program the line names (each segment's program past a `command` /
21
+ * `builtin` prefix, and the program an `xargs` segment hands its input to) must be one of them, else the
22
+ * line is not read-only for that face. It only ever narrows — a program here whose call writes is still not read-only. */
23
+ readonly readers?: ReadonlySet<string> | undefined;
24
+ }
11
25
  /** The reference implementation's question for a compound that changes directory and runs git (`cd-git-compound`). */
12
26
  export declare const CD_GIT_COMPOUND_SENTENCE = "This command changes directory before running a version-control command, which can pick up untrusted hooks or repository configuration from the target directory. Approve only if you trust it.";
13
27
  /**
@@ -17,8 +31,8 @@ export declare const CD_GIT_COMPOUND_SENTENCE = "This command changes directory
17
31
  */
18
32
  export declare function changesDirectoryBeforeGit(shape: ShellCommandShape, cwd?: string): boolean;
19
33
  /**
20
- * Read `command` as the allow layer must: read-only, or the first reason it is not. A shape already read by
21
- * the caller may be handed in (the gate reads every shell command once).
34
+ * Read `command` as every read-only consumer must: read-only, or the first reason it is not. A shape already read
35
+ * by the caller may be handed in (the gate reads every shell command once).
22
36
  *
23
37
  * @contract read_only_shell.every_segment — a command line is read-only iff the lexer reads it whole (no
24
38
  * unreadable segment, no group/subshell/control structure, no background `&`), no word anywhere carries a
@@ -30,10 +44,11 @@ export declare function changesDirectoryBeforeGit(shape: ShellCommandShape, cwd?
30
44
  * the exact forms, `echo`/`ls`/`cd`/`find`/`printf`/`history`/`arch`/`ifconfig`); else the flag-vetted
31
45
  * table with its per-row danger predicates, and the `uniq`/`jq` forms. A `cd` beside a `git` in one line
32
46
  * is never read-only (the git command's repository is then not the session's) unless the `cd` lands where the session
33
- * stands ({@link changesDirectoryBeforeGit}). Anything the reading does not positively admit is NOT read-only — the
34
- * answer is never a guess, and a `false` costs one question.
47
+ * stands ({@link changesDirectoryBeforeGit}). Given {@link ReadOnlyShellOptions.readers}, a program the line names
48
+ * outside them is an objection of its own, met where the reading meets the program. Anything the reading does not
49
+ * positively admit is NOT read-only — the answer is never a guess, and a `false` costs one question.
35
50
  */
36
- export declare function readOnlyShellVerdict(command: string, shape?: ShellCommandShape, cwd?: string, bound?: LineDescriptors | (() => LineDescriptors)): ReadOnlyShellVerdict;
51
+ export declare function readOnlyShellVerdict(command: string, opts?: ReadOnlyShellOptions): ReadOnlyShellVerdict;
37
52
  /**
38
53
  * The reader's LINE-level objection to `command` — what makes no segment of it read-only in its place, whatever the
39
54
  * segment reads on its own: the line's structure, or a `cd` beside a `git` ({@link changesDirectoryBeforeGit}). A caller
@@ -1,10 +1,12 @@
1
1
  import { posix } from "node:path";
2
2
  import { lexedWordOf, readShellCommand } from "./shell-run-candidates.js";
3
+ import { unlistedReaderSentence } from "../tools/fs/bash-readonly-classifier.js";
3
4
  import { descriptorsOfPlan, newLineDescriptors, standardDeviceUnrebound } from "../tools/fs/shell-read-device.js";
4
5
  import { planShellReads } from "../tools/fs/shell-read-plan.js";
5
6
  import { writesOnlyStandardDevices } from "../tools/fs/shell-read-write-targets.js";
6
7
  import { FIND_ACTION_PRIMARIES, FIND_NEWER_PRIMARY, FIND_VALUE_PRIMARIES, FLAG_VALUE_ACCEPTS, READ_ONLY_BARE_ONLY, READ_ONLY_BARE_PROGRAMS, READ_ONLY_COMMAND_TABLE, READ_ONLY_ENV_NAMES, READ_ONLY_EXACT_FORMS, READ_ONLY_GLOB_PROGRAMS, XARGS_READ_ONLY_TARGETS, dockerRetargetDanger, } from "./read-only-shell-table.js";
7
8
  const NOT = (reason) => ({ readOnly: false, reason });
9
+ const READ_ONLY = { readOnly: true };
8
10
  export const CD_GIT_COMPOUND_SENTENCE = "This command changes directory before running a version-control command, which can pick up untrusted hooks or repository configuration from the target directory. Approve only if you trust it.";
9
11
  export function changesDirectoryBeforeGit(shape, cwd) {
10
12
  const programs = shape.segments.map((s) => peelBuiltinPrefix(s.argv.slice(leadingAssignmentCount(s.argv)).map((w) => w.text))[0] ?? "");
@@ -20,7 +22,6 @@ export function changesDirectoryBeforeGit(shape, cwd) {
20
22
  const trim = (p) => p.replace(/\/+$/, "") || "/";
21
23
  return trim(posix.resolve(cwd, target.text)) !== trim(cwd);
22
24
  }
23
- const READ_ONLY = { readOnly: true };
24
25
  const BARE_PROGRAMS = new Set(READ_ONLY_BARE_PROGRAMS.filter((p) => !p.includes(" ")));
25
26
  const BARE_MULTIWORD = READ_ONLY_BARE_PROGRAMS.filter((p) => p.includes(" ")).map((p) => p.split(" "));
26
27
  const GLOB_PROGRAMS = new Set(READ_ONLY_GLOB_PROGRAMS);
@@ -41,7 +42,11 @@ const PRINTF_ESCAPE = new RegExp(`%[^%a-zA-Z]*${PRINTF_LENGTH}\\\\[0-7xX]`);
41
42
  const PRINTF_NUMERIC = new RegExp(`%[-+ 0#']*[0-9.*]*${PRINTF_LENGTH}[diouxXeEfFgGaAn]`);
42
43
  const JQ_DANGER_FLAG = /^['"]?-[a-zA-Z]*[fL]/;
43
44
  const JQ_DANGER_TEXT = /--from-file|--rawfile|--slurpfile|--run-tests|--library-path|\benv\b|\$ENV\b|\binclude\b|\bimport\b/;
44
- export function readOnlyShellVerdict(command, shape = readShellCommand(command), cwd, bound) {
45
+ export function readOnlyShellVerdict(command, opts = {}) {
46
+ const { cwd, bound, readers } = opts;
47
+ if (readers !== undefined && typeof readers.has !== "function")
48
+ throw new TypeError("readOnlyShellVerdict: `readers` must be a Set of program names");
49
+ const shape = opts.shape ?? readShellCommand(command);
45
50
  const line = lineStructureObjection(shape);
46
51
  if (line !== undefined)
47
52
  return NOT(line);
@@ -66,12 +71,15 @@ export function readOnlyShellVerdict(command, shape = readShellCommand(command),
66
71
  let boundOfText;
67
72
  const bindings = () => (boundOfText ??= (typeof bound === "function" ? bound() : bound) ?? lineDescriptorsOfText(command));
68
73
  for (const seg of shape.segments) {
69
- const verdict = segmentVerdict(seg, descriptors, bindings);
74
+ const verdict = segmentVerdict(seg, descriptors, bindings, readers);
70
75
  if (!verdict.readOnly)
71
76
  return verdict;
72
77
  }
73
78
  return READ_ONLY;
74
79
  }
80
+ function unlistedObjection(program, readers) {
81
+ return readers !== undefined && !readers.has(program) ? NOT(unlistedReaderSentence(program)) : undefined;
82
+ }
75
83
  const CD_GIT_REASON = "a compound that changes directory and runs git";
76
84
  function lineStructureObjection(shape) {
77
85
  if (shape.grouped)
@@ -144,16 +152,11 @@ function peelBuiltinPrefix(words) {
144
152
  return t;
145
153
  t = t.slice(r);
146
154
  }
147
- else if (t[0] === "noglob") {
148
- if (t.length <= 1)
149
- return t;
150
- t = t.slice(1);
151
- }
152
155
  else
153
156
  return t;
154
157
  }
155
158
  }
156
- function segmentVerdict(seg, line, bindings) {
159
+ function segmentVerdict(seg, line, bindings, readers) {
157
160
  for (const r of seg.redirections) {
158
161
  const target = r.target.text;
159
162
  if (!READING_REDIRECTS.has(r.op) && !standardDeviceUnrebound(target, line, []) && !(r.op === ">&" && /^\d+$/.test(target)))
@@ -174,6 +177,9 @@ function segmentVerdict(seg, line, bindings) {
174
177
  return NOT("a bare assignment runs no program");
175
178
  const words = peelBuiltinPrefix(run.map((w) => w.text));
176
179
  const program = words[0];
180
+ const unlisted = unlistedObjection(program, readers);
181
+ if (unlisted !== undefined)
182
+ return unlisted;
177
183
  if (run.some((w) => expansionKind(w) === "glob"))
178
184
  return GLOB_PROGRAMS.has(program) ? READ_ONLY : NOT(`\`${program}\` with a glob argument — the glob may name anything`);
179
185
  if (DEVICE_WRITERS.has(program) && writesOnlyStandardDevices(program, words.slice(1), bindings()))
@@ -181,7 +187,7 @@ function segmentVerdict(seg, line, bindings) {
181
187
  const structural = structuralReading(words);
182
188
  if (structural !== null)
183
189
  return structural ? READ_ONLY : NOT(`\`${program}\` with these arguments is not a read-only form`);
184
- return tableReading(words, run);
190
+ return tableReading(words, run, readers);
185
191
  }
186
192
  export function lineDescriptorsOfText(command) {
187
193
  return descriptorsOfPlan(planShellReads(command, { readers: new Set(), cwd: "/", roots: [] }));
@@ -248,7 +254,7 @@ function printfReading(words) {
248
254
  }
249
255
  return true;
250
256
  }
251
- function tableReading(words, run) {
257
+ function tableReading(words, run, readers) {
252
258
  const program = words[0];
253
259
  const hit = TABLE_ROWS.find((r) => words.length >= r.words.length && r.words.every((w, i) => words[i] === w));
254
260
  if (hit !== undefined) {
@@ -259,7 +265,8 @@ function tableReading(words, run) {
259
265
  if (a.includes("{") && (a.includes(",") || a.includes("..")))
260
266
  return NOT(`\`${program}\`: a brace pattern argument`);
261
267
  }
262
- if (!flagWalk(args, hit.row, program))
268
+ const named = [];
269
+ if (!flagWalk(args, hit.row, program, named))
263
270
  return NOT(`\`${program}\`: an option outside its read-only set (or a malformed option value)`);
264
271
  if (hit.row.wordsShape !== undefined ? !hit.row.wordsShape(args) : run.some((w) => w.raw.includes("`")))
265
272
  return NOT(`\`${program}\`: arguments outside its read-only form`);
@@ -267,6 +274,11 @@ function tableReading(words, run) {
267
274
  return NOT(`\`${program}\`: a line break inside an argument`);
268
275
  if (hit.row.dangerous?.(args) === true)
269
276
  return NOT(`\`${program}\`: an argument form upstream marks as writing, executing or resolving`);
277
+ for (const target of named) {
278
+ const unlisted = unlistedObjection(target, readers);
279
+ if (unlisted !== undefined)
280
+ return unlisted;
281
+ }
270
282
  return READ_ONLY;
271
283
  }
272
284
  if (program === "uniq" && words.slice(1).every((w, i, all) => /^-[a-zA-Z]+$/.test(w) || /^--[a-zA-Z-]+(=\S+)?$/.test(w) || (i > 0 && /^-[fsw]$/.test(all[i - 1]) && /^\d+$/.test(w))))
@@ -296,7 +308,7 @@ function jqReading(args) {
296
308
  }
297
309
  return true;
298
310
  }
299
- function flagWalk(args, row, program) {
311
+ function flagWalk(args, row, program, named) {
300
312
  let i = 0;
301
313
  while (i < args.length) {
302
314
  let word = args[i];
@@ -309,7 +321,10 @@ function flagWalk(args, row, program) {
309
321
  i++;
310
322
  word = args[i];
311
323
  }
312
- return XARGS_TARGETS.includes(word);
324
+ if (!XARGS_TARGETS.includes(word))
325
+ return false;
326
+ named.push(word);
327
+ return true;
313
328
  }
314
329
  if (word === "--") {
315
330
  if (row.respectsDoubleDash !== false)
@@ -323,7 +323,7 @@ export interface RemoteExecutionEnv extends ExecutionEnv {
323
323
  * `{isolation:true, suspendable:true}` adapter); **partial-capability** adapters (SSH/ADB: `{false, false}`
324
324
  * — a real machine/device, not snapshotable and not isolated) declare it here. **Required + explicit** so
325
325
  * the orchestrator never has to guess: there is no safe default (assuming isolation when there is none is a
326
- * security hole; assuming suspendable crashes on `suspendVM`). Use {@link isSuspendable}/{@link isIsolated}
326
+ * security hole; assuming suspendable crashes on `suspendVM`). Use {@link isSuspendable}/{@link isIsolated}/{@link processTableOf}
327
327
  * rather than the structural {@link isRemoteExecutionEnv} (method presence ≠ semantics — a stub `suspendVM`
328
328
  * that returns `"unsupported"` still satisfies the structural check). Extensible: add fields as new
329
329
  * partial-capability classes appear.
@@ -355,6 +355,29 @@ export interface RemoteExecutionEnv extends ExecutionEnv {
355
355
  * Read STRICTLY through {@link canonicalPathIsAuthoritative}, like every other capability whose
356
356
  * `true` changes what a containment leg does; a wrong-SHAPE value reads absent and is announced. */
357
357
  canonicalPathAuthoritative?: boolean;
358
+ /** True iff the commands this env runs are processes on a table that holds THIS process — the table the
359
+ * engine itself and the processes above it are on, so a kill the model writes there can reach them.
360
+ * `true` for an adapter that spawns the commands as this process's own descendants (a host lane), and
361
+ * for one whose commands run in a PID namespace that contains this process's (the host of the container
362
+ * the engine runs in); `false` only for one whose commands run where this process is not: another
363
+ * machine (SSH host, device, cloud sandbox) or a PID namespace this process is not in (a sandbox
364
+ * container, a pod). Not {@link isolation}: a non-isolated SSH host is a real machine and still another
365
+ * table. The self-preservation guard of the Bash tool asks its question exactly when this is `true`
366
+ * (and for every env that is not remote at all), and does not ask where it is `false`.
367
+ *
368
+ * What a `true` buys is the guard's question exactly as a NodeExecutionEnv gets it, limits included: on this
369
+ * process's own table, of the platform's `pgrep`, with the kill's words as written, from this process's own
370
+ * working directory. It is put as for this process's descendants, so for commands on the same table that
371
+ * are not (SSH to `localhost`) BSD's `pgrep` leaves its OWN caller's ancestors out where the real kill would
372
+ * not, and from an enclosing namespace the question sees only this process's namespace, not the ancestors
373
+ * above it.
374
+ *
375
+ * REQUIRED, with no default: either reading of an absent value is wrong somewhere (assuming `true`
376
+ * refuses an ordinary `pkill` in a sandbox because a word matched this engine here; assuming `false`
377
+ * lets a host lane's `pkill` end the session that issued it). So an absent or non-boolean value is
378
+ * announced once per run at the env's admission point and the guard refuses every pattern kill that needs the question on
379
+ * that env (`pkill -P $$` runs), naming this declaration, until the adapter states it. Read through {@link processTableOf}. */
380
+ sharesProcessTable: boolean;
358
381
  };
359
382
  /** Identity of the connected workspace (design/48 §5 gap 1). Synchronous: it is data the env already holds. */
360
383
  workspaceHandle(): WorkspaceHandle;
@@ -634,3 +657,16 @@ export declare function boundaryIsTheSandbox(env: ExecutionEnv): boolean;
634
657
  * has no case to fire on.
635
658
  */
636
659
  export declare function canonicalPathIsAuthoritative(env: ExecutionEnv): boolean;
660
+ /**
661
+ * Which process table this env's commands run on, as its adapter declares it
662
+ * ({@link RemoteExecutionEnv.capabilities}.sharesProcessTable):
663
+ * · `"this"` — a table that holds this process: a remote env that declares `true`, and every env that is not
664
+ * remote. The second is the base contract's in-process env (its commands are this process's children); an
665
+ * adapter that runs commands elsewhere without the remote seam has no block to declare in and is read the
666
+ * same way, which errs toward asking (a refusal of a kill that could not have reached this process);
667
+ * · `"other"` — a remote env that declares `false`;
668
+ * · `"undeclared"` — a remote env whose declaration is absent, not a boolean, or cannot be read (a throwing
669
+ * getter or Proxy trap). There is no default to fold it to, so the caller refuses what it cannot answer.
670
+ * Total: it never throws. It does not announce — the admission census does, once per run.
671
+ */
672
+ export declare function processTableOf(env: ExecutionEnv): "this" | "other" | "undeclared";
@@ -67,3 +67,14 @@ export function boundaryIsTheSandbox(env) {
67
67
  export function canonicalPathIsAuthoritative(env) {
68
68
  return isRemoteExecutionEnv(env) ? env.capabilities.canonicalPathAuthoritative === true : false;
69
69
  }
70
+ export function processTableOf(env) {
71
+ try {
72
+ if (!isRemoteExecutionEnv(env))
73
+ return "this";
74
+ const declared = env.capabilities.sharesProcessTable;
75
+ return declared === true ? "this" : declared === false ? "other" : "undeclared";
76
+ }
77
+ catch {
78
+ return "undeclared";
79
+ }
80
+ }
@@ -84,6 +84,28 @@ export type ReopenReasonTableCoversEveryCause = AssertAllKeysHandled<Exclude<Res
84
84
  * decision is untouched, and the retry replays it.
85
85
  */
86
86
  export declare function reopenReasonOf(cause: ResumeStartupCause | undefined): ReopenReason;
87
- /** What the result of a returned resume leg says after its checkpoint was reopened, per reason. */
88
- export declare function reopenedUnstartedSentence(reason: ReopenReason): string;
87
+ /**
88
+ * What happened to a claimed row whose approved action never started — the one closed outcome every exit of such a leg reports
89
+ * (the thrown-prepare backstop, the returned-leg settle, the post-claim abort): `reopened` under a reason (the row is pending again),
90
+ * `declined` (the store's `reopen` answered `false`: the row is no longer the resolved row this leg claimed — missing, expired, its
91
+ * decided action already disposed, or pending again — which the boolean does not say), `unknown` (the reopen threw: the write may have
92
+ * committed and only its acknowledgement been lost, so the row's state cannot be proven from here).
93
+ */
94
+ export type UnstartedRow = {
95
+ readonly kind: "reopened";
96
+ readonly reason: ReopenReason;
97
+ } | {
98
+ readonly kind: "declined";
99
+ } | {
100
+ readonly kind: "unknown";
101
+ readonly thrown: unknown;
102
+ };
103
+ /**
104
+ * THE compensation of a claimed leg whose approved action never started: the claim's reversal (`reopen`, bound to the row) asked once,
105
+ * under `reason`, and read into {@link UnstartedRow} — its answer, never a code sniffed off whatever it threw (a store's own error may
106
+ * carry any code, and a throw after a committed write is not a refusal). Every exit calls it; none re-reads the outcome another way.
107
+ */
108
+ export declare function compensateUnstarted(reopen: (reason: ReopenReason) => Promise<"reopened" | "declined">, reason: ReopenReason): Promise<UnstartedRow>;
109
+ /** The sentence for {@link UnstartedRow} — one per outcome, the same on every exit; the exit puts its own lead before it. */
110
+ export declare function unstartedRowSentence(row: UnstartedRow): string;
89
111
  export {};
@@ -1,3 +1,4 @@
1
+ import { egressThrownText } from "./untrusted-egress.js";
1
2
  export const REOPEN_REASONS = Object.freeze(["env_failed", "tool_unavailable", "constraint_rejected", "config_refused"]);
2
3
  export const RESUME_STARTUP_CAUSES = Object.freeze(["environment", "session_gone", "transcript_corrupt", "tool_unavailable", "configuration", "decision_rejected"]);
3
4
  const CAUSE_OF_CODE = new Map([
@@ -44,7 +45,25 @@ const REOPEN_REASON_OF_CAUSE = {
44
45
  export function reopenReasonOf(cause) {
45
46
  return cause === undefined ? "env_failed" : REOPEN_REASON_OF_CAUSE[cause];
46
47
  }
47
- export function reopenedUnstartedSentence(reason) {
48
+ export async function compensateUnstarted(reopen, reason) {
49
+ try {
50
+ return (await reopen(reason)) === "reopened" ? { kind: "reopened", reason } : { kind: "declined" };
51
+ }
52
+ catch (thrown) {
53
+ return { kind: "unknown", thrown };
54
+ }
55
+ }
56
+ export function unstartedRowSentence(row) {
57
+ switch (row.kind) {
58
+ case "reopened":
59
+ return reopenedUnstartedSentence(row.reason);
60
+ case "declined":
61
+ return "the approved action never started, and the store DECLINED to reopen the checkpoint — it is no longer the resolved row this leg claimed (missing, expired, its decided action already disposed, or pending again): read the row before deciding; if it is resolved or gone, a retry needs a fresh approval";
62
+ case "unknown":
63
+ return `the approved action never started, and reopening the checkpoint FAILED IN FLIGHT (${egressThrownText("same-principal", row.thrown)}) — its state UNKNOWN, unprovable from here: re-read it before deciding; do NOT issue a fresh approval on the assumption the old one is dead`;
64
+ }
65
+ }
66
+ function reopenedUnstartedSentence(reason) {
48
67
  switch (reason) {
49
68
  case "env_failed":
50
69
  return "the approved action never started, so the checkpoint was REOPENED (pending): the same approval can be resumed again, do not ask for a fresh one";
@@ -20,6 +20,14 @@ export declare function retiredKeyOf(bag: object, table: Readonly<Record<string,
20
20
  * `RunWorkflowToolDeps`, `TaskSpec`).
21
21
  */
22
22
  export declare function assertNoRetiredKeys(bag: object, table: Readonly<Record<string, string>>, owner: string): void;
23
+ /** The refusal {@link assertNoRetiredKeys} throws for a hit — the one sentence and code, for a caller that has to read the bag
24
+ * itself (to tell a refusal from a member that cannot be read) and must not read it a second time. */
25
+ export declare function retiredKeyRefusal(hit: {
26
+ key: string;
27
+ replacement: string;
28
+ }, owner: string): Error & {
29
+ code: string;
30
+ };
23
31
  /** What replaced the `hooks` record, on a deps bag and on a `TaskSpec` alike: one seat name, one sentence, quoted by both
24
32
  * tables (this one and `runner/retired-runner-deps.ts`). The record's callbacks never run, so a deny one carried would pass
25
33
  * unseen — the key is refused by name instead. */
@@ -29,6 +37,14 @@ export declare const RETIRED_HOOKS_REPLACEMENT = "the callback seats are `mods`
29
37
  * (`config.spec_retired_key`), never read as absence: a mode a caller believes it declared must not silently run
30
38
  * as another. */
31
39
  export declare const RETIRED_TASK_SPEC_KEYS: Readonly<Record<string, string>>;
40
+ /** The RETIRED `ToolSpec` members — a spec still carrying one is refused by name (`config.deps_retired_key`) where the
41
+ * factory reads the spec, never dropped unseen: a description the author wrote for one prompt shape would silently
42
+ * never be shown. */
43
+ export declare const RETIRED_TOOL_SPEC_KEYS: Readonly<Record<string, string>>;
44
+ /** The RETIRED {@link import("../engine/llm/types.js").Model} members — a model still carrying one is refused by name
45
+ * (`config.deps_retired_key`) at the model door, never read as absence: text a deployment believes it appended would
46
+ * silently not reach the model. */
47
+ export declare const RETIRED_MODEL_KEYS: Readonly<Record<string, string>>;
32
48
  /** The RETIRED `ToolPolicy` members — a policy still carrying one is refused by name (`config.deps_retired_key`) wherever
33
49
  * the engine reads a policy's members: the intake of the caller's policy (prepare, and a resume before its claim), the
34
50
  * by-name member reader the wrap and the path-rule installation share, and `combinePolicies`. A member the policy no
@@ -18,11 +18,13 @@ export function retiredKeyOf(bag, table) {
18
18
  }
19
19
  export function assertNoRetiredKeys(bag, table, owner) {
20
20
  const hit = retiredKeyOf(bag, table);
21
- if (hit === undefined)
22
- return;
21
+ if (hit !== undefined)
22
+ throw retiredKeyRefusal(hit, owner);
23
+ }
24
+ export function retiredKeyRefusal(hit, owner) {
23
25
  const e = new Error(`${owner}.${hit.key} is retired and is not read by this engine — ${hit.replacement}. Refused rather than ignored: a seat that is silently dropped reads to the deployment as wired.`);
24
26
  e.code = owner === "TaskSpec" ? "config.spec_retired_key" : "config.deps_retired_key";
25
- throw e;
27
+ return e;
26
28
  }
27
29
  export const RETIRED_HOOKS_REPLACEMENT = 'the callback seats are `mods` registrations now — register the extension on `RunnerDeps.mods` (a deployment\'s) or `TaskSpec.mods` (a task\'s), hung on the `classic.*` events (`classic.PreToolUse`, `classic.PostToolUse`, `classic.PostToolBatch`, `classic.UserPromptSubmit`, `classic.Stop`, `classic.SubagentStop`, …); a callback that denied is a handler answering `{ action: "deny", message }`';
28
30
  export const RETIRED_TASK_SPEC_KEYS = Object.freeze({
@@ -32,6 +34,13 @@ export const RETIRED_TASK_SPEC_KEYS = Object.freeze({
32
34
  "attachments.planModeReminder": "the read-only planning posture is stated whenever the leg's mode is `plan` (first turn, every 5 turns, and an exit frame when it ends) — drop the key",
33
35
  "skills[].manifest": "a skill's tools are its `allowedTools` / `disallowedTools` now — an allow-rule and a deny-rule source for the run the skill is activated in, never a fence; move `manifest.allowTools` to `allowedTools`. To fence tools write deny rules (or a delegated agent definition's `allowTools`); to fence write paths use session `allowDirs`",
34
36
  promptProvider: "a task changes prompt text through overlays: its role text is `systemPrompt` (it replaces the role base `promptRole` selects), its added block `appendSystemPrompt`, the minimal form `promptForm: \"minimal\"`; anything else is a `prompt.compose` registration on the task's own `mods` answering `{ overlays }` (an already-assembled prompt is refused, never passed through)",
37
+ promptProfile: 'the prompt\'s shape is the `lean_prompt` trait now — write `promptLean: false` for the long (classic) shape, `promptLean: true` (or nothing, on a model that declares `lean_prompt`) for the lean one',
38
+ });
39
+ export const RETIRED_TOOL_SPEC_KEYS = Object.freeze({
40
+ descriptionClassic: 'a description\'s other forms are `descriptionVariants` now — the long form is `{ id: "classic", traits: { noneOf: ["lean_prompt"] }, text }`, chosen at mount by the run\'s prompt traits',
41
+ });
42
+ export const RETIRED_MODEL_KEYS = Object.freeze({
43
+ promptGuidance: "a model selects prompt text by its traits now — declare them in `Model.promptTraits` (the reference's capability names, or a deployment's own `x-<namespace>-<name>`); text meant for one model is an overlay (a center artifact's `add` to the `behavior` band, or a `prompt.compose` registration) whose `when.traits.allOf` names that trait",
35
44
  });
36
45
  export const RETIRED_TOOL_POLICY_KEYS = Object.freeze({
37
46
  writeTargetGuard: "the guarded write targets are stated as rows now — `ToolPolicy.writeGuardRows`, an async provider of the one path table's `PathGuardRow`s the leg's ONE write judgment reads for every writer the policy cannot see as a call (the shell's file commands). A wrapper carries it through `wrapToolPolicy`, which reads every member a policy declares",
@@ -40,9 +49,12 @@ export const RETIRED_SHELL_READ_BOUNDARY_KEYS = Object.freeze({
40
49
  writeProtectionJudge: 'the station asks ONE write judgment, `ShellReadBoundary.writeTargetJudge`, over the write-protection table and the deployment\'s guarded write rows together — it answers `"protected"`, `"guarded"` or `undefined`, not a boolean',
41
50
  writeTargetGuard: 'the deployment\'s guarded write rows join the same one judgment, `ShellReadBoundary.writeTargetJudge` (`"guarded"` for a target a `ToolPolicy.writeGuardRows` row covers) — the boundary has no second write seat',
42
51
  });
52
+ const GUARDS_ARE_ENGINE_FINDINGS = "state `requiresRealApproval: true` for a person's confirmation — the integrity guards are the engine's findings, carried on its attestation record (install the engine's guard policy for one)";
43
53
  export const RETIRED_DECISION_MEMBERS = Object.freeze({
44
54
  reason: 'rename it to "message" (the one text field a decision carries)',
45
- guard: 'write `guards: ["<word>"]` instead (the same five words, as a list: one ask may stand on several integrity guards)',
55
+ guard: GUARDS_ARE_ENGINE_FINDINGS,
56
+ guards: GUARDS_ARE_ENGINE_FINDINGS,
57
+ foldedAskClasses: "the classes of the asks a policy fold collapsed ride the engine's attestation record that combinePolicies writes (a spread of its answer keeps the record); a policy does not state them",
46
58
  });
47
59
  export function assertNoRetiredToolPolicyKeys(policy) {
48
60
  if (policy === undefined || policy === null)