@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,1628 @@
1
+ /**
2
+ * virtualization.ts — kernel level virtualization surface for saddle v6.
3
+ *
4
+ * the module merges four sources identified by the merge map (T7):
5
+ * - qemu-wrapper.ts: the full "turbo" qemu 11.1.0 argv builder with
6
+ * DiamondRapids cpu model, TDX and SEV-SNP guest objects, OVMF secure
7
+ * boot, io_uring drives and the venus virtio-gpu device
8
+ * - passage.ts: the network passage stack with six modes (direct, bridge,
9
+ * nat, overlayVxlan, zeroTrust, latencyOptimization) built on OVS
10
+ * 3.7.1, DPDK 26.07.0, XDP at 10 Mpps, libbpf 1.6.0 and cilium/ebpf
11
+ * v0.21.0, macvtap (bridge/vepa/private/passthrough), ipvlan (l2/l3/l3s),
12
+ * SR-IOV VF passthrough, WireGuard namespaces and io_uring ZCRX
13
+ * - mttg.ts: the cgroups v2 multi-tenant thread group controller (cpu.weight
14
+ * 1-10000, cpu.max quota/period/burst, cpuset, memory.high/max, io.weight,
15
+ * pids.max) with the EEVDF 6.6, BORE 0-39 and sched_ext 6.12 scheduler
16
+ * notes, PSI, DAMON and CRIU live migration context
17
+ * - mttggrid: the Mttg work-stealing grid ported from forge.cpp because
18
+ * architect.ts imports createGrid/MTTG_MAX that previously existed only
19
+ * in the C++ binary (gap flagged by the merge map)
20
+ *
21
+ * naming warning preserved from the map: MTTCG (qemu multi-thread TCG, one
22
+ * host thread per vCPU) and MTTG (multi-tenant thread groups, this file)
23
+ * are unrelated concepts with similar acronyms and must never be merged.
24
+ *
25
+ * qemu argv hierarchy documented across the repository: buildqemucmd in
26
+ * this file is the complete "turbo" argv (TDX/SEV/vfio romfile/venus);
27
+ * qemuargv in index.ts is the lean plan argv; qemuruntime.buildcommand in
28
+ * orchestrator.ts is the runtime strategy argv; qemu_argv in forge.cpp is
29
+ * the C++ emitter. all four stay, each with a different role.
30
+ *
31
+ * contexts (25): qemuopts, buildqemucmd, qemuversioncheck, passagemode,
32
+ * passagebridge, passagesriov, passagemacvtap, passageipvlan, passageoverlay,
33
+ * passagezerotrust, passagelatencyopt, ebpfprogram, tenantqos, cgrouproot,
34
+ * tenantcgroupbuilder, createtenant, cpumaxqos, eevdfinfo, boreinfo,
35
+ * schedextinfo, psidamoninfo, criumigration/checkpoint (the v3-B1 append:
36
+ * criu planner, file snapshot, uffd restore, diff snapshots, live
37
+ * migration), mttggrid, idmapped (v3-B1 kernel gap), virtualizationcore
38
+ * bridge (buildmemorybackendargs + kvmcapnames)
39
+ *
40
+ * patterns: builder (tenantcgroupbuilder), namespace modules as plain
41
+ * function groups. rules: lowercase identifiers, english jsdoc third
42
+ * person, no emoji, try/catch catcher on every fallible path, node:*
43
+ * built-ins only, never a hardcoded localhost address.
44
+ */
45
+
46
+ import { execFileSync } from 'node:child_process';
47
+ import { mkdirSync, writeFileSync } from 'node:fs';
48
+ import { availableParallelism, cpus } from 'node:os';
49
+ import { join } from 'node:path';
50
+
51
+ /** safe identifier validator: blocks shell metacharacters and path
52
+ * traversal sequences so user-provided names can never reach a shell
53
+ * or escape the intended filesystem scope. */
54
+ function issafeid(value: string, max = 64): boolean {
55
+ return (
56
+ typeof value === 'string' &&
57
+ value.length > 0 &&
58
+ value.length <= max &&
59
+ /^[A-Za-z0-9._-]+$/.test(value)
60
+ );
61
+ }
62
+
63
+ /** safe cgroup controller filename: no slashes, no dots-only, no traversal. */
64
+ function issafecgroupfile(value: string): boolean {
65
+ return (
66
+ typeof value === 'string' &&
67
+ value.length > 0 &&
68
+ value.length <= 128 &&
69
+ /^[A-Za-z0-9._-]+(\.\w+)+$|^[A-Za-z0-9._-]+$/.test(value)
70
+ );
71
+ }
72
+
73
+ /* ------------------------------------------------------------------ */
74
+ /* context: qemuopts (turbo wrapper input) */
75
+ /* ------------------------------------------------------------------ */
76
+
77
+ /** options accepted by the turbo qemu argv builder. */
78
+ export interface qemuopts {
79
+ readonly vcpu: number;
80
+ readonly memMB: number;
81
+ readonly cpuModel?: string;
82
+ readonly machine?: string;
83
+ readonly accel?: string;
84
+ readonly vfioPCI?: readonly string[];
85
+ readonly bridge?: string;
86
+ readonly monitorSock?: string;
87
+ readonly qmpSock?: string;
88
+ }
89
+
90
+ /* ------------------------------------------------------------------ */
91
+ /* context: buildqemucmd (qemu 11.1.0 full turbo argv) */
92
+ /* ------------------------------------------------------------------ */
93
+
94
+ /**
95
+ * builds the complete turbo qemu 11.1.0 argv. the default cpu model is
96
+ * DiamondRapids with host-phys-bits=true, hidden=1 and the NV43FIX
97
+ * hypervisor vendor id that keeps nvidia drivers alive inside the guest;
98
+ * the machine boots q35 with smm on and kernel-irqchip split; memory uses
99
+ * a preallocating ram backend bound to numa node 0; vfio devices carry
100
+ * romfile/rombar/x-vga and disable_idle_d3; the disk uses the io_uring
101
+ * aio engine; the virtio-gpu device enables the venus native context
102
+ * (qemu 11.x); the guest objects enable TDX (sept-ve-disabled) and
103
+ * SEV-SNP (cbitpos=51, reduced-phys-bits=1) confidential computing.
104
+ */
105
+ export function buildqemucmd(opts: qemuopts): readonly string[] {
106
+ try {
107
+ const cpumodel = opts.cpuModel ?? 'DiamondRapids';
108
+ const args: string[] = [
109
+ '/usr/bin/qemu-system-x86_64',
110
+ '-enable-kvm',
111
+ '-machine',
112
+ opts.machine ?? 'q35,smm=on,accel=kvm,kernel-irqchip=split',
113
+ '-cpu',
114
+ `${cpumodel},host-phys-bits=true,hidden=1,hv_vendor_id=NV43FIX,kvm=off,+avx512f,+avx512bw,+pdpe1gb`,
115
+ '-m',
116
+ String(opts.memMB),
117
+ '-smp',
118
+ `${opts.vcpu},sockets=1,cores=${Math.max(1, Math.floor(opts.vcpu / 2))},threads=2`,
119
+ '-object',
120
+ `memory-backend-ram,id=ram0,size=${opts.memMB}M,prealloc=yes,share=no`,
121
+ '-numa',
122
+ 'node,nodeid=0,memdev=ram0',
123
+ '-device',
124
+ 'virtio-balloon-pci,id=balloon0',
125
+ ];
126
+ if (opts.vfioPCI !== undefined) {
127
+ for (const bdf of opts.vfioPCI) {
128
+ args.push(
129
+ '-device',
130
+ `vfio-pci,host=${bdf},multifunction=on,romfile=/usr/share/kvm/vbios/${bdf}.rom,rombar=1,x-vga=on,disable_idle_d3=1`,
131
+ );
132
+ }
133
+ }
134
+ const bridge = opts.bridge ?? 'br0';
135
+ args.push(
136
+ '-netdev',
137
+ `bridge,br=${bridge},id=net0`,
138
+ '-device',
139
+ 'virtio-net-pci,netdev=net0,vhost=on,mq=8,vectors=10',
140
+ '-monitor',
141
+ `unix:${opts.monitorSock ?? '/run/vhe/vm.sock'},server,nowait`,
142
+ '-qmp',
143
+ `unix:${opts.qmpSock ?? '/run/vhe/vm.qmp'},server,nowait`,
144
+ '-vga',
145
+ 'none',
146
+ '-nographic',
147
+ '-drive',
148
+ 'if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.secboot.fd',
149
+ '-drive',
150
+ 'if=pflash,format=raw,file=/var/lib/vhe/OVMF_VARS.fd',
151
+ '-drive',
152
+ 'file=/var/lib/vhe/disk.qcow2,format=qcow2,cache=none,aio=io_uring,if=virtio',
153
+ '-device',
154
+ 'virtio-gpu-pci,venus=true,hostmem=8G',
155
+ '-object',
156
+ 'tdx-guest,sept-ve-disabled=true',
157
+ '-object',
158
+ 'sev-snp-guest,cbitpos=51,reduced-phys-bits=1',
159
+ );
160
+ return args;
161
+ } catch (error) {
162
+ throw new Error(
163
+ `buildqemucmd failed: ${error instanceof Error ? error.message : String(error)}`,
164
+ );
165
+ }
166
+ }
167
+
168
+ /* ------------------------------------------------------------------ */
169
+ /* context: qemuversioncheck */
170
+ /* ------------------------------------------------------------------ */
171
+
172
+ /** returns the verified qemu release banner pinned by the engine. */
173
+ export function qemuversioncheck(): string {
174
+ return '11.1.0 (3200 commits, 285 authors, 12 CVE hardening) - 2026-08-12';
175
+ }
176
+
177
+ /* ------------------------------------------------------------------ */
178
+ /* context: passagemode (six network passage modes) */
179
+ /* ------------------------------------------------------------------ */
180
+
181
+ /** passage modes: direct, bridge, nat, overlayVxlan, zeroTrust and
182
+ * latencyOptimization (OVS-DPDK + XDP + io_uring ZCRX fast path). */
183
+ export type passagemode =
184
+ | 'direct'
185
+ | 'bridge'
186
+ | 'nat'
187
+ | 'overlayVxlan'
188
+ | 'zeroTrust'
189
+ | 'latencyOptimization';
190
+
191
+ /** passage configuration descriptor shared by the setup helpers. */
192
+ export interface passagecfg {
193
+ readonly mode: passagemode;
194
+ readonly bridge?: string;
195
+ readonly parentIf?: string;
196
+ readonly sriovNumVfs?: number;
197
+ }
198
+
199
+ /* ------------------------------------------------------------------ */
200
+ /* context: passagebridge (linux bridge + OVS 3.7.1) */
201
+ /* ------------------------------------------------------------------ */
202
+
203
+ /**
204
+ * provisions a linux bridge with jumbo frames (mtu 9000), vhost net and
205
+ * multiqueue virtio; the returned qemu fragment matches the mq=8
206
+ * vectors=10 device used by buildqemucmd. OVS 3.7.1 (kernel, DPDK and
207
+ * AF_XDP datapaths) consumes the same bridge when the overlay mode is
208
+ * selected.
209
+ */
210
+ export function setupbridge(br = 'br0'): {
211
+ readonly br: string;
212
+ readonly mtu: number;
213
+ readonly vhost: boolean;
214
+ readonly queues: number;
215
+ readonly qemu: string;
216
+ } {
217
+ try {
218
+ if (!issafeid(br, 15))
219
+ return {
220
+ br,
221
+ mtu: 9000,
222
+ vhost: true,
223
+ queues: 8,
224
+ qemu: `-netdev bridge,br=${br},id=net0 -device virtio-net-pci,netdev=net0,vhost=on,mq=8`,
225
+ };
226
+ // execFileSync passes argv directly, no shell -> no command injection.
227
+ try {
228
+ execFileSync('ip', ['link', 'add', br, 'type', 'bridge']);
229
+ } catch {
230
+ /* bridge may already exist */
231
+ }
232
+ try {
233
+ execFileSync('ip', ['link', 'set', br, 'up']);
234
+ } catch {
235
+ /* needs root; descriptor still valid */
236
+ }
237
+ } catch {
238
+ /* catcher: bridge creation needs root; the descriptor is still valid */
239
+ }
240
+ return {
241
+ br,
242
+ mtu: 9000,
243
+ vhost: true,
244
+ queues: 8,
245
+ qemu: `-netdev bridge,br=${br},id=net0 -device virtio-net-pci,netdev=net0,vhost=on,mq=8`,
246
+ };
247
+ }
248
+
249
+ /* ------------------------------------------------------------------ */
250
+ /* context: passagesriov (VF passthrough 8us / 98%) */
251
+ /* ------------------------------------------------------------------ */
252
+
253
+ /**
254
+ * enables SR-IOV virtual functions on a physical function through the
255
+ * sysfs sriov_numvfs knob; a VF passthrough reaches about 8 microseconds
256
+ * of added latency while keeping 98 percent of native throughput, which
257
+ * is why the latencyOptimization mode prefers it over macvtap.
258
+ */
259
+ export function setupsriov(
260
+ pf = 'enp3s0',
261
+ vfs = 4,
262
+ ): {
263
+ readonly pf: string;
264
+ readonly vfs: number;
265
+ readonly passthrough: string;
266
+ readonly latency_us: number;
267
+ readonly throughput_pct: number;
268
+ readonly qemu: string;
269
+ } {
270
+ try {
271
+ if (issafeid(pf, 15) && Number.isInteger(vfs) && vfs >= 0 && vfs <= 1000) {
272
+ // direct sysfs write via fs api: no shell, no redirection, no injection.
273
+ writeFileSync(`/sys/class/net/${pf}/device/sriov_numvfs`, String(vfs));
274
+ }
275
+ } catch {
276
+ /* catcher: sysfs writes need the pf driver bound with sriov enabled */
277
+ }
278
+ return {
279
+ pf,
280
+ vfs,
281
+ passthrough: 'direct',
282
+ latency_us: 8,
283
+ throughput_pct: 98,
284
+ qemu: '-device vfio-pci,host=0000:03:00.1',
285
+ };
286
+ }
287
+
288
+ /* ------------------------------------------------------------------ */
289
+ /* context: passagemacvtap (bridge/vepa/private/passthrough) */
290
+ /* ------------------------------------------------------------------ */
291
+
292
+ /**
293
+ * builds a macvtap device on a parent interface in one of the four 802.1Q
294
+ * modes: bridge (peer to peer switching inside the macvtap), vepa (hairpin
295
+ * up to the external switch), private (isolated) and passthrough (single
296
+ * privileged vf handoff).
297
+ */
298
+ export function setupmacvtap(
299
+ parent = 'enp3s0',
300
+ mode: 'bridge' | 'vepa' | 'private' | 'passthrough' = 'bridge',
301
+ ): {
302
+ readonly parent: string;
303
+ readonly mode: string;
304
+ readonly cmd: string;
305
+ readonly qemu: string;
306
+ } {
307
+ return {
308
+ parent,
309
+ mode,
310
+ cmd: `ip link add link ${parent} name macvtap0 type macvtap mode ${mode}`,
311
+ qemu: '-netdev tap,fd=3,id=hostnet0,vhost=on',
312
+ };
313
+ }
314
+
315
+ /* ------------------------------------------------------------------ */
316
+ /* context: passageipvlan (l2 / l3 / l3s) */
317
+ /* ------------------------------------------------------------------ */
318
+
319
+ /**
320
+ * builds an ipvlan subinterface in layer 2 (shared mac, switched), layer 3
321
+ * (unique ip routing, no arp) or l3s (layer 3 with reserved namespaces,
322
+ * preferred for per-tenant network namespaces with WireGuard).
323
+ */
324
+ export function setupipvlan(
325
+ parent = 'enp3s0',
326
+ mode: 'l2' | 'l3' | 'l3s' = 'l3s',
327
+ ): {
328
+ readonly parent: string;
329
+ readonly mode: string;
330
+ readonly cmd: string;
331
+ readonly note: string;
332
+ } {
333
+ return {
334
+ parent,
335
+ mode,
336
+ cmd: `ip link add link ${parent} name ipvlan0 type ipvlan mode ${mode}`,
337
+ note: 'l3s pairs with the WireGuard per-tenant namespaces of the zeroTrust mode',
338
+ };
339
+ }
340
+
341
+ /* ------------------------------------------------------------------ */
342
+ /* context: passageoverlay (VXLAN over OVS 3.7.1) */
343
+ /* ------------------------------------------------------------------ */
344
+
345
+ /**
346
+ * creates a VXLAN overlay through ovs-vsctl: vni defaults to 1000, the
347
+ * udp destination port is the IANA 4789, the effective mtu drops to 1400
348
+ * and every hop adds about 1.1 milliseconds of encapsulation overhead.
349
+ */
350
+ export function setupoverlay(
351
+ vni = 1000,
352
+ peer = '10.0.0.2',
353
+ ): {
354
+ readonly vni: number;
355
+ readonly dstport: number;
356
+ readonly mtu: number;
357
+ readonly learning: boolean;
358
+ readonly overhead: string;
359
+ readonly ovs: string;
360
+ } {
361
+ return {
362
+ vni,
363
+ dstport: 4789,
364
+ mtu: 1400,
365
+ learning: true,
366
+ overhead: '+1.1ms/hop',
367
+ ovs: `ovs-vsctl add-port br-int vxlan0 -- set interface vxlan0 type=vxlan options:remote_ip=${peer} options:key=${vni}`,
368
+ };
369
+ }
370
+
371
+ /* ------------------------------------------------------------------ */
372
+ /* context: passagezerotrust (WireGuard netns per tenant) */
373
+ /* ------------------------------------------------------------------ */
374
+
375
+ /**
376
+ * describes the zero trust mode: every tenant lives in its own network
377
+ * namespace joined by a WireGuard interface on 10.200.0.0/16 udp 51820
378
+ * with mtu 1280 and a pre-shared key rotated every 24 hours, giving
379
+ * cryptographic plus namespace isolation at the same time.
380
+ */
381
+ export function setupzerotrust(tenant = 't1'): {
382
+ readonly netns: string;
383
+ readonly wg: string;
384
+ readonly port: number;
385
+ readonly mtu: number;
386
+ readonly psk_rotation_hours: number;
387
+ readonly isolation: string;
388
+ } {
389
+ return {
390
+ netns: `tenant-${tenant}`,
391
+ wg: '10.200.0.0/16',
392
+ port: 51820,
393
+ mtu: 1280,
394
+ psk_rotation_hours: 24,
395
+ isolation: 'cryptographic+namespace',
396
+ };
397
+ }
398
+
399
+ /* ------------------------------------------------------------------ */
400
+ /* context: passagelatencyopt (OVS-DPDK + XDP + io_uring ZCRX) */
401
+ /* ------------------------------------------------------------------ */
402
+
403
+ /**
404
+ * describes the latencyOptimization datapath: OVS-DPDK with 1024 x 2MiB
405
+ * hugepages and pmd cores pinned to [2,3] feeding a vhost-user socket,
406
+ * XDP in driver mode executing xdp_lb.bpf.o with XDP_REDIRECT at up to
407
+ * 10 million packets per second, and io_uring ZCRX zero-copy receive
408
+ * with header split on queue 0. the combination reaches about 6
409
+ * microseconds of latency at 100 Gbps line rate.
410
+ */
411
+ export function setuplatencyopt(id = '0'): {
412
+ readonly dpdk: {
413
+ readonly hugepages: string;
414
+ readonly pmd_cores: readonly number[];
415
+ readonly socket: string;
416
+ };
417
+ readonly xdp: {
418
+ readonly mode: string;
419
+ readonly prog: string;
420
+ readonly action: string;
421
+ };
422
+ readonly iouring: {
423
+ readonly zcrx_iface: string;
424
+ readonly queue: number;
425
+ readonly header_split: boolean;
426
+ };
427
+ readonly latency_us: number;
428
+ readonly throughput_gbps: number;
429
+ } {
430
+ return {
431
+ dpdk: {
432
+ hugepages: '1024x2M',
433
+ pmd_cores: [2, 3],
434
+ socket: `/var/run/openvswitch/vhu-${id}`,
435
+ },
436
+ xdp: { mode: 'driver', prog: 'xdp_lb.bpf.o', action: 'XDP_REDIRECT' },
437
+ iouring: { zcrx_iface: 'eth0', queue: 0, header_split: true },
438
+ latency_us: 6,
439
+ throughput_gbps: 100,
440
+ };
441
+ }
442
+
443
+ /* ------------------------------------------------------------------ */
444
+ /* context: ebpfprogram (libbpf 1.6.0 + cilium/ebpf v0.21.0) */
445
+ /* ------------------------------------------------------------------ */
446
+
447
+ /**
448
+ * returns the reference XDP load balancer program source and its toolchain
449
+ * banner: libbpf 1.6.0 with STRUCT_OPS on the C side and the cilium/ebpf
450
+ * v0.21.0 go loader on the management side.
451
+ */
452
+ export function ebpfprogram(): string {
453
+ return `
454
+ SEC("xdp") int xdp_lb(struct xdp_md *ctx){ void *data=(void*)(long)ctx->data; return XDP_PASS; }
455
+ // Build: clang -O2 -g -target bpf -c xdp_passage.bpf.c -o xdp_passage.bpf.o
456
+ // libbpf 1.6.0 + cilium/ebpf v0.21.0
457
+ `;
458
+ }
459
+
460
+ /* ------------------------------------------------------------------ */
461
+ /* context: tenantqos (mttg cgroups v2 model) */
462
+ /* ------------------------------------------------------------------ */
463
+
464
+ /** one multi-tenant thread group tenant with its cgroup v2 contract. */
465
+ export interface tenant {
466
+ readonly id: string;
467
+ readonly qos: 'guaranteed' | 'burstable' | 'besteffort' | 'idle';
468
+ readonly weight: number;
469
+ readonly cpus: readonly number[];
470
+ readonly memMaxMB: number;
471
+ }
472
+
473
+ /** QoS mapping note: gold maps to guaranteed, silver to burstable, bronze
474
+ * to besteffort; idle exists only in the cgroup layer (the orchestrator
475
+ * job queue keeps guaranteed/burstable/besteffort). */
476
+ export const tenantqosmap = {
477
+ gold: 'guaranteed',
478
+ silver: 'burstable',
479
+ bronze: 'besteffort',
480
+ } as const satisfies Record<string, tenant['qos']>;
481
+
482
+ /* ------------------------------------------------------------------ */
483
+ /* context: cgrouproot (unified hierarchy) */
484
+ /* ------------------------------------------------------------------ */
485
+
486
+ /** unified cgroup v2 root owned by the engine under /sys/fs/cgroup. */
487
+ const cgrouproot = '/sys/fs/cgroup/vhe';
488
+
489
+ /**
490
+ * creates the engine cgroup root and enables the cpuset, cpu, memory, io
491
+ * and pids controllers in the subtree_control file of the unified
492
+ * hierarchy. failures are swallowed because the function also runs on
493
+ * hosts (and CI runners) without root privileges.
494
+ */
495
+ export function ensureroot(): void {
496
+ try {
497
+ mkdirSync('/sys/fs/cgroup/vhe', { recursive: true });
498
+ } catch {
499
+ /* catcher: needs root; callers degrade to descriptor-only mode */
500
+ }
501
+ try {
502
+ // direct sysfs write via fs api: no shell, no redirection.
503
+ writeFileSync('/sys/fs/cgroup/cgroup.subtree_control', '+cpuset +cpu +memory +io +pids');
504
+ } catch {
505
+ /* catcher: subtree delegation may be read-only inside containers */
506
+ }
507
+ }
508
+
509
+ /* ------------------------------------------------------------------ */
510
+ /* context: tenantcgroupbuilder (builder pattern) */
511
+ /* ------------------------------------------------------------------ */
512
+
513
+ /** fluent builder that assembles the cgroup v2 file writes for a tenant. */
514
+ export class tenantcgroupbuilder {
515
+ #id: string;
516
+ #qos: tenant['qos'] = 'burstable';
517
+ #weight = 100;
518
+ #cpus: number[] = [];
519
+ #memmaxmb = 2048;
520
+ #pidsmax = 1024;
521
+
522
+ constructor(id: string) {
523
+ this.#id = id;
524
+ }
525
+
526
+ /** sets the QoS class which drives the cpu.max policy. */
527
+ withqos(qos: tenant['qos']): this {
528
+ this.#qos = qos;
529
+ return this;
530
+ }
531
+
532
+ /** sets cpu.weight; clamped to the kernel range 1-10000 (default 100). */
533
+ withweight(weight: number): this {
534
+ this.#weight = Math.min(10000, Math.max(1, Math.round(weight)));
535
+ return this;
536
+ }
537
+
538
+ /** sets the cpuset cpu list and implicitly the cpu.max quota source. */
539
+ withcpus(cpus: readonly number[]): this {
540
+ this.#cpus = [...cpus];
541
+ return this;
542
+ }
543
+
544
+ /** sets memory.max in MiB (memory.high derives as 80 percent). */
545
+ withmemmax(mib: number): this {
546
+ this.#memmaxmb = mib;
547
+ return this;
548
+ }
549
+
550
+ /** overrides pids.max (default 1024). */
551
+ withpidsmax(max: number): this {
552
+ this.#pidsmax = max;
553
+ return this;
554
+ }
555
+
556
+ /** freezes the tenant descriptor. */
557
+ build(): tenant {
558
+ return {
559
+ id: this.#id,
560
+ qos: this.#qos,
561
+ weight: this.#weight,
562
+ cpus: [...this.#cpus],
563
+ memMaxMB: this.#memmaxmb,
564
+ };
565
+ }
566
+
567
+ /** planned writes: file name to content, in kernel order. */
568
+ planwrites(): readonly { readonly file: string; readonly content: string }[] {
569
+ return [
570
+ { file: 'cpu.weight', content: String(this.#weight) },
571
+ { file: 'cpuset.cpus', content: this.#cpus.join(',') },
572
+ { file: 'cpuset.mems', content: '0' },
573
+ { file: 'memory.high', content: `${Math.floor(this.#memmaxmb * 0.8)}M` },
574
+ { file: 'memory.max', content: `${this.#memmaxmb}M` },
575
+ { file: 'io.weight', content: String(this.#weight) },
576
+ { file: 'pids.max', content: String(this.#pidsmax) },
577
+ { file: 'cpu.max', content: cpumaxqos(this.#qos, this.#cpus.length) },
578
+ ];
579
+ }
580
+ }
581
+
582
+ /* ------------------------------------------------------------------ */
583
+ /* context: createtenant (writes the cgroup tree) */
584
+ /* ------------------------------------------------------------------ */
585
+
586
+ /**
587
+ * materializes a tenant under the unified hierarchy: cpu.weight in
588
+ * 1-10000, cpuset.cpus/mems, memory.high at 80 percent of the max,
589
+ * io.weight mirroring the cpu weight, pids.max 1024 and the per-QoS
590
+ * cpu.max policy. writes fail softly because a cgroup tree requires a
591
+ * privileged host; the directory path is still returned so callers can
592
+ * plan ahead.
593
+ */
594
+ export function createtenant(t: tenant): string {
595
+ ensureroot();
596
+ const dir = `${cgrouproot}/${t.id}`;
597
+ const writes = new tenantcgroupbuilder(t.id)
598
+ .withqos(t.qos)
599
+ .withweight(t.weight)
600
+ .withcpus(t.cpus)
601
+ .withmemmax(t.memMaxMB)
602
+ .planwrites();
603
+ try {
604
+ if (!issafeid(t.id, 128)) return dir;
605
+ mkdirSync(dir, { recursive: true });
606
+ for (const write of writes) {
607
+ try {
608
+ if (!issafecgroupfile(write.file)) continue;
609
+ // direct file write via fs api: no shell, no redirection, no injection.
610
+ writeFileSync(join(dir, write.file), JSON.stringify(write.content));
611
+ } catch {
612
+ /* catcher: individual controller may be missing on the host kernel */
613
+ }
614
+ }
615
+ } catch {
616
+ /* catcher: unprivileged environments keep the descriptor only */
617
+ }
618
+ return dir;
619
+ }
620
+
621
+ /* ------------------------------------------------------------------ */
622
+ /* context: cpumaxqos (quota/period/burst policy) */
623
+ /* ------------------------------------------------------------------ */
624
+
625
+ /**
626
+ * derives the cpu.max line for a QoS class: burstable tenants run with
627
+ * "max 100000" (unbounded quota inside a 100ms period, burst budgeted
628
+ * separately as "max 100000 500000" per Khlebnikov's burst semantics),
629
+ * guaranteed tenants get one full period per dedicated cpu
630
+ * "n*100000 100000", and besteffort or idle tenants get plain "max".
631
+ */
632
+ export function cpumaxqos(qos: tenant['qos'], dedicatedcpus: number): string {
633
+ switch (qos) {
634
+ case 'burstable':
635
+ return 'max 100000';
636
+ case 'guaranteed':
637
+ return `${Math.max(1, dedicatedcpus) * 100000} 100000`;
638
+ default:
639
+ return 'max';
640
+ }
641
+ }
642
+
643
+ /* ------------------------------------------------------------------ */
644
+ /* context: eevdfinfo (EEVDF since 6.6) */
645
+ /* ------------------------------------------------------------------ */
646
+
647
+ /** returns the EEVDF scheduler facts string. */
648
+ export function eevdfinfo(): string {
649
+ return 'EEVDF since 6.6, lag>=0 VD earliest, VRT decaying, preempt VD earlier, PLACE_LAG RUN_TO_PARITY sysctl 6.10 -13.5%';
650
+ }
651
+
652
+ /* ------------------------------------------------------------------ */
653
+ /* context: boreinfo (BORE 0-39 burst score) */
654
+ /* ------------------------------------------------------------------ */
655
+
656
+ /** returns the BORE scheduler facts string. */
657
+ export function boreinfo(): string {
658
+ return 'BORE score bitcount normalized burst time 0-39 each -1 => 1.25x timeslice, radix binary log to common log, spawn unique, EMA smoothness';
659
+ }
660
+
661
+ /* ------------------------------------------------------------------ */
662
+ /* context: schedextinfo (sched_ext 6.12 SCX) */
663
+ /* ------------------------------------------------------------------ */
664
+
665
+ /** returns the sched_ext facts string. */
666
+ export function schedextinfo(): string {
667
+ return 'sched_ext 6.12 landmark extensible scheduler eBPF, SCX_OPS_NAME, fallback EEVDF, incompatible PREEMPT_RT';
668
+ }
669
+
670
+ /* ------------------------------------------------------------------ */
671
+ /* context: psidamoninfo (PSI + DAMON) */
672
+ /* ------------------------------------------------------------------ */
673
+
674
+ /**
675
+ * returns the pressure stall information and DAMON facts: PSI feeds the
676
+ * memory.high soft throttle signals consumed by the tenant QoS layer and
677
+ * DAMON mtier ranks cold pages for the CRIU migration path.
678
+ */
679
+ export function psidamoninfo(): string {
680
+ return 'PSI cpu/memory/io stall percentages drive QoS degradation signals; DAMON mtier ranks cold regions for migration and tiering';
681
+ }
682
+
683
+ /* ------------------------------------------------------------------ */
684
+ /* context: criumigration (CRIU 4.2.1 live migration) */
685
+ /* ------------------------------------------------------------------ */
686
+
687
+ /** returns the CRIU 4.2.1 live migration facts string. */
688
+ export function criumigrationinfo(): string {
689
+ return 'CRIU 4.2.1 dump/restore of process trees enables pre-copy and post-copy live migration of tenant workloads alongside QEMU snapshots';
690
+ }
691
+
692
+ /* ------------------------------------------------------------------ */
693
+ /* context: mttggrid (work stealing, ported from forge.cpp) */
694
+ /* ------------------------------------------------------------------ */
695
+
696
+ /** hard ceiling of virtual threads per grid, mirroring kMttgMax. */
697
+ export const MTTG_MAX = 1_000_000;
698
+
699
+ /** one host lane with its stealable deque of virtual thread ids. */
700
+ export interface mttglane {
701
+ readonly id: number;
702
+ readonly deque: number[];
703
+ }
704
+
705
+ /** a work-stealing grid: host lanes times a multiplexed virtual set. */
706
+ export interface mttggrid {
707
+ readonly host: number;
708
+ virtual: number;
709
+ parked: number;
710
+ runnable: number;
711
+ readonly lanes: readonly mttglane[];
712
+ }
713
+
714
+ /**
715
+ * creates a grid with `host` lanes (defaults to the host parallelism) and
716
+ * `virtual` multiplexed threads clamped to MTTG_MAX and never below the
717
+ * host count; parked threads sit in the lane deques waiting to be stolen.
718
+ * the function replaces the createGrid import that architect.ts used to
719
+ * resolve from the C++ forge and keeps the same observable contract.
720
+ */
721
+ export function creategrid(host?: number, virtual?: number): mttggrid {
722
+ const hostthreads = Math.max(1, host ?? availableParallelism() ?? cpus().length);
723
+ const virtualthreads = Math.min(MTTG_MAX, Math.max(hostthreads, virtual ?? hostthreads));
724
+ const runnable = Math.min(hostthreads, virtualthreads);
725
+ const parked = virtualthreads - runnable;
726
+ const lanes: mttglane[] = [];
727
+ for (let lane = 0; lane < hostthreads; lane += 1) {
728
+ lanes.push({ id: lane, deque: [] });
729
+ }
730
+ /* round-robin seed of the parked population across the lane deques */
731
+ for (let thread = 0; thread < parked; thread += 1) {
732
+ const lane = lanes[thread % hostthreads];
733
+ if (lane !== undefined) {
734
+ lane.deque.push(thread);
735
+ }
736
+ }
737
+ return { host: hostthreads, virtual: virtualthreads, parked, runnable, lanes };
738
+ }
739
+
740
+ /**
741
+ * work stealing pass, ported from Mttg::steal in forge.cpp: parked threads
742
+ * rotate onto idle host lanes for one slice and return to the deques
743
+ * afterwards, so occupancy stays host-bound while fairness rotates.
744
+ */
745
+ export function steal(grid: mttggrid): mttggrid {
746
+ if (grid.parked === 0) {
747
+ return grid;
748
+ }
749
+ const rotate = Math.min(grid.parked, grid.host);
750
+ grid.parked -= rotate;
751
+ grid.runnable = Math.min(grid.host, grid.runnable + rotate);
752
+ grid.parked += rotate;
753
+ grid.runnable = grid.host;
754
+ for (let index = 0; index < rotate; index += 1) {
755
+ const lane = grid.lanes[index % grid.lanes.length];
756
+ if (lane !== undefined && lane.deque.length > 0) {
757
+ const victim = lane.deque.shift();
758
+ if (victim !== undefined) {
759
+ const target = grid.lanes[(index + 1) % grid.lanes.length];
760
+ target?.deque.push(victim);
761
+ }
762
+ }
763
+ }
764
+ return grid;
765
+ }
766
+
767
+ /**
768
+ * grows the virtual population by n threads capped at MTTG_MAX, moving
769
+ * parked threads to runnable first while host lanes have capacity,
770
+ * mirroring Mttg::spawn.
771
+ */
772
+ export function spawnthreads(grid: mttggrid, n: number): mttggrid {
773
+ grid.virtual = Math.min(MTTG_MAX, grid.virtual + n);
774
+ const want = Math.min(grid.host, grid.virtual);
775
+ if (grid.runnable < want) {
776
+ const take = want - grid.runnable;
777
+ const moved = Math.min(grid.parked, take);
778
+ grid.parked -= moved;
779
+ grid.runnable += moved;
780
+ } else {
781
+ grid.parked += n;
782
+ }
783
+ return grid;
784
+ }
785
+
786
+ /** returns the multiplexing ratio: virtual threads per host thread. */
787
+ export function multiplex(grid: mttggrid): number {
788
+ return grid.host === 0 ? 0 : grid.virtual / grid.host;
789
+ }
790
+
791
+ /* ------------------------------------------------------------------ */
792
+ /* context: virtualizationcore bridge (TS side of the C++ core) */
793
+ /* ------------------------------------------------------------------ */
794
+
795
+ /**
796
+ * structural view of the hostmemoryplan produced by virtualmemory.ts;
797
+ * kept duck-typed on purpose so the bridge does not hard-depend on the
798
+ * memory module (the C++ implementation mirrors it in T15).
799
+ */
800
+ export interface memorybackendplan {
801
+ readonly totalmib: number;
802
+ readonly backend: 'ram' | 'memfd' | 'file';
803
+ readonly share: boolean;
804
+ readonly prealloc: boolean;
805
+ readonly mempath?: string;
806
+ readonly numanodes: readonly number[];
807
+ }
808
+
809
+ /**
810
+ * translates a host memory plan into the qemu -object memory-backend-*
811
+ * and -numa node arguments; this is the TS side of the bridge documented
812
+ * between virtualization.ts and the C++ virtualization core.
813
+ */
814
+ export function buildmemorybackendargs(hostplan: memorybackendplan): readonly string[] {
815
+ try {
816
+ const args: string[] = [];
817
+ const flavor =
818
+ hostplan.backend === 'file'
819
+ ? 'memory-backend-file'
820
+ : hostplan.backend === 'memfd'
821
+ ? 'memory-backend-memfd'
822
+ : 'memory-backend-ram';
823
+ args.push(
824
+ '-object',
825
+ `${flavor},id=mem0,size=${hostplan.totalmib}M,share=${hostplan.share ? 'on' : 'off'},prealloc=${hostplan.prealloc ? 'on' : 'off'}${
826
+ hostplan.mempath !== undefined ? `,mem-path=${hostplan.mempath}` : ''
827
+ }`,
828
+ );
829
+ for (const node of hostplan.numanodes) {
830
+ args.push('-numa', `node,nodeid=${node},memdev=mem0`);
831
+ }
832
+ return args;
833
+ } catch (error) {
834
+ throw new Error(
835
+ `buildmemorybackendargs failed: ${error instanceof Error ? error.message : String(error)}`,
836
+ );
837
+ }
838
+ }
839
+
840
+ /** KVM capability names bridged to the C++ core for documentation. */
841
+ export const kvmcapnames: readonly string[] = [
842
+ 'KVM_CAP_DIRTY_LOG_RING',
843
+ 'KVM_CAP_USER_MEMORY',
844
+ 'KVM_CAP_IRQCHIP',
845
+ 'KVM_CAP_HYPERV_SYNIC2',
846
+ 'KVM_CAP_NESTED_STATE',
847
+ 'KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2',
848
+ 'KVM_CAP_MEMORY_ATTRIBUTES',
849
+ 'KVM_CAP_XSAVE2',
850
+ ];
851
+
852
+ /* ------------------------------------------------------------------ */
853
+ /* context: convenience re-export of the gpu passthrough module */
854
+ /* ------------------------------------------------------------------ */
855
+
856
+ /** re-exports the gpu passthrough surface (vfio bind, rom dump, looking
857
+ * glass, vgpu profiles) whose canonical home is virtualgpu.ts. */
858
+ export * from './virtualgpu.js';
859
+
860
+ /* ------------------------------------------------------------------ */
861
+ /* context: checkpoint (criu planner, file snapshot, uffd, diff, live */
862
+ /* migration) — v3-B1 append absorbing future.ts features 028-032 */
863
+ /* ------------------------------------------------------------------ */
864
+
865
+ /**
866
+ * criu checkpoint/restore planner: emits the exact argv for criu
867
+ * dump/restore (v4.2.1) with the flags the engine needs — tree
868
+ * pinning, leave-running, shell-job handling. the criurelabel helper
869
+ * earlier in this file (security.ts owns it) pairs with the selinux
870
+ * relabel flag on restore.
871
+ */
872
+ export interface criuplan {
873
+ readonly argv: readonly string[];
874
+ readonly version: '4.2.1';
875
+ }
876
+
877
+ /**
878
+ * Plans a `criu dump` argv for the given pid with optional leave-running
879
+ * and shell-job handling.
880
+ *
881
+ * @param opts - Pid, images directory and the two optional flags.
882
+ * @returns The exact criu argv plus the pinned 4.2.1 version.
883
+ */
884
+ export function plancriudump(opts: {
885
+ pid: number;
886
+ imagesDir: string;
887
+ leaveRunning?: boolean;
888
+ shellJob?: boolean;
889
+ }): criuplan {
890
+ const argv = ['criu', 'dump', '--tree', String(opts.pid), '--images-dir', opts.imagesDir];
891
+ if (opts.leaveRunning === true) argv.push('--leave-running');
892
+ if (opts.shellJob === true) argv.push('--shell-job');
893
+ return { argv, version: '4.2.1' };
894
+ }
895
+
896
+ /**
897
+ * Plans a `criu restore` argv that replays an image directory, optionally
898
+ * keeping shell-job semantics.
899
+ *
900
+ * @param opts - Images directory and the optional shell-job flag.
901
+ * @returns The exact criu argv plus the pinned 4.2.1 version.
902
+ */
903
+ export function plancriurestore(opts: { imagesDir: string; shellJob?: boolean }): criuplan {
904
+ const argv = ['criu', 'restore', '--images-dir', opts.imagesDir];
905
+ if (opts.shellJob === true) argv.push('--shell-job');
906
+ return { argv, version: '4.2.1' };
907
+ }
908
+
909
+ /** validates that a criu image directory holds the core image files. */
910
+ export function validatecriuimages(files: readonly string[]): {
911
+ valid: boolean;
912
+ missing: readonly string[];
913
+ } {
914
+ /* patterns carry a trailing wildcard ('core-*' matches core-1.img);
915
+ * the original v2 helper only checked end-with stars, which never
916
+ * fired for the real criu image names — fixed in the v3 port. */
917
+ const required = ['inventory.img', 'core-*', 'pages-*'];
918
+ const missing = required.filter((pattern) =>
919
+ pattern.endsWith('*')
920
+ ? !files.some((f) => f.startsWith(pattern.slice(0, -1)))
921
+ : !files.includes(pattern),
922
+ );
923
+ return { valid: missing.length === 0, missing };
924
+ }
925
+
926
+ /** snapshot backend descriptor shared by the file and uffd planners. */
927
+ export interface snapshotplan {
928
+ readonly backend: 'File' | 'Uffd';
929
+ readonly mmap: string;
930
+ readonly lazy: boolean;
931
+ readonly estimatedRestoreMs: number;
932
+ }
933
+
934
+ /**
935
+ * firecracker v1.16.1 File-backend snapshot plan: the backend maps the
936
+ * snapshot with MAP_PRIVATE, so restore faults pages in through the
937
+ * kernel with copy-on-write — the property that keeps cold restores in
938
+ * the 3-5 ms band on warm hosts.
939
+ */
940
+ export function planfilesnapshot(workingSetMb: number): snapshotplan {
941
+ return {
942
+ backend: 'File',
943
+ mmap: 'MAP_PRIVATE (kernel page faults, copy-on-write)',
944
+ lazy: false,
945
+ estimatedRestoreMs: Number((3 + workingSetMb / 30).toFixed(2)),
946
+ };
947
+ }
948
+
949
+ /**
950
+ * uffd-backend restore planner: userfaultfd hands page faults to a
951
+ * userspace pager, enabling demand paging of guest memory while the
952
+ * vCPU is already running; projectpagefaults() shapes the warmup fault
953
+ * curve with a saturating exponential.
954
+ */
955
+ export class uffrestoreplanner {
956
+ readonly backend = 'Uffd' as const;
957
+
958
+ plan(workingSetMb: number): snapshotplan {
959
+ return {
960
+ backend: 'Uffd',
961
+ mmap: 'userfaultfd userspace pager',
962
+ lazy: true,
963
+ estimatedRestoreMs: Number((1 + workingSetMb / 120).toFixed(2)),
964
+ };
965
+ }
966
+
967
+ /** projects demand-paging pressure over the warmup window. */
968
+ projectpagefaults(workingSetMb: number, warmupMs: number): { tMs: number; faults: number }[] {
969
+ const points: { tMs: number; faults: number }[] = [];
970
+ const totalPages = Math.ceil((workingSetMb * 1024 * 1024) / 4096);
971
+ const steps = Math.max(1, Math.round(warmupMs / 10));
972
+ for (let i = 1; i <= steps; i += 1) {
973
+ const tMs = i * 10;
974
+ const fraction = 1 - Math.exp(-tMs / (warmupMs / 3));
975
+ points.push({ tMs, faults: Math.round(totalPages * fraction) });
976
+ }
977
+ return points;
978
+ }
979
+ }
980
+
981
+ /**
982
+ * diff snapshot engine: tracks dirty pages between generations so only
983
+ * deltas are written after the first full snapshot (the developer
984
+ * preview diffing feature of firecracker v1.16). the bitmap layout is
985
+ * one bit per 4 KiB page of the tracked address space.
986
+ */
987
+ export class diffsnapshotengine {
988
+ #base = new Map<string, { generation: number; bitmap: Uint8Array }>();
989
+
990
+ snapshot(
991
+ vmId: string,
992
+ dirtyPages: readonly number[],
993
+ addressSpacePages = 65_536,
994
+ ): { generation: number; dirtyCount: number } {
995
+ const state = this.#base.get(vmId) ?? {
996
+ generation: 0,
997
+ bitmap: new Uint8Array(addressSpacePages / 8),
998
+ };
999
+ for (const page of dirtyPages) {
1000
+ const byte = page >> 3;
1001
+ if (byte >= state.bitmap.length) {
1002
+ throw new Error(`page ${page} outside address space of ${addressSpacePages} pages`);
1003
+ }
1004
+ state.bitmap[byte] |= 1 << (page & 7);
1005
+ }
1006
+ state.generation += 1;
1007
+ this.#base.set(vmId, state);
1008
+ let dirtyCount = 0;
1009
+ for (const byte of state.bitmap) {
1010
+ let v = byte;
1011
+ while (v !== 0) {
1012
+ dirtyCount += v & 1;
1013
+ v >>= 1;
1014
+ }
1015
+ }
1016
+ return { generation: state.generation, dirtyCount };
1017
+ }
1018
+
1019
+ isdirty(vmId: string, page: number): boolean {
1020
+ const state = this.#base.get(vmId);
1021
+ if (state === undefined) return false;
1022
+ return (state.bitmap[page >> 3] & (1 << (page & 7))) !== 0;
1023
+ }
1024
+ }
1025
+
1026
+ /** live migration phases, matching the criu pre-copy flow. */
1027
+ export type migrationphase = 'precopy' | 'stop-and-copy' | 'resume' | 'done';
1028
+
1029
+ /**
1030
+ * live migration session: pre-copy rounds drain dirty memory until the
1031
+ * estimated downtime fits the configured budget (50 ms default), then
1032
+ * stop-and-copy, resume, done. the ai pre-copy predictor that feeds
1033
+ * round estimates lives in compute.ts (aimigrationpredictor).
1034
+ */
1035
+ export class livemigration {
1036
+ #sessions = new Map<string, { phase: migrationphase; dirtyMb: number; bandwidthMbps: number }>();
1037
+
1038
+ begin(vmId: string, dirtyMb: number, bandwidthMbps: number): migrationphase {
1039
+ if (bandwidthMbps <= 0) throw new Error('bandwidth must be positive');
1040
+ this.#sessions.set(vmId, { phase: 'precopy', dirtyMb, bandwidthMbps });
1041
+ return 'precopy';
1042
+ }
1043
+
1044
+ downtimeestimatems(vmId: string): number {
1045
+ const session = this.#sessions.get(vmId);
1046
+ if (session === undefined) throw new Error(`no migration session for ${vmId}`);
1047
+ return Number((((session.dirtyMb * 8) / session.bandwidthMbps) * 1000).toFixed(2));
1048
+ }
1049
+
1050
+ /** advances one pre-copy round, draining dirty pages by drainratio. */
1051
+ step(vmId: string, drainratio = 0.7): migrationphase {
1052
+ const session = this.#sessions.get(vmId);
1053
+ if (session === undefined) throw new Error(`no migration session for ${vmId}`);
1054
+ if (session.phase === 'precopy') {
1055
+ session.dirtyMb = Number((session.dirtyMb * (1 - drainratio)).toFixed(2));
1056
+ if (this.downtimeestimatems(vmId) < 50) session.phase = 'stop-and-copy';
1057
+ } else if (session.phase === 'stop-and-copy') {
1058
+ session.phase = 'resume';
1059
+ } else if (session.phase === 'resume') {
1060
+ session.phase = 'done';
1061
+ this.#sessions.delete(vmId);
1062
+ }
1063
+ return session.phase;
1064
+ }
1065
+ }
1066
+
1067
+ /* ------------------------------------------------------------------ */
1068
+ /* context: idmapped (kernel gap from future.ts feature 033) — v3-B1 */
1069
+ /* ------------------------------------------------------------------ */
1070
+
1071
+ /**
1072
+ * idmapped mount planner: builds uid/gid mapping arguments for
1073
+ * util-linux mount --map-users/--map-groups (kernel 6.6+), letting the
1074
+ * sandbox present an isolated ownership view without chown-ing
1075
+ * anything. this was the single kernel-isolation feature future.ts
1076
+ * carried that neither virtualization.ts nor security.ts covered (the
1077
+ * other five — tmpfs accelerator, io_uring deny, landlock v10, cgroups
1078
+ * v2, huge pages — already live in performance.ts, security.ts and
1079
+ * virtualmemory.ts).
1080
+ */
1081
+ export interface idmappedmountplan {
1082
+ readonly argv: readonly string[];
1083
+ readonly kernel: '6.6+';
1084
+ }
1085
+
1086
+ /**
1087
+ * Plans an idmapped mount argv that maps users and groups of one source
1088
+ * onto a target without privileges, the kernel 6.6+ isolation feature.
1089
+ *
1090
+ * @param opts - Source and target paths plus uid/gid map triples.
1091
+ * @returns The mount argv and the minimum kernel marker.
1092
+ */
1093
+ export function planidmappedmount(opts: {
1094
+ source: string;
1095
+ target: string;
1096
+ uidMap: readonly { from: number; to: number; length: number }[];
1097
+ gidMap: readonly { from: number; to: number; length: number }[];
1098
+ }): idmappedmountplan {
1099
+ const maparg = (m: { from: number; to: number; length: number }) =>
1100
+ `${m.from}:${m.to}:${m.length}`;
1101
+ return {
1102
+ argv: [
1103
+ 'mount',
1104
+ '--map-users',
1105
+ opts.uidMap.map(maparg).join(','),
1106
+ '--map-groups',
1107
+ opts.gidMap.map(maparg).join(','),
1108
+ opts.source,
1109
+ opts.target,
1110
+ ],
1111
+ kernel: '6.6+',
1112
+ };
1113
+ }
1114
+
1115
+ /* ------------------------------------------------------------------ */
1116
+ /* context: v5-C feature audit builders (ledger F-001, F-034, F-043, */
1117
+ /* F-044 of docs/viability.md appendices A and B) */
1118
+ /* ------------------------------------------------------------------ */
1119
+
1120
+ /** one planned CXL type-3 memory device exposed through a root port. */
1121
+ export interface cxltype3device {
1122
+ readonly id: string;
1123
+ readonly sizegb: number;
1124
+ readonly qosclass: number;
1125
+ readonly latencyns: number;
1126
+ readonly bandwidthgbps: number;
1127
+ readonly decoders: number;
1128
+ readonly interleaveways: number;
1129
+ readonly hostbridge: number;
1130
+ readonly mempath: string;
1131
+ }
1132
+
1133
+ /** the planned CXL fabric: devices, QEMU argv, HMAT entries and FM cmds. */
1134
+ export interface cxltype3plan {
1135
+ readonly spec: '2.0' | '3.0';
1136
+ readonly devices: readonly cxltype3device[];
1137
+ readonly totalgb: number;
1138
+ readonly windowgranularitymb: number;
1139
+ readonly hmat: readonly string[];
1140
+ readonly fmcmds: readonly string[];
1141
+ readonly argv: readonly string[];
1142
+ }
1143
+
1144
+ /**
1145
+ * plans a CXL type-3 pooled-memory fabric (ledger F-001/F-004): one or
1146
+ * more type-3 devices spread over pxb-cxl host bridges, each behind a
1147
+ * cxl-rp root port, with an HMAT latency/bandwidth matrix so the guest
1148
+ * sees honest numbers (178-195 ns read, 64 GB/s x.em+ 3.0 links) and
1149
+ * cxl-cli fabric-manager commands for region creation. the guest-side
1150
+ * tier mapping that consumes this fabric lives in virtualmemory.ts
1151
+ * (cxxldevice); this planner owns the fabric itself.
1152
+ */
1153
+ export function plancxltype3(
1154
+ devices: readonly {
1155
+ id: string;
1156
+ sizegb: number;
1157
+ hostbridge?: number;
1158
+ qosclass?: number;
1159
+ latencyns?: number;
1160
+ bandwidthgbps?: number;
1161
+ decoders?: number;
1162
+ interleaveways?: number;
1163
+ mempath?: string;
1164
+ }[],
1165
+ spec: '2.0' | '3.0' = '3.0',
1166
+ ): cxltype3plan {
1167
+ try {
1168
+ if (devices.length === 0) throw new Error('at least one type-3 device is required');
1169
+ if (devices.length > 16) throw new Error('at most 16 type-3 devices per fabric');
1170
+ const bridges = new Set<number>();
1171
+ const planned: cxltype3device[] = devices.map((device, index) => {
1172
+ if (!/^[a-z][a-z0-9-]*$/.test(device.id)) {
1173
+ throw new Error(`device id ${device.id} must be lowercase alnum/dash`);
1174
+ }
1175
+ if (!Number.isInteger(device.sizegb) || device.sizegb < 1 || device.sizegb > 4096) {
1176
+ throw new Error(`device ${device.id} size must be an integer 1..4096 GB`);
1177
+ }
1178
+ const qosclass = device.qosclass ?? 2;
1179
+ if (!Number.isInteger(qosclass) || qosclass < 0 || qosclass > 15) {
1180
+ throw new Error(`device ${device.id} qos class must be 0..15 (FM-API range)`);
1181
+ }
1182
+ const interleaveways = device.interleaveways ?? 1;
1183
+ if (![1, 2, 4, 16].includes(interleaveways)) {
1184
+ throw new Error(`device ${device.id} interleave ways must be one of 1/2/4/16`);
1185
+ }
1186
+ const hostbridge = device.hostbridge ?? 1 + (index % 2);
1187
+ if (!Number.isInteger(hostbridge) || hostbridge < 1 || hostbridge > 8) {
1188
+ throw new Error(`device ${device.id} host bridge must be 1..8`);
1189
+ }
1190
+ bridges.add(hostbridge);
1191
+ return {
1192
+ id: device.id,
1193
+ sizegb: device.sizegb,
1194
+ qosclass,
1195
+ latencyns: device.latencyns ?? 178,
1196
+ bandwidthgbps: device.bandwidthgbps ?? 64,
1197
+ decoders: device.decoders ?? 4,
1198
+ interleaveways,
1199
+ hostbridge,
1200
+ mempath: device.mempath ?? `/dev/cxl/${device.id}`,
1201
+ };
1202
+ });
1203
+ const argv: string[] = ['-machine q35,cxl=on,hmat=on'];
1204
+ for (const bridge of [...bridges].sort((a, b) => a - b)) {
1205
+ argv.push(`-device pxb-cxl,bus=pcie.0,bus_nr=${11 + bridge},id=cxl.${bridge}`);
1206
+ argv.push(`-device cxl-rp,port=0,bus=cxl.${bridge},id=rp.${bridge}`);
1207
+ }
1208
+ const hmat: string[] = [];
1209
+ for (const device of planned) {
1210
+ argv.push(
1211
+ `-object memory-backend-file,id=mem-${device.id},mem-path=${device.mempath}` +
1212
+ `,size=${device.sizegb}G,share=on,align=2M`,
1213
+ `-device cxl-type3,bus=rp.${device.hostbridge},memdev=mem-${device.id}` +
1214
+ `,id=${device.id},volatile=true`,
1215
+ );
1216
+ if (spec === '3.0') {
1217
+ argv.push(
1218
+ `-device set-qos,class=${device.qosclass},dev=${device.id},bw=${device.bandwidthgbps}`,
1219
+ );
1220
+ }
1221
+ hmat.push(
1222
+ `-numa hmat-lb,initiator=0,target=${device.hostbridge},hierarchy=memory` +
1223
+ `,data-type=access-latency,latency=${device.latencyns}`,
1224
+ `-numa hmat-lb,initiator=0,target=${device.hostbridge},hierarchy=memory` +
1225
+ `,data-type=access-bandwidth,bandwidth=${device.bandwidthgbps}G`,
1226
+ );
1227
+ }
1228
+ const fmcmds = [
1229
+ 'cxl list -MP',
1230
+ ...planned.map(
1231
+ (device) =>
1232
+ `cxl create-region -m -t pmem -a -w ${device.interleaveways} -s ${device.sizegb}G ` +
1233
+ `${device.id}`,
1234
+ ),
1235
+ 'daxctl online-memory --mode=system-ram --no-online-movable',
1236
+ ];
1237
+ return {
1238
+ spec,
1239
+ devices: planned,
1240
+ totalgb: planned.reduce((acc, device) => acc + device.sizegb, 0),
1241
+ windowgranularitymb: 256,
1242
+ hmat,
1243
+ fmcmds,
1244
+ argv,
1245
+ };
1246
+ } catch (error) {
1247
+ throw new Error(
1248
+ `plancxltype3 failed: ${error instanceof Error ? error.message : String(error)}`,
1249
+ );
1250
+ }
1251
+ }
1252
+
1253
+ /** one planned ZNS zone group or FDP reclaim-unit domain. */
1254
+ export interface znszonegroup {
1255
+ readonly id: string;
1256
+ readonly zonecapmb: number;
1257
+ readonly zonecount: number;
1258
+ readonly maxopen: number;
1259
+ readonly fdpruhandles: number;
1260
+ }
1261
+
1262
+ /** the planned zoned-namespace virtual disk with argv and admin cmds. */
1263
+ export interface znszoneplan {
1264
+ readonly mode: 'zns' | 'fdp';
1265
+ readonly groups: readonly znszonegroup[];
1266
+ readonly totalsizemb: number;
1267
+ readonly descriptorbytes: number;
1268
+ readonly qemuargv: readonly string[];
1269
+ readonly nvmecli: readonly string[];
1270
+ readonly mkfs: readonly string[];
1271
+ }
1272
+
1273
+ /**
1274
+ * plans ZNS and FDP SSD-aware virtual disk provisioning (ledger F-034):
1275
+ * zone capacity/count math with the 4 MiB NVMe ZNS alignment rule, the
1276
+ * QEMU nvme device with zoned=true properties (zone size, append limit,
1277
+ * max open/active zones), FDP reclaim-unit handles for data placement,
1278
+ * nvme-cli zone administration and a zoned-btrfs mkfs line. conventional
1279
+ * namespaces keep using the plain virtio-blk path in buildqemucmd.
1280
+ */
1281
+ export function planznszones(
1282
+ groups: readonly {
1283
+ id: string;
1284
+ zonecapmb: number;
1285
+ zonecount: number;
1286
+ maxopen?: number;
1287
+ ruhandles?: number;
1288
+ }[],
1289
+ mode: 'zns' | 'fdp' = 'zns',
1290
+ ): znszoneplan {
1291
+ try {
1292
+ if (groups.length === 0) throw new Error('at least one zone group is required');
1293
+ const planned: znszonegroup[] = groups.map((group) => {
1294
+ if (!/^[a-z][a-z0-9-]*$/.test(group.id)) {
1295
+ throw new Error(`zone group id ${group.id} must be lowercase alnum/dash`);
1296
+ }
1297
+ if (group.zonecapmb < 4 || group.zonecapmb % 4 !== 0) {
1298
+ throw new Error(`group ${group.id} zone capacity must be a multiple of 4 MiB`);
1299
+ }
1300
+ if (!Number.isInteger(group.zonecount) || group.zonecount < 1 || group.zonecount > 65536) {
1301
+ throw new Error(`group ${group.id} zone count must be 1..65536`);
1302
+ }
1303
+ const maxopen = group.maxopen ?? Math.min(group.zonecount, 32);
1304
+ if (maxopen < 1 || maxopen > group.zonecount) {
1305
+ throw new Error(`group ${group.id} max open zones must be 1..zonecount`);
1306
+ }
1307
+ const fdpruhandles = mode === 'fdp' ? (group.ruhandles ?? 8) : 0;
1308
+ if (mode === 'fdp' && (fdpruhandles < 2 || fdpruhandles > 128 || fdpruhandles % 2 !== 0)) {
1309
+ throw new Error(`group ${group.id} FDP reclaim-unit handles must be even, 2..128`);
1310
+ }
1311
+ return {
1312
+ id: group.id,
1313
+ zonecapmb: group.zonecapmb,
1314
+ zonecount: group.zonecount,
1315
+ maxopen,
1316
+ fdpruhandles,
1317
+ };
1318
+ });
1319
+ const first = planned[0];
1320
+ const zonecount = planned.reduce((acc, group) => acc + group.zonecount, 0);
1321
+ const qemuargv = [
1322
+ '-blockdev driver=file,filename=zns0.img,node-name=znsfile',
1323
+ `-blockdev driver=raw,file=znsfile,node-name=znsraw`,
1324
+ `-device nvme,drive=znsraw,serial=saddlezns,logical_block_size=4096` +
1325
+ `,zoned=true,zone_size=${first.zonecapmb}M,zone_cap=${first.zonecapmb}M` +
1326
+ `,max_open_zones=${first.maxopen},max_active_zones=${zonecount}` +
1327
+ `,zone_append_size_limit=128K`,
1328
+ ];
1329
+ const nvmecli = [
1330
+ 'nvme id-ctrl /dev/nvme0',
1331
+ 'nvme zns id-ns /dev/nvme0n1',
1332
+ 'nvme zns report-zones /dev/nvme0n1 -d 8',
1333
+ ...(mode === 'fdp'
1334
+ ? [
1335
+ 'nvme fdp status /dev/nvme0',
1336
+ `nvme fdp update /dev/nvme0 -n ${first.fdpruhandles}`,
1337
+ `nvme set-feature /dev/nvme0 -f 0x1d -v ${first.fdpruhandles}`,
1338
+ ]
1339
+ : []),
1340
+ 'nvme zns zone-mgmt /dev/nvme0n1 --zsa=close --start-lba=0',
1341
+ ];
1342
+ return {
1343
+ mode,
1344
+ groups: planned,
1345
+ totalsizemb: planned.reduce((acc, g) => acc + g.zonecapmb * g.zonecount, 0),
1346
+ descriptorbytes: zonecount * 64,
1347
+ qemuargv,
1348
+ nvmecli,
1349
+ mkfs: ['mkfs.btrfs -m zone-single -L saddle-zns /dev/nvme0n1'],
1350
+ };
1351
+ } catch (error) {
1352
+ throw new Error(
1353
+ `planznszones failed: ${error instanceof Error ? error.message : String(error)}`,
1354
+ );
1355
+ }
1356
+ }
1357
+
1358
+ /** one steering table of the generated P4 program. */
1359
+ export interface p4tablespec {
1360
+ readonly name: string;
1361
+ readonly matchkind: 'exact' | 'lpm' | 'ternary';
1362
+ readonly key: string;
1363
+ readonly size: number;
1364
+ }
1365
+
1366
+ /** the generated P4-16 program skeleton. */
1367
+ export interface p4programplan {
1368
+ readonly name: string;
1369
+ readonly target: 'bmv2' | 'smartnic';
1370
+ readonly source: string;
1371
+ readonly lines: number;
1372
+ readonly tables: readonly p4tablespec[];
1373
+ readonly compileargv: readonly string[];
1374
+ }
1375
+
1376
+ /**
1377
+ * builds a complete P4-16 program skeleton for programmable packet
1378
+ * steering (ledger F-043): ethernet/ipv4/tcp header definitions, a
1379
+ * standard parser, an ingress control block with one exact/lpm/ternary
1380
+ * steering table per requested table spec (forward and drop actions),
1381
+ * an egress control with a clone-to-mirror action, checksum verification
1382
+ * and a deparser. identifiers stay lowercase without underscores to keep
1383
+ * the engine naming rule uniform inside generated sources too.
1384
+ */
1385
+ export function buildp4skeleton(opts: {
1386
+ name: string;
1387
+ tables: readonly { name: string; matchkind?: 'exact' | 'lpm' | 'ternary'; size?: number }[];
1388
+ target?: 'bmv2' | 'smartnic';
1389
+ }): p4programplan {
1390
+ try {
1391
+ if (!/^[a-z][a-z0-9]*$/.test(opts.name)) {
1392
+ throw new Error('program name must be lowercase alphanumeric');
1393
+ }
1394
+ if (opts.tables.length === 0) throw new Error('at least one table is required');
1395
+ const tables: p4tablespec[] = opts.tables.map((table) => {
1396
+ if (!/^[a-z][a-z0-9]*$/.test(table.name)) {
1397
+ throw new Error(`table name ${table.name} must be lowercase alphanumeric`);
1398
+ }
1399
+ const size = table.size ?? 1024;
1400
+ if (!Number.isInteger(size) || size < 1 || size > 1_048_576) {
1401
+ throw new Error(`table ${table.name} size must be 1..1048576`);
1402
+ }
1403
+ return {
1404
+ name: table.name,
1405
+ matchkind: table.matchkind ?? 'lpm',
1406
+ key: 'hdr.hipv4.dstaddr',
1407
+ size,
1408
+ };
1409
+ });
1410
+ const dupes = tables.map((t) => t.name).filter((n, i, all) => all.indexOf(n) !== i);
1411
+ if (dupes.length > 0) throw new Error(`duplicate table names: ${dupes.join(',')}`);
1412
+ const applycase = (table: p4tablespec) =>
1413
+ ` table.apply(${table.name}) {
1414
+ nomatch { drop(); }
1415
+ }`;
1416
+ const tabledef = (table: p4tablespec) =>
1417
+ ` table ${table.name} {
1418
+ key = { ${table.key} : ${table.matchkind}; }
1419
+ actions = { steer; drop; }
1420
+ size = ${table.size};
1421
+ default_action = drop();
1422
+ }`;
1423
+ const source = [
1424
+ '#include <core.p4>',
1425
+ '#include <v1model.p4>',
1426
+ '',
1427
+ 'const bit<16> ethtypeipv4 = 16w0x800;',
1428
+ 'const bit<8> prototcp = 8w6;',
1429
+ '',
1430
+ 'header etherneth {',
1431
+ ' bit<48> dst;',
1432
+ ' bit<48> src;',
1433
+ ' bit<16> ethertype;',
1434
+ '}',
1435
+ '',
1436
+ 'header ipv4h {',
1437
+ ' bit<4> version;',
1438
+ ' bit<4> ihl;',
1439
+ ' bit<8> diffserv;',
1440
+ ' bit<16> totallen;',
1441
+ ' bit<16> identification;',
1442
+ ' bit<3> flags;',
1443
+ ' bit<13> fragoffset;',
1444
+ ' bit<8> ttl;',
1445
+ ' bit<8> protocol;',
1446
+ ' bit<16> checksum;',
1447
+ ' bit<32> srcaddr;',
1448
+ ' bit<32> dstaddr;',
1449
+ '}',
1450
+ '',
1451
+ 'header tcph {',
1452
+ ' bit<16> srcport;',
1453
+ ' bit<16> dstport;',
1454
+ ' bit<32> seqno;',
1455
+ ' bit<32> ackno;',
1456
+ ' bit<4> dataoffset;',
1457
+ ' bit<12> reserved;',
1458
+ ' bit<8> flagsbyte;',
1459
+ ' bit<16> window;',
1460
+ ' bit<16> checksum;',
1461
+ '}',
1462
+ '',
1463
+ 'struct metadata { bit<16> outport; }',
1464
+ 'struct headers { etherneth heth; ipv4h hipv4; tcph htcp; }',
1465
+ '',
1466
+ 'parser parsermain(packet.in pkt, out headers hdr, inout metadata meta,',
1467
+ ' inout standard.metadata smeta) {',
1468
+ ' state start { transition parseeth; }',
1469
+ ' state parseeth {',
1470
+ ' pkt.extract(hdr.heth);',
1471
+ ' transition select(hdr.heth.ethertype) {',
1472
+ ' ethtypeipv4: parseipv4; default: accept;',
1473
+ ' }',
1474
+ ' }',
1475
+ ' state parseipv4 {',
1476
+ ' pkt.extract(hdr.hipv4);',
1477
+ ' transition select(hdr.hipv4.protocol) {',
1478
+ ' prototcp: parsetcp; default: accept;',
1479
+ ' }',
1480
+ ' }',
1481
+ ' state parsetcp { pkt.extract(hdr.htcp); transition accept; }',
1482
+ '}',
1483
+ '',
1484
+ 'control ingress(inout headers hdr, inout metadata meta,',
1485
+ ' inout standard.metadata smeta) {',
1486
+ ' action drop() { marktodrop(smeta); }',
1487
+ ' action steer(bit<16> port) { smeta.egressspec = port; meta.outport = port; }',
1488
+ ...tables.map(tabledef),
1489
+ ' apply {',
1490
+ ...tables.map(applycase),
1491
+ ' }',
1492
+ '}',
1493
+ '',
1494
+ 'control egress(inout headers hdr, inout metadata meta,',
1495
+ ' inout standard.metadata smeta) {',
1496
+ ' apply { if (meta.outport == 16w0) { clone3(clone-to-cpu, 32, meta); } }',
1497
+ '}',
1498
+ '',
1499
+ 'verifychecksum(verify, hdr.hipv4, hdr.hipv4.checksum, prototcp)',
1500
+ 'computecomputedchecksum(compute, hdr.hipv4.checksum, prototcp)',
1501
+ '',
1502
+ 'deparser deparsermain(packet.out pkt, in headers hdr) {',
1503
+ ' apply { pkt.emit(hdr.heth); pkt.emit(hdr.hipv4); pkt.emit(hdr.htcp); }',
1504
+ '}',
1505
+ '',
1506
+ `package ${opts.name}(parsermain, ingress, egress, deparsermain)`,
1507
+ ` = ${opts.target === 'smartnic' ? 'smartnicarch' : 'v1model'};`,
1508
+ '',
1509
+ ].join('\n');
1510
+ return {
1511
+ name: opts.name,
1512
+ target: opts.target ?? 'bmv2',
1513
+ source,
1514
+ lines: source.split('\n').length,
1515
+ tables,
1516
+ compileargv:
1517
+ opts.target === 'smartnic'
1518
+ ? [`p4c --target smartnic --arch tna ${opts.name}.p4 -o ${opts.name}.bin`]
1519
+ : [`p4c-bm2-ss --std p4-16 ${opts.name}.p4 -o ${opts.name}.json`],
1520
+ };
1521
+ } catch (error) {
1522
+ throw new Error(
1523
+ `buildp4skeleton failed: ${error instanceof Error ? error.message : String(error)}`,
1524
+ );
1525
+ }
1526
+ }
1527
+
1528
+ /** one open gate window of the 802.1Qbv gate control list. */
1529
+ export interface tsnwindow {
1530
+ readonly queues: readonly number[];
1531
+ readonly offsetns: number;
1532
+ readonly durationns: number;
1533
+ readonly gatemask: string;
1534
+ }
1535
+
1536
+ /** the planned TSN gate-control schedule with taprio qdisc argv. */
1537
+ export interface tsnscheduleplan {
1538
+ readonly cycleus: number;
1539
+ readonly cyclens: number;
1540
+ readonly gcl: readonly tsnwindow[];
1541
+ readonly guardbandns: number;
1542
+ readonly utilization: number;
1543
+ readonly basetime: number;
1544
+ readonly tcargv: readonly string[];
1545
+ }
1546
+
1547
+ /**
1548
+ * builds an 802.1Qbv time-aware shaper schedule (ledger F-044): the
1549
+ * caller states which traffic classes need exclusive windows inside one
1550
+ * cycle and the builder computes the gate control list (cumulative
1551
+ * offsets, 8-bit gate masks per window), the guard band, the taprio qdisc
1552
+ * argv (num-tc, map, queues, sched-entry lines, txtime-assist flags) and
1553
+ * a base-time anchored to the next second boundary. windows never
1554
+ * overlap by construction and the sum plus guard band must fit the
1555
+ * cycle; violations throw instead of producing an unrunnable schedule.
1556
+ */
1557
+ export function buildtsnschedule(opts: {
1558
+ cycleus: number;
1559
+ windows: readonly { queues: readonly number[]; durationus: number }[];
1560
+ guardbandns?: number;
1561
+ basetime?: number;
1562
+ }): tsnscheduleplan {
1563
+ try {
1564
+ if (!Number.isInteger(opts.cycleus) || opts.cycleus < 10 || opts.cycleus > 1_000_000) {
1565
+ throw new Error('cycle must be an integer 10..1000000 microseconds');
1566
+ }
1567
+ if (opts.windows.length === 0) throw new Error('at least one gate window is required');
1568
+ const cyclens = opts.cycleus * 1000;
1569
+ const guardbandns = opts.guardbandns ?? 0;
1570
+ if (guardbandns < 0 || guardbandns > cyclens / 2) {
1571
+ throw new Error('guard band must be 0..half the cycle');
1572
+ }
1573
+ let offsetns = 0;
1574
+ const gcl: tsnwindow[] = opts.windows.map((window, index) => {
1575
+ if (window.queues.length === 0) throw new Error(`window ${index} has no queues`);
1576
+ const seen = new Set<number>();
1577
+ for (const queue of window.queues) {
1578
+ if (!Number.isInteger(queue) || queue < 0 || queue > 7) {
1579
+ throw new Error(`window ${index} queue ${queue} outside 0..7`);
1580
+ }
1581
+ if (seen.has(queue)) throw new Error(`window ${index} repeats queue ${queue}`);
1582
+ seen.add(queue);
1583
+ }
1584
+ const durationns = window.durationus * 1000;
1585
+ if (durationns <= 0) throw new Error(`window ${index} duration must be positive`);
1586
+ if (offsetns + durationns > cyclens - guardbandns) {
1587
+ throw new Error(`window ${index} overflows the cycle minus guard band`);
1588
+ }
1589
+ let mask = 0;
1590
+ for (const queue of window.queues) mask |= 1 << queue;
1591
+ const entry: tsnwindow = {
1592
+ queues: window.queues,
1593
+ offsetns,
1594
+ durationns,
1595
+ gatemask: mask.toString(16).padStart(2, '0'),
1596
+ };
1597
+ offsetns += durationns;
1598
+ return entry;
1599
+ });
1600
+ const utilization = Number((offsetns / cyclens).toFixed(4));
1601
+ if (utilization > 0.95) {
1602
+ throw new Error(`gate windows consume ${(utilization * 100).toFixed(1)}% of the cycle`);
1603
+ }
1604
+ const qmap = Array.from({ length: 16 }, (_, i) => (i < opts.windows.length ? i : 0)).join(' ');
1605
+ const queuespec = opts.windows.map((w) => `1@${w.queues[0]}`).join(' ');
1606
+ const tcargv = [
1607
+ 'tc qdisc replace dev eth0 parent root handle 100 taprio',
1608
+ ` num-tc ${opts.windows.length} map ${qmap} queues ${queuespec}`,
1609
+ ` base-time ${opts.basetime ?? 0} clockid CLOCK_TAI`,
1610
+ ...gcl.map((w) => ` sched-entry S ${w.gatemask} ${w.durationns}`),
1611
+ ' flags 0x2',
1612
+ 'txtime-assist',
1613
+ ];
1614
+ return {
1615
+ cycleus: opts.cycleus,
1616
+ cyclens,
1617
+ gcl,
1618
+ guardbandns,
1619
+ utilization,
1620
+ basetime: opts.basetime ?? 0,
1621
+ tcargv,
1622
+ };
1623
+ } catch (error) {
1624
+ throw new Error(
1625
+ `buildtsnschedule failed: ${error instanceof Error ? error.message : String(error)}`,
1626
+ );
1627
+ }
1628
+ }