@quolu/lattice 0.1.0 → 0.12.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 (370) hide show
  1. package/README.md +87 -4
  2. package/bin/lattice-bridge.mjs +87 -0
  3. package/bin/lattice-dashboard.mjs +70 -0
  4. package/bin/lattice-mcp.mjs +9 -9
  5. package/bin/lattice.mjs +61 -8
  6. package/docs/bridge-setup.md +87 -0
  7. package/docs/schemas/lattice.plan_create_input.v1.schema.json +56 -0
  8. package/docs/schemas/lattice.plan_create_input.v2.schema.json +72 -0
  9. package/docs/schemas/lattice.plan_create_input.v3.schema.json +81 -0
  10. package/package.json +19 -7
  11. package/sensor/dist/bin/command-supervision.d.ts +1 -1
  12. package/sensor/dist/bin/command-supervision.js +4 -4
  13. package/sensor/dist/bin/command-supervision.js.map +1 -1
  14. package/sensor/dist/bin/fatal-handler.js +2 -2
  15. package/sensor/dist/bin/fatal-handler.js.map +1 -1
  16. package/sensor/dist/bin/{codegraph.js → lattice-sensor.js} +207 -328
  17. package/sensor/dist/bin/node-version-check.d.ts +7 -5
  18. package/sensor/dist/bin/node-version-check.d.ts.map +1 -1
  19. package/sensor/dist/bin/node-version-check.js +19 -14
  20. package/sensor/dist/bin/node-version-check.js.map +1 -1
  21. package/sensor/dist/context/index.d.ts +1 -1
  22. package/sensor/dist/context/index.js +6 -6
  23. package/sensor/dist/context/index.js.map +1 -1
  24. package/sensor/dist/db/index.d.ts +5 -5
  25. package/sensor/dist/db/index.d.ts.map +1 -1
  26. package/sensor/dist/db/index.js +7 -7
  27. package/sensor/dist/db/index.js.map +1 -1
  28. package/sensor/dist/db/migrations.js +1 -1
  29. package/sensor/dist/db/migrations.js.map +1 -1
  30. package/sensor/dist/db/queries.d.ts +1 -1
  31. package/sensor/dist/db/queries.js +5 -5
  32. package/sensor/dist/db/queries.js.map +1 -1
  33. package/sensor/dist/db/schema.sql +2 -2
  34. package/sensor/dist/db/sqlite-adapter.d.ts +2 -2
  35. package/sensor/dist/db/sqlite-adapter.js +3 -3
  36. package/sensor/dist/db/sqlite-adapter.js.map +1 -1
  37. package/sensor/dist/db/wal-valve.d.ts +1 -1
  38. package/sensor/dist/db/wal-valve.d.ts.map +1 -1
  39. package/sensor/dist/db/wal-valve.js +2 -2
  40. package/sensor/dist/db/wal-valve.js.map +1 -1
  41. package/sensor/dist/directory.d.ts +27 -63
  42. package/sensor/dist/directory.d.ts.map +1 -1
  43. package/sensor/dist/directory.js +78 -134
  44. package/sensor/dist/directory.js.map +1 -1
  45. package/sensor/dist/errors.d.ts +15 -15
  46. package/sensor/dist/errors.d.ts.map +1 -1
  47. package/sensor/dist/errors.js +21 -21
  48. package/sensor/dist/errors.js.map +1 -1
  49. package/sensor/dist/extraction/dynamic-import.d.ts +1 -1
  50. package/sensor/dist/extraction/dynamic-import.js +1 -1
  51. package/sensor/dist/extraction/extraction-version.d.ts +1 -1
  52. package/sensor/dist/extraction/extraction-version.js +1 -1
  53. package/sensor/dist/extraction/generated-detection.d.ts +1 -1
  54. package/sensor/dist/extraction/generated-detection.js +1 -1
  55. package/sensor/dist/extraction/grammars.d.ts +3 -3
  56. package/sensor/dist/extraction/grammars.js +5 -5
  57. package/sensor/dist/extraction/grammars.js.map +1 -1
  58. package/sensor/dist/extraction/index.d.ts +6 -6
  59. package/sensor/dist/extraction/index.js +50 -50
  60. package/sensor/dist/extraction/index.js.map +1 -1
  61. package/sensor/dist/extraction/kernel/decode.d.ts +1 -1
  62. package/sensor/dist/extraction/kernel/decode.js +1 -1
  63. package/sensor/dist/extraction/kernel/index.d.ts +3 -3
  64. package/sensor/dist/extraction/kernel/index.js +6 -6
  65. package/sensor/dist/extraction/kernel/index.js.map +1 -1
  66. package/sensor/dist/extraction/kernel/layout.d.ts +1 -1
  67. package/sensor/dist/extraction/kernel/layout.js +1 -1
  68. package/sensor/dist/extraction/kernel/loader.d.ts +6 -6
  69. package/sensor/dist/extraction/kernel/loader.js +13 -13
  70. package/sensor/dist/extraction/kernel/loader.js.map +1 -1
  71. package/sensor/dist/extraction/languages/cfquery.d.ts +1 -1
  72. package/sensor/dist/extraction/languages/cfquery.js +1 -1
  73. package/sensor/dist/extraction/languages/lua.d.ts +11 -0
  74. package/sensor/dist/extraction/languages/lua.d.ts.map +1 -1
  75. package/sensor/dist/extraction/languages/lua.js +1 -0
  76. package/sensor/dist/extraction/languages/lua.js.map +1 -1
  77. package/sensor/dist/extraction/parse-pool.d.ts +5 -5
  78. package/sensor/dist/extraction/parse-pool.d.ts.map +1 -1
  79. package/sensor/dist/extraction/parse-pool.js +4 -4
  80. package/sensor/dist/extraction/parse-worker.js +1 -1
  81. package/sensor/dist/extraction/parse-worker.js.map +1 -1
  82. package/sensor/dist/extraction/store-writer.d.ts +1 -1
  83. package/sensor/dist/extraction/store-writer.js +1 -1
  84. package/sensor/dist/extraction/svelte-extractor.d.ts +1 -1
  85. package/sensor/dist/extraction/svelte-extractor.js +1 -1
  86. package/sensor/dist/extraction/tree-sitter-helpers.js +1 -1
  87. package/sensor/dist/extraction/tree-sitter.d.ts +2 -2
  88. package/sensor/dist/extraction/tree-sitter.d.ts.map +1 -1
  89. package/sensor/dist/extraction/tree-sitter.js +71 -4
  90. package/sensor/dist/extraction/tree-sitter.js.map +1 -1
  91. package/sensor/dist/extraction/wasm-runtime-flags.d.ts +2 -2
  92. package/sensor/dist/extraction/wasm-runtime-flags.d.ts.map +1 -1
  93. package/sensor/dist/extraction/wasm-runtime-flags.js +5 -5
  94. package/sensor/dist/extraction/wasm-runtime-flags.js.map +1 -1
  95. package/sensor/dist/index.d.ts +36 -36
  96. package/sensor/dist/index.d.ts.map +1 -1
  97. package/sensor/dist/index.js +71 -71
  98. package/sensor/dist/index.js.map +1 -1
  99. package/sensor/dist/mcp/daemon-manager.js +1 -1
  100. package/sensor/dist/mcp/daemon-paths.d.ts +3 -3
  101. package/sensor/dist/mcp/daemon-paths.js +7 -7
  102. package/sensor/dist/mcp/daemon-paths.js.map +1 -1
  103. package/sensor/dist/mcp/daemon-registry.d.ts +2 -2
  104. package/sensor/dist/mcp/daemon-registry.js +5 -5
  105. package/sensor/dist/mcp/daemon.d.ts +7 -7
  106. package/sensor/dist/mcp/daemon.d.ts.map +1 -1
  107. package/sensor/dist/mcp/daemon.js +21 -21
  108. package/sensor/dist/mcp/daemon.js.map +1 -1
  109. package/sensor/dist/mcp/dynamic-boundaries.js +1 -1
  110. package/sensor/dist/mcp/engine.d.ts +9 -9
  111. package/sensor/dist/mcp/engine.d.ts.map +1 -1
  112. package/sensor/dist/mcp/engine.js +44 -44
  113. package/sensor/dist/mcp/engine.js.map +1 -1
  114. package/sensor/dist/mcp/index.d.ts +14 -14
  115. package/sensor/dist/mcp/index.d.ts.map +1 -1
  116. package/sensor/dist/mcp/index.js +41 -41
  117. package/sensor/dist/mcp/index.js.map +1 -1
  118. package/sensor/dist/mcp/liveness-watchdog.js +7 -7
  119. package/sensor/dist/mcp/liveness-watchdog.js.map +1 -1
  120. package/sensor/dist/mcp/ppid-watchdog.d.ts +3 -3
  121. package/sensor/dist/mcp/ppid-watchdog.js +2 -2
  122. package/sensor/dist/mcp/proxy.d.ts.map +1 -1
  123. package/sensor/dist/mcp/proxy.js +37 -37
  124. package/sensor/dist/mcp/proxy.js.map +1 -1
  125. package/sensor/dist/mcp/query-pool.d.ts +3 -3
  126. package/sensor/dist/mcp/query-pool.js +7 -7
  127. package/sensor/dist/mcp/query-pool.js.map +1 -1
  128. package/sensor/dist/mcp/query-worker.d.ts +2 -2
  129. package/sensor/dist/mcp/query-worker.js +7 -7
  130. package/sensor/dist/mcp/query-worker.js.map +1 -1
  131. package/sensor/dist/mcp/server-instructions.d.ts +10 -12
  132. package/sensor/dist/mcp/server-instructions.d.ts.map +1 -1
  133. package/sensor/dist/mcp/server-instructions.js +39 -37
  134. package/sensor/dist/mcp/server-instructions.js.map +1 -1
  135. package/sensor/dist/mcp/session.d.ts +2 -2
  136. package/sensor/dist/mcp/session.js +18 -18
  137. package/sensor/dist/mcp/session.js.map +1 -1
  138. package/sensor/dist/mcp/startup-handshake.d.ts +3 -3
  139. package/sensor/dist/mcp/startup-handshake.d.ts.map +1 -1
  140. package/sensor/dist/mcp/startup-handshake.js +3 -3
  141. package/sensor/dist/mcp/startup-handshake.js.map +1 -1
  142. package/sensor/dist/mcp/tools.d.ts +53 -53
  143. package/sensor/dist/mcp/tools.d.ts.map +1 -1
  144. package/sensor/dist/mcp/tools.js +180 -216
  145. package/sensor/dist/mcp/tools.js.map +1 -1
  146. package/sensor/dist/mcp/transport.d.ts +1 -1
  147. package/sensor/dist/mcp/transport.js +6 -6
  148. package/sensor/dist/mcp/transport.js.map +1 -1
  149. package/sensor/dist/mcp/version.d.ts +2 -2
  150. package/sensor/dist/mcp/version.d.ts.map +1 -1
  151. package/sensor/dist/mcp/version.js +3 -3
  152. package/sensor/dist/mcp/version.js.map +1 -1
  153. package/sensor/dist/project-config.d.ts +6 -6
  154. package/sensor/dist/project-config.d.ts.map +1 -1
  155. package/sensor/dist/project-config.js +10 -10
  156. package/sensor/dist/project-config.js.map +1 -1
  157. package/sensor/dist/resolution/callback-synthesizer.js +4 -4
  158. package/sensor/dist/resolution/callback-synthesizer.js.map +1 -1
  159. package/sensor/dist/resolution/frameworks/drupal.d.ts +3 -3
  160. package/sensor/dist/resolution/frameworks/drupal.js +3 -3
  161. package/sensor/dist/resolution/frameworks/fabric.js +1 -1
  162. package/sensor/dist/resolution/frameworks/fabric.js.map +1 -1
  163. package/sensor/dist/resolution/frameworks/java.js +1 -1
  164. package/sensor/dist/resolution/frameworks/java.js.map +1 -1
  165. package/sensor/dist/resolution/frameworks/svelte.js +1 -1
  166. package/sensor/dist/resolution/frameworks/svelte.js.map +1 -1
  167. package/sensor/dist/resolution/goframe-synthesizer.d.ts +1 -1
  168. package/sensor/dist/resolution/goframe-synthesizer.js +1 -1
  169. package/sensor/dist/resolution/index.d.ts +1 -1
  170. package/sensor/dist/resolution/index.js +9 -9
  171. package/sensor/dist/resolution/index.js.map +1 -1
  172. package/sensor/dist/resolution/name-matcher.js +2 -2
  173. package/sensor/dist/resolution/name-matcher.js.map +1 -1
  174. package/sensor/dist/resolution/resolver-pool.d.ts +2 -2
  175. package/sensor/dist/resolution/resolver-pool.js +4 -4
  176. package/sensor/dist/resolution/resolver-pool.js.map +1 -1
  177. package/sensor/dist/resolution/resolver-worker.js +2 -2
  178. package/sensor/dist/resolution/resolver-worker.js.map +1 -1
  179. package/sensor/dist/resolution/workspace-packages.js +1 -1
  180. package/sensor/dist/resolution/workspace-packages.js.map +1 -1
  181. package/sensor/dist/search/identifier-segments.d.ts +1 -1
  182. package/sensor/dist/search/identifier-segments.js +1 -1
  183. package/sensor/dist/search/query-utils.d.ts +1 -0
  184. package/sensor/dist/search/query-utils.d.ts.map +1 -1
  185. package/sensor/dist/search/query-utils.js +10 -3
  186. package/sensor/dist/search/query-utils.js.map +1 -1
  187. package/sensor/dist/sync/git-hooks.d.ts +9 -9
  188. package/sensor/dist/sync/git-hooks.d.ts.map +1 -1
  189. package/sensor/dist/sync/git-hooks.js +15 -15
  190. package/sensor/dist/sync/git-hooks.js.map +1 -1
  191. package/sensor/dist/sync/watch-policy.d.ts +2 -2
  192. package/sensor/dist/sync/watch-policy.js +5 -5
  193. package/sensor/dist/sync/watch-policy.js.map +1 -1
  194. package/sensor/dist/sync/watcher.d.ts +2 -2
  195. package/sensor/dist/sync/watcher.d.ts.map +1 -1
  196. package/sensor/dist/sync/watcher.js +16 -16
  197. package/sensor/dist/sync/watcher.js.map +1 -1
  198. package/sensor/dist/sync/worktree.d.ts +5 -5
  199. package/sensor/dist/sync/worktree.d.ts.map +1 -1
  200. package/sensor/dist/sync/worktree.js +9 -9
  201. package/sensor/dist/sync/worktree.js.map +1 -1
  202. package/sensor/dist/telemetry/index.d.ts +8 -8
  203. package/sensor/dist/telemetry/index.d.ts.map +1 -1
  204. package/sensor/dist/telemetry/index.js +16 -16
  205. package/sensor/dist/telemetry/index.js.map +1 -1
  206. package/sensor/dist/types.d.ts +2 -2
  207. package/sensor/dist/types.js +1 -1
  208. package/sensor/dist/ui/color.d.ts +2 -2
  209. package/sensor/dist/ui/color.js +2 -2
  210. package/sensor/dist/ui/glyphs.d.ts +3 -3
  211. package/sensor/dist/ui/glyphs.js +7 -7
  212. package/sensor/dist/ui/glyphs.js.map +1 -1
  213. package/sensor/dist/utils.d.ts +4 -4
  214. package/sensor/dist/utils.js +8 -8
  215. package/sensor/dist/utils.js.map +1 -1
  216. package/sensor/package.json +8 -13
  217. package/src/artifact-contracts.mjs +2 -2
  218. package/src/boundary-compiler.mjs +28 -28
  219. package/src/boundary-observation-compiler-v2.mjs +10 -10
  220. package/src/bounded-seam.mjs +144 -0
  221. package/src/bridge-cli.mjs +227 -0
  222. package/src/bridge-config.mjs +346 -0
  223. package/src/bridge-daemon.mjs +328 -0
  224. package/src/bridge-launch-agent.mjs +311 -0
  225. package/src/bridge-server.mjs +309 -0
  226. package/src/cli-help.mjs +163 -0
  227. package/src/control-compiler.mjs +30 -30
  228. package/src/dag-chain.mjs +261 -0
  229. package/src/factory-diagnostics.mjs +8 -7
  230. package/src/hash-chain.mjs +76 -0
  231. package/src/node-version-guard.mjs +5 -4
  232. package/src/project-cli.mjs +392 -0
  233. package/src/project-identity.mjs +71 -0
  234. package/src/rc1-evidence-bundle.mjs +16 -16
  235. package/src/rc1-v4-campaign.mjs +15 -14
  236. package/src/rc1-v5-artifact-set.mjs +2 -2
  237. package/src/rc1-v5-campaign.mjs +15 -14
  238. package/src/rc1-v6-artifact-set.mjs +18 -18
  239. package/src/rc1-v6-campaign.mjs +16 -16
  240. package/src/rc1-v6-causal-binding.mjs +16 -14
  241. package/src/rc1-v6-measurement.mjs +20 -38
  242. package/src/rc2-artifact-set.mjs +45 -40
  243. package/src/rc2-campaign.mjs +48 -66
  244. package/src/rc2-delivery-policy-front-end.mjs +30 -30
  245. package/src/rc2-rc1-transfer-front-end.mjs +5 -5
  246. package/src/rc3-actual-dogfood.mjs +6 -6
  247. package/src/rc3-dogfood-scaffold.mjs +12 -7
  248. package/src/rc3-scripted-campaign.mjs +75 -21
  249. package/src/rc4-stage1-dogfood.mjs +24 -7
  250. package/src/runtime-cli.mjs +2424 -45
  251. package/src/runtime-contracts.mjs +7 -7
  252. package/src/runtime-control-store.mjs +547 -0
  253. package/src/runtime-controller-protocol.mjs +517 -0
  254. package/src/runtime-direct-os-observer.mjs +284 -0
  255. package/src/runtime-engine.mjs +2 -2
  256. package/src/runtime-errors.mjs +1 -1
  257. package/src/runtime-event-store.mjs +15 -43
  258. package/src/runtime-front-end.mjs +26 -26
  259. package/src/runtime-gate-store.mjs +477 -0
  260. package/src/runtime-hold-recompile.mjs +214 -23
  261. package/src/runtime-lifecycle-lock.mjs +290 -0
  262. package/src/runtime-managed-supervisor.mjs +1276 -0
  263. package/src/runtime-multi-epoch-store.mjs +761 -0
  264. package/src/runtime-projection.mjs +62 -0
  265. package/src/seam-transform.mjs +38 -38
  266. package/src/{codegraph-adapter.mjs → sensor-adapter.mjs} +7 -7
  267. package/src/sensor-cli.mjs +107 -0
  268. package/src/sensor-runtime.mjs +48 -0
  269. package/src/timestamp-contract.mjs +8 -0
  270. package/src/todo-chain.mjs +178 -0
  271. package/src/todo-cli.mjs +1032 -0
  272. package/src/todo-contracts.mjs +501 -0
  273. package/src/todo-dashboard-registry.mjs +318 -0
  274. package/src/todo-gantt-html.mjs +416 -0
  275. package/src/todo-gantt-layout.mjs +603 -0
  276. package/src/todo-gantt-live.mjs +269 -0
  277. package/src/todo-gantt-presentation.mjs +217 -0
  278. package/src/todo-gantt-svg.mjs +249 -0
  279. package/src/todo-markdown-renderer.mjs +260 -0
  280. package/src/todo-migration.mjs +260 -0
  281. package/src/todo-narrative-anchor.mjs +130 -0
  282. package/src/todo-revision.mjs +425 -0
  283. package/src/todo-status.mjs +340 -0
  284. package/src/todo-store.mjs +3451 -0
  285. package/src/treatment-compiler.mjs +28 -28
  286. package/src/treatment-runner.mjs +42 -44
  287. package/sensor/dist/bin/codegraph.d.ts +0 -26
  288. package/sensor/dist/bin/codegraph.d.ts.map +0 -1
  289. package/sensor/dist/bin/codegraph.js.map +0 -1
  290. package/sensor/dist/bin/uninstall.d.ts +0 -14
  291. package/sensor/dist/bin/uninstall.d.ts.map +0 -1
  292. package/sensor/dist/bin/uninstall.js +0 -36
  293. package/sensor/dist/bin/uninstall.js.map +0 -1
  294. package/sensor/dist/installer/beta-signup.d.ts +0 -54
  295. package/sensor/dist/installer/beta-signup.d.ts.map +0 -1
  296. package/sensor/dist/installer/beta-signup.js +0 -178
  297. package/sensor/dist/installer/beta-signup.js.map +0 -1
  298. package/sensor/dist/installer/config-writer.d.ts +0 -28
  299. package/sensor/dist/installer/config-writer.d.ts.map +0 -1
  300. package/sensor/dist/installer/config-writer.js +0 -91
  301. package/sensor/dist/installer/config-writer.js.map +0 -1
  302. package/sensor/dist/installer/index.d.ts +0 -142
  303. package/sensor/dist/installer/index.d.ts.map +0 -1
  304. package/sensor/dist/installer/index.js +0 -622
  305. package/sensor/dist/installer/index.js.map +0 -1
  306. package/sensor/dist/installer/instructions-template.d.ts +0 -41
  307. package/sensor/dist/installer/instructions-template.d.ts.map +0 -1
  308. package/sensor/dist/installer/instructions-template.js +0 -53
  309. package/sensor/dist/installer/instructions-template.js.map +0 -1
  310. package/sensor/dist/installer/targets/antigravity.d.ts +0 -57
  311. package/sensor/dist/installer/targets/antigravity.d.ts.map +0 -1
  312. package/sensor/dist/installer/targets/antigravity.js +0 -308
  313. package/sensor/dist/installer/targets/antigravity.js.map +0 -1
  314. package/sensor/dist/installer/targets/claude.d.ts +0 -62
  315. package/sensor/dist/installer/targets/claude.d.ts.map +0 -1
  316. package/sensor/dist/installer/targets/claude.js +0 -454
  317. package/sensor/dist/installer/targets/claude.js.map +0 -1
  318. package/sensor/dist/installer/targets/codex.d.ts +0 -18
  319. package/sensor/dist/installer/targets/codex.d.ts.map +0 -1
  320. package/sensor/dist/installer/targets/codex.js +0 -185
  321. package/sensor/dist/installer/targets/codex.js.map +0 -1
  322. package/sensor/dist/installer/targets/cursor.d.ts +0 -35
  323. package/sensor/dist/installer/targets/cursor.d.ts.map +0 -1
  324. package/sensor/dist/installer/targets/cursor.js +0 -254
  325. package/sensor/dist/installer/targets/cursor.js.map +0 -1
  326. package/sensor/dist/installer/targets/gemini.d.ts +0 -26
  327. package/sensor/dist/installer/targets/gemini.d.ts.map +0 -1
  328. package/sensor/dist/installer/targets/gemini.js +0 -165
  329. package/sensor/dist/installer/targets/gemini.js.map +0 -1
  330. package/sensor/dist/installer/targets/hermes.d.ts +0 -18
  331. package/sensor/dist/installer/targets/hermes.d.ts.map +0 -1
  332. package/sensor/dist/installer/targets/hermes.js +0 -359
  333. package/sensor/dist/installer/targets/hermes.js.map +0 -1
  334. package/sensor/dist/installer/targets/kiro.d.ts +0 -27
  335. package/sensor/dist/installer/targets/kiro.d.ts.map +0 -1
  336. package/sensor/dist/installer/targets/kiro.js +0 -178
  337. package/sensor/dist/installer/targets/kiro.js.map +0 -1
  338. package/sensor/dist/installer/targets/opencode.d.ts +0 -38
  339. package/sensor/dist/installer/targets/opencode.d.ts.map +0 -1
  340. package/sensor/dist/installer/targets/opencode.js +0 -288
  341. package/sensor/dist/installer/targets/opencode.js.map +0 -1
  342. package/sensor/dist/installer/targets/registry.d.ts +0 -35
  343. package/sensor/dist/installer/targets/registry.d.ts.map +0 -1
  344. package/sensor/dist/installer/targets/registry.js +0 -91
  345. package/sensor/dist/installer/targets/registry.js.map +0 -1
  346. package/sensor/dist/installer/targets/shared.d.ts +0 -101
  347. package/sensor/dist/installer/targets/shared.d.ts.map +0 -1
  348. package/sensor/dist/installer/targets/shared.js +0 -264
  349. package/sensor/dist/installer/targets/shared.js.map +0 -1
  350. package/sensor/dist/installer/targets/toml.d.ts +0 -52
  351. package/sensor/dist/installer/targets/toml.d.ts.map +0 -1
  352. package/sensor/dist/installer/targets/toml.js +0 -147
  353. package/sensor/dist/installer/targets/toml.js.map +0 -1
  354. package/sensor/dist/installer/targets/types.d.ts +0 -108
  355. package/sensor/dist/installer/targets/types.d.ts.map +0 -1
  356. package/sensor/dist/installer/targets/types.js +0 -16
  357. package/sensor/dist/installer/targets/types.js.map +0 -1
  358. package/sensor/dist/upgrade/index.d.ts +0 -171
  359. package/sensor/dist/upgrade/index.d.ts.map +0 -1
  360. package/sensor/dist/upgrade/index.js +0 -659
  361. package/sensor/dist/upgrade/index.js.map +0 -1
  362. package/sensor/dist/upgrade/remove-binary.d.ts +0 -87
  363. package/sensor/dist/upgrade/remove-binary.d.ts.map +0 -1
  364. package/sensor/dist/upgrade/remove-binary.js +0 -289
  365. package/sensor/dist/upgrade/remove-binary.js.map +0 -1
  366. package/sensor/dist/upgrade/update-check.d.ts +0 -92
  367. package/sensor/dist/upgrade/update-check.d.ts.map +0 -1
  368. package/sensor/dist/upgrade/update-check.js +0 -258
  369. package/sensor/dist/upgrade/update-check.js.map +0 -1
  370. package/src/bootstrap.mjs +0 -88
@@ -0,0 +1,517 @@
1
+ import { canonicalizeArtifact, digestArtifact } from './artifact-contracts.mjs';
2
+ import { selfDigest, validateEpochRebindPacket, validateExecutorPacket } from './runtime-contracts.mjs';
3
+
4
+ const SHA256 = /^[0-9a-f]{64}$/;
5
+ const ID = /^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$/;
6
+
7
+ export const CONTROLLER_OPERATIONS = Object.freeze([
8
+ 'dispatch', 'observe', 'inventory', 'barrier', 'rebind', 'prepare', 'activate', 'release', 'revoke',
9
+ ]);
10
+
11
+ const RUNTIME_CONTROL_OUTCOMES = Object.freeze({
12
+ activate: 'activated',
13
+ finding_record: 'recorded',
14
+ conflict: 'frozen',
15
+ hold: 'held',
16
+ recompile: 'recompiled',
17
+ reprocess: 'reprocessed',
18
+ close: 'closed',
19
+ abandon: 'abandoned',
20
+ });
21
+ const ARTIFACT_CONTROL_OPERATIONS = new Set(['finding_record', 'recompile']);
22
+ const DIGEST_REFERENCE_OPERATIONS = new Set(['conflict']);
23
+ const MAX_CONTROL_ARTIFACT_BYTES = 8_388_608;
24
+
25
+ const WIRES = Object.freeze({
26
+ dispatch: {
27
+ request: ['schema', 'request_id', 'registration_digest', 'packet', 'write_lease', 'request_digest'],
28
+ requestSchema: 'lattice.adapter_dispatch_request.v1',
29
+ response: ['schema', 'request_id', 'executor_handle', 'worktree_id', 'packet_digest', 'lease_digest', 'response_digest'],
30
+ responseSchema: 'lattice.adapter_dispatch_response.v1',
31
+ },
32
+ observe: {
33
+ request: ['schema', 'request_id', 'registration_digest', 'executor_handle', 'expected_epoch', 'expected_lease_digest', 'request_digest'],
34
+ requestSchema: 'lattice.adapter_observe_request.v1',
35
+ response: ['schema', 'request_id', 'observation', 'observation_digest', 'response_digest'],
36
+ responseSchema: 'lattice.adapter_observe_response.v1',
37
+ },
38
+ inventory: {
39
+ request: ['schema', 'request_id', 'registration_digest', 'frozen_event_digest', 'request_digest'],
40
+ requestSchema: 'lattice.adapter_running_inventory_request.v1',
41
+ response: ['schema', 'request_id', 'running_bindings', 'inventory_digest', 'response_digest'],
42
+ responseSchema: 'lattice.adapter_running_inventory_response.v1',
43
+ },
44
+ barrier: {
45
+ request: ['schema', 'request_id', 'registration_digest', 'barrier_id', 'reason', 'running_bindings', 'frozen_event_digest', 'barrier_control_digest', 'request_digest'],
46
+ requestSchema: 'lattice.adapter_barrier_request.v1',
47
+ response: ['schema', 'request_id', 'barrier_id', 'quiescence_acks', 'response_digest'],
48
+ responseSchema: 'lattice.adapter_barrier_response.v1',
49
+ },
50
+ rebind: {
51
+ request: ['schema', 'request_id', 'registration_digest', 'rebind_packet', 'staged_lease', 'request_digest'],
52
+ requestSchema: 'lattice.adapter_rebind_request.v1',
53
+ response: ['schema', 'request_id', 'rebind_ack', 'staged_lease_digest', 'response_digest'],
54
+ responseSchema: 'lattice.adapter_rebind_response.v1',
55
+ },
56
+ prepare: {
57
+ request: ['schema', 'request_id', 'registration_digest', 'executor_packet', 'staged_lease', 'request_digest'],
58
+ requestSchema: 'lattice.adapter_prepare_request.v1',
59
+ response: ['schema', 'request_id', 'prepare_ack', 'staged_lease_digest', 'response_digest'],
60
+ responseSchema: 'lattice.adapter_prepare_response.v1',
61
+ },
62
+ activate: {
63
+ request: ['schema', 'request_id', 'registration_digest', 'committed_epoch_digest', 'activation_digest', 'staged_lease_digests', 'request_digest'],
64
+ requestSchema: 'lattice.adapter_activate_request.v1',
65
+ response: ['schema', 'request_id', 'ready_ack', 'observed_pointer_digest', 'response_digest'],
66
+ responseSchema: 'lattice.adapter_activate_response.v1',
67
+ },
68
+ release: {
69
+ request: ['schema', 'request_id', 'registration_digest', 'release_barrier_digest', 'activation_digest', 'gate_generation', 'staged_lease_digests', 'request_digest'],
70
+ requestSchema: 'lattice.adapter_release_request.v1',
71
+ response: ['schema', 'request_id', 'release_ack', 'armed_lease_digests', 'observed_gate_generation', 'response_digest'],
72
+ responseSchema: 'lattice.adapter_release_response.v1',
73
+ },
74
+ revoke: {
75
+ request: ['schema', 'request_id', 'registration_digest', 'reason', 'lease_digests', 'request_digest'],
76
+ requestSchema: 'lattice.adapter_revoke_request.v1',
77
+ response: ['schema', 'request_id', 'revoked_lease_digests', 'residual_processes', 'response_digest'],
78
+ responseSchema: 'lattice.adapter_revoke_response.v1',
79
+ },
80
+ });
81
+
82
+ function plain(value) {
83
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
84
+ && Object.getPrototypeOf(value) === Object.prototype;
85
+ }
86
+
87
+ function exact(value, fields) {
88
+ if (!plain(value)) return false;
89
+ const actual = Object.keys(value).sort();
90
+ const expected = [...fields].sort();
91
+ return actual.length === expected.length && actual.every((key, i) => key === expected[i]);
92
+ }
93
+
94
+ function digest(value) { return typeof value === 'string' && SHA256.test(value); }
95
+ function identifier(value) { return typeof value === 'string' && ID.test(value); }
96
+ function uniqueSortedDigests(value) {
97
+ return Array.isArray(value) && value.length <= 256 && value.every(digest)
98
+ && value.every((entry, index) => index === 0 || value[index - 1] < entry);
99
+ }
100
+ function selfValid(value, field) {
101
+ try { return digest(value[field]) && selfDigest(value, field) === value[field]; } catch { return false; }
102
+ }
103
+
104
+ export function validateRuntimeHeartbeatPolicy(value) {
105
+ return exact(value, ['schema', 'interval_ms', 'ttl_ms', 'disconnect_revokes_immediately', 'policy_digest'])
106
+ && value.schema === 'lattice.runtime_heartbeat_policy.v1'
107
+ && Number.isSafeInteger(value.interval_ms) && value.interval_ms > 0
108
+ && Number.isSafeInteger(value.ttl_ms) && value.ttl_ms > value.interval_ms
109
+ && value.disconnect_revokes_immediately === true
110
+ && selfValid(value, 'policy_digest');
111
+ }
112
+
113
+ export function validateControllerHeartbeat(value) {
114
+ return exact(value, ['schema', 'controller_id', 'registration_digest', 'supervisor_session_nonce', 'sequence', 'lease_set_digest', 'heartbeat_digest'])
115
+ && value.schema === 'lattice.adapter_controller_heartbeat.v1'
116
+ && identifier(value.controller_id) && digest(value.registration_digest)
117
+ && typeof value.supervisor_session_nonce === 'string' && value.supervisor_session_nonce.length >= 32
118
+ && Number.isSafeInteger(value.sequence) && value.sequence > 0 && digest(value.lease_set_digest)
119
+ && selfValid(value, 'heartbeat_digest');
120
+ }
121
+
122
+ export function validateRuntimeAdapterCapabilities(value) {
123
+ return exact(value, ['schema', 'operations', 'process_observation', 'worktree_fingerprint', 'staged_write_lease', 'durable_dispatch', 'capabilities_digest'])
124
+ && value.schema === 'lattice.runtime_adapter_capabilities.v1'
125
+ && Array.isArray(value.operations) && value.operations.length === CONTROLLER_OPERATIONS.length
126
+ && value.operations.every((op, i) => op === CONTROLLER_OPERATIONS[i])
127
+ && value.process_observation === true && value.worktree_fingerprint === true
128
+ && value.staged_write_lease === true && value.durable_dispatch === true
129
+ && selfValid(value, 'capabilities_digest');
130
+ }
131
+
132
+ export function validateProcessStartIdentity(value) {
133
+ return exact(value, ['schema', 'platform', 'pid', 'started_identity', 'identity_digest'])
134
+ && value.schema === 'lattice.process_start_identity.v1'
135
+ && typeof value.platform === 'string' && value.platform.length > 0
136
+ && Number.isSafeInteger(value.pid) && value.pid > 0
137
+ && typeof value.started_identity === 'string' && value.started_identity.length > 0
138
+ && selfValid(value, 'identity_digest');
139
+ }
140
+
141
+ export function validateControllerDescriptor(value) {
142
+ return exact(value, ['schema', 'controller_id', 'adapter_kind', 'pid', 'process_start_identity', 'socket_ref', 'controller_session_nonce_digest', 'capabilities', 'heartbeat', 'descriptor_digest'])
143
+ && value.schema === 'lattice.runtime_adapter_controller_descriptor.v1'
144
+ && identifier(value.controller_id) && identifier(value.adapter_kind)
145
+ && Number.isSafeInteger(value.pid) && value.pid > 0
146
+ && validateProcessStartIdentity(value.process_start_identity)
147
+ && value.process_start_identity.pid === value.pid
148
+ && value.socket_ref === `supervisor/controllers/${value.controller_id}.sock`
149
+ && digest(value.controller_session_nonce_digest)
150
+ && validateRuntimeAdapterCapabilities(value.capabilities)
151
+ && validateRuntimeHeartbeatPolicy(value.heartbeat)
152
+ && selfValid(value, 'descriptor_digest');
153
+ }
154
+
155
+ export function validateControllerRegistration(value) {
156
+ return exact(value, ['schema', 'registration_id', 'run_id', 'supervisor_session_nonce_digest', 'controller_descriptor_digest', 'registered_operations', 'registered_at', 'registration_digest'])
157
+ && value.schema === 'lattice.runtime_adapter_registration.v1'
158
+ && identifier(value.registration_id) && identifier(value.run_id)
159
+ && digest(value.supervisor_session_nonce_digest) && digest(value.controller_descriptor_digest)
160
+ && Array.isArray(value.registered_operations)
161
+ && value.registered_operations.length === CONTROLLER_OPERATIONS.length
162
+ && value.registered_operations.every((op, i) => op === CONTROLLER_OPERATIONS[i])
163
+ && typeof value.registered_at === 'string' && !Number.isNaN(Date.parse(value.registered_at))
164
+ && selfValid(value, 'registration_digest');
165
+ }
166
+
167
+ export function validateAdapterRegistry(value) {
168
+ return exact(value, ['schema', 'entries', 'registry_digest'])
169
+ && value.schema === 'lattice.runtime_adapter_registry.v1'
170
+ && Array.isArray(value.entries) && value.entries.length > 0 && value.entries.length <= 256
171
+ && value.entries.every((entry) => exact(entry, ['adapter_kind', 'launch_descriptor_ref', 'launch_descriptor_digest'])
172
+ && identifier(entry.adapter_kind) && typeof entry.launch_descriptor_ref === 'string'
173
+ && entry.launch_descriptor_ref === `.lattice/runtime/adapter-registry/descriptors/${entry.adapter_kind}.json`
174
+ && digest(entry.launch_descriptor_digest))
175
+ && new Set(value.entries.map((entry) => entry.adapter_kind)).size === value.entries.length
176
+ && value.entries.every((entry, index) => index === 0 || value.entries[index - 1].adapter_kind < entry.adapter_kind)
177
+ && selfValid(value, 'registry_digest');
178
+ }
179
+
180
+ function nullableDigest(value) { return value === null || digest(value); }
181
+ export function validateAdapterLaunchDescriptor(value) {
182
+ if (!exact(value, ['schema', 'adapter_kind', 'launch_kind', 'binary_path', 'binary_digest', 'binary_identity', 'argv', 'config_ref', 'config_digest', 'endpoint', 'capabilities_digest', 'descriptor_digest'])
183
+ || value.schema !== 'lattice.runtime_adapter_launch_descriptor.v1'
184
+ || !identifier(value.adapter_kind) || !['host_binary', 'existing_endpoint'].includes(value.launch_kind)
185
+ || !Array.isArray(value.argv) || value.argv.length > 64 || !value.argv.every((arg) => typeof arg === 'string' && !arg.includes('\0'))
186
+ || !digest(value.capabilities_digest) || !selfValid(value, 'descriptor_digest')) return false;
187
+ if (value.launch_kind === 'host_binary') {
188
+ return typeof value.binary_path === 'string' && value.binary_path.startsWith('/')
189
+ && digest(value.binary_digest) && value.endpoint === null
190
+ && (value.binary_identity === null || (exact(value.binary_identity, ['schema', 'kind', 'cdhash', 'signing_identifier', 'team_identifier', 'designated_requirement_digest', 'identity_digest'])
191
+ && value.binary_identity.schema === 'lattice.macos_binary_identity.v1'
192
+ && value.binary_identity.kind === 'macos_codesign'
193
+ && [value.binary_identity.cdhash, value.binary_identity.designated_requirement_digest].every(digest)
194
+ && typeof value.binary_identity.signing_identifier === 'string'
195
+ && typeof value.binary_identity.team_identifier === 'string'
196
+ && selfValid(value.binary_identity, 'identity_digest')))
197
+ && typeof value.config_ref === 'string' && value.config_ref.length > 0 && digest(value.config_digest);
198
+ }
199
+ return value.binary_path === null && value.binary_digest === null && value.binary_identity === null
200
+ && value.argv.length === 0 && value.config_ref === null && value.config_digest === null
201
+ && typeof value.endpoint === 'string' && value.endpoint.length > 0;
202
+ }
203
+
204
+ export function createControllerBootstrap({ requestId, runId, controllerSocketRef, supervisorSocketRef, supervisorSessionNonce }) {
205
+ const value = { schema: 'lattice.adapter_controller_bootstrap.v1', request_id: requestId, run_id: runId, controller_socket_ref: controllerSocketRef, supervisor_socket_ref: supervisorSocketRef, supervisor_session_nonce: supervisorSessionNonce, bootstrap_digest: '' };
206
+ value.bootstrap_digest = selfDigest(value, 'bootstrap_digest');
207
+ return value;
208
+ }
209
+
210
+ export function validateControllerHandshakeResponse(value, { requestId, challenge, runId }) {
211
+ return exact(value, ['schema', 'request_id', 'run_id', 'challenge_digest', 'controller_session_nonce', 'descriptor', 'response_digest'])
212
+ && value.schema === 'lattice.adapter_controller_handshake_response.v1'
213
+ && value.request_id === requestId && value.run_id === runId
214
+ && value.challenge_digest === digestArtifact(challenge)
215
+ && typeof value.controller_session_nonce === 'string' && value.controller_session_nonce.length >= 32
216
+ && validateControllerDescriptor(value.descriptor)
217
+ && value.descriptor.controller_session_nonce_digest === digestArtifact(value.controller_session_nonce)
218
+ && selfValid(value, 'response_digest');
219
+ }
220
+
221
+ export function validateRuntimeControlRequest(value) {
222
+ return exact(value, ['schema', 'request_id', 'run_id', 'operation', 'payload', 'session_nonce', 'request_digest'])
223
+ && value.schema === 'lattice.runtime_control_request.v1'
224
+ && identifier(value.request_id) && identifier(value.run_id)
225
+ && ['activate', 'finding_record', 'conflict', 'hold', 'recompile', 'reprocess', 'close', 'abandon'].includes(value.operation)
226
+ && validateRuntimeControlOperation(value.payload)
227
+ && value.payload.operation === value.operation
228
+ && typeof value.session_nonce === 'string' && value.session_nonce.length >= 32
229
+ && selfValid(value, 'request_digest');
230
+ }
231
+
232
+ function validateRuntimeControlOperation(value) {
233
+ return exact(value, ['schema', 'operation', 'run_ref', 'artifact', 'artifact_digest', 'checkpoint_digest',
234
+ 'expected_epoch', 'expected_queue_digest', 'shutdown_reason', 'operation_digest'])
235
+ && value.schema === 'lattice.runtime_control_operation.v1'
236
+ && ['activate', 'finding_record', 'conflict', 'hold', 'recompile', 'reprocess', 'close', 'abandon'].includes(value.operation)
237
+ && typeof value.run_ref === 'string' && value.run_ref.length > 0
238
+ && (ARTIFACT_CONTROL_OPERATIONS.has(value.operation)
239
+ ? plain(value.artifact)
240
+ && Buffer.byteLength(canonicalizeArtifact(value.artifact), 'utf8') <= MAX_CONTROL_ARTIFACT_BYTES
241
+ && digest(value.artifact_digest) && digestArtifact(value.artifact) === value.artifact_digest
242
+ : value.artifact === null)
243
+ && (DIGEST_REFERENCE_OPERATIONS.has(value.operation)
244
+ ? digest(value.artifact_digest)
245
+ : (ARTIFACT_CONTROL_OPERATIONS.has(value.operation) || value.artifact_digest === null))
246
+ && (value.operation === 'finding_record'
247
+ ? digest(value.checkpoint_digest) : value.checkpoint_digest === null)
248
+ && Number.isSafeInteger(value.expected_epoch) && value.expected_epoch > 0
249
+ && nullableDigest(value.expected_queue_digest)
250
+ && (['close', 'abandon'].includes(value.operation)
251
+ ? typeof value.shutdown_reason === 'string' && value.shutdown_reason.length > 0
252
+ : value.shutdown_reason === null)
253
+ && selfValid(value, 'operation_digest');
254
+ }
255
+
256
+ export function createRuntimeControlRequest({ requestId, runId, operation, payload, sessionNonce }) {
257
+ const request = { schema: 'lattice.runtime_control_request.v1', request_id: requestId, run_id: runId, operation, payload, session_nonce: sessionNonce, request_digest: '' };
258
+ request.request_digest = selfDigest(request, 'request_digest');
259
+ if (!validateRuntimeControlRequest(request)) throw new TypeError('INVALID_RUNTIME_CONTROL_REQUEST');
260
+ return request;
261
+ }
262
+
263
+ export function validateRuntimeControlResponse(value, expectedOperation = null) {
264
+ return exact(value, ['schema', 'request_id', 'run_id', 'outcome', 'result', 'control_head_digest', 'response_digest'])
265
+ && value.schema === 'lattice.runtime_control_response.v1'
266
+ && identifier(value.request_id) && identifier(value.run_id)
267
+ && ['completed', 'rejected', 'unknown'].includes(value.outcome)
268
+ && validateRuntimeControlResult(value.result)
269
+ && (expectedOperation === null || value.result.operation === expectedOperation)
270
+ && value.result.control_head_digest === value.control_head_digest
271
+ && (value.outcome === 'completed'
272
+ ? value.result.outcome === RUNTIME_CONTROL_OUTCOMES[value.result.operation]
273
+ : value.result.outcome === value.outcome)
274
+ && nullableDigest(value.control_head_digest)
275
+ && selfValid(value, 'response_digest');
276
+ }
277
+
278
+ function validateRuntimeControlResult(value) {
279
+ const fields = ['schema', 'operation', 'outcome', 'event_head_digest', 'control_head_digest',
280
+ 'active_epoch', 'staged_epoch', 'unmet', 'result_digest'];
281
+ if (value?.operation === 'finding_record' && value?.outcome === 'recorded') fields.push('finding_digest');
282
+ return exact(value, fields)
283
+ && value.schema === 'lattice.runtime_control_result.v1'
284
+ && Object.hasOwn(RUNTIME_CONTROL_OUTCOMES, value.operation)
285
+ && [RUNTIME_CONTROL_OUTCOMES[value.operation], 'rejected', 'unknown'].includes(value.outcome)
286
+ && nullableDigest(value.event_head_digest) && nullableDigest(value.control_head_digest)
287
+ && Number.isSafeInteger(value.active_epoch) && value.active_epoch > 0
288
+ && (value.staged_epoch === null
289
+ || (Number.isSafeInteger(value.staged_epoch) && value.staged_epoch > 0))
290
+ && Array.isArray(value.unmet) && value.unmet.length <= 256
291
+ && value.unmet.every((entry) => typeof entry === 'string' && entry.length > 0)
292
+ && (value.operation !== 'finding_record' || value.outcome !== 'recorded'
293
+ || digest(value.finding_digest))
294
+ && selfValid(value, 'result_digest');
295
+ }
296
+
297
+ export function createControllerRequest(operation, fields) {
298
+ const wire = WIRES[operation];
299
+ if (!wire) throw new TypeError('UNKNOWN_CONTROLLER_OPERATION');
300
+ const request = { schema: wire.requestSchema, ...fields, request_digest: '' };
301
+ request.request_digest = selfDigest(request, 'request_digest');
302
+ if (!validateControllerRequest(operation, request)) throw new TypeError('INVALID_CONTROLLER_REQUEST');
303
+ return request;
304
+ }
305
+
306
+ export function validateControllerRequest(operation, value) {
307
+ const wire = WIRES[operation];
308
+ if (!(Boolean(wire) && exact(value, wire.request) && value.schema === wire.requestSchema
309
+ && identifier(value.request_id) && digest(value.registration_digest)
310
+ && selfValid(value, 'request_digest'))) return false;
311
+ if (operation === 'dispatch') return validateExecutorPacket(value.packet) && validateArmedWriteLease(value.write_lease);
312
+ if (operation === 'observe') return identifier(value.executor_handle) && Number.isSafeInteger(value.expected_epoch)
313
+ && value.expected_epoch > 0 && digest(value.expected_lease_digest);
314
+ if (operation === 'inventory') return digest(value.frozen_event_digest);
315
+ if (operation === 'barrier') return identifier(value.barrier_id) && typeof value.reason === 'string'
316
+ && value.reason.length > 0 && Array.isArray(value.running_bindings)
317
+ && value.running_bindings.every(validateProtocolRunningBinding) && digest(value.frozen_event_digest)
318
+ && digest(value.barrier_control_digest);
319
+ if (operation === 'rebind') return validateEpochRebindPacket(value.rebind_packet) && validateStagedWriteLease(value.staged_lease);
320
+ if (operation === 'prepare') return validateExecutorPacket(value.executor_packet) && validateStagedWriteLease(value.staged_lease);
321
+ if (operation === 'activate') return digest(value.committed_epoch_digest) && digest(value.activation_digest)
322
+ && uniqueSortedDigests(value.staged_lease_digests);
323
+ if (operation === 'release') return digest(value.release_barrier_digest) && digest(value.activation_digest)
324
+ && Number.isSafeInteger(value.gate_generation) && value.gate_generation > 0
325
+ && uniqueSortedDigests(value.staged_lease_digests);
326
+ return typeof value.reason === 'string' && value.reason.length > 0 && uniqueSortedDigests(value.lease_digests);
327
+ }
328
+
329
+ export function validateControllerResponse(operation, value, expectedRequestId = null) {
330
+ const wire = WIRES[operation];
331
+ if (!(Boolean(wire) && exact(value, wire.response) && value.schema === wire.responseSchema
332
+ && identifier(value.request_id) && (expectedRequestId === null || value.request_id === expectedRequestId)
333
+ && selfValid(value, 'response_digest'))) return false;
334
+ if (operation === 'dispatch') return identifier(value.executor_handle) && identifier(value.worktree_id)
335
+ && digest(value.packet_digest) && digest(value.lease_digest);
336
+ if (operation === 'observe') return exact(value.observation, ['schema', 'state', 'executor_handle', 'plan_epoch', 'lease_digest', 'payload_digest', 'observation_digest'])
337
+ && value.observation.schema === 'lattice.adapter_observation.v1'
338
+ && ['running', 'checkpoint_ready', 'terminal', 'held'].includes(value.observation.state)
339
+ && identifier(value.observation.executor_handle) && Number.isSafeInteger(value.observation.plan_epoch)
340
+ && value.observation.plan_epoch > 0 && digest(value.observation.lease_digest)
341
+ && digest(value.observation.payload_digest) && selfValid(value.observation, 'observation_digest')
342
+ && value.observation_digest === value.observation.observation_digest;
343
+ if (operation === 'inventory') return Array.isArray(value.running_bindings)
344
+ && value.running_bindings.length <= 4096
345
+ && value.running_bindings.every(validateProtocolRunningBinding)
346
+ && value.running_bindings.every((binding, index) => index === 0
347
+ || value.running_bindings[index - 1].todo_id < binding.todo_id)
348
+ && new Set(value.running_bindings.map((binding) => binding.executor_handle)).size === value.running_bindings.length
349
+ && digest(value.inventory_digest)
350
+ && value.inventory_digest === digestArtifact(value.running_bindings);
351
+ if (operation === 'barrier') return identifier(value.barrier_id) && Array.isArray(value.quiescence_acks)
352
+ && value.quiescence_acks.every(validateQuiescenceAck);
353
+ if (operation === 'rebind') return validateEpochRebindAck(value.rebind_ack) && digest(value.staged_lease_digest);
354
+ if (operation === 'prepare') return validatePrepareAck(value.prepare_ack)
355
+ && value.prepare_ack.staged_lease_digest === value.staged_lease_digest;
356
+ if (operation === 'activate') return validateReadyAck(value.ready_ack)
357
+ && digest(value.observed_pointer_digest);
358
+ if (operation === 'release') return validateReleaseAck(value.release_ack)
359
+ && uniqueSortedDigests(value.armed_lease_digests)
360
+ && Number.isSafeInteger(value.observed_gate_generation) && value.observed_gate_generation > 0;
361
+ return uniqueSortedDigests(value.revoked_lease_digests) && Array.isArray(value.residual_processes)
362
+ && value.residual_processes.every((entry) => exact(entry, ['schema', 'pid', 'process_start_identity_digest', 'state'])
363
+ && entry.schema === 'lattice.adapter_residual_process.v1'
364
+ && Number.isSafeInteger(entry.pid) && entry.pid > 0 && digest(entry.process_start_identity_digest)
365
+ && ['running', 'stopped', 'unknown'].includes(entry.state));
366
+ }
367
+
368
+ function validatePrepareAck(value) {
369
+ return exact(value, ['schema', 'ack_id', 'registration_digest', 'controller_id', 'run_id', 'todo_id', 'plan_epoch', 'packet_digest', 'staged_lease_digest', 'supervisor_session_nonce_digest', 'ack_digest'])
370
+ && value.schema === 'lattice.adapter_prepare_ack.v1'
371
+ && ['ack_id', 'controller_id', 'run_id', 'todo_id'].every((key) => identifier(value[key]))
372
+ && Number.isSafeInteger(value.plan_epoch) && value.plan_epoch > 0
373
+ && ['registration_digest', 'packet_digest', 'staged_lease_digest', 'supervisor_session_nonce_digest'].every((key) => digest(value[key]))
374
+ && selfValid(value, 'ack_digest');
375
+ }
376
+
377
+ function validateReadyAck(value) {
378
+ return exact(value, ['schema', 'ack_id', 'registration_digest', 'controller_id', 'run_id', 'plan_epoch', 'activation_digest', 'staged_lease_digests', 'supervisor_session_nonce_digest', 'ack_digest'])
379
+ && value.schema === 'lattice.adapter_ready_ack.v1'
380
+ && ['ack_id', 'controller_id', 'run_id'].every((key) => identifier(value[key]))
381
+ && Number.isSafeInteger(value.plan_epoch) && value.plan_epoch > 0
382
+ && ['registration_digest', 'activation_digest', 'supervisor_session_nonce_digest'].every((key) => digest(value[key]))
383
+ && uniqueSortedDigests(value.staged_lease_digests) && selfValid(value, 'ack_digest');
384
+ }
385
+
386
+ function validateProtocolRunningBinding(value) {
387
+ return exact(value, ['todo_id', 'executor_handle', 'worktree_id', 'plan_epoch', 'packet_digest', 'write_lease_id', 'controller_registration_digest'])
388
+ && identifier(value.todo_id) && identifier(value.executor_handle) && identifier(value.worktree_id)
389
+ && Number.isSafeInteger(value.plan_epoch) && value.plan_epoch > 0 && digest(value.packet_digest)
390
+ && identifier(value.write_lease_id) && digest(value.controller_registration_digest);
391
+ }
392
+
393
+ export function validateQuiescenceAck(value) {
394
+ return exact(value, ['schema', 'ack_id', 'run_id', 'todo_id', 'executor_handle', 'worktree_id', 'plan_epoch', 'packet_digest', 'write_lease_id', 'barrier_control_digest', 'final_checkpoint_digest', 'process_observation_digest', 'worktree_fingerprint_digest', 'supervisor_session_nonce_digest', 'ack_digest'])
395
+ && value.schema === 'lattice.executor_quiescence_ack.v1'
396
+ && ['ack_id', 'run_id', 'todo_id', 'executor_handle', 'worktree_id', 'write_lease_id'].every((key) => identifier(value[key]))
397
+ && Number.isSafeInteger(value.plan_epoch) && value.plan_epoch > 0
398
+ && ['packet_digest', 'barrier_control_digest', 'final_checkpoint_digest', 'process_observation_digest', 'worktree_fingerprint_digest', 'supervisor_session_nonce_digest'].every((key) => digest(value[key]))
399
+ && selfValid(value, 'ack_digest');
400
+ }
401
+
402
+ export function validateEpochRebindAck(value) {
403
+ return exact(value, ['schema', 'ack_id', 'run_id', 'todo_id', 'executor_handle', 'worktree_id', 'predecessor_epoch', 'successor_epoch', 'predecessor_packet_digest', 'rebind_packet_digest', 'new_write_lease_id', 'supervisor_session_nonce_digest', 'ack_digest'])
404
+ && value.schema === 'lattice.executor_epoch_rebind_ack.v1'
405
+ && ['ack_id', 'run_id', 'todo_id', 'executor_handle', 'worktree_id', 'new_write_lease_id'].every((key) => identifier(value[key]))
406
+ && Number.isSafeInteger(value.predecessor_epoch) && value.predecessor_epoch > 0
407
+ && value.successor_epoch === value.predecessor_epoch + 1
408
+ && ['predecessor_packet_digest', 'rebind_packet_digest', 'supervisor_session_nonce_digest'].every((key) => digest(value[key]))
409
+ && selfValid(value, 'ack_digest');
410
+ }
411
+
412
+ export function validateStagedWriteLease(value) {
413
+ return exact(value, ['schema', 'lease_id', 'run_id', 'todo_id', 'plan_epoch', 'packet_digest', 'controller_registration_digest', 'supervisor_session_nonce_digest', 'state', 'ttl_ms', 'issued_control_digest', 'lease_digest'])
414
+ && value.schema === 'lattice.runtime_write_lease.v1' && value.state === 'staged'
415
+ && ['lease_id', 'run_id', 'todo_id'].every((key) => identifier(value[key]))
416
+ && Number.isSafeInteger(value.plan_epoch) && value.plan_epoch > 0
417
+ && Number.isSafeInteger(value.ttl_ms) && value.ttl_ms > 0
418
+ && ['packet_digest', 'controller_registration_digest', 'supervisor_session_nonce_digest', 'issued_control_digest'].every((key) => digest(value[key]))
419
+ && selfValid(value, 'lease_digest');
420
+ }
421
+
422
+ export function validateArmedWriteLease(value) {
423
+ return exact(value, ['schema', 'lease_id', 'run_id', 'todo_id', 'plan_epoch', 'packet_digest', 'controller_registration_digest', 'supervisor_session_nonce_digest', 'state', 'ttl_ms', 'issued_control_digest', 'release_barrier_digest', 'gate_generation', 'lease_digest'])
424
+ && value.schema === 'lattice.runtime_write_lease.v2' && value.state === 'armed'
425
+ && ['lease_id', 'run_id', 'todo_id'].every((key) => identifier(value[key]))
426
+ && Number.isSafeInteger(value.plan_epoch) && value.plan_epoch > 0
427
+ && Number.isSafeInteger(value.ttl_ms) && value.ttl_ms > 0
428
+ && Number.isSafeInteger(value.gate_generation) && value.gate_generation > 0
429
+ && ['packet_digest', 'controller_registration_digest', 'supervisor_session_nonce_digest', 'issued_control_digest', 'release_barrier_digest'].every((key) => digest(value[key]))
430
+ && selfValid(value, 'lease_digest');
431
+ }
432
+
433
+ export function armStagedWriteLease(staged, { releaseBarrierDigest, gateGeneration }) {
434
+ if (!validateStagedWriteLease(staged) || !digest(releaseBarrierDigest)
435
+ || !Number.isSafeInteger(gateGeneration) || gateGeneration < 1) throw new TypeError('INVALID_STAGED_LEASE_ARM');
436
+ const armed = { ...staged, schema: 'lattice.runtime_write_lease.v2', state: 'armed', release_barrier_digest: releaseBarrierDigest, gate_generation: gateGeneration };
437
+ armed.lease_digest = selfDigest(armed, 'lease_digest');
438
+ return armed;
439
+ }
440
+
441
+ export function validateReleaseAck(value) {
442
+ return exact(value, ['schema', 'ack_id', 'registration_digest', 'controller_id', 'run_id', 'plan_epoch', 'release_barrier_digest', 'gate_generation', 'armed_lease_digests', 'supervisor_session_nonce_digest', 'ack_digest'])
443
+ && value.schema === 'lattice.adapter_release_ack.v1'
444
+ && ['ack_id', 'controller_id', 'run_id'].every((key) => identifier(value[key]))
445
+ && ['registration_digest', 'release_barrier_digest', 'supervisor_session_nonce_digest'].every((key) => digest(value[key]))
446
+ && Number.isSafeInteger(value.plan_epoch) && value.plan_epoch > 0
447
+ && Number.isSafeInteger(value.gate_generation) && value.gate_generation > 0
448
+ && uniqueSortedDigests(value.armed_lease_digests)
449
+ && selfValid(value, 'ack_digest');
450
+ }
451
+
452
+ export function createWriteGate({ runId, planEpoch, gateGeneration, releaseBarrierDigest, releaseAcks, armedLeases, previousGateDigest = null, committedAt }) {
453
+ const gate = {
454
+ schema: 'lattice.supervisor_write_gate.v1', run_id: runId, plan_epoch: planEpoch,
455
+ gate_generation: gateGeneration, release_barrier_digest: releaseBarrierDigest,
456
+ controller_release_ack_digests: releaseAcks.map((ack) => ack.ack_digest).sort(),
457
+ armed_lease_digests: armedLeases.map((lease) => lease.lease_digest).sort(),
458
+ previous_gate_digest: previousGateDigest, committed_at: committedAt, gate_digest: '',
459
+ };
460
+ gate.gate_digest = selfDigest(gate, 'gate_digest');
461
+ return gate;
462
+ }
463
+
464
+ export function verifyCentralWriteGate({ gate, runId, planEpoch, releaseBarrierDigest, sessionNonceDigest, registrations, controllers, releaseAcks, armedLeases, previousGate = null }) {
465
+ const fail = (reason) => ({ valid: false, reason });
466
+ if (!exact(gate, ['schema', 'run_id', 'plan_epoch', 'gate_generation', 'release_barrier_digest', 'controller_release_ack_digests', 'armed_lease_digests', 'previous_gate_digest', 'committed_at', 'gate_digest'])
467
+ || gate.schema !== 'lattice.supervisor_write_gate.v1' || !selfValid(gate, 'gate_digest')) return fail('gate_invalid');
468
+ if (gate.run_id !== runId || gate.plan_epoch !== planEpoch || gate.release_barrier_digest !== releaseBarrierDigest) return fail('gate_binding_mismatch');
469
+ if (gate.gate_generation !== (previousGate?.gate_generation ?? 0) + 1
470
+ || gate.previous_gate_digest !== (previousGate?.gate_digest ?? null)) return fail('gate_chain_mismatch');
471
+ if (!Array.isArray(registrations) || !Array.isArray(controllers) || registrations.length !== controllers.length
472
+ || releaseAcks.length !== registrations.length) return fail('controller_set_mismatch');
473
+ const controllerByDigest = new Map();
474
+ for (const controller of controllers) {
475
+ if (!validateControllerDescriptor(controller) || controllerByDigest.has(controller.descriptor_digest)) return fail('controller_invalid');
476
+ controllerByDigest.set(controller.descriptor_digest, controller);
477
+ }
478
+ const registrationByDigest = new Map();
479
+ for (const registration of registrations) {
480
+ const controller = controllerByDigest.get(registration.controller_descriptor_digest);
481
+ if (!validateControllerRegistration(registration) || !controller || registration.run_id !== runId
482
+ || registration.supervisor_session_nonce_digest !== sessionNonceDigest
483
+ || registrationByDigest.has(registration.registration_digest)) return fail('registration_invalid');
484
+ registrationByDigest.set(registration.registration_digest, { registration, controller });
485
+ }
486
+ const leaseByDigest = new Map();
487
+ for (const lease of armedLeases) {
488
+ if (!validateArmedWriteLease(lease) || lease.run_id !== runId || lease.plan_epoch !== planEpoch
489
+ || lease.supervisor_session_nonce_digest !== sessionNonceDigest
490
+ || lease.release_barrier_digest !== releaseBarrierDigest || lease.gate_generation !== gate.gate_generation
491
+ || !registrationByDigest.has(lease.controller_registration_digest) || leaseByDigest.has(lease.lease_digest)) return fail('lease_invalid');
492
+ leaseByDigest.set(lease.lease_digest, lease);
493
+ }
494
+ const seenRegistrations = new Set();
495
+ const ackLeaseUnion = new Set();
496
+ for (const ack of releaseAcks) {
497
+ const binding = registrationByDigest.get(ack.registration_digest);
498
+ if (!validateReleaseAck(ack) || !binding || seenRegistrations.has(ack.registration_digest)
499
+ || binding.controller.controller_id !== ack.controller_id || ack.run_id !== runId
500
+ || ack.plan_epoch !== planEpoch || ack.release_barrier_digest !== releaseBarrierDigest
501
+ || ack.gate_generation !== gate.gate_generation || ack.supervisor_session_nonce_digest !== sessionNonceDigest) return fail('release_ack_invalid');
502
+ seenRegistrations.add(ack.registration_digest);
503
+ for (const leaseDigest of ack.armed_lease_digests) {
504
+ const lease = leaseByDigest.get(leaseDigest);
505
+ if (!lease || lease.controller_registration_digest !== ack.registration_digest || ackLeaseUnion.has(leaseDigest)) return fail('release_ack_lease_invalid');
506
+ ackLeaseUnion.add(leaseDigest);
507
+ }
508
+ }
509
+ const expectedAcks = releaseAcks.map((ack) => ack.ack_digest).sort();
510
+ const expectedLeases = [...leaseByDigest.keys()].sort();
511
+ if (JSON.stringify(gate.controller_release_ack_digests) !== JSON.stringify(expectedAcks)
512
+ || JSON.stringify(gate.armed_lease_digests) !== JSON.stringify(expectedLeases)
513
+ || JSON.stringify([...ackLeaseUnion].sort()) !== JSON.stringify(expectedLeases)) return fail('gate_membership_mismatch');
514
+ return { valid: true, gate_digest: gate.gate_digest };
515
+ }
516
+
517
+ export function controllerProtocolDigest(value) { return digestArtifact(value); }