@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
@@ -2,18 +2,19 @@ import { existsSync, renameSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { writerOf } from "../../core/permission-rule-store.js";
4
4
  import { readRuleOwner, ruleOwnerText, sameRuleOwner } from "../../core/rule-owner.js";
5
+ import { principalNameOf } from "../../core/principal-name.js";
5
6
  import { createPermissionRuleStoreProvider } from "../../core/permission-rule-provider.js";
6
7
  import { syncPermissionRules } from "../../core/permission-rule-sync.js";
7
8
  import { thrownText } from "../../core/thrown-value.js";
8
9
  import { FileStoreLockError } from "./fs-atomic.js";
9
10
  import { FileDurableRulePartitionProvider, LOCAL_OWNER_FILE, principalRuleFileName, readRuleAdoptionFile, writeRuleAdoptionFile, } from "./permission-rule-store.js";
10
11
  export async function adoptFilePermissionRuleStore(opts) {
11
- if (typeof opts.toPrincipal !== "string" || opts.toPrincipal === "") {
12
- throw new Error("adoptFilePermissionRuleStore requires the adopting principal — adoption is the act of giving this bucket an identity");
12
+ if (principalNameOf(opts.toPrincipal) === undefined) {
13
+ throw new Error("adoptFilePermissionRuleStore requires the adopting principal, a principal name — adoption is the act of giving this bucket an identity");
13
14
  }
14
15
  const from = readRuleOwner(opts.from);
15
16
  if (from === undefined) {
16
- throw new Error("adoptFilePermissionRuleStore requires a source owner — a principal with a non-blank name, or the local owner");
17
+ throw new Error("adoptFilePermissionRuleStore requires a source owner — a principal owner whose principal is a principal name, or the local owner");
17
18
  }
18
19
  if (from.kind === "principal" && from.principal === opts.toPrincipal) {
19
20
  throw new Error(`the bucket already belongs to "${opts.toPrincipal}" — there is nothing to adopt`);
@@ -4,6 +4,7 @@ import { createHash, randomBytes } from "node:crypto";
4
4
  import { isRuleBehavior } from "../../core/permission-rule-model.js";
5
5
  import { posixModeBitsMeaningful } from "../../core/posix-mode-face.js";
6
6
  import { readRuleOwner } from "../../core/rule-owner.js";
7
+ import { principalNameOf, readPrincipal } from "../../core/principal-name.js";
7
8
  import { PERMISSION_RULES_LATER_GRAMMAR_CODE, PERMISSION_RULE_WRITER, applySyncJoin, applyTombstones, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, foldDelta, unknownRuleWriteDeltaError, } from "../../core/permission-rule-store.js";
8
9
  import { sameOrgPolicyContent } from "../../core/permission-rule-org.js";
9
10
  import { SESSION_RULES_GRAMMAR, readRuleGrammarStamp } from "../../core/session-policy-store.js";
@@ -66,7 +67,7 @@ function isRuleAdoptionFileShape(v) {
66
67
  const rec = (hasMarker ? v.marker : v.adopted);
67
68
  if (rec === null || typeof rec !== "object")
68
69
  return false;
69
- if (readRuleOwner(rec.from) === undefined || typeof rec.toPrincipal !== "string" || rec.toPrincipal === "")
70
+ if (readRuleOwner(rec.from) === undefined || principalNameOf(rec.toPrincipal) === undefined)
70
71
  return false;
71
72
  return hasMarker ? rec.phase === 2 || rec.phase === 3 || rec.phase === 4 || rec.phase === 5 : typeof rec.atMs === "number" && Number.isFinite(rec.atMs);
72
73
  }
@@ -452,17 +453,22 @@ export class FileDurableRulePartitionProvider {
452
453
  this.lock = lock;
453
454
  };
454
455
  forPrincipal(principal) {
455
- if (typeof principal !== "string" || principal === "") {
456
+ const reading = readPrincipal(principal);
457
+ if (reading.kind === "invalid") {
458
+ throw new Error(`the principal given is not a principal name (got ${reading.fault}) — refusing to resolve a bucket for it; a provided value that names nobody is not "no principal"`);
459
+ }
460
+ if (reading.kind === "absent") {
456
461
  return { list: async () => ({ ...EMPTY_READ }), durability: "process-local" };
457
462
  }
463
+ const name = reading.name;
458
464
  const adoption = this.adoptionMarker();
459
465
  if (adoption !== undefined) {
460
466
  const rec = "adopted" in adoption ? adoption.adopted : adoption.marker;
461
- if (rec.from.kind === "principal" && rec.from.principal === principal) {
462
- return this.readOnlySourceView(principalRuleFileName(principal), principalRuleFileName(rec.toPrincipal), "adopted" in adoption || adoption.marker.phase >= 4);
467
+ if (rec.from.kind === "principal" && rec.from.principal === name) {
468
+ return this.readOnlySourceView(principalRuleFileName(name), principalRuleFileName(rec.toPrincipal), "adopted" in adoption || adoption.marker.phase >= 4);
463
469
  }
464
470
  }
465
- return new FileDurableRulePartition(this.dir, join(this.dir, principalRuleFileName(principal)), this.acquireWriteLock, this.onError, this.vetting);
471
+ return new FileDurableRulePartition(this.dir, join(this.dir, principalRuleFileName(name)), this.acquireWriteLock, this.onError, this.vetting);
466
472
  }
467
473
  readOnlySourceView(sourceName, targetName, flipped) {
468
474
  const pick = flipped ? targetName : existsSync(join(this.dir, sourceName)) ? sourceName : targetName;
@@ -1,4 +1,4 @@
1
- import type { Session, SessionCreateOptions, SessionForkOptions, SessionHead, SessionMetadata, SessionPlacementRecord, SessionRepo, SessionTreeEntry } from "../../internal/harness.js";
1
+ import type { Session, SessionCreateOptions, SessionForkOptions, SessionHead, SessionMetadata, SessionPlacementRecord, SessionRepo, SessionRow, SessionTreeEntry } from "../../internal/harness.js";
2
2
  import type { PlacedSessionRow } from "../../core/session.js";
3
3
  import { type CorruptReadInfo } from "./corrupt-read-sink.js";
4
4
  export interface FileSessionRepoOptions {
@@ -8,8 +8,9 @@ export interface FileSessionRepoOptions {
8
8
  * "corrupt read as missing" are one failure grammar, so they get one seat name.
9
9
  *
10
10
  * Fires for: an unreadable sessions DIRECTORY (the listing degrades to "no sessions"), a session log
11
- * that could not be replayed during a listing (skipped from the result), and each corrupt interior JSONL
12
- * record dropped on replay plus that replay's tally (turns missing from an otherwise healthy session).
11
+ * whose header could not be read during a listing (skipped from the result — a listing reads headers,
12
+ * it never replays a log), and each corrupt interior JSONL record dropped on replay plus that replay's
13
+ * tally (turns missing from an otherwise healthy session).
13
14
  *
14
15
  * Never fires on plain ENOENT / `not_found` — that is honest absence, and the torn TAIL stays silent
15
16
  * too (dying mid-write is the append log's documented crash-recovery shape, not corruption).
@@ -59,6 +60,15 @@ export declare class FileSessionRepo implements SessionRepo {
59
60
  * head does not see. A leaf entry naming an id the log does not hold is not checked here (a replay refuses that log on open).
60
61
  */
61
62
  headOf(sessionId: string): Promise<SessionHead | undefined>;
63
+ /**
64
+ * The row's {@link SessionRow} — its header cells and the newest write it holds, the log's modification time (every write to a row
65
+ * is an append to its log; the placed listing's age reads the same time) — in one read of the header, never a replay of the log.
66
+ * `undefined` = no row; a row whose header cannot be read rejects (`corrupt_session`).
67
+ */
68
+ private rowOf;
69
+ /** The one descriptor a by-id read of the row takes: its size and modification time and its header, from one inode (a file replaced
70
+ * or removed while this reads is still the inode this descriptor opened); `undefined` = no file. */
71
+ private atRow;
62
72
  private storage;
63
73
  /**
64
74
  * RB-437 — release every shared authority this repo joined (LAST holder ⇒ evict + close the append fd).
@@ -75,12 +85,25 @@ export declare class FileSessionRepo implements SessionRepo {
75
85
  dispose(): Promise<void>;
76
86
  create(options?: SessionCreateOptions): Promise<Session>;
77
87
  open(metadata: SessionMetadata): Promise<Session>;
78
- list(): Promise<SessionMetadata[]>;
88
+ /** Record activity on the row now: its log's modification time — the one time a listing reads, which every append moves too — is
89
+ * set to now, the log's bytes untouched. A missing file is nothing to record; any other fault rejects. */
90
+ touch(sessionId: string): Promise<void>;
91
+ /** Every ordinary row with the newest write its log holds ({@link rowOf}): one header read per session file, no replay — what a
92
+ * listing costs grows with the number of sessions, never with their history. Placed rows are the placed listing's. */
93
+ list(): Promise<SessionRow[]>;
94
+ /**
95
+ * Every row of the sessions directory, each read by {@link rowOf}. The listing degrades to "no sessions" so a
96
+ * browse face never throws — but "I could not read the directory" and "there are none" are different facts, and only the sink can
97
+ * tell them apart (ENOENT is honest absence: the constructor creates the directory, so it was removed underneath us). A session
98
+ * whose header cannot be read is skipped and disclosed — it exists and is missing from the listing — while a file that vanished
99
+ * between the directory read and its own is honest absence.
100
+ */
101
+ private rows;
79
102
  /**
80
103
  * Subagent transcript persistence — the PLACED partition's own enumeration (the joint reap's
81
104
  * partition-leg input; `TtlSessionStore` re-exposes it verbatim). Age (`olderThanMs`) is judged on
82
- * the session FILE's mtime — the transcript's last append — falling back to `placedAt` when the
83
- * stat fails (mtime is also the CC orphan-adoption window's basis, so the two age reads agree).
105
+ * the session FILE's mtime — the transcript's last append, the time the host listing reads too
106
+ * (mtime is also the CC orphan-adoption window's basis, so the age reads agree).
84
107
  * Rows missing either `(scope, handle)` join half return the honest `tupleIncomplete` variant
85
108
  * (consumers fail closed on it — never age-reaped, see the SessionStore contract).
86
109
  */
@@ -1,4 +1,4 @@
1
- import { closeSync, existsSync, fstatSync, openSync, readdirSync, rmSync, statSync } from "node:fs";
1
+ import { closeSync, existsSync, fstatSync, openSync, readdirSync, rmSync, utimesSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { BaseSessionStorage, StoredSession, SessionError, assertForkTarget, compareOccupants, forkRowCells, frozenRow, getEntriesToFork, importRowCells, incarnationCell, leafIdAfterEntry, ownerCell, readIncarnationCell, readOwnerCell, uuidv7, validateEntriesForImport, } from "../../internal/harness.js";
4
4
  import { canonicalStoreKey, AppendLog, atomicWriteFile, ensureDir, firstJsonlRecord, lastJsonlRecord, readJsonlRecords, sanitizePathComponent, writeThenLink } from "./fs-atomic.js";
@@ -125,6 +125,15 @@ export class FileSessionRepo {
125
125
  };
126
126
  }
127
127
  async headOf(sessionId) {
128
+ return this.atRow(sessionId, (fd, size, meta) => {
129
+ const last = lastJsonlRecord(fd, size, (r) => r.kind === "entry", SESSION_LINE_JUDGE);
130
+ return { owner: meta.owner ?? null, incarnation: meta.incarnation, leafId: last === undefined ? null : leafIdAfterEntry(last.entry) };
131
+ });
132
+ }
133
+ rowOf(sessionId) {
134
+ return this.atRow(sessionId, (_fd, _size, meta, mtimeMs) => ({ ...meta, lastActiveAt: Math.trunc(mtimeMs) }));
135
+ }
136
+ atRow(sessionId, read) {
128
137
  const path = this.pathFor(sessionId);
129
138
  let fd;
130
139
  try {
@@ -136,10 +145,8 @@ export class FileSessionRepo {
136
145
  throw err;
137
146
  }
138
147
  try {
139
- const size = fstatSync(fd).size;
140
- const meta = this.headerOf(sessionId, path, firstJsonlRecord(fd, size, SESSION_LINE_JUDGE));
141
- const last = lastJsonlRecord(fd, size, (r) => r.kind === "entry", SESSION_LINE_JUDGE);
142
- return { owner: meta.owner ?? null, incarnation: meta.incarnation, leafId: last === undefined ? null : leafIdAfterEntry(last.entry) };
148
+ const { size, mtimeMs } = fstatSync(fd);
149
+ return read(fd, size, this.headerOf(sessionId, path, firstJsonlRecord(fd, size, SESSION_LINE_JUDGE)), mtimeMs);
143
150
  }
144
151
  finally {
145
152
  closeSync(fd);
@@ -201,80 +208,65 @@ export class FileSessionRepo {
201
208
  const { meta, entries } = this.read(metadata.id);
202
209
  return new StoredSession(this.storage(meta, entries));
203
210
  }
204
- async list() {
205
- let names;
211
+ async touch(sessionId) {
212
+ const now = new Date();
206
213
  try {
207
- names = readdirSync(this.dir);
214
+ utimesSync(this.pathFor(sessionId), now, now);
208
215
  }
209
216
  catch (err) {
210
- if (err.code !== "ENOENT") {
211
- this.disclose(this.dir, `session directory unreadable (${err.code ?? "unknown"}) — listed as empty`);
212
- }
213
- return [];
214
- }
215
- const out = [];
216
- for (const name of names) {
217
- if (!name.endsWith(SUFFIX))
218
- continue;
219
- const id = name.slice(0, -SUFFIX.length);
220
- try {
221
- const { createdAt, forkedFrom, placement } = this.read(id).meta;
222
- if (placement !== undefined)
223
- continue;
224
- out.push({ id, createdAt, ...(forkedFrom !== undefined ? { forkedFrom } : {}) });
225
- }
226
- catch (err) {
227
- if (!(err instanceof SessionError && err.code === "not_found")) {
228
- this.disclose(this.pathFor(id), `session log unreadable (${thrownText(err)}) — skipped from the listing`, id);
229
- }
230
- }
217
+ if (err.code === "ENOENT")
218
+ return;
219
+ throw new SessionError("storage", `session ${sessionId}'s activity could not be recorded: ${thrownText(err)}`, err instanceof Error ? err : undefined);
231
220
  }
232
- return out.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
233
221
  }
234
- async listPlaced(kind, opts) {
222
+ async list() {
223
+ return this.rows("the listing")
224
+ .filter((row) => row.placement === undefined)
225
+ .sort((a, b) => a.createdAt.localeCompare(b.createdAt));
226
+ }
227
+ rows(listing) {
235
228
  let names;
236
229
  try {
237
230
  names = readdirSync(this.dir);
238
231
  }
239
232
  catch (err) {
240
233
  if (err.code !== "ENOENT") {
241
- this.disclose(this.dir, `session directory unreadable (${err.code ?? "unknown"}) — placed listing degraded to empty`);
234
+ this.disclose(this.dir, `session directory unreadable (${err.code ?? "unknown"}) — ${listing} degraded to empty`);
242
235
  }
243
236
  return [];
244
237
  }
245
- const now = Date.now();
246
238
  const out = [];
247
239
  for (const name of names) {
248
240
  if (!name.endsWith(SUFFIX))
249
241
  continue;
250
242
  const id = name.slice(0, -SUFFIX.length);
251
- let placement;
243
+ let row;
252
244
  try {
253
- placement = this.read(id).meta.placement;
245
+ row = this.rowOf(id);
254
246
  }
255
247
  catch (err) {
256
- if (!(err instanceof SessionError && err.code === "not_found")) {
257
- this.disclose(this.pathFor(id), `session log unreadable (${thrownText(err)}) — skipped from the placed listing`, id);
258
- }
248
+ this.disclose(this.pathFor(id), `session log unreadable (${thrownText(err)}) — skipped from ${listing}`, id);
259
249
  continue;
260
250
  }
251
+ if (row !== undefined)
252
+ out.push(row);
253
+ }
254
+ return out;
255
+ }
256
+ async listPlaced(kind, opts) {
257
+ const now = Date.now();
258
+ const out = [];
259
+ for (const row of this.rows("the placed listing")) {
260
+ const placement = row.placement;
261
261
  if (placement === undefined || placement.kind !== kind)
262
262
  continue;
263
263
  if (opts?.scope !== undefined && placement.scope !== opts.scope)
264
264
  continue;
265
- if (opts?.olderThanMs !== undefined) {
266
- let ageAnchor = placement.placedAt;
267
- try {
268
- ageAnchor = statSync(this.pathFor(id)).mtimeMs;
269
- }
270
- catch {
271
- }
272
- if (now - ageAnchor <= opts.olderThanMs)
273
- continue;
274
- }
265
+ if (opts?.olderThanMs !== undefined && now - row.lastActiveAt <= opts.olderThanMs)
266
+ continue;
275
267
  out.push(placement.scope !== undefined && placement.handle !== undefined
276
- ? { sessionId: id, placedAt: placement.placedAt, scope: placement.scope, handle: placement.handle }
277
- : { sessionId: id, placedAt: placement.placedAt, tupleIncomplete: true });
268
+ ? { sessionId: row.id, placedAt: placement.placedAt, scope: placement.scope, handle: placement.handle }
269
+ : { sessionId: row.id, placedAt: placement.placedAt, tupleIncomplete: true });
278
270
  }
279
271
  return out;
280
272
  }
@@ -9,7 +9,7 @@ const ARTIFACT_ACTION_LEGS = {
9
9
  "local-stub": { publish: ["env"], list: [], read: [], list_files: [], read_file: [] },
10
10
  };
11
11
  import { ARTIFACT_TOOL_NAME, mountRuleFace, toolFace } from "../../core/tool-catalog-entries.js";
12
- import { resolveAsk } from "../../core/tool-policy.js";
12
+ import { attest, resolveAsk } from "../../core/tool-policy.js";
13
13
  import { NOT_BINDABLE } from "../../core/skill-grant-binding.js";
14
14
  import { approvalCardOf } from "../../core/tool-roster.js";
15
15
  import { errorResult } from "../../core/tools.js";
@@ -328,7 +328,8 @@ export function createArtifactTool(opts) {
328
328
  if (sharedReadApproved.has(url))
329
329
  return Promise.resolve({ ok: true });
330
330
  if (permissionMode !== undefined) {
331
- const verdict = arbitrateByMode(permissionMode(), classifyAsk({ action: "ask", requiresRealApproval: true, guards: ["artifact_shared_read"] }, { contentQuestion: false, markedUnresolvable: false, org: undefined, tightened: undefined, mandateMarks: {} }));
331
+ const call = { toolCallId: ctx.toolCallId, toolName: ARTIFACT_TOOL_NAME };
332
+ const verdict = arbitrateByMode(permissionMode(), classifyAsk(attest({ action: "ask", requiresRealApproval: true }, call, { guards: ["artifact_shared_read"] }), { call, contentQuestion: false, markedUnresolvable: false, org: undefined, tightened: undefined, mandateMarks: {} }));
332
333
  if (verdict.kind === "released") {
333
334
  if (!releaseAnnounced && onNotice !== undefined) {
334
335
  releaseAnnounced = true;
@@ -39,14 +39,27 @@ export declare const LOOP_LIST_HEADS: ReadonlySet<string>;
39
39
  * over control words and earlier assignments re-traces). One fact, two readers that must agree.
40
40
  */
41
41
  export declare function isLeadingAssignmentWord(words: readonly LexedWord[], i: number): boolean;
42
- export declare const PROGRAM_POSITION_REFUSAL_KINDS: readonly ["option_at_program_position", "control_syntax_at_program_position"];
42
+ export declare const PROGRAM_POSITION_REFUSAL_KINDS: readonly ["option_at_program_position", "control_syntax_at_program_position", "wildcard_program_word"];
43
43
  export type ProgramPositionRefusalKind = (typeof PROGRAM_POSITION_REFUSAL_KINDS)[number];
44
44
  /** Why the program could not be read — a closed set, each member minted into one sentence. `owner` is the word
45
45
  * that took the offending token: the control word or the first launcher of the chain. */
46
- export type ProgramPositionRefusal = {
46
+ export type ProgramPositionRefusal =
47
+ /** `endedBy`: the launcher whose bare `--` ended its options before this word — the word is then no option of anyone's
48
+ * but a name spelled like one (`env -- -i ls` runs a program named `-i`), and the sentence says that, not "the option". */
49
+ {
47
50
  readonly kind: "option_at_program_position";
48
51
  readonly owner: string;
49
52
  readonly option: string;
53
+ readonly endedBy?: string;
54
+ }
55
+ /** The program word carries an unquoted glob (`s[h]`, `s*h`, `./c?t`): the shell expands it against the filesystem,
56
+ * so which program runs — a shell among them — is not readable from the text (`touch sh; s[h] -c '…'`). `word` is the
57
+ * word as written, `at` its argv index (the words AFTER it are still handed over, so a deny operand still refuses).
58
+ * Both faces ask, the same as any unreadable program position. */
59
+ | {
60
+ readonly kind: "wildcard_program_word";
61
+ readonly word: string;
62
+ readonly at: number;
50
63
  } | {
51
64
  readonly kind: "control_syntax_at_program_position";
52
65
  readonly owner: string;
@@ -130,3 +143,7 @@ export declare function programPositionRunsShell(pos: ProgramPosition, runsShell
130
143
  export declare function shellScanDeclineOf(pos: ProgramPosition, acceptsStreamTarget: (basename: string) => boolean): ShellScanDecline | undefined;
131
144
  /** ONE sentence per refusal kind, minted here and nowhere else. */
132
145
  export declare function programPositionRefusalSentence(refusal: ProgramPositionRefusal): string;
146
+ /** The sentence a segment whose program the walk DECLINED carries, read off the segment's text — the program-position reader's own
147
+ * refusal, the stream fact, or that no program could be named: the read station's account of the segment and the removal guard's
148
+ * are this one sentence. */
149
+ export declare function declinedProgramSentence(text: string): string;
@@ -1,4 +1,4 @@
1
- import { SHELL_CONTROL_PREFIXES } from "../../shell/lex.js";
1
+ import { SHELL_CONTROL_PREFIXES, argvOf, lexShellText } from "../../shell/lex.js";
2
2
  import { shellWordsOf } from "../../shell/shell-words.js";
3
3
  import { BLOCK_WORD_NAMES, LAUNCHER_NAMES, feedsArgvFromStdin, launcherOptionMovesBase, launcherOptionQueries, launcherOptionStep, launcherRunsShell, programRow, selectedOptions, streamDefaultProgram } from "./program-read-model.js";
4
4
  export const NOT_AUTO_ALLOWED = "— not auto-allowed";
@@ -31,7 +31,7 @@ function launcherRowOf(name) {
31
31
  const row = programRow(name);
32
32
  return row?.launcher !== undefined ? row : undefined;
33
33
  }
34
- function pastLauncherOptions(launcher, folded, i, moved, queried) {
34
+ function pastLauncherOptions(launcher, folded, i, moved, queried, ended) {
35
35
  const row = launcherRowOf(launcher);
36
36
  if (row === undefined)
37
37
  return i;
@@ -53,14 +53,19 @@ function pastLauncherOptions(launcher, folded, i, moved, queried) {
53
53
  if (launcherOptionQueries(row, tok))
54
54
  queried?.();
55
55
  i += step;
56
- if (tok === "--")
56
+ if (tok === "--") {
57
+ ended?.();
57
58
  return i;
59
+ }
58
60
  }
59
61
  }
60
- export const PROGRAM_POSITION_REFUSAL_KINDS = Object.freeze(["option_at_program_position", "control_syntax_at_program_position"]);
62
+ export const PROGRAM_POSITION_REFUSAL_KINDS = Object.freeze(["option_at_program_position", "control_syntax_at_program_position", "wildcard_program_word"]);
61
63
  export function readProgramPosition(words) {
62
64
  const folded = words.map((w) => w.folded);
63
65
  const controlWords = [];
66
+ const ended = { by: undefined };
67
+ const endsOptions = (name) => () => { ended.by = name; };
68
+ const optionShaped = (owner, option) => ({ kind: "option_at_program_position", owner, option, ...(ended.by !== undefined ? { endedBy: ended.by } : {}) });
64
69
  let i = 0;
65
70
  while (i < folded.length && isBareControlWord(words, i, SHELL_CONTROL_PREFIXES)) {
66
71
  const controlWord = folded[i];
@@ -68,6 +73,23 @@ export function readProgramPosition(words) {
68
73
  i = pastLauncherOptions(controlWord, folded, i + 1);
69
74
  }
70
75
  const none = (written, assignments, refusal) => ({ controlWords, written, assignments, launchers: [], argvFromStdin: false, runsDefaultProgram: false, program: undefined, refusal, launcherMovesBase: false });
76
+ const globProgramRefusal = (idx) => {
77
+ let glob = false;
78
+ for (const p of words[idx].pieces) {
79
+ const k = p.expansion?.kind;
80
+ if (k === "process" || k === "brace")
81
+ return undefined;
82
+ if (k === "glob")
83
+ glob = true;
84
+ if (p.literal !== undefined) {
85
+ if (p.quotedBy === undefined && /[{}$`]/.test(p.literal))
86
+ return undefined;
87
+ if (p.quotedBy === '"' && /[$`]/.test(p.literal))
88
+ return undefined;
89
+ }
90
+ }
91
+ return glob ? { kind: "wildcard_program_word", word: folded[idx], at: idx } : undefined;
92
+ };
71
93
  if (i >= folded.length)
72
94
  return none(undefined, []);
73
95
  const written = i;
@@ -82,9 +104,12 @@ export function readProgramPosition(words) {
82
104
  const basename = programBasename(head);
83
105
  if (basename.startsWith("-") && basename !== "-") {
84
106
  const owner = controlWords.length > 0 ? folded[controlWords[controlWords.length - 1]] : head;
85
- return none(written, assignments, { kind: "option_at_program_position", owner, option: head });
107
+ return none(written, assignments, optionShaped(owner, head));
86
108
  }
87
109
  if (!LAUNCHER_NAMES.has(basename)) {
110
+ const glob = globProgramRefusal(i);
111
+ if (glob !== undefined)
112
+ return none(written, assignments, glob);
88
113
  return { controlWords, written, assignments, launchers: [], argvFromStdin: false, runsDefaultProgram: false, program: { index: i, name: head, basename }, refusal: undefined, launcherMovesBase: false };
89
114
  }
90
115
  const launchers = [{ index: i, name: basename }];
@@ -107,7 +132,7 @@ export function readProgramPosition(words) {
107
132
  return { controlWords, written, assignments, launchers, argvFromStdin, runsDefaultProgram, ...(runsDefaultProgram && reentryDefault !== undefined ? { defaultProgram: reentryDefault } : {}), program, refusal, launcherMovesBase };
108
133
  };
109
134
  const selectsShell = (l, end) => selectedOptions(launcherRowOf(l.name), folded.slice(l.index + 1, end)).some((o) => o.mode === "interactive");
110
- const first = pastLauncherOptions(basename, folded, i + 1, moved, queried);
135
+ const first = pastLauncherOptions(basename, folded, i + 1, moved, queried, endsOptions(basename));
111
136
  if (looksUp)
112
137
  return chain(undefined);
113
138
  for (let j = first; j < folded.length; j++) {
@@ -127,6 +152,7 @@ export function readProgramPosition(words) {
127
152
  reentryDefault = streamDefaultProgram(wordBasename);
128
153
  lastRow = undefined;
129
154
  owedOperands = 0;
155
+ ended.by = undefined;
130
156
  continue;
131
157
  }
132
158
  if (LAUNCHER_NAMES.has(wordBasename)) {
@@ -135,16 +161,20 @@ export function readProgramPosition(words) {
135
161
  if (launcherRunsShell(launcherRowOf(wordBasename), folded.slice(j + 1)))
136
162
  return chain(undefined, shellRefusal(j, j + 1));
137
163
  owedOperands = lastRow?.requiredOperands ?? 0;
138
- j = pastLauncherOptions(wordBasename, folded, j + 1, moved, queried) - 1;
164
+ ended.by = undefined;
165
+ j = pastLauncherOptions(wordBasename, folded, j + 1, moved, queried, endsOptions(wordBasename)) - 1;
139
166
  if (looksUp)
140
167
  return chain(undefined);
141
168
  continue;
142
169
  }
143
170
  if (t.startsWith("-"))
144
- return chain(undefined, { kind: "option_at_program_position", owner, option: t });
171
+ return chain(undefined, optionShaped(owner, t));
145
172
  if (SHELL_CONTROL_PREFIXES.has(wordBasename) || BLOCK_WORD_NAMES.has(wordBasename)) {
146
173
  return chain(undefined, { kind: "control_syntax_at_program_position", owner, word: wordBasename });
147
174
  }
175
+ const glob = globProgramRefusal(j);
176
+ if (glob !== undefined)
177
+ return chain(undefined, glob);
148
178
  return chain({ index: j, name: t, basename: wordBasename });
149
179
  }
150
180
  const last = launchers[launchers.length - 1];
@@ -173,12 +203,29 @@ export function shellScanDeclineOf(pos, acceptsStreamTarget) {
173
203
  export function programPositionRefusalSentence(refusal) {
174
204
  switch (refusal.kind) {
175
205
  case "option_at_program_position":
176
- return `"${refusal.owner}" is given the option "${refusal.option}" where the program it runs would be — which program runs is not readable without that word's option table ${NOT_AUTO_ALLOWED}`;
206
+ return refusal.endedBy !== undefined
207
+ ? `"${refusal.endedBy} --" ends the options, and "${refusal.option}" after it is a name spelled like an option where the program it runs would be — which program runs is not read from such a word ${NOT_AUTO_ALLOWED}`
208
+ : `"${refusal.owner}" is given the option "${refusal.option}" where the program it runs would be — which program runs is not readable without that word's option table ${NOT_AUTO_ALLOWED}`;
177
209
  case "control_syntax_at_program_position":
178
210
  return `"${refusal.owner}" is given shell control syntax ("${refusal.word}") where the program it runs would be ${NOT_AUTO_ALLOWED}`;
211
+ case "wildcard_program_word":
212
+ return `the program word "${refusal.word}" carries an unquoted filename pattern, so the shell expands it against the filesystem and which program runs is not readable from the text ${NOT_AUTO_ALLOWED}`;
179
213
  default: {
180
214
  const exhaustive = refusal;
181
215
  return exhaustive;
182
216
  }
183
217
  }
184
218
  }
219
+ export function declinedProgramSentence(text) {
220
+ const lexed = lexShellText(text);
221
+ if (!("reject" in lexed) && lexed.segments[0] !== undefined) {
222
+ const pos = readProgramPosition(argvOf(lexed.segments[0]));
223
+ if (pos.refusal !== undefined)
224
+ return programPositionRefusalSentence(pos.refusal);
225
+ if (pos.argvFromStdin) {
226
+ const runs = pos.program?.basename ?? "the program it runs";
227
+ return `"${text.trim()}" hands ${runs} its operands on its standard input, which this station does not read ${NOT_AUTO_ALLOWED}`;
228
+ }
229
+ }
230
+ return `"${text.trim()}" runs a program this station cannot name ${NOT_AUTO_ALLOWED}`;
231
+ }
@@ -2,15 +2,15 @@ import { type LexedCommand, type LexedSegment, type LexedWord, type ShellLex, ty
2
2
  import { type ProgramRow } from "./program-read-model.js";
3
3
  /**
4
4
  * Bare command names `bash_readonly` permits out of the box, ALSO the default reversible set for the
5
- * The {@link import("./fs-bash.js").bashReversibilityProbe} classifier. **Coarse first filter, NOT a security
6
- * boundary**: {@link coarseReadonlyCheck} matches only the command NAME, so a listed command with a
7
- * writing flag (e.g. `find -delete`, `sort -o`, `tee`) would still write. Such commands are therefore
8
- * kept OFF this default — the list is curated to commands with NO write/mutation mode under ANY args, so
9
- * the `effect:"read"` declaration (relied on by wake/resume reconcile + the verifier read-only boundary)
10
- * AND the classifier's "reversible" promise both stay truthful. The deployment's tool-policy gate is the
11
- * authoritative control (council blocker #1); anything that can mutate state or run arbitrary
12
- * code belongs on the full `bash` (effect:write, gated), not here. A deployment may widen this list,
13
- * accepting that responsibility.
5
+ * {@link import("./fs-bash.js").bashReversibilityProbe} classifier. On the read-only face and in the transcript gate the
6
+ * list only NARROWS the read-only reader ({@link import("../../core/read-only-shell.js").readOnlyShellVerdict}'s
7
+ * `readers`): a listed program runs there only in a call the reader reads as read-only, so a deployment that widens the
8
+ * list with `sort` still has `sort -o out f` refused. The reversibility classifier reads the list as its allowlist: a
9
+ * listed program with a program-model row has its writing options refused by the row; one without a row is admitted
10
+ * by its name. The default is curated to commands with NO write/mutation mode under ANY args, so the `effect:"read"`
11
+ * declaration (relied on by wake/resume reconcile + the verifier read-only boundary) AND the classifier's
12
+ * "reversible" promise both stay truthful. The deployment's tool-policy gate is the authoritative control;
13
+ * anything that can mutate state or run arbitrary code belongs on the full `bash` (effect:write, gated), not here.
14
14
  *
15
15
  * Deliberately ABSENT: `date` (`-s`/`--set` → CLOCK_SETTIME), `hostname` (`<name>` → kernel
16
16
  * hostname), and `file` (`-C -m` → compiles/writes a magic file) were REMOVED — each is read-only by NAME
@@ -112,7 +112,7 @@ export interface LeadingCommandNameOptions {
112
112
  pathPrefixedNameIsText?: boolean;
113
113
  }
114
114
  /**
115
- * The SINGLE fail-closed simple-command parser shared by `bash_readonly` ({@link coarseReadonlyCheck}), the
115
+ * The SINGLE fail-closed simple-command parser shared by `bash_readonly`'s single-command admission, the
116
116
  * `bash` reversibility classifier ({@link import("./fs-bash.js").bashReversibilityProbe}), and the coarse command-name policy
117
117
  * ({@link import("../../core/tool-policy.js").createCoarseCommandNamePolicy}). It extracts the leading
118
118
  * `argv[0]` command NAME of a SINGLE simple command, rejecting anything that could chain past or escape an
@@ -131,13 +131,9 @@ export declare function parseLeadingCommandName(command: string, options?: Leadi
131
131
  } | {
132
132
  reject: string;
133
133
  };
134
- /** Coarse pre-execution check for `bash_readonly`: the command must be a single bare allowlisted command
135
- * with no shell operators. It validates the NAME only (+ blocks operators/path-prefix/env-assignment); it
136
- * does NOT inspect arguments for write flags — keeping the allowlist free of write-capable commands and
137
- * the policy gate are what make `effect:"read"` truthful. Returns a reason when rejected, else undefined.
138
- * This `effect:"read"` DECLARATION face deliberately stays strict-single-command; only the
139
- * classify face ({@link classifyCompoundReadonly} via {@link import("./fs-bash.js").bashReversibilityProbe}) segments compounds. */
140
- export declare function coarseReadonlyCheck(command: string, allow: ReadonlySet<string>, options?: LeadingCommandNameOptions): string | undefined;
134
+ /** The one sentence for a program a face's list of programs does not name — the compound classifier's list check and
135
+ * the read-only reader's `readers` narrowing both mint it here. */
136
+ export declare function unlistedReaderSentence(program: string): string;
141
137
  /**
142
138
  * Does this text carry a bare redirection operator — the ONE metacharacter family
143
139
  * {@link splitShellCompoundSegments} can be asked to tolerate at its whole-string gate
@@ -226,7 +222,7 @@ export declare function splitShellCompoundSegments(source: string, options?: {
226
222
  /**
227
223
  * Compound read-only classification for the `bash` full-shell face (the shape tier).
228
224
  * Splits a command on the connector set `;` `&&` `||` `|` and passes every segment through
229
- * {@link coarseReadonlyCheck} (the single {@link parseLeadingCommandName} parser + bare-name allowlist).
225
+ * the single {@link parseLeadingCommandName} parser and the bare-name allowlist.
230
226
  * All segments green ⇒ read-only. Returns a reason when rejected, else undefined.
231
227
  *
232
228
  * G2 — the split CARRIES QUOTE STATE (the one lexer): a connector character inside a quoted region is
@@ -548,7 +544,7 @@ export declare const POLL_LOOP_MAX_SLEEP_SECONDS = 600;
548
544
  * -f`, unbounded devices all reject), and `sleep` must be a literal ≤
549
545
  * {@link POLL_LOOP_MAX_SLEEP_SECONDS}. Bounded beats × terminating body ⇒ the loop halts.
550
546
  * G2 NO WRITE OR EGRESS CHANNEL. Every non-`sleep` body segment must pass the SAME
551
- * {@link coarseReadonlyCheck} parser + allowlist as the plain face (one parser, no drift);
547
+ * {@link parseLeadingCommandName} parser + allowlist the compound classifier reads (one parser, no drift);
552
548
  * `sleep` touches neither filesystem nor network. No redirection (`>` `<`), no `$`/backtick
553
549
  * substitution, no subshell exists anywhere: the body bans them wholesale
554
550
  * ({@link POLL_BODY_HARD_REJECT}), and the head's single `$(seq <int> <int>)` exemption is an
@@ -71,13 +71,8 @@ export function parseLeadingCommandName(command, options) {
71
71
  return { reject: "the command name must be a bare token (no quotes, braces, globs, or ~)" };
72
72
  return { name: first };
73
73
  }
74
- export function coarseReadonlyCheck(command, allow, options) {
75
- const parsed = parseLeadingCommandName(command, options);
76
- if ("reject" in parsed)
77
- return parsed.reject;
78
- if (!allow.has(parsed.name))
79
- return `command "${parsed.name}" is not in the read-only allowlist`;
80
- return undefined;
74
+ export function unlistedReaderSentence(program) {
75
+ return `command "${program}" is not in the read-only allowlist`;
81
76
  }
82
77
  const SHELL_SEGMENT_QUOTE_BLIND_REJECT = /[<>()`\n\r\\]/;
83
78
  const SHELL_EXPANSION_CHARS = /[$]/;
@@ -761,7 +756,7 @@ export function classifyCompoundReadonlyDetailed(command, allow, boundary) {
761
756
  return { reason: "`coproc` backgrounds a command — a backgrounded process outlives the command" };
762
757
  if (isBareControlWord(words, from, BLOCK_WORD_NAMES)) {
763
758
  unlistedSegments.add(si);
764
- nameRefusal ??= `command "${written}" is not in the read-only allowlist`;
759
+ nameRefusal ??= unlistedReaderSentence(written);
765
760
  continue;
766
761
  }
767
762
  const program = pos.program;
@@ -783,10 +778,10 @@ export function classifyCompoundReadonlyDetailed(command, allow, boundary) {
783
778
  if (pathPrefixed || from > 0)
784
779
  reheaded.set(si, { from, head: name });
785
780
  if (from > 0)
786
- nameRefusal ??= `command "${folded[0]}" is not in the read-only allowlist`;
781
+ nameRefusal ??= unlistedReaderSentence(folded[0]);
787
782
  continue;
788
783
  }
789
- nameRefusal ??= `command "${parsed.name}" is not in the read-only allowlist`;
784
+ nameRefusal ??= unlistedReaderSentence(parsed.name);
790
785
  if (runsShellText(name))
791
786
  return { reason: unjudgedProgramTextRefusal(parsed.name, "runs its argument as shell text") };
792
787
  if (pos.launchers.length > 0) {