open-multi-agent-kit 1.0.0 → 1.2.2

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 (622) hide show
  1. package/CHANGELOG.md +52 -1
  2. package/README.md +2 -2
  3. package/dist/approval-api.d.ts +5 -0
  4. package/dist/approval-api.d.ts.map +1 -0
  5. package/dist/approval-api.js +5 -0
  6. package/dist/approval-api.js.map +1 -0
  7. package/dist/cli/help.d.ts.map +1 -1
  8. package/dist/cli/help.js +1 -0
  9. package/dist/cli/help.js.map +1 -1
  10. package/dist/cli/session-picker.d.ts +2 -2
  11. package/dist/cli/session-picker.d.ts.map +1 -1
  12. package/dist/cli/session-picker.js.map +1 -1
  13. package/dist/commands/verified-run-cli.d.ts.map +1 -1
  14. package/dist/commands/verified-run-cli.js +69 -22
  15. package/dist/commands/verified-run-cli.js.map +1 -1
  16. package/dist/commands/verified-run-signal.d.ts +3 -0
  17. package/dist/commands/verified-run-signal.d.ts.map +1 -0
  18. package/dist/commands/verified-run-signal.js +15 -0
  19. package/dist/commands/verified-run-signal.js.map +1 -0
  20. package/dist/coordination/awareness.d.ts +32 -0
  21. package/dist/coordination/awareness.d.ts.map +1 -0
  22. package/dist/coordination/awareness.js +55 -0
  23. package/dist/coordination/awareness.js.map +1 -0
  24. package/dist/coordination/broker.d.ts +79 -0
  25. package/dist/coordination/broker.d.ts.map +1 -0
  26. package/dist/coordination/broker.js +202 -0
  27. package/dist/coordination/broker.js.map +1 -0
  28. package/dist/coordination/index.d.ts +16 -0
  29. package/dist/coordination/index.d.ts.map +1 -0
  30. package/dist/coordination/index.js +16 -0
  31. package/dist/coordination/index.js.map +1 -0
  32. package/dist/coordination/integration.d.ts +59 -0
  33. package/dist/coordination/integration.d.ts.map +1 -0
  34. package/dist/coordination/integration.js +126 -0
  35. package/dist/coordination/integration.js.map +1 -0
  36. package/dist/coordination/operation.d.ts +107 -0
  37. package/dist/coordination/operation.d.ts.map +1 -0
  38. package/dist/coordination/operation.js +231 -0
  39. package/dist/coordination/operation.js.map +1 -0
  40. package/dist/coordination/resource.d.ts +33 -0
  41. package/dist/coordination/resource.d.ts.map +1 -0
  42. package/dist/coordination/resource.js +95 -0
  43. package/dist/coordination/resource.js.map +1 -0
  44. package/dist/coordination/session.d.ts +74 -0
  45. package/dist/coordination/session.d.ts.map +1 -0
  46. package/dist/coordination/session.js +143 -0
  47. package/dist/coordination/session.js.map +1 -0
  48. package/dist/coordination/types.d.ts +68 -0
  49. package/dist/coordination/types.d.ts.map +1 -0
  50. package/dist/coordination/types.js +26 -0
  51. package/dist/coordination/types.js.map +1 -0
  52. package/dist/core/adaptorch-bridge.d.ts +1 -1
  53. package/dist/core/adaptorch-bridge.d.ts.map +1 -1
  54. package/dist/core/adaptorch-bridge.js +1 -1
  55. package/dist/core/adaptorch-bridge.js.map +1 -1
  56. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  57. package/dist/core/agent-session-runtime.js +16 -16
  58. package/dist/core/agent-session-runtime.js.map +1 -1
  59. package/dist/core/agent-session.d.ts.map +1 -1
  60. package/dist/core/agent-session.js +35 -15
  61. package/dist/core/agent-session.js.map +1 -1
  62. package/dist/core/canonical-json.d.ts +3 -0
  63. package/dist/core/canonical-json.d.ts.map +1 -0
  64. package/dist/core/canonical-json.js +20 -0
  65. package/dist/core/canonical-json.js.map +1 -0
  66. package/dist/core/compaction/compaction.d.ts +7 -3
  67. package/dist/core/compaction/compaction.d.ts.map +1 -1
  68. package/dist/core/compaction/compaction.js +14 -29
  69. package/dist/core/compaction/compaction.js.map +1 -1
  70. package/dist/core/compaction/control-state.d.ts +41 -0
  71. package/dist/core/compaction/control-state.d.ts.map +1 -0
  72. package/dist/core/compaction/control-state.js +85 -0
  73. package/dist/core/compaction/control-state.js.map +1 -0
  74. package/dist/core/compaction/fallback.d.ts +71 -0
  75. package/dist/core/compaction/fallback.d.ts.map +1 -0
  76. package/dist/core/compaction/fallback.js +118 -0
  77. package/dist/core/compaction/fallback.js.map +1 -0
  78. package/dist/core/compaction/index.d.ts +2 -0
  79. package/dist/core/compaction/index.d.ts.map +1 -1
  80. package/dist/core/compaction/index.js +2 -0
  81. package/dist/core/compaction/index.js.map +1 -1
  82. package/dist/core/compaction/model-failover.d.ts +21 -0
  83. package/dist/core/compaction/model-failover.d.ts.map +1 -0
  84. package/dist/core/compaction/model-failover.js +46 -0
  85. package/dist/core/compaction/model-failover.js.map +1 -0
  86. package/dist/core/compaction/session-summary.d.ts +21 -0
  87. package/dist/core/compaction/session-summary.d.ts.map +1 -0
  88. package/dist/core/compaction/session-summary.js +27 -0
  89. package/dist/core/compaction/session-summary.js.map +1 -0
  90. package/dist/core/context-budget-headroom-candidates.d.ts +16 -1
  91. package/dist/core/context-budget-headroom-candidates.d.ts.map +1 -1
  92. package/dist/core/context-budget-headroom-candidates.js +31 -13
  93. package/dist/core/context-budget-headroom-candidates.js.map +1 -1
  94. package/dist/core/context-budget-headroom-types.d.ts +7 -1
  95. package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
  96. package/dist/core/context-budget-headroom-types.js +0 -1
  97. package/dist/core/context-budget-headroom-types.js.map +1 -1
  98. package/dist/core/context-budget-headroom.d.ts +10 -0
  99. package/dist/core/context-budget-headroom.d.ts.map +1 -1
  100. package/dist/core/context-budget-headroom.js +11 -2
  101. package/dist/core/context-budget-headroom.js.map +1 -1
  102. package/dist/core/context-budget-v2-global-pass.d.ts +21 -0
  103. package/dist/core/context-budget-v2-global-pass.d.ts.map +1 -0
  104. package/dist/core/context-budget-v2-global-pass.js +203 -0
  105. package/dist/core/context-budget-v2-global-pass.js.map +1 -0
  106. package/dist/core/context-budget-v2-planned-items.d.ts +12 -0
  107. package/dist/core/context-budget-v2-planned-items.d.ts.map +1 -1
  108. package/dist/core/context-budget-v2-planned-items.js +21 -2
  109. package/dist/core/context-budget-v2-planned-items.js.map +1 -1
  110. package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
  111. package/dist/core/context-budget-v2-planner.js +18 -19
  112. package/dist/core/context-budget-v2-planner.js.map +1 -1
  113. package/dist/core/context-budget-v2-scoring.d.ts +7 -1
  114. package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
  115. package/dist/core/context-budget-v2-scoring.js.map +1 -1
  116. package/dist/core/context-budget-v2-selection.d.ts +3 -0
  117. package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
  118. package/dist/core/context-budget-v2-selection.js +6 -2
  119. package/dist/core/context-budget-v2-selection.js.map +1 -1
  120. package/dist/core/context-budget-v2-types.d.ts +6 -1
  121. package/dist/core/context-budget-v2-types.d.ts.map +1 -1
  122. package/dist/core/context-budget-v2-types.js +6 -1
  123. package/dist/core/context-budget-v2-types.js.map +1 -1
  124. package/dist/core/export-html/template.js +14 -0
  125. package/dist/core/extensions/index.d.ts +1 -1
  126. package/dist/core/extensions/index.d.ts.map +1 -1
  127. package/dist/core/extensions/index.js.map +1 -1
  128. package/dist/core/extensions/session-lifecycle-types.d.ts +14 -0
  129. package/dist/core/extensions/session-lifecycle-types.d.ts.map +1 -0
  130. package/dist/core/extensions/session-lifecycle-types.js +2 -0
  131. package/dist/core/extensions/session-lifecycle-types.js.map +1 -0
  132. package/dist/core/extensions/types.d.ts +4 -9
  133. package/dist/core/extensions/types.d.ts.map +1 -1
  134. package/dist/core/extensions/types.js.map +1 -1
  135. package/dist/core/http-dispatcher.d.ts.map +1 -1
  136. package/dist/core/http-dispatcher.js +10 -1
  137. package/dist/core/http-dispatcher.js.map +1 -1
  138. package/dist/core/keybindings.d.ts.map +1 -1
  139. package/dist/core/keybindings.js +3 -6
  140. package/dist/core/keybindings.js.map +1 -1
  141. package/dist/core/legacy-resource-policy.d.ts +7 -0
  142. package/dist/core/legacy-resource-policy.d.ts.map +1 -0
  143. package/dist/core/legacy-resource-policy.js +9 -0
  144. package/dist/core/legacy-resource-policy.js.map +1 -0
  145. package/dist/core/mcp/config.d.ts.map +1 -1
  146. package/dist/core/mcp/config.js +17 -3
  147. package/dist/core/mcp/config.js.map +1 -1
  148. package/dist/core/mcp/connection-queue.d.ts +12 -0
  149. package/dist/core/mcp/connection-queue.d.ts.map +1 -0
  150. package/dist/core/mcp/connection-queue.js +46 -0
  151. package/dist/core/mcp/connection-queue.js.map +1 -0
  152. package/dist/core/mcp/manager-runtime.d.ts +55 -0
  153. package/dist/core/mcp/manager-runtime.d.ts.map +1 -0
  154. package/dist/core/mcp/manager-runtime.js +66 -0
  155. package/dist/core/mcp/manager-runtime.js.map +1 -0
  156. package/dist/core/mcp/manager.d.ts +12 -68
  157. package/dist/core/mcp/manager.d.ts.map +1 -1
  158. package/dist/core/mcp/manager.js +33 -113
  159. package/dist/core/mcp/manager.js.map +1 -1
  160. package/dist/core/mcp/protocol.d.ts.map +1 -1
  161. package/dist/core/mcp/protocol.js +70 -40
  162. package/dist/core/mcp/protocol.js.map +1 -1
  163. package/dist/core/package-manager.d.ts +4 -0
  164. package/dist/core/package-manager.d.ts.map +1 -1
  165. package/dist/core/package-manager.js +59 -129
  166. package/dist/core/package-manager.js.map +1 -1
  167. package/dist/core/package-resource-patterns.d.ts +7 -0
  168. package/dist/core/package-resource-patterns.d.ts.map +1 -0
  169. package/dist/core/package-resource-patterns.js +99 -0
  170. package/dist/core/package-resource-patterns.js.map +1 -0
  171. package/dist/core/provider-default-models.d.ts +1 -0
  172. package/dist/core/provider-default-models.d.ts.map +1 -1
  173. package/dist/core/provider-default-models.js +1 -0
  174. package/dist/core/provider-default-models.js.map +1 -1
  175. package/dist/core/provider-display-names.d.ts.map +1 -1
  176. package/dist/core/provider-display-names.js +1 -0
  177. package/dist/core/provider-display-names.js.map +1 -1
  178. package/dist/core/provider-resilience.d.ts +9 -0
  179. package/dist/core/provider-resilience.d.ts.map +1 -1
  180. package/dist/core/provider-resilience.js +15 -0
  181. package/dist/core/provider-resilience.js.map +1 -1
  182. package/dist/core/reasoning-router-resolver.d.ts +7 -0
  183. package/dist/core/reasoning-router-resolver.d.ts.map +1 -1
  184. package/dist/core/reasoning-router-resolver.js +21 -3
  185. package/dist/core/reasoning-router-resolver.js.map +1 -1
  186. package/dist/core/reasoning-router-v4.d.ts +13 -7
  187. package/dist/core/reasoning-router-v4.d.ts.map +1 -1
  188. package/dist/core/reasoning-router-v4.js +8 -5
  189. package/dist/core/reasoning-router-v4.js.map +1 -1
  190. package/dist/core/resource-loader.d.ts.map +1 -1
  191. package/dist/core/resource-loader.js +4 -8
  192. package/dist/core/resource-loader.js.map +1 -1
  193. package/dist/core/run-execution-api.d.ts +8 -1
  194. package/dist/core/run-execution-api.d.ts.map +1 -1
  195. package/dist/core/run-execution-api.js +4 -0
  196. package/dist/core/run-execution-api.js.map +1 -1
  197. package/dist/core/run-journal.d.ts +1 -2
  198. package/dist/core/run-journal.d.ts.map +1 -1
  199. package/dist/core/run-journal.js +2 -19
  200. package/dist/core/run-journal.js.map +1 -1
  201. package/dist/core/session-compaction-service.d.ts +15 -0
  202. package/dist/core/session-compaction-service.d.ts.map +1 -1
  203. package/dist/core/session-compaction-service.js +17 -4
  204. package/dist/core/session-compaction-service.js.map +1 -1
  205. package/dist/core/session-listing.d.ts +51 -0
  206. package/dist/core/session-listing.d.ts.map +1 -0
  207. package/dist/core/session-listing.js +111 -0
  208. package/dist/core/session-listing.js.map +1 -0
  209. package/dist/core/session-manager.d.ts +12 -37
  210. package/dist/core/session-manager.d.ts.map +1 -1
  211. package/dist/core/session-manager.js +12 -118
  212. package/dist/core/session-manager.js.map +1 -1
  213. package/dist/core/session-message-text.d.ts +5 -0
  214. package/dist/core/session-message-text.d.ts.map +1 -0
  215. package/dist/core/session-message-text.js +9 -0
  216. package/dist/core/session-message-text.js.map +1 -0
  217. package/dist/core/skills-catalog-cache.d.ts +2 -0
  218. package/dist/core/skills-catalog-cache.d.ts.map +1 -1
  219. package/dist/core/skills-catalog-cache.js +71 -17
  220. package/dist/core/skills-catalog-cache.js.map +1 -1
  221. package/dist/core/todo-runtime-state.d.ts +12 -0
  222. package/dist/core/todo-runtime-state.d.ts.map +1 -1
  223. package/dist/core/todo-runtime-state.js +23 -0
  224. package/dist/core/todo-runtime-state.js.map +1 -1
  225. package/dist/core/tools/read.d.ts.map +1 -1
  226. package/dist/core/tools/read.js +1 -1
  227. package/dist/core/tools/read.js.map +1 -1
  228. package/dist/core/verified-run/authority-clock.d.ts +3 -0
  229. package/dist/core/verified-run/authority-clock.d.ts.map +1 -0
  230. package/dist/core/verified-run/authority-clock.js +25 -0
  231. package/dist/core/verified-run/authority-clock.js.map +1 -0
  232. package/dist/core/verified-run/authority-errors.d.ts +10 -0
  233. package/dist/core/verified-run/authority-errors.d.ts.map +1 -0
  234. package/dist/core/verified-run/authority-errors.js +17 -0
  235. package/dist/core/verified-run/authority-errors.js.map +1 -0
  236. package/dist/core/verified-run/authority-events.d.ts +126 -0
  237. package/dist/core/verified-run/authority-events.d.ts.map +1 -0
  238. package/dist/core/verified-run/authority-events.js +482 -0
  239. package/dist/core/verified-run/authority-events.js.map +1 -0
  240. package/dist/core/verified-run/authority-journal.d.ts +27 -0
  241. package/dist/core/verified-run/authority-journal.d.ts.map +1 -0
  242. package/dist/core/verified-run/authority-journal.js +83 -0
  243. package/dist/core/verified-run/authority-journal.js.map +1 -0
  244. package/dist/core/verified-run/authority-meaning.d.ts +13 -0
  245. package/dist/core/verified-run/authority-meaning.d.ts.map +1 -0
  246. package/dist/core/verified-run/authority-meaning.js +40 -0
  247. package/dist/core/verified-run/authority-meaning.js.map +1 -0
  248. package/dist/core/verified-run/authority-runtime.d.ts +82 -0
  249. package/dist/core/verified-run/authority-runtime.d.ts.map +1 -0
  250. package/dist/core/verified-run/authority-runtime.js +169 -0
  251. package/dist/core/verified-run/authority-runtime.js.map +1 -0
  252. package/dist/core/verified-run/authority-store.d.ts +204 -0
  253. package/dist/core/verified-run/authority-store.d.ts.map +1 -0
  254. package/dist/core/verified-run/authority-store.js +852 -0
  255. package/dist/core/verified-run/authority-store.js.map +1 -0
  256. package/dist/core/verified-run/broker.d.ts +8 -1
  257. package/dist/core/verified-run/broker.d.ts.map +1 -1
  258. package/dist/core/verified-run/broker.js +94 -90
  259. package/dist/core/verified-run/broker.js.map +1 -1
  260. package/dist/core/verified-run/candidate-policy.d.ts +10 -0
  261. package/dist/core/verified-run/candidate-policy.d.ts.map +1 -0
  262. package/dist/core/verified-run/candidate-policy.js +33 -0
  263. package/dist/core/verified-run/candidate-policy.js.map +1 -0
  264. package/dist/core/verified-run/candidate.d.ts.map +1 -1
  265. package/dist/core/verified-run/candidate.js +5 -10
  266. package/dist/core/verified-run/candidate.js.map +1 -1
  267. package/dist/core/verified-run/coordinator.d.ts +35 -17
  268. package/dist/core/verified-run/coordinator.d.ts.map +1 -1
  269. package/dist/core/verified-run/coordinator.js +111 -57
  270. package/dist/core/verified-run/coordinator.js.map +1 -1
  271. package/dist/core/verified-run/dag-phase.d.ts.map +1 -1
  272. package/dist/core/verified-run/dag-phase.js +1 -1
  273. package/dist/core/verified-run/dag-phase.js.map +1 -1
  274. package/dist/core/verified-run/dag-recovery.d.ts +5 -1
  275. package/dist/core/verified-run/dag-recovery.d.ts.map +1 -1
  276. package/dist/core/verified-run/dag-recovery.js +10 -4
  277. package/dist/core/verified-run/dag-recovery.js.map +1 -1
  278. package/dist/core/verified-run/event-parser.d.ts.map +1 -1
  279. package/dist/core/verified-run/event-parser.js +33 -0
  280. package/dist/core/verified-run/event-parser.js.map +1 -1
  281. package/dist/core/verified-run/evidence-read-projection.d.ts +4 -0
  282. package/dist/core/verified-run/evidence-read-projection.d.ts.map +1 -0
  283. package/dist/core/verified-run/evidence-read-projection.js +27 -0
  284. package/dist/core/verified-run/evidence-read-projection.js.map +1 -0
  285. package/dist/core/verified-run/evidence.d.ts +12 -1
  286. package/dist/core/verified-run/evidence.d.ts.map +1 -1
  287. package/dist/core/verified-run/evidence.js +51 -2
  288. package/dist/core/verified-run/evidence.js.map +1 -1
  289. package/dist/core/verified-run/git-candidate-preflight.d.ts +4 -0
  290. package/dist/core/verified-run/git-candidate-preflight.d.ts.map +1 -0
  291. package/dist/core/verified-run/git-candidate-preflight.js +34 -0
  292. package/dist/core/verified-run/git-candidate-preflight.js.map +1 -0
  293. package/dist/core/verified-run/git-effect-supervisor.d.ts +24 -0
  294. package/dist/core/verified-run/git-effect-supervisor.d.ts.map +1 -0
  295. package/dist/core/verified-run/git-effect-supervisor.js +174 -0
  296. package/dist/core/verified-run/git-effect-supervisor.js.map +1 -0
  297. package/dist/core/verified-run/git-execution.d.ts +27 -0
  298. package/dist/core/verified-run/git-execution.d.ts.map +1 -0
  299. package/dist/core/verified-run/git-execution.js +118 -0
  300. package/dist/core/verified-run/git-execution.js.map +1 -0
  301. package/dist/core/verified-run/git-plumbing.d.ts +37 -0
  302. package/dist/core/verified-run/git-plumbing.d.ts.map +1 -0
  303. package/dist/core/verified-run/git-plumbing.js +171 -0
  304. package/dist/core/verified-run/git-plumbing.js.map +1 -0
  305. package/dist/core/verified-run/git-publication-worker.d.ts +2 -0
  306. package/dist/core/verified-run/git-publication-worker.d.ts.map +1 -0
  307. package/dist/core/verified-run/git-publication-worker.js +54 -0
  308. package/dist/core/verified-run/git-publication-worker.js.map +1 -0
  309. package/dist/core/verified-run/git-sandbox-layout.d.ts +4 -0
  310. package/dist/core/verified-run/git-sandbox-layout.d.ts.map +1 -0
  311. package/dist/core/verified-run/git-sandbox-layout.js +29 -0
  312. package/dist/core/verified-run/git-sandbox-layout.js.map +1 -0
  313. package/dist/core/verified-run/git-worker-protocol.d.ts +19 -0
  314. package/dist/core/verified-run/git-worker-protocol.d.ts.map +1 -0
  315. package/dist/core/verified-run/git-worker-protocol.js +109 -0
  316. package/dist/core/verified-run/git-worker-protocol.js.map +1 -0
  317. package/dist/core/verified-run/git-worker-runtime.d.ts +19 -0
  318. package/dist/core/verified-run/git-worker-runtime.d.ts.map +1 -0
  319. package/dist/core/verified-run/git-worker-runtime.js +74 -0
  320. package/dist/core/verified-run/git-worker-runtime.js.map +1 -0
  321. package/dist/core/verified-run/journal.d.ts +2 -3
  322. package/dist/core/verified-run/journal.d.ts.map +1 -1
  323. package/dist/core/verified-run/journal.js.map +1 -1
  324. package/dist/core/verified-run/namespace-identity.d.ts.map +1 -1
  325. package/dist/core/verified-run/namespace-identity.js +1 -1
  326. package/dist/core/verified-run/namespace-identity.js.map +1 -1
  327. package/dist/core/verified-run/owned-execution.d.ts +10 -1
  328. package/dist/core/verified-run/owned-execution.d.ts.map +1 -1
  329. package/dist/core/verified-run/owned-execution.js +124 -31
  330. package/dist/core/verified-run/owned-execution.js.map +1 -1
  331. package/dist/core/verified-run/phase-context.d.ts +2 -0
  332. package/dist/core/verified-run/phase-context.d.ts.map +1 -1
  333. package/dist/core/verified-run/phase-context.js.map +1 -1
  334. package/dist/core/verified-run/projection.d.ts.map +1 -1
  335. package/dist/core/verified-run/projection.js +51 -1
  336. package/dist/core/verified-run/projection.js.map +1 -1
  337. package/dist/core/verified-run/publish-preflight.d.ts +12 -0
  338. package/dist/core/verified-run/publish-preflight.d.ts.map +1 -0
  339. package/dist/core/verified-run/publish-preflight.js +38 -0
  340. package/dist/core/verified-run/publish-preflight.js.map +1 -0
  341. package/dist/core/verified-run/publish-start.d.ts +5 -0
  342. package/dist/core/verified-run/publish-start.d.ts.map +1 -0
  343. package/dist/core/verified-run/publish-start.js +7 -0
  344. package/dist/core/verified-run/publish-start.js.map +1 -0
  345. package/dist/core/verified-run/recovery-projection.d.ts.map +1 -1
  346. package/dist/core/verified-run/recovery-projection.js +5 -0
  347. package/dist/core/verified-run/recovery-projection.js.map +1 -1
  348. package/dist/core/verified-run/recovery.d.ts +5 -1
  349. package/dist/core/verified-run/recovery.d.ts.map +1 -1
  350. package/dist/core/verified-run/recovery.js +10 -4
  351. package/dist/core/verified-run/recovery.js.map +1 -1
  352. package/dist/core/verified-run/run-plan.d.ts +17 -0
  353. package/dist/core/verified-run/run-plan.d.ts.map +1 -0
  354. package/dist/core/verified-run/run-plan.js +18 -0
  355. package/dist/core/verified-run/run-plan.js.map +1 -0
  356. package/dist/core/verified-run/run-publish-owned.d.ts +6 -0
  357. package/dist/core/verified-run/run-publish-owned.d.ts.map +1 -0
  358. package/dist/core/verified-run/run-publish-owned.js +199 -0
  359. package/dist/core/verified-run/run-publish-owned.js.map +1 -0
  360. package/dist/core/verified-run/run-publish.d.ts +19 -0
  361. package/dist/core/verified-run/run-publish.d.ts.map +1 -0
  362. package/dist/core/verified-run/run-publish.js +210 -0
  363. package/dist/core/verified-run/run-publish.js.map +1 -0
  364. package/dist/core/verified-run/run-status-owned.d.ts +4 -0
  365. package/dist/core/verified-run/run-status-owned.d.ts.map +1 -0
  366. package/dist/core/verified-run/run-status-owned.js +14 -0
  367. package/dist/core/verified-run/run-status-owned.js.map +1 -0
  368. package/dist/core/verified-run/run-status.d.ts +133 -0
  369. package/dist/core/verified-run/run-status.d.ts.map +1 -0
  370. package/dist/core/verified-run/run-status.js +193 -0
  371. package/dist/core/verified-run/run-status.js.map +1 -0
  372. package/dist/core/verified-run/run-types.d.ts +31 -0
  373. package/dist/core/verified-run/run-types.d.ts.map +1 -1
  374. package/dist/core/verified-run/run-types.js.map +1 -1
  375. package/dist/core/verified-run/storage.d.ts.map +1 -1
  376. package/dist/core/verified-run/storage.js +1 -1
  377. package/dist/core/verified-run/storage.js.map +1 -1
  378. package/dist/core/verified-run/supervisor-adapter.d.ts +77 -0
  379. package/dist/core/verified-run/supervisor-adapter.d.ts.map +1 -0
  380. package/dist/core/verified-run/supervisor-adapter.js +164 -0
  381. package/dist/core/verified-run/supervisor-adapter.js.map +1 -0
  382. package/dist/core/verified-run/verification-phase.d.ts.map +1 -1
  383. package/dist/core/verified-run/verification-phase.js +1 -1
  384. package/dist/core/verified-run/verification-phase.js.map +1 -1
  385. package/dist/core/verified-run/writer-phase.d.ts.map +1 -1
  386. package/dist/core/verified-run/writer-phase.js +1 -0
  387. package/dist/core/verified-run/writer-phase.js.map +1 -1
  388. package/dist/core/verified-run/writer-recovery.d.ts +2 -0
  389. package/dist/core/verified-run/writer-recovery.d.ts.map +1 -1
  390. package/dist/core/verified-run/writer-recovery.js +1 -0
  391. package/dist/core/verified-run/writer-recovery.js.map +1 -1
  392. package/dist/core/workload-shard-execution-types.d.ts +4 -1
  393. package/dist/core/workload-shard-execution-types.d.ts.map +1 -1
  394. package/dist/core/workload-shard-execution-types.js.map +1 -1
  395. package/dist/core/workload-shard-executor.d.ts +2 -2
  396. package/dist/core/workload-shard-executor.d.ts.map +1 -1
  397. package/dist/core/workload-shard-executor.js +16 -37
  398. package/dist/core/workload-shard-executor.js.map +1 -1
  399. package/dist/core/workload-shard-frontier.d.ts +5 -0
  400. package/dist/core/workload-shard-frontier.d.ts.map +1 -0
  401. package/dist/core/workload-shard-frontier.js +47 -0
  402. package/dist/core/workload-shard-frontier.js.map +1 -0
  403. package/dist/core/workload-shard-runner.d.ts.map +1 -1
  404. package/dist/core/workload-shard-runner.js +28 -17
  405. package/dist/core/workload-shard-runner.js.map +1 -1
  406. package/dist/index.d.ts +4 -5
  407. package/dist/index.d.ts.map +1 -1
  408. package/dist/index.js +3 -4
  409. package/dist/index.js.map +1 -1
  410. package/dist/main.d.ts.map +1 -1
  411. package/dist/main.js +2 -1
  412. package/dist/main.js.map +1 -1
  413. package/dist/metacognition/bridge-result.d.ts +148 -0
  414. package/dist/metacognition/bridge-result.d.ts.map +1 -0
  415. package/dist/metacognition/bridge-result.js +46 -0
  416. package/dist/metacognition/bridge-result.js.map +1 -0
  417. package/dist/metacognition/calibration-selective.d.ts +78 -0
  418. package/dist/metacognition/calibration-selective.d.ts.map +1 -0
  419. package/dist/metacognition/calibration-selective.js +167 -0
  420. package/dist/metacognition/calibration-selective.js.map +1 -0
  421. package/dist/metacognition/calibration.d.ts +62 -0
  422. package/dist/metacognition/calibration.d.ts.map +1 -0
  423. package/dist/metacognition/calibration.js +122 -0
  424. package/dist/metacognition/calibration.js.map +1 -0
  425. package/dist/metacognition/checkpoint.d.ts +60 -0
  426. package/dist/metacognition/checkpoint.d.ts.map +1 -0
  427. package/dist/metacognition/checkpoint.js +57 -0
  428. package/dist/metacognition/checkpoint.js.map +1 -0
  429. package/dist/metacognition/context7.d.ts +48 -0
  430. package/dist/metacognition/context7.d.ts.map +1 -0
  431. package/dist/metacognition/context7.js +154 -0
  432. package/dist/metacognition/context7.js.map +1 -0
  433. package/dist/metacognition/decision.d.ts +44 -0
  434. package/dist/metacognition/decision.d.ts.map +1 -0
  435. package/dist/metacognition/decision.js +111 -0
  436. package/dist/metacognition/decision.js.map +1 -0
  437. package/dist/metacognition/evaluation.d.ts +73 -0
  438. package/dist/metacognition/evaluation.d.ts.map +1 -0
  439. package/dist/metacognition/evaluation.js +97 -0
  440. package/dist/metacognition/evaluation.js.map +1 -0
  441. package/dist/metacognition/index.d.ts +32 -0
  442. package/dist/metacognition/index.d.ts.map +1 -0
  443. package/dist/metacognition/index.js +32 -0
  444. package/dist/metacognition/index.js.map +1 -0
  445. package/dist/metacognition/knowledge-action.d.ts +43 -0
  446. package/dist/metacognition/knowledge-action.d.ts.map +1 -0
  447. package/dist/metacognition/knowledge-action.js +60 -0
  448. package/dist/metacognition/knowledge-action.js.map +1 -0
  449. package/dist/metacognition/knowledge.d.ts +84 -0
  450. package/dist/metacognition/knowledge.d.ts.map +1 -0
  451. package/dist/metacognition/knowledge.js +165 -0
  452. package/dist/metacognition/knowledge.js.map +1 -0
  453. package/dist/metacognition/obligations.d.ts +82 -0
  454. package/dist/metacognition/obligations.d.ts.map +1 -0
  455. package/dist/metacognition/obligations.js +139 -0
  456. package/dist/metacognition/obligations.js.map +1 -0
  457. package/dist/metacognition/observation-validity.d.ts +83 -0
  458. package/dist/metacognition/observation-validity.d.ts.map +1 -0
  459. package/dist/metacognition/observation-validity.js +118 -0
  460. package/dist/metacognition/observation-validity.js.map +1 -0
  461. package/dist/metacognition/observe.d.ts +45 -0
  462. package/dist/metacognition/observe.d.ts.map +1 -0
  463. package/dist/metacognition/observe.js +59 -0
  464. package/dist/metacognition/observe.js.map +1 -0
  465. package/dist/metacognition/policy.d.ts +53 -0
  466. package/dist/metacognition/policy.d.ts.map +1 -0
  467. package/dist/metacognition/policy.js +155 -0
  468. package/dist/metacognition/policy.js.map +1 -0
  469. package/dist/metacognition/predictions.d.ts +78 -0
  470. package/dist/metacognition/predictions.d.ts.map +1 -0
  471. package/dist/metacognition/predictions.js +181 -0
  472. package/dist/metacognition/predictions.js.map +1 -0
  473. package/dist/metacognition/retrieval.d.ts +53 -0
  474. package/dist/metacognition/retrieval.d.ts.map +1 -0
  475. package/dist/metacognition/retrieval.js +170 -0
  476. package/dist/metacognition/retrieval.js.map +1 -0
  477. package/dist/metacognition/risk.d.ts +48 -0
  478. package/dist/metacognition/risk.d.ts.map +1 -0
  479. package/dist/metacognition/risk.js +179 -0
  480. package/dist/metacognition/risk.js.map +1 -0
  481. package/dist/metacognition/route-economics.d.ts +95 -0
  482. package/dist/metacognition/route-economics.d.ts.map +1 -0
  483. package/dist/metacognition/route-economics.js +110 -0
  484. package/dist/metacognition/route-economics.js.map +1 -0
  485. package/dist/metacognition/runtime-bridge.d.ts +81 -0
  486. package/dist/metacognition/runtime-bridge.d.ts.map +1 -0
  487. package/dist/metacognition/runtime-bridge.js +458 -0
  488. package/dist/metacognition/runtime-bridge.js.map +1 -0
  489. package/dist/metacognition/skills.d.ts +42 -0
  490. package/dist/metacognition/skills.d.ts.map +1 -0
  491. package/dist/metacognition/skills.js +220 -0
  492. package/dist/metacognition/skills.js.map +1 -0
  493. package/dist/metacognition/state.d.ts +110 -0
  494. package/dist/metacognition/state.d.ts.map +1 -0
  495. package/dist/metacognition/state.js +52 -0
  496. package/dist/metacognition/state.js.map +1 -0
  497. package/dist/metacognition/validation.d.ts +19 -0
  498. package/dist/metacognition/validation.d.ts.map +1 -0
  499. package/dist/metacognition/validation.js +58 -0
  500. package/dist/metacognition/validation.js.map +1 -0
  501. package/dist/metacognition/verification.d.ts +93 -0
  502. package/dist/metacognition/verification.d.ts.map +1 -0
  503. package/dist/metacognition/verification.js +132 -0
  504. package/dist/metacognition/verification.js.map +1 -0
  505. package/dist/metacognition/verifier.d.ts +49 -0
  506. package/dist/metacognition/verifier.d.ts.map +1 -0
  507. package/dist/metacognition/verifier.js +88 -0
  508. package/dist/metacognition/verifier.js.map +1 -0
  509. package/dist/modes/interactive/components/assistant-message.d.ts +2 -0
  510. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  511. package/dist/modes/interactive/components/assistant-message.js +42 -26
  512. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  513. package/dist/modes/interactive/components/chat-container.d.ts +7 -0
  514. package/dist/modes/interactive/components/chat-container.d.ts.map +1 -0
  515. package/dist/modes/interactive/components/chat-container.js +14 -0
  516. package/dist/modes/interactive/components/chat-container.js.map +1 -0
  517. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  518. package/dist/modes/interactive/components/dynamic-border.js +4 -2
  519. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  520. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  521. package/dist/modes/interactive/components/login-dialog.js +0 -1
  522. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  523. package/dist/modes/interactive/components/session-selector-async-search.d.ts +33 -0
  524. package/dist/modes/interactive/components/session-selector-async-search.d.ts.map +1 -0
  525. package/dist/modes/interactive/components/session-selector-async-search.js +109 -0
  526. package/dist/modes/interactive/components/session-selector-async-search.js.map +1 -0
  527. package/dist/modes/interactive/components/session-selector-loaders.d.ts +6 -0
  528. package/dist/modes/interactive/components/session-selector-loaders.d.ts.map +1 -0
  529. package/dist/modes/interactive/components/session-selector-loaders.js +9 -0
  530. package/dist/modes/interactive/components/session-selector-loaders.js.map +1 -0
  531. package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
  532. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  533. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  534. package/dist/modes/interactive/components/session-selector-tree.d.ts +16 -0
  535. package/dist/modes/interactive/components/session-selector-tree.d.ts.map +1 -0
  536. package/dist/modes/interactive/components/session-selector-tree.js +46 -0
  537. package/dist/modes/interactive/components/session-selector-tree.js.map +1 -0
  538. package/dist/modes/interactive/components/session-selector.d.ts +6 -1
  539. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  540. package/dist/modes/interactive/components/session-selector.js +36 -76
  541. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  542. package/dist/modes/interactive/components/tool-execution-images.d.ts +32 -0
  543. package/dist/modes/interactive/components/tool-execution-images.d.ts.map +1 -0
  544. package/dist/modes/interactive/components/tool-execution-images.js +144 -0
  545. package/dist/modes/interactive/components/tool-execution-images.js.map +1 -0
  546. package/dist/modes/interactive/components/tool-execution.d.ts +3 -4
  547. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  548. package/dist/modes/interactive/components/tool-execution.js +22 -71
  549. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  550. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  551. package/dist/modes/interactive/interactive-mode.js +7 -9
  552. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  553. package/dist/modes/interactive/tui-diagnostics.d.ts +8 -4
  554. package/dist/modes/interactive/tui-diagnostics.d.ts.map +1 -1
  555. package/dist/modes/interactive/tui-diagnostics.js +35 -1
  556. package/dist/modes/interactive/tui-diagnostics.js.map +1 -1
  557. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  558. package/dist/modes/rpc/rpc-mode.js +14 -17
  559. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  560. package/dist/modes/rpc/rpc-response.d.ts +5 -0
  561. package/dist/modes/rpc/rpc-response.d.ts.map +1 -0
  562. package/dist/modes/rpc/rpc-response.js +17 -0
  563. package/dist/modes/rpc/rpc-response.js.map +1 -0
  564. package/dist/observation/identity.d.ts +14 -0
  565. package/dist/observation/identity.d.ts.map +1 -0
  566. package/dist/observation/identity.js +29 -0
  567. package/dist/observation/identity.js.map +1 -0
  568. package/dist/observation/index.d.ts +13 -0
  569. package/dist/observation/index.d.ts.map +1 -0
  570. package/dist/observation/index.js +13 -0
  571. package/dist/observation/index.js.map +1 -0
  572. package/dist/observation/observe-mode.d.ts +46 -0
  573. package/dist/observation/observe-mode.d.ts.map +1 -0
  574. package/dist/observation/observe-mode.js +83 -0
  575. package/dist/observation/observe-mode.js.map +1 -0
  576. package/dist/observation/store.d.ts +53 -0
  577. package/dist/observation/store.d.ts.map +1 -0
  578. package/dist/observation/store.js +126 -0
  579. package/dist/observation/store.js.map +1 -0
  580. package/dist/observation/types.d.ts +72 -0
  581. package/dist/observation/types.d.ts.map +1 -0
  582. package/dist/observation/types.js +9 -0
  583. package/dist/observation/types.js.map +1 -0
  584. package/dist/observation/view.d.ts +39 -0
  585. package/dist/observation/view.d.ts.map +1 -0
  586. package/dist/observation/view.js +173 -0
  587. package/dist/observation/view.js.map +1 -0
  588. package/dist/utils/exif-orientation.d.ts.map +1 -1
  589. package/dist/utils/exif-orientation.js +2 -3
  590. package/dist/utils/exif-orientation.js.map +1 -1
  591. package/dist/utils/tools-manager.d.ts.map +1 -1
  592. package/dist/utils/tools-manager.js +3 -5
  593. package/dist/utils/tools-manager.js.map +1 -1
  594. package/docs/adaptorch-preview-spec.md +7 -7
  595. package/docs/atomic-commit-planning.md +69 -0
  596. package/docs/compaction.md +26 -1
  597. package/docs/extensions.md +14 -0
  598. package/docs/mcp.md +22 -0
  599. package/docs/metacognition.md +130 -0
  600. package/docs/model-catalog-refresh.md +218 -1
  601. package/docs/models.md +1 -1
  602. package/docs/providers.md +53 -0
  603. package/docs/runtime-algorithms.md +156 -7
  604. package/docs/session-format.md +8 -0
  605. package/docs/sessions.md +19 -0
  606. package/docs/skills.md +19 -0
  607. package/docs/terminal-setup.md +15 -0
  608. package/docs/tui.md +41 -0
  609. package/docs/verified-run-safety.md +75 -0
  610. package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
  611. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  612. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  613. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  614. package/examples/extensions/doom-overlay/wad-finder.ts +7 -3
  615. package/examples/extensions/gondolin/package-lock.json +2 -2
  616. package/examples/extensions/gondolin/package.json +1 -1
  617. package/examples/extensions/sandbox/package-lock.json +2 -2
  618. package/examples/extensions/sandbox/package.json +1 -1
  619. package/examples/extensions/with-deps/package-lock.json +2 -2
  620. package/examples/extensions/with-deps/package.json +1 -1
  621. package/npm-shrinkwrap.json +18 -18
  622. package/package.json +6 -8
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation.js","sourceRoot":"","sources":["../../src/coordination/operation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Authorized operation lifecycle for GUI-driving adapters (Jev audit A6).\n *\n * Two reproduced defects shape this module:\n * F01 — an adapter re-interpreted a free-text instruction at execution time,\n * so an approved candidate and the executed action could differ. Here\n * dispatch consumes a recorded observation binding, never a sentence.\n * F02 — a cancellation signal was accepted and then ignored across the\n * approval await, so a cancelled operation still dispatched. Here the\n * permit is re-evaluated at the dispatch boundary, and cancellation\n * after dispatch can never be reported as cancelled-before-dispatch.\n *\n * Pure state machine: no browser, no driver, no timers. \"Dispatched\" means the\n * command left this process, which is not evidence about the remote effect —\n * that is why `outcome-unknown` is a first-class state rather than a failure.\n */\n\nimport type { Sequence } from \"./types.ts\";\nimport { sequence } from \"./types.ts\";\n\nexport type OperationState =\n\t| \"created\"\n\t| \"observed\"\n\t| \"proposed\"\n\t| \"authorized\"\n\t| \"dispatched\"\n\t| \"applied\"\n\t| \"verified\"\n\t| \"inspection-required\"\n\t| \"failed-confirmed\"\n\t| \"outcome-unknown\"\n\t| \"cancelled-before-dispatch\";\n\n/** Outcomes a driver may report once a command has left the process. */\nexport type SettledOutcome = \"applied\" | \"failed-confirmed\" | \"outcome-unknown\";\n\nconst TERMINAL_STATES: ReadonlySet<OperationState> = new Set<OperationState>([\n\t\"verified\",\n\t\"inspection-required\",\n\t\"failed-confirmed\",\n\t\"cancelled-before-dispatch\",\n]);\n\n/**\n * Host-held reference to one observed candidate.\n *\n * The adapter receives these identifiers, not an instruction string, so the\n * action that was approved is the action that runs.\n */\nexport interface ObservationBinding {\n\treadonly observationId: string;\n\treadonly actionId: string;\n\treadonly targetId: string;\n\t/** Document/DOM generation the candidate was observed against. */\n\treadonly documentGeneration: Sequence;\n}\n\nexport type PermitDenial =\n\t| \"cancelled\"\n\t| \"policy-denied\"\n\t| \"approval-mismatch\"\n\t| \"stale-lease\"\n\t| \"observation-invalid\"\n\t| \"budget-exhausted\";\n\nexport type PermitDecision = { readonly allowed: true } | { readonly allowed: false; readonly reason: PermitDenial };\n\nexport interface PermitInput {\n\treadonly policyAllowed: boolean;\n\t/** Digest of the intent actually about to run. */\n\treadonly intentDigest: string;\n\t/** Digest the operator approved; a post-approval edit breaks this equality. */\n\treadonly approvalDigest: string;\n\treadonly policyVersion: string;\n\treadonly approvalPolicyVersion: string;\n\treadonly leaseGeneration: Sequence;\n\treadonly currentLeaseGeneration: Sequence;\n\treadonly observationValid: boolean;\n\treadonly cancelled: boolean;\n\treadonly budgetAvailable: boolean;\n}\n\n/**\n * Permit(I) = PolicyAllowed ∧ ApprovalMatches ∧ LeaseCurrent ∧ ObservationValid\n * ∧ ¬Cancelled ∧ BudgetAvailable.\n *\n * Cancellation is reported first: when a run is cancelled, saying \"budget\n * exhausted\" would send the operator looking for the wrong problem.\n */\nexport function evaluatePermit(input: PermitInput): PermitDecision {\n\tfor (const value of [input.cancelled, input.policyAllowed, input.observationValid, input.budgetAvailable]) {\n\t\tif (typeof value !== \"boolean\") throw new TypeError(\"permit flags must be booleans\");\n\t}\n\tfor (const value of [input.intentDigest, input.approvalDigest, input.policyVersion, input.approvalPolicyVersion]) {\n\t\tif (typeof value !== \"string\" || value.length === 0 || value.length > 4096) {\n\t\t\tthrow new TypeError(\"permit binding must be a bounded non-empty string\");\n\t\t}\n\t}\n\tsequence(input.leaseGeneration);\n\tsequence(input.currentLeaseGeneration);\n\tif (input.cancelled) return { allowed: false, reason: \"cancelled\" };\n\tif (!input.policyAllowed) return { allowed: false, reason: \"policy-denied\" };\n\tif (input.approvalDigest !== input.intentDigest || input.approvalPolicyVersion !== input.policyVersion) {\n\t\treturn { allowed: false, reason: \"approval-mismatch\" };\n\t}\n\tif (input.leaseGeneration !== input.currentLeaseGeneration) return { allowed: false, reason: \"stale-lease\" };\n\tif (!input.observationValid) return { allowed: false, reason: \"observation-invalid\" };\n\tif (!input.budgetAvailable) return { allowed: false, reason: \"budget-exhausted\" };\n\treturn { allowed: true };\n}\n\nexport class OperationLifecycle {\n\treadonly operationId: string;\n\tprivate current: OperationState = \"created\";\n\tprivate readonly states: OperationState[] = [\"created\"];\n\tprivate observations: readonly ObservationBinding[] = [];\n\tprivate selected: ObservationBinding | undefined;\n\tprivate authorizedPermit: Readonly<PermitInput> | undefined;\n\tprivate hasDispatched = false;\n\tprivate cancelRequested = false;\n\n\tconstructor(operationId: string) {\n\t\tif (typeof operationId !== \"string\" || operationId.length === 0) {\n\t\t\tthrow new TypeError(\"operationId must be a non-empty string\");\n\t\t}\n\t\tthis.operationId = operationId;\n\t}\n\n\tget state(): OperationState {\n\t\treturn this.current;\n\t}\n\n\tget history(): readonly OperationState[] {\n\t\treturn [...this.states];\n\t}\n\n\t/** True once a command left this process; it says nothing about the effect. */\n\tget dispatched(): boolean {\n\t\treturn this.hasDispatched;\n\t}\n\n\tget cancellationRequested(): boolean {\n\t\treturn this.cancelRequested;\n\t}\n\n\tprivate enter(next: OperationState): void {\n\t\tthis.current = next;\n\t\tthis.states.push(next);\n\t}\n\n\tprivate assertOpen(): void {\n\t\tif (TERMINAL_STATES.has(this.current)) {\n\t\t\tthrow new Error(`operation ${this.operationId} is terminal in state ${this.current}`);\n\t\t}\n\t}\n\n\t/** Record the host-held candidate set. Without this, nothing can dispatch. */\n\tobserve(candidates: readonly ObservationBinding[]): void {\n\t\tthis.assertOpen();\n\t\tif (candidates.length === 0) throw new TypeError(\"observation must yield at least one candidate\");\n\t\tif (this.current !== \"created\" && this.current !== \"observed\") {\n\t\t\tthrow new Error(\"observe requires a created or observed operation\");\n\t\t}\n\t\tconst snapshots = candidates.map((candidate) => {\n\t\t\tfor (const value of [candidate.observationId, candidate.actionId, candidate.targetId]) {\n\t\t\t\tif (typeof value !== \"string\" || value.length === 0 || value.length > 4096) {\n\t\t\t\t\tthrow new TypeError(\"observation binding must be a bounded non-empty string\");\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Object.freeze({\n\t\t\t\tobservationId: candidate.observationId,\n\t\t\t\tactionId: candidate.actionId,\n\t\t\t\ttargetId: candidate.targetId,\n\t\t\t\tdocumentGeneration: sequence(candidate.documentGeneration),\n\t\t\t});\n\t\t});\n\t\tthis.observations = Object.freeze(snapshots);\n\t\tthis.enter(\"observed\");\n\t}\n\n\t/** Select one observed candidate. Free-text re-interpretation has no path here. */\n\tpropose(candidate: ObservationBinding): void {\n\t\tthis.assertOpen();\n\t\tif (this.observations.length === 0) {\n\t\t\tthrow new Error(\"cannot propose before observe: the candidate set is unbound\");\n\t\t}\n\t\tif (this.current !== \"observed\" && this.current !== \"proposed\") {\n\t\t\tthrow new Error(\"propose requires an observed or proposed operation\");\n\t\t}\n\t\tconst match = this.observations.find(\n\t\t\t(o) =>\n\t\t\t\to.observationId === candidate.observationId &&\n\t\t\t\to.actionId === candidate.actionId &&\n\t\t\t\to.targetId === candidate.targetId &&\n\t\t\t\to.documentGeneration === candidate.documentGeneration,\n\t\t);\n\t\tif (match === undefined) throw new Error(\"proposed action is not among the recorded observations\");\n\t\tthis.selected = match;\n\t\tthis.enter(\"proposed\");\n\t}\n\n\tauthorize(permit: PermitInput): PermitDecision {\n\t\tthis.assertOpen();\n\t\tif (this.current !== \"proposed\") throw new Error(\"authorize requires a proposed operation\");\n\t\tconst decision = evaluatePermit(permit);\n\t\tif (!decision.allowed) {\n\t\t\tthis.applyPreDispatchDenial(decision.reason);\n\t\t\treturn decision;\n\t\t}\n\t\tthis.authorizedPermit = Object.freeze({ ...permit });\n\t\tthis.enter(\"authorized\");\n\t\treturn decision;\n\t}\n\n\t/**\n\t * Re-evaluate the permit and hand the command to the driver.\n\t *\n\t * The second evaluation is the point of the audit finding: approval and\n\t * dispatch are separated by awaits (queueing, the operator prompt, browser\n\t * startup), and state observed before those awaits is not state now.\n\t */\n\tdispatch(permit: PermitInput): PermitDecision {\n\t\tthis.assertOpen();\n\t\tif (this.current !== \"authorized\") throw new Error(\"dispatch requires an authorized operation\");\n\t\tif (this.selected === undefined) throw new Error(\"dispatch requires a bound observation\");\n\t\tconst decision = evaluatePermit(permit);\n\t\tif (!decision.allowed) {\n\t\t\tthis.applyPreDispatchDenial(decision.reason);\n\t\t\treturn decision;\n\t\t}\n\t\tconst approved = this.authorizedPermit;\n\t\tif (\n\t\t\tapproved === undefined ||\n\t\t\tapproved.intentDigest !== permit.intentDigest ||\n\t\t\tapproved.approvalDigest !== permit.approvalDigest ||\n\t\t\tapproved.policyVersion !== permit.policyVersion ||\n\t\t\tapproved.approvalPolicyVersion !== permit.approvalPolicyVersion\n\t\t) {\n\t\t\treturn { allowed: false, reason: \"approval-mismatch\" };\n\t\t}\n\t\tif (approved.leaseGeneration !== permit.leaseGeneration) {\n\t\t\treturn { allowed: false, reason: \"stale-lease\" };\n\t\t}\n\t\tthis.hasDispatched = true;\n\t\tthis.enter(\"dispatched\");\n\t\treturn decision;\n\t}\n\n\tprivate applyPreDispatchDenial(reason: PermitDenial): void {\n\t\tif (reason === \"cancelled\") {\n\t\t\tthis.cancelRequested = true;\n\t\t\tthis.enter(\"cancelled-before-dispatch\");\n\t\t}\n\t}\n\n\t/** Driver-reported outcome. Only valid once the command actually left. */\n\tsettle(outcome: SettledOutcome): void {\n\t\tif (!this.hasDispatched) throw new Error(\"settle requires a dispatched operation\");\n\t\tif (outcome !== \"applied\" && outcome !== \"failed-confirmed\" && outcome !== \"outcome-unknown\") {\n\t\t\tthrow new TypeError(\"invalid settled outcome\");\n\t\t}\n\t\t// Exact duplicate reports are idempotent. A final result cannot be revised.\n\t\tif (this.current === outcome) return;\n\t\tif (this.current !== \"dispatched\" && this.current !== \"outcome-unknown\") {\n\t\t\tthrow new Error(\"settle requires an unresolved dispatched outcome\");\n\t\t}\n\t\tthis.enter(outcome);\n\t}\n\n\t/** Explicit postcondition check. A driver's return value is not this. */\n\tverify(postconditionMet: boolean): void {\n\t\tif (typeof postconditionMet !== \"boolean\") throw new TypeError(\"postcondition must be a boolean\");\n\t\tif (this.current !== \"applied\") throw new Error(\"verify requires an applied outcome\");\n\t\tthis.enter(postconditionMet ? \"verified\" : \"inspection-required\");\n\t}\n\n\t/**\n\t * Request cancellation.\n\t *\n\t * Before dispatch this is terminal. After dispatch it only records the\n\t * request: the command is already outside this process, so the real outcome\n\t * has to be settled separately and stays `outcome-unknown` until it is.\n\t */\n\tcancel(): void {\n\t\tthis.cancelRequested = true;\n\t\tif (TERMINAL_STATES.has(this.current)) return;\n\t\tif (!this.hasDispatched) {\n\t\t\tthis.enter(\"cancelled-before-dispatch\");\n\t\t\treturn;\n\t\t}\n\t\tif (this.current === \"dispatched\") this.enter(\"outcome-unknown\");\n\t}\n}\n"]}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Resource claim identity and conflict algebra.
3
+ *
4
+ * Two claims conflict when they name overlapping resources and at least one
5
+ * side writes. Overlap is prefix containment on path components, so `src`
6
+ * covers `src/a/x` but never `src/ab` — a shared character prefix that straddles
7
+ * a component boundary is a different resource, not a nested one.
8
+ */
9
+ import type { ResourceClaim } from "./types.ts";
10
+ export interface ResourceClaimInput {
11
+ readonly namespace: string;
12
+ readonly instanceId: string;
13
+ readonly canonicalKey: string;
14
+ readonly access: string;
15
+ readonly generation: string;
16
+ }
17
+ /**
18
+ * Validate and freeze one claim.
19
+ *
20
+ * A non-canonical key is rejected rather than normalized: normalizing
21
+ * `a/../b` here would let one session hold `a/../b` and another hold `b`
22
+ * while both believe their scopes are disjoint.
23
+ */
24
+ export declare function canonicalClaim(input: ResourceClaimInput): ResourceClaim;
25
+ /** Same resource identity, or one key nested under the other. Ignores access. */
26
+ export declare function resourcesOverlap(a: ResourceClaim, b: ResourceClaim): boolean;
27
+ export declare function claimsConflict(a: ResourceClaim, b: ResourceClaim): boolean;
28
+ export declare function claimSetsConflict(a: readonly ResourceClaim[], b: readonly ResourceClaim[]): boolean;
29
+ /** Stable key for exact-set comparison when binding a start to its reservation. */
30
+ export declare function claimKey(claim: ResourceClaim): string;
31
+ /** Exact set equality by identity+access+generation; a post-hook that widened scope fails this. */
32
+ export declare function sameClaimSet(a: readonly ResourceClaim[], b: readonly ResourceClaim[]): boolean;
33
+ //# sourceMappingURL=resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/coordination/resource.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAA+B,aAAa,EAAE,MAAM,YAAY,CAAC;AAc7E,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAuBvE;AAiBD,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,GAAG,OAAO,CAI5E;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,GAAG,OAAO,CAE1E;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,SAAS,aAAa,EAAE,EAAE,CAAC,EAAE,SAAS,aAAa,EAAE,GAAG,OAAO,CAEnG;AAED,mFAAmF;AACnF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAErD;AAED,mGAAmG;AACnG,wBAAgB,YAAY,CAAC,CAAC,EAAE,SAAS,aAAa,EAAE,EAAE,CAAC,EAAE,SAAS,aAAa,EAAE,GAAG,OAAO,CAS9F","sourcesContent":["/**\n * Resource claim identity and conflict algebra.\n *\n * Two claims conflict when they name overlapping resources and at least one\n * side writes. Overlap is prefix containment on path components, so `src`\n * covers `src/a/x` but never `src/ab` — a shared character prefix that straddles\n * a component boundary is a different resource, not a nested one.\n */\n\nimport type { ClaimAccess, ClaimNamespace, ResourceClaim } from \"./types.ts\";\nimport { sequence } from \"./types.ts\";\n\nconst CLAIM_NAMESPACES: ReadonlySet<string> = new Set<ClaimNamespace>([\n\t\"filesystem\",\n\t\"git-ref\",\n\t\"contract\",\n\t\"socket\",\n\t\"database\",\n\t\"host-budget\",\n]);\nconst CLAIM_ACCESS: ReadonlySet<string> = new Set<ClaimAccess>([\"read\", \"write\"]);\nconst MAX_KEY_LENGTH = 4096;\n\nexport interface ResourceClaimInput {\n\treadonly namespace: string;\n\treadonly instanceId: string;\n\treadonly canonicalKey: string;\n\treadonly access: string;\n\treadonly generation: string;\n}\n\n/**\n * Validate and freeze one claim.\n *\n * A non-canonical key is rejected rather than normalized: normalizing\n * `a/../b` here would let one session hold `a/../b` and another hold `b`\n * while both believe their scopes are disjoint.\n */\nexport function canonicalClaim(input: ResourceClaimInput): ResourceClaim {\n\tif (!CLAIM_NAMESPACES.has(input.namespace)) {\n\t\tthrow new TypeError(`unsupported claim namespace: ${String(input.namespace)}`);\n\t}\n\tif (!CLAIM_ACCESS.has(input.access)) {\n\t\tthrow new TypeError(`unsupported claim access: ${String(input.access)}`);\n\t}\n\tif (\n\t\ttypeof input.instanceId !== \"string\" ||\n\t\tinput.instanceId.length === 0 ||\n\t\tinput.instanceId.length > MAX_KEY_LENGTH ||\n\t\tinput.instanceId.includes(\"\\u0000\")\n\t) {\n\t\tthrow new TypeError(\"claim instanceId must be a bounded non-empty string without NUL\");\n\t}\n\tassertCanonicalKey(input.canonicalKey);\n\treturn Object.freeze({\n\t\tnamespace: input.namespace as ClaimNamespace,\n\t\tinstanceId: input.instanceId,\n\t\tcanonicalKey: input.canonicalKey,\n\t\taccess: input.access as ClaimAccess,\n\t\tgeneration: sequence(input.generation),\n\t});\n}\n\nfunction assertCanonicalKey(key: unknown): asserts key is string {\n\tif (typeof key !== \"string\" || key.length === 0 || key.length > MAX_KEY_LENGTH) {\n\t\tthrow new TypeError(\"claim canonicalKey must be a bounded non-empty string\");\n\t}\n\tif (key.startsWith(\"/\")) throw new TypeError(\"claim canonicalKey must be relative\");\n\tif (key.includes(\"\\u0000\") || key.includes(\"\\\\\")) {\n\t\tthrow new TypeError(\"claim canonicalKey must use slash components without NUL\");\n\t}\n\tfor (const part of key.split(\"/\")) {\n\t\tif (part === \"\" || part === \".\" || part === \"..\") {\n\t\t\tthrow new TypeError(`claim canonicalKey is not canonical: ${key}`);\n\t\t}\n\t}\n}\n\n/** Same resource identity, or one key nested under the other. Ignores access. */\nexport function resourcesOverlap(a: ResourceClaim, b: ResourceClaim): boolean {\n\tif (a.namespace !== b.namespace || a.instanceId !== b.instanceId) return false;\n\tif (a.canonicalKey === b.canonicalKey) return true;\n\treturn a.canonicalKey.startsWith(`${b.canonicalKey}/`) || b.canonicalKey.startsWith(`${a.canonicalKey}/`);\n}\n\nexport function claimsConflict(a: ResourceClaim, b: ResourceClaim): boolean {\n\treturn resourcesOverlap(a, b) && (a.access === \"write\" || b.access === \"write\");\n}\n\nexport function claimSetsConflict(a: readonly ResourceClaim[], b: readonly ResourceClaim[]): boolean {\n\treturn a.some((x) => b.some((y) => claimsConflict(x, y)));\n}\n\n/** Stable key for exact-set comparison when binding a start to its reservation. */\nexport function claimKey(claim: ResourceClaim): string {\n\treturn JSON.stringify([claim.namespace, claim.instanceId, claim.canonicalKey, claim.access, claim.generation]);\n}\n\n/** Exact set equality by identity+access+generation; a post-hook that widened scope fails this. */\nexport function sameClaimSet(a: readonly ResourceClaim[], b: readonly ResourceClaim[]): boolean {\n\tif (a.length !== b.length) return false;\n\tconst byCodeUnit = (x: string, y: string): number => {\n\t\tif (x < y) return -1;\n\t\treturn x > y ? 1 : 0;\n\t};\n\tconst left = a.map(claimKey).sort(byCodeUnit);\n\tconst right = b.map(claimKey).sort(byCodeUnit);\n\treturn left.every((value, index) => value === right[index]);\n}\n"]}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Resource claim identity and conflict algebra.
3
+ *
4
+ * Two claims conflict when they name overlapping resources and at least one
5
+ * side writes. Overlap is prefix containment on path components, so `src`
6
+ * covers `src/a/x` but never `src/ab` — a shared character prefix that straddles
7
+ * a component boundary is a different resource, not a nested one.
8
+ */
9
+ import { sequence } from "./types.js";
10
+ const CLAIM_NAMESPACES = new Set([
11
+ "filesystem",
12
+ "git-ref",
13
+ "contract",
14
+ "socket",
15
+ "database",
16
+ "host-budget",
17
+ ]);
18
+ const CLAIM_ACCESS = new Set(["read", "write"]);
19
+ const MAX_KEY_LENGTH = 4096;
20
+ /**
21
+ * Validate and freeze one claim.
22
+ *
23
+ * A non-canonical key is rejected rather than normalized: normalizing
24
+ * `a/../b` here would let one session hold `a/../b` and another hold `b`
25
+ * while both believe their scopes are disjoint.
26
+ */
27
+ export function canonicalClaim(input) {
28
+ if (!CLAIM_NAMESPACES.has(input.namespace)) {
29
+ throw new TypeError(`unsupported claim namespace: ${String(input.namespace)}`);
30
+ }
31
+ if (!CLAIM_ACCESS.has(input.access)) {
32
+ throw new TypeError(`unsupported claim access: ${String(input.access)}`);
33
+ }
34
+ if (typeof input.instanceId !== "string" ||
35
+ input.instanceId.length === 0 ||
36
+ input.instanceId.length > MAX_KEY_LENGTH ||
37
+ input.instanceId.includes("\u0000")) {
38
+ throw new TypeError("claim instanceId must be a bounded non-empty string without NUL");
39
+ }
40
+ assertCanonicalKey(input.canonicalKey);
41
+ return Object.freeze({
42
+ namespace: input.namespace,
43
+ instanceId: input.instanceId,
44
+ canonicalKey: input.canonicalKey,
45
+ access: input.access,
46
+ generation: sequence(input.generation),
47
+ });
48
+ }
49
+ function assertCanonicalKey(key) {
50
+ if (typeof key !== "string" || key.length === 0 || key.length > MAX_KEY_LENGTH) {
51
+ throw new TypeError("claim canonicalKey must be a bounded non-empty string");
52
+ }
53
+ if (key.startsWith("/"))
54
+ throw new TypeError("claim canonicalKey must be relative");
55
+ if (key.includes("\u0000") || key.includes("\\")) {
56
+ throw new TypeError("claim canonicalKey must use slash components without NUL");
57
+ }
58
+ for (const part of key.split("/")) {
59
+ if (part === "" || part === "." || part === "..") {
60
+ throw new TypeError(`claim canonicalKey is not canonical: ${key}`);
61
+ }
62
+ }
63
+ }
64
+ /** Same resource identity, or one key nested under the other. Ignores access. */
65
+ export function resourcesOverlap(a, b) {
66
+ if (a.namespace !== b.namespace || a.instanceId !== b.instanceId)
67
+ return false;
68
+ if (a.canonicalKey === b.canonicalKey)
69
+ return true;
70
+ return a.canonicalKey.startsWith(`${b.canonicalKey}/`) || b.canonicalKey.startsWith(`${a.canonicalKey}/`);
71
+ }
72
+ export function claimsConflict(a, b) {
73
+ return resourcesOverlap(a, b) && (a.access === "write" || b.access === "write");
74
+ }
75
+ export function claimSetsConflict(a, b) {
76
+ return a.some((x) => b.some((y) => claimsConflict(x, y)));
77
+ }
78
+ /** Stable key for exact-set comparison when binding a start to its reservation. */
79
+ export function claimKey(claim) {
80
+ return JSON.stringify([claim.namespace, claim.instanceId, claim.canonicalKey, claim.access, claim.generation]);
81
+ }
82
+ /** Exact set equality by identity+access+generation; a post-hook that widened scope fails this. */
83
+ export function sameClaimSet(a, b) {
84
+ if (a.length !== b.length)
85
+ return false;
86
+ const byCodeUnit = (x, y) => {
87
+ if (x < y)
88
+ return -1;
89
+ return x > y ? 1 : 0;
90
+ };
91
+ const left = a.map(claimKey).sort(byCodeUnit);
92
+ const right = b.map(claimKey).sort(byCodeUnit);
93
+ return left.every((value, index) => value === right[index]);
94
+ }
95
+ //# sourceMappingURL=resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.js","sourceRoot":"","sources":["../../src/coordination/resource.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Resource claim identity and conflict algebra.\n *\n * Two claims conflict when they name overlapping resources and at least one\n * side writes. Overlap is prefix containment on path components, so `src`\n * covers `src/a/x` but never `src/ab` — a shared character prefix that straddles\n * a component boundary is a different resource, not a nested one.\n */\n\nimport type { ClaimAccess, ClaimNamespace, ResourceClaim } from \"./types.ts\";\nimport { sequence } from \"./types.ts\";\n\nconst CLAIM_NAMESPACES: ReadonlySet<string> = new Set<ClaimNamespace>([\n\t\"filesystem\",\n\t\"git-ref\",\n\t\"contract\",\n\t\"socket\",\n\t\"database\",\n\t\"host-budget\",\n]);\nconst CLAIM_ACCESS: ReadonlySet<string> = new Set<ClaimAccess>([\"read\", \"write\"]);\nconst MAX_KEY_LENGTH = 4096;\n\nexport interface ResourceClaimInput {\n\treadonly namespace: string;\n\treadonly instanceId: string;\n\treadonly canonicalKey: string;\n\treadonly access: string;\n\treadonly generation: string;\n}\n\n/**\n * Validate and freeze one claim.\n *\n * A non-canonical key is rejected rather than normalized: normalizing\n * `a/../b` here would let one session hold `a/../b` and another hold `b`\n * while both believe their scopes are disjoint.\n */\nexport function canonicalClaim(input: ResourceClaimInput): ResourceClaim {\n\tif (!CLAIM_NAMESPACES.has(input.namespace)) {\n\t\tthrow new TypeError(`unsupported claim namespace: ${String(input.namespace)}`);\n\t}\n\tif (!CLAIM_ACCESS.has(input.access)) {\n\t\tthrow new TypeError(`unsupported claim access: ${String(input.access)}`);\n\t}\n\tif (\n\t\ttypeof input.instanceId !== \"string\" ||\n\t\tinput.instanceId.length === 0 ||\n\t\tinput.instanceId.length > MAX_KEY_LENGTH ||\n\t\tinput.instanceId.includes(\"\\u0000\")\n\t) {\n\t\tthrow new TypeError(\"claim instanceId must be a bounded non-empty string without NUL\");\n\t}\n\tassertCanonicalKey(input.canonicalKey);\n\treturn Object.freeze({\n\t\tnamespace: input.namespace as ClaimNamespace,\n\t\tinstanceId: input.instanceId,\n\t\tcanonicalKey: input.canonicalKey,\n\t\taccess: input.access as ClaimAccess,\n\t\tgeneration: sequence(input.generation),\n\t});\n}\n\nfunction assertCanonicalKey(key: unknown): asserts key is string {\n\tif (typeof key !== \"string\" || key.length === 0 || key.length > MAX_KEY_LENGTH) {\n\t\tthrow new TypeError(\"claim canonicalKey must be a bounded non-empty string\");\n\t}\n\tif (key.startsWith(\"/\")) throw new TypeError(\"claim canonicalKey must be relative\");\n\tif (key.includes(\"\\u0000\") || key.includes(\"\\\\\")) {\n\t\tthrow new TypeError(\"claim canonicalKey must use slash components without NUL\");\n\t}\n\tfor (const part of key.split(\"/\")) {\n\t\tif (part === \"\" || part === \".\" || part === \"..\") {\n\t\t\tthrow new TypeError(`claim canonicalKey is not canonical: ${key}`);\n\t\t}\n\t}\n}\n\n/** Same resource identity, or one key nested under the other. Ignores access. */\nexport function resourcesOverlap(a: ResourceClaim, b: ResourceClaim): boolean {\n\tif (a.namespace !== b.namespace || a.instanceId !== b.instanceId) return false;\n\tif (a.canonicalKey === b.canonicalKey) return true;\n\treturn a.canonicalKey.startsWith(`${b.canonicalKey}/`) || b.canonicalKey.startsWith(`${a.canonicalKey}/`);\n}\n\nexport function claimsConflict(a: ResourceClaim, b: ResourceClaim): boolean {\n\treturn resourcesOverlap(a, b) && (a.access === \"write\" || b.access === \"write\");\n}\n\nexport function claimSetsConflict(a: readonly ResourceClaim[], b: readonly ResourceClaim[]): boolean {\n\treturn a.some((x) => b.some((y) => claimsConflict(x, y)));\n}\n\n/** Stable key for exact-set comparison when binding a start to its reservation. */\nexport function claimKey(claim: ResourceClaim): string {\n\treturn JSON.stringify([claim.namespace, claim.instanceId, claim.canonicalKey, claim.access, claim.generation]);\n}\n\n/** Exact set equality by identity+access+generation; a post-hook that widened scope fails this. */\nexport function sameClaimSet(a: readonly ResourceClaim[], b: readonly ResourceClaim[]): boolean {\n\tif (a.length !== b.length) return false;\n\tconst byCodeUnit = (x: string, y: string): number => {\n\t\tif (x < y) return -1;\n\t\treturn x > y ? 1 : 0;\n\t};\n\tconst left = a.map(claimKey).sort(byCodeUnit);\n\tconst right = b.map(claimKey).sort(byCodeUnit);\n\treturn left.every((value, index) => value === right[index]);\n}\n"]}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Generation-tagged browser session lifecycle (Jev audit F03, algorithm A6 §12.5).
3
+ *
4
+ * idle → initializing(g) → ready(g) → draining(g) → closed(g)
5
+ * ↘ init failure → idle
6
+ * ready | draining → close failure → close-failed(g)
7
+ *
8
+ * Two reproduced defects motivate every rule here:
9
+ * R09 — shutdown read an empty session slot while init was in flight, then
10
+ * the init completed and assigned it, resurrecting a closed session.
11
+ * R10 — close cleared the handle before the driver call resolved, so a close
12
+ * that threw left no handle and the next call claimed success.
13
+ *
14
+ * The invariant is that a handle is never dropped on the floor: a late init
15
+ * from a superseded generation is moved to `discardedHandles` for the caller
16
+ * to clean up, and a failed close keeps its handle in `close-failed`.
17
+ */
18
+ import type { Sequence } from "./types.ts";
19
+ export type SessionState = "idle" | "initializing" | "ready" | "draining" | "closed" | "close-failed";
20
+ export declare class SessionLifecycle<THandle = unknown> {
21
+ private currentState;
22
+ private generation;
23
+ private currentHandle;
24
+ private failure;
25
+ private shutdownRequested;
26
+ private readonly discarded;
27
+ get state(): SessionState;
28
+ get currentGeneration(): Sequence;
29
+ get handle(): THandle | undefined;
30
+ /** Handles from superseded or unknown generations; the caller must close them. */
31
+ get discardedHandles(): readonly THandle[];
32
+ get closeFailure(): Error | undefined;
33
+ /** Only a completed close counts. A close failure is not closed. */
34
+ get isClosed(): boolean;
35
+ /**
36
+ * Open a new generation.
37
+ *
38
+ * Refused while a close failure is unresolved: launching a second browser
39
+ * on top of one that may still be running is how orphan processes and
40
+ * duplicate effects start.
41
+ */
42
+ beginInit(): Sequence;
43
+ /**
44
+ * Adopt an initialized handle.
45
+ *
46
+ * Returns false when this generation is no longer the one being awaited —
47
+ * the handle is retained for cleanup rather than installed, because the
48
+ * session it belonged to is already gone.
49
+ */
50
+ completeInit(generation: Sequence, handle: THandle): boolean;
51
+ failInit(generation: Sequence, error: Error): boolean;
52
+ /**
53
+ * Ask the session to stop.
54
+ *
55
+ * With no handle yet there is nothing to drain, so this closes immediately
56
+ * and any in-flight init will be discarded on arrival. With a live handle
57
+ * the session must drain: the caller still has to close the driver.
58
+ */
59
+ requestShutdown(): void;
60
+ beginClose(): void;
61
+ /** The driver confirmed the session is gone; only now is the handle released. */
62
+ completeClose(): void;
63
+ /** The close attempt threw. Keep the handle so a retry can still reach it. */
64
+ failClose(error: Error): void;
65
+ /**
66
+ * Fencing gate: accept a command only from the current generation of a
67
+ * ready session. A generation number in a log proves nothing; the gate that
68
+ * hands commands to the driver has to be the one refusing stale ones.
69
+ */
70
+ accepts(generation: Sequence): boolean;
71
+ /** True once a shutdown was asked for, regardless of how far draining got. */
72
+ get shutdownPending(): boolean;
73
+ }
74
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/coordination/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,cAAc,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,cAAc,CAAC;AAEtG,qBAAa,gBAAgB,CAAC,OAAO,GAAG,OAAO;IAC9C,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAE3C,IAAI,KAAK,IAAI,YAAY,CAExB;IAED,IAAI,iBAAiB,IAAI,QAAQ,CAEhC;IAED,IAAI,MAAM,IAAI,OAAO,GAAG,SAAS,CAEhC;IAED,kFAAkF;IAClF,IAAI,gBAAgB,IAAI,SAAS,OAAO,EAAE,CAEzC;IAED,IAAI,YAAY,IAAI,KAAK,GAAG,SAAS,CAEpC;IAED,oEAAoE;IACpE,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;;;;;;OAMG;IACH,SAAS,IAAI,QAAQ,CAWpB;IAED;;;;;;OAMG;IACH,YAAY,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAQ3D;IAED,QAAQ,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAOpD;IAED;;;;;;OAMG;IACH,eAAe,IAAI,IAAI,CAOtB;IAED,UAAU,IAAI,IAAI,CAMjB;IAED,iFAAiF;IACjF,aAAa,IAAI,IAAI,CAOpB;IAED,8EAA8E;IAC9E,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAM5B;IAED;;;;OAIG;IACH,OAAO,CAAC,UAAU,EAAE,QAAQ,GAAG,OAAO,CAErC;IAED,8EAA8E;IAC9E,IAAI,eAAe,IAAI,OAAO,CAE7B;CACD","sourcesContent":["/**\n * Generation-tagged browser session lifecycle (Jev audit F03, algorithm A6 §12.5).\n *\n * idle → initializing(g) → ready(g) → draining(g) → closed(g)\n * ↘ init failure → idle\n * ready | draining → close failure → close-failed(g)\n *\n * Two reproduced defects motivate every rule here:\n * R09 — shutdown read an empty session slot while init was in flight, then\n * the init completed and assigned it, resurrecting a closed session.\n * R10 — close cleared the handle before the driver call resolved, so a close\n * that threw left no handle and the next call claimed success.\n *\n * The invariant is that a handle is never dropped on the floor: a late init\n * from a superseded generation is moved to `discardedHandles` for the caller\n * to clean up, and a failed close keeps its handle in `close-failed`.\n */\n\nimport type { Sequence } from \"./types.ts\";\nimport { nextSequence, sequence } from \"./types.ts\";\n\nexport type SessionState = \"idle\" | \"initializing\" | \"ready\" | \"draining\" | \"closed\" | \"close-failed\";\n\nexport class SessionLifecycle<THandle = unknown> {\n\tprivate currentState: SessionState = \"idle\";\n\tprivate generation: Sequence = sequence(\"0\");\n\tprivate currentHandle: THandle | undefined;\n\tprivate failure: Error | undefined;\n\tprivate shutdownRequested = false;\n\tprivate readonly discarded: THandle[] = [];\n\n\tget state(): SessionState {\n\t\treturn this.currentState;\n\t}\n\n\tget currentGeneration(): Sequence {\n\t\treturn this.generation;\n\t}\n\n\tget handle(): THandle | undefined {\n\t\treturn this.currentHandle;\n\t}\n\n\t/** Handles from superseded or unknown generations; the caller must close them. */\n\tget discardedHandles(): readonly THandle[] {\n\t\treturn [...this.discarded];\n\t}\n\n\tget closeFailure(): Error | undefined {\n\t\treturn this.failure;\n\t}\n\n\t/** Only a completed close counts. A close failure is not closed. */\n\tget isClosed(): boolean {\n\t\treturn this.currentState === \"closed\";\n\t}\n\n\t/**\n\t * Open a new generation.\n\t *\n\t * Refused while a close failure is unresolved: launching a second browser\n\t * on top of one that may still be running is how orphan processes and\n\t * duplicate effects start.\n\t */\n\tbeginInit(): Sequence {\n\t\tif (this.currentState === \"close-failed\") {\n\t\t\tthrow new Error(\"cannot initialize while a close-failed session is unresolved\");\n\t\t}\n\t\tif (this.currentState === \"initializing\" || this.currentState === \"ready\" || this.currentState === \"draining\") {\n\t\t\tthrow new Error(`cannot initialize from state ${this.currentState}`);\n\t\t}\n\t\tthis.generation = nextSequence(this.generation);\n\t\tthis.shutdownRequested = false;\n\t\tthis.currentState = \"initializing\";\n\t\treturn this.generation;\n\t}\n\n\t/**\n\t * Adopt an initialized handle.\n\t *\n\t * Returns false when this generation is no longer the one being awaited —\n\t * the handle is retained for cleanup rather than installed, because the\n\t * session it belonged to is already gone.\n\t */\n\tcompleteInit(generation: Sequence, handle: THandle): boolean {\n\t\tif (generation !== this.generation || this.currentState !== \"initializing\") {\n\t\t\tthis.discarded.push(handle);\n\t\t\treturn false;\n\t\t}\n\t\tthis.currentHandle = handle;\n\t\tthis.currentState = \"ready\";\n\t\treturn true;\n\t}\n\n\tfailInit(generation: Sequence, error: Error): boolean {\n\t\tif (generation !== this.generation || this.currentState !== \"initializing\") return false;\n\t\tthis.failure = undefined;\n\t\tthis.currentHandle = undefined;\n\t\tthis.currentState = \"idle\";\n\t\tvoid error;\n\t\treturn true;\n\t}\n\n\t/**\n\t * Ask the session to stop.\n\t *\n\t * With no handle yet there is nothing to drain, so this closes immediately\n\t * and any in-flight init will be discarded on arrival. With a live handle\n\t * the session must drain: the caller still has to close the driver.\n\t */\n\trequestShutdown(): void {\n\t\tthis.shutdownRequested = true;\n\t\tif (this.currentState === \"initializing\" || this.currentState === \"idle\") {\n\t\t\tthis.currentState = \"closed\";\n\t\t\treturn;\n\t\t}\n\t\tif (this.currentState === \"ready\") this.currentState = \"draining\";\n\t}\n\n\tbeginClose(): void {\n\t\tif (this.currentState !== \"ready\" && this.currentState !== \"close-failed\") {\n\t\t\tthrow new Error(`cannot close from state ${this.currentState}`);\n\t\t}\n\t\tthis.failure = undefined;\n\t\tthis.currentState = \"draining\";\n\t}\n\n\t/** The driver confirmed the session is gone; only now is the handle released. */\n\tcompleteClose(): void {\n\t\tif (this.currentState !== \"draining\") {\n\t\t\tthrow new Error(`cannot complete close from state ${this.currentState}`);\n\t\t}\n\t\tthis.currentHandle = undefined;\n\t\tthis.failure = undefined;\n\t\tthis.currentState = \"closed\";\n\t}\n\n\t/** The close attempt threw. Keep the handle so a retry can still reach it. */\n\tfailClose(error: Error): void {\n\t\tif (this.currentState !== \"draining\") {\n\t\t\tthrow new Error(`cannot fail close from state ${this.currentState}`);\n\t\t}\n\t\tthis.failure = error;\n\t\tthis.currentState = \"close-failed\";\n\t}\n\n\t/**\n\t * Fencing gate: accept a command only from the current generation of a\n\t * ready session. A generation number in a log proves nothing; the gate that\n\t * hands commands to the driver has to be the one refusing stale ones.\n\t */\n\taccepts(generation: Sequence): boolean {\n\t\treturn this.currentState === \"ready\" && generation === this.generation;\n\t}\n\n\t/** True once a shutdown was asked for, regardless of how far draining got. */\n\tget shutdownPending(): boolean {\n\t\treturn this.shutdownRequested;\n\t}\n}\n"]}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Generation-tagged browser session lifecycle (Jev audit F03, algorithm A6 §12.5).
3
+ *
4
+ * idle → initializing(g) → ready(g) → draining(g) → closed(g)
5
+ * ↘ init failure → idle
6
+ * ready | draining → close failure → close-failed(g)
7
+ *
8
+ * Two reproduced defects motivate every rule here:
9
+ * R09 — shutdown read an empty session slot while init was in flight, then
10
+ * the init completed and assigned it, resurrecting a closed session.
11
+ * R10 — close cleared the handle before the driver call resolved, so a close
12
+ * that threw left no handle and the next call claimed success.
13
+ *
14
+ * The invariant is that a handle is never dropped on the floor: a late init
15
+ * from a superseded generation is moved to `discardedHandles` for the caller
16
+ * to clean up, and a failed close keeps its handle in `close-failed`.
17
+ */
18
+ import { nextSequence, sequence } from "./types.js";
19
+ export class SessionLifecycle {
20
+ currentState = "idle";
21
+ generation = sequence("0");
22
+ currentHandle;
23
+ failure;
24
+ shutdownRequested = false;
25
+ discarded = [];
26
+ get state() {
27
+ return this.currentState;
28
+ }
29
+ get currentGeneration() {
30
+ return this.generation;
31
+ }
32
+ get handle() {
33
+ return this.currentHandle;
34
+ }
35
+ /** Handles from superseded or unknown generations; the caller must close them. */
36
+ get discardedHandles() {
37
+ return [...this.discarded];
38
+ }
39
+ get closeFailure() {
40
+ return this.failure;
41
+ }
42
+ /** Only a completed close counts. A close failure is not closed. */
43
+ get isClosed() {
44
+ return this.currentState === "closed";
45
+ }
46
+ /**
47
+ * Open a new generation.
48
+ *
49
+ * Refused while a close failure is unresolved: launching a second browser
50
+ * on top of one that may still be running is how orphan processes and
51
+ * duplicate effects start.
52
+ */
53
+ beginInit() {
54
+ if (this.currentState === "close-failed") {
55
+ throw new Error("cannot initialize while a close-failed session is unresolved");
56
+ }
57
+ if (this.currentState === "initializing" || this.currentState === "ready" || this.currentState === "draining") {
58
+ throw new Error(`cannot initialize from state ${this.currentState}`);
59
+ }
60
+ this.generation = nextSequence(this.generation);
61
+ this.shutdownRequested = false;
62
+ this.currentState = "initializing";
63
+ return this.generation;
64
+ }
65
+ /**
66
+ * Adopt an initialized handle.
67
+ *
68
+ * Returns false when this generation is no longer the one being awaited —
69
+ * the handle is retained for cleanup rather than installed, because the
70
+ * session it belonged to is already gone.
71
+ */
72
+ completeInit(generation, handle) {
73
+ if (generation !== this.generation || this.currentState !== "initializing") {
74
+ this.discarded.push(handle);
75
+ return false;
76
+ }
77
+ this.currentHandle = handle;
78
+ this.currentState = "ready";
79
+ return true;
80
+ }
81
+ failInit(generation, error) {
82
+ if (generation !== this.generation || this.currentState !== "initializing")
83
+ return false;
84
+ this.failure = undefined;
85
+ this.currentHandle = undefined;
86
+ this.currentState = "idle";
87
+ void error;
88
+ return true;
89
+ }
90
+ /**
91
+ * Ask the session to stop.
92
+ *
93
+ * With no handle yet there is nothing to drain, so this closes immediately
94
+ * and any in-flight init will be discarded on arrival. With a live handle
95
+ * the session must drain: the caller still has to close the driver.
96
+ */
97
+ requestShutdown() {
98
+ this.shutdownRequested = true;
99
+ if (this.currentState === "initializing" || this.currentState === "idle") {
100
+ this.currentState = "closed";
101
+ return;
102
+ }
103
+ if (this.currentState === "ready")
104
+ this.currentState = "draining";
105
+ }
106
+ beginClose() {
107
+ if (this.currentState !== "ready" && this.currentState !== "close-failed") {
108
+ throw new Error(`cannot close from state ${this.currentState}`);
109
+ }
110
+ this.failure = undefined;
111
+ this.currentState = "draining";
112
+ }
113
+ /** The driver confirmed the session is gone; only now is the handle released. */
114
+ completeClose() {
115
+ if (this.currentState !== "draining") {
116
+ throw new Error(`cannot complete close from state ${this.currentState}`);
117
+ }
118
+ this.currentHandle = undefined;
119
+ this.failure = undefined;
120
+ this.currentState = "closed";
121
+ }
122
+ /** The close attempt threw. Keep the handle so a retry can still reach it. */
123
+ failClose(error) {
124
+ if (this.currentState !== "draining") {
125
+ throw new Error(`cannot fail close from state ${this.currentState}`);
126
+ }
127
+ this.failure = error;
128
+ this.currentState = "close-failed";
129
+ }
130
+ /**
131
+ * Fencing gate: accept a command only from the current generation of a
132
+ * ready session. A generation number in a log proves nothing; the gate that
133
+ * hands commands to the driver has to be the one refusing stale ones.
134
+ */
135
+ accepts(generation) {
136
+ return this.currentState === "ready" && generation === this.generation;
137
+ }
138
+ /** True once a shutdown was asked for, regardless of how far draining got. */
139
+ get shutdownPending() {
140
+ return this.shutdownRequested;
141
+ }
142
+ }
143
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/coordination/session.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generation-tagged browser session lifecycle (Jev audit F03, algorithm A6 §12.5).\n *\n * idle → initializing(g) → ready(g) → draining(g) → closed(g)\n * ↘ init failure → idle\n * ready | draining → close failure → close-failed(g)\n *\n * Two reproduced defects motivate every rule here:\n * R09 — shutdown read an empty session slot while init was in flight, then\n * the init completed and assigned it, resurrecting a closed session.\n * R10 — close cleared the handle before the driver call resolved, so a close\n * that threw left no handle and the next call claimed success.\n *\n * The invariant is that a handle is never dropped on the floor: a late init\n * from a superseded generation is moved to `discardedHandles` for the caller\n * to clean up, and a failed close keeps its handle in `close-failed`.\n */\n\nimport type { Sequence } from \"./types.ts\";\nimport { nextSequence, sequence } from \"./types.ts\";\n\nexport type SessionState = \"idle\" | \"initializing\" | \"ready\" | \"draining\" | \"closed\" | \"close-failed\";\n\nexport class SessionLifecycle<THandle = unknown> {\n\tprivate currentState: SessionState = \"idle\";\n\tprivate generation: Sequence = sequence(\"0\");\n\tprivate currentHandle: THandle | undefined;\n\tprivate failure: Error | undefined;\n\tprivate shutdownRequested = false;\n\tprivate readonly discarded: THandle[] = [];\n\n\tget state(): SessionState {\n\t\treturn this.currentState;\n\t}\n\n\tget currentGeneration(): Sequence {\n\t\treturn this.generation;\n\t}\n\n\tget handle(): THandle | undefined {\n\t\treturn this.currentHandle;\n\t}\n\n\t/** Handles from superseded or unknown generations; the caller must close them. */\n\tget discardedHandles(): readonly THandle[] {\n\t\treturn [...this.discarded];\n\t}\n\n\tget closeFailure(): Error | undefined {\n\t\treturn this.failure;\n\t}\n\n\t/** Only a completed close counts. A close failure is not closed. */\n\tget isClosed(): boolean {\n\t\treturn this.currentState === \"closed\";\n\t}\n\n\t/**\n\t * Open a new generation.\n\t *\n\t * Refused while a close failure is unresolved: launching a second browser\n\t * on top of one that may still be running is how orphan processes and\n\t * duplicate effects start.\n\t */\n\tbeginInit(): Sequence {\n\t\tif (this.currentState === \"close-failed\") {\n\t\t\tthrow new Error(\"cannot initialize while a close-failed session is unresolved\");\n\t\t}\n\t\tif (this.currentState === \"initializing\" || this.currentState === \"ready\" || this.currentState === \"draining\") {\n\t\t\tthrow new Error(`cannot initialize from state ${this.currentState}`);\n\t\t}\n\t\tthis.generation = nextSequence(this.generation);\n\t\tthis.shutdownRequested = false;\n\t\tthis.currentState = \"initializing\";\n\t\treturn this.generation;\n\t}\n\n\t/**\n\t * Adopt an initialized handle.\n\t *\n\t * Returns false when this generation is no longer the one being awaited —\n\t * the handle is retained for cleanup rather than installed, because the\n\t * session it belonged to is already gone.\n\t */\n\tcompleteInit(generation: Sequence, handle: THandle): boolean {\n\t\tif (generation !== this.generation || this.currentState !== \"initializing\") {\n\t\t\tthis.discarded.push(handle);\n\t\t\treturn false;\n\t\t}\n\t\tthis.currentHandle = handle;\n\t\tthis.currentState = \"ready\";\n\t\treturn true;\n\t}\n\n\tfailInit(generation: Sequence, error: Error): boolean {\n\t\tif (generation !== this.generation || this.currentState !== \"initializing\") return false;\n\t\tthis.failure = undefined;\n\t\tthis.currentHandle = undefined;\n\t\tthis.currentState = \"idle\";\n\t\tvoid error;\n\t\treturn true;\n\t}\n\n\t/**\n\t * Ask the session to stop.\n\t *\n\t * With no handle yet there is nothing to drain, so this closes immediately\n\t * and any in-flight init will be discarded on arrival. With a live handle\n\t * the session must drain: the caller still has to close the driver.\n\t */\n\trequestShutdown(): void {\n\t\tthis.shutdownRequested = true;\n\t\tif (this.currentState === \"initializing\" || this.currentState === \"idle\") {\n\t\t\tthis.currentState = \"closed\";\n\t\t\treturn;\n\t\t}\n\t\tif (this.currentState === \"ready\") this.currentState = \"draining\";\n\t}\n\n\tbeginClose(): void {\n\t\tif (this.currentState !== \"ready\" && this.currentState !== \"close-failed\") {\n\t\t\tthrow new Error(`cannot close from state ${this.currentState}`);\n\t\t}\n\t\tthis.failure = undefined;\n\t\tthis.currentState = \"draining\";\n\t}\n\n\t/** The driver confirmed the session is gone; only now is the handle released. */\n\tcompleteClose(): void {\n\t\tif (this.currentState !== \"draining\") {\n\t\t\tthrow new Error(`cannot complete close from state ${this.currentState}`);\n\t\t}\n\t\tthis.currentHandle = undefined;\n\t\tthis.failure = undefined;\n\t\tthis.currentState = \"closed\";\n\t}\n\n\t/** The close attempt threw. Keep the handle so a retry can still reach it. */\n\tfailClose(error: Error): void {\n\t\tif (this.currentState !== \"draining\") {\n\t\t\tthrow new Error(`cannot fail close from state ${this.currentState}`);\n\t\t}\n\t\tthis.failure = error;\n\t\tthis.currentState = \"close-failed\";\n\t}\n\n\t/**\n\t * Fencing gate: accept a command only from the current generation of a\n\t * ready session. A generation number in a log proves nothing; the gate that\n\t * hands commands to the driver has to be the one refusing stale ones.\n\t */\n\taccepts(generation: Sequence): boolean {\n\t\treturn this.currentState === \"ready\" && generation === this.generation;\n\t}\n\n\t/** True once a shutdown was asked for, regardless of how far draining got. */\n\tget shutdownPending(): boolean {\n\t\treturn this.shutdownRequested;\n\t}\n}\n"]}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Wire contracts for parallel-session coordination.
3
+ *
4
+ * Ported from the proposed `contracts.ts` of the 2026-09-20 coordination
5
+ * design. These are new contracts, not pre-existing OMK exports.
6
+ *
7
+ * The central distinction the types encode: an authorization deadline is not a
8
+ * termination proof. A grant whose deadline passed while an external effect was
9
+ * live becomes `quarantined` — still holding its claims — rather than free.
10
+ */
11
+ /** Canonical nonnegative decimal string. Ordering is numeric, not lexical. */
12
+ export type Sequence = string & {
13
+ readonly __sequence: unique symbol;
14
+ };
15
+ export declare function sequence(value: unknown): Sequence;
16
+ export declare function nextSequence(value: Sequence): Sequence;
17
+ /**
18
+ * Lifecycle of an authorized effect.
19
+ *
20
+ * The in-process broker currently mints `reserved`, `running`, `quarantined`,
21
+ * `terminated` and `cancelled`. `starting` and `terminating` are reserved for
22
+ * the out-of-process supervisor that reports those transitions over the wire;
23
+ * nothing emits them yet, and the broker must not infer them.
24
+ */
25
+ export type EffectState = "reserved" | "starting" | "running" | "terminating" | "quarantined" | "terminated" | "cancelled";
26
+ /** States in which a grant no longer holds its claims. */
27
+ export declare const SETTLED_EFFECT_STATES: ReadonlySet<EffectState>;
28
+ export type ClaimNamespace = "filesystem" | "git-ref" | "contract" | "socket" | "database" | "host-budget";
29
+ export type ClaimAccess = "read" | "write";
30
+ /**
31
+ * One declared resource claim.
32
+ *
33
+ * `canonicalKey` must already be normalized by the caller: the broker rejects
34
+ * rather than guesses, because silently normalizing `a/../b` would let two
35
+ * sessions believe they hold disjoint keys.
36
+ */
37
+ export interface ResourceClaim {
38
+ readonly namespace: ClaimNamespace;
39
+ readonly instanceId: string;
40
+ readonly canonicalKey: string;
41
+ readonly access: ClaimAccess;
42
+ readonly generation: Sequence;
43
+ }
44
+ /**
45
+ * Proof of admission for exactly one operation of one session incarnation.
46
+ *
47
+ * `authorizationDeadline` bounds the authorization only. Termination is a
48
+ * separate, supervisor-reported fact.
49
+ */
50
+ export interface GrantToken {
51
+ readonly authorityEpoch: Sequence;
52
+ readonly grantSequence: Sequence;
53
+ readonly sessionId: string;
54
+ readonly sessionIncarnation: Sequence;
55
+ readonly authorizationDeadline: number;
56
+ }
57
+ export type AdmissionOutcome = {
58
+ readonly status: "granted";
59
+ readonly token: GrantToken;
60
+ } | {
61
+ readonly status: "blocked";
62
+ readonly blockers: readonly Sequence[];
63
+ } | {
64
+ readonly status: "over-capacity";
65
+ readonly requestedWeight: number;
66
+ readonly availableWeight: number;
67
+ };
68
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/coordination/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,MAAM,CAAA;CAAE,CAAC;AAKvE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAMjD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAEtD;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GACpB,UAAU,GACV,UAAU,GACV,SAAS,GACT,aAAa,GACb,aAAa,GACb,YAAY,GACZ,WAAW,CAAC;AAEf,0DAA0D;AAC1D,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,WAAW,CAAqD,CAAC;AAEjH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,aAAa,CAAC;AAC3G,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,CAAC;IACtC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;CACvC;AAED,MAAM,MAAM,gBAAgB,GACzB;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,QAAQ,EAAE,CAAA;CAAE,GACtE;IAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC","sourcesContent":["/**\n * Wire contracts for parallel-session coordination.\n *\n * Ported from the proposed `contracts.ts` of the 2026-09-20 coordination\n * design. These are new contracts, not pre-existing OMK exports.\n *\n * The central distinction the types encode: an authorization deadline is not a\n * termination proof. A grant whose deadline passed while an external effect was\n * live becomes `quarantined` — still holding its claims — rather than free.\n */\n\n/** Canonical nonnegative decimal string. Ordering is numeric, not lexical. */\nexport type Sequence = string & { readonly __sequence: unique symbol };\n\nconst SEQUENCE_PATTERN = /^(0|[1-9][0-9]*)$/;\nconst MAX_SEQUENCE_LENGTH = 40;\n\nexport function sequence(value: unknown): Sequence {\n\tif (typeof value !== \"string\" || !SEQUENCE_PATTERN.test(value)) {\n\t\tthrow new TypeError(\"sequence must be a canonical nonnegative decimal string\");\n\t}\n\tif (value.length > MAX_SEQUENCE_LENGTH) throw new RangeError(\"sequence too long\");\n\treturn value as Sequence;\n}\n\nexport function nextSequence(value: Sequence): Sequence {\n\treturn sequence(String(BigInt(sequence(value)) + 1n));\n}\n\n/**\n * Lifecycle of an authorized effect.\n *\n * The in-process broker currently mints `reserved`, `running`, `quarantined`,\n * `terminated` and `cancelled`. `starting` and `terminating` are reserved for\n * the out-of-process supervisor that reports those transitions over the wire;\n * nothing emits them yet, and the broker must not infer them.\n */\nexport type EffectState =\n\t| \"reserved\"\n\t| \"starting\"\n\t| \"running\"\n\t| \"terminating\"\n\t| \"quarantined\"\n\t| \"terminated\"\n\t| \"cancelled\";\n\n/** States in which a grant no longer holds its claims. */\nexport const SETTLED_EFFECT_STATES: ReadonlySet<EffectState> = new Set<EffectState>([\"terminated\", \"cancelled\"]);\n\nexport type ClaimNamespace = \"filesystem\" | \"git-ref\" | \"contract\" | \"socket\" | \"database\" | \"host-budget\";\nexport type ClaimAccess = \"read\" | \"write\";\n\n/**\n * One declared resource claim.\n *\n * `canonicalKey` must already be normalized by the caller: the broker rejects\n * rather than guesses, because silently normalizing `a/../b` would let two\n * sessions believe they hold disjoint keys.\n */\nexport interface ResourceClaim {\n\treadonly namespace: ClaimNamespace;\n\treadonly instanceId: string;\n\treadonly canonicalKey: string;\n\treadonly access: ClaimAccess;\n\treadonly generation: Sequence;\n}\n\n/**\n * Proof of admission for exactly one operation of one session incarnation.\n *\n * `authorizationDeadline` bounds the authorization only. Termination is a\n * separate, supervisor-reported fact.\n */\nexport interface GrantToken {\n\treadonly authorityEpoch: Sequence;\n\treadonly grantSequence: Sequence;\n\treadonly sessionId: string;\n\treadonly sessionIncarnation: Sequence;\n\treadonly authorizationDeadline: number;\n}\n\nexport type AdmissionOutcome =\n\t| { readonly status: \"granted\"; readonly token: GrantToken }\n\t| { readonly status: \"blocked\"; readonly blockers: readonly Sequence[] }\n\t| { readonly status: \"over-capacity\"; readonly requestedWeight: number; readonly availableWeight: number };\n"]}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Wire contracts for parallel-session coordination.
3
+ *
4
+ * Ported from the proposed `contracts.ts` of the 2026-09-20 coordination
5
+ * design. These are new contracts, not pre-existing OMK exports.
6
+ *
7
+ * The central distinction the types encode: an authorization deadline is not a
8
+ * termination proof. A grant whose deadline passed while an external effect was
9
+ * live becomes `quarantined` — still holding its claims — rather than free.
10
+ */
11
+ const SEQUENCE_PATTERN = /^(0|[1-9][0-9]*)$/;
12
+ const MAX_SEQUENCE_LENGTH = 40;
13
+ export function sequence(value) {
14
+ if (typeof value !== "string" || !SEQUENCE_PATTERN.test(value)) {
15
+ throw new TypeError("sequence must be a canonical nonnegative decimal string");
16
+ }
17
+ if (value.length > MAX_SEQUENCE_LENGTH)
18
+ throw new RangeError("sequence too long");
19
+ return value;
20
+ }
21
+ export function nextSequence(value) {
22
+ return sequence(String(BigInt(sequence(value)) + 1n));
23
+ }
24
+ /** States in which a grant no longer holds its claims. */
25
+ export const SETTLED_EFFECT_STATES = new Set(["terminated", "cancelled"]);
26
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/coordination/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AAC7C,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,MAAM,UAAU,QAAQ,CAAC,KAAc,EAAY;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,SAAS,CAAC,yDAAyD,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,mBAAmB;QAAE,MAAM,IAAI,UAAU,CAAC,mBAAmB,CAAC,CAAC;IAClF,OAAO,KAAiB,CAAC;AAAA,CACzB;AAED,MAAM,UAAU,YAAY,CAAC,KAAe,EAAY;IACvD,OAAO,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAAA,CACtD;AAmBD,0DAA0D;AAC1D,MAAM,CAAC,MAAM,qBAAqB,GAA6B,IAAI,GAAG,CAAc,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC","sourcesContent":["/**\n * Wire contracts for parallel-session coordination.\n *\n * Ported from the proposed `contracts.ts` of the 2026-09-20 coordination\n * design. These are new contracts, not pre-existing OMK exports.\n *\n * The central distinction the types encode: an authorization deadline is not a\n * termination proof. A grant whose deadline passed while an external effect was\n * live becomes `quarantined` — still holding its claims — rather than free.\n */\n\n/** Canonical nonnegative decimal string. Ordering is numeric, not lexical. */\nexport type Sequence = string & { readonly __sequence: unique symbol };\n\nconst SEQUENCE_PATTERN = /^(0|[1-9][0-9]*)$/;\nconst MAX_SEQUENCE_LENGTH = 40;\n\nexport function sequence(value: unknown): Sequence {\n\tif (typeof value !== \"string\" || !SEQUENCE_PATTERN.test(value)) {\n\t\tthrow new TypeError(\"sequence must be a canonical nonnegative decimal string\");\n\t}\n\tif (value.length > MAX_SEQUENCE_LENGTH) throw new RangeError(\"sequence too long\");\n\treturn value as Sequence;\n}\n\nexport function nextSequence(value: Sequence): Sequence {\n\treturn sequence(String(BigInt(sequence(value)) + 1n));\n}\n\n/**\n * Lifecycle of an authorized effect.\n *\n * The in-process broker currently mints `reserved`, `running`, `quarantined`,\n * `terminated` and `cancelled`. `starting` and `terminating` are reserved for\n * the out-of-process supervisor that reports those transitions over the wire;\n * nothing emits them yet, and the broker must not infer them.\n */\nexport type EffectState =\n\t| \"reserved\"\n\t| \"starting\"\n\t| \"running\"\n\t| \"terminating\"\n\t| \"quarantined\"\n\t| \"terminated\"\n\t| \"cancelled\";\n\n/** States in which a grant no longer holds its claims. */\nexport const SETTLED_EFFECT_STATES: ReadonlySet<EffectState> = new Set<EffectState>([\"terminated\", \"cancelled\"]);\n\nexport type ClaimNamespace = \"filesystem\" | \"git-ref\" | \"contract\" | \"socket\" | \"database\" | \"host-budget\";\nexport type ClaimAccess = \"read\" | \"write\";\n\n/**\n * One declared resource claim.\n *\n * `canonicalKey` must already be normalized by the caller: the broker rejects\n * rather than guesses, because silently normalizing `a/../b` would let two\n * sessions believe they hold disjoint keys.\n */\nexport interface ResourceClaim {\n\treadonly namespace: ClaimNamespace;\n\treadonly instanceId: string;\n\treadonly canonicalKey: string;\n\treadonly access: ClaimAccess;\n\treadonly generation: Sequence;\n}\n\n/**\n * Proof of admission for exactly one operation of one session incarnation.\n *\n * `authorizationDeadline` bounds the authorization only. Termination is a\n * separate, supervisor-reported fact.\n */\nexport interface GrantToken {\n\treadonly authorityEpoch: Sequence;\n\treadonly grantSequence: Sequence;\n\treadonly sessionId: string;\n\treadonly sessionIncarnation: Sequence;\n\treadonly authorizationDeadline: number;\n}\n\nexport type AdmissionOutcome =\n\t| { readonly status: \"granted\"; readonly token: GrantToken }\n\t| { readonly status: \"blocked\"; readonly blockers: readonly Sequence[] }\n\t| { readonly status: \"over-capacity\"; readonly requestedWeight: number; readonly availableWeight: number };\n"]}
@@ -119,7 +119,7 @@ export declare function sanitizeConsultPayload(candidate: unknown): AdaptorchCon
119
119
  export declare function sanitizeAdvisoryResult(candidate: unknown): AdaptorchAdvisoryResult | null;
120
120
  /**
121
121
  * Read-only/local AdaptOrch MCP tool names this bridge may ever reference,
122
- * grounded in the real 10-tool surface documented in
122
+ * grounded in the eleven-tool surface documented in
123
123
  * packages/adaptorch-wpl/src/adaptorch-client.ts (cross-checked there
124
124
  * against the AdaptOrch server's own docs) and narrowed to the two tools the
125
125
  * read-first plan puts in scope for a reasoning-effort hint (plan 4.2): the