@wenathlan/saddle 2.0.154 → 2.0.159

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 (314) hide show
  1. package/Dockerfile +167 -1334
  2. package/README.md +59 -60
  3. package/biome.jsonc +3 -3
  4. package/browser.ts +482 -0
  5. package/cli.ts +274 -0
  6. package/distribution.ts +731 -0
  7. package/docker.config +29 -8
  8. package/docs/{architecture.1.8.19.mmd → architecture1819.md} +6 -0
  9. package/docs/artifactavailability.md +2 -2
  10. package/docs/browser.md +18 -1
  11. package/docs/{containerplatforms.2.1.0.md → containerplatforms210.md} +1 -1
  12. package/docs/{documentmap.1.8.12.md → documentmap1812.md} +1 -1
  13. package/docs/extension.md +13 -2
  14. package/docs/features.md +5 -0
  15. package/docs/libraryapi.md +1 -1
  16. package/docs/{ninety.modalities.md → ninetymodalities.md} +87 -4
  17. package/docs/{planning.ninety.md → planningninety.md} +6 -6
  18. package/docs/{releasenotes.1.8.13.md → releasenotes1813.md} +2 -2
  19. package/docs/{releasenotes.1.8.14.md → releasenotes1814.md} +1 -1
  20. package/docs/{repo.synthesis.1.8.16.md → reposynthesis1816.md} +1 -1
  21. package/docs/todo.md +2 -2
  22. package/docs/{todo.1.8.15.md → todo1815.md} +1 -1
  23. package/docs/{todo.1.8.16.md → todo1816.md} +5 -5
  24. package/execution.ts +677 -0
  25. package/foundation.ts +314 -0
  26. package/index.ts +36 -34
  27. package/isolation.ts +84 -0
  28. package/modalityregistry.ts +189 -145
  29. package/modes.ts +170 -0
  30. package/mttg.config +1 -1
  31. package/orchestrator.ts +49 -15
  32. package/package.json +105 -89
  33. package/qemu.config +2 -2
  34. package/sandbox.ts +3279 -0
  35. package/scheduler.ts +1 -1
  36. package/server.ts +52 -0
  37. package/tsconfig.json +12 -13
  38. package/virtual.ts +7528 -0
  39. package/workloadlaw.ts +293 -0
  40. package/dist/App.d.ts +0 -5
  41. package/dist/App.js +0 -52
  42. package/dist/Sol/Sol.d.ts +0 -3
  43. package/dist/Sol/Sol.js +0 -46
  44. package/dist/Sol/agentbrowser/agentbrowser.d.ts +0 -9
  45. package/dist/Sol/agentbrowser/agentbrowser.js +0 -121
  46. package/dist/Sol/architecture/architecture.d.ts +0 -9
  47. package/dist/Sol/architecture/architecture.js +0 -93
  48. package/dist/Sol/compute/compute.d.ts +0 -9
  49. package/dist/Sol/compute/compute.js +0 -22
  50. package/dist/Sol/console/console.d.ts +0 -15
  51. package/dist/Sol/console/console.js +0 -292
  52. package/dist/Sol/dashboard/dashboard.d.ts +0 -10
  53. package/dist/Sol/dashboard/dashboard.js +0 -181
  54. package/dist/Sol/docs/docs.d.ts +0 -9
  55. package/dist/Sol/docs/docs.js +0 -28
  56. package/dist/Sol/home/home.d.ts +0 -35
  57. package/dist/Sol/home/home.js +0 -239
  58. package/dist/Sol/integrations/integrations.d.ts +0 -9
  59. package/dist/Sol/integrations/integrations.js +0 -83
  60. package/dist/Sol/intro/intro.d.ts +0 -7
  61. package/dist/Sol/intro/intro.js +0 -102
  62. package/dist/Sol/login/login.d.ts +0 -16
  63. package/dist/Sol/login/login.js +0 -49
  64. package/dist/Sol/notfound/notfound.d.ts +0 -9
  65. package/dist/Sol/notfound/notfound.js +0 -15
  66. package/dist/Sol/onboarding/onboarding.d.ts +0 -25
  67. package/dist/Sol/onboarding/onboarding.js +0 -60
  68. package/dist/Sol/playground/playground.d.ts +0 -9
  69. package/dist/Sol/playground/playground.js +0 -127
  70. package/dist/Sol/register/register.d.ts +0 -16
  71. package/dist/Sol/register/register.js +0 -193
  72. package/dist/Sol/shell/Shell.d.ts +0 -124
  73. package/dist/Sol/shell/Shell.js +0 -335
  74. package/dist/Sol/wingets/ComputeBootladder.d.ts +0 -6
  75. package/dist/Sol/wingets/ComputeBootladder.js +0 -71
  76. package/dist/Sol/wingets/ComputeModalitycatalog.d.ts +0 -7
  77. package/dist/Sol/wingets/ComputeModalitycatalog.js +0 -71
  78. package/dist/Sol/wingets/ConsoleApibadge.d.ts +0 -7
  79. package/dist/Sol/wingets/ConsoleApibadge.js +0 -5
  80. package/dist/Sol/wingets/ConsoleEdgelaw.d.ts +0 -6
  81. package/dist/Sol/wingets/ConsoleEdgelaw.js +0 -36
  82. package/dist/Sol/wingets/ConsoleEventstimeline.d.ts +0 -19
  83. package/dist/Sol/wingets/ConsoleEventstimeline.js +0 -12
  84. package/dist/Sol/wingets/ConsoleSnapshotcontrols.d.ts +0 -8
  85. package/dist/Sol/wingets/ConsoleSnapshotcontrols.js +0 -8
  86. package/dist/Sol/wingets/ConsoleSpecpanel.d.ts +0 -21
  87. package/dist/Sol/wingets/ConsoleSpecpanel.js +0 -75
  88. package/dist/Sol/wingets/ConsoleTerminal.d.ts +0 -22
  89. package/dist/Sol/wingets/ConsoleTerminal.js +0 -77
  90. package/dist/Sol/wingets/DashboardAccountpanel.d.ts +0 -18
  91. package/dist/Sol/wingets/DashboardAccountpanel.js +0 -65
  92. package/dist/Sol/wingets/DashboardAdminpanel.d.ts +0 -6
  93. package/dist/Sol/wingets/DashboardAdminpanel.js +0 -90
  94. package/dist/Sol/wingets/DashboardAuditlog.d.ts +0 -8
  95. package/dist/Sol/wingets/DashboardAuditlog.js +0 -50
  96. package/dist/Sol/wingets/DashboardCreatesandboxform.d.ts +0 -10
  97. package/dist/Sol/wingets/DashboardCreatesandboxform.js +0 -71
  98. package/dist/Sol/wingets/DashboardEventstimeline.d.ts +0 -8
  99. package/dist/Sol/wingets/DashboardEventstimeline.js +0 -83
  100. package/dist/Sol/wingets/DashboardGlobalsandboxestable.d.ts +0 -8
  101. package/dist/Sol/wingets/DashboardGlobalsandboxestable.js +0 -57
  102. package/dist/Sol/wingets/DashboardMeshnodestable.d.ts +0 -8
  103. package/dist/Sol/wingets/DashboardMeshnodestable.js +0 -103
  104. package/dist/Sol/wingets/DashboardSandboxlist.d.ts +0 -10
  105. package/dist/Sol/wingets/DashboardSandboxlist.js +0 -163
  106. package/dist/Sol/wingets/DashboardUserstable.d.ts +0 -8
  107. package/dist/Sol/wingets/DashboardUserstable.js +0 -78
  108. package/dist/Sol/wingets/HomeEntrygate.d.ts +0 -23
  109. package/dist/Sol/wingets/HomeEntrygate.js +0 -73
  110. package/dist/Sol/wingets/HomeMetricstrip.d.ts +0 -9
  111. package/dist/Sol/wingets/HomeMetricstrip.js +0 -4
  112. package/dist/Sol/wingets/HomeRuntimediagram.d.ts +0 -1
  113. package/dist/Sol/wingets/HomeRuntimediagram.js +0 -22
  114. package/dist/Sol/wingets/LoginForm.d.ts +0 -19
  115. package/dist/Sol/wingets/LoginForm.js +0 -141
  116. package/dist/Sol/wingets/RegisterPasswordconfirm.d.ts +0 -13
  117. package/dist/Sol/wingets/RegisterPasswordconfirm.js +0 -16
  118. package/dist/Sol/wingets/RegisterPasswordmeter.d.ts +0 -19
  119. package/dist/Sol/wingets/RegisterPasswordmeter.js +0 -65
  120. package/dist/Sol/wingets/RegisterUsernamerules.d.ts +0 -11
  121. package/dist/Sol/wingets/RegisterUsernamerules.js +0 -16
  122. package/dist/Sol/wingets/index.d.ts +0 -39
  123. package/dist/Sol/wingets/index.js +0 -39
  124. package/dist/alternatives.d.ts +0 -508
  125. package/dist/alternatives.js +0 -950
  126. package/dist/api.d.ts +0 -154
  127. package/dist/api.js +0 -174
  128. package/dist/auth.d.ts +0 -268
  129. package/dist/auth.js +0 -476
  130. package/dist/automation.d.ts +0 -425
  131. package/dist/automation.js +0 -566
  132. package/dist/browser.d.ts +0 -561
  133. package/dist/browser.js +0 -1058
  134. package/dist/capacitor.config.d.ts +0 -45
  135. package/dist/capacitor.config.js +0 -48
  136. package/dist/catalog.d.ts +0 -43
  137. package/dist/catalog.js +0 -44
  138. package/dist/cli.d.ts +0 -16
  139. package/dist/cli.js +0 -168
  140. package/dist/communication.d.ts +0 -181
  141. package/dist/communication.js +0 -376
  142. package/dist/compute.d.ts +0 -1160
  143. package/dist/compute.js +0 -2272
  144. package/dist/dashboardlib.d.ts +0 -58
  145. package/dist/dashboardlib.js +0 -161
  146. package/dist/db.d.ts +0 -569
  147. package/dist/db.js +0 -1080
  148. package/dist/distribution.d.ts +0 -528
  149. package/dist/distribution.js +0 -810
  150. package/dist/drizzle.config.d.ts +0 -20
  151. package/dist/drizzle.config.js +0 -18
  152. package/dist/edgelandes.d.ts +0 -70
  153. package/dist/edgelandes.host.d.ts +0 -26
  154. package/dist/edgelandes.host.js +0 -1089
  155. package/dist/edgelandes.inproc.d.ts +0 -27
  156. package/dist/edgelandes.inproc.js +0 -952
  157. package/dist/edgelandes.js +0 -1133
  158. package/dist/edgelandes.ninety.d.ts +0 -31
  159. package/dist/edgelandes.ninety.js +0 -174
  160. package/dist/edgelandes.virtual.d.ts +0 -25
  161. package/dist/edgelandes.virtual.js +0 -629
  162. package/dist/edgeplane.d.ts +0 -121
  163. package/dist/edgeplane.js +0 -341
  164. package/dist/examplelocaljob.d.ts +0 -1
  165. package/dist/examplelocaljob.js +0 -14
  166. package/dist/execution.d.ts +0 -529
  167. package/dist/execution.js +0 -760
  168. package/dist/family.d.ts +0 -16
  169. package/dist/family.js +0 -42
  170. package/dist/familyurl.d.ts +0 -21
  171. package/dist/familyurl.js +0 -24
  172. package/dist/format.d.ts +0 -18
  173. package/dist/format.js +0 -59
  174. package/dist/foundation.d.ts +0 -172
  175. package/dist/foundation.js +0 -312
  176. package/dist/index.d.ts +0 -735
  177. package/dist/index.js +0 -1020
  178. package/dist/integration.d.ts +0 -235
  179. package/dist/integration.js +0 -228
  180. package/dist/intelligence.d.ts +0 -93
  181. package/dist/intelligence.js +0 -144
  182. package/dist/isolation.d.ts +0 -128
  183. package/dist/isolation.js +0 -95
  184. package/dist/labels.d.ts +0 -665
  185. package/dist/labels.js +0 -707
  186. package/dist/localauth.d.ts +0 -127
  187. package/dist/localauth.js +0 -413
  188. package/dist/media.d.ts +0 -343
  189. package/dist/media.js +0 -985
  190. package/dist/mesh.d.ts +0 -177
  191. package/dist/mesh.js +0 -468
  192. package/dist/modalityregistry.d.ts +0 -109
  193. package/dist/modalityregistry.js +0 -1386
  194. package/dist/modes.d.ts +0 -358
  195. package/dist/modes.js +0 -133
  196. package/dist/onboardingstate.d.ts +0 -79
  197. package/dist/onboardingstate.js +0 -282
  198. package/dist/orchestrator.d.ts +0 -1338
  199. package/dist/orchestrator.js +0 -4310
  200. package/dist/packager/targetcli.js +0 -4
  201. package/dist/paths.d.ts +0 -2
  202. package/dist/paths.js +0 -14
  203. package/dist/performance.d.ts +0 -415
  204. package/dist/performance.js +0 -826
  205. package/dist/quantum.d.ts +0 -809
  206. package/dist/quantum.js +0 -2072
  207. package/dist/render.d.ts +0 -380
  208. package/dist/render.js +0 -1072
  209. package/dist/runall.d.ts +0 -2
  210. package/dist/runall.js +0 -39
  211. package/dist/runtimeprobe.d.ts +0 -4
  212. package/dist/runtimeprobe.js +0 -8
  213. package/dist/sandbox.d.ts +0 -355
  214. package/dist/sandbox.js +0 -1721
  215. package/dist/sandboxenvprofile.d.ts +0 -29
  216. package/dist/sandboxenvprofile.js +0 -89
  217. package/dist/sandboxprofile.d.ts +0 -137
  218. package/dist/sandboxprofile.js +0 -241
  219. package/dist/sandboxqueue.d.ts +0 -108
  220. package/dist/sandboxqueue.js +0 -201
  221. package/dist/sandboxquota.d.ts +0 -121
  222. package/dist/sandboxquota.js +0 -236
  223. package/dist/scheduler.d.ts +0 -595
  224. package/dist/scheduler.js +0 -1258
  225. package/dist/scriptlanes.d.ts +0 -182
  226. package/dist/scriptlanes.js +0 -660
  227. package/dist/scripts.buildengine.d.ts +0 -1
  228. package/dist/scripts.buildengine.js +0 -39
  229. package/dist/scripts.securitygate.d.ts +0 -1
  230. package/dist/scripts.securitygate.js +0 -68
  231. package/dist/scripts.validateflatnative.d.ts +0 -1
  232. package/dist/scripts.validateflatnative.js +0 -72
  233. package/dist/security.d.ts +0 -500
  234. package/dist/security.js +0 -1169
  235. package/dist/seedcatalog.d.ts +0 -13
  236. package/dist/seedcatalog.js +0 -46
  237. package/dist/server.d.ts +0 -20
  238. package/dist/server.js +0 -53
  239. package/dist/speccatalog.d.ts +0 -31
  240. package/dist/speccatalog.js +0 -163
  241. package/dist/tiers.d.ts +0 -1001
  242. package/dist/tiers.js +0 -2169
  243. package/dist/utils.d.ts +0 -2
  244. package/dist/utils.js +0 -5
  245. package/dist/vaulthandoff.d.ts +0 -141
  246. package/dist/vaulthandoff.js +0 -444
  247. package/dist/virtual.d.ts +0 -640
  248. package/dist/virtual.js +0 -1284
  249. package/dist/virtualcpu.d.ts +0 -315
  250. package/dist/virtualcpu.js +0 -1180
  251. package/dist/virtualgpu.d.ts +0 -344
  252. package/dist/virtualgpu.js +0 -1000
  253. package/dist/virtualization.d.ts +0 -606
  254. package/dist/virtualization.js +0 -1186
  255. package/dist/virtualmemory.d.ts +0 -817
  256. package/dist/virtualmemory.js +0 -1795
  257. package/dist/vite.config.d.ts +0 -3
  258. package/dist/vite.config.js +0 -48
  259. package/dist/vitest.config.d.ts +0 -2
  260. package/dist/vitest.config.js +0 -25
  261. package/dist/webserver.d.ts +0 -166
  262. package/dist/webserver.js +0 -2226
  263. package/dist/workloadlaw.d.ts +0 -133
  264. package/dist/workloadlaw.js +0 -193
  265. package/docs/.gitkeep +0 -0
  266. package/docs/architecture.1.8.19.md +0 -76
  267. package/docs/logs/examplesession.json +0 -54
  268. package/docs/repo.analysis.1.8.21.json +0 -2617
  269. package/docs/repo.candidates.1.8.21.jsonl +0 -666
  270. package/docs/repo.selected.1.8.21.json +0 -786
  271. package/manifest.json +0 -20
  272. package/media.ts +0 -1337
  273. package/virtualcpu.ts +0 -1274
  274. package/virtualgpu.ts +0 -1182
  275. package/virtualization.ts +0 -1628
  276. package/virtualmemory.ts +0 -2303
  277. /package/docs/{artifactresearch.1.8.9.md → artifactresearch189.md} +0 -0
  278. /package/docs/{batches.1816.to.1820.md → batches1816to1820.md} +0 -0
  279. /package/docs/{brancharchive.2026.08.18.md → brancharchive20260818.md} +0 -0
  280. /package/docs/{containerplatforms.1.8.17.md → containerplatforms1817.md} +0 -0
  281. /package/docs/{e2ugh.engine.md → e2ughengine.md} +0 -0
  282. /package/docs/{flatbuildresearch.1.8.11.md → flatbuildresearch1811.md} +0 -0
  283. /package/docs/{licenseaudit.1.8.12.md → licenseaudit1812.md} +0 -0
  284. /package/docs/{mobileconversionresearch.1.8.10.md → mobileconversionresearch1810.md} +0 -0
  285. /package/docs/{nativeidentityresearch.1.8.11.md → nativeidentityresearch1811.md} +0 -0
  286. /package/docs/{native.wrappers.md → nativewrappers.md} +0 -0
  287. /package/docs/{planning.1.8.18.md → planning1818.md} +0 -0
  288. /package/docs/{planning.1.8.19.md → planning1819.md} +0 -0
  289. /package/docs/{planning.engine.md → planningengine.md} +0 -0
  290. /package/docs/{releasenotes.1.8.12.md → releasenotes1812.md} +0 -0
  291. /package/docs/{releasenotes.1.8.15.md → releasenotes1815.md} +0 -0
  292. /package/docs/{releasenotes.1.8.16.md → releasenotes1816.md} +0 -0
  293. /package/docs/{releasenotes.1.8.17.md → releasenotes1817.md} +0 -0
  294. /package/docs/{releasenotes.1.8.18.md → releasenotes1818.md} +0 -0
  295. /package/docs/{releasenotes.1.8.19.md → releasenotes1819.md} +0 -0
  296. /package/docs/{reorganization.1.8.8.md → reorganization188.md} +0 -0
  297. /package/docs/{reorganization.1.8.9.md → reorganization189.md} +0 -0
  298. /package/docs/{repo.research.1.8.16.md → reporesearch1816.md} +0 -0
  299. /package/docs/{repo.research.1.8.21.md → reporesearch1821.md} +0 -0
  300. /package/docs/{repo.synthesis.1.8.21.md → reposynthesis1821.md} +0 -0
  301. /package/docs/{research.1.8.18.isolation.md → research1818isolation.md} +0 -0
  302. /package/docs/{research.1.8.19.virtual.browser.md → research1819virtualbrowser.md} +0 -0
  303. /package/docs/{scanningresearch.1.8.11.md → scanningresearch1811.md} +0 -0
  304. /package/docs/{securityaudit.1.8.7.md → securityaudit187.md} +0 -0
  305. /package/docs/{securityreferences.1.8.11.md → securityreferences1811.md} +0 -0
  306. /package/docs/{securityresearch.1.8.11.md → securityresearch1811.md} +0 -0
  307. /package/docs/{signingresearch.1.8.12.md → signingresearch1812.md} +0 -0
  308. /package/docs/{tauri.glib.risk.1.8.11.md → tauriglibrisk1811.md} +0 -0
  309. /package/docs/{todo.1.8.18.md → todo1818.md} +0 -0
  310. /package/docs/{todo.1.8.19.md → todo1819.md} +0 -0
  311. /package/docs/{toolchainresearch.1.8.9.md → toolchainresearch189.md} +0 -0
  312. /package/docs/{web.duplicatecleanup.md → webduplicatecleanup.md} +0 -0
  313. /package/docs/{web.ideas.md → webideas.md} +0 -0
  314. /package/docs/{workflowimprovements.2026.08.19.md → workflowimprovements20260819.md} +0 -0
@@ -1,629 +0,0 @@
1
- // # edgelandes.virtual.ts — the virtual hardware composition lanes of
2
- // the edge plane (the ninety modalities wave, group c, task wa-2c: the
3
- // seven planned virtual-hardware modalities wired as honest composition
4
- // lanes). every lane rides the engine's own virtual hardware payloads —
5
- // sandbox.ts generates the procfs, smi, dmesg and mesa surfaces,
6
- // virtualization.ts carries the qemu/kvm plan surface — and composes the
7
- // per-modality machine report from them: a lane never boots anything on
8
- // the host, the report says composed, never booted. the code field of
9
- // every executor is the machine manifest (json: model, gpu, ramgb, boot
10
- // with the optional vcpus and mig); an unparsable manifest answers
11
- // invalid-machine-manifest, a catalog reference the engine does not
12
- // carry answers catalog-entry-absent, a plan the recipe cannot compose
13
- // answers kvm-composition-failed and a blown deadline answers
14
- // run-deadline-exceeded. determinism is the lane law: the engine samples
15
- // some payload values per run (crypto-random memory fractions, the smi
16
- // timestamp and counters, the state token), so the lanes pin those
17
- // ranges at their midpoints and keep only the run-invariant smi lines —
18
- // the same manifest always composes the same report bytes.
19
- import { edgelaneerror } from "./edgelandes.ts";
20
- import { bootSequence, clinfoSummary, cpudata, freeh, getcpu, getcpubyid, getgpu, getmig, glxinfoSummary, gpudata, lscpu, mesaenv, migprofiles, nvidiaSmiTable, pagealign, solvetopology, vulkanSummary, } from "./sandbox.ts";
21
- /* the virtualization domain (virtualization.ts) re-exports virtualgpu
22
- * through a .js specifier — the webserver's plain node host resolves only
23
- * .ts specifiers, so the kvm lane loads the domain lazily inside the
24
- * executor (the family law: a domain the host cannot resolve degrades
25
- * that one lane honestly, never the engine boot). */
26
- async function loadvirtualization() {
27
- try {
28
- return await import("./virtualization.ts");
29
- }
30
- catch (error) {
31
- throw edgelaneerror("KVM_MODULE_UNAVAILABLE", `the virtualization domain cannot load under this host (the .js specifier graph needs a full resolver): ${error instanceof Error ? error.message : String(error)}`);
32
- }
33
- }
34
- /** the engine's virtual memory ceiling createSandboxState clamps under;
35
- * the lane law refuses a manifest above it instead of silently
36
- * rewriting the caller's machine. */
37
- const ENGINERAMCEILINGGB = 18432;
38
- /** parses the code field as the machine manifest: a json object carrying
39
- * the optional model, gpu, ramgb, vcpus, boot and mig fields, every
40
- * present field type-checked and bounded — anything else answers
41
- * invalid-machine-manifest with the reason. */
42
- function parsemanifest(code) {
43
- const invalid = (detail) => {
44
- throw edgelaneerror("INVALID_MACHINE_MANIFEST", detail);
45
- };
46
- let parsed;
47
- try {
48
- parsed = JSON.parse(code);
49
- }
50
- catch (error) {
51
- invalid(`the code field is not parsable json (the machine manifest law): ${error instanceof Error ? error.message : String(error)}`);
52
- }
53
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
54
- invalid("the machine manifest must be a json object carrying the machine fields");
55
- }
56
- const raw = parsed;
57
- if (raw.model !== undefined && typeof raw.model !== "string") {
58
- invalid("the model field must be a string when present");
59
- }
60
- if (raw.gpu !== undefined && typeof raw.gpu !== "string") {
61
- invalid("the gpu field must be a string when present");
62
- }
63
- if (raw.mig !== undefined && typeof raw.mig !== "string") {
64
- invalid("the mig field must be a string when present (a mig profile id or off)");
65
- }
66
- if (raw.boot !== undefined && typeof raw.boot !== "boolean") {
67
- invalid("the boot field must be a boolean when present");
68
- }
69
- if (raw.ramgb !== undefined) {
70
- if (typeof raw.ramgb !== "number" || !Number.isFinite(raw.ramgb)) {
71
- invalid("the ramgb field must be a finite number when present");
72
- }
73
- if (raw.ramgb <= 0) {
74
- invalid("the ramgb field must be a positive number of gigabytes");
75
- }
76
- if (raw.ramgb > ENGINERAMCEILINGGB) {
77
- invalid(`the ramgb field must stay under the engine's ${ENGINERAMCEILINGGB} gb virtual ceiling (createSandboxState clamps there; the lane refuses instead of rewriting the manifest)`);
78
- }
79
- }
80
- if (raw.vcpus !== undefined) {
81
- if (typeof raw.vcpus !== "number" || !Number.isFinite(raw.vcpus)) {
82
- invalid("the vcpus field must be a finite number when present");
83
- }
84
- if (raw.vcpus < 1) {
85
- invalid("the vcpus field must be at least 1");
86
- }
87
- }
88
- return { model: raw.model, gpu: raw.gpu, ramgb: raw.ramgb, vcpus: raw.vcpus, boot: raw.boot, mig: raw.mig };
89
- }
90
- /** resolves the manifest against the engine catalogs: the model lookup
91
- * accepts the catalog model name or its slug id (getcpu then
92
- * getcpubyid), the gpu lookup accepts the id or the name, the mig
93
- * lookup accepts a mig profile id or off; an entry the catalog does not
94
- * carry answers catalog-entry-absent naming the known ids. the defaults
95
- * mirror the engine's own laws: the first catalog entry for model and
96
- * gpu (the vgpu lane overrides the gpu default with the first
97
- * mig-capable device), 32 gb ram and 8 vcpus (the SandboxSpec defaults
98
- * createSandboxState rides), the vcpus clamped by the engine's own
99
- * solvetopology. */
100
- function composemachine(raw, defaultgpu) {
101
- const modelwanted = raw.model ?? cpudata[0].model;
102
- const cpuspec = getcpu(modelwanted) ?? getcpubyid(modelwanted);
103
- if (cpuspec === undefined) {
104
- throw edgelaneerror("CATALOG_ENTRY_ABSENT", `the cpu catalog carries no model "${modelwanted}"; known models: ${cpudata.map((entry) => entry.model).join(", ")}`);
105
- }
106
- const gpuwanted = raw.gpu ?? defaultgpu ?? gpudata[0].id;
107
- const gpuspec = getgpu(gpuwanted);
108
- if (gpuspec === undefined) {
109
- throw edgelaneerror("CATALOG_ENTRY_ABSENT", `the gpu catalog carries no device "${gpuwanted}"; known ids: ${gpudata.map((entry) => entry.id).join(", ")}`);
110
- }
111
- const migwanted = raw.mig ?? "off";
112
- if (migwanted !== "off" && !migprofiles.some((profile) => profile.id === migwanted)) {
113
- throw edgelaneerror("CATALOG_ENTRY_ABSENT", `the mig catalog carries no profile "${migwanted}"; known profiles: off, ${migprofiles.map((profile) => profile.id).join(", ")}`);
114
- }
115
- const topology = solvetopology(cpuspec, raw.vcpus ?? 8);
116
- const manifest = {
117
- model: cpuspec.model,
118
- gpu: gpuspec.id,
119
- ramgb: raw.ramgb ?? 32,
120
- vcpus: topology.vcpus,
121
- boot: raw.boot ?? false,
122
- mig: migwanted,
123
- };
124
- return { manifest, cpuspec, gpuspec, topology };
125
- }
126
- /** renders the canonical manifest json (fixed key order): the bytes the
127
- * session-otp gate hashes and the manifest the artifacts carry. */
128
- function canonicalmanifest(manifest) {
129
- return JSON.stringify({
130
- model: manifest.model,
131
- gpu: manifest.gpu,
132
- ramgb: manifest.ramgb,
133
- vcpus: manifest.vcpus,
134
- boot: manifest.boot,
135
- mig: manifest.mig,
136
- });
137
- }
138
- /** hashes one text with 64-bit fnv-1a and renders 16 lowercase hex
139
- * characters: the deterministic digest the session-otp gate and the
140
- * sandbox id ride — the engine's token() samples crypto randomness per
141
- * run, the lane hashes the manifest instead so identical manifests
142
- * compose identical ids. */
143
- function fnv1a64(text) {
144
- let hash = 0xcbf29ce484222325n;
145
- for (let index = 0; index < text.length; index += 1) {
146
- hash ^= BigInt(text.charCodeAt(index));
147
- hash = (hash * 0x100000001b3n) & 0xffffffffffffffffn;
148
- }
149
- return hash.toString(16).padStart(16, "0");
150
- }
151
- /** honors the deadline after the composition (the boot budget law: the
152
- * compositions are fast, a blown budget answers run-deadline-exceeded
153
- * instead of a report the caller never paid for). */
154
- function guarddeadline(startedat, deadline) {
155
- const budget = Number.isFinite(deadline) ? Math.max(0, deadline) : Number.POSITIVE_INFINITY;
156
- if (Date.now() - startedat > budget) {
157
- throw edgelaneerror("RUN_DEADLINE_EXCEEDED", `the composition exceeded its ${deadline} ms deadline (the boot budget law)`);
158
- }
159
- }
160
- /** composes the memory plan from the engine's own formulas: pagealign
161
- * and the MemTotal and swap laws meminfo/createSandboxState ride, with
162
- * every per-run sampled fraction pinned at the midpoint of the engine's
163
- * rnd range (the engine samples free, buffers, cached, shmem and
164
- * swapfree per run; the lane pins the midpoints so the same manifest
165
- * composes the same bytes) — the free -h table still renders through
166
- * the engine's own freeh over the pinned snapshot. */
167
- function composememoryplan(ramgb, vcpus) {
168
- const memtotalkb = pagealign(ramgb * 1024 * 1024 - 131072);
169
- const swapgb = Math.min(Math.max(Math.round(ramgb / 8), 2), 128);
170
- const swaptotalkb = swapgb * 1024 * 1024;
171
- const row = (key, kb) => `${key}:${String(kb).padStart(24 - key.length - 1)} kB`;
172
- const rows = [
173
- row("MemTotal", memtotalkb),
174
- row("MemFree", pagealign(memtotalkb * 0.053)),
175
- row("MemAvailable", pagealign(memtotalkb * 0.895)),
176
- row("Buffers", pagealign(memtotalkb * 0.0065)),
177
- row("Cached", pagealign(memtotalkb * 0.36)),
178
- row("SReclaimable", 0),
179
- row("Shmem", pagealign(memtotalkb * 0.0085)),
180
- row("SwapTotal", swaptotalkb),
181
- row("SwapFree", pagealign(swaptotalkb * 0.915)),
182
- row("KernelStack", pagealign(vcpus * 320)),
183
- ];
184
- return { memtotalkb, swapgb, rows, free: freeh(rows.join("\n")) };
185
- }
186
- /** keeps the run-invariant lines of the engine's 89-char smi table: the
187
- * composer stamps a per-run timestamp and samples the fan, temperature,
188
- * memory and utilization counters, so the surface drops the timestamp
189
- * line, the sampled perf row and the mig-worker process rows and keeps
190
- * every deterministic line (the borders, the headers, the device row,
191
- * the mig line, the no-running-processes line). */
192
- function smilines(gpu, mig) {
193
- return nvidiaSmiTable(gpu, mig)
194
- .split("\n")
195
- .filter((line) => !/^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat) /.test(line))
196
- .filter((line) => !/P0\s+\d+W \//.test(line))
197
- .filter((line) => !line.includes("mig-worker"));
198
- }
199
- /** the session law of the virtual display (the lane pins it; the
200
- * registry record charges the virtual-screen modality under the xvfb
201
- * and looking-glass drivers with the session-otp hardening gate):
202
- * display :0, geometry 1280x800x24 and the vnc endpoint on the symbolic
203
- * saddle-display host — the lane composes the tree, it never binds a
204
- * socket. */
205
- const displaylaw = {
206
- display: ":0",
207
- screen: 0,
208
- geometry: "1280x800x24",
209
- vnc: "vnc://saddle-display:5900",
210
- driver: "looking-glass b7 (kvmfr ivshmem 128m, the guest-to-host frame bridge)",
211
- };
212
- /** reads the driver-quota bound from the lane inputs: inputs.quota with
213
- * the default of 4 devices, clamped to 1-16 (the registry record's
214
- * driver-quota hardening gate — the nvml surface never answers more
215
- * devices than the quota bounds). */
216
- function driverquota(inputs) {
217
- const wanted = typeof inputs === "object" && inputs !== null ? inputs.quota : undefined;
218
- if (typeof wanted !== "number" || !Number.isFinite(wanted)) {
219
- return 4;
220
- }
221
- return Math.max(1, Math.min(16, Math.round(wanted)));
222
- }
223
- /** reads the context-quota bound from the lane inputs: inputs.contexts
224
- * with the default of 8 contexts, clamped to 1-64 (the registry record's
225
- * context-quota hardening gate). */
226
- function contextquota(inputs) {
227
- const wanted = typeof inputs === "object" && inputs !== null ? inputs.contexts : undefined;
228
- if (typeof wanted !== "number" || !Number.isFinite(wanted)) {
229
- return 8;
230
- }
231
- return Math.max(1, Math.min(64, Math.round(wanted)));
232
- }
233
- /** extracts the driver version strings from the engine's boot payload:
234
- * the kernel banner of the first line rides virtualcpu and the engine's
235
- * own version line rides virtualmemory (the boot sequence is
236
- * deterministic, so the driver table composes identical bytes). */
237
- function driverversions(manifest) {
238
- const boot = bootSequence(manifest.model, manifest.vcpus, manifest.ramgb, manifest.gpu);
239
- return {
240
- kernel: /Linux version (\S+) /.exec(boot[0])?.[1] ?? "6.12.0-saddle",
241
- engine: /virtual hardware engine v([0-9.]+)/.exec(boot.join("\n"))?.[1] ?? "2.0.127",
242
- };
243
- }
244
- /* ════════════════════════════════════════════════════════════════════ */
245
- /* Section 3: the seven lane executors — one per planned modality. */
246
- /* ════════════════════════════════════════════════════════════════════ */
247
- /** the artifact encoder shared by the lanes. */
248
- const textencoder = new TextEncoder();
249
- /** virtual-full: the complete machine. composes the cpu (the catalog by
250
- * model, default the first entry), the gpu (by id, default the first),
251
- * the memory (the engine's meminfo/freeh formulas), the boot dmesg
252
- * sequence (when the manifest asks boot), the topology (solvetopology)
253
- * and the sandbox state facts; the report answers the model, the
254
- * cores/threads, the smi summary, the memory report, the state line and
255
- * the boot dmesg head, and the artifact carries the complete manifest. */
256
- async function virtualfulllane(code, _inputs, deadline) {
257
- const startedat = Date.now();
258
- const { manifest, cpuspec, gpuspec, topology } = composemachine(parsemanifest(code));
259
- const memory = composememoryplan(manifest.ramgb, manifest.vcpus);
260
- const smi = smilines(manifest.gpu, "off");
261
- const digest = fnv1a64(canonicalmanifest(manifest));
262
- const sandboxid = `sb-${digest.slice(0, 8)}`;
263
- const hostname = `saddle-${digest.slice(0, 8)}`;
264
- const kernel = cpuspec.arch === "arm64" ? "6.12.0-saddle-aarch64" : "6.12.0-saddle";
265
- const boot = manifest.boot ? bootSequence(manifest.model, manifest.vcpus, manifest.ramgb, manifest.gpu) : [];
266
- const stdout = [
267
- "saddle virtual-full: composed machine report (composed, never booted)",
268
- ` model: ${cpuspec.displayname} — ${cpuspec.cores} cores / ${cpuspec.threads} threads (${cpuspec.microarch}, ${cpuspec.socket})`,
269
- ` topology: ${topology.vcpus} vcpus, ${topology.coresonline} cores online, ${topology.threadspercore} threads per core, ${topology.sockets} socket (solved by the engine's solvetopology)`,
270
- ` gpu: ${gpuspec.name} (${gpuspec.id}) — ${gpuspec.memtype} ${gpuspec.vrammib / 1024} gb, driver ${gpuspec.driver}${gpuspec.cuda === null ? "" : `, cuda ${gpuspec.cuda}`}`,
271
- " smi (the engine's 89-char table, the run-invariant lines):",
272
- ...smi.map((line) => ` ${line}`),
273
- " memory (the engine's formulas, the sampled fractions pinned at their midpoints):",
274
- ...memory.rows.map((line) => ` ${line}`),
275
- " free -h (the engine's free table over the pinned plan):",
276
- ...memory.free.split("\n").map((line) => ` ${line}`),
277
- ` state: hostname ${hostname}, kernel ${kernel}, sandbox ${sandboxid} (the id pinned from the manifest hash — the engine's state composer samples a per-run token and meminfo snapshot instead)`,
278
- ...(manifest.boot
279
- ? [
280
- ` boot dmesg head (${Math.min(8, boot.length)} of ${boot.length} lines):`,
281
- ...boot.slice(0, 8).map((line) => ` ${line}`),
282
- ]
283
- : [" boot: the manifest asks for no boot sequence (boot false)"]),
284
- ].join("\n");
285
- guarddeadline(startedat, deadline);
286
- const artifact = {
287
- modality: "virtual-full",
288
- verdict: "composed",
289
- manifest,
290
- machine: {
291
- cpumodel: cpuspec.model,
292
- cores: cpuspec.cores,
293
- threads: cpuspec.threads,
294
- gpuid: gpuspec.id,
295
- gpuname: gpuspec.name,
296
- vrammib: gpuspec.vrammib,
297
- memtotalkb: memory.memtotalkb,
298
- swapgb: memory.swapgb,
299
- },
300
- topology,
301
- smi,
302
- memory: { rows: memory.rows, free: memory.free },
303
- state: { id: sandboxid, hostname, kernel },
304
- boot,
305
- lscpu: lscpu(manifest.model, manifest.vcpus),
306
- };
307
- return {
308
- stdout,
309
- artifact: { mime: "application/vnd.devthink.sandbox+json", bytes: textencoder.encode(JSON.stringify(artifact)) },
310
- };
311
- }
312
- /** virtual-vgpu: the vgpu slice. composes the mig-capable device (the
313
- * manifest's gpu selects it, default the first mig-capable entry), the
314
- * mig slicing (the engine's migprofiles catalog), the smi table for the
315
- * sliced device and the nvml shim surface (FAKE_MODEL/FAKE_VRAM under
316
- * the profile, the engine's env law); a non-mig device answers
317
- * catalog-entry-absent — the lane composes slices of the mig-class
318
- * devices only, it never pretends a gaming card slices. */
319
- async function virtualvgpulane(code, _inputs, deadline) {
320
- const startedat = Date.now();
321
- const defaultvgpu = gpudata.find((entry) => entry.mig) ?? gpudata[0];
322
- const { manifest, gpuspec } = composemachine(parsemanifest(code), defaultvgpu.id);
323
- if (!gpuspec.mig) {
324
- throw edgelaneerror("CATALOG_ENTRY_ABSENT", `the gpu catalog carries no mig-capable entry for "${manifest.gpu}" (${gpuspec.name}); the vgpu lane composes slices of the mig-class devices only: ${gpudata
325
- .filter((entry) => entry.mig)
326
- .map((entry) => entry.id)
327
- .join(", ")}`);
328
- }
329
- const profile = getmig(manifest.mig) ?? migprofiles[0];
330
- const smi = smilines(manifest.gpu, profile.id);
331
- const stdout = [
332
- "saddle virtual-vgpu: composed vgpu slice report (composed, never booted)",
333
- ` device: ${gpuspec.name} (${gpuspec.id}) — ${gpuspec.memtype} ${gpuspec.vrammib / 1024} gb class, mig capable (driver ${gpuspec.driver})`,
334
- ` profile: ${profile.id} — ${profile.slicegb} gb slices, up to ${profile.maxinstances} instances`,
335
- " slice table (the engine's mig catalog for the 96 gb-class device):",
336
- ...migprofiles.map((entry) => ` ${entry.id} ${entry.slicegb} gb max ${entry.maxinstances} instances`),
337
- " smi (the sliced device, the run-invariant lines):",
338
- ...smi.map((line) => ` ${line}`),
339
- " nvml shim (the engine's FAKE_* law under mig, the env surface of the sandbox state):",
340
- ` FAKE_MODEL=${gpuspec.name}`,
341
- ` FAKE_VRAM=${profile.slicegb * 1024}`,
342
- ].join("\n");
343
- guarddeadline(startedat, deadline);
344
- const artifact = {
345
- modality: "virtual-vgpu",
346
- verdict: "composed",
347
- manifest,
348
- device: { id: gpuspec.id, name: gpuspec.name, vrammib: gpuspec.vrammib, mig: gpuspec.mig },
349
- profile,
350
- slicetable: migprofiles,
351
- nvmlshim: { FAKE_MODEL: gpuspec.name, FAKE_VRAM: profile.slicegb * 1024 },
352
- smi,
353
- };
354
- return {
355
- stdout,
356
- artifact: { mime: "application/vnd.devthink.sandbox+json", bytes: textencoder.encode(JSON.stringify(artifact)) },
357
- };
358
- }
359
- /** virtual-screen: the vm plus vnc. composes the machine (cpu, gpu,
360
- * memory) plus the virtual display tree (xvfb :0 at 1280x800x24, the
361
- * looking-glass driver line, the vnc endpoint the session law pins) and
362
- * the session-otp hardening gate: the 64-bit fnv-1a digest of the
363
- * canonical manifest, deterministic per manifest (the same manifest
364
- * always answers the same otp); the lane composes the tree, it never
365
- * binds the endpoint. */
366
- async function virtualscreenlane(code, _inputs, deadline) {
367
- const startedat = Date.now();
368
- const { manifest, cpuspec, gpuspec } = composemachine(parsemanifest(code));
369
- const memory = composememoryplan(manifest.ramgb, manifest.vcpus);
370
- const otp = fnv1a64(canonicalmanifest(manifest));
371
- const stdout = [
372
- "saddle virtual-screen: composed display report (composed, never booted)",
373
- ` machine: ${cpuspec.displayname} + ${gpuspec.name} + ${manifest.ramgb} gb (the composed machine beneath the display)`,
374
- ` memory: memtotal ${memory.memtotalkb} kb, swap ${memory.swapgb} gb (the engine's formulas)`,
375
- " display tree (the session law the lane pins):",
376
- ` ${displaylaw.display} xvfb virtual display, screen ${displaylaw.screen}, geometry ${displaylaw.geometry}, nolisten tcp`,
377
- ` driver ${displaylaw.driver}`,
378
- ` vnc ${displaylaw.vnc} (the endpoint the session law pins; the lane composes, never binds)`,
379
- " session otp hardening gate (fnv-1a 64 over the canonical manifest):",
380
- ` otp: ${otp}`,
381
- ].join("\n");
382
- guarddeadline(startedat, deadline);
383
- const artifact = {
384
- modality: "virtual-screen",
385
- verdict: "composed",
386
- manifest,
387
- display: {
388
- display: displaylaw.display,
389
- screen: displaylaw.screen,
390
- geometry: displaylaw.geometry,
391
- vnc: displaylaw.vnc,
392
- },
393
- otp,
394
- machine: { model: cpuspec.model, gpu: gpuspec.id, ramgb: manifest.ramgb, memtotalkb: memory.memtotalkb },
395
- };
396
- return {
397
- stdout,
398
- artifact: { mime: "application/vnd.devthink.screen+json", bytes: textencoder.encode(JSON.stringify(artifact)) },
399
- };
400
- }
401
- /** virtual-drivers: the virtual driver surface. composes the driver
402
- * table from the engine's own version strings (the kernel banner of the
403
- * boot payload rides virtualcpu, the gpu catalog's driver string rides
404
- * virtualgpu, the engine's own version line rides virtualmemory) and the
405
- * nvml shim answers under the driver-quota gate: inputs.quota devices
406
- * (default 4, clamped 1-16), each carrying the selected gpu identity
407
- * through FAKE_MODEL/FAKE_VRAM. */
408
- async function virtualdriverslane(code, inputs, deadline) {
409
- const startedat = Date.now();
410
- const { manifest, gpuspec } = composemachine(parsemanifest(code));
411
- const quota = driverquota(inputs);
412
- const versions = driverversions(manifest);
413
- const stdout = [
414
- "saddle virtual-drivers: composed driver report (composed, never booted)",
415
- " driver table (the engine's own version strings):",
416
- ` virtualcpu ${versions.kernel} (the kernel banner of the engine's boot sequence)`,
417
- ` virtualgpu ${gpuspec.driver} (the driver string of the gpu catalog entry)`,
418
- ` virtualmemory ${versions.engine} (the engine version line of the boot sequence)`,
419
- ` nvml shim (the driver-quota gate, quota ${quota}, clamped 1-16):`,
420
- ...Array.from({ length: quota }, (_, index) => ` device ${index}: FAKE_MODEL=${gpuspec.name} FAKE_VRAM=${gpuspec.smireportedmib}`),
421
- ].join("\n");
422
- guarddeadline(startedat, deadline);
423
- const artifact = {
424
- modality: "virtual-drivers",
425
- verdict: "composed",
426
- manifest,
427
- drivers: { virtualcpu: versions.kernel, virtualgpu: gpuspec.driver, virtualmemory: versions.engine },
428
- quota,
429
- nvmlshim: Array.from({ length: quota }, (_, index) => ({
430
- device: index,
431
- FAKE_MODEL: gpuspec.name,
432
- FAKE_VRAM: gpuspec.smireportedmib,
433
- })),
434
- };
435
- return {
436
- stdout,
437
- artifact: { mime: "application/vnd.devthink.sandbox+json", bytes: textencoder.encode(JSON.stringify(artifact)) },
438
- };
439
- }
440
- /** virtual-kvm: the kvm machine planner. composes the qemu argv from the
441
- * engine's turbo builder (buildqemucmd over the manifest's ramgb and the
442
- * topology-resolved vcpus — the cpu model rides the recipe's own
443
- * DiamondRapids default, the qemu cpu model space is the recipe's law),
444
- * the kvm capability names and the clean-rootfs law; the report answers
445
- * the composed plan, never a booted machine — the actual boot rides the
446
- * firecracker/qemu host lanes. a manifest asking for more memory than
447
- * the model's catalog ceiling answers kvm-composition-failed (the
448
- * recipe cannot compose hardware the model cannot address). */
449
- async function virtualkvmlane(code, _inputs, deadline) {
450
- const startedat = Date.now();
451
- const { manifest, cpuspec } = composemachine(parsemanifest(code));
452
- if (manifest.ramgb > cpuspec.maxmemorygb) {
453
- throw edgelaneerror("KVM_COMPOSITION_FAILED", `the manifest asks for ${manifest.ramgb} gb on ${cpuspec.model} whose catalog ceiling is ${cpuspec.maxmemorygb} gb — the recipe cannot compose hardware the model cannot address`);
454
- }
455
- const domain = await loadvirtualization();
456
- const argv = domain.buildqemucmd({ vcpu: manifest.vcpus, memMB: manifest.ramgb * 1024 });
457
- const stdout = [
458
- "saddle virtual-kvm: composed kvm plan (the planner — the boot rides the host lanes, never this one)",
459
- ` manifest: model ${manifest.model} (validated against the cpu catalog), gpu ${manifest.gpu} (validated; the plan carries no display device, vga none), ${manifest.ramgb} gb, ${manifest.vcpus} vcpus`,
460
- ` qemu (the engine's turbo builder, qemu ${domain.qemuversioncheck().split(" ")[0]}):`,
461
- ...argv.map((arg, index) => (index === 0 ? ` ${arg}` : ` ${arg}`)),
462
- ` kvm caps: ${domain.kvmcapnames.length} (${domain.kvmcapnames.join(", ")})`,
463
- " rootfs law: clean-rootfs — the plan ships a pristine rootfs image; this lane composes the plan, it never boots",
464
- ].join("\n");
465
- guarddeadline(startedat, deadline);
466
- const artifact = {
467
- modality: "virtual-kvm",
468
- verdict: "composed-plan",
469
- manifest,
470
- qemu: { version: domain.qemuversioncheck(), argv },
471
- kvmcaps: domain.kvmcapnames,
472
- rootfslaw: "clean-rootfs",
473
- };
474
- return {
475
- stdout,
476
- artifact: { mime: "application/vnd.devthink.sandbox+json", bytes: textencoder.encode(JSON.stringify(artifact)) },
477
- };
478
- }
479
- /** microvm-gpuless: the gpuless render. composes the mesa software stack
480
- * (the engine's pinned summaries: llvmpipe opengl 4.6 through glxinfo,
481
- * lavapipe vulkan 1.4 through vulkaninfo, rusticl opencl 3.1 through
482
- * clinfo, the validated mesaenv record), the cpu and the memory, and
483
- * the xvfb display — the full software-render machine with no gpu
484
- * device in the composition (the render rides the cpu). */
485
- async function microvmgpulesslane(code, _inputs, deadline) {
486
- const startedat = Date.now();
487
- const { manifest, cpuspec } = composemachine(parsemanifest(code));
488
- const memory = composememoryplan(manifest.ramgb, manifest.vcpus);
489
- const env = mesaenv(manifest.vcpus);
490
- const glxinfo = glxinfoSummary();
491
- const vulkan = vulkanSummary();
492
- const clinfo = clinfoSummary(manifest.vcpus);
493
- const stdout = [
494
- "saddle microvm-gpuless: composed software-render machine (composed, never booted)",
495
- ` cpu: ${cpuspec.displayname} — ${manifest.vcpus} vcpus (${cpuspec.microarch})`,
496
- ` memory: ${manifest.ramgb} gb (memtotal ${memory.memtotalkb} kb, swap ${memory.swapgb} gb, the engine's formulas)`,
497
- " mesa software stack (the engine's pinned summaries):",
498
- " glxinfo (llvmpipe — opengl 4.6 core):",
499
- ...glxinfo.split("\n").map((line) => ` ${line}`),
500
- " vulkaninfo (lavapipe — vulkan 1.4):",
501
- ...vulkan.split("\n").map((line) => ` ${line}`),
502
- " clinfo (rusticl — opencl 3.1):",
503
- ...clinfo.split("\n").map((line) => ` ${line}`),
504
- " env (the engine's mesaenv record):",
505
- ...Object.keys(env)
506
- .sort()
507
- .map((key) => ` ${key}=${env[key]}`),
508
- " display (the gpuless virtual display):",
509
- ` ${displaylaw.display} xvfb, screen ${displaylaw.screen}, geometry ${displaylaw.geometry} (the software-render display, nolisten tcp)`,
510
- ].join("\n");
511
- guarddeadline(startedat, deadline);
512
- const artifact = {
513
- modality: "microvm-gpuless",
514
- verdict: "composed",
515
- manifest,
516
- memory: { memtotalkb: memory.memtotalkb, swapgb: memory.swapgb, free: memory.free },
517
- mesa: { glxinfo, vulkan, clinfo, env },
518
- display: { display: displaylaw.display, geometry: displaylaw.geometry },
519
- };
520
- return {
521
- stdout,
522
- artifact: { mime: "application/vnd.devthink.microvm+json", bytes: textencoder.encode(JSON.stringify(artifact)) },
523
- };
524
- }
525
- /** gpu-virgl: the virgl render slice. composes the gpu catalog entry for
526
- * the virtual device, the context-quota law (inputs.contexts, default
527
- * 8, clamped 1-64) and the 3d capability report — the virtio-gpu virgl
528
- * bridge carrying the device identity; the report never claims a host
529
- * gpu, the composition rides the catalog entry. */
530
- async function gpuvirgllane(code, inputs, deadline) {
531
- const startedat = Date.now();
532
- const { manifest, gpuspec } = composemachine(parsemanifest(code));
533
- const contexts = contextquota(inputs);
534
- const stdout = [
535
- "saddle gpu-virgl: composed virgl render slice (composed, never booted)",
536
- ` device: ${gpuspec.name} (${gpuspec.id}) — ${gpuspec.arch}, ${gpuspec.smarch}, ${gpuspec.smcount} sms`,
537
- ` vram: ${gpuspec.vrammib} MiB ${gpuspec.memtype} (the smi surface reports ${gpuspec.smireportedmib} MiB)`,
538
- ` driver: ${gpuspec.driver}${gpuspec.cuda === null ? "" : ` (cuda ${gpuspec.cuda})`}`,
539
- ` context quota: ${contexts} (the context-quota law; inputs.contexts overrides, clamped 1-64)`,
540
- " 3d capability report (the virtual device's catalog entry through the virtio-gpu virgl bridge):",
541
- " virtio-gpu virgl 3d acceleration on (the venus native context stays off — the virgl bridge is the composed path)",
542
- ` contexts ${contexts} concurrent render contexts (ctx 0-${contexts - 1})`,
543
- " render the guest contexts render through the composed device identity above; the lane never claims a host gpu",
544
- ].join("\n");
545
- guarddeadline(startedat, deadline);
546
- const artifact = {
547
- modality: "gpu-virgl",
548
- verdict: "composed",
549
- manifest,
550
- device: {
551
- id: gpuspec.id,
552
- name: gpuspec.name,
553
- arch: gpuspec.arch,
554
- smarch: gpuspec.smarch,
555
- smcount: gpuspec.smcount,
556
- vrammib: gpuspec.vrammib,
557
- driver: gpuspec.driver,
558
- },
559
- contexts,
560
- caps: { virgl: true, venus: false, contexts: `ctx 0-${contexts - 1}` },
561
- };
562
- return {
563
- stdout,
564
- artifact: { mime: "application/vnd.devthink.gpu+json", bytes: textencoder.encode(JSON.stringify(artifact)) },
565
- };
566
- }
567
- /** the seven virtual lane specs (kind live — the lanes compose the
568
- * engine's own payloads in process; the present probes guard the
569
- * imported surfaces by typeof so a module graph that cannot load one
570
- * surface answers absent for that lane, never a fake presence). */
571
- export const virtuallanespecs = Object.freeze([
572
- {
573
- modality: "virtual-full",
574
- kind: "live",
575
- runtime: "sandbox-hardware",
576
- present: () => typeof getcpu === "function" && typeof bootSequence === "function",
577
- },
578
- {
579
- modality: "virtual-vgpu",
580
- kind: "live",
581
- runtime: "sandbox-mig",
582
- present: () => typeof nvidiaSmiTable === "function" && migprofiles.length > 0,
583
- },
584
- {
585
- modality: "virtual-screen",
586
- kind: "live",
587
- runtime: "sandbox-display",
588
- present: () => typeof getgpu === "function" && typeof freeh === "function",
589
- },
590
- {
591
- modality: "virtual-drivers",
592
- kind: "live",
593
- runtime: "sandbox-drivers",
594
- present: () => typeof bootSequence === "function" && typeof getgpu === "function",
595
- },
596
- {
597
- modality: "virtual-kvm",
598
- kind: "live",
599
- runtime: "qemu-planner",
600
- present: () => true /* the kvm lane composes from the lazy domain: the probe answers the engine ships the composition seat */,
601
- },
602
- {
603
- modality: "microvm-gpuless",
604
- kind: "live",
605
- runtime: "mesa-llvmpipe",
606
- present: () => typeof glxinfoSummary === "function" && typeof mesaenv === "function",
607
- },
608
- {
609
- modality: "gpu-virgl",
610
- kind: "live",
611
- runtime: "virgl-virtio-gpu",
612
- present: () => typeof getgpu === "function" && typeof solvetopology === "function",
613
- },
614
- ]);
615
- /** the lane executor table of the virtual lanes, keyed by modality id:
616
- * the dispatch plane refuses to boot over a lane it cannot wire. */
617
- export const edgelaneexecutorsvirtual = Object.freeze({
618
- "virtual-full": virtualfulllane,
619
- "virtual-vgpu": virtualvgpulane,
620
- "virtual-screen": virtualscreenlane,
621
- "virtual-drivers": virtualdriverslane,
622
- "virtual-kvm": virtualkvmlane,
623
- "microvm-gpuless": microvmgpulesslane,
624
- "gpu-virgl": gpuvirgllane,
625
- });
626
- /** the seven virtual lane ids derived from the spec table (the order is
627
- * the spec order; the ids are pinned — the orchestrator's edge plane and
628
- * the api routes read them exactly). */
629
- export const virtuallaneids = Object.freeze(virtuallanespecs.map((spec) => spec.modality));