@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
package/cli.ts ADDED
@@ -0,0 +1,274 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * cli.ts — the saddle command-line entry point.
4
+ *
5
+ * This file is the v2.0.0 grand-merge consolidation of the former nested
6
+ * folders of the repository (cli) into the single
7
+ * root-level domain file of the e2ugh family standard: one optimized
8
+ * TypeScript file per correlated domain, ordinal sections, JSDoc on every
9
+ * block, intra-domain imports dissolved, cross-domain imports rewritten to
10
+ * ./<domain>.js. Every capability of every source file is preserved here;
11
+ * the pure re-export barrels (none in this domain) folded their surface into this file directly.
12
+ */
13
+
14
+ import { mkdtemp, readFile } from "node:fs/promises";
15
+ import { tmpdir } from "node:os";
16
+ import { join } from "node:path";
17
+ import { argv } from "node:process";
18
+ import { eventbus } from "./foundation.ts";
19
+ import { localmemory, localstorage } from "./virtual.ts";
20
+ import { engine, inprocess, scheduler } from "./execution.ts";
21
+ import { mcpserver } from "./integration.ts";
22
+ import { modecatalog } from "./modes.ts";
23
+ import { creategrid, defaultplan, dockerrun, multiplex, planlint, plantoml, qemucommand, type plan } from "./index.ts";
24
+ import {
25
+ compilewithbabel,
26
+ dockerdescriptor,
27
+ interpretsh,
28
+ interpretyaml,
29
+ interpretyml,
30
+ runscript,
31
+ runscriptbackground,
32
+ scriptRunStatus,
33
+ type ScriptPlan,
34
+ } from "./scriptlanes.ts";
35
+
36
+ /* ════════════════════════════════════════════════════════════════════ */
37
+ /* Section 1: cli/main.ts — the saddle command-line entry point (the bin "saddle" resolves to this source through the source-is-library law (node 26 strips the types, the shebang hands the file to the runtime)). */
38
+ /* ════════════════════════════════════════════════════════════════════ */
39
+ /**
40
+ * the cli keeps local execution explicit and leaves remote dispatch to adapters.
41
+ */
42
+
43
+ /** Runs one CLI command and keeps external services behind adapters. */
44
+ export async function main(args = argv.slice(2)) {
45
+ const command = args[0] ?? "help";
46
+ /* Help stays short and lists only stable local commands. */
47
+ if (["help", "--help", "-h"].includes(command)) { console.log("saddle <command>\n\ncommands\n help\n modes\n plan [qemu|docker|toml]\n vm [qemu|docker|toml]\n vmlint\n gpus\n runexample\n script <run|background|status|docker|compile> [file|runid]\n mcp"); return; }
48
+ if (command === "modes") { console.log(JSON.stringify(modecatalog(), null, 2)); return; }
49
+ if (command === "plan") { await renderplan(args[1]); return; }
50
+ /* The vm/vmlint/gpus triad makes the nominal npm aliases (vm:create, */
51
+ /* vm:validate, gpu:list) real: they map to the live engine surface — */
52
+ /* the plan renderer, the planlint validator, and the gpus.json catalog. */
53
+ if (command === "vm") { await renderplan(args[1] ?? "qemu"); return; }
54
+ if (command === "vmlint") { await rendervmlint(); return; }
55
+ if (command === "gpus") { await rendergpus(); return; }
56
+ if (command === "runexample") {
57
+ const root = await mkdtemp(join(tmpdir(), "saddlecli"));
58
+ const events = eventbus();
59
+ const run = engine({ storage: localstorage(root), memory: localmemory(), scheduler: scheduler([inprocess()]), events });
60
+ const result = await run.run({ name: "cliexample", input: { hello: "saddle" } }, ({ job }) => ({ jobid: job.id, ok: true, message: "storage to working set to result" }));
61
+ console.log(JSON.stringify({ jobid: result.job.id, artifact: result.artifact, events: events.all().length }, null, 2));
62
+ return;
63
+ }
64
+ if (command === "script") { await renderscript(args[1], args[2]); return; }
65
+ if (command === "mcp") { const server = mcpserver(); console.log(JSON.stringify({ tools: server.listtools() }, null, 2)); return; }
66
+ throw new Error(`unknown command: ${command}`);
67
+ }
68
+
69
+ /* ════════════════════════════════════════════════════════════════════ */
70
+ /* Section 2: the plan renderer — the architect CLI absorbed from the e2ugh */
71
+ /* engine entry (index.ts); the former `e2ugh` bin folds into the single */
72
+ /* `saddle` bin at the 2.0.0 grand merge. */
73
+ /* ════════════════════════════════════════════════════════════════════ */
74
+ /**
75
+ * Renders one machine plan (defaulting to defaultplan, overridden by the
76
+ * optional vm.config.toml regex fields) preceded by the MTTG multiplex
77
+ * header — the absorbed e2ugh engine CLI entry, byte-compatible with the
78
+ * former `node ./index.ts` invocation through the single saddle bin.
79
+ *
80
+ * @param format the render format: qemu (default), docker or toml.
81
+ */
82
+ async function renderplan(format = "qemu") {
83
+ try {
84
+ let candidate: plan = { ...defaultplan };
85
+ try {
86
+ const raw = await readFile("vm.config.toml", "utf8");
87
+ const vcpus = /vcpus = (\d+)/.exec(raw)?.[1];
88
+ const mem = /gib = (\d+)/.exec(raw)?.[1];
89
+ const mttg = /virtual_threads = (\d+)/.exec(raw)?.[1];
90
+ if (vcpus !== undefined) {
91
+ candidate = { ...candidate, vcpus: Number(vcpus) };
92
+ }
93
+ if (mem !== undefined) {
94
+ candidate = { ...candidate, memorygib: Number(mem) };
95
+ }
96
+ if (mttg !== undefined) {
97
+ candidate = { ...candidate, mttgthreads: Number(mttg), mttg: true };
98
+ }
99
+ } catch {
100
+ /* catcher: vm.config.toml is optional; defaults stay */
101
+ }
102
+ const grid = creategrid(undefined, candidate.mttgthreads);
103
+ const header = `# multiplex ${multiplex(grid).toFixed(1)}x on ${grid.host} host threads\n`;
104
+ const body =
105
+ format === "docker"
106
+ ? dockerrun(candidate)
107
+ : format === "toml"
108
+ ? plantoml(candidate)
109
+ : qemucommand(candidate);
110
+ process.stdout.write(`${header}${body}\n`);
111
+ for (const note of planlint(candidate)) {
112
+ process.stderr.write(`# ${note}\n`);
113
+ }
114
+ } catch (error) {
115
+ process.stderr.write(
116
+ `planner failed: ${error instanceof Error ? error.message : String(error)}\n`,
117
+ );
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Validates the effective machine plan (defaults overridden by the optional
123
+ * vm.config.toml fields) through planlint and prints only the advisory
124
+ * notes — the engine behind the nominal `vm:validate` npm alias: exit code
125
+ * stays zero because the notes are advisory, never fatal.
126
+ */
127
+ async function rendervmlint() {
128
+ let candidate: plan = { ...defaultplan };
129
+ try {
130
+ const raw = await readFile("vm.config.toml", "utf8");
131
+ const vcpus = /vcpus = (\d+)/.exec(raw)?.[1];
132
+ const mem = /gib = (\d+)/.exec(raw)?.[1];
133
+ const mttg = /virtual_threads = (\d+)/.exec(raw)?.[1];
134
+ if (vcpus !== undefined) candidate = { ...candidate, vcpus: Number(vcpus) };
135
+ if (mem !== undefined) candidate = { ...candidate, memorygib: Number(mem) };
136
+ if (mttg !== undefined) candidate = { ...candidate, mttgthreads: Number(mttg), mttg: true };
137
+ } catch {
138
+ /* catcher: vm.config.toml is optional; defaults stay */
139
+ }
140
+ const notes = planlint(candidate);
141
+ console.log(`vcpus ${candidate.vcpus} memorygib ${candidate.memorygib} — ${notes.length} note(s)`);
142
+ for (const note of notes) {
143
+ console.log(`# ${note}`);
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Lists the GPU catalog of the engine (gpus.json — the catalog the
149
+ * orchestrator resolves GPU requests against) — the engine behind the
150
+ * nominal `gpu:list` npm alias.
151
+ */
152
+ async function rendergpus() {
153
+ const catalog = JSON.parse(await readFile("gpus.json", "utf8")) as { gpus: Array<Record<string, unknown>> };
154
+ console.log(`${catalog.gpus.length} gpus`);
155
+ for (const gpu of catalog.gpus) {
156
+ const name = String(gpu.name ?? gpu.model ?? "unknown");
157
+ const profiles = Array.isArray(gpu.profiles) ? (gpu.profiles as unknown[]).length : 0;
158
+ console.log(profiles > 0 ? `${name} (${profiles} mig profiles)` : name);
159
+ }
160
+ }
161
+
162
+ /* ══════════════════════════════════════════════════════════════════ */
163
+ /* Section 3: the script lanes renderer — the sh/yml/yaml execution */
164
+ /* surface of the engine lane (PR15): run, background, status, docker */
165
+ /* and compile ride the very scriptlanes.ts functions the webserver */
166
+ /* routes serve, so the bin and the api speak one lane. */
167
+ /* ══════════════════════════════════════════════════════════════════ */
168
+ /**
169
+ * the script lanes renderer: every descriptor subcommand reads one
170
+ * file whose extension picks the interpretation lane and answers the
171
+ * honest result — no faked exit codes, no silent skips.
172
+ */
173
+
174
+ /** the poll pause the background renderer waits with (the same cadence
175
+ * the script lanes test polls the detached record with). */
176
+ const scriptpause = (milliseconds: number) => new Promise((resolve) => setTimeout(resolve, milliseconds));
177
+
178
+ /**
179
+ * interprets one descriptor file into a script plan: the extension
180
+ * picks the lane — .sh wraps the raw script as one direct step,
181
+ * .yml and .yaml ride the house yaml subset (both spellings one lane,
182
+ * the plan declares the babel compile lane). a missing file or an
183
+ * unknown extension refuses honestly instead of guessing.
184
+ *
185
+ * @param target the descriptor file path.
186
+ * @returns the interpreted plan.
187
+ */
188
+ async function scriptplanfromfile(target: string): Promise<ScriptPlan> {
189
+ if (target.length === 0) {
190
+ throw new Error("the script subcommand requires a descriptor file (.sh, .yml or .yaml)");
191
+ }
192
+ const text = await readFile(target, "utf8");
193
+ if (target.endsWith(".sh")) return interpretsh(text);
194
+ if (target.endsWith(".yml")) return interpretyml(text);
195
+ if (target.endsWith(".yaml")) return interpretyaml(text);
196
+ throw new Error(`the descriptor extension of "${target}" is not one the script lanes speak (.sh, .yml, .yaml)`);
197
+ }
198
+
199
+ /**
200
+ * Renders one script lanes subcommand: run executes the plan
201
+ * server-side with the enforced per-step deadlines and prints the
202
+ * honest per-step result (a failed plan exits 1); background kicks the
203
+ * plan detached through the house job queue, prints the launch answer
204
+ * and observes the record settle through the run status (the registry
205
+ * lives in this process, the poll reads it the way the api consumer
206
+ * does); status reads the observable record of one runid — honestly
207
+ * refusing a runid another process launched (SCRIPT_RUN_NOT_FOUND,
208
+ * the one-shot cli never carried that registry); docker emits the
209
+ * docker-ready descriptor of the plan; compile validates the babel
210
+ * roundtrip and prints the compiled plan.
211
+ *
212
+ * @param subcommand the script subcommand (run, background, status, docker, compile).
213
+ * @param target the descriptor file path (or the runid for status).
214
+ */
215
+ async function renderscript(subcommand = "help", target = "") {
216
+ if (["help", "--help", "-h"].includes(subcommand)) {
217
+ console.log(
218
+ "saddle script <run|background|status|docker|compile> [file|runid]" +
219
+ "\n\n run <file> execute the plan server-side and print the honest per-step result" +
220
+ "\n background <file> kick the plan detached and observe the record settle" +
221
+ "\n status <runid> read the observable record of one background run" +
222
+ "\n docker <file> emit the docker-ready descriptor of the plan" +
223
+ "\n compile <file> ride the babel compile roundtrip and print the compiled plan",
224
+ );
225
+ return;
226
+ }
227
+ try {
228
+ if (subcommand === "run") {
229
+ const plan = await scriptplanfromfile(target);
230
+ const result = await runscript(plan);
231
+ console.log(JSON.stringify({ source: plan.source, compiledvia: plan.compiledvia, ...result }, null, 2));
232
+ if (result.status === "failed") process.exitCode = 1;
233
+ return;
234
+ }
235
+ if (subcommand === "background") {
236
+ const plan = await scriptplanfromfile(target);
237
+ const launch = runscriptbackground(plan);
238
+ console.log(JSON.stringify({ runid: launch.runid, status: launch.status, source: plan.source }, null, 2));
239
+ let record = scriptRunStatus(launch.runid);
240
+ const deadlineat = Date.now() + 60000;
241
+ while (record.status !== "succeeded" && record.status !== "failed" && Date.now() < deadlineat) {
242
+ await scriptpause(50);
243
+ record = scriptRunStatus(launch.runid);
244
+ }
245
+ console.log(JSON.stringify(record, null, 2));
246
+ if (record.status === "failed") process.exitCode = 1;
247
+ return;
248
+ }
249
+ if (subcommand === "status") {
250
+ if (target.length === 0) throw new Error("the status subcommand requires a runid");
251
+ console.log(JSON.stringify(scriptRunStatus(target), null, 2));
252
+ return;
253
+ }
254
+ if (subcommand === "docker") {
255
+ const plan = await scriptplanfromfile(target);
256
+ const descriptor = dockerdescriptor(plan);
257
+ process.stdout.write(descriptor.dockerfile);
258
+ process.stdout.write(`# entrypoint (docker run): ${descriptor.entrypoint}\n`);
259
+ return;
260
+ }
261
+ if (subcommand === "compile") {
262
+ const plan = await scriptplanfromfile(target);
263
+ const compiled = await compilewithbabel(plan);
264
+ console.log(JSON.stringify(compiled, null, 2));
265
+ return;
266
+ }
267
+ throw new Error(`unknown script subcommand: ${subcommand}`);
268
+ } catch (error) {
269
+ process.stderr.write(`script lane failed: ${error instanceof Error ? error.message : String(error)}\n`);
270
+ process.exitCode = 1;
271
+ }
272
+ }
273
+
274
+ if (import.meta.url === `file://${argv[1]}`) main().catch((error) => { console.error(error); process.exitCode = 1; });