@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
@@ -4,13 +4,15 @@ import { NAMESPACED_NAME_SHAPES } from "./protocol-table.js";
4
4
  import { callerToolNameProblem } from "./caller-tool-name.js";
5
5
  import { compileAllowList, compiledEntryName, inertEntryPhrase, readRuleEntry, renderListEntry, rootFacingToolNames } from "./allow-entry.js";
6
6
  import { valueTypeLabel } from "./tool-name-list.js";
7
- import { noticeRuleText } from "./permission-rule-model.js";
7
+ import { NAME_RULE_FACES, noticeRuleText } from "./permission-rule-model.js";
8
+ import { parsePermissionRule, ruleSpellingOf } from "./permission-rule-syntax.js";
9
+ import { splitNamespacedName } from "./tool-name-aliases.js";
8
10
  const SESSION_RULE_BUCKETS = { toolAllow: "allow", toolDeny: "deny", allowDirs: "dirs" };
9
11
  const BUCKETS = Object.keys(SESSION_RULE_BUCKETS);
10
12
  const ENTRY_FIELDS = BUCKETS.filter((f) => SESSION_RULE_BUCKETS[f] !== "dirs");
11
13
  const STORE_STAMPS = new Set(["rev", "gen", "grammar"]);
12
14
  const OPERATOR_PART = "operatorRules";
13
- export const SESSION_RULES_GRAMMAR = 4;
15
+ export const SESSION_RULES_GRAMMAR = 6;
14
16
  export class SessionPolicyError extends Error {
15
17
  code;
16
18
  detail;
@@ -149,42 +151,142 @@ function canonicalRules(read) {
149
151
  }
150
152
  return out;
151
153
  }
152
- function earlierGrammarReads(grammar, field, entry, reading) {
153
- if (grammar >= SESSION_RULES_GRAMMAR)
154
- return false;
155
- if (reading.kind === "inert" && reading.reason === "grammar")
156
- return true;
157
- if (grammar !== 0 || SESSION_RULE_BUCKETS[field] !== "allow")
158
- return false;
159
- return reading.kind === "row" ? compiledEntryName(reading.compiled) !== entry : reading.reason === "wildcard_all";
160
- }
161
- function readsAsNoRule(entry, field) {
162
- const reading = readRuleEntry(entry, SESSION_RULE_BUCKETS[field]);
163
- return reading.kind === "inert" && reading.reason === "grammar";
154
+ const NAMES_NO_TOOL = "an entry naming no tool, so it refused nothing";
155
+ const NO_RULE_THEN = (direction) => (direction === "allow" ? "no rule, so it admitted nothing" : "no rule, so the rules could not be read and refused every call");
156
+ const NAME_PATTERN_NOW = "a pattern over the whole tool name, every tool it matches";
157
+ function spellsWholeProtocol(name) {
158
+ const split = splitNamespacedName(name);
159
+ return split !== undefined && split.peer === "*" && (split.tool === undefined || split.tool === "*");
160
+ }
161
+ const GRAMMAR_REVISIONS = [
162
+ {
163
+ grammar: 1,
164
+ answer: ({ direction, entry, reading }) => {
165
+ const otherName = reading.kind === "row" ? compiledEntryName(reading.compiled) !== entry : reading.reason === "wildcard_all";
166
+ if (!otherName)
167
+ return undefined;
168
+ if (direction === "allow")
169
+ return { was: "a tool name compared as written, naming no tool", now: "the rule it spells", keep: { kind: "inert", reason: "earlier_grammar" }, reader: "named_no_tool" };
170
+ return reading.kind === "row" ? { was: "a tool name compared as written, naming no tool, so it refused nothing", now: "the rule it spells", reader: "grammar_revised" } : undefined;
171
+ },
172
+ },
173
+ {
174
+ grammar: 3,
175
+ answer: ({ direction, reading }) => direction === "deny" && reading.kind === "row" && reading.compiled.kind === "covering" && spellsWholeProtocol(reading.compiled.pattern)
176
+ ? { was: NAMES_NO_TOOL, now: "a deny of every tool of the protocol", reader: "grammar_revised" }
177
+ : undefined,
178
+ },
179
+ {
180
+ grammar: 4,
181
+ answer: ({ direction, reading }) => {
182
+ if (reading.kind !== "row")
183
+ return undefined;
184
+ const { compiled } = reading;
185
+ if (compiled.kind === "name" && NAME_RULE_FACES[compiled.rule.tool]?.values === "mounted") {
186
+ return { was: direction === "allow" ? "an entry with no rule form, so it admitted nothing" : "an entry with no rule form, so it refused nothing", now: "a rule on the agent type it names", reader: "grammar_revised" };
187
+ }
188
+ return compiled.kind === "command" && compiled.rule.match === "pattern" ? { was: NO_RULE_THEN(direction), now: "the Bash pattern rule it spells", reader: "grammar_revised" } : undefined;
189
+ },
190
+ },
191
+ {
192
+ grammar: 5,
193
+ answer: ({ row, direction, entry, reading, list }) => {
194
+ if (direction === "allow") {
195
+ if (row >= 1 && list.some(readsAsWildcard))
196
+ return { was: "voided by the `*` its list holds", now: "one entry that grants nothing, the entries beside it read as written", keep: { kind: "inert", reason: "wildcard_all" } };
197
+ const parsed = reading.kind === "inert" ? ruleSpellingOf(entry) : undefined;
198
+ const name = parsed?.ruleContent === undefined ? parsed?.toolName : undefined;
199
+ if (name === undefined || name === "*" || !name.includes("*") || name.startsWith("*") || splitNamespacedName(name) !== undefined)
200
+ return undefined;
201
+ return { was: `the exact tool name ${JSON.stringify(name)}`, now: "no rule (an allow reads a `*` only in a protocol name's tool segment)", keep: { kind: "row", compiled: { kind: "tool", name } }, reader: "grammar_revised" };
202
+ }
203
+ if (reading.kind !== "row" || reading.compiled.kind !== "covering")
204
+ return undefined;
205
+ const { pattern } = reading.compiled;
206
+ const split = splitNamespacedName(pattern);
207
+ if (!pattern.includes("*") || spellsWholeProtocol(pattern) || (split !== undefined && !split.peer.includes("*")))
208
+ return undefined;
209
+ const answer = { now: NAME_PATTERN_NOW, reader: "grammar_revised" };
210
+ if (pattern === "*")
211
+ return { ...answer, was: NAMES_NO_TOOL, keep: { kind: "inert", reason: "wildcard_all" } };
212
+ if (split !== undefined)
213
+ return { ...answer, was: NAMES_NO_TOOL, keep: { kind: "inert", reason: "namespace_wildcard" } };
214
+ if (pattern.startsWith("*"))
215
+ return { ...answer, was: NO_RULE_THEN(direction) };
216
+ return { ...answer, was: `the exact tool name ${JSON.stringify(pattern)}, so it refused only a tool of that name`, keep: { kind: "row", compiled: { kind: "tool", name: pattern } } };
217
+ },
218
+ },
219
+ ];
220
+ function earlierGrammarReads(row, direction, entry, reading, list) {
221
+ if (row >= SESSION_RULES_GRAMMAR)
222
+ return { reading };
223
+ let first;
224
+ let last;
225
+ let kept;
226
+ for (const revision of GRAMMAR_REVISIONS) {
227
+ if (revision.grammar <= row)
228
+ continue;
229
+ const answer = revision.answer({ row, direction, entry, reading, list });
230
+ if (answer === undefined)
231
+ continue;
232
+ first ??= answer;
233
+ last = answer;
234
+ if (answer.keep !== undefined) {
235
+ kept = answer.keep;
236
+ break;
237
+ }
238
+ }
239
+ const read = kept ?? reading;
240
+ if (read.kind === "inert" && read.reason === "grammar")
241
+ return { reading: { kind: "inert", reason: "earlier_grammar" }, reader: "no_rule" };
242
+ if (first === undefined || last === undefined)
243
+ return { reading: read };
244
+ const reader = first.reader === "named_no_tool" ? first.reader : last.reader;
245
+ if (reader === undefined)
246
+ return { reading: read };
247
+ return { reading: read, reader, ...(reader === "grammar_revised" ? { revised: { was: first.was, now: last.now, stands: kept !== undefined } } : {}) };
164
248
  }
165
249
  const NO_RULE_REASONS = new Set(["grammar", "earlier_grammar"]);
166
250
  export function unreadableDenyEntries(rules, roster) {
167
251
  return compileSessionRuleBucket(rules, "toolDeny", roster).inert.filter((i) => NO_RULE_REASONS.has(i.reason));
168
252
  }
169
- function readsAsWildcard(entry) {
170
- return compileAllowList([entry], "allow").inert.some((i) => i.reason === "wildcard_all");
171
- }
172
253
  const STAR_IS_NO_ALLOW_RULE = "it is no allow rule in any grammar and a write holding it is refused";
173
254
  function starWayOut(onlyStars, others, left) {
174
255
  return onlyStars
175
256
  ? `"*" is no allow rule in any grammar (a write holding it is refused); to drop it, write the session's rules afresh without it ${REWRITE_THROUGH}; ${left}`
176
257
  : `${others}, leaving "*" out — ${STAR_IS_NO_ALLOW_RULE}; ${left}`;
177
258
  }
178
- export function compileSessionRuleBucket(rules, field, roster) {
259
+ function readsAsWildcard(entry) {
260
+ return typeof entry === "string" && entry === entry.trim() && parsePermissionRule(entry).toolName === "*";
261
+ }
262
+ function entryBucketDirection(field) {
179
263
  const direction = SESSION_RULE_BUCKETS[field];
264
+ if (direction === "allow" || direction === "deny")
265
+ return direction;
266
+ throw new SessionPolicyError("invalid_shape", `${JSON.stringify(field)} is no rule-entry bucket of the session rules — the entry buckets are ${ENTRY_FIELDS.join(" and ")}`);
267
+ }
268
+ function bucketReadings(rules, field, roster) {
269
+ const direction = entryBucketDirection(field);
180
270
  const entries = rules[field] ?? [];
181
- const earlier = new Set(entries.filter((e) => earlierGrammarReads(rules.grammar, field, e, readRuleEntry(e, direction, roster))));
182
- const whole = compileAllowList(entries, direction, roster);
183
- const voided = direction === "allow" && whole.inert.some((i) => i.reason === "wildcard_all");
184
- if (earlier.size === 0 || (voided && rules.grammar > 0))
185
- return whole;
186
- const list = compileAllowList(entries.filter((e) => !earlier.has(e)), direction, roster);
187
- return { rows: list.rows, inert: [...list.inert, ...entries.filter((e) => earlier.has(e)).map((entry) => ({ entry, reason: "earlier_grammar" }))] };
271
+ return entries.map((entry) => ({ entry, ...earlierGrammarReads(rules.grammar, direction, entry, readRuleEntry(entry, direction, roster), entries) }));
272
+ }
273
+ export function compileSessionRuleBucket(rules, field, roster) {
274
+ const rows = [];
275
+ const inert = [];
276
+ const earlier = [];
277
+ for (const { entry, reading } of bucketReadings(rules, field, roster)) {
278
+ if (reading.kind === "row")
279
+ rows.push({ entry, compiled: reading.compiled });
280
+ else {
281
+ const { kind: _kind, ...why } = reading;
282
+ void _kind;
283
+ (why.reason === "earlier_grammar" ? earlier : inert).push({ entry, ...why });
284
+ }
285
+ }
286
+ return { rows, inert: [...inert, ...earlier] };
287
+ }
288
+ export function earlierGrammarEntries(rules, field) {
289
+ return bucketReadings(rules, field).flatMap((r) => (r.reader === undefined ? [] : [r.entry]));
188
290
  }
189
291
  const ADVISORY_ENTRIES_SHOWN = 5;
190
292
  function shownEntries(entries, render) {
@@ -193,14 +295,33 @@ function shownEntries(entries, render) {
193
295
  }
194
296
  const REWRITE_THROUGH = `through this engine (an operator write of a new value without the stored row's rev; the write stamps grammar ${SESSION_RULES_GRAMMAR})`;
195
297
  export function earlierGrammarAdvisory(sessionId, entries, field, grammar) {
196
- const read = earlierGrammarReadings(entries, field);
298
+ const read = earlierGrammarReadings(entries, field, grammar);
197
299
  const noRule = read.filter((r) => r.reader === "no_rule").map((r) => r.entry);
198
300
  const namedNoTool = read.filter((r) => r.reader === "named_no_tool").map((r) => r.entry);
199
- const sentences = [...(namedNoTool.length > 0 ? [namedNoToolInGrammar0(namedNoTool)] : []), ...(noRule.length > 0 ? [noRuleInThisGrammar(noRule, field, grammar)] : [])];
301
+ const revised = read.flatMap((r) => (r.revised === undefined ? [] : [{ entry: r.entry, ...r.revised }]));
302
+ const sentences = [
303
+ ...(namedNoTool.length > 0 ? [namedNoToolInGrammar0(namedNoTool)] : []),
304
+ ...(noRule.length > 0 ? [noRuleInThisGrammar(noRule, field, grammar)] : []),
305
+ ...(revised.length > 0 ? [revisedSinceGrammar(revised, field, grammar)] : []),
306
+ ];
200
307
  return `session permission rules of session ${JSON.stringify(sessionId)}: ${sentences.join(" ")}`;
201
308
  }
202
- function earlierGrammarReadings(entries, field) {
203
- return entries.map((entry) => ({ entry, reader: readsAsNoRule(entry, field) ? "no_rule" : "named_no_tool" }));
309
+ function earlierGrammarReadings(entries, field, grammar) {
310
+ const direction = entryBucketDirection(field);
311
+ return entries.map((entry) => {
312
+ const read = earlierGrammarReads(grammar, direction, entry, readRuleEntry(entry, direction), entries);
313
+ return { entry, reader: read.reader ?? "no_rule", ...(read.revised !== undefined ? { revised: read.revised } : {}) };
314
+ });
315
+ }
316
+ function revisedSinceGrammar(entries, field, grammar) {
317
+ const one = entries.length === 1;
318
+ const said = entries
319
+ .slice(0, ADVISORY_ENTRIES_SHOWN)
320
+ .map((e) => `${renderListEntry(e.entry)} meant ${e.was} there; this engine's rule grammar (${SESSION_RULES_GRAMMAR}) reads it as ${e.now}, and ${e.stands ? "the stored meaning stands" : "this grammar's reading applies"}`)
321
+ .join("; ");
322
+ const rest = entries.length > ADVISORY_ENTRIES_SHOWN ? `; and ${entries.length - ADVISORY_ENTRIES_SHOWN} more` : "";
323
+ return (`${field} ${one ? "holds an entry" : "holds entries"} stored in rule grammar ${grammar}${grammar === 0 ? " (before the rule grammar stamp)" : ""} whose meaning a later grammar revised — ${said}${rest}. ` +
324
+ `To give ${one ? "it" : "them"} this grammar's reading, write the session's rules afresh ${REWRITE_THROUGH}; left as stored, ${one ? "it reads" : "they read"} as said.`);
204
325
  }
205
326
  export function earlierGrammarNotice(input) {
206
327
  const { rulesSessionId, sessionId, entries, field, grammar } = input;
@@ -210,7 +331,7 @@ export function earlierGrammarNotice(input) {
210
331
  detail: {
211
332
  bucket: field,
212
333
  storedGrammar: grammar,
213
- entries: earlierGrammarReadings(entries, field).map((r) => ({ entry: noticeRuleText(r.entry), reader: r.reader })),
334
+ entries: earlierGrammarReadings(entries, field, grammar).map((r) => ({ entry: noticeRuleText(r.entry), reader: r.reader })),
214
335
  rewrite: { by: "operator_write_without_rev", stampsGrammar: SESSION_RULES_GRAMMAR },
215
336
  rulesSessionId,
216
337
  sessionId,
@@ -245,8 +366,9 @@ function noRuleInThisGrammar(entries, field, grammar) {
245
366
  export function earlierGrammarRefusalClause(entries, grammar) {
246
367
  if (entries.length === 0)
247
368
  return "";
248
- const noRule = entries.filter((e) => readsAsNoRule(e, "toolAllow")).length;
249
- const namedNoTool = entries.filter((e) => !readsAsNoRule(e, "toolAllow"));
369
+ const read = earlierGrammarReadings(entries, "toolAllow", grammar);
370
+ const noRule = read.filter((r) => r.reader === "no_rule").length;
371
+ const namedNoTool = read.filter((r) => r.reader !== "no_rule").map((r) => r.entry);
250
372
  const stars = namedNoTool.filter(readsAsWildcard).length;
251
373
  const others = namedNoTool.length - stars;
252
374
  const named = [...(stars > 0 ? ['"*"'] : []), ...(others > 0 ? [`${others} parenthesized ${others === 1 ? "entry" : "entries"}`] : [])];
@@ -276,15 +398,13 @@ function effectiveEntries(rules, field, mountedToolNames) {
276
398
  function assertEntriesRead(rules, mountedToolNames) {
277
399
  const known = rootFacingToolNames(mountedToolNames);
278
400
  for (const field of ENTRY_FIELDS) {
279
- for (const entry of rules[field] ?? []) {
280
- const reading = readRuleEntry(entry, SESSION_RULE_BUCKETS[field], known);
281
- const read = earlierGrammarReads(rules.grammar, field, entry, reading) ? { kind: "inert", reason: "earlier_grammar" } : reading;
401
+ for (const { entry, reading: read, reader } of bucketReadings(rules, field, known)) {
282
402
  if (read.kind === "row")
283
403
  continue;
284
404
  const { kind: _kind, ...why } = read;
285
405
  void _kind;
286
406
  const way = why.reason === "earlier_grammar"
287
- ? readsAsNoRule(entry, field)
407
+ ? reader === "no_rule"
288
408
  ? ` These rules are written in grammar ${rules.grammar} (a stored row), and this engine's grammar (${SESSION_RULES_GRAMMAR}) reads this entry as no rule (grammar) — ` +
289
409
  (field === "toolAllow" && readsAsWildcard(entry) ? `leave the entry out: it spells "*", and ${STAR_IS_NO_ALLOW_RULE}.` : "leave the entry out, or spell the tool's name as a rule spells one.")
290
410
  : ` These rules are written in grammar ${rules.grammar} (a stored row from before the grammar stamp), in which this entry names no tool.` +
@@ -1,5 +1,5 @@
1
1
  import { type Session, type SessionHead, type SessionPlacementRecord, type SessionRepo } from "../internal/harness.js";
2
- import { type AcquiredSession, type PlacedSessionRow, type SessionPlacement, type SessionStore, type SessionStoreSummary } from "./session.js";
2
+ import { type AcquiredSession, type PlacedSessionRow, type SessionListQuery, type SessionPlacement, type SessionStore, type SessionStoreSummary } from "./session.js";
3
3
  import type { StoreDurability } from "./checkpoint-store.js";
4
4
  import { SESSION_DEFAULT_TTL_DAYS } from "../config/defaults.js";
5
5
  export { SESSION_DEFAULT_TTL_DAYS };
@@ -149,9 +149,16 @@ export declare class TtlSessionStore implements SessionStore {
149
149
  requireExisting?: boolean;
150
150
  placement?: SessionPlacement;
151
151
  }): Promise<AcquiredSession>;
152
- /** Whether a cached view is still the occupant the row holds: the row's head, read in one read, names the same occupant as the cached
153
- * session (`compareOccupants` — unknown is never the same). Over a repo with no head read there is nothing to read the row with, and
154
- * the view is served as it is. */
152
+ /** The one judgement of "does this cached view still stand for this row": `shown` is the view's session metadata and `row` the row as
153
+ * a read of it answered (a listed row, or the repo's head; `undefined` = no row, or no read of one). A row naming the view's
154
+ * occupant (`compareOccupants`) stands for it; a row naming another does not; and a row naming a different owner does not either —
155
+ * the owner is recorded once, by the write that creates the row, so another owner's row is another row whatever it names. When
156
+ * the evidence says neither (unknown) the answer is the repo's: over one with a head read the row can always be read again, so a
157
+ * view without positive proof is dropped and the id resolved from the row; over one with no head read (it mints no occupant token)
158
+ * the cached view is the only evidence of the occupant, and it stands. */
159
+ private viewStandsFor;
160
+ /** Whether a cached view is still the occupant the row holds ({@link viewStandsFor}, over the row's head read in one read). Over a repo
161
+ * with no head read there is no row to read: the judge's answer for no row there is "stands", given without reading the view. */
155
162
  private cachedViewStands;
156
163
  /** The placement admission ({@link admitSessionPlacement}) for this store, judged on every resolution path. The
157
164
  * partition declaration is a getter over this store's live field, so it is read where the admission judges the
@@ -161,16 +168,28 @@ export declare class TtlSessionStore implements SessionStore {
161
168
  * `requireExisting`, in which case a genuinely-missing id fails loud instead — design/114 Phase3). */
162
169
  private openOrCreate;
163
170
  private createAndStore;
164
- /** Refresh the idle timer for a session. */
165
- touch(sessionId: string): void;
171
+ /** Refresh the idle timer for a session, and record the activity on its row through the repo ({@link SessionRepo.touch}, where the repo
172
+ * has it) — the time {@link list} orders by. A fault recording it rejects. */
173
+ touch(sessionId: string): Promise<void>;
166
174
  /** Record the most recent task run on a cached session (the `/resume` `lastRunId`); also bumps the idle
167
175
  * timer. Best-effort — a no-op if the session isn't cached here (the run will still be re-attachable via
168
176
  * its checkpoint). */
169
177
  noteTaskRun(sessionId: string, taskId: string, runId?: string): void;
170
- /** List the live cache as {@link SessionStoreSummary} projections, newest-first by `lastActiveAt` (so a
171
- * shell's `/resume` shows recent sessions + their last run first). The in-memory store lists only its
172
- * live cache, not evicted/durable history — a durable backend overrides this to list persisted sessions. */
173
- list(): Promise<SessionStoreSummary[]>;
178
+ /**
179
+ * One page of the repo's sessions ({@link SessionStore.list}): the rows the repo lists — what a restart still finds, not this
180
+ * cache — each projected from the row and ordered by the activity the repo RECORDS for it (its writes, and the touches this store
181
+ * records through it): never by what this process saw, so a dropped cache, a restart or another replica pages the same order, and a
182
+ * cursor is never overtaken by a row whose time moved back. The cached view adds only what it alone holds — the run it recorded
183
+ * (`lastTaskId` / `lastTaskRunId`; after a restart, or once the view is evicted, a row lists without them) — and only while the view
184
+ * stands for the listed row ({@link viewStandsFor}, the judgement `acquire` serves the cached session by). Every row is read to order the page; the repo's listing cost is its own (the File repo: one header
185
+ * read per session).
186
+ */
187
+ list(query?: SessionListQuery): Promise<SessionStoreSummary[]>;
188
+ /** A listed row's projection: the row's own cells, and the cached view's run while the view stands for the row
189
+ * ({@link viewStandsFor} — the row is read here, so a view of an occupant it names otherwise lends nothing). A row's activity is the
190
+ * repo's recorded time for it, else its creation — the view's own time is never read, so a repo that records none lists by creation;
191
+ * one whose times are both unreadable lists at 0 — at the end, never left out. */
192
+ private summaryOf;
174
193
  /**
175
194
  * design/110 (F3) — FORK a session: copy `sourceId`'s committed history into a NEW session and return its id
176
195
  * (or `null` when the source doesn't exist). Delegates to the backing repo's `fork`, so a durable repo persists the
@@ -1,5 +1,5 @@
1
- import { InMemorySessionRepo, ParentChainGuard, SessionError, findUnansweredToolBatch, compareOccupants, uuidv7, } from "../internal/harness.js";
2
- import { isSessionConflict } from "./session.js";
1
+ import { InMemorySessionRepo, ParentChainGuard, SessionError, findUnansweredToolBatch, compareOccupants, ownerCell, uuidv7, } from "../internal/harness.js";
2
+ import { isSessionConflict, readSessionListQuery } from "./session.js";
3
3
  import { readMember } from "./thrown-value.js";
4
4
  const DAY_MS = 24 * 60 * 60 * 1000;
5
5
  import { SESSION_DEFAULT_TTL_DAYS } from "../config/defaults.js";
@@ -97,11 +97,19 @@ export class TtlSessionStore {
97
97
  const meta = await session.getMetadata();
98
98
  return { session, sessionId: meta.id };
99
99
  }
100
+ viewStandsFor(shown, row) {
101
+ const verdict = compareOccupants(shown, row);
102
+ if (verdict !== "unknown")
103
+ return verdict === "same";
104
+ if (row !== undefined && (shown.owner ?? null) !== (row.owner ?? null))
105
+ return false;
106
+ return this.repoHead === undefined;
107
+ }
100
108
  async cachedViewStands(sessionId, cached) {
101
109
  if (this.repoHead === undefined)
102
110
  return true;
103
111
  const [shown, row] = await Promise.all([cached.session.getMetadata(), this.repoHead(sessionId)]);
104
- return compareOccupants(shown, row) === "same";
112
+ return this.viewStandsFor(shown, row);
105
113
  }
106
114
  assertPlacementAdmission(sessionId, placement, opts) {
107
115
  const store = this;
@@ -142,11 +150,12 @@ export class TtlSessionStore {
142
150
  this.entries.set(meta.id, { session, lastActiveAt: Date.now(), createdAt: meta.createdAt, ...(meta.forkedFrom !== undefined ? { forkedFrom: meta.forkedFrom } : {}), ...(meta.placement !== undefined ? { placement: meta.placement } : {}) });
143
151
  return session;
144
152
  }
145
- touch(sessionId) {
153
+ async touch(sessionId) {
146
154
  const e = this.entries.get(sessionId);
147
155
  if (e) {
148
156
  e.lastActiveAt = Date.now();
149
157
  }
158
+ await this.repo.touch?.(sessionId);
150
159
  }
151
160
  noteTaskRun(sessionId, taskId, runId) {
152
161
  const e = this.entries.get(sessionId);
@@ -159,18 +168,36 @@ export class TtlSessionStore {
159
168
  e.lastActiveAt = Date.now();
160
169
  }
161
170
  }
162
- async list() {
163
- return [...this.entries.entries()]
164
- .filter(([, e]) => e.placement === undefined)
165
- .map(([sessionId, e]) => ({
166
- sessionId,
167
- lastActiveAt: e.lastActiveAt,
168
- ...(e.createdAt !== undefined && e.createdAt !== "" ? { createdAt: e.createdAt } : {}),
169
- ...(e.lastTaskId !== undefined ? { lastTaskId: e.lastTaskId } : {}),
170
- ...(e.lastTaskRunId !== undefined ? { lastTaskRunId: e.lastTaskRunId } : {}),
171
- ...(e.forkedFrom !== undefined ? { forkedFrom: e.forkedFrom } : {}),
172
- }))
173
- .sort((a, b) => b.lastActiveAt - a.lastActiveAt);
171
+ async list(query) {
172
+ const q = readSessionListQuery(query);
173
+ const page = [];
174
+ for (const row of await this.repo.list()) {
175
+ if (row.placement !== undefined)
176
+ continue;
177
+ const owner = row.owner ?? null;
178
+ if (q.owner !== undefined && owner !== q.owner && !(q.includeUnowned && owner === null))
179
+ continue;
180
+ const summary = await this.summaryOf(row);
181
+ if (q.after !== undefined && newestFirst(q.after, summary) >= 0)
182
+ continue;
183
+ page.push(summary);
184
+ }
185
+ return page.sort(newestFirst).slice(0, q.limit);
186
+ }
187
+ async summaryOf(row) {
188
+ const cached = this.entries.get(row.id);
189
+ const view = cached !== undefined && this.viewStandsFor(await cached.session.getMetadata(), row) ? cached : undefined;
190
+ const recorded = row.lastActiveAt !== undefined && Number.isFinite(row.lastActiveAt) ? row.lastActiveAt : Date.parse(row.createdAt);
191
+ const lastActiveAt = Number.isFinite(recorded) ? recorded : 0;
192
+ const forkedFrom = row.forkedFrom ?? view?.forkedFrom;
193
+ return {
194
+ sessionId: row.id,
195
+ lastActiveAt,
196
+ ...(row.createdAt !== "" ? { createdAt: row.createdAt } : {}),
197
+ ...(view?.lastTaskId !== undefined ? { lastTaskId: view.lastTaskId } : {}),
198
+ ...(view?.lastTaskRunId !== undefined ? { lastTaskRunId: view.lastTaskRunId } : {}),
199
+ ...(forkedFrom !== undefined ? { forkedFrom } : {}),
200
+ };
174
201
  }
175
202
  async fork(sourceId, owner) {
176
203
  let source;
@@ -274,9 +301,9 @@ export class TtlSessionStore {
274
301
  await inflightRelease;
275
302
  if (await this.hasRow(sessionId))
276
303
  return;
277
- if (owner !== null && typeof owner !== "string") {
278
- throw new TypeError(`SessionStore.register: owner must be a string (owned) or null (anonymous), got ${owner === undefined ? "undefined" : typeof owner}`);
279
- }
304
+ if (owner === undefined)
305
+ throw new TypeError("SessionStore.register: owner must be a principal name or null (anonymous), got undefined");
306
+ ownerCell(owner);
280
307
  try {
281
308
  await this.repo.create({ id: sessionId, owner });
282
309
  }
@@ -347,6 +374,11 @@ export async function settledForkOptions(source) {
347
374
  }
348
375
  return {};
349
376
  }
377
+ function newestFirst(a, b) {
378
+ if (a.lastActiveAt !== b.lastActiveAt)
379
+ return b.lastActiveAt - a.lastActiveAt;
380
+ return a.sessionId < b.sessionId ? 1 : a.sessionId > b.sessionId ? -1 : 0;
381
+ }
350
382
  function isNotFound(err) {
351
383
  return readMember(err, "code") === "not_found";
352
384
  }
@@ -2,7 +2,7 @@ export { StoredSession } from "../internal/harness.js";
2
2
  export type { Session } from "../internal/harness.js";
3
3
  export { InMemorySessionRepo, InMemorySessionStorage, uuidv7, validateEntriesForImport, StreamingImportValidator, } from "../internal/harness.js";
4
4
  export { BaseSessionStorage, leafIdAfterEntry, } from "../internal/harness.js";
5
- export type { SessionStorage, SessionRepo, SessionMetadata, SessionTreeEntry, } from "../internal/harness.js";
5
+ export type { SessionStorage, SessionRepo, SessionRow, SessionMetadata, SessionTreeEntry, } from "../internal/harness.js";
6
6
  export { SessionError } from "../internal/harness.js";
7
7
  export type { SessionWriteOptions } from "../internal/harness.js";
8
8
  import type { Session } from "../internal/harness.js";
@@ -55,7 +55,7 @@ export interface AcquiredSession {
55
55
  }
56
56
  /**
57
57
  * A lightweight, read-only projection of one session for a `/resume` list (shell K-5 — re-attach without an
58
- * N+1 walk). Returned in bulk by {@link SessionStore.list}, newest-first by `lastActiveAt` by convention.
58
+ * N+1 walk). Returned in pages by {@link SessionStore.list}, newest-first by `(lastActiveAt, sessionId)`.
59
59
  * `lastTaskId` is the engine's term for what the service/wire surfaces as the session's **`lastRunId`** — the
60
60
  * most recent task run on this session, so a shell re-attaches in ONE hop.
61
61
  *
@@ -72,7 +72,10 @@ export interface SessionStoreSummary {
72
72
  /** When the session was created ({@link SessionMetadata.createdAt}, ISO string); absent when the backend's
73
73
  * cache view doesn't carry it. */
74
74
  createdAt?: string;
75
- /** Epoch ms the session was last acquired / touched / ran — the newest-first sort key for "recent sessions". */
75
+ /** Epoch ms of the session's newest activity the store RECORDS — its writes and its {@link SessionStore.touch}es (the Runner touches
76
+ * a session as each run ends) — the newest-first sort key for "recent sessions". Recorded, never what one process saw: a restart,
77
+ * another replica or a dropped cache reads the same time, and only a later activity moves it. An acquire that writes nothing is not
78
+ * activity. */
76
79
  lastActiveAt: number;
77
80
  /** The most recent task run on this session (core's `taskId`; the service projects it as `lastRunId`).
78
81
  * Absent until a task has run on the session (recorded via {@link SessionStore.noteTaskRun}). */
@@ -106,6 +109,54 @@ export interface SessionStoreSummary {
106
109
  * predate the fork. The durable source of truth is the repo's persisted metadata. */
107
110
  forkedFrom?: string;
108
111
  }
112
+ /** The page bounds of {@link SessionStore.list}: a query without `limit` reads `default` rows; an explicit `limit` is an integer in
113
+ * 1..`max`. */
114
+ export declare const SESSION_LIST_LIMITS: Readonly<{
115
+ readonly default: 50;
116
+ readonly max: 1000;
117
+ }>;
118
+ /**
119
+ * What {@link SessionStore.list} is asked for. No query, or `{}`, is the unfiltered list — every owner's rows, unowned ones included —
120
+ * read from its first page, at most {@link SESSION_LIST_LIMITS}`.default` rows; a caller that wants every row pages with `after`.
121
+ * A store may define extension filters of its own (members beside these, e.g. a text search); a filter applies before the page is
122
+ * cut, so `after` and `limit` page the filtered list. A store refuses a member it does not read — an unread filter would list rows the
123
+ * caller asked to exclude.
124
+ */
125
+ export interface SessionListQuery {
126
+ /** Only the rows this owner owns (exact match; a principal name, so a blank string is refused, never an owner of its own). Absent = no owner filter. */
127
+ owner?: string;
128
+ /** With `owner`: the unowned rows (owner `null`) too. A member of the owner filter only — given without `owner` it is refused, so a
129
+ * query that lost its owner never widens into every owner's list. */
130
+ includeUnowned?: boolean;
131
+ /** The keyset cursor — the `lastActiveAt` and `sessionId` of the last row of the previous page: only rows after it in the list's
132
+ * order are read (a smaller `lastActiveAt`, or the same one with a smaller `sessionId`). */
133
+ after?: {
134
+ lastActiveAt: number;
135
+ sessionId: string;
136
+ };
137
+ /** At most this many rows, an integer in 1..{@link SESSION_LIST_LIMITS}`.max`; absent = the default. Ask for one more than a page
138
+ * shows to learn whether another page exists. */
139
+ limit?: number;
140
+ }
141
+ /** {@link readSessionListQuery}'s answer: the query's members as read, the defaults filled in. */
142
+ export interface SessionListQueryReading {
143
+ readonly owner?: string;
144
+ readonly includeUnowned: boolean;
145
+ readonly after?: {
146
+ readonly lastActiveAt: number;
147
+ readonly sessionId: string;
148
+ };
149
+ readonly limit: number;
150
+ /** The values of the extension members the reading store declared and the query carries. */
151
+ readonly extensions: Readonly<Record<string, unknown>>;
152
+ }
153
+ /**
154
+ * The one reading of a {@link SessionListQuery}, for every store that implements {@link SessionStore.list}: `raw` read by the
155
+ * engine's receipt law (a plain object, each member read once), each member judged, the default limit filled in. `extensions` names
156
+ * the extension members the calling store reads (none for a store without extension filters); any other member is refused. A bad
157
+ * value is refused, never mapped to a default: `config.invalid_argument`.
158
+ */
159
+ export declare function readSessionListQuery(raw: unknown, extensions?: readonly string[]): SessionListQueryReading;
109
160
  /**
110
161
  * The session lifecycle/caching layer the {@link Runner} depends on.
111
162
  *
@@ -114,8 +165,12 @@ export interface SessionStoreSummary {
114
165
  * a session from the persisted event log so any stateless runner instance can resume it.
115
166
  *
116
167
  * Implementations must be safe under concurrent `acquire` of the same id (return one session).
168
+ *
169
+ * `S` / `Q` are the store's list projection and query: a backend whose list carries more per row (or filters by more) extends
170
+ * {@link SessionStoreSummary} / {@link SessionListQuery} and implements `SessionStore<Its summary, Its query>` — still assignable
171
+ * wherever a `SessionStore` is taken.
117
172
  */
118
- export interface SessionStore {
173
+ export interface SessionStore<S extends SessionStoreSummary = SessionStoreSummary, Q extends SessionListQuery = SessionListQuery> {
119
174
  /**
120
175
  * design/173 §2.3 — durability declaration (see
121
176
  * {@link import("./checkpoint-store.js").StoreDurability}): whether sessions this store accepts
@@ -142,7 +197,7 @@ export interface SessionStore {
142
197
  * Declaring this commits the store to the placement obligations:
143
198
  * 1. a placed session enjoys the declared durability (`acquire(id, {requireExisting:true})`
144
199
  * reaches it after a restart when `"durable"`);
145
- * 2. placed sessions do NOT appear on host enumeration faces (`list()` and every deployment
200
+ * 2. placed sessions do NOT appear on host enumeration faces (`list` and every deployment
146
201
  * listing path — restart-stable);
147
202
  * 3. acquire semantics for sessions WITHOUT a placement are byte-unchanged;
148
203
  * 4. `release(placedId)` is a REAL deletion (durable history included) — the joint reap's
@@ -171,7 +226,8 @@ export interface SessionStore {
171
226
  requireExisting?: boolean;
172
227
  placement?: SessionPlacement;
173
228
  }): Promise<AcquiredSession>;
174
- /** Mark a session recently active (resets idle TTL where applicable). May be async for durable stores. */
229
+ /** Mark a session recently active: resets the idle TTL where applicable, and is activity the {@link list} order records. May be
230
+ * async for durable stores. */
175
231
  touch(sessionId: string): void | Promise<void>;
176
232
  /** Drop a session from the live set (e.g. a throwaway task). Durable history may be retained by the backend. */
177
233
  release(sessionId: string): Promise<void>;
@@ -215,12 +271,16 @@ export interface SessionStore {
215
271
  */
216
272
  noteTaskRun?(sessionId: string, taskId: string, runId?: string): void | Promise<void>;
217
273
  /**
218
- * Enumerate known sessions as lightweight {@link SessionStoreSummary} projections (newest-first by
219
- * `lastActiveAt`) so a shell's `/resume` lists sessions + their last run in ONE call. **Optional**: the
220
- * in-memory `TtlSessionStore` lists its live cache; a durable backend lists persisted sessions. A store
221
- * that cannot enumerate omits this (the shell then has no session-list affordance — honest degrade).
274
+ * One page of the store's sessions as lightweight {@link SessionStoreSummary} projections, so a shell's `/resume` lists sessions +
275
+ * their last run in ONE call: every session ROW the store holds — what a restart still finds, not only what this process has
276
+ * cached — that the query admits, newest-first by `(lastActiveAt, sessionId)` (both descending; equal times order by id), at most
277
+ * `limit` rows after the `after` cursor (see {@link SessionListQuery}; read it with {@link readSessionListQuery}, whose refusals are
278
+ * this face's). Placed sessions are never listed (placement obligation 2). Reading the list is not activity, and a row's time only
279
+ * moves forward, so paging with `after` never reads a row twice — a row written or touched between two pages moves ahead of the
280
+ * cursor, where later pages do not read it (a fresh first page shows it). **Optional**: a store that cannot enumerate omits this (the
281
+ * shell then has no session-list affordance — honest degrade).
222
282
  */
223
- list?(): Promise<SessionStoreSummary[]>;
283
+ list?(query?: Q): Promise<S[]>;
224
284
  /**
225
285
  * Subagent transcript persistence — enumerate the PLACED partition (the input to the joint reap's
226
286
  * partition leg: sessions whose owning agent row is gone are the orphan shape it collects).
@@ -247,7 +307,8 @@ export interface SessionStore {
247
307
  * fork time (returns `null`). The fork is a new row whose owner cell is recorded in the write that creates it — a fork
248
308
  * COPIES the source's history, so the copy is never weaker than the original: with no `owner` argument, or an
249
309
  * EXPLICIT `null`, the fork records the SOURCE row's owner ("anonymous" on a copy of an OWNED source would admit
250
- * every principal to that history — a downgrade this face exists to prevent); an owner string records that owner.
310
+ * every principal to that history — a downgrade this face exists to prevent); an owner string (a principal name — a blank
311
+ * string is refused, with no row left behind) records that owner.
251
312
  * MUST copy the COMMITTED leaf (an in-flight uncommitted turn of an active source is not included — a fork is a
252
313
  * snapshot at the fork point).
253
314
  */
@@ -260,7 +321,10 @@ export interface SessionStore {
260
321
  * The BY-ID read, for a reader that did not acquire the session (hosts, a deployment's authorizer). A store that has it hands out,
261
322
  * from `acquire`, only a session of the occupant it names — a cached view of an occupant the row no longer holds (the row deleted,
262
323
  * or deleted and created again, through another writer — on the File lane a writer in another process too) is not served — so its `incarnation` and the acquired session's metadata agree (the kit pins both); a run's own memory seat reads the session it ACQUIRED instead, never this lookup. The owner is a cell of the row: `null` = anonymous (admitted to every principal) — a row created
263
- * with no owner, a placed row, or a row written before the cell existed; a string = owned. **Optional**: absent ⇒ no by-id read,
324
+ * with no owner (`acquire` names none), or a row written before the cell existed; a principal name = owned (a cell holding a blank string
325
+ * names nobody and is a read fault, never an owner). A placed row carries the owner its placing write recorded: the bundled stores'
326
+ * placing write names none (`acquire`'s options and {@link SessionPlacement} carry no principal), so their placed rows read `null`; a
327
+ * store's own placing write may record a principal (e.g. a delegation tree's owner), and a reader takes the row's owner as it reads. **Optional**: absent ⇒ no by-id read,
264
328
  * and a deployment's authorizer, which needs this and {@link register} together, takes its fail-closed arm.
265
329
  */
266
330
  headOf?(sessionId: string): Promise<SessionHead | undefined>;
@@ -268,9 +332,11 @@ export interface SessionStore {
268
332
  * The owner write of the ownership pair ({@link headOf} + this). On an id with NO row it creates the row — an ordinary row, no
269
333
  * placement — recording `owner` in the creating write, first-write-wins and atomic: of two concurrent first registers, both
270
334
  * callers' re-reads see the same winner (durable implementations need a real uniqueness guarantee, not read-then-write). On an id
271
- * whose row EXISTS it does nothing, whatever it carries — an owned row, an anonymous row, or a row `acquire` created (which
272
- * records `null`) stays as it is; there is no claiming of an existing row. A FIRST write whose `owner` is neither a string nor
273
- * `null` is refused loudly and leaves no row; a later call stays a silent no-op whatever it carries. Deliberately makes NO
335
+ * whose row EXISTS it does nothing, whatever it carries — an owned row, an anonymous row, a row `acquire` created (which
336
+ * records `null`), or a placed row (the owner its placing write recorded) stays as it is: a row's owner is recorded by the write that
337
+ * creates it and `register` never changes it; there is no claiming of an existing row. A FIRST write whose `owner` is neither a principal
338
+ * name (a string with a visible character, no control or separator character, and no format character but a joiner) nor `null` is refused loudly and leaves no row; a later call stays a silent no-op
339
+ * whatever it carries. Deliberately makes NO
274
340
  * authorization decision — the caller re-reads {@link headOf} and judges there. The owner lives and dies with its row.
275
341
  */
276
342
  register?(sessionId: string, owner: string | null): Promise<void>;