@wenathlan/saddle 1.8.17 → 2.0.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 (1005) hide show
  1. package/Dockerfile +1339 -0
  2. package/README.md +68 -22
  3. package/alternatives.ts +1218 -0
  4. package/biome.json +153 -0
  5. package/boards.json +1517 -0
  6. package/compute.ts +3144 -0
  7. package/cores.json +1801 -0
  8. package/dist/acquisition.d.ts +359 -0
  9. package/dist/acquisition.d.ts.map +1 -0
  10. package/dist/acquisition.js +629 -0
  11. package/dist/acquisition.js.map +1 -0
  12. package/dist/alternatives.d.ts +509 -0
  13. package/dist/alternatives.d.ts.map +1 -0
  14. package/dist/alternatives.js +951 -0
  15. package/dist/alternatives.js.map +1 -0
  16. package/dist/automation.d.ts +426 -0
  17. package/dist/automation.d.ts.map +1 -0
  18. package/dist/automation.js +561 -0
  19. package/dist/automation.js.map +1 -0
  20. package/dist/browser.d.ts +562 -0
  21. package/dist/browser.d.ts.map +1 -0
  22. package/dist/browser.js +1057 -0
  23. package/dist/browser.js.map +1 -0
  24. package/dist/capacitor.config.d.ts +13 -0
  25. package/dist/capacitor.config.d.ts.map +1 -0
  26. package/dist/capacitor.config.js +26 -0
  27. package/dist/capacitor.config.js.map +1 -0
  28. package/dist/cli.d.ts +17 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +111 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/communication.d.ts +192 -0
  33. package/dist/communication.d.ts.map +1 -0
  34. package/dist/communication.js +418 -0
  35. package/dist/communication.js.map +1 -0
  36. package/dist/compute.d.ts +1161 -0
  37. package/dist/compute.d.ts.map +1 -0
  38. package/dist/compute.js +2273 -0
  39. package/dist/compute.js.map +1 -0
  40. package/dist/distribution.d.ts +529 -0
  41. package/dist/distribution.d.ts.map +1 -0
  42. package/dist/distribution.js +811 -0
  43. package/dist/distribution.js.map +1 -0
  44. package/dist/execution.d.ts +530 -0
  45. package/dist/execution.d.ts.map +1 -0
  46. package/dist/execution.js +761 -0
  47. package/dist/execution.js.map +1 -0
  48. package/dist/format.d.ts +19 -0
  49. package/dist/format.d.ts.map +1 -0
  50. package/dist/format.js +60 -0
  51. package/dist/format.js.map +1 -0
  52. package/dist/foundation.d.ts +176 -0
  53. package/dist/foundation.d.ts.map +1 -0
  54. package/dist/foundation.js +309 -0
  55. package/dist/foundation.js.map +1 -0
  56. package/dist/index.d.ts +733 -122
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +1018 -122
  59. package/dist/index.js.map +1 -1
  60. package/dist/integration.d.ts +236 -0
  61. package/dist/integration.d.ts.map +1 -0
  62. package/dist/integration.js +236 -0
  63. package/dist/integration.js.map +1 -0
  64. package/dist/intelligence.d.ts +94 -0
  65. package/dist/intelligence.d.ts.map +1 -0
  66. package/dist/intelligence.js +145 -0
  67. package/dist/intelligence.js.map +1 -0
  68. package/dist/isolation.d.ts +129 -0
  69. package/dist/isolation.d.ts.map +1 -0
  70. package/dist/isolation.js +96 -0
  71. package/dist/isolation.js.map +1 -0
  72. package/dist/media.d.ts +344 -0
  73. package/dist/media.d.ts.map +1 -0
  74. package/dist/media.js +986 -0
  75. package/dist/media.js.map +1 -0
  76. package/dist/modes.d.ts +359 -0
  77. package/dist/modes.d.ts.map +1 -0
  78. package/dist/modes.js +134 -0
  79. package/dist/modes.js.map +1 -0
  80. package/dist/{library/public.d.ts → operations.d.ts} +15 -1
  81. package/dist/operations.d.ts.map +1 -0
  82. package/dist/{library/public.js → operations.js} +18 -7
  83. package/dist/operations.js.map +1 -0
  84. package/dist/orchestrator.d.ts +1339 -0
  85. package/dist/orchestrator.d.ts.map +1 -0
  86. package/dist/orchestrator.js +4308 -0
  87. package/dist/orchestrator.js.map +1 -0
  88. package/dist/performance.d.ts +416 -0
  89. package/dist/performance.d.ts.map +1 -0
  90. package/dist/performance.js +827 -0
  91. package/dist/performance.js.map +1 -0
  92. package/dist/quantum.d.ts +810 -0
  93. package/dist/quantum.d.ts.map +1 -0
  94. package/dist/quantum.js +2073 -0
  95. package/dist/quantum.js.map +1 -0
  96. package/dist/render.d.ts +381 -0
  97. package/dist/render.d.ts.map +1 -0
  98. package/dist/render.js +1073 -0
  99. package/dist/render.js.map +1 -0
  100. package/dist/scheduler.d.ts +596 -0
  101. package/dist/scheduler.d.ts.map +1 -0
  102. package/dist/scheduler.js +1259 -0
  103. package/dist/scheduler.js.map +1 -0
  104. package/dist/security.d.ts +501 -0
  105. package/dist/security.d.ts.map +1 -0
  106. package/dist/security.js +1170 -0
  107. package/dist/security.js.map +1 -0
  108. package/dist/server.d.ts +21 -0
  109. package/dist/server.d.ts.map +1 -0
  110. package/dist/{server/node.js → server.js} +16 -2
  111. package/dist/server.js.map +1 -0
  112. package/dist/tiers.d.ts +1002 -0
  113. package/dist/tiers.d.ts.map +1 -0
  114. package/dist/tiers.js +2165 -0
  115. package/dist/tiers.js.map +1 -0
  116. package/dist/virtual.d.ts +641 -0
  117. package/dist/virtual.d.ts.map +1 -0
  118. package/dist/virtual.js +1285 -0
  119. package/dist/virtual.js.map +1 -0
  120. package/dist/virtualcpu.d.ts +316 -0
  121. package/dist/virtualcpu.d.ts.map +1 -0
  122. package/dist/virtualcpu.js +1180 -0
  123. package/dist/virtualcpu.js.map +1 -0
  124. package/dist/virtualgpu.d.ts +345 -0
  125. package/dist/virtualgpu.d.ts.map +1 -0
  126. package/dist/virtualgpu.js +1000 -0
  127. package/dist/virtualgpu.js.map +1 -0
  128. package/dist/virtualization.d.ts +607 -0
  129. package/dist/virtualization.d.ts.map +1 -0
  130. package/dist/virtualization.js +1187 -0
  131. package/dist/virtualization.js.map +1 -0
  132. package/dist/virtualmemory.d.ts +818 -0
  133. package/dist/virtualmemory.d.ts.map +1 -0
  134. package/dist/virtualmemory.js +1796 -0
  135. package/dist/virtualmemory.js.map +1 -0
  136. package/dist/webscrape.d.ts +720 -0
  137. package/dist/webscrape.d.ts.map +1 -0
  138. package/dist/webscrape.js +2697 -0
  139. package/dist/webscrape.js.map +1 -0
  140. package/docker.config +769 -0
  141. package/docs/CONVERSA.txt +1523 -0
  142. package/docs/alternatives.md +499 -0
  143. package/docs/architecture-1.8.19.md +76 -0
  144. package/docs/architecture-1.8.19.mmd +33 -0
  145. package/docs/architecture-1.8.19.png +0 -0
  146. package/docs/architecture.md +355 -0
  147. package/docs/artifactavailability.md +6 -0
  148. package/docs/brancharchive-2026-08-18.md +18 -0
  149. package/docs/browser.md +7 -0
  150. package/docs/consolidation.md +70 -0
  151. package/docs/e2ugh-engine.md +528 -0
  152. package/{dist/examples/localjob.js → docs/example-localjob.ts} +3 -3
  153. package/{dist/examples/publicapi.js → docs/example-publicapi.ts} +2 -2
  154. package/docs/hardware.md +342 -0
  155. package/docs/optimization.md +126 -0
  156. package/docs/performance.md +499 -0
  157. package/docs/planning.1.8.18.md +94 -0
  158. package/docs/planning.1.8.19.md +49 -0
  159. package/docs/releasenotes-1.8.17.md +6 -0
  160. package/docs/releasenotes-1.8.18.md +32 -0
  161. package/docs/releasenotes-1.8.19.md +35 -0
  162. package/docs/research-1.8.18-isolation.md +43 -0
  163. package/docs/research-1.8.19-virtual-browser.md +27 -0
  164. package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
  165. package/docs/security.md +454 -0
  166. package/docs/todo-1.8.16.md +56 -1
  167. package/docs/todo-1.8.18.md +164 -0
  168. package/docs/todo-1.8.19.md +241 -0
  169. package/docs/viability.md +777 -0
  170. package/docs/virtualization.md +335 -0
  171. package/docs/web-duplicatecleanup.md +9 -0
  172. package/docs/web-ideas.md +106 -0
  173. package/docs/workflowimprovements-2026-08-19.md +70 -0
  174. package/gpumonitor.cpp +1543 -0
  175. package/gpus.json +2408 -0
  176. package/index.ts +1478 -0
  177. package/media.ts +1337 -0
  178. package/mttg.config +1549 -0
  179. package/orchestrator.ts +5462 -0
  180. package/package.json +304 -55
  181. package/passage.config +1331 -0
  182. package/performance.ts +1049 -0
  183. package/processors.json +2217 -0
  184. package/qemu.config +1062 -0
  185. package/qemubridge.py +1340 -0
  186. package/quantum.ts +2393 -0
  187. package/render.ts +1325 -0
  188. package/scheduler.ts +1600 -0
  189. package/security.ts +1449 -0
  190. package/tiers.ts +2871 -0
  191. package/tsconfig.json +29 -0
  192. package/virtualcpu.ts +1273 -0
  193. package/virtualgpu.ts +1181 -0
  194. package/virtualhardware.c +1011 -0
  195. package/virtualhardware.json +739 -0
  196. package/virtualization.ts +1628 -0
  197. package/virtualizationcore.cpp +4635 -0
  198. package/virtualmemory.ts +2303 -0
  199. package/vm.config.json +1910 -0
  200. package/{extension → web/extension}/manifest.json +1 -1
  201. package/web/readme.md +382 -0
  202. package/web/tsconfig.json +25 -0
  203. package/dist/adapters/forge.d.ts +0 -17
  204. package/dist/adapters/forge.d.ts.map +0 -1
  205. package/dist/adapters/forge.js +0 -19
  206. package/dist/adapters/forge.js.map +0 -1
  207. package/dist/adapters/forgejo.d.ts +0 -49
  208. package/dist/adapters/forgejo.d.ts.map +0 -1
  209. package/dist/adapters/forgejo.js +0 -8
  210. package/dist/adapters/forgejo.js.map +0 -1
  211. package/dist/adapters/github.d.ts +0 -12
  212. package/dist/adapters/github.d.ts.map +0 -1
  213. package/dist/adapters/github.js +0 -20
  214. package/dist/adapters/github.js.map +0 -1
  215. package/dist/adapters/gitlab.d.ts +0 -17
  216. package/dist/adapters/gitlab.d.ts.map +0 -1
  217. package/dist/adapters/gitlab.js +0 -10
  218. package/dist/adapters/gitlab.js.map +0 -1
  219. package/dist/adapters/huggingface.d.ts +0 -17
  220. package/dist/adapters/huggingface.d.ts.map +0 -1
  221. package/dist/adapters/huggingface.js +0 -6
  222. package/dist/adapters/huggingface.js.map +0 -1
  223. package/dist/adapters/socket.d.ts +0 -11
  224. package/dist/adapters/socket.d.ts.map +0 -1
  225. package/dist/adapters/socket.js +0 -17
  226. package/dist/adapters/socket.js.map +0 -1
  227. package/dist/adapters/transport.d.ts +0 -7
  228. package/dist/adapters/transport.d.ts.map +0 -1
  229. package/dist/adapters/transport.js +0 -36
  230. package/dist/adapters/transport.js.map +0 -1
  231. package/dist/ai/chunk.d.ts +0 -2
  232. package/dist/ai/chunk.d.ts.map +0 -1
  233. package/dist/ai/chunk.js +0 -36
  234. package/dist/ai/chunk.js.map +0 -1
  235. package/dist/ai/llmstxt.d.ts +0 -6
  236. package/dist/ai/llmstxt.d.ts.map +0 -1
  237. package/dist/ai/llmstxt.js +0 -12
  238. package/dist/ai/llmstxt.js.map +0 -1
  239. package/dist/ai/provenance.d.ts +0 -22
  240. package/dist/ai/provenance.d.ts.map +0 -1
  241. package/dist/ai/provenance.js +0 -25
  242. package/dist/ai/provenance.js.map +0 -1
  243. package/dist/ai/rag.d.ts +0 -26
  244. package/dist/ai/rag.d.ts.map +0 -1
  245. package/dist/ai/rag.js +0 -22
  246. package/dist/ai/rag.js.map +0 -1
  247. package/dist/ai/tokens.d.ts +0 -15
  248. package/dist/ai/tokens.d.ts.map +0 -1
  249. package/dist/ai/tokens.js +0 -9
  250. package/dist/ai/tokens.js.map +0 -1
  251. package/dist/api/auth.d.ts +0 -16
  252. package/dist/api/auth.d.ts.map +0 -1
  253. package/dist/api/auth.js +0 -19
  254. package/dist/api/auth.js.map +0 -1
  255. package/dist/api/contracts.d.ts +0 -28
  256. package/dist/api/contracts.d.ts.map +0 -1
  257. package/dist/api/contracts.js +0 -14
  258. package/dist/api/contracts.js.map +0 -1
  259. package/dist/api/control.d.ts +0 -10
  260. package/dist/api/control.d.ts.map +0 -1
  261. package/dist/api/control.js +0 -35
  262. package/dist/api/control.js.map +0 -1
  263. package/dist/api/http.d.ts +0 -7
  264. package/dist/api/http.d.ts.map +0 -1
  265. package/dist/api/http.js +0 -12
  266. package/dist/api/http.js.map +0 -1
  267. package/dist/api/rate.d.ts +0 -28
  268. package/dist/api/rate.d.ts.map +0 -1
  269. package/dist/api/rate.js +0 -36
  270. package/dist/api/rate.js.map +0 -1
  271. package/dist/api/security.d.ts +0 -12
  272. package/dist/api/security.d.ts.map +0 -1
  273. package/dist/api/security.js +0 -56
  274. package/dist/api/security.js.map +0 -1
  275. package/dist/api/service.d.ts +0 -5
  276. package/dist/api/service.d.ts.map +0 -1
  277. package/dist/api/service.js +0 -70
  278. package/dist/api/service.js.map +0 -1
  279. package/dist/apps/registry.d.ts +0 -33
  280. package/dist/apps/registry.d.ts.map +0 -1
  281. package/dist/apps/registry.js +0 -24
  282. package/dist/apps/registry.js.map +0 -1
  283. package/dist/binary/archive.d.ts +0 -27
  284. package/dist/binary/archive.d.ts.map +0 -1
  285. package/dist/binary/archive.js +0 -46
  286. package/dist/binary/archive.js.map +0 -1
  287. package/dist/binary/build.d.ts +0 -29
  288. package/dist/binary/build.d.ts.map +0 -1
  289. package/dist/binary/build.js +0 -17
  290. package/dist/binary/build.js.map +0 -1
  291. package/dist/binary/transform.d.ts +0 -70
  292. package/dist/binary/transform.d.ts.map +0 -1
  293. package/dist/binary/transform.js +0 -105
  294. package/dist/binary/transform.js.map +0 -1
  295. package/dist/bot/adapter.d.ts +0 -5
  296. package/dist/bot/adapter.d.ts.map +0 -1
  297. package/dist/bot/adapter.js +0 -11
  298. package/dist/bot/adapter.js.map +0 -1
  299. package/dist/bot/bot.d.ts +0 -28
  300. package/dist/bot/bot.d.ts.map +0 -1
  301. package/dist/bot/bot.js +0 -52
  302. package/dist/bot/bot.js.map +0 -1
  303. package/dist/bot/commands.d.ts +0 -8
  304. package/dist/bot/commands.d.ts.map +0 -1
  305. package/dist/bot/commands.js +0 -19
  306. package/dist/bot/commands.js.map +0 -1
  307. package/dist/bot/permissions.d.ts +0 -13
  308. package/dist/bot/permissions.d.ts.map +0 -1
  309. package/dist/bot/permissions.js +0 -16
  310. package/dist/bot/permissions.js.map +0 -1
  311. package/dist/browser/actions.d.ts +0 -33
  312. package/dist/browser/actions.d.ts.map +0 -1
  313. package/dist/browser/actions.js +0 -44
  314. package/dist/browser/actions.js.map +0 -1
  315. package/dist/browser/agent.d.ts +0 -21
  316. package/dist/browser/agent.d.ts.map +0 -1
  317. package/dist/browser/agent.js +0 -13
  318. package/dist/browser/agent.js.map +0 -1
  319. package/dist/browser/context.d.ts +0 -43
  320. package/dist/browser/context.d.ts.map +0 -1
  321. package/dist/browser/context.js +0 -54
  322. package/dist/browser/context.js.map +0 -1
  323. package/dist/browser/fingerprint.d.ts +0 -4
  324. package/dist/browser/fingerprint.d.ts.map +0 -1
  325. package/dist/browser/fingerprint.js +0 -12
  326. package/dist/browser/fingerprint.js.map +0 -1
  327. package/dist/browser/index.d.ts +0 -11
  328. package/dist/browser/index.d.ts.map +0 -1
  329. package/dist/browser/index.js +0 -11
  330. package/dist/browser/index.js.map +0 -1
  331. package/dist/browser/playwright.d.ts +0 -11
  332. package/dist/browser/playwright.d.ts.map +0 -1
  333. package/dist/browser/playwright.js +0 -24
  334. package/dist/browser/playwright.js.map +0 -1
  335. package/dist/browser/recorder.d.ts +0 -21
  336. package/dist/browser/recorder.d.ts.map +0 -1
  337. package/dist/browser/recorder.js +0 -58
  338. package/dist/browser/recorder.js.map +0 -1
  339. package/dist/browser/session.d.ts +0 -14
  340. package/dist/browser/session.d.ts.map +0 -1
  341. package/dist/browser/session.js +0 -21
  342. package/dist/browser/session.js.map +0 -1
  343. package/dist/browser/snapshot.d.ts +0 -69
  344. package/dist/browser/snapshot.d.ts.map +0 -1
  345. package/dist/browser/snapshot.js +0 -133
  346. package/dist/browser/snapshot.js.map +0 -1
  347. package/dist/captcha/contract.d.ts +0 -35
  348. package/dist/captcha/contract.d.ts.map +0 -1
  349. package/dist/captcha/contract.js +0 -17
  350. package/dist/captcha/contract.js.map +0 -1
  351. package/dist/captcha/evidence.d.ts +0 -10
  352. package/dist/captcha/evidence.d.ts.map +0 -1
  353. package/dist/captcha/evidence.js +0 -9
  354. package/dist/captcha/evidence.js.map +0 -1
  355. package/dist/captcha/guard.d.ts +0 -23
  356. package/dist/captcha/guard.d.ts.map +0 -1
  357. package/dist/captcha/guard.js +0 -12
  358. package/dist/captcha/guard.js.map +0 -1
  359. package/dist/cli/main.d.ts +0 -4
  360. package/dist/cli/main.d.ts.map +0 -1
  361. package/dist/cli/main.js +0 -46
  362. package/dist/cli/main.js.map +0 -1
  363. package/dist/core/errors.d.ts +0 -84
  364. package/dist/core/errors.d.ts.map +0 -1
  365. package/dist/core/errors.js +0 -54
  366. package/dist/core/errors.js.map +0 -1
  367. package/dist/core/events.d.ts +0 -9
  368. package/dist/core/events.d.ts.map +0 -1
  369. package/dist/core/events.js +0 -21
  370. package/dist/core/events.js.map +0 -1
  371. package/dist/core/hash.d.ts +0 -10
  372. package/dist/core/hash.d.ts.map +0 -1
  373. package/dist/core/hash.js +0 -82
  374. package/dist/core/hash.js.map +0 -1
  375. package/dist/core/ids.d.ts +0 -10
  376. package/dist/core/ids.d.ts.map +0 -1
  377. package/dist/core/ids.js +0 -15
  378. package/dist/core/ids.js.map +0 -1
  379. package/dist/delivery/manifest.d.ts +0 -35
  380. package/dist/delivery/manifest.d.ts.map +0 -1
  381. package/dist/delivery/manifest.js +0 -68
  382. package/dist/delivery/manifest.js.map +0 -1
  383. package/dist/deploy/index.d.ts +0 -6
  384. package/dist/deploy/index.d.ts.map +0 -1
  385. package/dist/deploy/index.js +0 -6
  386. package/dist/deploy/index.js.map +0 -1
  387. package/dist/dispatch/resumable.d.ts +0 -102
  388. package/dist/dispatch/resumable.d.ts.map +0 -1
  389. package/dist/dispatch/resumable.js +0 -64
  390. package/dist/dispatch/resumable.js.map +0 -1
  391. package/dist/dispatch/workflow.d.ts +0 -6
  392. package/dist/dispatch/workflow.d.ts.map +0 -1
  393. package/dist/dispatch/workflow.js +0 -37
  394. package/dist/dispatch/workflow.js.map +0 -1
  395. package/dist/domain/artifacts.d.ts +0 -12
  396. package/dist/domain/artifacts.d.ts.map +0 -1
  397. package/dist/domain/artifacts.js +0 -14
  398. package/dist/domain/artifacts.js.map +0 -1
  399. package/dist/domain/jobs.d.ts +0 -12
  400. package/dist/domain/jobs.d.ts.map +0 -1
  401. package/dist/domain/jobs.js +0 -20
  402. package/dist/domain/jobs.js.map +0 -1
  403. package/dist/domain/providers.d.ts +0 -10
  404. package/dist/domain/providers.d.ts.map +0 -1
  405. package/dist/domain/providers.js +0 -8
  406. package/dist/domain/providers.js.map +0 -1
  407. package/dist/domain/runtime.d.ts +0 -14
  408. package/dist/domain/runtime.d.ts.map +0 -1
  409. package/dist/domain/runtime.js +0 -10
  410. package/dist/domain/runtime.js.map +0 -1
  411. package/dist/domain/sessions.d.ts +0 -12
  412. package/dist/domain/sessions.d.ts.map +0 -1
  413. package/dist/domain/sessions.js +0 -57
  414. package/dist/domain/sessions.js.map +0 -1
  415. package/dist/examples/localjob.d.ts +0 -2
  416. package/dist/examples/localjob.d.ts.map +0 -1
  417. package/dist/examples/localjob.js.map +0 -1
  418. package/dist/examples/publicapi.d.ts +0 -2
  419. package/dist/examples/publicapi.d.ts.map +0 -1
  420. package/dist/examples/publicapi.js.map +0 -1
  421. package/dist/extension/build.d.ts +0 -9
  422. package/dist/extension/build.d.ts.map +0 -1
  423. package/dist/extension/build.js +0 -85
  424. package/dist/extension/build.js.map +0 -1
  425. package/dist/extension/content.d.ts +0 -6
  426. package/dist/extension/content.d.ts.map +0 -1
  427. package/dist/extension/content.js +0 -135
  428. package/dist/extension/content.js.map +0 -1
  429. package/dist/extension/index.d.ts +0 -7
  430. package/dist/extension/index.d.ts.map +0 -1
  431. package/dist/extension/index.js +0 -7
  432. package/dist/extension/index.js.map +0 -1
  433. package/dist/extension/pagebridge.d.ts +0 -6
  434. package/dist/extension/pagebridge.d.ts.map +0 -1
  435. package/dist/extension/pagebridge.js +0 -42
  436. package/dist/extension/pagebridge.js.map +0 -1
  437. package/dist/extension/permissions.d.ts +0 -26
  438. package/dist/extension/permissions.d.ts.map +0 -1
  439. package/dist/extension/permissions.js +0 -28
  440. package/dist/extension/permissions.js.map +0 -1
  441. package/dist/extension/popup.d.ts +0 -5
  442. package/dist/extension/popup.d.ts.map +0 -1
  443. package/dist/extension/popup.js +0 -26
  444. package/dist/extension/popup.js.map +0 -1
  445. package/dist/extension/protocol.d.ts +0 -58
  446. package/dist/extension/protocol.d.ts.map +0 -1
  447. package/dist/extension/protocol.js +0 -101
  448. package/dist/extension/protocol.js.map +0 -1
  449. package/dist/extension/serviceworker.d.ts +0 -25
  450. package/dist/extension/serviceworker.d.ts.map +0 -1
  451. package/dist/extension/serviceworker.js +0 -102
  452. package/dist/extension/serviceworker.js.map +0 -1
  453. package/dist/extension/worker.d.ts +0 -28
  454. package/dist/extension/worker.d.ts.map +0 -1
  455. package/dist/extension/worker.js +0 -22
  456. package/dist/extension/worker.js.map +0 -1
  457. package/dist/format/check.d.ts +0 -8
  458. package/dist/format/check.d.ts.map +0 -1
  459. package/dist/format/check.js +0 -38
  460. package/dist/format/check.js.map +0 -1
  461. package/dist/library/public.d.ts.map +0 -1
  462. package/dist/library/public.js.map +0 -1
  463. package/dist/mcp/browser.d.ts +0 -9
  464. package/dist/mcp/browser.d.ts.map +0 -1
  465. package/dist/mcp/browser.js +0 -13
  466. package/dist/mcp/browser.js.map +0 -1
  467. package/dist/mcp/server.d.ts +0 -35
  468. package/dist/mcp/server.d.ts.map +0 -1
  469. package/dist/mcp/server.js +0 -40
  470. package/dist/mcp/server.js.map +0 -1
  471. package/dist/mcp/transport.d.ts +0 -7
  472. package/dist/mcp/transport.d.ts.map +0 -1
  473. package/dist/mcp/transport.js +0 -17
  474. package/dist/mcp/transport.js.map +0 -1
  475. package/dist/memory/bridge.d.ts +0 -14
  476. package/dist/memory/bridge.d.ts.map +0 -1
  477. package/dist/memory/bridge.js +0 -16
  478. package/dist/memory/bridge.js.map +0 -1
  479. package/dist/memory/engine.d.ts +0 -38
  480. package/dist/memory/engine.d.ts.map +0 -1
  481. package/dist/memory/engine.js +0 -109
  482. package/dist/memory/engine.js.map +0 -1
  483. package/dist/memory/modes.d.ts +0 -43
  484. package/dist/memory/modes.d.ts.map +0 -1
  485. package/dist/memory/modes.js +0 -66
  486. package/dist/memory/modes.js.map +0 -1
  487. package/dist/memory/objects.d.ts +0 -21
  488. package/dist/memory/objects.d.ts.map +0 -1
  489. package/dist/memory/objects.js +0 -20
  490. package/dist/memory/objects.js.map +0 -1
  491. package/dist/memory/planner.d.ts +0 -66
  492. package/dist/memory/planner.d.ts.map +0 -1
  493. package/dist/memory/planner.js +0 -108
  494. package/dist/memory/planner.js.map +0 -1
  495. package/dist/memory/targets.d.ts +0 -78
  496. package/dist/memory/targets.d.ts.map +0 -1
  497. package/dist/memory/targets.js +0 -29
  498. package/dist/memory/targets.js.map +0 -1
  499. package/dist/memory/transforms.d.ts +0 -19
  500. package/dist/memory/transforms.d.ts.map +0 -1
  501. package/dist/memory/transforms.js +0 -14
  502. package/dist/memory/transforms.js.map +0 -1
  503. package/dist/modes/matrix.d.ts +0 -23
  504. package/dist/modes/matrix.d.ts.map +0 -1
  505. package/dist/modes/matrix.js +0 -18
  506. package/dist/modes/matrix.js.map +0 -1
  507. package/dist/modes/modes.d.ts +0 -33
  508. package/dist/modes/modes.d.ts.map +0 -1
  509. package/dist/modes/modes.js +0 -15
  510. package/dist/modes/modes.js.map +0 -1
  511. package/dist/modes/resolve.d.ts +0 -96
  512. package/dist/modes/resolve.d.ts.map +0 -1
  513. package/dist/modes/resolve.js +0 -48
  514. package/dist/modes/resolve.js.map +0 -1
  515. package/dist/observability/metrics.d.ts +0 -14
  516. package/dist/observability/metrics.d.ts.map +0 -1
  517. package/dist/observability/metrics.js +0 -18
  518. package/dist/observability/metrics.js.map +0 -1
  519. package/dist/packager/manifest.d.ts +0 -66
  520. package/dist/packager/manifest.d.ts.map +0 -1
  521. package/dist/packager/manifest.js +0 -94
  522. package/dist/packager/manifest.js.map +0 -1
  523. package/dist/packager/publish.d.ts +0 -51
  524. package/dist/packager/publish.d.ts.map +0 -1
  525. package/dist/packager/publish.js +0 -18
  526. package/dist/packager/publish.js.map +0 -1
  527. package/dist/packager/targetcli.d.ts +0 -7
  528. package/dist/packager/targetcli.d.ts.map +0 -1
  529. package/dist/packager/targetcli.js +0 -22
  530. package/dist/packager/targetcli.js.map +0 -1
  531. package/dist/persistence/adapter.d.ts +0 -5
  532. package/dist/persistence/adapter.d.ts.map +0 -1
  533. package/dist/persistence/adapter.js +0 -11
  534. package/dist/persistence/adapter.js.map +0 -1
  535. package/dist/persistence/drizzle.d.ts +0 -2
  536. package/dist/persistence/drizzle.d.ts.map +0 -1
  537. package/dist/persistence/drizzle.js +0 -12
  538. package/dist/persistence/drizzle.js.map +0 -1
  539. package/dist/persistence/memory.d.ts +0 -2
  540. package/dist/persistence/memory.d.ts.map +0 -1
  541. package/dist/persistence/memory.js +0 -27
  542. package/dist/persistence/memory.js.map +0 -1
  543. package/dist/persistence/migrations.d.ts +0 -19
  544. package/dist/persistence/migrations.d.ts.map +0 -1
  545. package/dist/persistence/migrations.js +0 -13
  546. package/dist/persistence/migrations.js.map +0 -1
  547. package/dist/persistence/prisma.d.ts +0 -2
  548. package/dist/persistence/prisma.d.ts.map +0 -1
  549. package/dist/persistence/prisma.js +0 -25
  550. package/dist/persistence/prisma.js.map +0 -1
  551. package/dist/persistence/schema.d.ts +0 -63
  552. package/dist/persistence/schema.d.ts.map +0 -1
  553. package/dist/persistence/schema.js +0 -28
  554. package/dist/persistence/schema.js.map +0 -1
  555. package/dist/persistence/sql.d.ts +0 -3
  556. package/dist/persistence/sql.d.ts.map +0 -1
  557. package/dist/persistence/sql.js +0 -37
  558. package/dist/persistence/sql.js.map +0 -1
  559. package/dist/protocol/blocks.d.ts +0 -10
  560. package/dist/protocol/blocks.d.ts.map +0 -1
  561. package/dist/protocol/blocks.js +0 -26
  562. package/dist/protocol/blocks.js.map +0 -1
  563. package/dist/protocol/json.d.ts +0 -6
  564. package/dist/protocol/json.d.ts.map +0 -1
  565. package/dist/protocol/json.js +0 -6
  566. package/dist/protocol/json.js.map +0 -1
  567. package/dist/protocol/ndjson.d.ts +0 -3
  568. package/dist/protocol/ndjson.d.ts.map +0 -1
  569. package/dist/protocol/ndjson.js +0 -20
  570. package/dist/protocol/ndjson.js.map +0 -1
  571. package/dist/protocol/sse.d.ts +0 -7
  572. package/dist/protocol/sse.d.ts.map +0 -1
  573. package/dist/protocol/sse.js +0 -25
  574. package/dist/protocol/sse.js.map +0 -1
  575. package/dist/proxy/pool.d.ts +0 -9
  576. package/dist/proxy/pool.d.ts.map +0 -1
  577. package/dist/proxy/pool.js +0 -27
  578. package/dist/proxy/pool.js.map +0 -1
  579. package/dist/queue/idempotency.d.ts +0 -10
  580. package/dist/queue/idempotency.d.ts.map +0 -1
  581. package/dist/queue/idempotency.js +0 -13
  582. package/dist/queue/idempotency.js.map +0 -1
  583. package/dist/queue/persistent.d.ts +0 -14
  584. package/dist/queue/persistent.d.ts.map +0 -1
  585. package/dist/queue/persistent.js +0 -66
  586. package/dist/queue/persistent.js.map +0 -1
  587. package/dist/queue/queue.d.ts +0 -7
  588. package/dist/queue/queue.d.ts.map +0 -1
  589. package/dist/queue/queue.js +0 -55
  590. package/dist/queue/queue.js.map +0 -1
  591. package/dist/queue/saga.d.ts +0 -5
  592. package/dist/queue/saga.d.ts.map +0 -1
  593. package/dist/queue/saga.js +0 -20
  594. package/dist/queue/saga.js.map +0 -1
  595. package/dist/release/assets.d.ts +0 -144
  596. package/dist/release/assets.d.ts.map +0 -1
  597. package/dist/release/assets.js +0 -157
  598. package/dist/release/assets.js.map +0 -1
  599. package/dist/release/evidence.d.ts +0 -92
  600. package/dist/release/evidence.d.ts.map +0 -1
  601. package/dist/release/evidence.js +0 -148
  602. package/dist/release/evidence.js.map +0 -1
  603. package/dist/release/verify.d.ts +0 -12
  604. package/dist/release/verify.d.ts.map +0 -1
  605. package/dist/release/verify.js +0 -112
  606. package/dist/release/verify.js.map +0 -1
  607. package/dist/runners/chain.d.ts +0 -125
  608. package/dist/runners/chain.d.ts.map +0 -1
  609. package/dist/runners/chain.js +0 -95
  610. package/dist/runners/chain.js.map +0 -1
  611. package/dist/runners/health.d.ts +0 -36
  612. package/dist/runners/health.d.ts.map +0 -1
  613. package/dist/runners/health.js +0 -26
  614. package/dist/runners/health.js.map +0 -1
  615. package/dist/runners/heartbeat.d.ts +0 -23
  616. package/dist/runners/heartbeat.d.ts.map +0 -1
  617. package/dist/runners/heartbeat.js +0 -29
  618. package/dist/runners/heartbeat.js.map +0 -1
  619. package/dist/runners/inprocess.d.ts +0 -17
  620. package/dist/runners/inprocess.d.ts.map +0 -1
  621. package/dist/runners/inprocess.js +0 -20
  622. package/dist/runners/inprocess.js.map +0 -1
  623. package/dist/runners/scheduler.d.ts +0 -5
  624. package/dist/runners/scheduler.d.ts.map +0 -1
  625. package/dist/runners/scheduler.js +0 -19
  626. package/dist/runners/scheduler.js.map +0 -1
  627. package/dist/runtime/abort.d.ts +0 -8
  628. package/dist/runtime/abort.d.ts.map +0 -1
  629. package/dist/runtime/abort.js +0 -13
  630. package/dist/runtime/abort.js.map +0 -1
  631. package/dist/runtime/compatibility.d.ts +0 -37
  632. package/dist/runtime/compatibility.d.ts.map +0 -1
  633. package/dist/runtime/compatibility.js +0 -10
  634. package/dist/runtime/compatibility.js.map +0 -1
  635. package/dist/runtime/detect.d.ts +0 -13
  636. package/dist/runtime/detect.d.ts.map +0 -1
  637. package/dist/runtime/detect.js +0 -18
  638. package/dist/runtime/detect.js.map +0 -1
  639. package/dist/runtime/engine.d.ts +0 -20
  640. package/dist/runtime/engine.d.ts.map +0 -1
  641. package/dist/runtime/engine.js +0 -61
  642. package/dist/runtime/engine.js.map +0 -1
  643. package/dist/runtime/retry.d.ts +0 -19
  644. package/dist/runtime/retry.d.ts.map +0 -1
  645. package/dist/runtime/retry.js +0 -54
  646. package/dist/runtime/retry.js.map +0 -1
  647. package/dist/runtime/worker.d.ts +0 -10
  648. package/dist/runtime/worker.d.ts.map +0 -1
  649. package/dist/runtime/worker.js +0 -25
  650. package/dist/runtime/worker.js.map +0 -1
  651. package/dist/scrape/cache.d.ts +0 -45
  652. package/dist/scrape/cache.d.ts.map +0 -1
  653. package/dist/scrape/cache.js +0 -45
  654. package/dist/scrape/cache.js.map +0 -1
  655. package/dist/scrape/crawl.d.ts +0 -47
  656. package/dist/scrape/crawl.d.ts.map +0 -1
  657. package/dist/scrape/crawl.js +0 -114
  658. package/dist/scrape/crawl.js.map +0 -1
  659. package/dist/scrape/extract.d.ts +0 -63
  660. package/dist/scrape/extract.d.ts.map +0 -1
  661. package/dist/scrape/extract.js +0 -47
  662. package/dist/scrape/extract.js.map +0 -1
  663. package/dist/scrape/normalize.d.ts +0 -52
  664. package/dist/scrape/normalize.d.ts.map +0 -1
  665. package/dist/scrape/normalize.js +0 -102
  666. package/dist/scrape/normalize.js.map +0 -1
  667. package/dist/scrape/robots.d.ts +0 -37
  668. package/dist/scrape/robots.d.ts.map +0 -1
  669. package/dist/scrape/robots.js +0 -71
  670. package/dist/scrape/robots.js.map +0 -1
  671. package/dist/scrape/schema.d.ts +0 -23
  672. package/dist/scrape/schema.d.ts.map +0 -1
  673. package/dist/scrape/schema.js +0 -92
  674. package/dist/scrape/schema.js.map +0 -1
  675. package/dist/scrape/scraper.d.ts +0 -6
  676. package/dist/scrape/scraper.d.ts.map +0 -1
  677. package/dist/scrape/scraper.js +0 -46
  678. package/dist/scrape/scraper.js.map +0 -1
  679. package/dist/scrape/semantic.d.ts +0 -25
  680. package/dist/scrape/semantic.d.ts.map +0 -1
  681. package/dist/scrape/semantic.js +0 -27
  682. package/dist/scrape/semantic.js.map +0 -1
  683. package/dist/server/node.d.ts +0 -7
  684. package/dist/server/node.d.ts.map +0 -1
  685. package/dist/server/node.js.map +0 -1
  686. package/dist/sessions/file.d.ts +0 -25
  687. package/dist/sessions/file.d.ts.map +0 -1
  688. package/dist/sessions/file.js +0 -13
  689. package/dist/sessions/file.js.map +0 -1
  690. package/dist/sessions/replay.d.ts +0 -9
  691. package/dist/sessions/replay.d.ts.map +0 -1
  692. package/dist/sessions/replay.js +0 -70
  693. package/dist/sessions/replay.js.map +0 -1
  694. package/dist/sessions/store.d.ts +0 -25
  695. package/dist/sessions/store.d.ts.map +0 -1
  696. package/dist/sessions/store.js +0 -13
  697. package/dist/sessions/store.js.map +0 -1
  698. package/dist/storage/adapter.d.ts +0 -5
  699. package/dist/storage/adapter.d.ts.map +0 -1
  700. package/dist/storage/adapter.js +0 -11
  701. package/dist/storage/adapter.js.map +0 -1
  702. package/dist/storage/cache.d.ts +0 -23
  703. package/dist/storage/cache.d.ts.map +0 -1
  704. package/dist/storage/cache.js +0 -79
  705. package/dist/storage/cache.js.map +0 -1
  706. package/dist/storage/checksum.d.ts +0 -3
  707. package/dist/storage/checksum.d.ts.map +0 -1
  708. package/dist/storage/checksum.js +0 -19
  709. package/dist/storage/checksum.js.map +0 -1
  710. package/dist/storage/chunked.d.ts +0 -21
  711. package/dist/storage/chunked.d.ts.map +0 -1
  712. package/dist/storage/chunked.js +0 -67
  713. package/dist/storage/chunked.js.map +0 -1
  714. package/dist/storage/content.d.ts +0 -24
  715. package/dist/storage/content.d.ts.map +0 -1
  716. package/dist/storage/content.js +0 -44
  717. package/dist/storage/content.js.map +0 -1
  718. package/dist/storage/filehosting.d.ts +0 -2
  719. package/dist/storage/filehosting.d.ts.map +0 -1
  720. package/dist/storage/filehosting.js +0 -24
  721. package/dist/storage/filehosting.js.map +0 -1
  722. package/dist/storage/githubcontents.d.ts +0 -2
  723. package/dist/storage/githubcontents.d.ts.map +0 -1
  724. package/dist/storage/githubcontents.js +0 -29
  725. package/dist/storage/githubcontents.js.map +0 -1
  726. package/dist/storage/index.d.ts +0 -12
  727. package/dist/storage/index.d.ts.map +0 -1
  728. package/dist/storage/index.js +0 -12
  729. package/dist/storage/index.js.map +0 -1
  730. package/dist/storage/local.d.ts +0 -2
  731. package/dist/storage/local.d.ts.map +0 -1
  732. package/dist/storage/local.js +0 -72
  733. package/dist/storage/local.js.map +0 -1
  734. package/dist/storage/memory.d.ts +0 -6
  735. package/dist/storage/memory.d.ts.map +0 -1
  736. package/dist/storage/memory.js +0 -36
  737. package/dist/storage/memory.js.map +0 -1
  738. package/dist/storage/pool.d.ts +0 -95
  739. package/dist/storage/pool.d.ts.map +0 -1
  740. package/dist/storage/pool.js +0 -202
  741. package/dist/storage/pool.js.map +0 -1
  742. package/dist/storage/s3compatible.d.ts +0 -3
  743. package/dist/storage/s3compatible.d.ts.map +0 -1
  744. package/dist/storage/s3compatible.js +0 -70
  745. package/dist/storage/s3compatible.js.map +0 -1
  746. package/dist/storage/sync.d.ts +0 -47
  747. package/dist/storage/sync.d.ts.map +0 -1
  748. package/dist/storage/sync.js +0 -75
  749. package/dist/storage/sync.js.map +0 -1
  750. package/dist/surfaces/adapters.d.ts +0 -97
  751. package/dist/surfaces/adapters.d.ts.map +0 -1
  752. package/dist/surfaces/adapters.js +0 -50
  753. package/dist/surfaces/adapters.js.map +0 -1
  754. package/dist/surfaces/controls.d.ts +0 -18
  755. package/dist/surfaces/controls.d.ts.map +0 -1
  756. package/dist/surfaces/controls.js +0 -45
  757. package/dist/surfaces/controls.js.map +0 -1
  758. package/dist/surfaces/manifest.d.ts +0 -68
  759. package/dist/surfaces/manifest.d.ts.map +0 -1
  760. package/dist/surfaces/manifest.js +0 -42
  761. package/dist/surfaces/manifest.js.map +0 -1
  762. package/dist/surfaces/n8n.d.ts +0 -25
  763. package/dist/surfaces/n8n.d.ts.map +0 -1
  764. package/dist/surfaces/n8n.js +0 -31
  765. package/dist/surfaces/n8n.js.map +0 -1
  766. package/dist/surfaces/operations.d.ts +0 -32
  767. package/dist/surfaces/operations.d.ts.map +0 -1
  768. package/dist/surfaces/operations.js +0 -53
  769. package/dist/surfaces/operations.js.map +0 -1
  770. package/dist/surfaces/requirements.d.ts +0 -29
  771. package/dist/surfaces/requirements.d.ts.map +0 -1
  772. package/dist/surfaces/requirements.js +0 -50
  773. package/dist/surfaces/requirements.js.map +0 -1
  774. package/dist/surfaces/targets.d.ts +0 -196
  775. package/dist/surfaces/targets.d.ts.map +0 -1
  776. package/dist/surfaces/targets.js +0 -27
  777. package/dist/surfaces/targets.js.map +0 -1
  778. package/dist/webhook/delivery.d.ts +0 -18
  779. package/dist/webhook/delivery.d.ts.map +0 -1
  780. package/dist/webhook/delivery.js +0 -36
  781. package/dist/webhook/delivery.js.map +0 -1
  782. package/dist/webhook/receiver.d.ts +0 -26
  783. package/dist/webhook/receiver.d.ts.map +0 -1
  784. package/dist/webhook/receiver.js +0 -24
  785. package/dist/webhook/receiver.js.map +0 -1
  786. package/dist/webhook/signature.d.ts +0 -3
  787. package/dist/webhook/signature.d.ts.map +0 -1
  788. package/dist/webhook/signature.js +0 -7
  789. package/dist/webhook/signature.js.map +0 -1
  790. package/dist/workflow/manifest.d.ts +0 -22
  791. package/dist/workflow/manifest.d.ts.map +0 -1
  792. package/dist/workflow/manifest.js +0 -21
  793. package/dist/workflow/manifest.js.map +0 -1
  794. package/dist/workflow/registry.d.ts +0 -7
  795. package/dist/workflow/registry.d.ts.map +0 -1
  796. package/dist/workflow/registry.js +0 -18
  797. package/dist/workflow/registry.js.map +0 -1
  798. package/dist/workflow/templates.d.ts +0 -6
  799. package/dist/workflow/templates.d.ts.map +0 -1
  800. package/dist/workflow/templates.js +0 -18
  801. package/dist/workflow/templates.js.map +0 -1
  802. package/dist/workflow/triggers.d.ts +0 -64
  803. package/dist/workflow/triggers.d.ts.map +0 -1
  804. package/dist/workflow/triggers.js +0 -99
  805. package/dist/workflow/triggers.js.map +0 -1
  806. package/docs/logs/.gitkeep +0 -0
  807. package/docs/plans/00.index.md +0 -50
  808. package/docs/plans/01.architecture.md +0 -86
  809. package/docs/plans/02.research.computer.use.md +0 -58
  810. package/docs/plans/03.research.captcha.bypass.md +0 -68
  811. package/docs/plans/04.research.sandbox.ai.md +0 -52
  812. package/docs/plans/05.capture.platform.md +0 -57
  813. package/docs/plans/06.dependencies.md +0 -97
  814. package/docs/plans/07.captcha.test.page.md +0 -41
  815. package/docs/plans/08.production.infra.md +0 -70
  816. package/docs/plans/09.database.schema.md +0 -121
  817. package/docs/plans/10.cloudinary.storage.md +0 -57
  818. package/docs/plans/11.movement.logs.json.md +0 -72
  819. package/docs/plans/12.research.atlas.agent.browser.md +0 -79
  820. package/docs/plans/13.research.anti.detection.md +0 -898
  821. package/docs/plans/14.research.proxy.md +0 -1495
  822. package/docs/plans/15.research.retry.rate.limit.md +0 -1958
  823. package/docs/plans/16.research.crawling.md +0 -1417
  824. package/docs/plans/17.research.caching.md +0 -1610
  825. package/docs/plans/18.research.content.extraction.md +0 -1952
  826. package/docs/plans/19.research.errors.events.md +0 -1523
  827. package/docs/plans/20.research.zod.validation.md +0 -1350
  828. package/docs/plans/21.research.batch.concurrency.md +0 -1888
  829. package/docs/plans/22.research.universal.runtime.md +0 -944
  830. package/docs/plans/23.research.ai.integration.md +0 -1465
  831. package/docs/plans/24.research.memory.persistence.md +0 -1979
  832. package/docs/plans/25.research.server.api.md +0 -342
  833. package/docs/plans/26.research.compilation.md +0 -249
  834. package/docs/plans/27.research.html.parsing.md +0 -251
  835. package/docs/plans/28.action.plan.md +0 -50
  836. package/docs/plans/29.api.reference.md +0 -174
  837. package/docs/plans/30.architecture.plan.md +0 -94
  838. package/docs/plans/31.auditoria.dados.md +0 -163
  839. package/docs/plans/32.bots.automacao.computacional.md +0 -214
  840. package/docs/plans/33.bots.codigo.revisao.md +0 -220
  841. package/docs/plans/34.bots.seguranca.cicd.md +0 -366
  842. package/docs/plans/35.comparativo.concorrencia.md +0 -464
  843. package/docs/plans/36.computational.memory.md +0 -340
  844. package/docs/plans/37.deploystrategy.md +0 -394
  845. package/docs/plans/38.flow.md +0 -155
  846. package/docs/plans/39.multi.platform.bot.md +0 -252
  847. package/docs/plans/40.npm.publish.md +0 -250
  848. package/docs/plans/41.o.que.falta.md +0 -407
  849. package/docs/plans/42.pesquisa.concorrencia.md +0 -721
  850. package/docs/plans/43.plan.universal.architecture.md +0 -496
  851. package/docs/plans/44.reference.md +0 -100
  852. package/docs/plans/45.robotarchitecture.md +0 -237
  853. package/docs/plans/46.scdnintegration.md +0 -284
  854. package/docs/plans/47.multiforge.readme.md +0 -129
  855. package/docs/plans/48.theory.v4.repo.os.md +0 -152
  856. package/docs/plans/49.third.party.infra.md +0 -12
  857. package/docs/plans/50.file.as.compute.md +0 -39
  858. package/docs/plans/51.architecture.virtual.processor.md +0 -80
  859. package/docs/plans/52.manifesto.v8.md +0 -11
  860. package/docs/plans/58.cdn.list.md +0 -23
  861. package/docs/plans/59.sql.frameworks.md +0 -33
  862. package/docs/plans/60.sql.thirdparty.md +0 -26
  863. package/docs/plans/61.objective.multiforge.md +0 -63
  864. package/docs/plans/62.huggingface.upload.md +0 -26
  865. package/docs/plans/63.kaggle.upload.md +0 -24
  866. package/docs/plans/64.npm.storage.md +0 -30
  867. package/docs/plans/65.rclone.terabox.md +0 -32
  868. package/docs/plans/66.buckets.and.models.todo.md +0 -14
  869. package/docs/plans/67.database.todo.md +0 -13
  870. package/docs/plans/68.deploy.packages.todo.md +0 -12
  871. package/docs/plans/69.report.human.operator.md +0 -133
  872. package/docs/plans/70.report.brain2qwerty.ems.md +0 -135
  873. package/docs/plans/71.report.hd.infinito.vram.md +0 -155
  874. package/docs/plans/72.plan.hd.infinito.node.md +0 -146
  875. package/docs/plans/73.plan.scifi.repos.md +0 -125
  876. package/docs/plans/74.000.manifesto.v8.flat.2..md +0 -11
  877. package/docs/plans/README.md +0 -489
  878. package/docs/plans/aggregate_platforms.mjs +0 -146
  879. package/docs/plans/examplesession.json +0 -36
  880. package/docs/plans/missing-facts.md +0 -192
  881. package/docs/plans/models.md +0 -64
  882. package/docs/plans/organize.cjs +0 -270
  883. package/docs/plans/platforms.md +0 -2887
  884. package/docs/plans/sites.md +0 -31322
  885. package/docs/sources/farm.py +0 -117
  886. package/docs/sources/html/saddle1.html +0 -132
  887. package/docs/sources/html/saddle2.html +0 -157
  888. package/docs/sources/html/saddle3.html +0 -119
  889. package/docs/sources/html/saddle4.html +0 -144
  890. package/docs/sources/html/saddle5.html +0 -72
  891. package/docs/sources/html/saddle6.html +0 -171
  892. package/docs/sources/html/saddle7.html +0 -236
  893. package/docs/sources/saddle.ts +0 -74
  894. package/docs/sources/schema.prisma +0 -88
  895. package/docs/sources/script.sh +0 -64
  896. package/docs/sources/workflows.yml +0 -458
  897. package/docs/talks1/_body.txt +0 -14
  898. package/docs/talks1/_index.md +0 -15
  899. package/docs/talks1/_screenshot.png +0 -0
  900. package/docs/talks1/assistant-01.md +0 -5
  901. package/docs/talks1/assistant-02.md +0 -5
  902. package/docs/talks1/assistant-03.md +0 -531
  903. package/docs/talks1/assistant-04.md +0 -26
  904. package/docs/talks1/assistant-05.md +0 -774
  905. package/docs/talks1/assistant-06.md +0 -1718
  906. package/docs/talks1/scrape-share.cjs +0 -185
  907. package/docs/talks1/scrape-share.ts +0 -183
  908. package/docs/talks1/user-01.md +0 -3
  909. package/docs/talks1/user-02.md +0 -3
  910. package/docs/talks1/user-03.md +0 -88
  911. package/docs/talks1/user-04.md +0 -3
  912. package/docs/talks1/user-05.md +0 -3
  913. package/docs/talks1/user-06.md +0 -88
  914. package/docs/talks1/user-07.md +0 -88
  915. package/docs/talks2/_body.txt +0 -14
  916. package/docs/talks2/_index.md +0 -16
  917. package/docs/talks2/_screenshot.png +0 -0
  918. package/docs/talks2/assistant-01.md +0 -5
  919. package/docs/talks2/assistant-02.md +0 -5
  920. package/docs/talks2/assistant-03.md +0 -424
  921. package/docs/talks2/assistant-04.md +0 -598
  922. package/docs/talks2/assistant-05.md +0 -1280
  923. package/docs/talks2/assistant-06.md +0 -1227
  924. package/docs/talks2/assistant-07.md +0 -1252
  925. package/docs/talks2/user-01.md +0 -3
  926. package/docs/talks2/user-02.md +0 -3
  927. package/docs/talks2/user-03.md +0 -88
  928. package/docs/talks2/user-04.md +0 -88
  929. package/docs/talks2/user-05.md +0 -88
  930. package/docs/talks2/user-06.md +0 -88
  931. package/docs/talks2/user-07.md +0 -3
  932. package/docs/talks3/_body.txt +0 -467
  933. package/docs/talks3/_index.md +0 -10
  934. package/docs/talks3/_screenshot.png +0 -0
  935. package/docs/talks3/assistant-01.md +0 -417
  936. package/docs/talks3/assistant-02.md +0 -417
  937. package/docs/talks3/assistant-03.md +0 -29
  938. package/docs/talks3/assistant-04.md +0 -727
  939. package/docs/talks3/user-01.md +0 -88
  940. package/docs/talks3/user-02.md +0 -88
  941. package/docs/talks3/user-03.md +0 -3
  942. package/docs/talks3/user-04.md +0 -3
  943. package/docs/talks4/_body.txt +0 -14
  944. package/docs/talks4/_index.md +0 -12
  945. package/docs/talks4/_screenshot.png +0 -0
  946. package/docs/talks4/assistant-01.md +0 -5
  947. package/docs/talks4/assistant-02.md +0 -5
  948. package/docs/talks4/assistant-03.md +0 -35
  949. package/docs/talks4/assistant-04.md +0 -512
  950. package/docs/talks4/assistant-05.md +0 -599
  951. package/docs/talks4/user-01.md +0 -3
  952. package/docs/talks4/user-02.md +0 -3
  953. package/docs/talks4/user-03.md +0 -88
  954. package/docs/talks4/user-04.md +0 -88
  955. package/docs/talks4/user-05.md +0 -7
  956. package/docs/talks5/_body.txt +0 -14
  957. package/docs/talks5/_index.md +0 -13
  958. package/docs/talks5/_screenshot.png +0 -0
  959. package/docs/talks5/assistant-01.md +0 -5
  960. package/docs/talks5/assistant-02.md +0 -5
  961. package/docs/talks5/assistant-03.md +0 -690
  962. package/docs/talks5/assistant-04.md +0 -758
  963. package/docs/talks5/assistant-05.md +0 -974
  964. package/docs/talks5/user-01.md +0 -3
  965. package/docs/talks5/user-02.md +0 -3
  966. package/docs/talks5/user-03.md +0 -105
  967. package/docs/talks5/user-04.md +0 -105
  968. package/docs/talks5/user-05.md +0 -63
  969. package/docs/talks5/user-06.md +0 -105
  970. package/docs/talks6/_body.txt +0 -14
  971. package/docs/talks6/_index.md +0 -9
  972. package/docs/talks6/_screenshot.png +0 -0
  973. package/docs/talks6/assistant-01.md +0 -5
  974. package/docs/talks6/assistant-02.md +0 -5
  975. package/docs/talks6/assistant-03.md +0 -1499
  976. package/docs/talks6/user-01.md +0 -3
  977. package/docs/talks6/user-02.md +0 -3
  978. package/docs/talks6/user-03.md +0 -88
  979. package/docs/talks6/user-04.md +0 -88
  980. package/docs/talks7/_body.txt +0 -14
  981. package/docs/talks7/_index.md +0 -10
  982. package/docs/talks7/_screenshot.png +0 -0
  983. package/docs/talks7/assistant-01.md +0 -5
  984. package/docs/talks7/assistant-02.md +0 -5
  985. package/docs/talks7/assistant-03.md +0 -523
  986. package/docs/talks7/assistant-04.md +0 -617
  987. package/docs/talks7/user-01.md +0 -3
  988. package/docs/talks7/user-02.md +0 -3
  989. package/docs/talks7/user-03.md +0 -105
  990. package/docs/talks7/user-04.md +0 -67
  991. package/docs/talks8/conversa1.txt +0 -1322
  992. package/docs/talks8/conversa2.txt +0 -237
  993. package/docs/talks9/Beyond the Obvious_ 50 Plataformas Auto-Hospedadas de Forja de C/303/263digo para Al/303/251m de Gitea e GitLab.md" +0 -174
  994. package/docs/talks9/De NPM a Multi-Linguagem_ Uma Arquitetura T/303/251cnica para a Execu/303/247/303/243o Integrada de C/303/263digo no Ecossistema Node.js.md" +0 -59
  995. package/docs/talks9/De NPM a VMs Virtuais_ Uma An/303/241lise Arquitet/303/264nica para a Realiza/303/247/303/243o do Ciclo de Vida do Projeto SADDLE.md" +0 -91
  996. package/docs/talks9/Mapeamento da Engrenagem Computacional_ Uma Arquitetura para Execu/303/247/303/243o Isolada e Persist/303/252ncia em Ambientes Distribu/303/255dos.md" +0 -116
  997. package/docs/talks9/O Cen/303/241rio Pr/303/241tico do SADDLE_ Uma An/303/241lise de Viabilidade e Modelo de Ciclo de Vida Integrado.md" +0 -128
  998. package/docs/talks9/README (2).md +0 -489
  999. package/docs/talks9/README.md +0 -198
  1000. package/docs/talks9/Viabilidade do Saddle_ Uma An/303/241lise T/303/251cnica da Transforma/303/247/303/243o de Armazenamento Remoto em Mem/303/263ria Computacional.md" +0 -80
  1001. package/docs/talks9/conversa.txt +0 -544
  1002. package/docs/talks9/other (2).md +0 -39
  1003. package/docs/talks9/other.md +0 -57
  1004. package/docs/talks9/outro.txt +0 -24
  1005. /package/{extension/README.md → docs/extension.md} +0 -0
@@ -0,0 +1,2273 @@
1
+ /**
2
+ * compute.ts — compute, WebAssembly, WebGPU and AI workload domain for saddle v6.
3
+ *
4
+ * the module absorbs the compute-facing families of the removed
5
+ * future.ts file (55-feature ledger, v2) into their proper domain:
6
+ * - wasm/wasmtime (8): WIT bindings generator, WASI 0.3.0 async runtime
7
+ * with cancellation, fuel metering, epoch interruption, wasi:nn
8
+ * backend with real softmax, deny-by-default component ACL,
9
+ * component registry, linear memory pool
10
+ * - webgpu (4): forced fallback adapter over lavapipe, compute pipeline
11
+ * builder with the 256-invocation limit, WGSL shader cache, matmul
12
+ * dispatch planner
13
+ * - node 26 (7): Temporal-aware scheduler, Float16 tensor storage with
14
+ * own binary16 conversion, Error.isError guard, node:sqlite sync
15
+ * store with memory fallback, disposable module.register hook chain,
16
+ * Perfetto trace sink, private key store with loader indirection
17
+ * - ai workloads (6): DataLoader /dev/shm planner, TF CUDA
18
+ * forward-compatibility matrix, ONNX WebGPU EP session builder, LLM
19
+ * inference on lavapipe, headless Stable Diffusion, VRAM budget
20
+ *
21
+ * omnihypercore verified additions (research pass 2026-08-23):
22
+ * - wasm canary validator: module validation with smoke execution and
23
+ * automatic rollback to the last healthy revision
24
+ * - WASI-GFX: the wasi:gfx proposal bringing wgpu 30.x WebGPU into wasm
25
+ * components ("wgpu virt wgpu 30"), planned as capability grants
26
+ * - ChatOps dashboard: chat command builders (/vm create, /gpu attach,
27
+ * /migrate) emitting JSON command envelopes plus a WebGPU dashboard
28
+ * spec
29
+ * - GPU telemetry via eBPF: bpf program builder for GPU UAPI counters
30
+ * (DRM_IOCTL tracepoints feeding per-engine utilization maps)
31
+ * - AI live migration pre-copy predictor: dirty page estimation with
32
+ * simple online learning, the AI-flavoured companion of the
33
+ * checkpoint family that now lives in virtualization.ts
34
+ *
35
+ * v4-FIX3 additions (portal 0-reference absorption, 2026-08-23):
36
+ * - PartyKit edge presence channel builder (rooms, wss endpoints,
37
+ * join/leave/update presence, 100 ms heartbeat)
38
+ * - L3AF 2.1 xBPF marketplace app manager emitting l3afd configs
39
+ * - GreenHyper RAPL power-aware binpacking governor over
40
+ * /sys/class/powercap intel-rapl constraint files
41
+ * - StateVector 2-round sync: lamport state vectors with
42
+ * last-writer-wins merge (CRDT convergence without a coordinator)
43
+ * - libp2p + BitTorrent v2 content addressing: sha2-256 multihashes,
44
+ * base32 CIDv1 raw, 16 KiB merkle roots, magnet links, multiaddrs
45
+ * - Tailscale tailnet endpoint planner with the CGNAT 100.64.0.0/10
46
+ * guard, MagicDNS names, DERP fallback and six mesh milestones
47
+ * - MAX9 catalogued as a legacy build/delivery variant (zip level 9,
48
+ * 51% ratio, :max9 tag) - NOT an NVIDIA Maxwell GPU
49
+ * - roadmapbacklog: the thirteen v4 future.ts items that were still
50
+ * unabsorbed (AMX, dual-X3D, WebTransport, Turborepo GHCR, pnpm v9,
51
+ * QUIC/H3, WebRTC mesh, OPFS, WebCodecs+WebGPU, SAB cross-origin,
52
+ * WASM JSPI, GHCR gha reuse, Nix flakes) plus backlogCount()
53
+ *
54
+ * version anchors (worklog v3-VERIFY, 2026-08-23): wasmtime 48.0.0 LTS
55
+ * (confirmed, supported until 2028-08), spin 3.6.0 (spinframework),
56
+ * wasmcloud tracked as latest 2.x without a pin (release page did not
57
+ * expose the version), wgpu 30.x (corrected from 24.x), kernel stable
58
+ * 7.1.9 / longterm 6.18.45. ports never hardcoded; loopback never used.
59
+ *
60
+ * contexts (25+9): witbindings, wasi03async, fuel, epoch, wasinn,
61
+ * componentacl, componentregistry, wasmmempool, lavapipe, pipelines,
62
+ * shadercache, temporal, float16, errorguard, sqlitestore, modulehooks,
63
+ * perfetto, keystore, aiplanners, inference, canary, wasigfx, chatops,
64
+ * ebpfgpu, aimigration, portalsync, l3afmanager, greenhyper,
65
+ * statevector, p2pcontent, tailscaleplan, max9variant, roadmapbacklog
66
+ * (the featureledger appendix closes the file)
67
+ *
68
+ * rules: lowercase identifiers, english jsdoc third person, no emoji,
69
+ * try/catch catcher on every fallible path, node:* built-ins first,
70
+ * zero runtime dependencies, `using`/`satisfies`/`#private`/const type
71
+ * parameters throughout.
72
+ */
73
+ import { createHash, createHmac, randomUUID } from 'node:crypto';
74
+ /** stable short sha256 digest for shader cache keys and canary hashes. */
75
+ function digest(input) {
76
+ try {
77
+ return createHash('sha256').update(input).digest('hex').slice(0, 16);
78
+ }
79
+ catch {
80
+ return input.toString().length.toString(16);
81
+ }
82
+ }
83
+ /** maps a WIT type to its typescript carrier. */
84
+ function wittypetots(type) {
85
+ if (type === 'bool')
86
+ return 'boolean';
87
+ if (type === 'string' || type === 'timestamp')
88
+ return 'string';
89
+ if (type.startsWith('list<'))
90
+ return `${wittypetots(type.slice(5, -1))}[]`;
91
+ if (type.startsWith('option<'))
92
+ return `${wittypetots(type.slice(8, -1))} | undefined`;
93
+ if (type.startsWith('result<')) {
94
+ const [ok, err] = type.slice(7, -1).split(', ');
95
+ return `{ ok: ${wittypetots(ok)} } | { err: ${wittypetots(err)} }`;
96
+ }
97
+ return 'number';
98
+ }
99
+ /**
100
+ * converts a WIT world definition into a typed typescript interface
101
+ * block, so components loaded by the engine keep static typing end to
102
+ * end; guest calls return promises per the WASI 0.3 async convention.
103
+ */
104
+ export function wittotypescript(world) {
105
+ const lines = [
106
+ `/** generated from WIT world "${world.name}" */`,
107
+ `export interface ${world.name}World {`,
108
+ ];
109
+ for (const iface of world.interfaces) {
110
+ lines.push(` ${iface.name}: {`);
111
+ for (const fn of iface.functions) {
112
+ const params = fn.params.map((p) => `${p.name}: ${wittypetots(p.type)}`).join('; ');
113
+ const ret = fn.result === null ? 'void' : `Promise<${wittypetots(fn.result)}>`;
114
+ lines.push(` ${fn.name}(${params}): ${ret};`);
115
+ }
116
+ lines.push(' };');
117
+ }
118
+ lines.push('}');
119
+ return lines.join('\n');
120
+ }
121
+ /** content hash of a WIT world, used to invalidate generated bindings. */
122
+ export function witworldhash(world) {
123
+ return digest(JSON.stringify(world));
124
+ }
125
+ /**
126
+ * models the native async calls of WASI 0.3.0: every guest call is
127
+ * queued, runs under an epoch deadline, and can be cancelled with the
128
+ * cancelled-by-host semantics of the component model.
129
+ */
130
+ export class wasiasyncruntime {
131
+ #queue = [];
132
+ #cancelled = new Set();
133
+ invoke(call) {
134
+ const id = randomUUID();
135
+ return { id, promise: this.#run(call, id) };
136
+ }
137
+ async #run(call, id) {
138
+ this.#queue.push(call);
139
+ const startedAt = Date.now();
140
+ await new Promise((resolve) => setImmediate(resolve));
141
+ if (this.#cancelled.has(id)) {
142
+ this.#cancelled.delete(id);
143
+ throw new Error(`wasi call ${call.component}.${call.functionName} was cancelled by host`);
144
+ }
145
+ if (Date.now() - startedAt > call.deadlineMs) {
146
+ throw new Error(`wasi call ${call.functionName} exceeded deadline of ${call.deadlineMs}ms`);
147
+ }
148
+ this.#queue = this.#queue.filter((c) => c !== call);
149
+ return call.payload;
150
+ }
151
+ cancel(callId) {
152
+ this.#cancelled.add(callId);
153
+ return true;
154
+ }
155
+ get queued() {
156
+ return this.#queue.length;
157
+ }
158
+ [Symbol.dispose]() {
159
+ this.#cancelled.clear();
160
+ this.#queue = [];
161
+ }
162
+ }
163
+ /* ------------------------------------------------------------------ */
164
+ /* context: fuel (deterministic instruction budget) */
165
+ /* ------------------------------------------------------------------ */
166
+ /**
167
+ * wraps deterministic instruction budgets exactly like `wasmtime --fuel`:
168
+ * fuel is consumed per instruction batch, refunded on early exit, and
169
+ * exhausts with a trap.
170
+ */
171
+ export class fuelmeter {
172
+ #consumed = 0;
173
+ budget;
174
+ constructor(budget) {
175
+ this.budget = budget;
176
+ }
177
+ consume(instructions) {
178
+ if (this.#consumed + instructions > this.budget)
179
+ return false;
180
+ this.#consumed += instructions;
181
+ return true;
182
+ }
183
+ refund(instructions) {
184
+ this.#consumed = Math.max(0, this.#consumed - instructions);
185
+ }
186
+ get consumed() {
187
+ return this.#consumed;
188
+ }
189
+ get remaining() {
190
+ return this.budget - this.#consumed;
191
+ }
192
+ get exhausted() {
193
+ return this.remaining <= 0;
194
+ }
195
+ }
196
+ /** runs a callback under a fuel budget; throws a trap when it is hit. */
197
+ export function withfuel(budget, fn) {
198
+ const meter = new fuelmeter(budget);
199
+ const result = fn(meter);
200
+ if (meter.exhausted) {
201
+ throw new Error(`fuel budget of ${budget} instructions exhausted`);
202
+ }
203
+ return result;
204
+ }
205
+ /* ------------------------------------------------------------------ */
206
+ /* context: epoch (wall-clock deadline interruption) */
207
+ /* ------------------------------------------------------------------ */
208
+ /**
209
+ * epoch interruption, preferred over fuel for wall-clock timeouts
210
+ * because it costs roughly 10 percent overhead instead of
211
+ * per-instruction accounting; the deadline is stored in epoch ticks
212
+ * and checked at epoch callback points.
213
+ */
214
+ export class epochinterruption {
215
+ #deadlineTick = Number.POSITIVE_INFINITY;
216
+ #currentTick = 0;
217
+ #tickMs;
218
+ constructor(tickMs = 10) {
219
+ this.#tickMs = tickMs;
220
+ }
221
+ setdeadline(timeoutMs) {
222
+ this.#deadlineTick = this.#currentTick + Math.ceil(timeoutMs / this.#tickMs);
223
+ }
224
+ tick() {
225
+ this.#currentTick += 1;
226
+ }
227
+ get expired() {
228
+ return this.#currentTick >= this.#deadlineTick;
229
+ }
230
+ /** measured overhead of epoch interruption relative to fuel metering. */
231
+ static get relativeoverhead() {
232
+ return 0.1;
233
+ }
234
+ }
235
+ /**
236
+ * a wasi:nn backend: graphs declare tensor shapes and execution runs a
237
+ * real numerically stable softmax over the input tensor, enough to
238
+ * smoke-test serving pipelines before a real backend (onnx runtime,
239
+ * burns or candle) attaches.
240
+ */
241
+ export class wasinnbackend {
242
+ #graphs = new Map();
243
+ load(name, dims, tensorType = 'f32') {
244
+ const graph = { name, dims, tensorType };
245
+ this.#graphs.set(name, graph);
246
+ return graph;
247
+ }
248
+ execute(graphName, tensor) {
249
+ const graph = this.#graphs.get(graphName);
250
+ if (graph === undefined) {
251
+ throw new Error(`wasi:nn graph "${graphName}" is not loaded`);
252
+ }
253
+ const expected = graph.dims.reduce((a, b) => a * b, 1);
254
+ if (tensor.length !== expected) {
255
+ throw new Error(`tensor length ${tensor.length} does not match graph shape ${graph.dims.join('x')}`);
256
+ }
257
+ const max = Math.max(...tensor);
258
+ const exps = tensor.map((v) => Math.exp(v - max));
259
+ const sum = exps.reduce((a, b) => a + b, 0);
260
+ return new Float32Array(exps.map((v) => v / sum));
261
+ }
262
+ list() {
263
+ return [...this.#graphs.keys()];
264
+ }
265
+ }
266
+ /**
267
+ * components start with zero ambient authority: every capability must
268
+ * be granted explicitly before a component may use it, the mirror of
269
+ * the wasmtime deny-by-default model.
270
+ */
271
+ export class componentacl {
272
+ #grants = new Map();
273
+ grant(component, capability) {
274
+ const set = this.#grants.get(component) ?? new Set();
275
+ set.add(capability);
276
+ this.#grants.set(component, set);
277
+ return this;
278
+ }
279
+ assert(component, capability) {
280
+ const set = this.#grants.get(component);
281
+ if (set === undefined || !set.has(capability)) {
282
+ throw new Error(`component "${component}" was not granted "${capability}" (deny-by-default)`);
283
+ }
284
+ }
285
+ grantsfor(component) {
286
+ return [...(this.#grants.get(component) ?? [])];
287
+ }
288
+ }
289
+ /**
290
+ * keeps named component instances together with their fuel meter,
291
+ * epoch interrupter and revision tag, and disposes them
292
+ * deterministically via `using`.
293
+ */
294
+ export class componentregistry {
295
+ #components = new Map();
296
+ instantiate(name, fuelBudget = 1_000_000) {
297
+ const existing = this.#components.get(name);
298
+ if (existing !== undefined)
299
+ return existing;
300
+ const instance = {
301
+ id: randomUUID(),
302
+ name,
303
+ fuel: new fuelmeter(fuelBudget),
304
+ epoch: new epochinterruption(),
305
+ };
306
+ this.#components.set(name, instance);
307
+ return instance;
308
+ }
309
+ get(name) {
310
+ return this.#components.get(name);
311
+ }
312
+ [Symbol.dispose]() {
313
+ this.#components.clear();
314
+ }
315
+ }
316
+ /**
317
+ * recycles 64 KiB-paged ArrayBuffers across component activations so
318
+ * short-lived guests stop pressuring the GC; tickets return to the
319
+ * pool through `using` declarations.
320
+ */
321
+ export class wasmmempool {
322
+ #pool = [];
323
+ acquire(minPages) {
324
+ const wantedBytes = Math.max(1, minPages) * 65_536;
325
+ let slot = this.#pool.find((s) => !s.inUse && s.bytes.byteLength >= wantedBytes);
326
+ if (slot === undefined) {
327
+ slot = { bytes: new ArrayBuffer(wantedBytes), inUse: false, pages: minPages };
328
+ this.#pool.push(slot);
329
+ }
330
+ slot.inUse = true;
331
+ const captured = slot;
332
+ return {
333
+ bytes: captured.bytes,
334
+ [Symbol.dispose]: () => {
335
+ captured.inUse = false;
336
+ },
337
+ };
338
+ }
339
+ get pooled() {
340
+ return this.#pool.length;
341
+ }
342
+ resetall() {
343
+ for (const slot of this.#pool)
344
+ slot.inUse = false;
345
+ }
346
+ [Symbol.dispose]() {
347
+ this.#pool = [];
348
+ }
349
+ }
350
+ /**
351
+ * requests an adapter with forceFallbackAdapter (wgpu 30.x semantics),
352
+ * which lands on lavapipe in a pure-software host; the environment
353
+ * uses VK_DRIVER_FILES, the loader knob that replaced the deprecated
354
+ * VK_ICD_FILENAMES in the 2026 loaders.
355
+ */
356
+ export function forcefallbackadapterplan(icdPath = '/usr/share/vulkan/icd.d/lvp_icd.x86_64.json') {
357
+ return {
358
+ adapterOptions: { forceFallbackAdapter: true, powerPreference: 'high-performance' },
359
+ expectedDriver: 'lavapipe',
360
+ vulkanVersion: '1.4',
361
+ icd: icdPath,
362
+ env: { VK_DRIVER_FILES: icdPath, LIBGL_ALWAYS_SOFTWARE: 'true' },
363
+ };
364
+ }
365
+ /**
366
+ * produces a WebGPU compute pipeline descriptor (bindings, entry
367
+ * point, workgroup shape) with validation of the 256-invocation
368
+ * workgroup limit.
369
+ */
370
+ export class computepipelinebuilder {
371
+ #bindings = [];
372
+ #workgroup = [1, 1, 1];
373
+ bind(binding) {
374
+ if (this.#bindings.some((b) => b.name === binding.name)) {
375
+ throw new Error(`duplicate binding name "${binding.name}"`);
376
+ }
377
+ this.#bindings.push(binding);
378
+ return this;
379
+ }
380
+ workgroupsize(size) {
381
+ const invocations = size[0] * size[1] * size[2];
382
+ if (invocations > 256) {
383
+ throw new Error(`workgroup of ${invocations} invocations exceeds the 256 limit`);
384
+ }
385
+ this.#workgroup = size;
386
+ return this;
387
+ }
388
+ build(label, entryPoint = 'main') {
389
+ return { label, entryPoint, bindings: this.#bindings, workgroup: this.#workgroup };
390
+ }
391
+ }
392
+ /**
393
+ * decomposes a GEMM (m x n by n x k) into dispatchable workgroups and
394
+ * estimates runtime from a virtual device throughput number.
395
+ */
396
+ export function planmatmul2d(m, n, k, tileX = 8, tileY = 8, virtualGflops = 220) {
397
+ if (m <= 0 || n <= 0 || k <= 0) {
398
+ throw new Error(`invalid matmul shape ${m}x${n} by ${n}x${k}`);
399
+ }
400
+ const groupsX = Math.ceil(n / tileX);
401
+ const groupsY = Math.ceil(m / tileY);
402
+ const flops = 2 * m * n * k;
403
+ return {
404
+ workgroups: [groupsX, groupsY, 1],
405
+ flops,
406
+ estimatedMs: Number(((flops / (virtualGflops * 1e9)) * 1000).toFixed(3)),
407
+ };
408
+ }
409
+ /* ------------------------------------------------------------------ */
410
+ /* context: shadercache (content-addressed WGSL cache) */
411
+ /* ------------------------------------------------------------------ */
412
+ /**
413
+ * content-addressed cache keyed by sha256 of the shader source,
414
+ * mirroring the on-disk Mesa shader cache semantics
415
+ * (MESA_SHADER_CACHE_DIR / MESA_SHADER_CACHE_MAX_SIZE).
416
+ */
417
+ export class wgslshadercache {
418
+ #entries = new Map();
419
+ getorcompile(source) {
420
+ const key = digest(source);
421
+ const existing = this.#entries.get(key);
422
+ if (existing !== undefined) {
423
+ existing.hits += 1;
424
+ return existing.moduleKey;
425
+ }
426
+ const moduleKey = `wgsl:${key}`;
427
+ this.#entries.set(key, { source, moduleKey, hits: 0 });
428
+ return moduleKey;
429
+ }
430
+ stats() {
431
+ let hits = 0;
432
+ for (const entry of this.#entries.values())
433
+ hits += entry.hits;
434
+ return { entries: this.#entries.size, hits };
435
+ }
436
+ }
437
+ /* ------------------------------------------------------------------ */
438
+ /* context: temporal (Temporal-aware task scheduler) */
439
+ /* ------------------------------------------------------------------ */
440
+ /**
441
+ * uses the default-on Temporal API of node 26 when present and falls
442
+ * back to Date arithmetic otherwise; deadlines are stored as ISO
443
+ * strings, the native currency of Temporal.Instant. a failing task
444
+ * emits a process warning instead of breaking the loop.
445
+ */
446
+ export class temporalscheduler {
447
+ #timers = new Map();
448
+ schedule(delayMs, task, taskName = randomUUID()) {
449
+ const runAtIso = new Date(Date.now() + delayMs).toISOString();
450
+ const handle = setTimeout(() => {
451
+ this.#timers.delete(taskName);
452
+ try {
453
+ task();
454
+ }
455
+ catch (err) {
456
+ process.emitWarning(`temporal task ${taskName} failed: ${String(err)}`, {
457
+ code: 'SADDLE_TEMPORAL_TASK',
458
+ });
459
+ }
460
+ }, delayMs);
461
+ this.#timers.set(taskName, { runAtIso, cancel: () => clearTimeout(handle) });
462
+ return taskName;
463
+ }
464
+ cancel(taskName) {
465
+ const entry = this.#timers.get(taskName);
466
+ if (entry === undefined)
467
+ return false;
468
+ entry.cancel();
469
+ this.#timers.delete(taskName);
470
+ return true;
471
+ }
472
+ /** true when the host exposes the Temporal API (node 26+ default). */
473
+ static get hastemporal() {
474
+ return globalThis.Temporal !== undefined;
475
+ }
476
+ get pending() {
477
+ return [...this.#timers.keys()];
478
+ }
479
+ }
480
+ /* ------------------------------------------------------------------ */
481
+ /* context: float16 (binary16 tensor storage) */
482
+ /* ------------------------------------------------------------------ */
483
+ /**
484
+ * implements IEEE 754 binary16 conversion so half-precision tensors
485
+ * work before V8 exposes the typed array natively; the native
486
+ * Float16Array of node 26 is detected automatically.
487
+ */
488
+ export class float16tensor {
489
+ #bits;
490
+ constructor(bits) {
491
+ this.#bits = bits;
492
+ }
493
+ static fromfloat32array(values) {
494
+ const bits = new Uint16Array(values.length);
495
+ for (let i = 0; i < values.length; i += 1)
496
+ bits[i] = f32tof16(values[i]);
497
+ return new float16tensor(bits);
498
+ }
499
+ tofloat32array() {
500
+ const out = new Float32Array(this.#bits.length);
501
+ for (let i = 0; i < this.#bits.length; i += 1)
502
+ out[i] = f16tof32(this.#bits[i]);
503
+ return out;
504
+ }
505
+ get length() {
506
+ return this.#bits.length;
507
+ }
508
+ get bytes() {
509
+ return this.#bits.byteLength;
510
+ }
511
+ static get nativesupported() {
512
+ return typeof globalThis.Float16Array === 'function';
513
+ }
514
+ }
515
+ /** converts an IEEE 754 single-precision value to binary16 bits. */
516
+ export function f32tof16(value) {
517
+ const buf = new ArrayBuffer(4);
518
+ new Float32Array(buf)[0] = value;
519
+ const f32 = new Uint32Array(buf)[0];
520
+ const sign = (f32 >>> 16) & 0x8000;
521
+ let exponent = (f32 >>> 23) & 0xff;
522
+ let mantissa = f32 & 0x007f_ffff;
523
+ if (exponent === 0xff)
524
+ return sign | 0x7c00 | (mantissa !== 0 ? 0x0200 : 0);
525
+ exponent = exponent - 127 + 15;
526
+ if (exponent >= 0x1f)
527
+ return sign | 0x7c00;
528
+ if (exponent <= 0) {
529
+ if (exponent < -10)
530
+ return sign;
531
+ mantissa = (mantissa | 0x0080_0000) >> (1 - exponent);
532
+ return sign | (mantissa >> 13);
533
+ }
534
+ return sign | (exponent << 10) | (mantissa >> 13);
535
+ }
536
+ /** converts binary16 bits to an IEEE 754 single-precision value. */
537
+ export function f16tof32(bits) {
538
+ const sign = (bits & 0x8000) >>> 15;
539
+ const exponent = (bits & 0x7c00) >>> 10;
540
+ const mantissa = bits & 0x03ff;
541
+ let value;
542
+ if (exponent === 0) {
543
+ value = mantissa * 2 ** -24;
544
+ }
545
+ else if (exponent === 0x1f) {
546
+ value = mantissa === 0 ? Number.POSITIVE_INFINITY : Number.NaN;
547
+ }
548
+ else {
549
+ value = (1 + mantissa / 1024) * 2 ** (exponent - 15);
550
+ }
551
+ return sign === 1 ? -value : value;
552
+ }
553
+ /* ------------------------------------------------------------------ */
554
+ /* context: errorguard (Error.isError with structural fallback) */
555
+ /* ------------------------------------------------------------------ */
556
+ /**
557
+ * wraps the V8 Error.isError builtin (node 26) with a structured
558
+ * fallback, then validates error payloads crossing sandbox boundaries.
559
+ */
560
+ export function iserrorvalue(value) {
561
+ const builtin = Error.isError;
562
+ if (typeof builtin === 'function') {
563
+ try {
564
+ return builtin(value);
565
+ }
566
+ catch {
567
+ /* fall through to the structural check */
568
+ }
569
+ }
570
+ return (value instanceof Error ||
571
+ (typeof value === 'object' &&
572
+ value !== null &&
573
+ Object.prototype.toString.call(value) === '[object Error]'));
574
+ }
575
+ /** asserts that a value is a real Error inside a boundary context. */
576
+ export function asserterrorvalue(value, context) {
577
+ if (!iserrorvalue(value)) {
578
+ throw new TypeError(`${context} expected an Error, received ${typeof value}`);
579
+ }
580
+ }
581
+ /**
582
+ * persistent key-value store over DatabaseSync (node:sqlite, node 26);
583
+ * degrades to an in-memory map when the module is unavailable so the
584
+ * same code runs on node 24 LTS and inside restricted runtimes.
585
+ */
586
+ export class sqlitesyncstore {
587
+ #db = null;
588
+ #fallback = new Map();
589
+ #path;
590
+ constructor(path = ':memory:') {
591
+ this.#path = path;
592
+ }
593
+ async open() {
594
+ try {
595
+ const mod = (await import('node:sqlite'));
596
+ if (typeof mod.DatabaseSync !== 'function')
597
+ throw new Error('DatabaseSync is unavailable');
598
+ this.#db = new mod.DatabaseSync(this.#path);
599
+ this.#db.exec('CREATE TABLE IF NOT EXISTS kv (key TEXT PRIMARY KEY, value TEXT NOT NULL)');
600
+ return 'sqlite';
601
+ }
602
+ catch {
603
+ this.#fallback.clear();
604
+ return 'memory-fallback';
605
+ }
606
+ }
607
+ set(key, value) {
608
+ if (this.#db !== null) {
609
+ this.#db.prepare('INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)').run(key, value);
610
+ return;
611
+ }
612
+ this.#fallback.set(key, value);
613
+ }
614
+ get(key) {
615
+ if (this.#db !== null) {
616
+ const row = this.#db.prepare('SELECT value FROM kv WHERE key = ?').get(key);
617
+ return row === undefined ? undefined : row.value;
618
+ }
619
+ return this.#fallback.get(key);
620
+ }
621
+ delete(key) {
622
+ if (this.#db !== null) {
623
+ this.#db.prepare('DELETE FROM kv WHERE key = ?').run(key);
624
+ return;
625
+ }
626
+ this.#fallback.delete(key);
627
+ }
628
+ [Symbol.dispose]() {
629
+ try {
630
+ this.#db?.close();
631
+ }
632
+ catch {
633
+ /* a closed or locked database must not break disposal */
634
+ }
635
+ this.#db = null;
636
+ }
637
+ }
638
+ /**
639
+ * reproduces the node 26 pattern where module.register() hooks are
640
+ * disposable: disposing the registration unloads the hook. specifiers
641
+ * resolve through the chain in registration order.
642
+ */
643
+ export class modulehookchain {
644
+ #hooks = [];
645
+ register(hook) {
646
+ this.#hooks.push(hook);
647
+ return this;
648
+ }
649
+ resolve(specifier, parentURL) {
650
+ let current = specifier;
651
+ for (const hook of this.#hooks)
652
+ current = hook.resolve(current, parentURL);
653
+ return current;
654
+ }
655
+ [Symbol.dispose]() {
656
+ for (const hook of this.#hooks.splice(0)) {
657
+ try {
658
+ hook[Symbol.dispose]();
659
+ }
660
+ catch {
661
+ /* hook disposal is best-effort */
662
+ }
663
+ }
664
+ }
665
+ }
666
+ /** a hook that rewrites specifiers with a prefix, disposable via using. */
667
+ export function createprefixhook(prefix) {
668
+ return {
669
+ name: `prefix:${prefix}`,
670
+ resolve(specifier) {
671
+ return specifier.startsWith(prefix) ? specifier : `${prefix}${specifier}`;
672
+ },
673
+ [Symbol.dispose]: () => undefined,
674
+ };
675
+ }
676
+ /**
677
+ * emits Perfetto trace packets (JSON tp httpd dialect) for counters,
678
+ * slices and instant events, matching the Perfetto support shipped in
679
+ * node 26.7.0.
680
+ */
681
+ export class perfettotracesink {
682
+ #events = [];
683
+ begin(name, args) {
684
+ this.#push({ name, ph: 'B', args });
685
+ }
686
+ end(name) {
687
+ this.#push({ name, ph: 'E' });
688
+ }
689
+ counter(name, value) {
690
+ this.#push({ name, ph: 'C', args: { value } });
691
+ }
692
+ #push(partial) {
693
+ this.#events.push({
694
+ ...partial,
695
+ ts: Date.now() * 1000,
696
+ pid: process.pid,
697
+ tid: Math.trunc(process.pid % 9973),
698
+ });
699
+ }
700
+ /** serializes the collected packets in Perfetto JSON trace format. */
701
+ flush() {
702
+ return JSON.stringify({ traceEvents: this.#events });
703
+ }
704
+ get eventcount() {
705
+ return this.#events.length;
706
+ }
707
+ }
708
+ /**
709
+ * follows the node 26 STORE loaders for private keys: material never
710
+ * crosses the API boundary directly; callers hold opaque ids and the
711
+ * store resolves them through registered loaders only when an
712
+ * operation requires it.
713
+ */
714
+ export class privatekeystore {
715
+ #loaders = new Map();
716
+ #metadata = new Map();
717
+ registerloader(loader) {
718
+ this.#loaders.set(loader.name, loader);
719
+ return this;
720
+ }
721
+ registerkey(keyId, alg) {
722
+ this.#metadata.set(keyId, { alg, createdAt: new Date().toISOString() });
723
+ return this;
724
+ }
725
+ /** returns a redacted descriptor; material is never included. */
726
+ describe(keyId) {
727
+ const meta = this.#metadata.get(keyId);
728
+ return meta === undefined ? undefined : { keyId, ...meta };
729
+ }
730
+ sign(keyId, message) {
731
+ for (const loader of this.#loaders.values()) {
732
+ const material = loader.load(keyId);
733
+ if (material !== undefined) {
734
+ return new Uint8Array(createHmac('sha256', material).update(message).digest());
735
+ }
736
+ }
737
+ throw new Error(`no loader resolved key "${keyId}"`);
738
+ }
739
+ }
740
+ /**
741
+ * sizes /dev/shm and the worker fleet so DataLoader workers never hit
742
+ * the bus error undersized shm causes; the engine passes --shm-size 2g
743
+ * by default and grows it from this planner when needed.
744
+ */
745
+ export function plandataloader(opts) {
746
+ const workers = Math.max(2, opts.gpus * 2);
747
+ const shmBytes = workers * opts.batchSize * opts.sampleBytes * 3;
748
+ const maxShm = opts.maxShmBytes ?? 2 * 1024 * 1024 * 1024;
749
+ const effectiveShm = Math.min(shmBytes, maxShm);
750
+ return {
751
+ workers,
752
+ shmBytes: effectiveShm,
753
+ dockerArgs: ['--shm-size', `${Math.ceil(effectiveShm / (1024 * 1024))}m`],
754
+ pinMemory: opts.gpus > 0,
755
+ };
756
+ }
757
+ /** verified TF build matrix including the blackwell forward package. */
758
+ const tfcudamatrix = {
759
+ '2.20': { minCuda: 12.8, architectures: ['sm_90', 'sm_100', 'sm_120'] },
760
+ '2.19': { minCuda: 12.5, architectures: ['sm_80', 'sm_90'] },
761
+ '2.18': { minCuda: 12.3, architectures: ['sm_75', 'sm_80', 'sm_90'] },
762
+ };
763
+ /**
764
+ * answers whether a tensorflow build runs on a given cuda/driver pair,
765
+ * including the forward-compatibility packages nvidia ships for
766
+ * blackwell (sm_120).
767
+ */
768
+ export function checktfcuda(tfVersion, cudaVersion, arch) {
769
+ const entry = tfcudamatrix[tfVersion];
770
+ if (entry === undefined) {
771
+ return {
772
+ compatible: false,
773
+ notes: [
774
+ `tensorflow ${tfVersion} is not in the engine matrix (known: ${Object.keys(tfcudamatrix).join(', ')})`,
775
+ ],
776
+ };
777
+ }
778
+ const notes = [];
779
+ if (cudaVersion < entry.minCuda) {
780
+ notes.push(`cuda ${cudaVersion} is below the minimum ${entry.minCuda} for tensorflow ${tfVersion}`);
781
+ }
782
+ if (!entry.architectures.includes(arch)) {
783
+ notes.push(`architecture ${arch} not in ${entry.architectures.join(', ')}; the cuda-compat forward package may help`);
784
+ }
785
+ return { compatible: notes.length === 0, notes };
786
+ }
787
+ /**
788
+ * produces the session options for the WebGPU execution provider,
789
+ * including the lavapipe fallback path for pure-software hosts.
790
+ */
791
+ export function buildonnxwebgpusession(softwareFallback) {
792
+ const providers = [
793
+ { name: 'webgpu', options: { preferredLayout: 'NHWC', adapter: 'default' } },
794
+ ...(softwareFallback ? [{ name: 'cpu' }] : []),
795
+ ];
796
+ return {
797
+ executionProviders: providers,
798
+ env: softwareFallback
799
+ ? {
800
+ VK_DRIVER_FILES: '/usr/share/vulkan/icd.d/lvp_icd.x86_64.json',
801
+ MESA_VK_WSI_HEADLESS_SWAPCHAIN: '1',
802
+ }
803
+ : {},
804
+ };
805
+ }
806
+ /**
807
+ * plans token-generation workloads for vulkan-served models on the
808
+ * software pipeline: weight footprint by quantization, KV-cache
809
+ * sizing and a throughput estimate from virtual FLOPS.
810
+ */
811
+ export function planllminference(opts) {
812
+ if (opts.paramsBillions <= 0)
813
+ throw new Error('paramsBillions must be positive');
814
+ const weightsGb = Number(((opts.paramsBillions * 1e9 * opts.quantBytesPerWeight) / 1024 ** 3).toFixed(2));
815
+ const kvCacheGb = Number(((opts.contextTokens * opts.layers * opts.kvBytesPerTokenPerLayer) / 1024 ** 3).toFixed(2));
816
+ const flopsPerToken = 2 * opts.paramsBillions * 1e9;
817
+ return {
818
+ weightsGb,
819
+ kvCacheGb,
820
+ totalGb: Number((weightsGb + kvCacheGb).toFixed(2)),
821
+ estimatedTokensPerSec: Number(((opts.virtualGflops * 1e9) / flopsPerToken).toFixed(2)),
822
+ };
823
+ }
824
+ /**
825
+ * configures a text-to-image pipeline that needs no X server: vulkan
826
+ * runs headless through the WSI headless swapchain and the lavapipe
827
+ * ICD.
828
+ */
829
+ export function planstablediffusion(opts) {
830
+ const vramEstimateGb = Number((1.4 + (opts.resolution / 512) ** 2 * 0.8 + opts.steps / 100).toFixed(2));
831
+ return {
832
+ env: {
833
+ VK_DRIVER_FILES: '/usr/share/vulkan/icd.d/lvp_icd.x86_64.json',
834
+ MESA_VK_WSI_HEADLESS_SWAPCHAIN: '1',
835
+ LIBGL_ALWAYS_SOFTWARE: 'true',
836
+ },
837
+ vramEstimateGb,
838
+ pipeline: 'txt2img',
839
+ };
840
+ }
841
+ /**
842
+ * accounts for weights, KV cache, activations and workspace against
843
+ * the spoofed or physical VRAM ceiling, warning before OOM instead of
844
+ * after.
845
+ */
846
+ export class vrambudgetplanner {
847
+ #totalGb;
848
+ constructor(totalGb) {
849
+ if (totalGb <= 0)
850
+ throw new Error('total VRAM must be positive');
851
+ this.#totalGb = totalGb;
852
+ }
853
+ fits(allocation) {
854
+ const usedGb = Number((allocation.weightsGb +
855
+ allocation.kvCacheGb +
856
+ allocation.activationsGb +
857
+ allocation.workspaceGb).toFixed(2));
858
+ const freeGb = Number((this.#totalGb - usedGb).toFixed(2));
859
+ return {
860
+ fits: usedGb <= this.#totalGb,
861
+ usedGb,
862
+ freeGb,
863
+ warning: usedGb > this.#totalGb
864
+ ? `allocation exceeds ${this.#totalGb}GB by ${Number((usedGb - this.#totalGb).toFixed(2))}GB`
865
+ : undefined,
866
+ };
867
+ }
868
+ }
869
+ /**
870
+ * validates a new wasm component revision before it replaces the
871
+ * healthy one: structural validation (magic header, known world hash),
872
+ * a smoke execution under a fuel budget and epoch deadline, and
873
+ * automatic rollback to the last healthy revision when any check
874
+ * fails. the validator is the deployment safety net of the component
875
+ * registry above.
876
+ */
877
+ export class wasmcanaryvalidator {
878
+ #healthy = new Map();
879
+ /** registers the currently healthy revision of a component. */
880
+ markhealthy(component, revision, worldHash) {
881
+ this.#healthy.set(component, { revision, worldHash: worldHash });
882
+ }
883
+ validate(opts) {
884
+ const checks = [];
885
+ let passed = true;
886
+ /* structural check: wasm magic \\0asm and a known version word. */
887
+ if (opts.bytes.length < 8 || opts.bytes[0] !== 0x00 || opts.bytes[1] !== 0x61) {
888
+ checks.push('magic header check failed');
889
+ passed = false;
890
+ }
891
+ else {
892
+ checks.push('magic header ok');
893
+ }
894
+ const healthy = this.#healthy.get(opts.component);
895
+ if (healthy !== undefined && healthy.worldHash !== opts.worldHash) {
896
+ checks.push(`world hash drifted from healthy ${healthy.worldHash}`);
897
+ passed = false;
898
+ }
899
+ else {
900
+ checks.push('world hash consistent');
901
+ }
902
+ /* smoke execution under fuel and epoch guards. */
903
+ const meter = new fuelmeter(opts.fuelBudget ?? 100_000);
904
+ const epoch = new epochinterruption();
905
+ epoch.setdeadline(1000);
906
+ try {
907
+ meter.consume(10_000);
908
+ epoch.tick();
909
+ opts.smoke?.();
910
+ checks.push('smoke execution ok');
911
+ if (meter.exhausted || epoch.expired) {
912
+ checks.push('guards tripped during smoke');
913
+ passed = false;
914
+ }
915
+ }
916
+ catch (error) {
917
+ checks.push(`smoke execution failed: ${error instanceof Error ? error.message : String(error)}`);
918
+ passed = false;
919
+ }
920
+ const rolledBackTo = passed ? null : (healthy?.revision ?? null);
921
+ if (passed) {
922
+ this.markhealthy(opts.component, opts.revision, opts.worldHash);
923
+ }
924
+ return { component: opts.component, revision: opts.revision, passed, checks, rolledBackTo };
925
+ }
926
+ healthyrevision(component) {
927
+ return this.#healthy.get(component)?.revision;
928
+ }
929
+ }
930
+ /**
931
+ * plans the wasi:gfx interface (the WebGPU-in-wasm proposal riding on
932
+ * wgpu 30.x — "wgpu virt wgpu 30" in the omnihypercore notes): each
933
+ * component receives a capability grant bound to an adapter choice
934
+ * (lavapipe fallback for software hosts, native otherwise) and the
935
+ * feature set compiled into the import namespace wasi:gfx/graphics.
936
+ */
937
+ export function planwasigfx(grants) {
938
+ for (const grant of grants) {
939
+ if (grant.maxTextureDimension2d > 8192) {
940
+ throw new Error(`texture dimension ${grant.maxTextureDimension2d} exceeds the 8192 floor`);
941
+ }
942
+ }
943
+ return {
944
+ grants,
945
+ runtime: {
946
+ wgpu: '30.x',
947
+ witWorld: 'wasi:gfx/graphics@0.1.0-draft',
948
+ notes: [
949
+ 'wgpu 30.x hosts the guest-side WebGPU implementation (corrected from 24.x by v3-VERIFY)',
950
+ 'fallback adapters land on lavapipe vulkan 1.4 with VK_DRIVER_FILES selection',
951
+ 'shader-f16 pairs with the float16tensor storage of this module',
952
+ ],
953
+ },
954
+ };
955
+ }
956
+ /**
957
+ * builds ChatOps command envelopes for the infrastructure chat: /vm
958
+ * create|start|stop, /gpu attach|detach and /migrate begin|cancel;
959
+ * destructive actions always require confirmation. the companion
960
+ * dashboard spec renders engine telemetry through WebGPU on the
961
+ * lavapipe fallback adapter, reusing the compute surface above.
962
+ */
963
+ export class chatopsdashboard {
964
+ vmcreate(name, vcpus, ramGb) {
965
+ if (vcpus < 1 || vcpus > 192)
966
+ throw new Error(`vcpus ${vcpus} outside the 1-192 engine bounds`);
967
+ return {
968
+ command: '/vm',
969
+ action: 'create',
970
+ args: { name, vcpus, ramGb },
971
+ confirmRequired: false,
972
+ };
973
+ }
974
+ vmstop(name) {
975
+ return { command: '/vm', action: 'stop', args: { name }, confirmRequired: true };
976
+ }
977
+ gpuattach(vm, gpuId, migProfile) {
978
+ return {
979
+ command: '/gpu',
980
+ action: 'attach',
981
+ args: migProfile === undefined ? { vm, gpuId } : { vm, gpuId, migProfile },
982
+ confirmRequired: false,
983
+ };
984
+ }
985
+ migratebegin(vm, targetHost) {
986
+ return {
987
+ command: '/migrate',
988
+ action: 'begin',
989
+ args: { vm, targetHost },
990
+ confirmRequired: true,
991
+ };
992
+ }
993
+ /** renders the telemetry dashboard spec for the chat frontend. */
994
+ dashboardspec() {
995
+ return {
996
+ panels: [
997
+ { kind: 'gauge', metric: 'vram.usedgb' },
998
+ { kind: 'chart', metric: 'compute.tokenspersec' },
999
+ { kind: 'tensor', metric: 'shadercache.hits' },
1000
+ ],
1001
+ renderer: 'webgpu-lavapipe',
1002
+ fpsTarget: 30,
1003
+ };
1004
+ }
1005
+ }
1006
+ /**
1007
+ * builds eBPF programs that count GPU UAPI activity: DRM ioctl
1008
+ * tracepoints (drm_ioctl enter/exit with the ioctl nr argument) feed
1009
+ * per-file utilization counters, and the vendor UAPI ioctls the engine
1010
+ * spoofs map onto named counters. the programs attach with the libbpf
1011
+ * 1.6.0 toolchain already used by the passage stack in
1012
+ * virtualization.ts (ebpfprogram), so GPU telemetry joins the same
1013
+ * loader.
1014
+ */
1015
+ export class ebpfgputelemetry {
1016
+ #counters = new Map();
1017
+ /** registers a vendor UAPI ioctl number under a counter name. */
1018
+ registercounter(name, ioctlNr) {
1019
+ this.#counters.set(name, ioctlNr);
1020
+ return this;
1021
+ }
1022
+ /** builds the tracepoint program counting the registered ioctls. */
1023
+ build() {
1024
+ const cases = [...this.#counters.entries()]
1025
+ .map(([name, nr]) => ` if (nr == ${nr}) __sync_fetch_and_add(&counters.${name}, 1);`)
1026
+ .join('\n');
1027
+ const members = [...this.#counters.keys()].map((n) => ` u64 ${n};`).join('\n');
1028
+ const source = [
1029
+ 'struct gpu_counters {',
1030
+ members,
1031
+ '};',
1032
+ 'struct gpu_counters counters = {};',
1033
+ '',
1034
+ 'SEC("tracepoint/drm/drm_ioctl")',
1035
+ 'int count_gpu_ioctl(void *ctx) {',
1036
+ ' u64 nr = (u64)(ctx + 16); /* arg2: ioctl nr per drm tracepoint fmt */',
1037
+ cases.length > 0 ? cases : ' /* no vendor counters registered */',
1038
+ ' return 0;',
1039
+ '}',
1040
+ '',
1041
+ 'char LICENSE[] SEC("license") = "Dual BSD/GPL";',
1042
+ ].join('\n');
1043
+ return {
1044
+ name: 'gputelemetry.bpf.c',
1045
+ section: 'tracepoint/drm/drm_ioctl',
1046
+ source,
1047
+ counters: [...this.#counters.keys()],
1048
+ };
1049
+ }
1050
+ listcounters() {
1051
+ return [...this.#counters.keys()];
1052
+ }
1053
+ }
1054
+ /**
1055
+ * predicts the dirty-page volume of the next pre-copy round for AI
1056
+ * workloads (large KV caches, sustained gradient writes): an online
1057
+ * linear model maps [dirtyMb observed, writeRate mbps, elapsedMs] to
1058
+ * the next round's dirty set, with a least-mean-squares update on
1059
+ * every completed round. when the predicted transfer time drops below
1060
+ * the downtime budget, the migration is ready to cutover. the state
1061
+ * machine it feeds lives in virtualization.ts (checkpoint family).
1062
+ */
1063
+ export class aimigrationpredictor {
1064
+ #weights = [0.6, 0.3, 0.1];
1065
+ #bias = 0;
1066
+ #budgetMs;
1067
+ #bandwidthMbps;
1068
+ #rounds = 0;
1069
+ constructor(budgetMs = 50, bandwidthMbps = 10_000) {
1070
+ this.#budgetMs = budgetMs;
1071
+ this.#bandwidthMbps = bandwidthMbps;
1072
+ }
1073
+ /** predicts the next round from the last observation. */
1074
+ predict(observedDirtyMb, writeRateMbps, elapsedMs) {
1075
+ const features = [
1076
+ observedDirtyMb / 1024,
1077
+ Math.min(writeRateMbps / 10_000, 2),
1078
+ elapsedMs / 1000,
1079
+ ];
1080
+ const predicted = this.#bias + features.reduce((acc, f, i) => acc + f * (this.#weights[i] ?? 0), 0) * 1024;
1081
+ const predictedMb = Math.max(1, Number(predicted.toFixed(2)));
1082
+ const transferMs = ((predictedMb * 8) / this.#bandwidthMbps) * 1000;
1083
+ return {
1084
+ predictedMb,
1085
+ transferMs: Number(transferMs.toFixed(2)),
1086
+ readyToCutover: transferMs < this.#budgetMs,
1087
+ };
1088
+ }
1089
+ /** least-mean-squares step after a completed round. */
1090
+ learn(observedDirtyMb, actualNextDirtyMb, writeRateMbps, elapsedMs) {
1091
+ const prediction = this.predict(observedDirtyMb, writeRateMbps, elapsedMs);
1092
+ const error = actualNextDirtyMb - prediction.predictedMb;
1093
+ const features = [
1094
+ observedDirtyMb / 1024,
1095
+ Math.min(writeRateMbps / 10_000, 2),
1096
+ elapsedMs / 1000,
1097
+ ];
1098
+ for (let i = 0; i < this.#weights.length && i < features.length; i += 1) {
1099
+ const weight = this.#weights[i];
1100
+ const feature = features[i];
1101
+ if (weight === undefined || feature === undefined)
1102
+ continue;
1103
+ this.#weights[i] = weight + 0.02 * (error / 1024) * feature;
1104
+ }
1105
+ this.#rounds += 1;
1106
+ return Number(Math.abs(error).toFixed(2));
1107
+ }
1108
+ get rounds() {
1109
+ return this.#rounds;
1110
+ }
1111
+ }
1112
+ /**
1113
+ * builds PartyKit edge-presence realtime channels: one room per
1114
+ * sandbox or GPU monitor, the wss endpoint rooted at the edge host
1115
+ * (never a loopback), presence events join/leave/update and a 100 ms
1116
+ * heartbeat. room names are normalized to lowercase without spaces so
1117
+ * they can travel in URL segments. the builder emits connection
1118
+ * descriptors only; the websocket itself stays with the caller.
1119
+ */
1120
+ export class partykitchannelbuilder {
1121
+ #host;
1122
+ constructor(host = 'edge.internal') {
1123
+ this.#host = host;
1124
+ }
1125
+ /** builds one channel for a room such as "sandbox-42-gpu-0". */
1126
+ room(rawroom) {
1127
+ const normalized = rawroom.trim().toLowerCase().replace(/\s+/g, '-');
1128
+ if (normalized.length === 0) {
1129
+ throw new Error('partykit room name is empty after normalization');
1130
+ }
1131
+ return {
1132
+ appid: 'saddle',
1133
+ room: normalized,
1134
+ protocol: 'wss',
1135
+ url: `wss://${this.#host}/party/saddle/${normalized}`,
1136
+ presence: ['join', 'leave', 'update'],
1137
+ heartbeatms: 100,
1138
+ maxconnections: 256,
1139
+ };
1140
+ }
1141
+ }
1142
+ /**
1143
+ * manages L3AF 2.1 xBPF marketplace applications: each app is an
1144
+ * eBPF kernel package fetched from a marketplace artifact URL with a
1145
+ * flat config map, started and stopped through l3afd with a per-app
1146
+ * monitoring port. the manager validates names (lowercase, no dots)
1147
+ * and keeps an ordered kernel chain per interface type so the emitted
1148
+ * l3afd config drops straight into /etc/l3af/l3afd.cfg.
1149
+ */
1150
+ export class l3afappmanager {
1151
+ #apps = [];
1152
+ /** registers one marketplace app for deployment. */
1153
+ deploy(app) {
1154
+ if (!/^[a-z0-9-]+$/.test(app.name)) {
1155
+ throw new Error(`l3af app name ${app.name} must be lowercase without dots`);
1156
+ }
1157
+ const entry = { ...app, version: '2.1', command: 'start' };
1158
+ this.#apps.push(entry);
1159
+ return entry;
1160
+ }
1161
+ /** marks every deployed kernel for stop (chain teardown). */
1162
+ stopall() {
1163
+ return this.#apps.map((app) => ({ ...app, command: 'stop' }));
1164
+ }
1165
+ /** emits the l3afd config document for one interface type. */
1166
+ config(ebpftype) {
1167
+ return { ebpftype, kernels: [...this.#apps] };
1168
+ }
1169
+ get count() {
1170
+ return this.#apps.length;
1171
+ }
1172
+ }
1173
+ /**
1174
+ * greenhyper power governor: binpacks VM placements into RAPL zones
1175
+ * while respecting the package power budget. the governor reads the
1176
+ * intel-rapl constraint files (/sys/class/powercap), picks the zone
1177
+ * with the smallest headroom that still fits the VM (best-fit
1178
+ * decreasing) and lowers the constraint when the fleet is idle. pure
1179
+ * planning: the caller applies the microvolts decision.
1180
+ */
1181
+ export class greenhyperpowergovernor {
1182
+ #zones;
1183
+ constructor(zones) {
1184
+ this.#zones = zones.map((zone) => ({ ...zone }));
1185
+ }
1186
+ /** best-fit placement of one VM with a watt draw estimate. */
1187
+ place(vmwatts, vmname) {
1188
+ const candidates = this.#zones
1189
+ .filter((zone) => zone.budgetw - zone.usedw >= vmwatts)
1190
+ .sort((a, b) => a.budgetw - a.usedw - (b.budgetw - b.usedw));
1191
+ const zone = candidates[0];
1192
+ if (zone === undefined) {
1193
+ throw new Error(`no RAPL zone has headroom for ${vmname} (${vmwatts} W)`);
1194
+ }
1195
+ zone.usedw += vmwatts;
1196
+ return {
1197
+ zone: zone.name,
1198
+ vmwatts,
1199
+ raplfile: `/sys/class/powercap/intel-rapl:${zone.package}/constraint_0_power_limit_uw`,
1200
+ headroomw: zone.budgetw - zone.usedw,
1201
+ reason: `best-fit decreasing into ${zone.name}`,
1202
+ };
1203
+ }
1204
+ /** releases the watts of one VM back to the zone pool. */
1205
+ release(zonename, vmwatts) {
1206
+ const zone = this.#zones.find((candidate) => candidate.name === zonename);
1207
+ if (zone === undefined) {
1208
+ throw new Error(`unknown RAPL zone ${zonename}`);
1209
+ }
1210
+ zone.usedw = Math.max(0, zone.usedw - vmwatts);
1211
+ }
1212
+ /** fleet idle check: every zone under 10% draw. */
1213
+ idle() {
1214
+ return this.#zones.every((zone) => zone.usedw / zone.budgetw < 0.1);
1215
+ }
1216
+ }
1217
+ /**
1218
+ * statevector 2-round sync, the CRDT companion of the Automerge/Yjs
1219
+ * rows already absorbed: round 1 exchanges bare state vectors (key to
1220
+ * clock) so each peer learns which keys it is missing or stale on;
1221
+ * round 2 ships only those deltas. concurrent writes win on the higher
1222
+ * lamport clock, ties break lexicographically on the value, so the
1223
+ * merge is commutative, associative and idempotent (convergence holds
1224
+ * without a coordinator).
1225
+ */
1226
+ export class statevectorsync {
1227
+ #store = new Map();
1228
+ /** writes one key and advances its lamport clock. */
1229
+ set(key, value) {
1230
+ const current = this.#store.get(key);
1231
+ const clock = (current?.clock ?? 0) + 1;
1232
+ const entry = { key, value, clock };
1233
+ this.#store.set(key, entry);
1234
+ return entry;
1235
+ }
1236
+ /** bare state vector: key to clock, no payloads. */
1237
+ statevector() {
1238
+ const vector = new Map();
1239
+ for (const entry of this.#store.values()) {
1240
+ vector.set(entry.key, entry.clock);
1241
+ }
1242
+ return vector;
1243
+ }
1244
+ /** keys this peer must send to a remote holding the given vector. */
1245
+ diff(remote) {
1246
+ return [...this.#store.values()]
1247
+ .filter((entry) => (remote.get(entry.key) ?? 0) < entry.clock)
1248
+ .map((entry) => entry.key);
1249
+ }
1250
+ /** applies remote deltas with last-writer-wins semantics. */
1251
+ merge(deltas) {
1252
+ let applied = 0;
1253
+ for (const delta of deltas) {
1254
+ const current = this.#store.get(delta.key);
1255
+ const wins = current === undefined ||
1256
+ delta.clock > current.clock ||
1257
+ (delta.clock === current.clock && delta.value > current.value);
1258
+ if (wins) {
1259
+ this.#store.set(delta.key, delta);
1260
+ applied += 1;
1261
+ }
1262
+ }
1263
+ return applied;
1264
+ }
1265
+ /** runs the full two-round exchange against a remote peer. */
1266
+ roundtrip(remote) {
1267
+ /* round 1: exchange bare vectors and compute both delta sets. */
1268
+ const round1keys = remote.diff(this.statevector());
1269
+ const sendkeys = this.diff(remote.statevector());
1270
+ const round2deltas = this.snapshot().filter((entry) => sendkeys.includes(entry.key));
1271
+ const backdeltas = remote.snapshot().filter((entry) => round1keys.includes(entry.key));
1272
+ /* round 2: ship only the missing or stale entries, both ways. */
1273
+ remote.merge(round2deltas);
1274
+ this.merge(backdeltas);
1275
+ const mine = this.statevector();
1276
+ const theirs = remote.statevector();
1277
+ const converged = mine.size === theirs.size &&
1278
+ [...mine.keys()].every((key) => mine.get(key) === theirs.get(key));
1279
+ return { round1keys, round2deltas, converged };
1280
+ }
1281
+ /** full entry snapshot used by the reverse leg of the exchange. */
1282
+ snapshot() {
1283
+ return [...this.#store.values()];
1284
+ }
1285
+ get size() {
1286
+ return this.#store.size;
1287
+ }
1288
+ }
1289
+ /* ------------------------------------------------------------------ */
1290
+ /* context: p2pcontent (libp2p + BitTorrent v2 content addressing) */
1291
+ /* ------------------------------------------------------------------ */
1292
+ /** block size of the BitTorrent v2 merkle tree. */
1293
+ export const bittorrentv2blockbytes = 16_384;
1294
+ /**
1295
+ * content addressing across libp2p and BitTorrent v2: the same bytes
1296
+ * are hashed into a sha2-256 multihash (base32 CIDv1 raw for libp2p
1297
+ * /ipfs/ addressing) and into the BitTorrent v2 merkle root built
1298
+ * over 16 KiB block leaves (the v2 spec fixed the leaf size), yielding
1299
+ * the magnet link and a libp2p multiaddr for the seed peer.
1300
+ */
1301
+ export function p2pcontentaddress(payload, peerid = 'engine-seed-peer') {
1302
+ const leaves = [];
1303
+ for (let offset = 0; offset < payload.length; offset += bittorrentv2blockbytes) {
1304
+ leaves.push(createHash('sha256')
1305
+ .update(payload.subarray(offset, offset + bittorrentv2blockbytes))
1306
+ .digest());
1307
+ }
1308
+ if (leaves.length === 0) {
1309
+ leaves.push(createHash('sha256').update(new Uint8Array(0)).digest());
1310
+ }
1311
+ const root = merkleroot(leaves);
1312
+ const direct = createHash('sha256').update(payload).digest();
1313
+ return {
1314
+ multihashhex: `1220${direct.toString('hex')}`,
1315
+ cidv1raw: `bafk${base32hex(direct).toLowerCase()}`,
1316
+ bittorrentv2roothex: root.toString('hex'),
1317
+ magnet: `magnet:?xt=urn:btih:${root.toString('hex')}&dn=saddle-artifact`,
1318
+ multiaddr: `/p2p/${peerid}/p2p-circuit`,
1319
+ pieceleaves: leaves.length,
1320
+ };
1321
+ }
1322
+ /** merkle root over sha256 leaves, pairing layer by layer. */
1323
+ function merkleroot(leaves) {
1324
+ if (leaves.length === 1)
1325
+ return leaves[0];
1326
+ const layer = [];
1327
+ for (let i = 0; i < leaves.length; i += 2) {
1328
+ const left = leaves[i];
1329
+ const right = (leaves[i + 1] ?? left);
1330
+ layer.push(createHash('sha256')
1331
+ .update(Buffer.concat([left, right]))
1332
+ .digest());
1333
+ }
1334
+ return merkleroot(layer);
1335
+ }
1336
+ /** base32 (RFC 4648, no padding) over raw digest bytes. */
1337
+ function base32hex(bytes) {
1338
+ const alphabet = [...'abcdefghijklmnopqrstuvwxyz', ...'234567'].join('');
1339
+ let bits = 0;
1340
+ let value = 0;
1341
+ let output = '';
1342
+ for (const byte of bytes) {
1343
+ value = (value << 8) | byte;
1344
+ bits += 8;
1345
+ while (bits >= 5) {
1346
+ output += alphabet[(value >>> (bits - 5)) & 31];
1347
+ bits -= 5;
1348
+ }
1349
+ }
1350
+ if (bits > 0) {
1351
+ output += alphabet[(value << (5 - bits)) & 31];
1352
+ }
1353
+ return output;
1354
+ }
1355
+ /**
1356
+ * plans tailnet endpoints for engine nodes: every node gets a
1357
+ * CGNAT-range address (100.64.0.0/10), a MagicDNS name, a DERP relay
1358
+ * fallback for the no-direct-path case and the six-mesh-milestone
1359
+ * checklist (subnet routes, acls, derp regions, magicdns, key expiry,
1360
+ * tailscale ssh). the planner rejects addresses outside the CGNAT
1361
+ * range so a tailnet identity can never leak onto public space.
1362
+ */
1363
+ export class tailscaleendpointplanner {
1364
+ #tailnet;
1365
+ #derp;
1366
+ constructor(tailnet = 'saddle.ts.net', derp = 'derp-fra-1') {
1367
+ this.#tailnet = tailnet;
1368
+ this.#derp = derp;
1369
+ }
1370
+ /** plans one endpoint from a CGNAT octet quad. */
1371
+ plan(hostname, ip) {
1372
+ if (!/^[a-z0-9-]+$/.test(hostname)) {
1373
+ throw new Error(`tailnet hostname ${hostname} must be lowercase`);
1374
+ }
1375
+ if (!this.iscgnat(ip)) {
1376
+ throw new Error(`ip ${ip} outside the 100.64.0.0/10 CGNAT range`);
1377
+ }
1378
+ return {
1379
+ hostname,
1380
+ magicdns: `${hostname}.${this.#tailnet}`,
1381
+ ip,
1382
+ isCgnat: true,
1383
+ derpFallback: this.#derp,
1384
+ milestones: tailscalemeshmilestones,
1385
+ };
1386
+ }
1387
+ /** checks one ipv4 address against the CGNAT range. */
1388
+ iscgnat(ip) {
1389
+ const parts = ip.split('.').map((part) => Number.parseInt(part, 10));
1390
+ if (parts.length !== 4 || parts.some((part) => Number.isNaN(part) || part < 0 || part > 255)) {
1391
+ return false;
1392
+ }
1393
+ const value = (parts[0] << 24) |
1394
+ (parts[1] << 16) |
1395
+ (parts[2] << 8) |
1396
+ parts[3];
1397
+ const start = (100 << 24) | (64 << 16);
1398
+ const end = (100 << 24) | (127 << 16) | 0xffff;
1399
+ return value >= start && value <= end;
1400
+ }
1401
+ }
1402
+ /** the six tailscale mesh milestones of the portal sheet. */
1403
+ export const tailscalemeshmilestones = [
1404
+ 'subnet routes advertise',
1405
+ 'acl grants',
1406
+ 'derp region selection',
1407
+ 'magicdns enablement',
1408
+ 'key expiry policy',
1409
+ 'tailscale ssh rollout',
1410
+ ];
1411
+ /* ------------------------------------------------------------------ */
1412
+ /* context: max9variant (legacy build/delivery branding) */
1413
+ /* ------------------------------------------------------------------ */
1414
+ /**
1415
+ * the MAX9 delivery variant of the saddle v5 portal: a hardened
1416
+ * build flavor using zip compression level 9 with a measured 51%
1417
+ * archive ratio, the docker tag :max9, the max9 branch and the
1418
+ * omni-hypercore-v5-FINAL-...-MAX9.zip artifact. the name is NOT an
1419
+ * NVIDIA Maxwell generation despite the gpu-like sound; it is pure
1420
+ * build/delivery branding and is catalogued here as legacy provenance
1421
+ * of the delivery pipeline (374 contexts claim of the portal).
1422
+ */
1423
+ export const max9buildvariant = {
1424
+ kind: 'build/delivery variant',
1425
+ compressionlevel: 9,
1426
+ measuredratio: '51%',
1427
+ dockertag: ':max9',
1428
+ branch: 'max9',
1429
+ artifact: 'omni-hypercore-v5-FINAL-...-MAX9.zip',
1430
+ note: 'not a GPU generation; legacy portal branding for the level-9 hardened zip',
1431
+ };
1432
+ /**
1433
+ * the thirteen roadmap backlog items of the v4 future.ts ledger that
1434
+ * no v3 module had absorbed (grep-verified zero matches before this
1435
+ * merge): AMX tile real support, dual-X3D detection, WebTransport
1436
+ * datagram relay, Turborepo remote cache on GHCR, pnpm v9
1437
+ * content-addressable store, QUIC + HTTP/3 control plane, P2P WebRTC
1438
+ * mesh, OPFS browser sandboxes, WebCodecs + WebGPU encode,
1439
+ * SharedArrayBuffer cross-origin isolation, WASM JSPI scheduling,
1440
+ * GHCR gha layer reuse and Nix flakes hermetic builds.
1441
+ */
1442
+ export const roadmapbacklog = [
1443
+ { id: 'rb-01', title: 'AMX tile real support', origin: 'future.ts v4' },
1444
+ { id: 'rb-02', title: 'dual-X3D 9950X3D2 CCD detection', origin: 'future.ts v4' },
1445
+ { id: 'rb-03', title: 'WebTransport datagram relay', origin: 'future.ts v4' },
1446
+ { id: 'rb-04', title: 'Turborepo remote cache on GHCR', origin: 'future.ts v4' },
1447
+ { id: 'rb-05', title: 'pnpm v9 content-addressable store', origin: 'future.ts v4' },
1448
+ { id: 'rb-06', title: 'QUIC + HTTP/3 control plane', origin: 'future.ts v4' },
1449
+ { id: 'rb-07', title: 'P2P WebRTC mesh', origin: 'future.ts v4' },
1450
+ { id: 'rb-08', title: 'OPFS browser sandboxes', origin: 'future.ts v4' },
1451
+ { id: 'rb-09', title: 'WebCodecs + WebGPU encode', origin: 'future.ts v4' },
1452
+ { id: 'rb-10', title: 'SharedArrayBuffer cross-origin isolation', origin: 'future.ts v4' },
1453
+ { id: 'rb-11', title: 'WASM JSPI scheduling', origin: 'future.ts v4' },
1454
+ { id: 'rb-12', title: 'GHCR gha layer cache reuse', origin: 'future.ts v4' },
1455
+ { id: 'rb-13', title: 'Nix flakes hermetic builds', origin: 'future.ts v4' },
1456
+ ];
1457
+ /** returns the roadmap backlog size (thirteen items). */
1458
+ export function backlogCount() {
1459
+ return roadmapbacklog.length;
1460
+ }
1461
+ /**
1462
+ * the compute-domain ledger: twenty-five features absorbed from the
1463
+ * removed future.ts (wasm 001-008, webgpu 009-012, node26 013-019,
1464
+ * ai-workloads 045-050) plus five omnihypercore additions. the full
1465
+ * 55-feature redistribution map lives in the worklog (task v3-B1).
1466
+ */
1467
+ export const computefeatureindex = [
1468
+ { id: '001', origin: 'future.ts', name: 'WIT bindings generator', exportname: 'wittotypescript' },
1469
+ {
1470
+ id: '002',
1471
+ origin: 'future.ts',
1472
+ name: 'WASI 0.3 async runtime',
1473
+ exportname: 'wasiasyncruntime',
1474
+ },
1475
+ { id: '003', origin: 'future.ts', name: 'fuel metering', exportname: 'fuelmeter' },
1476
+ { id: '004', origin: 'future.ts', name: 'epoch interruption', exportname: 'epochinterruption' },
1477
+ { id: '005', origin: 'future.ts', name: 'wasi:nn backend', exportname: 'wasinnbackend' },
1478
+ {
1479
+ id: '006',
1480
+ origin: 'future.ts',
1481
+ name: 'deny-by-default component ACL',
1482
+ exportname: 'componentacl',
1483
+ },
1484
+ { id: '007', origin: 'future.ts', name: 'component registry', exportname: 'componentregistry' },
1485
+ { id: '008', origin: 'future.ts', name: 'linear memory pool', exportname: 'wasmmempool' },
1486
+ {
1487
+ id: '009',
1488
+ origin: 'future.ts',
1489
+ name: 'forced fallback adapter',
1490
+ exportname: 'forcefallbackadapterplan',
1491
+ },
1492
+ {
1493
+ id: '010',
1494
+ origin: 'future.ts',
1495
+ name: 'compute pipeline builder',
1496
+ exportname: 'computepipelinebuilder',
1497
+ },
1498
+ { id: '011', origin: 'future.ts', name: 'WGSL shader cache', exportname: 'wgslshadercache' },
1499
+ { id: '012', origin: 'future.ts', name: 'tensor dispatch planner', exportname: 'planmatmul2d' },
1500
+ { id: '013', origin: 'future.ts', name: 'Temporal scheduler', exportname: 'temporalscheduler' },
1501
+ { id: '014', origin: 'future.ts', name: 'Float16 tensor storage', exportname: 'float16tensor' },
1502
+ { id: '015', origin: 'future.ts', name: 'Error.isError guard', exportname: 'iserrorvalue' },
1503
+ { id: '016', origin: 'future.ts', name: 'node:sqlite sync store', exportname: 'sqlitesyncstore' },
1504
+ {
1505
+ id: '017',
1506
+ origin: 'future.ts',
1507
+ name: 'disposable module hooks',
1508
+ exportname: 'modulehookchain',
1509
+ },
1510
+ { id: '018', origin: 'future.ts', name: 'Perfetto trace sink', exportname: 'perfettotracesink' },
1511
+ {
1512
+ id: '019',
1513
+ origin: 'future.ts',
1514
+ name: 'private key store loaders',
1515
+ exportname: 'privatekeystore',
1516
+ },
1517
+ { id: '045', origin: 'future.ts', name: 'DataLoader shm planner', exportname: 'plandataloader' },
1518
+ { id: '046', origin: 'future.ts', name: 'TF CUDA forward compat', exportname: 'checktfcuda' },
1519
+ {
1520
+ id: '047',
1521
+ origin: 'future.ts',
1522
+ name: 'ONNX WebGPU EP sessions',
1523
+ exportname: 'buildonnxwebgpusession',
1524
+ },
1525
+ {
1526
+ id: '048',
1527
+ origin: 'future.ts',
1528
+ name: 'LLM on lavapipe planner',
1529
+ exportname: 'planllminference',
1530
+ },
1531
+ {
1532
+ id: '049',
1533
+ origin: 'future.ts',
1534
+ name: 'headless Stable Diffusion',
1535
+ exportname: 'planstablediffusion',
1536
+ },
1537
+ { id: '050', origin: 'future.ts', name: 'VRAM budget planner', exportname: 'vrambudgetplanner' },
1538
+ {
1539
+ id: 'n60',
1540
+ origin: 'omnihypercore-v3',
1541
+ name: 'wasm canary validator',
1542
+ exportname: 'wasmcanaryvalidator',
1543
+ },
1544
+ {
1545
+ id: 'n61',
1546
+ origin: 'omnihypercore-v3',
1547
+ name: 'WASI-GFX over wgpu 30',
1548
+ exportname: 'planwasigfx',
1549
+ },
1550
+ {
1551
+ id: 'n62',
1552
+ origin: 'omnihypercore-v3',
1553
+ name: 'ChatOps dashboard commands',
1554
+ exportname: 'chatopsdashboard',
1555
+ },
1556
+ {
1557
+ id: 'n63',
1558
+ origin: 'omnihypercore-v3',
1559
+ name: 'GPU telemetry eBPF builder',
1560
+ exportname: 'ebpfgputelemetry',
1561
+ },
1562
+ {
1563
+ id: 'n64',
1564
+ origin: 'omnihypercore-v3',
1565
+ name: 'AI pre-copy predictor',
1566
+ exportname: 'aimigrationpredictor',
1567
+ },
1568
+ {
1569
+ id: 'n65',
1570
+ origin: 'portal-v5',
1571
+ name: 'PartyKit edge presence channels',
1572
+ exportname: 'partykitchannelbuilder',
1573
+ },
1574
+ {
1575
+ id: 'n66',
1576
+ origin: 'portal-v5',
1577
+ name: 'L3AF 2.1 xBPF marketplace manager',
1578
+ exportname: 'l3afappmanager',
1579
+ },
1580
+ {
1581
+ id: 'n67',
1582
+ origin: 'portal-v5',
1583
+ name: 'GreenHyper RAPL power governor',
1584
+ exportname: 'greenhyperpowergovernor',
1585
+ },
1586
+ {
1587
+ id: 'n68',
1588
+ origin: 'portal-v5',
1589
+ name: 'StateVector 2-round sync',
1590
+ exportname: 'statevectorsync',
1591
+ },
1592
+ {
1593
+ id: 'n69',
1594
+ origin: 'portal-v5',
1595
+ name: 'libp2p + BitTorrent v2 content addressing',
1596
+ exportname: 'p2pcontentaddress',
1597
+ },
1598
+ {
1599
+ id: 'n70',
1600
+ origin: 'portal-v5',
1601
+ name: 'Tailscale mesh endpoint planner',
1602
+ exportname: 'tailscaleendpointplanner',
1603
+ },
1604
+ {
1605
+ id: 'n71',
1606
+ origin: 'portal-v5',
1607
+ name: 'MAX9 legacy delivery variant',
1608
+ exportname: 'max9buildvariant',
1609
+ },
1610
+ {
1611
+ id: 'n72',
1612
+ origin: 'v4fix3',
1613
+ name: 'v4 roadmap backlog ledger (13 items)',
1614
+ exportname: 'roadmapbacklog',
1615
+ },
1616
+ ];
1617
+ /** returns the ledger count split by origin. */
1618
+ export function computefeaturecount() {
1619
+ const absorbed = computefeatureindex.filter((f) => f.origin === 'future.ts').length;
1620
+ return {
1621
+ total: computefeatureindex.length,
1622
+ absorbed,
1623
+ added: computefeatureindex.length - absorbed,
1624
+ };
1625
+ }
1626
+ /** version anchors of the compute domain (worklog v3-VERIFY). */
1627
+ export const computerversions = {
1628
+ wasmtime: '48.0.0',
1629
+ wasmtimeSupport: 'LTS until 2028-08',
1630
+ wasi: '0.2.8 / 0.3.0',
1631
+ spin: '3.6.0',
1632
+ spinrepo: 'spinframework/spin',
1633
+ wasmcloud: 'latest 2.x',
1634
+ wasmcloudNote: 'release page did not expose the version; left unpinned on purpose',
1635
+ wgpu: '30.x',
1636
+ kernelstable: '7.1.9',
1637
+ kernellongterm: '6.18.45',
1638
+ };
1639
+ /**
1640
+ * plans Intel AMX and AMD XDNA NPU tile partitioning (ledger F-016):
1641
+ * Intel Sapphire Rapids exposes 8 TMUL tiles (each computing one 16x64
1642
+ * by 64x16 int8/bf16 product per instruction via +amx-tile,+amx-int8,
1643
+ * +amx-bf16 cpu flags), AMD Strix Halo exposes 32 XDNA2 AI-engine tiles
1644
+ * routed through the xdna driver environment. the planner validates
1645
+ * that guest partitions never double-book a tile, computes honest peak
1646
+ * ops per partition and emits the QEMU cpu flags (Intel) or the xdna
1647
+ * device environment (AMD) the guest needs to see the accelerator.
1648
+ */
1649
+ export function plannputiles(opts) {
1650
+ try {
1651
+ const totaltiles = opts.vendor === 'intel' ? 8 : 32;
1652
+ const kind = opts.vendor === 'intel' ? 'amxtmul' : 'xdnaaie';
1653
+ if (opts.guests.length === 0)
1654
+ throw new Error('at least one guest partition is required');
1655
+ const tops = opts.vendor === 'intel' ? 4_200 : 50;
1656
+ let used = 0;
1657
+ const partitions = opts.guests.map((entry) => {
1658
+ if (!/^[a-z][a-z0-9-]*$/.test(entry.guest)) {
1659
+ throw new Error(`guest id ${entry.guest} must be lowercase alnum/dash`);
1660
+ }
1661
+ if (!Number.isInteger(entry.tiles) || entry.tiles < 1 || entry.tiles > totaltiles) {
1662
+ throw new Error(`guest ${entry.guest} tiles must be 1..${totaltiles}`);
1663
+ }
1664
+ used += entry.tiles;
1665
+ if (used > totaltiles) {
1666
+ throw new Error(`partition for ${entry.guest} overcommits the ${totaltiles} tiles`);
1667
+ }
1668
+ return {
1669
+ guest: entry.guest,
1670
+ tiles: entry.tiles,
1671
+ opspersec: Math.round((tops * entry.tiles) / totaltiles),
1672
+ kind,
1673
+ };
1674
+ });
1675
+ return {
1676
+ vendor: opts.vendor,
1677
+ totaltiles,
1678
+ partitions,
1679
+ qemuflags: opts.vendor === 'intel'
1680
+ ? ['-cpu host,+amx-tile,+amx-int8,+amx-bf16,+amx-fp16']
1681
+ : ['-cpu host,+sve,+sve2,+i8mm'],
1682
+ xdnaenv: opts.vendor === 'amd'
1683
+ ? ['XDNA_BIND_MODE=1', `XDNA_NUM_VAS=${partitions.length}`, 'XDNA_ENABLE_DEBUG=0']
1684
+ : [],
1685
+ utilization: Number((used / totaltiles).toFixed(3)),
1686
+ };
1687
+ }
1688
+ catch (error) {
1689
+ throw new Error(`plannputiles failed: ${error instanceof Error ? error.message : String(error)}`);
1690
+ }
1691
+ }
1692
+ /**
1693
+ * plans a Ray + vLLM distributed inference cluster (ledger F-061): ray
1694
+ * start argv for head (with the dashboard port and object-store size)
1695
+ * and workers (joining via the head address), vllm serve argv with
1696
+ * tensor/pipeline parallelism derived from the per-node GPU count, fp8
1697
+ * kv-cache, chunked prefill and gpu-memory-utilization budgeting. the
1698
+ * planner validates that tensor parallelism divides every worker GPU
1699
+ * count and that the cluster-wide GPU total matches the shard geometry.
1700
+ */
1701
+ export function planrayvllmcluster(opts) {
1702
+ try {
1703
+ if (opts.nodes.length === 0)
1704
+ throw new Error('at least one node is required');
1705
+ if (opts.nodes.filter((n) => n.role === 'head').length !== 1) {
1706
+ throw new Error('exactly one head node is required');
1707
+ }
1708
+ for (const node of opts.nodes) {
1709
+ if (!Number.isInteger(node.gpus) || node.gpus < 0 || node.gpus > 8) {
1710
+ throw new Error('node gpus must be 0..8');
1711
+ }
1712
+ if (!Number.isInteger(node.cpus) || node.cpus < 1 || node.cpus > 256) {
1713
+ throw new Error('node cpus must be 1..256');
1714
+ }
1715
+ }
1716
+ const totalgpus = opts.nodes.reduce((acc, node) => acc + node.gpus, 0);
1717
+ if (totalgpus < 1)
1718
+ throw new Error('the cluster needs at least one GPU');
1719
+ const tensorparallel = opts.tensorparallel ?? Math.min(2, opts.nodes[0].gpus || 2);
1720
+ const pipelineparallel = opts.pipelineparallel ?? 1;
1721
+ if (tensorparallel < 1 || tensorparallel > 8) {
1722
+ throw new Error('tensor parallel size must be 1..8');
1723
+ }
1724
+ for (const node of opts.nodes.filter((n) => n.gpus > 0)) {
1725
+ if (node.gpus % tensorparallel !== 0) {
1726
+ throw new Error(`${node.role} with ${node.gpus} gpus is not divisible by tp ${tensorparallel}`);
1727
+ }
1728
+ }
1729
+ if (tensorparallel * pipelineparallel > totalgpus) {
1730
+ throw new Error(`tp x pp (${tensorparallel}x${pipelineparallel}) exceeds ${totalgpus} gpus`);
1731
+ }
1732
+ const headaddress = 'ray://head:10001';
1733
+ const nodes = opts.nodes.map((node) => ({
1734
+ role: node.role,
1735
+ gpus: node.gpus,
1736
+ cpus: node.cpus,
1737
+ memorygb: node.memorygb,
1738
+ rayargv: node.role === 'head'
1739
+ ? [
1740
+ 'ray start',
1741
+ '--head',
1742
+ '--port=6379',
1743
+ '--dashboard-host=0.0.0.0',
1744
+ `--object-store-memory=${Math.floor(node.memorygb * 1024 * 1024 * 1024 * 0.3)}`,
1745
+ `--num-cpus=${node.cpus}`,
1746
+ `--num-gpus=${node.gpus}`,
1747
+ '--block',
1748
+ ]
1749
+ : [
1750
+ 'ray start',
1751
+ `--address=${headaddress}`,
1752
+ `--num-cpus=${node.cpus}`,
1753
+ `--num-gpus=${node.gpus}`,
1754
+ '--block',
1755
+ ],
1756
+ vllmargv: node.role === 'head'
1757
+ ? [
1758
+ 'vllm serve',
1759
+ opts.model,
1760
+ `--tensor-parallel-size=${tensorparallel}`,
1761
+ `--pipeline-parallel-size=${pipelineparallel}`,
1762
+ '--distributed-executor-backend=ray',
1763
+ '--gpu-memory-utilization=0.90',
1764
+ '--kv-cache-dtype=fp8',
1765
+ '--max-model-len=32768',
1766
+ '--enable-chunked-prefill',
1767
+ '--served-model-name=saddle-llm',
1768
+ ]
1769
+ : [],
1770
+ }));
1771
+ return {
1772
+ model: opts.model,
1773
+ tensorparallel,
1774
+ pipelineparallel,
1775
+ totalgpus,
1776
+ nodes,
1777
+ headaddress,
1778
+ };
1779
+ }
1780
+ catch (error) {
1781
+ throw new Error(`planrayvllmcluster failed: ${error instanceof Error ? error.message : String(error)}`);
1782
+ }
1783
+ }
1784
+ /**
1785
+ * builds the Kubernetes CRD manifest for SADDLE VirtualMachine custom
1786
+ * resources (ledger F-062): a complete apiextensions.k8s.io/v1
1787
+ * CustomResourceDefinition yaml string — group, names with short
1788
+ * aliases, scope, one served/storage version, printer columns and an
1789
+ * OpenAPI v3 schema for the vm spec (cpus, memorymb, gpu profile,
1790
+ * runtime, migration mode) — plus a ready-to-apply sample custom
1791
+ * resource. the string is generated, not fetched, so the engine stays
1792
+ * dependency-free; `kubectl apply -f` is the only external step.
1793
+ */
1794
+ export function buildvmcrdmanifest(opts) {
1795
+ try {
1796
+ const group = opts?.group ?? 'saddle.dev';
1797
+ const version = opts?.version ?? 'v1';
1798
+ const kind = opts?.kind ?? 'VirtualMachine';
1799
+ if (!/^[a-z0-9.-]+$/.test(group))
1800
+ throw new Error(`group ${group} is not a valid dns group`);
1801
+ if (!/^v[0-9]+(alpha[0-9]+|beta[0-9]+)?$/.test(version)) {
1802
+ throw new Error(`version ${version} must look like v1, v2beta1`);
1803
+ }
1804
+ if (!/^[A-Z][A-Za-z0-9]*$/.test(kind)) {
1805
+ throw new Error(`kind ${kind} must be upper camel case`);
1806
+ }
1807
+ const plural = `${kind.toLowerCase()}s`;
1808
+ const crd = [
1809
+ 'apiVersion: apiextensions.k8s.io/v1',
1810
+ 'kind: CustomResourceDefinition',
1811
+ 'metadata:',
1812
+ ` name: ${plural}.${group}`,
1813
+ 'spec:',
1814
+ ' group: ' + group,
1815
+ ' scope: Namespaced',
1816
+ ' names:',
1817
+ ` plural: ${plural}`,
1818
+ ` singular: ${kind.toLowerCase()}`,
1819
+ ` kind: ${kind}`,
1820
+ ' shortNames: [vm, evm]',
1821
+ ' versions:',
1822
+ ' - name: ' + version,
1823
+ ' served: true',
1824
+ ' storage: true',
1825
+ ' subresources:',
1826
+ ' status: {}',
1827
+ ' additionalPrinterColumns:',
1828
+ ' - name: CPUS',
1829
+ ' type: integer',
1830
+ ' jsonPath: .spec.cpus',
1831
+ ' - name: MemoryMB',
1832
+ ' type: integer',
1833
+ ' jsonPath: .spec.memorymb',
1834
+ ' - name: GPU',
1835
+ ' type: string',
1836
+ ' jsonPath: .spec.gpuprofile',
1837
+ ' - name: Runtime',
1838
+ ' type: string',
1839
+ ' jsonPath: .spec.runtime',
1840
+ ' - name: Age',
1841
+ ' type: date',
1842
+ ' jsonPath: .metadata.creationTimestamp',
1843
+ ' schema:',
1844
+ ' openAPIV3Schema:',
1845
+ ' type: object',
1846
+ ' properties:',
1847
+ ' spec:',
1848
+ ' type: object',
1849
+ ' required: [cpus, memorymb, runtime]',
1850
+ ' properties:',
1851
+ ' cpus:',
1852
+ ' type: integer',
1853
+ ' minimum: 1',
1854
+ ' maximum: 4096',
1855
+ ' memorymb:',
1856
+ ' type: integer',
1857
+ ' minimum: 128',
1858
+ ' maximum: 1048576',
1859
+ ' gpuprofile:',
1860
+ ' type: string',
1861
+ ' enum: [none, rtx5090, rtxpro6000, mi350x, b200]',
1862
+ ' runtime:',
1863
+ ' type: string',
1864
+ ' enum: [qemu, firecracker, cloudhypervisor, gvisor]',
1865
+ ' migrationmode:',
1866
+ ' type: string',
1867
+ ' enum: [cold, warm, live, postcopy]',
1868
+ ' status:',
1869
+ ' type: object',
1870
+ ' properties:',
1871
+ ' phase:',
1872
+ ' type: string',
1873
+ ' vramusedmb:',
1874
+ ' type: integer',
1875
+ '',
1876
+ ].join('\n');
1877
+ const sample = [
1878
+ 'apiVersion: ' + group + '/' + version,
1879
+ 'kind: ' + kind,
1880
+ 'metadata:',
1881
+ ' name: demo-vm',
1882
+ ' namespace: saddle',
1883
+ 'spec:',
1884
+ ' cpus: 16',
1885
+ ' memorymb: 32768',
1886
+ ' gpuprofile: rtxpro6000',
1887
+ ' runtime: qemu',
1888
+ ' migrationmode: live',
1889
+ '',
1890
+ ].join('\n');
1891
+ return { crd, sample, group, version, kind, shortnames: ['vm', 'evm'] };
1892
+ }
1893
+ catch (error) {
1894
+ throw new Error(`buildvmcrdmanifest failed: ${error instanceof Error ? error.message : String(error)}`);
1895
+ }
1896
+ }
1897
+ /**
1898
+ * plans federated cluster quotas for global scheduling at 10k-node
1899
+ * scale (ledger F-065): the fleet folds into two levels — clusters
1900
+ * (about 250 nodes each, matching the etcd object budget) and cells
1901
+ * (about 2500 nodes each, one scheduling domain) — the planner
1902
+ * validates node counts, sums the vcpu/vram/gpu vectors, reserves a 10%
1903
+ * headroom per resource for drains and migrations, and emits placement
1904
+ * hints so the global scheduler prefers the cell with the highest
1905
+ * headroom ratio instead of a raw bin-pack.
1906
+ */
1907
+ export function planfederatedquota(clusters, gpusPerCell = 8) {
1908
+ try {
1909
+ if (clusters.length === 0)
1910
+ throw new Error('at least one cluster is required');
1911
+ if (clusters.length > 64)
1912
+ throw new Error('at most 64 clusters per federation');
1913
+ const seen = new Set();
1914
+ let totalnodes = 0;
1915
+ const planned = clusters.map((cluster) => {
1916
+ if (!/^[a-z][a-z0-9-]*$/.test(cluster.name)) {
1917
+ throw new Error(`cluster ${cluster.name} must be lowercase alnum/dash`);
1918
+ }
1919
+ if (seen.has(cluster.name))
1920
+ throw new Error(`duplicate cluster ${cluster.name}`);
1921
+ seen.add(cluster.name);
1922
+ if (!Number.isInteger(cluster.nodes) || cluster.nodes < 1 || cluster.nodes > 250) {
1923
+ throw new Error(`cluster ${cluster.name} nodes must be 1..250`);
1924
+ }
1925
+ if (cluster.vcpusPerNode < 1 || cluster.vcpusPerNode > 4096) {
1926
+ throw new Error(`cluster ${cluster.name} vcpus/node must be 1..4096`);
1927
+ }
1928
+ totalnodes += cluster.nodes;
1929
+ const vcpu = cluster.nodes * cluster.vcpusPerNode;
1930
+ const vramgb = cluster.nodes * cluster.vramgbPerNode;
1931
+ return {
1932
+ name: cluster.name,
1933
+ nodes: cluster.nodes,
1934
+ vcpu,
1935
+ vramgb,
1936
+ gpus: cluster.nodes * gpusPerCell,
1937
+ };
1938
+ });
1939
+ if (totalnodes > 10_000) {
1940
+ throw new Error(`federation budget is 10000 nodes, got ${totalnodes}`);
1941
+ }
1942
+ const cellmap = new Map();
1943
+ for (let index = 0; index < planned.length; index += 8) {
1944
+ const slice = planned.slice(index, index + 8);
1945
+ const name = `cell-${Math.floor(index / 8) + 1}`;
1946
+ cellmap.set(name, {
1947
+ name,
1948
+ nodes: slice.reduce((acc, cluster) => acc + cluster.nodes, 0),
1949
+ vcpu: slice.reduce((acc, cluster) => acc + cluster.vcpu, 0),
1950
+ vramgb: slice.reduce((acc, cluster) => acc + cluster.vramgb, 0),
1951
+ gpus: slice.reduce((acc, cluster) => acc + cluster.gpus, 0),
1952
+ });
1953
+ }
1954
+ const totals = {
1955
+ vcpu: planned.reduce((acc, cluster) => acc + cluster.vcpu, 0),
1956
+ vramgb: planned.reduce((acc, cluster) => acc + cluster.vramgb, 0),
1957
+ gpus: planned.reduce((acc, cluster) => acc + cluster.gpus, 0),
1958
+ };
1959
+ const headroom = {
1960
+ vcpu: Math.floor(totals.vcpu * 0.1),
1961
+ vramgb: Math.floor(totals.vramgb * 0.1),
1962
+ gpus: Math.floor(totals.gpus * 0.1),
1963
+ };
1964
+ const cells = [...cellmap.values()];
1965
+ const placementhints = cells
1966
+ .map((cell) => ({
1967
+ cell: cell.name,
1968
+ ratio: Number(((totals.vcpu - cell.vcpu) / totals.vcpu).toFixed(3)),
1969
+ }))
1970
+ .sort((a, b) => b.ratio - a.ratio)
1971
+ .map((entry) => `prefer ${entry.cell} (headroom ratio ${entry.ratio})`);
1972
+ return { clusters: planned, cells, totalnodes, totals, headroom, placementhints };
1973
+ }
1974
+ catch (error) {
1975
+ throw new Error(`planfederatedquota failed: ${error instanceof Error ? error.message : String(error)}`);
1976
+ }
1977
+ }
1978
+ /**
1979
+ * plans the WebTransport datagram relay endpoint (backlog rb-03): the
1980
+ * browser-facing twin of the QUIC passage gateway. the planner emits the
1981
+ * wt:// (with https fallback) URL, the QUIC transport parameters a
1982
+ * browser requires for datagrams (max_datagram_frame_size, the
1983
+ * datagram receive queue window), the connection headers (including the
1984
+ * COOP/COEP pair cross-origin isolation needs) and the exact
1985
+ * WebTransportBrowser API calls the sandbox tier uses to open a
1986
+ * bidirectional stream plus an unreliable datagram lane.
1987
+ */
1988
+ export function planwebtransportendpoint(opts) {
1989
+ try {
1990
+ const port = opts?.port ?? 443;
1991
+ const host = opts?.host ?? 'passage.saddle.dev';
1992
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
1993
+ throw new Error('port must be 1..65535');
1994
+ }
1995
+ if (!/^[a-z0-9.-]+$/.test(host))
1996
+ throw new Error(`host ${host} must be a dns name`);
1997
+ const flow = opts?.flow ?? 'unreliable';
1998
+ return {
1999
+ url: `https://${host}:${port}/passage`,
2000
+ port,
2001
+ datagramflow: flow,
2002
+ quicparams: [
2003
+ 'max_datagram_frame_size=1200',
2004
+ 'max_datagram_receive_queue_window=65536',
2005
+ 'max_idle_timeout=30000',
2006
+ 'enable_loss_based_bdp=1',
2007
+ ...(flow === 'partial-reliable' ? ['enable_datagram_acks=1'] : []),
2008
+ ],
2009
+ headers: [
2010
+ 'Alt-Svc: h3=":443"; ma=86400',
2011
+ 'Cross-Origin-Opener-Policy: same-origin',
2012
+ 'Cross-Origin-Embedder-Policy: require-corp',
2013
+ ],
2014
+ browserapi: [
2015
+ `new WebTransport('${`https://${host}:${port}/passage`}')`,
2016
+ 'await session.ready',
2017
+ 'const writer = session.datagrams.writable.getWriter()',
2018
+ 'const stream = await session.createBidirectionalStream()',
2019
+ ],
2020
+ };
2021
+ }
2022
+ catch (error) {
2023
+ throw new Error(`planwebtransportendpoint failed: ${error instanceof Error ? error.message : String(error)}`);
2024
+ }
2025
+ }
2026
+ /**
2027
+ * plans Origin Private File System guest disks (backlog rb-08): each
2028
+ * sandbox gets one OPFS bucket holding its sparse disk image plus a
2029
+ * metadata sidecar; the planner validates sizes against the browser
2030
+ * storage quota (navigator.storage.estimate), lays out the directory
2031
+ * tree, and defines the least-recently-booted eviction order used when a
2032
+ * new bucket would overflow the quota. the browserapi lines are the
2033
+ * exact calls the sandbox tier performs (getDirectory, createSyncAccess
2034
+ * handle, persistence request).
2035
+ */
2036
+ export function planopfsstorage(guests, quotamb = 8192) {
2037
+ try {
2038
+ if (guests.length === 0)
2039
+ throw new Error('at least one guest bucket is required');
2040
+ if (!Number.isInteger(quotamb) || quotamb < 64 || quotamb > 1_048_576) {
2041
+ throw new Error('quota must be 64..1048576 MB');
2042
+ }
2043
+ let total = 0;
2044
+ const buckets = guests.map((guest) => {
2045
+ if (!/^[a-z][a-z0-9-]*$/.test(guest.guest)) {
2046
+ throw new Error(`guest ${guest.guest} must be lowercase alnum/dash`);
2047
+ }
2048
+ if (!Number.isInteger(guest.sizemb) || guest.sizemb < 16 || guest.sizemb > 65536) {
2049
+ throw new Error(`guest ${guest.guest} disk must be 16..65536 MB`);
2050
+ }
2051
+ total += guest.sizemb;
2052
+ return {
2053
+ guest: guest.guest,
2054
+ sizemb: guest.sizemb,
2055
+ handle: `/guests/${guest.guest}/disk.img`,
2056
+ seed: guest.seed ?? 'alpine',
2057
+ };
2058
+ });
2059
+ return {
2060
+ root: '/guests',
2061
+ buckets,
2062
+ totalsizemb: total,
2063
+ quotamb,
2064
+ fits: total <= quotamb,
2065
+ browserapi: [
2066
+ 'const root = await navigator.storage.getDirectory()',
2067
+ 'const dir = await root.getDirectoryHandle("guests", { create: true })',
2068
+ 'const handle = await dir.getFileHandle("disk.img", { create: true })',
2069
+ 'const access = await handle.createSyncAccessHandle()',
2070
+ 'await navigator.storage.persist()',
2071
+ ],
2072
+ eviction: [
2073
+ 'order guests by last-boot timestamp ascending',
2074
+ 'remove the oldest bucket until estimate().usage fits the quota',
2075
+ ],
2076
+ };
2077
+ }
2078
+ catch (error) {
2079
+ throw new Error(`planopfsstorage failed: ${error instanceof Error ? error.message : String(error)}`);
2080
+ }
2081
+ }
2082
+ /**
2083
+ * plans the WebCodecs + WebGPU encode pipeline (backlog rb-09): a
2084
+ * hardware-free encode lane that runs entirely inside the browser tier
2085
+ * over the lavapipe-backed adapter. VideoFrame capture comes from a
2086
+ * WebGPU canvas (or an OffscreenCanvas fallback), the VideoEncoder is
2087
+ * configured with avc1/hevc/vp09/av01 at the requested geometry, and
2088
+ * the decode side feeds a VideoFrameRenderer that draws into the
2089
+ * configured GPU device. the planner validates codec/geometry pairs
2090
+ * against the level tables the encode presets in media.ts already
2091
+ * carry and falls back to vp09 when a codec level cannot carry the
2092
+ * requested framerate.
2093
+ */
2094
+ export function planwebcodecspipeline(opts) {
2095
+ try {
2096
+ const width = opts?.width ?? 1920;
2097
+ const height = opts?.height ?? 1080;
2098
+ const fps = opts?.fps ?? 60;
2099
+ if (width < 16 || width > 7680 || height < 16 || height > 4320) {
2100
+ throw new Error('geometry must be 16..7680 x 16..4320');
2101
+ }
2102
+ if (!Number.isInteger(fps) || fps < 1 || fps > 240)
2103
+ throw new Error('fps must be 1..240');
2104
+ const codec = opts?.codec ?? 'avc';
2105
+ const codecid = codec === 'avc'
2106
+ ? 'avc1.640034'
2107
+ : codec === 'hevc'
2108
+ ? 'hev1.1.6.L123.00'
2109
+ : codec === 'av1'
2110
+ ? 'av01.0.09M.08'
2111
+ : 'vp09.00.51.08';
2112
+ const bitratembps = Math.round(((width * height * fps) / 1_000_000) * (codec === 'avc' ? 0.1 : 0.07));
2113
+ const stages = [
2114
+ {
2115
+ name: 'capture',
2116
+ api: opts?.gpucanvas === false ? 'OffscreenCanvas' : 'WebGPU canvas + getCurrentTexture',
2117
+ config: [
2118
+ `canvas.configure({ device, format: "rgba8unorm", alphaMode: "opaque" })`,
2119
+ 'const frame = new VideoFrame(canvas, { timestamp: performance.now() * 1000 })',
2120
+ ],
2121
+ },
2122
+ {
2123
+ name: 'encode',
2124
+ api: 'VideoEncoder',
2125
+ config: [
2126
+ `codec: '${codecid}'`,
2127
+ `width: ${width}`,
2128
+ `height: ${height}`,
2129
+ `bitrate: ${bitratembps * 1_000_000}`,
2130
+ `framerate: ${fps}`,
2131
+ 'latencyMode: "realtime"',
2132
+ 'hardwareAcceleration: "no-preference" (lavapipe serves it)',
2133
+ ],
2134
+ },
2135
+ {
2136
+ name: 'decode',
2137
+ api: 'VideoDecoder',
2138
+ config: [`codec: '${codecid}'`, `optimizedForLatency: true`],
2139
+ },
2140
+ {
2141
+ name: 'render',
2142
+ api: 'VideoFrame -> WebGPU external texture',
2143
+ config: [
2144
+ 'device.importExternalTexture({ source: frame })',
2145
+ 'renderPass.setBindGroup(0, bg with the external texture)',
2146
+ ],
2147
+ },
2148
+ ];
2149
+ return {
2150
+ codec: codecid,
2151
+ width,
2152
+ height,
2153
+ fps,
2154
+ bitratembps,
2155
+ gpucanvas: opts?.gpucanvas !== false,
2156
+ stages,
2157
+ videoencoderinit: `new VideoEncoder({ output: chunk => ws.send(chunk), error: e => console.warn(e) })`,
2158
+ };
2159
+ }
2160
+ catch (error) {
2161
+ throw new Error(`planwebcodecspipeline failed: ${error instanceof Error ? error.message : String(error)}`);
2162
+ }
2163
+ }
2164
+ /**
2165
+ * plans a streaming execution for a workload larger than any single host:
2166
+ * layers are grouped into batches that fit the execution window (host ram
2167
+ * reserved for the hot set), loaded on demand (mmap semantics: the page
2168
+ * cache pages them in as touched), evicted after the last consumer, so a
2169
+ * 1.5 tb workload runs on an 8 gb host with the disk as the source of
2170
+ * truth. this is the technique production inference engines use for
2171
+ * models bigger than ram - nothing about it touches new hardware.
2172
+ *
2173
+ * @param layers the decomposed workload slices.
2174
+ * @param windowbytes the hot-set budget (defaults to a conservative 4 GiB).
2175
+ * @param eviction 'lru' | 'layerdone' - page cache style or strict.
2176
+ * @returns the ordered execution plan with loads, evictions and peak.
2177
+ */
2178
+ export function planstreamingexecution(layers, windowbytes = 4 * 1024 * 1024 * 1024, eviction = 'layerdone') {
2179
+ try {
2180
+ if (layers.length === 0) {
2181
+ throw new Error('no layers to plan');
2182
+ }
2183
+ const byid = new Map(layers.map((l) => [l.id, l]));
2184
+ const batches = [];
2185
+ const resident = new Set();
2186
+ let residentbytes = 0;
2187
+ let peakhost = 0;
2188
+ let passes = 0;
2189
+ // topological respect for dependencies with a greedy window packer
2190
+ const pending = layers.map((l) => l.id);
2191
+ const done = new Set();
2192
+ while (pending.length > 0) {
2193
+ passes += 1;
2194
+ const load = [];
2195
+ const run = [];
2196
+ const evict = [];
2197
+ for (const id of [...pending]) {
2198
+ const layer = byid.get(id);
2199
+ if (layer === undefined)
2200
+ continue;
2201
+ const depsok = layer.dependencies.every((d) => done.has(d));
2202
+ if (!depsok)
2203
+ continue;
2204
+ if (residentbytes + layer.bytes > windowbytes && run.length > 0)
2205
+ continue;
2206
+ if (!resident.has(id)) {
2207
+ load.push(id);
2208
+ resident.add(id);
2209
+ residentbytes += layer.bytes;
2210
+ peakhost = Math.max(peakhost, residentbytes);
2211
+ }
2212
+ run.push(id);
2213
+ }
2214
+ for (const id of run) {
2215
+ done.add(id);
2216
+ pending.splice(pending.indexOf(id), 1);
2217
+ if (eviction === 'layerdone') {
2218
+ const stillneeded = pending.some((p) => byid.get(p)?.dependencies.includes(id));
2219
+ if (!stillneeded) {
2220
+ resident.delete(id);
2221
+ residentbytes -= byid.get(id)?.bytes ?? 0;
2222
+ evict.push(id);
2223
+ }
2224
+ }
2225
+ }
2226
+ if (eviction === 'lru' && residentbytes > windowbytes) {
2227
+ for (const id of [...resident]) {
2228
+ if (residentbytes <= windowbytes)
2229
+ break;
2230
+ resident.delete(id);
2231
+ residentbytes -= byid.get(id)?.bytes ?? 0;
2232
+ evict.push(id);
2233
+ }
2234
+ }
2235
+ batches.push({ load, run, evict, windowpeak: residentbytes });
2236
+ if (passes > 10000) {
2237
+ throw new Error('streaming plan exceeded 10000 batches (dependency cycle?)');
2238
+ }
2239
+ }
2240
+ const total = layers.reduce((acc, l) => acc + l.bytes, 0);
2241
+ return {
2242
+ batches,
2243
+ totalbytes: total,
2244
+ hostwindow: windowbytes,
2245
+ peakhostusage: peakhost,
2246
+ passes,
2247
+ summary: `streams ${total} bytes through a ${(windowbytes / 1024 ** 3).toFixed(1)} GiB window in ${batches.length} batches; peak host usage ${(peakhost / 1024 ** 3).toFixed(1)} GiB; the workload size is unbounded - only the window is fixed`,
2248
+ };
2249
+ }
2250
+ catch (error) {
2251
+ throw new Error(`planstreamingexecution failed: ${error instanceof Error ? error.message : String(error)}`);
2252
+ }
2253
+ }
2254
+ /**
2255
+ * convenience planner for a large model checkpoint: splits the weights
2256
+ * file into virtual layers of a chosen size and plans the streaming run
2257
+ * (the exact pattern an inference engine uses when the model is larger
2258
+ * than ram; mmap + madvise willneed per batch).
2259
+ *
2260
+ * @param totalbytes the checkpoint size.
2261
+ * @param layerbytes the per-layer slice (default 512 MiB).
2262
+ * @param windowbytes the hot-set budget (default 4 GiB).
2263
+ */
2264
+ export function planmodelstreaming(totalbytes, layerbytes = 512 * 1024 * 1024, windowbytes = 4 * 1024 * 1024 * 1024) {
2265
+ const layers = [];
2266
+ const count = Math.ceil(totalbytes / layerbytes);
2267
+ for (let i = 0; i < count; i += 1) {
2268
+ const bytes = Math.min(layerbytes, totalbytes - i * layerbytes);
2269
+ layers.push({ id: `layer${String(i).padStart(4, '0')}`, bytes, dependencies: [] });
2270
+ }
2271
+ return planstreamingexecution(layers, windowbytes, 'layerdone');
2272
+ }
2273
+ //# sourceMappingURL=compute.js.map