@wenathlan/saddle 1.8.18 → 2.0.3

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 (802) hide show
  1. package/Dockerfile +1346 -0
  2. package/README.md +33 -12
  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 -123
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +1018 -123
  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/contracts.d.ts → isolation.d.ts} +12 -1
  69. package/dist/isolation.d.ts.map +1 -0
  70. package/dist/{isolation/contracts.js → isolation.js} +13 -1
  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/packager/targetcli.js +4 -22
  89. package/dist/performance.d.ts +416 -0
  90. package/dist/performance.d.ts.map +1 -0
  91. package/dist/performance.js +827 -0
  92. package/dist/performance.js.map +1 -0
  93. package/dist/quantum.d.ts +810 -0
  94. package/dist/quantum.d.ts.map +1 -0
  95. package/dist/quantum.js +2073 -0
  96. package/dist/quantum.js.map +1 -0
  97. package/dist/render.d.ts +381 -0
  98. package/dist/render.d.ts.map +1 -0
  99. package/dist/render.js +1073 -0
  100. package/dist/render.js.map +1 -0
  101. package/dist/scheduler.d.ts +596 -0
  102. package/dist/scheduler.d.ts.map +1 -0
  103. package/dist/scheduler.js +1259 -0
  104. package/dist/scheduler.js.map +1 -0
  105. package/dist/security.d.ts +501 -0
  106. package/dist/security.d.ts.map +1 -0
  107. package/dist/security.js +1170 -0
  108. package/dist/security.js.map +1 -0
  109. package/dist/server.d.ts +21 -0
  110. package/dist/server.d.ts.map +1 -0
  111. package/dist/{server/node.js → server.js} +16 -2
  112. package/dist/server.js.map +1 -0
  113. package/dist/tiers.d.ts +1002 -0
  114. package/dist/tiers.d.ts.map +1 -0
  115. package/dist/tiers.js +2165 -0
  116. package/dist/tiers.js.map +1 -0
  117. package/dist/virtual.d.ts +641 -0
  118. package/dist/virtual.d.ts.map +1 -0
  119. package/dist/virtual.js +1285 -0
  120. package/dist/virtual.js.map +1 -0
  121. package/dist/virtualcpu.d.ts +316 -0
  122. package/dist/virtualcpu.d.ts.map +1 -0
  123. package/dist/virtualcpu.js +1180 -0
  124. package/dist/virtualcpu.js.map +1 -0
  125. package/dist/virtualgpu.d.ts +345 -0
  126. package/dist/virtualgpu.d.ts.map +1 -0
  127. package/dist/virtualgpu.js +1000 -0
  128. package/dist/virtualgpu.js.map +1 -0
  129. package/dist/virtualization.d.ts +607 -0
  130. package/dist/virtualization.d.ts.map +1 -0
  131. package/dist/virtualization.js +1187 -0
  132. package/dist/virtualization.js.map +1 -0
  133. package/dist/virtualmemory.d.ts +818 -0
  134. package/dist/virtualmemory.d.ts.map +1 -0
  135. package/dist/virtualmemory.js +1796 -0
  136. package/dist/virtualmemory.js.map +1 -0
  137. package/dist/webscrape.d.ts +720 -0
  138. package/dist/webscrape.d.ts.map +1 -0
  139. package/dist/webscrape.js +2697 -0
  140. package/dist/webscrape.js.map +1 -0
  141. package/docker.config +769 -0
  142. package/docs/CONVERSA.txt +1523 -0
  143. package/docs/alternatives.md +499 -0
  144. package/docs/architecture-1.8.19.md +76 -0
  145. package/docs/architecture-1.8.19.mmd +33 -0
  146. package/docs/architecture-1.8.19.png +0 -0
  147. package/docs/architecture.md +355 -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.19.md +35 -0
  160. package/docs/research-1.8.19-virtual-browser.md +27 -0
  161. package/docs/security.md +454 -0
  162. package/docs/todo-1.8.18.md +12 -0
  163. package/docs/todo-1.8.19.md +241 -0
  164. package/docs/viability.md +777 -0
  165. package/docs/virtualization.md +335 -0
  166. package/docs/web-duplicatecleanup.md +9 -0
  167. package/docs/web-ideas.md +106 -0
  168. package/docs/workflowimprovements-2026-08-19.md +70 -0
  169. package/gpumonitor.cpp +1543 -0
  170. package/gpus.json +2408 -0
  171. package/index.ts +1478 -0
  172. package/media.ts +1337 -0
  173. package/mttg.config +1549 -0
  174. package/orchestrator.ts +5462 -0
  175. package/package.json +304 -56
  176. package/passage.config +1331 -0
  177. package/performance.ts +1049 -0
  178. package/processors.json +2217 -0
  179. package/qemu.config +1062 -0
  180. package/qemubridge.py +1340 -0
  181. package/quantum.ts +2393 -0
  182. package/render.ts +1325 -0
  183. package/scheduler.ts +1600 -0
  184. package/security.ts +1449 -0
  185. package/tiers.ts +2871 -0
  186. package/tsconfig.json +29 -0
  187. package/virtualcpu.ts +1273 -0
  188. package/virtualgpu.ts +1181 -0
  189. package/virtualhardware.c +1011 -0
  190. package/virtualhardware.json +739 -0
  191. package/virtualization.ts +1628 -0
  192. package/virtualizationcore.cpp +4635 -0
  193. package/virtualmemory.ts +2303 -0
  194. package/vm.config.json +1910 -0
  195. package/{extension → web/extension}/manifest.json +1 -1
  196. package/web/readme.md +382 -0
  197. package/web/tsconfig.json +25 -0
  198. package/dist/adapters/forge.d.ts +0 -17
  199. package/dist/adapters/forge.d.ts.map +0 -1
  200. package/dist/adapters/forge.js +0 -19
  201. package/dist/adapters/forge.js.map +0 -1
  202. package/dist/adapters/forgejo.d.ts +0 -49
  203. package/dist/adapters/forgejo.d.ts.map +0 -1
  204. package/dist/adapters/forgejo.js +0 -8
  205. package/dist/adapters/forgejo.js.map +0 -1
  206. package/dist/adapters/github.d.ts +0 -12
  207. package/dist/adapters/github.d.ts.map +0 -1
  208. package/dist/adapters/github.js +0 -20
  209. package/dist/adapters/github.js.map +0 -1
  210. package/dist/adapters/gitlab.d.ts +0 -17
  211. package/dist/adapters/gitlab.d.ts.map +0 -1
  212. package/dist/adapters/gitlab.js +0 -10
  213. package/dist/adapters/gitlab.js.map +0 -1
  214. package/dist/adapters/huggingface.d.ts +0 -17
  215. package/dist/adapters/huggingface.d.ts.map +0 -1
  216. package/dist/adapters/huggingface.js +0 -6
  217. package/dist/adapters/huggingface.js.map +0 -1
  218. package/dist/adapters/socket.d.ts +0 -11
  219. package/dist/adapters/socket.d.ts.map +0 -1
  220. package/dist/adapters/socket.js +0 -17
  221. package/dist/adapters/socket.js.map +0 -1
  222. package/dist/adapters/transport.d.ts +0 -7
  223. package/dist/adapters/transport.d.ts.map +0 -1
  224. package/dist/adapters/transport.js +0 -36
  225. package/dist/adapters/transport.js.map +0 -1
  226. package/dist/ai/chunk.d.ts +0 -2
  227. package/dist/ai/chunk.d.ts.map +0 -1
  228. package/dist/ai/chunk.js +0 -36
  229. package/dist/ai/chunk.js.map +0 -1
  230. package/dist/ai/llmstxt.d.ts +0 -6
  231. package/dist/ai/llmstxt.d.ts.map +0 -1
  232. package/dist/ai/llmstxt.js +0 -12
  233. package/dist/ai/llmstxt.js.map +0 -1
  234. package/dist/ai/provenance.d.ts +0 -22
  235. package/dist/ai/provenance.d.ts.map +0 -1
  236. package/dist/ai/provenance.js +0 -25
  237. package/dist/ai/provenance.js.map +0 -1
  238. package/dist/ai/rag.d.ts +0 -26
  239. package/dist/ai/rag.d.ts.map +0 -1
  240. package/dist/ai/rag.js +0 -22
  241. package/dist/ai/rag.js.map +0 -1
  242. package/dist/ai/tokens.d.ts +0 -15
  243. package/dist/ai/tokens.d.ts.map +0 -1
  244. package/dist/ai/tokens.js +0 -9
  245. package/dist/ai/tokens.js.map +0 -1
  246. package/dist/api/auth.d.ts +0 -16
  247. package/dist/api/auth.d.ts.map +0 -1
  248. package/dist/api/auth.js +0 -19
  249. package/dist/api/auth.js.map +0 -1
  250. package/dist/api/contracts.d.ts +0 -28
  251. package/dist/api/contracts.d.ts.map +0 -1
  252. package/dist/api/contracts.js +0 -14
  253. package/dist/api/contracts.js.map +0 -1
  254. package/dist/api/control.d.ts +0 -10
  255. package/dist/api/control.d.ts.map +0 -1
  256. package/dist/api/control.js +0 -35
  257. package/dist/api/control.js.map +0 -1
  258. package/dist/api/http.d.ts +0 -7
  259. package/dist/api/http.d.ts.map +0 -1
  260. package/dist/api/http.js +0 -12
  261. package/dist/api/http.js.map +0 -1
  262. package/dist/api/rate.d.ts +0 -28
  263. package/dist/api/rate.d.ts.map +0 -1
  264. package/dist/api/rate.js +0 -36
  265. package/dist/api/rate.js.map +0 -1
  266. package/dist/api/security.d.ts +0 -12
  267. package/dist/api/security.d.ts.map +0 -1
  268. package/dist/api/security.js +0 -56
  269. package/dist/api/security.js.map +0 -1
  270. package/dist/api/service.d.ts +0 -5
  271. package/dist/api/service.d.ts.map +0 -1
  272. package/dist/api/service.js +0 -70
  273. package/dist/api/service.js.map +0 -1
  274. package/dist/apps/registry.d.ts +0 -33
  275. package/dist/apps/registry.d.ts.map +0 -1
  276. package/dist/apps/registry.js +0 -24
  277. package/dist/apps/registry.js.map +0 -1
  278. package/dist/binary/archive.d.ts +0 -27
  279. package/dist/binary/archive.d.ts.map +0 -1
  280. package/dist/binary/archive.js +0 -46
  281. package/dist/binary/archive.js.map +0 -1
  282. package/dist/binary/build.d.ts +0 -29
  283. package/dist/binary/build.d.ts.map +0 -1
  284. package/dist/binary/build.js +0 -17
  285. package/dist/binary/build.js.map +0 -1
  286. package/dist/binary/transform.d.ts +0 -70
  287. package/dist/binary/transform.d.ts.map +0 -1
  288. package/dist/binary/transform.js +0 -105
  289. package/dist/binary/transform.js.map +0 -1
  290. package/dist/bot/adapter.d.ts +0 -5
  291. package/dist/bot/adapter.d.ts.map +0 -1
  292. package/dist/bot/adapter.js +0 -11
  293. package/dist/bot/adapter.js.map +0 -1
  294. package/dist/bot/bot.d.ts +0 -28
  295. package/dist/bot/bot.d.ts.map +0 -1
  296. package/dist/bot/bot.js +0 -52
  297. package/dist/bot/bot.js.map +0 -1
  298. package/dist/bot/commands.d.ts +0 -8
  299. package/dist/bot/commands.d.ts.map +0 -1
  300. package/dist/bot/commands.js +0 -19
  301. package/dist/bot/commands.js.map +0 -1
  302. package/dist/bot/permissions.d.ts +0 -13
  303. package/dist/bot/permissions.d.ts.map +0 -1
  304. package/dist/bot/permissions.js +0 -16
  305. package/dist/bot/permissions.js.map +0 -1
  306. package/dist/browser/actions.d.ts +0 -33
  307. package/dist/browser/actions.d.ts.map +0 -1
  308. package/dist/browser/actions.js +0 -44
  309. package/dist/browser/actions.js.map +0 -1
  310. package/dist/browser/agent.d.ts +0 -21
  311. package/dist/browser/agent.d.ts.map +0 -1
  312. package/dist/browser/agent.js +0 -13
  313. package/dist/browser/agent.js.map +0 -1
  314. package/dist/browser/context.d.ts +0 -43
  315. package/dist/browser/context.d.ts.map +0 -1
  316. package/dist/browser/context.js +0 -54
  317. package/dist/browser/context.js.map +0 -1
  318. package/dist/browser/fingerprint.d.ts +0 -4
  319. package/dist/browser/fingerprint.d.ts.map +0 -1
  320. package/dist/browser/fingerprint.js +0 -12
  321. package/dist/browser/fingerprint.js.map +0 -1
  322. package/dist/browser/index.d.ts +0 -11
  323. package/dist/browser/index.d.ts.map +0 -1
  324. package/dist/browser/index.js +0 -11
  325. package/dist/browser/index.js.map +0 -1
  326. package/dist/browser/playwright.d.ts +0 -11
  327. package/dist/browser/playwright.d.ts.map +0 -1
  328. package/dist/browser/playwright.js +0 -24
  329. package/dist/browser/playwright.js.map +0 -1
  330. package/dist/browser/recorder.d.ts +0 -21
  331. package/dist/browser/recorder.d.ts.map +0 -1
  332. package/dist/browser/recorder.js +0 -58
  333. package/dist/browser/recorder.js.map +0 -1
  334. package/dist/browser/session.d.ts +0 -14
  335. package/dist/browser/session.d.ts.map +0 -1
  336. package/dist/browser/session.js +0 -21
  337. package/dist/browser/session.js.map +0 -1
  338. package/dist/browser/snapshot.d.ts +0 -69
  339. package/dist/browser/snapshot.d.ts.map +0 -1
  340. package/dist/browser/snapshot.js +0 -133
  341. package/dist/browser/snapshot.js.map +0 -1
  342. package/dist/captcha/contract.d.ts +0 -35
  343. package/dist/captcha/contract.d.ts.map +0 -1
  344. package/dist/captcha/contract.js +0 -17
  345. package/dist/captcha/contract.js.map +0 -1
  346. package/dist/captcha/evidence.d.ts +0 -10
  347. package/dist/captcha/evidence.d.ts.map +0 -1
  348. package/dist/captcha/evidence.js +0 -9
  349. package/dist/captcha/evidence.js.map +0 -1
  350. package/dist/captcha/guard.d.ts +0 -23
  351. package/dist/captcha/guard.d.ts.map +0 -1
  352. package/dist/captcha/guard.js +0 -12
  353. package/dist/captcha/guard.js.map +0 -1
  354. package/dist/cli/main.d.ts +0 -4
  355. package/dist/cli/main.d.ts.map +0 -1
  356. package/dist/cli/main.js +0 -46
  357. package/dist/cli/main.js.map +0 -1
  358. package/dist/core/errors.d.ts +0 -84
  359. package/dist/core/errors.d.ts.map +0 -1
  360. package/dist/core/errors.js +0 -54
  361. package/dist/core/errors.js.map +0 -1
  362. package/dist/core/events.d.ts +0 -9
  363. package/dist/core/events.d.ts.map +0 -1
  364. package/dist/core/events.js +0 -21
  365. package/dist/core/events.js.map +0 -1
  366. package/dist/core/hash.d.ts +0 -10
  367. package/dist/core/hash.d.ts.map +0 -1
  368. package/dist/core/hash.js +0 -82
  369. package/dist/core/hash.js.map +0 -1
  370. package/dist/core/ids.d.ts +0 -10
  371. package/dist/core/ids.d.ts.map +0 -1
  372. package/dist/core/ids.js +0 -15
  373. package/dist/core/ids.js.map +0 -1
  374. package/dist/delivery/manifest.d.ts +0 -35
  375. package/dist/delivery/manifest.d.ts.map +0 -1
  376. package/dist/delivery/manifest.js +0 -68
  377. package/dist/delivery/manifest.js.map +0 -1
  378. package/dist/deploy/index.d.ts +0 -6
  379. package/dist/deploy/index.d.ts.map +0 -1
  380. package/dist/deploy/index.js +0 -6
  381. package/dist/deploy/index.js.map +0 -1
  382. package/dist/dispatch/resumable.d.ts +0 -102
  383. package/dist/dispatch/resumable.d.ts.map +0 -1
  384. package/dist/dispatch/resumable.js +0 -64
  385. package/dist/dispatch/resumable.js.map +0 -1
  386. package/dist/dispatch/workflow.d.ts +0 -6
  387. package/dist/dispatch/workflow.d.ts.map +0 -1
  388. package/dist/dispatch/workflow.js +0 -37
  389. package/dist/dispatch/workflow.js.map +0 -1
  390. package/dist/domain/artifacts.d.ts +0 -12
  391. package/dist/domain/artifacts.d.ts.map +0 -1
  392. package/dist/domain/artifacts.js +0 -14
  393. package/dist/domain/artifacts.js.map +0 -1
  394. package/dist/domain/jobs.d.ts +0 -12
  395. package/dist/domain/jobs.d.ts.map +0 -1
  396. package/dist/domain/jobs.js +0 -20
  397. package/dist/domain/jobs.js.map +0 -1
  398. package/dist/domain/providers.d.ts +0 -10
  399. package/dist/domain/providers.d.ts.map +0 -1
  400. package/dist/domain/providers.js +0 -8
  401. package/dist/domain/providers.js.map +0 -1
  402. package/dist/domain/runtime.d.ts +0 -14
  403. package/dist/domain/runtime.d.ts.map +0 -1
  404. package/dist/domain/runtime.js +0 -10
  405. package/dist/domain/runtime.js.map +0 -1
  406. package/dist/domain/sessions.d.ts +0 -12
  407. package/dist/domain/sessions.d.ts.map +0 -1
  408. package/dist/domain/sessions.js +0 -57
  409. package/dist/domain/sessions.js.map +0 -1
  410. package/dist/examples/localjob.d.ts +0 -2
  411. package/dist/examples/localjob.d.ts.map +0 -1
  412. package/dist/examples/localjob.js.map +0 -1
  413. package/dist/examples/publicapi.d.ts +0 -2
  414. package/dist/examples/publicapi.d.ts.map +0 -1
  415. package/dist/examples/publicapi.js.map +0 -1
  416. package/dist/extension/build.d.ts +0 -9
  417. package/dist/extension/build.d.ts.map +0 -1
  418. package/dist/extension/build.js +0 -85
  419. package/dist/extension/build.js.map +0 -1
  420. package/dist/extension/content.d.ts +0 -6
  421. package/dist/extension/content.d.ts.map +0 -1
  422. package/dist/extension/content.js +0 -135
  423. package/dist/extension/content.js.map +0 -1
  424. package/dist/extension/index.d.ts +0 -7
  425. package/dist/extension/index.d.ts.map +0 -1
  426. package/dist/extension/index.js +0 -7
  427. package/dist/extension/index.js.map +0 -1
  428. package/dist/extension/pagebridge.d.ts +0 -6
  429. package/dist/extension/pagebridge.d.ts.map +0 -1
  430. package/dist/extension/pagebridge.js +0 -42
  431. package/dist/extension/pagebridge.js.map +0 -1
  432. package/dist/extension/permissions.d.ts +0 -26
  433. package/dist/extension/permissions.d.ts.map +0 -1
  434. package/dist/extension/permissions.js +0 -28
  435. package/dist/extension/permissions.js.map +0 -1
  436. package/dist/extension/popup.d.ts +0 -5
  437. package/dist/extension/popup.d.ts.map +0 -1
  438. package/dist/extension/popup.js +0 -26
  439. package/dist/extension/popup.js.map +0 -1
  440. package/dist/extension/protocol.d.ts +0 -58
  441. package/dist/extension/protocol.d.ts.map +0 -1
  442. package/dist/extension/protocol.js +0 -101
  443. package/dist/extension/protocol.js.map +0 -1
  444. package/dist/extension/serviceworker.d.ts +0 -25
  445. package/dist/extension/serviceworker.d.ts.map +0 -1
  446. package/dist/extension/serviceworker.js +0 -102
  447. package/dist/extension/serviceworker.js.map +0 -1
  448. package/dist/extension/worker.d.ts +0 -28
  449. package/dist/extension/worker.d.ts.map +0 -1
  450. package/dist/extension/worker.js +0 -22
  451. package/dist/extension/worker.js.map +0 -1
  452. package/dist/format/check.d.ts +0 -8
  453. package/dist/format/check.d.ts.map +0 -1
  454. package/dist/format/check.js +0 -38
  455. package/dist/format/check.js.map +0 -1
  456. package/dist/isolation/contracts.d.ts.map +0 -1
  457. package/dist/isolation/contracts.js.map +0 -1
  458. package/dist/library/public.d.ts.map +0 -1
  459. package/dist/library/public.js.map +0 -1
  460. package/dist/mcp/browser.d.ts +0 -9
  461. package/dist/mcp/browser.d.ts.map +0 -1
  462. package/dist/mcp/browser.js +0 -13
  463. package/dist/mcp/browser.js.map +0 -1
  464. package/dist/mcp/server.d.ts +0 -35
  465. package/dist/mcp/server.d.ts.map +0 -1
  466. package/dist/mcp/server.js +0 -40
  467. package/dist/mcp/server.js.map +0 -1
  468. package/dist/mcp/transport.d.ts +0 -7
  469. package/dist/mcp/transport.d.ts.map +0 -1
  470. package/dist/mcp/transport.js +0 -17
  471. package/dist/mcp/transport.js.map +0 -1
  472. package/dist/memory/bridge.d.ts +0 -14
  473. package/dist/memory/bridge.d.ts.map +0 -1
  474. package/dist/memory/bridge.js +0 -16
  475. package/dist/memory/bridge.js.map +0 -1
  476. package/dist/memory/engine.d.ts +0 -38
  477. package/dist/memory/engine.d.ts.map +0 -1
  478. package/dist/memory/engine.js +0 -109
  479. package/dist/memory/engine.js.map +0 -1
  480. package/dist/memory/modes.d.ts +0 -43
  481. package/dist/memory/modes.d.ts.map +0 -1
  482. package/dist/memory/modes.js +0 -66
  483. package/dist/memory/modes.js.map +0 -1
  484. package/dist/memory/objects.d.ts +0 -21
  485. package/dist/memory/objects.d.ts.map +0 -1
  486. package/dist/memory/objects.js +0 -20
  487. package/dist/memory/objects.js.map +0 -1
  488. package/dist/memory/planner.d.ts +0 -66
  489. package/dist/memory/planner.d.ts.map +0 -1
  490. package/dist/memory/planner.js +0 -108
  491. package/dist/memory/planner.js.map +0 -1
  492. package/dist/memory/targets.d.ts +0 -78
  493. package/dist/memory/targets.d.ts.map +0 -1
  494. package/dist/memory/targets.js +0 -29
  495. package/dist/memory/targets.js.map +0 -1
  496. package/dist/memory/transforms.d.ts +0 -19
  497. package/dist/memory/transforms.d.ts.map +0 -1
  498. package/dist/memory/transforms.js +0 -14
  499. package/dist/memory/transforms.js.map +0 -1
  500. package/dist/modes/matrix.d.ts +0 -23
  501. package/dist/modes/matrix.d.ts.map +0 -1
  502. package/dist/modes/matrix.js +0 -18
  503. package/dist/modes/matrix.js.map +0 -1
  504. package/dist/modes/modes.d.ts +0 -33
  505. package/dist/modes/modes.d.ts.map +0 -1
  506. package/dist/modes/modes.js +0 -15
  507. package/dist/modes/modes.js.map +0 -1
  508. package/dist/modes/resolve.d.ts +0 -96
  509. package/dist/modes/resolve.d.ts.map +0 -1
  510. package/dist/modes/resolve.js +0 -48
  511. package/dist/modes/resolve.js.map +0 -1
  512. package/dist/observability/metrics.d.ts +0 -14
  513. package/dist/observability/metrics.d.ts.map +0 -1
  514. package/dist/observability/metrics.js +0 -18
  515. package/dist/observability/metrics.js.map +0 -1
  516. package/dist/packager/manifest.d.ts +0 -66
  517. package/dist/packager/manifest.d.ts.map +0 -1
  518. package/dist/packager/manifest.js +0 -94
  519. package/dist/packager/manifest.js.map +0 -1
  520. package/dist/packager/publish.d.ts +0 -51
  521. package/dist/packager/publish.d.ts.map +0 -1
  522. package/dist/packager/publish.js +0 -18
  523. package/dist/packager/publish.js.map +0 -1
  524. package/dist/packager/targetcli.d.ts +0 -7
  525. package/dist/packager/targetcli.d.ts.map +0 -1
  526. package/dist/packager/targetcli.js.map +0 -1
  527. package/dist/persistence/adapter.d.ts +0 -5
  528. package/dist/persistence/adapter.d.ts.map +0 -1
  529. package/dist/persistence/adapter.js +0 -11
  530. package/dist/persistence/adapter.js.map +0 -1
  531. package/dist/persistence/drizzle.d.ts +0 -2
  532. package/dist/persistence/drizzle.d.ts.map +0 -1
  533. package/dist/persistence/drizzle.js +0 -12
  534. package/dist/persistence/drizzle.js.map +0 -1
  535. package/dist/persistence/memory.d.ts +0 -2
  536. package/dist/persistence/memory.d.ts.map +0 -1
  537. package/dist/persistence/memory.js +0 -27
  538. package/dist/persistence/memory.js.map +0 -1
  539. package/dist/persistence/migrations.d.ts +0 -19
  540. package/dist/persistence/migrations.d.ts.map +0 -1
  541. package/dist/persistence/migrations.js +0 -13
  542. package/dist/persistence/migrations.js.map +0 -1
  543. package/dist/persistence/prisma.d.ts +0 -2
  544. package/dist/persistence/prisma.d.ts.map +0 -1
  545. package/dist/persistence/prisma.js +0 -25
  546. package/dist/persistence/prisma.js.map +0 -1
  547. package/dist/persistence/schema.d.ts +0 -63
  548. package/dist/persistence/schema.d.ts.map +0 -1
  549. package/dist/persistence/schema.js +0 -28
  550. package/dist/persistence/schema.js.map +0 -1
  551. package/dist/persistence/sql.d.ts +0 -3
  552. package/dist/persistence/sql.d.ts.map +0 -1
  553. package/dist/persistence/sql.js +0 -37
  554. package/dist/persistence/sql.js.map +0 -1
  555. package/dist/protocol/blocks.d.ts +0 -10
  556. package/dist/protocol/blocks.d.ts.map +0 -1
  557. package/dist/protocol/blocks.js +0 -26
  558. package/dist/protocol/blocks.js.map +0 -1
  559. package/dist/protocol/json.d.ts +0 -6
  560. package/dist/protocol/json.d.ts.map +0 -1
  561. package/dist/protocol/json.js +0 -6
  562. package/dist/protocol/json.js.map +0 -1
  563. package/dist/protocol/ndjson.d.ts +0 -3
  564. package/dist/protocol/ndjson.d.ts.map +0 -1
  565. package/dist/protocol/ndjson.js +0 -20
  566. package/dist/protocol/ndjson.js.map +0 -1
  567. package/dist/protocol/sse.d.ts +0 -7
  568. package/dist/protocol/sse.d.ts.map +0 -1
  569. package/dist/protocol/sse.js +0 -25
  570. package/dist/protocol/sse.js.map +0 -1
  571. package/dist/proxy/pool.d.ts +0 -9
  572. package/dist/proxy/pool.d.ts.map +0 -1
  573. package/dist/proxy/pool.js +0 -27
  574. package/dist/proxy/pool.js.map +0 -1
  575. package/dist/queue/idempotency.d.ts +0 -10
  576. package/dist/queue/idempotency.d.ts.map +0 -1
  577. package/dist/queue/idempotency.js +0 -13
  578. package/dist/queue/idempotency.js.map +0 -1
  579. package/dist/queue/persistent.d.ts +0 -14
  580. package/dist/queue/persistent.d.ts.map +0 -1
  581. package/dist/queue/persistent.js +0 -66
  582. package/dist/queue/persistent.js.map +0 -1
  583. package/dist/queue/queue.d.ts +0 -7
  584. package/dist/queue/queue.d.ts.map +0 -1
  585. package/dist/queue/queue.js +0 -55
  586. package/dist/queue/queue.js.map +0 -1
  587. package/dist/queue/saga.d.ts +0 -5
  588. package/dist/queue/saga.d.ts.map +0 -1
  589. package/dist/queue/saga.js +0 -20
  590. package/dist/queue/saga.js.map +0 -1
  591. package/dist/release/assets.d.ts +0 -144
  592. package/dist/release/assets.d.ts.map +0 -1
  593. package/dist/release/assets.js +0 -157
  594. package/dist/release/assets.js.map +0 -1
  595. package/dist/release/evidence.d.ts +0 -92
  596. package/dist/release/evidence.d.ts.map +0 -1
  597. package/dist/release/evidence.js +0 -148
  598. package/dist/release/evidence.js.map +0 -1
  599. package/dist/release/verify.d.ts +0 -12
  600. package/dist/release/verify.d.ts.map +0 -1
  601. package/dist/release/verify.js +0 -112
  602. package/dist/release/verify.js.map +0 -1
  603. package/dist/runners/chain.d.ts +0 -125
  604. package/dist/runners/chain.d.ts.map +0 -1
  605. package/dist/runners/chain.js +0 -95
  606. package/dist/runners/chain.js.map +0 -1
  607. package/dist/runners/health.d.ts +0 -36
  608. package/dist/runners/health.d.ts.map +0 -1
  609. package/dist/runners/health.js +0 -26
  610. package/dist/runners/health.js.map +0 -1
  611. package/dist/runners/heartbeat.d.ts +0 -23
  612. package/dist/runners/heartbeat.d.ts.map +0 -1
  613. package/dist/runners/heartbeat.js +0 -29
  614. package/dist/runners/heartbeat.js.map +0 -1
  615. package/dist/runners/inprocess.d.ts +0 -17
  616. package/dist/runners/inprocess.d.ts.map +0 -1
  617. package/dist/runners/inprocess.js +0 -20
  618. package/dist/runners/inprocess.js.map +0 -1
  619. package/dist/runners/scheduler.d.ts +0 -5
  620. package/dist/runners/scheduler.d.ts.map +0 -1
  621. package/dist/runners/scheduler.js +0 -19
  622. package/dist/runners/scheduler.js.map +0 -1
  623. package/dist/runtime/abort.d.ts +0 -8
  624. package/dist/runtime/abort.d.ts.map +0 -1
  625. package/dist/runtime/abort.js +0 -13
  626. package/dist/runtime/abort.js.map +0 -1
  627. package/dist/runtime/compatibility.d.ts +0 -37
  628. package/dist/runtime/compatibility.d.ts.map +0 -1
  629. package/dist/runtime/compatibility.js +0 -10
  630. package/dist/runtime/compatibility.js.map +0 -1
  631. package/dist/runtime/detect.d.ts +0 -13
  632. package/dist/runtime/detect.d.ts.map +0 -1
  633. package/dist/runtime/detect.js +0 -18
  634. package/dist/runtime/detect.js.map +0 -1
  635. package/dist/runtime/engine.d.ts +0 -20
  636. package/dist/runtime/engine.d.ts.map +0 -1
  637. package/dist/runtime/engine.js +0 -61
  638. package/dist/runtime/engine.js.map +0 -1
  639. package/dist/runtime/retry.d.ts +0 -19
  640. package/dist/runtime/retry.d.ts.map +0 -1
  641. package/dist/runtime/retry.js +0 -54
  642. package/dist/runtime/retry.js.map +0 -1
  643. package/dist/runtime/worker.d.ts +0 -10
  644. package/dist/runtime/worker.d.ts.map +0 -1
  645. package/dist/runtime/worker.js +0 -25
  646. package/dist/runtime/worker.js.map +0 -1
  647. package/dist/scrape/cache.d.ts +0 -45
  648. package/dist/scrape/cache.d.ts.map +0 -1
  649. package/dist/scrape/cache.js +0 -45
  650. package/dist/scrape/cache.js.map +0 -1
  651. package/dist/scrape/crawl.d.ts +0 -47
  652. package/dist/scrape/crawl.d.ts.map +0 -1
  653. package/dist/scrape/crawl.js +0 -114
  654. package/dist/scrape/crawl.js.map +0 -1
  655. package/dist/scrape/extract.d.ts +0 -63
  656. package/dist/scrape/extract.d.ts.map +0 -1
  657. package/dist/scrape/extract.js +0 -47
  658. package/dist/scrape/extract.js.map +0 -1
  659. package/dist/scrape/normalize.d.ts +0 -52
  660. package/dist/scrape/normalize.d.ts.map +0 -1
  661. package/dist/scrape/normalize.js +0 -102
  662. package/dist/scrape/normalize.js.map +0 -1
  663. package/dist/scrape/robots.d.ts +0 -37
  664. package/dist/scrape/robots.d.ts.map +0 -1
  665. package/dist/scrape/robots.js +0 -71
  666. package/dist/scrape/robots.js.map +0 -1
  667. package/dist/scrape/schema.d.ts +0 -23
  668. package/dist/scrape/schema.d.ts.map +0 -1
  669. package/dist/scrape/schema.js +0 -92
  670. package/dist/scrape/schema.js.map +0 -1
  671. package/dist/scrape/scraper.d.ts +0 -6
  672. package/dist/scrape/scraper.d.ts.map +0 -1
  673. package/dist/scrape/scraper.js +0 -46
  674. package/dist/scrape/scraper.js.map +0 -1
  675. package/dist/scrape/semantic.d.ts +0 -25
  676. package/dist/scrape/semantic.d.ts.map +0 -1
  677. package/dist/scrape/semantic.js +0 -27
  678. package/dist/scrape/semantic.js.map +0 -1
  679. package/dist/server/node.d.ts +0 -7
  680. package/dist/server/node.d.ts.map +0 -1
  681. package/dist/server/node.js.map +0 -1
  682. package/dist/sessions/file.d.ts +0 -25
  683. package/dist/sessions/file.d.ts.map +0 -1
  684. package/dist/sessions/file.js +0 -13
  685. package/dist/sessions/file.js.map +0 -1
  686. package/dist/sessions/replay.d.ts +0 -9
  687. package/dist/sessions/replay.d.ts.map +0 -1
  688. package/dist/sessions/replay.js +0 -70
  689. package/dist/sessions/replay.js.map +0 -1
  690. package/dist/sessions/store.d.ts +0 -25
  691. package/dist/sessions/store.d.ts.map +0 -1
  692. package/dist/sessions/store.js +0 -13
  693. package/dist/sessions/store.js.map +0 -1
  694. package/dist/storage/adapter.d.ts +0 -5
  695. package/dist/storage/adapter.d.ts.map +0 -1
  696. package/dist/storage/adapter.js +0 -11
  697. package/dist/storage/adapter.js.map +0 -1
  698. package/dist/storage/cache.d.ts +0 -23
  699. package/dist/storage/cache.d.ts.map +0 -1
  700. package/dist/storage/cache.js +0 -79
  701. package/dist/storage/cache.js.map +0 -1
  702. package/dist/storage/checksum.d.ts +0 -3
  703. package/dist/storage/checksum.d.ts.map +0 -1
  704. package/dist/storage/checksum.js +0 -19
  705. package/dist/storage/checksum.js.map +0 -1
  706. package/dist/storage/chunked.d.ts +0 -21
  707. package/dist/storage/chunked.d.ts.map +0 -1
  708. package/dist/storage/chunked.js +0 -67
  709. package/dist/storage/chunked.js.map +0 -1
  710. package/dist/storage/content.d.ts +0 -24
  711. package/dist/storage/content.d.ts.map +0 -1
  712. package/dist/storage/content.js +0 -44
  713. package/dist/storage/content.js.map +0 -1
  714. package/dist/storage/filehosting.d.ts +0 -2
  715. package/dist/storage/filehosting.d.ts.map +0 -1
  716. package/dist/storage/filehosting.js +0 -24
  717. package/dist/storage/filehosting.js.map +0 -1
  718. package/dist/storage/githubcontents.d.ts +0 -2
  719. package/dist/storage/githubcontents.d.ts.map +0 -1
  720. package/dist/storage/githubcontents.js +0 -29
  721. package/dist/storage/githubcontents.js.map +0 -1
  722. package/dist/storage/index.d.ts +0 -12
  723. package/dist/storage/index.d.ts.map +0 -1
  724. package/dist/storage/index.js +0 -12
  725. package/dist/storage/index.js.map +0 -1
  726. package/dist/storage/local.d.ts +0 -2
  727. package/dist/storage/local.d.ts.map +0 -1
  728. package/dist/storage/local.js +0 -72
  729. package/dist/storage/local.js.map +0 -1
  730. package/dist/storage/memory.d.ts +0 -6
  731. package/dist/storage/memory.d.ts.map +0 -1
  732. package/dist/storage/memory.js +0 -36
  733. package/dist/storage/memory.js.map +0 -1
  734. package/dist/storage/pool.d.ts +0 -95
  735. package/dist/storage/pool.d.ts.map +0 -1
  736. package/dist/storage/pool.js +0 -202
  737. package/dist/storage/pool.js.map +0 -1
  738. package/dist/storage/s3compatible.d.ts +0 -3
  739. package/dist/storage/s3compatible.d.ts.map +0 -1
  740. package/dist/storage/s3compatible.js +0 -70
  741. package/dist/storage/s3compatible.js.map +0 -1
  742. package/dist/storage/sync.d.ts +0 -47
  743. package/dist/storage/sync.d.ts.map +0 -1
  744. package/dist/storage/sync.js +0 -75
  745. package/dist/storage/sync.js.map +0 -1
  746. package/dist/surfaces/adapters.d.ts +0 -97
  747. package/dist/surfaces/adapters.d.ts.map +0 -1
  748. package/dist/surfaces/adapters.js +0 -50
  749. package/dist/surfaces/adapters.js.map +0 -1
  750. package/dist/surfaces/controls.d.ts +0 -18
  751. package/dist/surfaces/controls.d.ts.map +0 -1
  752. package/dist/surfaces/controls.js +0 -45
  753. package/dist/surfaces/controls.js.map +0 -1
  754. package/dist/surfaces/manifest.d.ts +0 -68
  755. package/dist/surfaces/manifest.d.ts.map +0 -1
  756. package/dist/surfaces/manifest.js +0 -42
  757. package/dist/surfaces/manifest.js.map +0 -1
  758. package/dist/surfaces/n8n.d.ts +0 -25
  759. package/dist/surfaces/n8n.d.ts.map +0 -1
  760. package/dist/surfaces/n8n.js +0 -31
  761. package/dist/surfaces/n8n.js.map +0 -1
  762. package/dist/surfaces/operations.d.ts +0 -32
  763. package/dist/surfaces/operations.d.ts.map +0 -1
  764. package/dist/surfaces/operations.js +0 -53
  765. package/dist/surfaces/operations.js.map +0 -1
  766. package/dist/surfaces/requirements.d.ts +0 -29
  767. package/dist/surfaces/requirements.d.ts.map +0 -1
  768. package/dist/surfaces/requirements.js +0 -50
  769. package/dist/surfaces/requirements.js.map +0 -1
  770. package/dist/surfaces/targets.d.ts +0 -196
  771. package/dist/surfaces/targets.d.ts.map +0 -1
  772. package/dist/surfaces/targets.js +0 -27
  773. package/dist/surfaces/targets.js.map +0 -1
  774. package/dist/webhook/delivery.d.ts +0 -18
  775. package/dist/webhook/delivery.d.ts.map +0 -1
  776. package/dist/webhook/delivery.js +0 -36
  777. package/dist/webhook/delivery.js.map +0 -1
  778. package/dist/webhook/receiver.d.ts +0 -26
  779. package/dist/webhook/receiver.d.ts.map +0 -1
  780. package/dist/webhook/receiver.js +0 -24
  781. package/dist/webhook/receiver.js.map +0 -1
  782. package/dist/webhook/signature.d.ts +0 -3
  783. package/dist/webhook/signature.d.ts.map +0 -1
  784. package/dist/webhook/signature.js +0 -7
  785. package/dist/webhook/signature.js.map +0 -1
  786. package/dist/workflow/manifest.d.ts +0 -22
  787. package/dist/workflow/manifest.d.ts.map +0 -1
  788. package/dist/workflow/manifest.js +0 -21
  789. package/dist/workflow/manifest.js.map +0 -1
  790. package/dist/workflow/registry.d.ts +0 -7
  791. package/dist/workflow/registry.d.ts.map +0 -1
  792. package/dist/workflow/registry.js +0 -18
  793. package/dist/workflow/registry.js.map +0 -1
  794. package/dist/workflow/templates.d.ts +0 -6
  795. package/dist/workflow/templates.d.ts.map +0 -1
  796. package/dist/workflow/templates.js +0 -18
  797. package/dist/workflow/templates.js.map +0 -1
  798. package/dist/workflow/triggers.d.ts +0 -64
  799. package/dist/workflow/triggers.d.ts.map +0 -1
  800. package/dist/workflow/triggers.js +0 -99
  801. package/dist/workflow/triggers.js.map +0 -1
  802. /package/{extension/README.md → docs/extension.md} +0 -0
@@ -0,0 +1,1796 @@
1
+ /**
2
+ * virtualmemory - virtual memory tiers, controllers and the host-aware
3
+ * extreme memory planner.
4
+ *
5
+ * This module owns everything memory related: the MEMORY_TIERS catalog with
6
+ * real bandwidth figures (DDR5-6400 system memory, HBM3e stacked memory at
7
+ * 8 TB/s, GDDR7 graphics memory at 1792 GB/s), MIG slicing profiles
8
+ * (1g.24gb, 2g.48gb, 4g.96gb), NUMA topology generation, huge page planning
9
+ * (1 GB and 2 MB), the kernel samepage merging controller, virtio ballooning,
10
+ * swap overcommit with vm.overcommit_memory=2 semantics, the tmpfs shader
11
+ * cache (20 GB), Docker memory flags (MemorySwap -1 and ShmSize 2g, the fix
12
+ * for the classic PyTorch DataLoader bus error), tiered memory controllers
13
+ * modeled on real silicon, a fluent region builder, a guarding region Proxy
14
+ * and the virtualmemorymanager facade that ties every technique together.
15
+ *
16
+ * The v2 merge adds two host-aware layers absorbed from the Meta sources:
17
+ * the placement tier taxonomy (DRAM_FAST, DRAM_SLOW, CXL_FM, CXL_PMEM,
18
+ * HBM_BLACKWELL, ZRAM, PMEM_DAX) with CXL 2.0/3.0 Type-3 device profiles,
19
+ * zram compression profiles, transparent huge page profiles and CCD-aware
20
+ * vCPU pinning for the Ryzen 9 9950X3D; and the memorymodularizer class
21
+ * that detects real host tiers (lspci CXL scan, /dev/pmem0, shared
22
+ * Blackwell memory), plans zram with workload-dependent compression
23
+ * factors, synthesizes tiered QEMU arguments, exports cgroup v2 slices and
24
+ * QMP runtime commands, and persists plans as JSON. /proc/meminfo
25
+ * generation (generateVirtualMeminfo, meminfoptions, pagealign) moved here
26
+ * from the processor module so every memory concern lives in one file.
27
+ *
28
+ * Modularity extremes are first class: 1 to 192 vCPUs, 1 to 1024 GB of RAM
29
+ * and 8 to 96 GB of VRAM, all user chosen and validated against hard limits.
30
+ *
31
+ * Bandwidth sources verified on 2026-08-22: JEDEC DDR5-6400 (51.2 GB/s per
32
+ * channel), NVIDIA B200 and AMD Instinct MI350X HBM3e (8 TB/s aggregate),
33
+ * GeForce RTX 5090 and RTX PRO 6000 Blackwell GDDR7 (1792 GB/s over a
34
+ * 512-bit bus). CXL figures follow the CXL 2.0/3.0 Type-3 fabric numbers
35
+ * (178-195 ns latency, 32-64 GB/s per x16 PCIe 5.0 link) documented in the
36
+ * project research; zram compression ratios (lzo-rle 3.1:1, zstd 4.2:1)
37
+ * follow the kernel zram documentation.
38
+ *
39
+ * Contexts (25): memoryerror, memorytierid, MEMORY_TIERS, memorylimits,
40
+ * MIGPROFILES, validatememoryrequest, buildnumatopology, planhugepages,
41
+ * ksmcontroller, ballooningcontroller, overcommitcontroller,
42
+ * planswapdevices, shadercachecontroller, dockerMemoryFlags,
43
+ * memorycontroller, memoryregion, regionledger, memorystats, memoryplan,
44
+ * virtualmemorymanager, placementtier, cxxldevice, zramprofile,
45
+ * memorymodularizer, generateVirtualMeminfo.
46
+ *
47
+ * Patterns: strategy (memorycontroller), builder (regionbuilder), registry
48
+ * (regionledger), proxy (guardregion), observer (memorystats), facade
49
+ * (virtualmemorymanager), planner (memorymodularizer).
50
+ * Rules: lowercase identifiers, english jsdoc, third person, no emoji,
51
+ * try/catch catcher on every fallible path, node:* built-ins only, and no
52
+ * hardcoded localhost address anywhere.
53
+ */
54
+ import { execSync } from 'node:child_process';
55
+ import { createHash, randomInt, randomUUID } from 'node:crypto';
56
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
57
+ import { cpus, totalmem } from 'node:os';
58
+ /* ------------------------------------------------------------------ */
59
+ /* Section 1: errors */
60
+ /* ------------------------------------------------------------------ */
61
+ /** Error thrown by every memory subsystem with an optional cause chain. */
62
+ export class memoryerror extends Error {
63
+ /** Machine readable subsystem tag. */
64
+ subsystem;
65
+ constructor(message, options) {
66
+ super(message, options);
67
+ this.name = 'memoryerror';
68
+ this.subsystem = options?.subsystem ?? 'virtualmemory';
69
+ }
70
+ }
71
+ /**
72
+ * MEMORY_TIERS: the catalog of virtual memory technologies with real
73
+ * bandwidth arithmetic. DDR5-6400 moves 51.2 GB/s per channel (2 channels
74
+ * on desktop parts such as Ryzen and Core Ultra, 12 channels on EPYC SP5),
75
+ * HBM3e delivers 8 TB/s aggregate on B200 and MI350X class accelerators and
76
+ * GDDR7 reaches 1792 GB/s across the 512-bit bus of RTX 5090 and RTX PRO
77
+ * 6000 Blackwell boards.
78
+ */
79
+ export const MEMORY_TIERS = {
80
+ ddr5: {
81
+ id: 'ddr5',
82
+ label: 'DDR5-6400 system memory',
83
+ technology: 'DDR5 SDRAM at 6400 MT/s',
84
+ perchannelgbs: 51.2,
85
+ channels: 12,
86
+ modulegb: 96,
87
+ latencyns: 76,
88
+ usedfor: 'guest RAM, page cache, tmpfs shader cache',
89
+ },
90
+ hbm3e: {
91
+ id: 'hbm3e',
92
+ label: 'HBM3e stacked memory',
93
+ technology: 'high bandwidth memory 3e, 8 stacks',
94
+ perchannelgbs: 1000,
95
+ channels: 8,
96
+ modulegb: 36,
97
+ latencyns: 29,
98
+ usedfor: 'datacenter accelerator memory (B200 192 GB, MI350X 288 GB)',
99
+ },
100
+ gddr7: {
101
+ id: 'gddr7',
102
+ label: 'GDDR7 graphics memory',
103
+ technology: 'GDDR7 at 28 Gbps over a 512-bit bus',
104
+ perchannelgbs: 224,
105
+ channels: 8,
106
+ modulegb: 16,
107
+ latencyns: 42,
108
+ usedfor: 'workstation and consumer GPUs (RTX 5090, RTX PRO 6000)',
109
+ },
110
+ };
111
+ /** Returns one tier descriptor, throwing for unknown identifiers. */
112
+ export function selecttier(id) {
113
+ const tier = MEMORY_TIERS[id];
114
+ if (tier === undefined) {
115
+ throw new memoryerror(`unknown memory tier "${id}"; valid tiers: ${Object.keys(MEMORY_TIERS).join(', ')}`);
116
+ }
117
+ return tier;
118
+ }
119
+ /** Aggregated bandwidth of one tier in GB/s (per channel times channels). */
120
+ export function tierbandwidthgbs(id) {
121
+ const tier = selecttier(id);
122
+ return Number((tier.perchannelgbs * tier.channels).toFixed(1));
123
+ }
124
+ /** Extremes of modularity supported by the virtual memory planner. */
125
+ export const memorylimits = {
126
+ minvcpu: 1,
127
+ maxvcpu: 192,
128
+ minramgb: 1,
129
+ maxramgb: 1024,
130
+ minvramgb: 8,
131
+ maxvramgb: 96,
132
+ };
133
+ /**
134
+ * MIG profiles available on the 96 GB virtual device. The identifiers keep
135
+ * the NVIDIA convention of compute-slice names: 1g.24gb exposes 24 GB
136
+ * slices (up to 4 instances), 2g.48gb exposes 48 GB slices (up to 2
137
+ * instances) and 4g.96gb dedicates the full 96 GB to one instance.
138
+ */
139
+ export const MIGPROFILES = [
140
+ { id: '1g.24gb', slicegb: 24, maxinstances: 4 },
141
+ { id: '2g.48gb', slicegb: 48, maxinstances: 2 },
142
+ { id: '4g.96gb', slicegb: 96, maxinstances: 1 },
143
+ ];
144
+ /** Resolves a MIG profile by identifier, throwing for unknown names. */
145
+ export function getmigprofile(id) {
146
+ if (id === 'off') {
147
+ return null;
148
+ }
149
+ const found = MIGPROFILES.find((profile) => profile.id === id);
150
+ if (found === undefined) {
151
+ throw new memoryerror(`unknown MIG profile "${id}"; valid profiles: ${MIGPROFILES.map((profile) => profile.id).join(', ')} or off`);
152
+ }
153
+ return found;
154
+ }
155
+ /**
156
+ * Validates a memory request against the hard limits and the MIG catalog.
157
+ * The function reuses the rule style of the core validator: it accumulates
158
+ * errors for limit violations, warnings for suspicious-but-legal layouts
159
+ * (for example RAM below 16 GB with 96 GB of VRAM, or ballooning suggested
160
+ * when RAM exceeds 512 GB) and builds a plan when the request is valid.
161
+ */
162
+ export function validatememoryrequest(request) {
163
+ const errors = [];
164
+ const warnings = [];
165
+ try {
166
+ const vcpus = request.vcpus ?? 8;
167
+ const ramgb = request.ramgb ?? 32;
168
+ const vramgb = request.vramgb ?? 24;
169
+ const tier = request.tier ?? 'ddr5';
170
+ if (!Number.isInteger(vcpus) || vcpus < memorylimits.minvcpu || vcpus > memorylimits.maxvcpu) {
171
+ errors.push(`vcpus must be an integer between ${memorylimits.minvcpu} and ${memorylimits.maxvcpu}`);
172
+ }
173
+ if (!Number.isFinite(ramgb) || ramgb < memorylimits.minramgb || ramgb > memorylimits.maxramgb) {
174
+ errors.push(`ramgb must be between ${memorylimits.minramgb} and ${memorylimits.maxramgb}`);
175
+ }
176
+ if (!Number.isFinite(vramgb) ||
177
+ vramgb < memorylimits.minvramgb ||
178
+ vramgb > memorylimits.maxvramgb) {
179
+ errors.push(`vramgb must be between ${memorylimits.minvramgb} and ${memorylimits.maxvramgb}`);
180
+ }
181
+ const mig = request.mig ?? 'off';
182
+ const profile = getmigprofile(mig);
183
+ if (profile !== null && profile.slicegb !== vramgb) {
184
+ errors.push(`MIG profile ${mig} implies ${profile.slicegb} GB slices but vramgb is ${vramgb}`);
185
+ }
186
+ if (ramgb < 16 && vramgb >= 64) {
187
+ warnings.push('vramgb far exceeds ramgb: host page cache may thrash during model loads');
188
+ }
189
+ if (ramgb >= 512) {
190
+ warnings.push('RAM at or above 512 GB benefits from 1 GB huge pages and ballooning');
191
+ }
192
+ if (tier === 'ddr5' && vramgb > 64) {
193
+ warnings.push('ddr5 backing for VRAM above 64 GB halves effective bandwidth; prefer gddr7 or hbm3e tiers');
194
+ }
195
+ if (errors.length > 0) {
196
+ return { valid: false, errors, warnings, plan: null };
197
+ }
198
+ return { valid: true, errors, warnings, plan: planmemory(vcpus, ramgb, vramgb, mig, tier) };
199
+ }
200
+ catch (cause) {
201
+ return {
202
+ valid: false,
203
+ errors: [`validatememoryrequest crashed: ${cause.message}`],
204
+ warnings,
205
+ plan: null,
206
+ };
207
+ }
208
+ }
209
+ /**
210
+ * Builds a NUMA topology for a vCPU count split across a node count. Local
211
+ * distance is 10 and remote nodes sit at 32, mirroring the NPS modes of
212
+ * AMD EPYC parts; cpu ranges are rendered as the compact lists used by
213
+ * lscpu and numactl.
214
+ */
215
+ export function buildnumatopology(vcpus, nodes) {
216
+ try {
217
+ if (!Number.isInteger(vcpus) || vcpus < 1) {
218
+ throw new memoryerror(`vcpus must be a positive integer, received ${vcpus}`);
219
+ }
220
+ if (!Number.isInteger(nodes) || nodes < 1 || nodes > 16) {
221
+ throw new memoryerror(`nodes must be between 1 and 16, received ${nodes}`);
222
+ }
223
+ const pernode = Math.ceil(vcpus / nodes);
224
+ const cpuranges = [];
225
+ for (let node = 0; node < nodes; node += 1) {
226
+ const start = node * pernode;
227
+ const end = Math.min(start + pernode, vcpus) - 1;
228
+ if (start > end) {
229
+ cpuranges.push('');
230
+ continue;
231
+ }
232
+ cpuranges.push(start === end ? String(start) : `${start}-${end}`);
233
+ }
234
+ const distances = [];
235
+ for (let row = 0; row < nodes; row += 1) {
236
+ const line = [];
237
+ for (let column = 0; column < nodes; column += 1) {
238
+ line.push(row === column ? 10 : 32);
239
+ }
240
+ distances.push(line);
241
+ }
242
+ return {
243
+ nodes,
244
+ cpuranges,
245
+ distances,
246
+ description: `${nodes} NUMA node(s), ${pernode} vCPU(s) per node, remote distance 32`,
247
+ };
248
+ }
249
+ catch (cause) {
250
+ if (cause instanceof memoryerror) {
251
+ throw cause;
252
+ }
253
+ throw new memoryerror('buildnumatopology failed', { cause: cause });
254
+ }
255
+ }
256
+ /** Curated NUMA presets for common EPYC thread counts. */
257
+ export const NUMATOPOLOGIES = [
258
+ buildnumatopology(192, 4),
259
+ buildnumatopology(192, 8),
260
+ buildnumatopology(128, 4),
261
+ buildnumatopology(96, 2),
262
+ buildnumatopology(64, 2),
263
+ buildnumatopology(32, 1),
264
+ ];
265
+ /**
266
+ * Plans huge page reservations for a RAM size. Machines with at least 256 GB
267
+ * reserve half of their RAM as 1 GB pages for large model weights, plus a
268
+ * pool of 2048 2 MB pages for medium allocations; smaller machines keep a
269
+ * 2 MB-only layout.
270
+ */
271
+ export function planhugepages(ramgb) {
272
+ try {
273
+ if (!Number.isFinite(ramgb) || ramgb <= 0) {
274
+ throw new memoryerror(`ramgb must be a positive number, received ${ramgb}`);
275
+ }
276
+ if (ramgb >= 256) {
277
+ const onegbpages = Math.floor(ramgb / 2);
278
+ return [
279
+ { size: '1G', count: onegbpages, coversgb: onegbpages },
280
+ { size: '2M', count: 2048, coversgb: 4 },
281
+ ];
282
+ }
283
+ const twombpages = Math.floor((ramgb * 1024) / 4);
284
+ return [
285
+ { size: '2M', count: twombpages, coversgb: Number(((twombpages * 2) / 1024).toFixed(2)) },
286
+ ];
287
+ }
288
+ catch (cause) {
289
+ if (cause instanceof memoryerror) {
290
+ throw cause;
291
+ }
292
+ throw new memoryerror('planhugepages failed', { cause: cause });
293
+ }
294
+ }
295
+ /**
296
+ * Kernel samepage merging controller. KSM scans anonymous pages and merges
297
+ * identical ones, which matters for dense virtual machines running the same
298
+ * runtime image; the controller models the sysfs knobs documented by the
299
+ * kernel (run, pages_to_scan, sleep_millisecs, merge_across_nodes) and
300
+ * estimates the deduplication ratio from the shared/sharing counters.
301
+ */
302
+ export class ksmcontroller {
303
+ #pagestoscan;
304
+ #sleepmillisecs;
305
+ #mergeacrossnodes;
306
+ #enabled;
307
+ constructor(pagestoscan = 1000, sleepmillisecs = 20) {
308
+ this.#pagestoscan = pagestoscan;
309
+ this.#sleepmillisecs = sleepmillisecs;
310
+ this.#mergeacrossnodes = true;
311
+ this.#enabled = false;
312
+ }
313
+ /** Enables KSM and returns the sysfs writes required. */
314
+ enable() {
315
+ this.#enabled = true;
316
+ return [
317
+ 'echo 1 > /sys/kernel/mm/ksm/run',
318
+ `echo ${this.#pagestoscan} > /sys/kernel/mm/ksm/pages_to_scan`,
319
+ `echo ${this.#sleepmillisecs} > /sys/kernel/mm/ksm/sleep_millisecs`,
320
+ `echo ${this.#mergeacrossnodes ? 1 : 0} > /sys/kernel/mm/ksm/merge_across_nodes`,
321
+ ];
322
+ }
323
+ /** Disables KSM, leaving the scan counters untouched. */
324
+ disable() {
325
+ this.#enabled = false;
326
+ return ['echo 0 > /sys/kernel/mm/ksm/run'];
327
+ }
328
+ /** Tunes the scanner aggressiveness. */
329
+ tune(pagestoscan, sleepmillisecs) {
330
+ this.#pagestoscan = Math.max(1, pagestoscan);
331
+ this.#sleepmillisecs = Math.max(1, sleepmillisecs);
332
+ return this;
333
+ }
334
+ /** Reports whether the controller is currently enabled. */
335
+ get running() {
336
+ return this.#enabled;
337
+ }
338
+ /**
339
+ * Estimates the deduplication ratio from the classic kernel counters:
340
+ * pages_shared counts merged unique pages and pages_sharing counts the
341
+ * extra references pointing at them.
342
+ */
343
+ estimatesavings(pagesshared, pagessharing) {
344
+ const total = pagesshared + pagessharing;
345
+ const ratio = total === 0 ? 0 : Number((pagessharing / total).toFixed(4));
346
+ const freedmb = Number(((pagessharing * 4) / 1024).toFixed(2));
347
+ return { ratio, freedmb };
348
+ }
349
+ /** Renders the sysfs plan for logs and provisioners. */
350
+ describe() {
351
+ return {
352
+ subsystem: 'ksm',
353
+ enabled: this.#enabled,
354
+ pagestoscan: this.#pagestoscan,
355
+ sleepmillisecs: this.#sleepmillisecs,
356
+ mergeacrossnodes: this.#mergeacrossnodes,
357
+ };
358
+ }
359
+ }
360
+ /**
361
+ * Virtio ballooning controller. The balloon lets the host reclaim guest
362
+ * memory on demand and gives it back under pressure; the controller tracks
363
+ * the current target and honors a deflate-on-OOM policy so guests never
364
+ * deadlock while the balloon is inflated.
365
+ */
366
+ export class ballooningcontroller {
367
+ #targetmb;
368
+ #maxmb;
369
+ #deflateonom;
370
+ constructor(maxmb) {
371
+ this.#targetmb = 0;
372
+ this.#maxmb = maxmb;
373
+ this.#deflateonom = true;
374
+ }
375
+ /** Inflates the balloon to a target in MB, clamped to the maximum. */
376
+ inflate(targetmb) {
377
+ try {
378
+ if (targetmb < 0) {
379
+ throw new memoryerror(`balloon target must be non-negative, received ${targetmb}`);
380
+ }
381
+ this.#targetmb = Math.min(targetmb, this.#maxmb);
382
+ return this.#targetmb;
383
+ }
384
+ catch (cause) {
385
+ throw new memoryerror('ballooningcontroller.inflate failed', { cause: cause });
386
+ }
387
+ }
388
+ /** Deflates the balloon by the requested amount, floored at zero. */
389
+ deflate(amountmb) {
390
+ this.#targetmb = Math.max(0, this.#targetmb - Math.max(0, amountmb));
391
+ return this.#targetmb;
392
+ }
393
+ /** Current balloon target in MB. */
394
+ get targetmb() {
395
+ return this.#targetmb;
396
+ }
397
+ /** Renders the QEMU device plan for the balloon. */
398
+ describe() {
399
+ return {
400
+ subsystem: 'ballooning',
401
+ device: 'virtio-balloon-pci',
402
+ targetmb: this.#targetmb,
403
+ maxmb: this.#maxmb,
404
+ deflateonom: this.#deflateonom,
405
+ };
406
+ }
407
+ }
408
+ /**
409
+ * Swap overcommit controller implementing the vm.overcommit_memory=2
410
+ * semantics documented in Documentation/mm/overcommit-accounting.rst: the
411
+ * total committed address space may never exceed swap plus a configurable
412
+ * percentage of RAM (overcommit_ratio, default 50). The controller computes
413
+ * the commit limit and recommends swap sizing for a target commit budget.
414
+ */
415
+ export class overcommitcontroller {
416
+ #ratio;
417
+ #mode;
418
+ constructor(ratio = 50) {
419
+ this.#ratio = ratio;
420
+ this.#mode = 2;
421
+ }
422
+ /** Sets the overcommit ratio percentage applied in mode 2. */
423
+ setratio(ratio) {
424
+ if (!Number.isFinite(ratio) || ratio < 0 || ratio > 100) {
425
+ throw new memoryerror(`overcommit ratio must be between 0 and 100, received ${ratio}`);
426
+ }
427
+ this.#ratio = ratio;
428
+ return this;
429
+ }
430
+ /** Computes the commit limit in GB for a RAM and swap configuration. */
431
+ commitlimitgb(ramgb, swapgb) {
432
+ return Number((swapgb + (ramgb * this.#ratio) / 100).toFixed(2));
433
+ }
434
+ /** Recommends the swap size in GB for a desired commit budget. */
435
+ recommendswapgb(ramgb, targetcommitgb) {
436
+ const swapneeded = targetcommitgb - (ramgb * this.#ratio) / 100;
437
+ return Number(Math.max(0, Math.ceil(swapneeded)).toFixed(2));
438
+ }
439
+ /** Renders the sysctl dictionary for this controller. */
440
+ sysctl() {
441
+ return {
442
+ 'vm.overcommit_memory': String(this.#mode),
443
+ 'vm.overcommit_ratio': String(this.#ratio),
444
+ 'vm.swappiness': '10',
445
+ 'vm.max_map_count': '1048576',
446
+ };
447
+ }
448
+ /** Renders the controller plan for logs and provisioners. */
449
+ describe() {
450
+ return { subsystem: 'overcommit', mode: this.#mode, ratio: this.#ratio };
451
+ }
452
+ }
453
+ /**
454
+ * Plans swap devices for a RAM size. ZRAM (compressed in-memory swap,
455
+ * priority 100) covers latency-sensitive reclaim while a swapfile or
456
+ * partition (priority -2) extends the commit budget required by mode 2
457
+ * overcommit for RAM-heavy builds.
458
+ */
459
+ export function planswapdevices(ramgb) {
460
+ try {
461
+ if (!Number.isFinite(ramgb) || ramgb <= 0) {
462
+ throw new memoryerror(`ramgb must be a positive number, received ${ramgb}`);
463
+ }
464
+ const zramsize = Math.min(Math.max(Math.round(ramgb / 8), 2), 32);
465
+ const devices = [
466
+ { kind: 'zram', sizegb: zramsize, priority: 100, compressed: true },
467
+ ];
468
+ if (ramgb >= 256) {
469
+ devices.push({
470
+ kind: 'swapfile',
471
+ sizegb: Math.min(Math.round(ramgb / 8), 128),
472
+ priority: -2,
473
+ compressed: false,
474
+ });
475
+ }
476
+ return devices;
477
+ }
478
+ catch (cause) {
479
+ if (cause instanceof memoryerror) {
480
+ throw cause;
481
+ }
482
+ throw new memoryerror('planswapdevices failed', { cause: cause });
483
+ }
484
+ }
485
+ /**
486
+ * Tmpfs shader cache controller. Mesa keeps its on-disk shader cache in
487
+ * MESA_SHADER_CACHE_DIR; hosting it on a size-capped tmpfs (20 GB by
488
+ * default) removes disk latency from shader compilation storms typical of
489
+ * LLVMpipe and Lavapipe sessions.
490
+ */
491
+ export class shadercachecontroller {
492
+ #sizegb;
493
+ #mountpoint;
494
+ constructor(sizegb = 20, mountpoint = '/tmp/shadercache') {
495
+ this.#sizegb = sizegb;
496
+ this.#mountpoint = mountpoint;
497
+ }
498
+ /** Renders the fstab line for the tmpfs mount. */
499
+ fstabline() {
500
+ return `tmpfs ${this.#mountpoint} tmpfs rw,size=${this.#sizegb}g,nodev,nosuid,noatime 0 0`;
501
+ }
502
+ /** Renders the environment block pointing Mesa at the cache. */
503
+ environment() {
504
+ return {
505
+ MESA_SHADER_CACHE_DIR: this.#mountpoint,
506
+ MESA_SHADER_CACHE_MAX_SIZE: `${this.#sizegb * 1024}`,
507
+ MESA_GLSL_CACHE_DISABLE: 'false',
508
+ };
509
+ }
510
+ /** Mount size in GB. */
511
+ get sizegb() {
512
+ return this.#sizegb;
513
+ }
514
+ /** Renders the controller plan for logs and provisioners. */
515
+ describe() {
516
+ return { subsystem: 'shadercache', sizegb: this.#sizegb, mountpoint: this.#mountpoint };
517
+ }
518
+ }
519
+ /**
520
+ * Generates Docker memory flags for a container. MemorySwap -1 keeps swap
521
+ * unlimited as documented by Docker ("unlimited swap, up to the amount
522
+ * available on the host system"), ShmSize 2g raises /dev/shm from the 64 MB
523
+ * default which is the canonical fix for the PyTorch DataLoader bus error,
524
+ * and the tmpfs entry mounts the 20 GB shader cache. Every value remains a
525
+ * suggestion: callers override before use.
526
+ */
527
+ export function dockerMemoryFlags(options) {
528
+ try {
529
+ const ramgb = options?.ramgb ?? 32;
530
+ const shmsizegb = options?.shmsizegb ?? 2;
531
+ const unlimitedswap = options?.unlimitedswap ?? true;
532
+ const run = [
533
+ `--memory=${ramgb}g`,
534
+ unlimitedswap ? '--memory-swap=-1' : `--memory-swap=${ramgb * 2}g`,
535
+ `--shm-size=${shmsizegb}g`,
536
+ '--tmpfs /tmp/shadercache:size=20g',
537
+ '--kernel-memory=0',
538
+ ];
539
+ const compose = {
540
+ mem_limit: `${ramgb}g`,
541
+ memswap_limit: unlimitedswap ? -1 : `${ramgb * 2}g`,
542
+ shm_size: `${shmsizegb}g`,
543
+ tmpfs: ['/tmp/shadercache:size=20g'],
544
+ oom_score_adj: -500,
545
+ };
546
+ const sysctl = {
547
+ 'vm.overcommit_memory': '2',
548
+ 'vm.overcommit_ratio': '50',
549
+ };
550
+ const rationale = [
551
+ 'memory-swap -1 grants unlimited swap per the Docker resource constraints documentation',
552
+ `shm-size ${shmsizegb}g avoids the PyTorch DataLoader bus error caused by the 64 MB /dev/shm default`,
553
+ 'tmpfs shader cache keeps Mesa compilation artifacts in RAM with a 20 GB ceiling',
554
+ 'overcommit mode 2 with ratio 50 bounds the commit limit to swap plus half the RAM',
555
+ ];
556
+ return { run, compose, sysctl, rationale };
557
+ }
558
+ catch (cause) {
559
+ throw new memoryerror('dockerMemoryFlags failed', { cause: cause });
560
+ }
561
+ }
562
+ /** Shared transfer math used by every controller implementation. */
563
+ function simulatetransfer(tier, bytes, direction, bandwidthgbs, latencyns) {
564
+ const effectivengbs = Number((bandwidthgbs * (direction === 'read' ? 1 : 0.92)).toFixed(2));
565
+ const timemicros = Number(((bytes / (effectivengbs * 1e9)) * 1e6 + latencyns / 1000).toFixed(4));
566
+ return { tier, bytes, direction, effectivengbs, timemicros };
567
+ }
568
+ /** DDR5 controller: channels aggregated, bandwidth scales linearly. */
569
+ export class ddr5controller {
570
+ tier = 'ddr5';
571
+ #channels;
572
+ #totalgb;
573
+ constructor(channels = 12, totalgb = 1024) {
574
+ this.#channels = Math.max(1, Math.min(channels, 12));
575
+ this.#totalgb = totalgb;
576
+ }
577
+ /** Aggregate bandwidth in GB/s for the configured channel count. */
578
+ get bandwidthgbs() {
579
+ return Number((MEMORY_TIERS.ddr5.perchannelgbs * this.#channels).toFixed(1));
580
+ }
581
+ /** Total capacity in GB. */
582
+ get totalgb() {
583
+ return this.#totalgb;
584
+ }
585
+ /** Simulates one transfer over the DDR5 interconnect. */
586
+ transfer(bytes, direction) {
587
+ return simulatetransfer(this.tier, bytes, direction, this.bandwidthgbs, MEMORY_TIERS.ddr5.latencyns);
588
+ }
589
+ /** Average column access latency in nanoseconds. */
590
+ latencyns() {
591
+ return MEMORY_TIERS.ddr5.latencyns;
592
+ }
593
+ /** Renders the controller plan for logs and provisioners. */
594
+ describe() {
595
+ return {
596
+ tier: this.tier,
597
+ channels: this.#channels,
598
+ bandwidthgbs: this.bandwidthgbs,
599
+ totalgb: this.#totalgb,
600
+ technology: MEMORY_TIERS.ddr5.technology,
601
+ };
602
+ }
603
+ }
604
+ /** HBM3e controller: eight stacks, 8 TB/s aggregate, near-SRAM latency. */
605
+ export class hbm3econtroller {
606
+ tier = 'hbm3e';
607
+ #stacks;
608
+ #totalgb;
609
+ constructor(stacks = 8, totalgb = 192) {
610
+ this.#stacks = Math.max(1, Math.min(stacks, 8));
611
+ this.#totalgb = totalgb;
612
+ }
613
+ /** Aggregate bandwidth in GB/s for the configured stack count. */
614
+ get bandwidthgbs() {
615
+ return Number((MEMORY_TIERS.hbm3e.perchannelgbs * this.#stacks).toFixed(1));
616
+ }
617
+ /** Total capacity in GB. */
618
+ get totalgb() {
619
+ return this.#totalgb;
620
+ }
621
+ /** Simulates one transfer over the HBM3e fabric. */
622
+ transfer(bytes, direction) {
623
+ return simulatetransfer(this.tier, bytes, direction, this.bandwidthgbs, MEMORY_TIERS.hbm3e.latencyns);
624
+ }
625
+ /** Stack access latency in nanoseconds. */
626
+ latencyns() {
627
+ return MEMORY_TIERS.hbm3e.latencyns;
628
+ }
629
+ /** Renders the controller plan for logs and provisioners. */
630
+ describe() {
631
+ return {
632
+ tier: this.tier,
633
+ stacks: this.#stacks,
634
+ bandwidthgbs: this.bandwidthgbs,
635
+ totalgb: this.#totalgb,
636
+ technology: MEMORY_TIERS.hbm3e.technology,
637
+ };
638
+ }
639
+ }
640
+ /** GDDR7 controller: 512-bit bus, 1792 GB/s at full width. */
641
+ export class gddr7controller {
642
+ tier = 'gddr7';
643
+ #channels;
644
+ #totalgb;
645
+ constructor(channels = 8, totalgb = 96) {
646
+ this.#channels = Math.max(1, Math.min(channels, 8));
647
+ this.#totalgb = totalgb;
648
+ }
649
+ /** Aggregate bandwidth in GB/s for the configured bus width. */
650
+ get bandwidthgbs() {
651
+ return Number((MEMORY_TIERS.gddr7.perchannelgbs * this.#channels).toFixed(1));
652
+ }
653
+ /** Total capacity in GB. */
654
+ get totalgb() {
655
+ return this.#totalgb;
656
+ }
657
+ /** Simulates one transfer over the GDDR7 bus. */
658
+ transfer(bytes, direction) {
659
+ return simulatetransfer(this.tier, bytes, direction, this.bandwidthgbs, MEMORY_TIERS.gddr7.latencyns);
660
+ }
661
+ /** Memory access latency in nanoseconds. */
662
+ latencyns() {
663
+ return MEMORY_TIERS.gddr7.latencyns;
664
+ }
665
+ /** Renders the controller plan for logs and provisioners. */
666
+ describe() {
667
+ return {
668
+ tier: this.tier,
669
+ channels: this.#channels,
670
+ bandwidthgbs: this.bandwidthgbs,
671
+ totalgb: this.#totalgb,
672
+ technology: MEMORY_TIERS.gddr7.technology,
673
+ };
674
+ }
675
+ }
676
+ /**
677
+ * Controller factory (Factory plus Registry patterns): maps a tier
678
+ * identifier to a controller instance sized by the caller. The const type
679
+ * parameter preserves literal tier identifiers through the call.
680
+ */
681
+ export function creatememorycontroller(tier, totalgb, channels) {
682
+ switch (tier) {
683
+ case 'ddr5':
684
+ return new ddr5controller(channels ?? 12, totalgb);
685
+ case 'hbm3e':
686
+ return new hbm3econtroller(channels ?? 8, totalgb);
687
+ case 'gddr7':
688
+ return new gddr7controller(channels ?? 8, totalgb);
689
+ default: {
690
+ throw new memoryerror(`no controller registered for tier "${tier}"`);
691
+ }
692
+ }
693
+ }
694
+ /** A virtual memory region bound to a tier and a purpose. */
695
+ export class memoryregion {
696
+ id;
697
+ tier;
698
+ purpose;
699
+ sizegb;
700
+ #allocated;
701
+ #accesses;
702
+ constructor(tier, purpose, sizegb) {
703
+ this.id = randomUUID();
704
+ this.tier = tier;
705
+ this.purpose = purpose;
706
+ this.sizegb = sizegb;
707
+ this.#allocated = true;
708
+ this.#accesses = 0;
709
+ }
710
+ /** Number of tracked accesses through proxies or direct reads. */
711
+ get accesses() {
712
+ return this.#accesses;
713
+ }
714
+ /** True while the region holds virtual backing. */
715
+ get allocated() {
716
+ return this.#allocated;
717
+ }
718
+ /** Counts one access; used by the guarding Proxy. */
719
+ touch() {
720
+ this.#accesses += 1;
721
+ }
722
+ /** Releases the region; idempotent and safe to call twice. */
723
+ release() {
724
+ this.#allocated = false;
725
+ }
726
+ /** Synchronous disposer so regions compose with `using` declarations. */
727
+ [Symbol.dispose]() {
728
+ this.release();
729
+ }
730
+ /** Renders the region plan for logs and provisioners. */
731
+ describe() {
732
+ return {
733
+ id: this.id,
734
+ tier: this.tier,
735
+ purpose: this.purpose,
736
+ sizegb: this.sizegb,
737
+ allocated: this.#allocated,
738
+ accesses: this.#accesses,
739
+ };
740
+ }
741
+ }
742
+ /**
743
+ * Fluent builder for memory regions. The builder accumulates tier, purpose
744
+ * and size, validates the result against the tier capacity and produces a
745
+ * memoryregion registered in the regionledger.
746
+ */
747
+ export class regionbuilder {
748
+ #tier;
749
+ #purpose;
750
+ #sizegb;
751
+ constructor() {
752
+ this.#tier = 'ddr5';
753
+ this.#purpose = 'guest';
754
+ this.#sizegb = 1;
755
+ }
756
+ /** Selects the memory tier backing the region. */
757
+ withtier(tier) {
758
+ this.#tier = tier;
759
+ return this;
760
+ }
761
+ /** Selects the purpose tag of the region. */
762
+ withpurpose(purpose) {
763
+ this.#purpose = purpose;
764
+ return this;
765
+ }
766
+ /** Sets the region size in GB. */
767
+ withsize(sizegb) {
768
+ this.#sizegb = sizegb;
769
+ return this;
770
+ }
771
+ /** Validates and materializes the region, registering it in the ledger. */
772
+ build() {
773
+ try {
774
+ if (!Number.isFinite(this.#sizegb) || this.#sizegb <= 0) {
775
+ throw new memoryerror(`region size must be a positive number, received ${this.#sizegb}`);
776
+ }
777
+ const tier = selecttier(this.#tier);
778
+ const capacity = tier.modulegb * tier.channels;
779
+ if (this.#sizegb > capacity) {
780
+ throw new memoryerror(`region of ${this.#sizegb} GB exceeds the ${capacity} GB capacity of tier ${this.#tier}`);
781
+ }
782
+ const region = new memoryregion(this.#tier, this.#purpose, this.#sizegb);
783
+ regionledger.set(region.id, region);
784
+ return region;
785
+ }
786
+ catch (cause) {
787
+ if (cause instanceof memoryerror) {
788
+ throw cause;
789
+ }
790
+ throw new memoryerror('regionbuilder.build failed', { cause: cause });
791
+ }
792
+ }
793
+ }
794
+ /**
795
+ * Wraps a region in a guarding Proxy (Proxy pattern). Every property access
796
+ * is counted and recorded in the access ledger; accesses to released
797
+ * regions raise a memoryerror so consumers notice stale handles
798
+ * immediately instead of silently reading freed virtual memory.
799
+ */
800
+ export function guardregion(region) {
801
+ return new Proxy(region, {
802
+ get(target, property, receiver) {
803
+ target.touch();
804
+ if (!target.allocated && property !== 'describe') {
805
+ throw new memoryerror(`region ${target.id} has been released and can no longer be accessed`);
806
+ }
807
+ return Reflect.get(target, property, receiver);
808
+ },
809
+ });
810
+ }
811
+ /** Ledger of every live region, keyed by region id (Map first policy). */
812
+ export const regionledger = new Map();
813
+ /** Ephemeral access counters; WeakMap keeps probes from pinning regions. */
814
+ const accessprobes = new WeakMap();
815
+ /** Records an access probe for a region without keeping it alive. */
816
+ export function proberegion(region, accesses) {
817
+ accessprobes.set(region, accesses);
818
+ }
819
+ /** Reads the last access probe recorded for a region, if any. */
820
+ export function readprobe(region) {
821
+ return accessprobes.get(region) ?? null;
822
+ }
823
+ /** Sums the size of every allocated region in the ledger. */
824
+ export function totalallocatedgb() {
825
+ let total = 0;
826
+ for (const region of regionledger.values()) {
827
+ if (region.allocated) {
828
+ total += region.sizegb;
829
+ }
830
+ }
831
+ return Number(total.toFixed(2));
832
+ }
833
+ /**
834
+ * Memory pressure observer. The observer keeps listeners in a Map keyed by
835
+ * name (never bound to a runtime event loop) and evaluates samples against
836
+ * the classic watermarks: low at 85 percent, high at 95 percent and
837
+ * critical at 99 percent of the tracked capacity.
838
+ */
839
+ export class memorystats {
840
+ #listeners;
841
+ #capacitygb;
842
+ #lastlevel;
843
+ #history;
844
+ constructor(capacitygb) {
845
+ this.#listeners = new Map();
846
+ this.#capacitygb = capacitygb;
847
+ this.#lastlevel = 'nominal';
848
+ this.#history = [];
849
+ }
850
+ /** Subscribes a named listener to pressure transitions. */
851
+ subscribe(name, listener) {
852
+ this.#listeners.set(name, listener);
853
+ return this;
854
+ }
855
+ /** Removes a named listener; returns true when it existed. */
856
+ unsubscribe(name) {
857
+ return this.#listeners.delete(name);
858
+ }
859
+ /** Evaluates one used-memory sample and publishes level transitions. */
860
+ evaluate(usedgb) {
861
+ try {
862
+ const usedfraction = Math.min(1, usedgb / this.#capacitygb);
863
+ this.#history.push(usedfraction);
864
+ if (this.#history.length > 512) {
865
+ this.#history.shift();
866
+ }
867
+ const level = usedfraction >= 0.99
868
+ ? 'critical'
869
+ : usedfraction >= 0.95
870
+ ? 'high'
871
+ : usedfraction >= 0.85
872
+ ? 'low'
873
+ : 'nominal';
874
+ if (level === 'nominal' || level === this.#lastlevel) {
875
+ return null;
876
+ }
877
+ this.#lastlevel = level;
878
+ const event = {
879
+ level,
880
+ usedfraction: Number(usedfraction.toFixed(4)),
881
+ at: Date.now(),
882
+ };
883
+ for (const listener of this.#listeners.values()) {
884
+ try {
885
+ listener(event);
886
+ }
887
+ catch {
888
+ /* listener faults never break the observer loop */
889
+ }
890
+ }
891
+ return event;
892
+ }
893
+ catch (cause) {
894
+ throw new memoryerror('memorystats.evaluate failed', { cause: cause });
895
+ }
896
+ }
897
+ /** Peak observed usage fraction since construction. */
898
+ get peak() {
899
+ return this.#history.length === 0 ? 0 : Number(Math.max(...this.#history).toFixed(4));
900
+ }
901
+ /** Mean observed usage fraction since construction. */
902
+ get mean() {
903
+ if (this.#history.length === 0) {
904
+ return 0;
905
+ }
906
+ const sum = this.#history.reduce((acc, value) => acc + value, 0);
907
+ return Number((sum / this.#history.length).toFixed(4));
908
+ }
909
+ }
910
+ /**
911
+ * Computes the full memory plan for a machine: bandwidth per tier, MIG
912
+ * instance count, huge page layout, swap devices, NUMA topology, /dev/shm
913
+ * size and the shader cache ceiling.
914
+ */
915
+ export function planmemory(vcpus, ramgb, vramgb, mig, tier) {
916
+ try {
917
+ const profile = getmigprofile(mig);
918
+ const miginstances = profile === null
919
+ ? 1
920
+ : Math.max(1, Math.floor(memorylimits.maxvramgb / profile.slicegb) *
921
+ (vramgb >= profile.slicegb ? 1 : 0) || 1);
922
+ const numa = buildnumatopology(vcpus, vcpus >= 128 ? 8 : vcpus >= 64 ? 4 : vcpus >= 32 ? 2 : 1);
923
+ return Object.freeze({
924
+ vcpus,
925
+ ramgb,
926
+ vramgb,
927
+ tier,
928
+ mig,
929
+ miginstances: profile === null ? 1 : Math.min(profile.maxinstances, miginstances),
930
+ rambandwidthgbs: tierbandwidthgbs('ddr5'),
931
+ vrambandwidthgbs: tierbandwidthgbs(tier === 'ddr5' ? 'gddr7' : tier),
932
+ hugepages: planhugepages(ramgb),
933
+ swapdevices: planswapdevices(ramgb),
934
+ numa,
935
+ shmsizegb: 2,
936
+ shadercachesizegb: 20,
937
+ });
938
+ }
939
+ catch (cause) {
940
+ if (cause instanceof memoryerror) {
941
+ throw cause;
942
+ }
943
+ throw new memoryerror('planmemory failed', { cause: cause });
944
+ }
945
+ }
946
+ /**
947
+ * Renders kernel boot arguments for the memory techniques enabled by a
948
+ * plan: default 1 GB huge pages plus a 2 MB pool, and the MIG-aware NUMA
949
+ * hints consumed by the virtual machine launcher.
950
+ */
951
+ export function buildKernelArgs(plan) {
952
+ try {
953
+ const parts = ['default_hugepagesz=1G'];
954
+ for (const page of plan.hugepages) {
955
+ parts.push(`hugepagesz=${page.size === '1G' ? '1G' : '2M'}`, `hugepages=${page.count}`);
956
+ }
957
+ parts.push(`numa=fake=${plan.numa.nodes}`);
958
+ return parts.join(' ');
959
+ }
960
+ catch (cause) {
961
+ throw new memoryerror('buildKernelArgs failed', { cause: cause });
962
+ }
963
+ }
964
+ /**
965
+ * Facade that composes every memory technique for one machine. The manager
966
+ * exposes the plan, the sysctl dictionary, the kernel arguments, the Docker
967
+ * flags, the tier controllers and the pressure observer, and keeps all
968
+ * mutable state in Maps so the instance stays runtime agnostic.
969
+ */
970
+ export class virtualmemorymanager {
971
+ #plan;
972
+ #controllers;
973
+ #ksm;
974
+ #balloon;
975
+ #overcommit;
976
+ #cache;
977
+ #stats;
978
+ constructor(plan) {
979
+ this.#plan = plan;
980
+ this.#controllers = new Map();
981
+ this.#controllers.set('ddr5', creatememorycontroller('ddr5', plan.ramgb, 12));
982
+ this.#controllers.set(plan.tier === 'ddr5' ? 'gddr7' : plan.tier, creatememorycontroller(plan.tier === 'ddr5' ? 'gddr7' : plan.tier, plan.vramgb, 8));
983
+ this.#ksm = new ksmcontroller(1000, 20);
984
+ this.#balloon = new ballooningcontroller(plan.ramgb * 1024);
985
+ this.#overcommit = new overcommitcontroller(50);
986
+ this.#cache = new shadercachecontroller(plan.shadercachesizegb);
987
+ this.#stats = new memorystats(plan.ramgb);
988
+ }
989
+ /** The frozen plan this manager was constructed from. */
990
+ get plan() {
991
+ return this.#plan;
992
+ }
993
+ /** The pressure observer of this machine. */
994
+ get stats() {
995
+ return this.#stats;
996
+ }
997
+ /** The KSM controller of this machine. */
998
+ get ksm() {
999
+ return this.#ksm;
1000
+ }
1001
+ /** The ballooning controller of this machine. */
1002
+ get balloon() {
1003
+ return this.#balloon;
1004
+ }
1005
+ /** Returns the controller bound to a tier, when configured. */
1006
+ controller(tier) {
1007
+ return this.#controllers.get(tier) ?? null;
1008
+ }
1009
+ /** Simulates a synthetic workload sample and evaluates pressure. */
1010
+ sample() {
1011
+ const usedgb = Number((this.#plan.ramgb * (randomInt(600, 990) / 1000)).toFixed(2));
1012
+ return this.#stats.evaluate(usedgb);
1013
+ }
1014
+ /** Renders the sysctl dictionary of every controller. */
1015
+ sysctl() {
1016
+ return { ...this.#overcommit.sysctl() };
1017
+ }
1018
+ /** Renders the kernel boot arguments for this machine. */
1019
+ kernelargs() {
1020
+ return buildKernelArgs(this.#plan);
1021
+ }
1022
+ /** Renders the Docker memory flags for this machine. */
1023
+ dockerflags() {
1024
+ return dockerMemoryFlags({
1025
+ ramgb: this.#plan.ramgb,
1026
+ shmsizegb: this.#plan.shmsizegb,
1027
+ unlimitedswap: true,
1028
+ });
1029
+ }
1030
+ /** Renders the fstab line of the shader cache tmpfs. */
1031
+ cachefstab() {
1032
+ return this.#cache.fstabline();
1033
+ }
1034
+ /** Renders a complete JSON-safe description of the machine memory. */
1035
+ describe() {
1036
+ return {
1037
+ plan: this.#plan,
1038
+ controllers: [...this.#controllers.values()].map((controller) => controller.describe()),
1039
+ ksm: this.#ksm.describe(),
1040
+ ballooning: this.#balloon.describe(),
1041
+ overcommit: this.#overcommit.describe(),
1042
+ shadercache: this.#cache.describe(),
1043
+ sysctl: this.sysctl(),
1044
+ kernelargs: this.kernelargs(),
1045
+ stats: { peak: this.#stats.peak, mean: this.#stats.mean },
1046
+ };
1047
+ }
1048
+ }
1049
+ /**
1050
+ * Factory that builds a virtualmemorymanager from a raw request. The
1051
+ * request is validated against the hard limits; failures raise memoryerror
1052
+ * with the accumulated validation errors for quick diagnosis.
1053
+ */
1054
+ export function createVirtualMemory(request) {
1055
+ try {
1056
+ const result = validatememoryrequest(request);
1057
+ if (!result.valid || result.plan === null) {
1058
+ throw new memoryerror(`invalid memory request: ${result.errors.join('; ')}`);
1059
+ }
1060
+ return new virtualmemorymanager(result.plan);
1061
+ }
1062
+ catch (cause) {
1063
+ if (cause instanceof memoryerror) {
1064
+ throw cause;
1065
+ }
1066
+ throw new memoryerror('createVirtualMemory failed', { cause: cause });
1067
+ }
1068
+ }
1069
+ /* ------------------------------------------------------------------ */
1070
+ /* Section 12: host-aware extreme planner (memorymodularizer) */
1071
+ /* ------------------------------------------------------------------ */
1072
+ /**
1073
+ * Parses a key=value config file into a lowercase-keyed dictionary. Missing
1074
+ * files and parse failures degrade to an empty record; this is the safe
1075
+ * loader contract inherited from the Meta module.
1076
+ */
1077
+ function loadkv(path) {
1078
+ const out = {};
1079
+ try {
1080
+ if (!existsSync(path)) {
1081
+ return out;
1082
+ }
1083
+ for (const raw of readFileSync(path, 'utf8').split('\n')) {
1084
+ const trimmed = raw.trim();
1085
+ if (trimmed.length === 0 || trimmed.startsWith('#') || trimmed.startsWith('[')) {
1086
+ continue;
1087
+ }
1088
+ const eq = trimmed.indexOf('=');
1089
+ if (eq > -1) {
1090
+ const key = trimmed.slice(0, eq).trim().toLowerCase();
1091
+ const value = trimmed
1092
+ .slice(eq + 1)
1093
+ .trim()
1094
+ .replace(/^["']|["']$/g, '');
1095
+ out[key] = value;
1096
+ }
1097
+ }
1098
+ }
1099
+ catch {
1100
+ /* unreadable config degrades to defaults */
1101
+ }
1102
+ return out;
1103
+ }
1104
+ /**
1105
+ * Host-aware extreme memory planner, the fusion of the Meta
1106
+ * MemoryModularizer and ExtremeMemoryPlanner. The planner detects the real
1107
+ * host memory tiers (CXL fabric devices via lspci, PMEM DAX devdax nodes,
1108
+ * shared Blackwell HBM), tunes zram with workload-dependent compression
1109
+ * factors, plans host-aware huge pages, pins vCPUs across the 9950X3D CCD
1110
+ * layout, synthesizes the tiered QEMU arguments, exports cgroup v2 slices
1111
+ * and QMP runtime commands, and persists the plan as JSON. All host
1112
+ * interaction is best effort: every probe is wrapped in a catcher and
1113
+ * degrades to the documented defaults.
1114
+ */
1115
+ export class memorymodularizer {
1116
+ #vmconfig;
1117
+ #qemuconfig;
1118
+ #passageconfig;
1119
+ #hostthreads;
1120
+ constructor(options) {
1121
+ const dir = options?.configdir ?? '.';
1122
+ this.#vmconfig = loadkv(`${dir}/vm.config`);
1123
+ this.#qemuconfig = loadkv(`${dir}/qemu.config`);
1124
+ this.#passageconfig = loadkv(`${dir}/passage.config`);
1125
+ this.#hostthreads = cpus().length;
1126
+ }
1127
+ /** Host logical thread count observed at construction. */
1128
+ get hostthreads() {
1129
+ return this.#hostthreads;
1130
+ }
1131
+ /**
1132
+ * Detects the real host tiers. DRAM splits 70/30 into fast and slow
1133
+ * bands; an lspci scan for CXL vendor 1e98 or an explicit qemu.config
1134
+ * cxl_enabled flag adds a CXL_FM tier; /dev/pmem0 adds a persistent
1135
+ * PMEM_DAX tier (128 GB, 300 ns, 15 GB/s); a shared_host_mem blackwell
1136
+ * flag exposes half of the GPU VRAM as HBM_BLACKWELL through memfd.
1137
+ */
1138
+ detecthosttiers() {
1139
+ try {
1140
+ const totalmb = Math.floor(totalmem() / (1024 * 1024));
1141
+ const tiers = [
1142
+ {
1143
+ tier: 'DRAM_FAST',
1144
+ sizemb: Math.floor(totalmb * 0.7),
1145
+ latencyns: 78,
1146
+ bandwidthgbps: 89.6,
1147
+ qemubackend: 'memory-backend-ram',
1148
+ },
1149
+ {
1150
+ tier: 'DRAM_SLOW',
1151
+ sizemb: Math.floor(totalmb * 0.3),
1152
+ latencyns: 95,
1153
+ bandwidthgbps: 67,
1154
+ qemubackend: 'memory-backend-ram',
1155
+ },
1156
+ ];
1157
+ try {
1158
+ const lspci = execSync('lspci -d 1e98: 2>/dev/null || true', { encoding: 'utf8' });
1159
+ if (lspci.includes('CXL') || this.#qemuconfig.cxl_enabled === 'true') {
1160
+ tiers.push({
1161
+ tier: 'CXL_FM',
1162
+ sizemb: Number.parseInt(this.#qemuconfig.cxl_size_mb ?? '65536', 10),
1163
+ latencyns: 170,
1164
+ bandwidthgbps: 32,
1165
+ qemubackend: 'memory-backend-file',
1166
+ extraopts: { mem_path: '/dev/cxl/mem0', share: true },
1167
+ });
1168
+ }
1169
+ }
1170
+ catch {
1171
+ /* lspci unavailable: CXL tier stays hidden */
1172
+ }
1173
+ try {
1174
+ if (existsSync('/dev/pmem0')) {
1175
+ tiers.push({
1176
+ tier: 'PMEM_DAX',
1177
+ sizemb: 131072,
1178
+ latencyns: 300,
1179
+ bandwidthgbps: 15,
1180
+ persistent: true,
1181
+ qemubackend: 'memory-backend-file',
1182
+ extraopts: { mem_path: '/dev/pmem0', pmem: true },
1183
+ });
1184
+ }
1185
+ }
1186
+ catch {
1187
+ /* devdax probe failed: PMEM tier stays hidden */
1188
+ }
1189
+ if (this.#vmconfig.shared_host_mem === 'true') {
1190
+ const vramgb = Number(this.#vmconfig.blackwell_vram_gb ?? 32);
1191
+ tiers.push({
1192
+ tier: 'HBM_BLACKWELL',
1193
+ sizemb: Math.floor(vramgb * 1024 * 0.5),
1194
+ latencyns: 120,
1195
+ bandwidthgbps: 224,
1196
+ qemubackend: 'memory-backend-memfd',
1197
+ extraopts: { share: true },
1198
+ });
1199
+ }
1200
+ return tiers;
1201
+ }
1202
+ catch (cause) {
1203
+ throw new memoryerror('detecthosttiers failed', { cause: cause });
1204
+ }
1205
+ }
1206
+ /**
1207
+ * Plans zram sizing and command sequence for a requested capacity. The
1208
+ * compression factor adapts to the workload type from passage.config
1209
+ * (media_transcode 1.8, build 3.2, default 2.5) and to the algorithm
1210
+ * (zstd x1.15, lzo-rle x0.92); the disksize takes 30 percent of the
1211
+ * request and the returned commands cover modprobe, comp_algorithm,
1212
+ * disksize, mkswap and swapon at priority 100.
1213
+ */
1214
+ configurezram(requestedmb, algorithm = 'zstd', workload) {
1215
+ try {
1216
+ if (!Number.isFinite(requestedmb) || requestedmb <= 0) {
1217
+ throw new memoryerror(`requestedmb must be a positive number, received ${requestedmb}`);
1218
+ }
1219
+ const kind = workload ?? this.#passageconfig.workload_type ?? 'general';
1220
+ let factor = 2.5;
1221
+ if (kind === 'media_transcode') {
1222
+ factor = 1.8;
1223
+ }
1224
+ if (kind === 'build') {
1225
+ factor = 3.2;
1226
+ }
1227
+ if (algorithm === 'zstd') {
1228
+ factor *= 1.15;
1229
+ }
1230
+ if (algorithm === 'lzo-rle') {
1231
+ factor *= 0.92;
1232
+ }
1233
+ const disksizemb = Math.floor(requestedmb * 0.3);
1234
+ const commands = [
1235
+ 'modprobe zram num_devices=2',
1236
+ `echo ${algorithm} > /sys/block/zram0/comp_algorithm`,
1237
+ `echo ${disksizemb}M > /sys/block/zram0/disksize`,
1238
+ 'mkswap /dev/zram0 && swapon /dev/zram0 -p 100',
1239
+ ];
1240
+ return { enabled: true, factor: Number(factor.toFixed(2)), disksizemb, commands };
1241
+ }
1242
+ catch (cause) {
1243
+ if (cause instanceof memoryerror) {
1244
+ throw cause;
1245
+ }
1246
+ throw new memoryerror('configurezram failed', { cause: cause });
1247
+ }
1248
+ }
1249
+ /**
1250
+ * Host-aware huge page planning. Unlike the static planhugepages this
1251
+ * variant reads HugePages_Total from /proc/meminfo, honors the thp_enabled
1252
+ * knob from qemu.config for the transparent policy and mounts under
1253
+ * /dev/hugepages or /dev/hugepages-1G depending on the preferred size.
1254
+ */
1255
+ planhugepageshost(totalmb, prefer = '2M') {
1256
+ try {
1257
+ if (!Number.isFinite(totalmb) || totalmb <= 0) {
1258
+ throw new memoryerror(`totalmb must be a positive number, received ${totalmb}`);
1259
+ }
1260
+ const sizekb = prefer === '1G' ? 1048576 : 2048;
1261
+ const wanted = Math.ceil((totalmb * 1024) / sizekb);
1262
+ let available = 0;
1263
+ try {
1264
+ const meminfo = readFileSync('/proc/meminfo', 'utf8');
1265
+ const match = /HugePages_Total:\s+(\d+)/.exec(meminfo);
1266
+ available = match === null ? 0 : Number.parseInt(match[1], 10);
1267
+ }
1268
+ catch {
1269
+ /* no procfs: fall back to the computed count */
1270
+ }
1271
+ return {
1272
+ sizekb,
1273
+ count: Math.max(wanted, available),
1274
+ mount: prefer === '1G' ? '/dev/hugepages1G' : '/dev/hugepages',
1275
+ transparent: this.#qemuconfig.thp_enabled !== 'false',
1276
+ };
1277
+ }
1278
+ catch (cause) {
1279
+ if (cause instanceof memoryerror) {
1280
+ throw cause;
1281
+ }
1282
+ throw new memoryerror('planhugepageshost failed', { cause: cause });
1283
+ }
1284
+ }
1285
+ /**
1286
+ * Builds the CCD-aware pinning map for a virtual machine. Even vCPUs map
1287
+ * onto CCD0 (the 3D V-Cache complex) and odd vCPUs onto CCD1; two host
1288
+ * threads stay isolated for the emulator and the host. X3D parts report
1289
+ * two dies, matching the 9950X3D topology.
1290
+ */
1291
+ buildpinningmap(vmid, vcpucount) {
1292
+ try {
1293
+ if (vmid.trim().length === 0) {
1294
+ throw new memoryerror('vmid must not be empty');
1295
+ }
1296
+ if (!Number.isInteger(vcpucount) || vcpucount < 1) {
1297
+ throw new memoryerror(`vcpucount must be a positive integer, received ${vcpucount}`);
1298
+ }
1299
+ const hostthreads = Math.max(2, this.#hostthreads);
1300
+ const vcpus = Math.min(vcpucount, hostthreads - 2);
1301
+ const half = Math.max(1, Math.floor(hostthreads / 2));
1302
+ const ccd0 = Array.from({ length: Math.min(half, hostthreads) }, (_, i) => i).slice(0, half);
1303
+ const ccd1 = Array.from({ length: half }, (_, i) => i + half);
1304
+ const map = new Map();
1305
+ for (let v = 0; v < vcpus; v += 1) {
1306
+ const pool = v % 2 === 0 ? ccd0 : ccd1;
1307
+ map.set(v, [pool[v % pool.length] ?? pool[0]]);
1308
+ }
1309
+ return {
1310
+ vmid,
1311
+ map,
1312
+ isolated: [hostthreads - 2, hostthreads - 1],
1313
+ topology: {
1314
+ sockets: 1,
1315
+ dies: this.#vmconfig.x3d === 'true' ? 2 : 1,
1316
+ cores: vcpus,
1317
+ threads: 1,
1318
+ },
1319
+ };
1320
+ }
1321
+ catch (cause) {
1322
+ if (cause instanceof memoryerror) {
1323
+ throw cause;
1324
+ }
1325
+ throw new memoryerror('buildpinningmap failed', { cause: cause });
1326
+ }
1327
+ }
1328
+ /**
1329
+ * Builds the complete host-aware plan for a virtual machine. The memory
1330
+ * tier policy (performance, capacity or balanced) selects the tier mix:
1331
+ * performance dedicates DRAM_FAST, capacity spreads 60/30/10 across
1332
+ * DRAM/CXL/zram and balanced keeps 70/20 DRAM/zram plus 10 percent
1333
+ * Blackwell HBM when the shared flag is set. The plan carries the tiered
1334
+ * QEMU argument synthesis (cxl-type3 on bus cxl.0, virtio-mem-pci with 2M
1335
+ * blocks for HBM, memory-backend-ram/memfd/file objects, two NUMA nodes,
1336
+ * the avx-512 host cpu line, the balloon with free-page reporting and the
1337
+ * vsock chardev) and the compression-adjusted effective usable capacity.
1338
+ */
1339
+ buildhostplan(vmid, options) {
1340
+ try {
1341
+ const requestedmb = options?.requestedmb ?? 8192;
1342
+ const vcpucount = options?.vcpus ?? 8;
1343
+ const policy = options?.policy ?? this.#vmconfig.memory_tier_policy ?? 'balanced';
1344
+ if (!Number.isFinite(requestedmb) || requestedmb <= 0) {
1345
+ throw new memoryerror(`requestedmb must be a positive number, received ${requestedmb}`);
1346
+ }
1347
+ let tiers;
1348
+ if (policy === 'performance') {
1349
+ tiers = [
1350
+ {
1351
+ tier: 'DRAM_FAST',
1352
+ sizemb: requestedmb,
1353
+ latencyns: 78,
1354
+ bandwidthgbps: 89.6,
1355
+ qemubackend: 'memory-backend-ram',
1356
+ },
1357
+ ];
1358
+ }
1359
+ else if (policy === 'capacity') {
1360
+ tiers = [
1361
+ {
1362
+ tier: 'DRAM_FAST',
1363
+ sizemb: Math.floor(requestedmb * 0.6),
1364
+ latencyns: 78,
1365
+ bandwidthgbps: 89.6,
1366
+ qemubackend: 'memory-backend-ram',
1367
+ },
1368
+ {
1369
+ tier: 'CXL_FM',
1370
+ sizemb: Math.floor(requestedmb * 0.3),
1371
+ latencyns: 170,
1372
+ bandwidthgbps: 32,
1373
+ qemubackend: 'memory-backend-file',
1374
+ extraopts: { mem_path: '/dev/cxl/mem0', share: true },
1375
+ },
1376
+ {
1377
+ tier: 'ZRAM',
1378
+ sizemb: requestedmb - Math.floor(requestedmb * 0.6) - Math.floor(requestedmb * 0.3),
1379
+ latencyns: 250,
1380
+ bandwidthgbps: 20,
1381
+ compressionratio: 2.5,
1382
+ qemubackend: 'memory-backend-ram',
1383
+ },
1384
+ ];
1385
+ }
1386
+ else {
1387
+ const usehbm = this.#vmconfig.shared_host_mem === 'true';
1388
+ tiers = [
1389
+ {
1390
+ tier: 'DRAM_FAST',
1391
+ sizemb: Math.floor(requestedmb * 0.7),
1392
+ latencyns: 78,
1393
+ bandwidthgbps: 89.6,
1394
+ qemubackend: 'memory-backend-ram',
1395
+ },
1396
+ {
1397
+ tier: 'ZRAM',
1398
+ sizemb: Math.floor(requestedmb * 0.2),
1399
+ latencyns: 250,
1400
+ bandwidthgbps: 20,
1401
+ compressionratio: 2.5,
1402
+ qemubackend: 'memory-backend-ram',
1403
+ },
1404
+ ...(usehbm
1405
+ ? [
1406
+ {
1407
+ tier: 'HBM_BLACKWELL',
1408
+ sizemb: Math.floor(requestedmb * 0.1),
1409
+ latencyns: 120,
1410
+ bandwidthgbps: 224,
1411
+ qemubackend: 'memory-backend-memfd',
1412
+ extraopts: { share: true },
1413
+ },
1414
+ ]
1415
+ : []),
1416
+ ];
1417
+ }
1418
+ const prefer = requestedmb > 16384 ? '1G' : '2M';
1419
+ const hp = this.planhugepageshost(requestedmb, prefer);
1420
+ const zramplan = this.configurezram(requestedmb, 'zstd');
1421
+ const pinning = this.buildpinningmap(vmid, vcpucount);
1422
+ const cxl = policy === 'performance'
1423
+ ? []
1424
+ : [
1425
+ {
1426
+ id: 'cxl-mem0',
1427
+ spec: '3.0',
1428
+ type: 'type3',
1429
+ sizemb: 65536,
1430
+ latencyns: 178,
1431
+ bwgbps: 64,
1432
+ qosclass: 2,
1433
+ decoders: 4,
1434
+ interleaveways: 4,
1435
+ },
1436
+ ];
1437
+ const hugepages = {
1438
+ size: prefer,
1439
+ count: hp.count,
1440
+ mount: prefer === '1G' ? '/dev/hugepages-1G' : '/dev/hugepages',
1441
+ transparent: hp.transparent ? 'madvise' : 'never',
1442
+ shared: prefer === '1G',
1443
+ memfd: true,
1444
+ };
1445
+ const zram = {
1446
+ device: '/dev/zram0',
1447
+ algorithm: 'zstd',
1448
+ level: 1,
1449
+ disksizemb: zramplan.disksizemb,
1450
+ compratioachieved: 4.2,
1451
+ memusedmb: Math.floor(zramplan.disksizemb / 4.2),
1452
+ mountpoint: '/mnt/vhe-zram',
1453
+ };
1454
+ const halfthreads = Math.max(1, Math.floor(Math.max(2, this.#hostthreads) / 2));
1455
+ const vcpu = {
1456
+ vmid,
1457
+ totalvcpus: pinning.topology.cores,
1458
+ topology: {
1459
+ sockets: 1,
1460
+ dies: pinning.topology.dies,
1461
+ ccds: pinning.topology.dies,
1462
+ cores: pinning.topology.cores,
1463
+ threads: pinning.topology.cores * pinning.topology.threads,
1464
+ },
1465
+ ccd0: {
1466
+ cpus: Array.from({ length: halfthreads }, (_, i) => i),
1467
+ vcache: true,
1468
+ l3mb: 96,
1469
+ preferredfor: ['video', 'cuda_filter', 'encode', 'latency_sensitive'],
1470
+ },
1471
+ ccd1: {
1472
+ cpus: Array.from({ length: halfthreads }, (_, i) => i + halfthreads),
1473
+ vcache: false,
1474
+ l3mb: 32,
1475
+ preferredfor: ['audio', 'io', 'mux', 'throughput'],
1476
+ },
1477
+ pinning: pinning.map,
1478
+ isolated: pinning.isolated,
1479
+ numapolicy: 'strict',
1480
+ emulatorpin: [Math.max(1, this.#hostthreads) - 1],
1481
+ };
1482
+ const hugetlbsize = prefer === '1G' ? '1073741824' : '2097152';
1483
+ const qemuargs = [
1484
+ `-m ${requestedmb}`,
1485
+ '-object memory-backend-ram,id=ram-fast,size=' +
1486
+ `${tiers[0]?.sizemb ?? requestedmb}M,prealloc=on,host-nodes=0,policy=bind`,
1487
+ '-object memory-backend-memfd,id=ram-huge,size=' +
1488
+ `${hugepages.count * (prefer === '1G' ? 1024 : 2)}M,hugetlb=on,hugetlbsize=${hugetlbsize}`,
1489
+ ];
1490
+ if (cxl.length > 0) {
1491
+ qemuargs.push(`-object memory-backend-file,id=cxl-mem0,mem-path=/dev/cxl/${cxl[0].id},size=${cxl[0].sizemb}M,share=on`, '-device cxl-type3,bus=cxl.0,memdev=cxl-mem0,id=cxl-0');
1492
+ }
1493
+ for (const [index, tier] of tiers.entries()) {
1494
+ if (tier.tier === 'HBM_BLACKWELL') {
1495
+ qemuargs.push(`-object memory-backend-memfd,id=blackwell-${index},size=${tier.sizemb}M,share=on`, `-device virtio-mem-pci,node=0,block-size=2M,requested-size=${tier.sizemb}M,memdev=blackwell-${index}`);
1496
+ }
1497
+ }
1498
+ qemuargs.push(`-numa node,nodeid=0,cpus=0-${Math.max(0, vcpu.totalvcpus - 1)},memdev=ram-fast`);
1499
+ if (cxl.length > 0) {
1500
+ qemuargs.push('-numa node,nodeid=1,memdev=cxl-mem0');
1501
+ }
1502
+ qemuargs.push('-cpu host,migratable=no,+topoext,avx512f,avx512bw,avx512cd,avx512dq,avx512vl', '-device virtio-balloon,auto-balloon=on,free-page-reporting=on,free-page-hinting=on', '-chardev vsock,id=passage-ctrl,cid=2,port=1024', '-device vhost-vsock-pci,guest-cid=3');
1503
+ const effectiveusable = tiers.reduce((acc, tier) => acc + tier.sizemb * (tier.compressionratio ?? 1), 0);
1504
+ const digest = createHash('sha256')
1505
+ .update(JSON.stringify(tiers))
1506
+ .update(JSON.stringify([...pinning.map]))
1507
+ .digest('hex')
1508
+ .slice(0, 16);
1509
+ return {
1510
+ vmid,
1511
+ totalrequestedmb: requestedmb,
1512
+ effectiveusablemb: Math.floor(effectiveusable),
1513
+ tiers,
1514
+ hugepages,
1515
+ zram,
1516
+ cxl,
1517
+ vcpu,
1518
+ qemuargs,
1519
+ backendsdigest: digest,
1520
+ };
1521
+ }
1522
+ catch (cause) {
1523
+ if (cause instanceof memoryerror) {
1524
+ throw cause;
1525
+ }
1526
+ throw new memoryerror('buildhostplan failed', { cause: cause });
1527
+ }
1528
+ }
1529
+ /**
1530
+ * Calculates the balloon target under host pressure. Pressure below 0.3
1531
+ * leaves the guest untouched; above it the balloon reclaims half of the
1532
+ * excess, never dropping below 50 percent of the current allocation. A
1533
+ * host free memory below 4 GB escalates the effective pressure to at
1534
+ * least 0.5 so the balloon engages before the host starts swapping.
1535
+ */
1536
+ calculateballoontarget(currentmb, hostfreemb, pressure) {
1537
+ try {
1538
+ if (!Number.isFinite(currentmb) || currentmb <= 0) {
1539
+ throw new memoryerror(`currentmb must be a positive number, received ${currentmb}`);
1540
+ }
1541
+ if (!Number.isFinite(hostfreemb) || hostfreemb < 0) {
1542
+ throw new memoryerror(`hostfreemb must be a non-negative number, received ${hostfreemb}`);
1543
+ }
1544
+ if (!Number.isFinite(pressure) || pressure < 0 || pressure > 1) {
1545
+ throw new memoryerror(`pressure must be between 0 and 1, received ${pressure}`);
1546
+ }
1547
+ const effective = hostfreemb < 4096 ? Math.max(pressure, 0.5) : pressure;
1548
+ if (effective < 0.3) {
1549
+ return currentmb;
1550
+ }
1551
+ const reduction = Math.floor(currentmb * (effective - 0.3) * 0.5);
1552
+ const minmb = Math.floor(currentmb * 0.5);
1553
+ return Math.max(minmb, currentmb - reduction);
1554
+ }
1555
+ catch (cause) {
1556
+ if (cause instanceof memoryerror) {
1557
+ throw cause;
1558
+ }
1559
+ throw new memoryerror('calculateballoontarget failed', { cause: cause });
1560
+ }
1561
+ }
1562
+ /**
1563
+ * Renders the cgroup v2 slice configuration for a plan: MemoryMax at the
1564
+ * requested size, MemorySwapMax at 1.5x, AllowedCPUs from the isolated
1565
+ * pinning set and MemoryZSwapMax at the zram disksize.
1566
+ */
1567
+ generatecgroupv2config(plan) {
1568
+ try {
1569
+ return [
1570
+ '[slice]',
1571
+ `MemoryMax=${plan.totalrequestedmb}M`,
1572
+ `MemorySwapMax=${Math.floor(plan.totalrequestedmb * 1.5)}M`,
1573
+ `AllowedCPUs=${plan.vcpu.isolated.join(',')}`,
1574
+ `MemoryZSwapMax=${plan.zram.disksizemb}M`,
1575
+ `# hugepages ${plan.hugepages.mount} size ${plan.hugepages.size} count ${plan.hugepages.count}`,
1576
+ `# backends ${plan.backendsdigest}`,
1577
+ ].join('\n');
1578
+ }
1579
+ catch (cause) {
1580
+ throw new memoryerror('generatecgroupv2config failed', { cause: cause });
1581
+ }
1582
+ }
1583
+ /**
1584
+ * Exports the QMP runtime commands that apply a plan without a restart:
1585
+ * one balloon command sized to the requested memory plus object-add
1586
+ * commands for every CXL fabric tier.
1587
+ */
1588
+ exportqmpmemorycommands(plan) {
1589
+ try {
1590
+ const commands = [
1591
+ { execute: 'balloon', arguments: { value: plan.totalrequestedmb * 1024 * 1024 } },
1592
+ ];
1593
+ for (const [index, tier] of plan.tiers.entries()) {
1594
+ if (tier.tier !== 'CXL_FM') {
1595
+ continue;
1596
+ }
1597
+ commands.push({
1598
+ execute: 'object-add',
1599
+ arguments: {
1600
+ 'qom-type': tier.qemubackend,
1601
+ id: `cxl-mem-${index}`,
1602
+ props: {
1603
+ size: tier.sizemb * 1024 * 1024,
1604
+ 'mem-path': tier.extraopts?.mem_path,
1605
+ share: true,
1606
+ },
1607
+ },
1608
+ });
1609
+ }
1610
+ return commands;
1611
+ }
1612
+ catch (cause) {
1613
+ throw new memoryerror('exportqmpmemorycommands failed', { cause: cause });
1614
+ }
1615
+ }
1616
+ /**
1617
+ * Persists a plan as JSON next to the caller's chosen path. The pinning
1618
+ * Map is materialized as a plain object so the file round-trips without
1619
+ * loss; write failures raise a memoryerror with the cause chain.
1620
+ */
1621
+ saveplan(plan, outpath) {
1622
+ try {
1623
+ const target = outpath ?? `memory-plan-${plan.vmid}.json`;
1624
+ const serializable = {
1625
+ ...plan,
1626
+ vcpu: {
1627
+ ...plan.vcpu,
1628
+ pinning: Object.fromEntries([...plan.vcpu.pinning].map(([vcpu, hostcpus]) => [vcpu, [...hostcpus]])),
1629
+ },
1630
+ };
1631
+ writeFileSync(target, JSON.stringify(serializable, null, 2));
1632
+ return target;
1633
+ }
1634
+ catch (cause) {
1635
+ throw new memoryerror('saveplan failed', { cause: cause });
1636
+ }
1637
+ }
1638
+ }
1639
+ /** Rounds a kB value down to the nearest 4 kB page boundary. */
1640
+ export function pagealign(kb) {
1641
+ return Math.floor(kb / 4) * 4;
1642
+ }
1643
+ /**
1644
+ * Generates a complete /proc/meminfo text for a machine with the requested
1645
+ * total RAM. Every value is expressed in kB exactly like the kernel report:
1646
+ * MemTotal, MemFree, MemAvailable, Buffers, Cached, the anon/file split,
1647
+ * SwapTotal and SwapFree, slab accounting, commit accounting under
1648
+ * vm.overcommit_memory=2 semantics, virtual memory areas, huge page state
1649
+ * and the direct map breakdown.
1650
+ *
1651
+ * @param totalgb Total guest RAM in GB (positive number).
1652
+ * @param options Optional swap size, vCPU count, fractions and huge pages.
1653
+ */
1654
+ export function generateVirtualMeminfo(totalgb, options) {
1655
+ try {
1656
+ if (!Number.isFinite(totalgb) || totalgb <= 0) {
1657
+ throw new memoryerror(`totalgb must be a positive number, received ${totalgb}`);
1658
+ }
1659
+ const vcpus = options?.vcpus ?? 8;
1660
+ const totalkb = pagealign(totalgb * 1024 * 1024 - 131072);
1661
+ const freefraction = options?.freefraction ?? randomInt(38, 68) / 1000;
1662
+ const availablefraction = options?.availablefraction ?? randomInt(860, 930) / 1000;
1663
+ const memfree = pagealign(totalkb * freefraction);
1664
+ const memavailable = pagealign(totalkb * availablefraction);
1665
+ const buffers = pagealign(totalkb * (randomInt(50, 80) / 10000));
1666
+ const cached = pagealign(totalkb * (randomInt(300, 420) / 1000));
1667
+ const activeanon = pagealign(totalkb * (randomInt(240, 320) / 1000));
1668
+ const inactiveanon = pagealign(totalkb * (randomInt(60, 120) / 1000));
1669
+ const active = pagealign(activeanon + cached * 0.55);
1670
+ const inactive = pagealign(inactiveanon + cached * 0.4);
1671
+ const swapgb = options?.swapgb ?? Math.min(Math.max(Math.round(totalgb / 8), 2), 128);
1672
+ const swaptotal = swapgb * 1024 * 1024;
1673
+ const swapfree = pagealign(swaptotal * (randomInt(850, 980) / 1000));
1674
+ const overcommitratio = options?.overcommitratio ?? 50;
1675
+ const commitlimit = pagealign(swaptotal + (totalkb * overcommitratio) / 100);
1676
+ const committedas = pagealign(totalkb * (randomInt(95, 160) / 100));
1677
+ const slab = pagealign(totalkb * (randomInt(190, 240) / 10000));
1678
+ const sreclaimable = pagealign(slab * 0.64);
1679
+ const anonhuge = pagealign(activeanon * (randomInt(20, 45) / 100));
1680
+ const hugepages1g = options?.hugepages1g ?? 0;
1681
+ const directmap1g = totalgb >= 64 ? pagealign(totalkb * 0.8) : 0;
1682
+ const directmap2m = directmap1g > 0 ? pagealign(totalkb * 0.15) : pagealign(totalkb * 0.9);
1683
+ const rows = [
1684
+ ['MemTotal', totalkb],
1685
+ ['MemFree', memfree],
1686
+ ['MemAvailable', memavailable],
1687
+ ['Buffers', buffers],
1688
+ ['Cached', cached],
1689
+ ['SwapCached', 0],
1690
+ ['Active', active],
1691
+ ['Inactive', inactive],
1692
+ ['Active(anon)', activeanon],
1693
+ ['Inactive(anon)', inactiveanon],
1694
+ ['Active(file)', pagealign(active - activeanon)],
1695
+ ['Inactive(file)', pagealign(inactive - inactiveanon)],
1696
+ ['Unevictable', pagealign(randomInt(16384, 65536))],
1697
+ ['Mlocked', pagealign(randomInt(4096, 16384))],
1698
+ ['SwapTotal', swaptotal],
1699
+ ['SwapFree', swapfree],
1700
+ ['Dirty', pagealign(randomInt(20480, 262144))],
1701
+ ['Writeback', 0],
1702
+ ['AnonPages', pagealign(activeanon * 1.08)],
1703
+ ['Mapped', pagealign(totalkb * (randomInt(20, 42) / 1000))],
1704
+ ['Shmem', pagealign(totalkb * (randomInt(5, 12) / 1000))],
1705
+ ['KReclaimable', sreclaimable],
1706
+ ['Slab', slab],
1707
+ ['SReclaimable', sreclaimable],
1708
+ ['SUnreclaim', pagealign(slab - sreclaimable)],
1709
+ ['KernelStack', pagealign(vcpus * 320)],
1710
+ ['PageTables', pagealign(totalkb * (randomInt(30, 60) / 10000))],
1711
+ ['SecPageTables', pagealign(totalkb * (randomInt(8, 16) / 10000))],
1712
+ ['NFS_Unstable', 0],
1713
+ ['Bounce', 0],
1714
+ ['WritebackTmp', 0],
1715
+ ['CommitLimit', commitlimit],
1716
+ ['Committed_AS', committedas],
1717
+ ['VmallocTotal', 34359738367],
1718
+ ['VmallocUsed', pagealign(randomInt(49152, 131072))],
1719
+ ['VmallocChunk', 0],
1720
+ ['Percpu', pagealign(vcpus * randomInt(20480, 40960))],
1721
+ ['HardwareCorrupted', 0],
1722
+ ['AnonHugePages', anonhuge],
1723
+ ['ShmemHugePages', 0],
1724
+ ['ShmemPmdMapped', 0],
1725
+ ['FileHugePages', 0],
1726
+ ['FilePmdMapped', 0],
1727
+ ['Unaccepted', 0],
1728
+ ['HugePages_Total', hugepages1g],
1729
+ ['HugePages_Free', hugepages1g],
1730
+ ['HugePages_Rsvd', 0],
1731
+ ['HugePages_Surp', 0],
1732
+ ['Hugepagesize', 2048],
1733
+ ['Hugetlb', hugepages1g * 1048576],
1734
+ ['DirectMap4k', pagealign(randomInt(131072, 262144))],
1735
+ ['DirectMap2M', directmap2m],
1736
+ ['DirectMap1G', directmap1g],
1737
+ ];
1738
+ return rows
1739
+ .map(([key, value]) => `${key}:${String(value).padStart(24 - key.length - 1)} kB`)
1740
+ .join('\n');
1741
+ }
1742
+ catch (cause) {
1743
+ if (cause instanceof memoryerror) {
1744
+ throw cause;
1745
+ }
1746
+ throw new memoryerror('generateVirtualMeminfo failed', { cause: cause });
1747
+ }
1748
+ }
1749
+ /**
1750
+ * Renders the minimal one-line meminfo shape absorbed from the v2 stub:
1751
+ * a page-aligned MemTotal in kB for the requested capacity in MiB. The
1752
+ * full 47-field payload comes from generateVirtualMeminfo.
1753
+ */
1754
+ export function meminfoForMiB(mib) {
1755
+ try {
1756
+ if (!Number.isFinite(mib) || mib <= 0) {
1757
+ throw new memoryerror(`mib must be a positive number, received ${mib}`);
1758
+ }
1759
+ return `MemTotal: ${pagealign(mib * 1024)} kB\n`;
1760
+ }
1761
+ catch (cause) {
1762
+ throw new memoryerror('meminfoForMiB failed', { cause: cause });
1763
+ }
1764
+ }
1765
+ /**
1766
+ * Docker memory-swap sentinel absorbed from the v2 stub: "-1" keeps swap
1767
+ * unlimited, the value emitted by dockerMemoryFlags for every default plan.
1768
+ */
1769
+ export const memorySwap = '-1';
1770
+ /**
1771
+ * Docker /dev/shm size absorbed from the v2 stub: "2g" is the canonical
1772
+ * fix for the PyTorch DataLoader bus error caused by the 64 MB default.
1773
+ */
1774
+ export const shmSize = '2g';
1775
+ /**
1776
+ * MemTotal anchor of the meminfo128g reference artifact: exactly
1777
+ * 134217728 kB, the page-aligned total of 128 GiB. generatememinfo128g
1778
+ * keeps the v5 parametric behavior of subtracting the 131072 kB firmware
1779
+ * carveout, so its MemTotal reads 134086656 kB while this constant
1780
+ * preserves the physical anchor captured on 2026-08-22.
1781
+ */
1782
+ export const meminfo128gtotalkb = 134217728;
1783
+ /**
1784
+ * Regenerates the full 47-field /proc/meminfo payload anchored at the
1785
+ * meminfo128g artifact total (128 GiB, 134217728 kB) with the natural
1786
+ * jitter of a live machine.
1787
+ */
1788
+ export function generatememinfo128g(options) {
1789
+ try {
1790
+ return generateVirtualMeminfo(128, options);
1791
+ }
1792
+ catch (cause) {
1793
+ throw new memoryerror('generatememinfo128g failed', { cause: cause });
1794
+ }
1795
+ }
1796
+ //# sourceMappingURL=virtualmemory.js.map