windows-development-sandbox 1.7.0 → 1.9.0

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 (413) hide show
  1. package/config.example.json +10 -0
  2. package/dist/app/context.d.ts +8 -0
  3. package/dist/app/context.js +12 -0
  4. package/dist/app/features/defs.d.ts +322 -0
  5. package/dist/app/features/defs.js +28 -0
  6. package/dist/app/features/sandbox/index.d.ts +2 -0
  7. package/dist/app/features/sandbox/index.js +3 -0
  8. package/dist/app/features/sandbox/sandbox.def.d.ts +193 -0
  9. package/dist/app/features/sandbox/sandbox.def.js +245 -0
  10. package/dist/app/features/sandbox/sandbox.run.d.ts +72 -0
  11. package/dist/app/features/sandbox/sandbox.run.js +98 -0
  12. package/dist/app/features/sessions/index.d.ts +2 -0
  13. package/dist/app/features/sessions/index.js +3 -0
  14. package/dist/app/features/sessions/sessions.def.d.ts +141 -0
  15. package/dist/app/features/sessions/sessions.def.js +176 -0
  16. package/dist/app/features/sessions/sessions.run.d.ts +39 -0
  17. package/dist/app/features/sessions/sessions.run.js +58 -0
  18. package/dist/{cli/menu/settings/categories.d.ts → app/features/settings/categories.def.d.ts} +2 -0
  19. package/dist/{cli/menu/settings/categories.js → app/features/settings/categories.def.js} +24 -5
  20. package/dist/app/features/settings/index.d.ts +5 -0
  21. package/dist/app/features/settings/index.js +6 -0
  22. package/dist/{cli/menu/settings/config-file.d.ts → app/features/settings/settings-file.d.ts} +1 -1
  23. package/dist/{cli/menu/settings/config-file.js → app/features/settings/settings-file.js} +1 -1
  24. package/dist/app/features/settings/settings-rows.d.ts +35 -0
  25. package/dist/app/features/settings/settings-rows.js +94 -0
  26. package/dist/app/features/settings/settings.def.d.ts +157 -0
  27. package/dist/app/features/settings/settings.def.js +179 -0
  28. package/dist/app/features/settings/settings.run.d.ts +67 -0
  29. package/dist/app/features/settings/settings.run.js +84 -0
  30. package/dist/app/kernel/define.d.ts +143 -0
  31. package/dist/app/kernel/define.js +42 -0
  32. package/dist/app/kernel/errors.d.ts +34 -0
  33. package/dist/app/kernel/errors.js +45 -0
  34. package/dist/app/kernel/fields.d.ts +70 -0
  35. package/dist/app/kernel/fields.js +243 -0
  36. package/dist/app/kernel/index.d.ts +8 -0
  37. package/dist/app/kernel/index.js +10 -0
  38. package/dist/app/kernel/io.d.ts +193 -0
  39. package/dist/app/kernel/io.js +126 -0
  40. package/dist/app/kernel/rpc.d.ts +156 -0
  41. package/dist/app/kernel/rpc.js +47 -0
  42. package/dist/app/kernel/text.d.ts +6 -0
  43. package/dist/app/kernel/text.js +57 -0
  44. package/dist/app/kernel/view.d.ts +146 -0
  45. package/dist/app/kernel/view.js +28 -0
  46. package/dist/app/registry.d.ts +10 -0
  47. package/dist/app/registry.js +50 -0
  48. package/dist/cli/args.d.ts +5 -0
  49. package/dist/cli/args.js +6 -0
  50. package/dist/cli/commands/engine.d.ts +2 -0
  51. package/dist/cli/commands/engine.js +60 -0
  52. package/dist/cli/commands/index.d.ts +1 -1
  53. package/dist/cli/commands/index.js +1 -1
  54. package/dist/cli/commands/launch/launch.js +47 -7
  55. package/dist/cli/commands/launch/prepare.js +3 -3
  56. package/dist/cli/commands/launch/running.js +2 -1
  57. package/dist/cli/commands/launch/summary.d.ts +2 -0
  58. package/dist/cli/commands/maintenance/config-share.d.ts +12 -0
  59. package/dist/cli/commands/maintenance/config-share.js +80 -0
  60. package/dist/cli/commands/maintenance/config.js +8 -82
  61. package/dist/cli/commands/maintenance/logs.js +14 -0
  62. package/dist/cli/commands/registry.js +3 -7
  63. package/dist/cli/commands/repair/checks/contained.d.ts +2 -0
  64. package/dist/cli/commands/repair/checks/contained.js +139 -0
  65. package/dist/cli/commands/repair/checks/hcs.d.ts +7 -0
  66. package/dist/cli/commands/repair/checks/hcs.js +28 -0
  67. package/dist/cli/commands/repair/checks/index.js +4 -0
  68. package/dist/cli/commands/repair/checks/pc.js +32 -1
  69. package/dist/cli/commands/repair/checks/sandbox.js +16 -1
  70. package/dist/cli/commands/repair/checks/vpn.js +34 -9
  71. package/dist/cli/commands/repair/env.js +2 -1
  72. package/dist/cli/commands/sessions/index.d.ts +0 -4
  73. package/dist/cli/commands/sessions/index.js +3 -7
  74. package/dist/cli/commands/shared-use.d.ts +5 -2
  75. package/dist/cli/commands/shared-use.js +11 -8
  76. package/dist/cli/commands/storage/contained.d.ts +3 -0
  77. package/dist/cli/commands/storage/contained.js +179 -0
  78. package/dist/cli/commands/storage/offer.js +7 -1
  79. package/dist/cli/commands/storage/storage.js +10 -2
  80. package/dist/cli/commands/user-config.js +1 -1
  81. package/dist/cli/commands/vpn.js +19 -3
  82. package/dist/cli/commands/web.js +2 -0
  83. package/dist/cli/index.js +2 -1
  84. package/dist/cli/manifest.d.ts +72 -104
  85. package/dist/cli/manifest.js +64 -39
  86. package/dist/cli/menu/add-agent.d.ts +1 -1
  87. package/dist/cli/menu/add-agent.js +1 -1
  88. package/dist/cli/menu/apps.d.ts +7 -1
  89. package/dist/cli/menu/apps.js +36 -0
  90. package/dist/cli/menu/command-fields.d.ts +1 -1
  91. package/dist/cli/menu/command-form.js +2 -2
  92. package/dist/cli/menu/io-menu.d.ts +29 -0
  93. package/dist/cli/menu/io-menu.js +126 -0
  94. package/dist/cli/menu/live.d.ts +27 -0
  95. package/dist/cli/menu/live.js +69 -0
  96. package/dist/cli/menu/memory.d.ts +19 -0
  97. package/dist/cli/menu/memory.js +53 -0
  98. package/dist/cli/menu/menu.d.ts +10 -1
  99. package/dist/cli/menu/menu.js +27 -9
  100. package/dist/cli/menu/pages/agents-page.d.ts +3 -1
  101. package/dist/cli/menu/pages/agents-page.js +12 -5
  102. package/dist/cli/menu/pages/apps-page.d.ts +3 -1
  103. package/dist/cli/menu/pages/apps-page.js +19 -2
  104. package/dist/cli/menu/pages/list-page.d.ts +27 -0
  105. package/dist/cli/menu/pages/list-page.js +109 -7
  106. package/dist/cli/menu/pages/maintenance-page.d.ts +0 -5
  107. package/dist/cli/menu/pages/maintenance-page.js +17 -19
  108. package/dist/cli/menu/pages/sandbox-page.d.ts +4 -6
  109. package/dist/cli/menu/pages/sandbox-page.js +26 -118
  110. package/dist/cli/menu/pages/scopes.d.ts +1 -1
  111. package/dist/cli/menu/pages/sessions-page.d.ts +5 -11
  112. package/dist/cli/menu/pages/sessions-page.js +19 -88
  113. package/dist/cli/menu/pages/settings-page.d.ts +2 -10
  114. package/dist/cli/menu/pages/settings-page.js +64 -94
  115. package/dist/cli/menu/render-view.d.ts +28 -0
  116. package/dist/cli/menu/render-view.js +112 -0
  117. package/dist/cli/menu/settings/{path-kind.d.ts → ask-path.d.ts} +1 -7
  118. package/dist/cli/menu/settings/ask-path.js +14 -0
  119. package/dist/cli/menu/settings/collections/collection-editor.d.ts +1 -1
  120. package/dist/cli/menu/settings/collections/string-list-editor.d.ts +1 -2
  121. package/dist/cli/menu/settings/collections/string-list-editor.js +1 -1
  122. package/dist/cli/menu/settings/draft.d.ts +1 -1
  123. package/dist/cli/menu/settings/format.d.ts +1 -3
  124. package/dist/cli/menu/settings/format.js +6 -36
  125. package/dist/cli/menu/settings/index.d.ts +1 -3
  126. package/dist/cli/menu/settings/index.js +3 -3
  127. package/dist/cli/menu/settings/object-editor.d.ts +1 -1
  128. package/dist/cli/menu/settings/share.d.ts +36 -0
  129. package/dist/cli/menu/settings/share.js +131 -0
  130. package/dist/cli/menu/settings/value-editor.d.ts +5 -1
  131. package/dist/cli/menu/settings/value-editor.js +57 -54
  132. package/dist/cli/menu/several.js +1 -1
  133. package/dist/cli/menu/share-settings.d.ts +21 -0
  134. package/dist/cli/menu/share-settings.js +112 -0
  135. package/dist/cli/menu/shell.d.ts +21 -5
  136. package/dist/cli/menu/shell.js +31 -6
  137. package/dist/cli/menu/views.d.ts +7 -0
  138. package/dist/cli/menu/views.js +11 -0
  139. package/dist/cli/menu/vpn-login.js +8 -0
  140. package/dist/cli/operations/handler.d.ts +6 -0
  141. package/dist/cli/operations/handler.js +61 -0
  142. package/dist/cli/operations/index.d.ts +4 -0
  143. package/dist/cli/operations/index.js +5 -0
  144. package/dist/cli/operations/input.d.ts +6 -0
  145. package/dist/cli/operations/input.js +37 -0
  146. package/dist/cli/operations/io-cli.d.ts +7 -0
  147. package/dist/cli/operations/io-cli.js +62 -0
  148. package/dist/cli/operations/spec.d.ts +18 -0
  149. package/dist/cli/operations/spec.js +108 -0
  150. package/dist/cli/output/colors.d.ts +2 -2
  151. package/dist/cli/output/colors.js +2 -11
  152. package/dist/cli/output/index.d.ts +1 -0
  153. package/dist/cli/output/index.js +1 -0
  154. package/dist/cli/output/print.d.ts +3 -1
  155. package/dist/cli/output/print.js +7 -3
  156. package/dist/cli/output/progress.d.ts +15 -0
  157. package/dist/cli/output/progress.js +44 -0
  158. package/dist/cli/output/render-view.d.ts +4 -0
  159. package/dist/cli/output/render-view.js +63 -0
  160. package/dist/cli/services/agent-commands-service.d.ts +2 -0
  161. package/dist/cli/services/agent-commands-service.js +11 -2
  162. package/dist/cli/services/logs-service.js +4 -3
  163. package/dist/cli/tui/app.d.ts +6 -1
  164. package/dist/cli/tui/app.js +26 -4
  165. package/dist/cli/tui/list/list-screen.d.ts +14 -0
  166. package/dist/cli/tui/list/list-screen.js +64 -36
  167. package/dist/cli/tui/list/list-types.d.ts +2 -0
  168. package/dist/cli/tui/terminal.d.ts +7 -0
  169. package/dist/cli/tui/terminal.js +30 -10
  170. package/dist/core/config/defaults.js +8 -0
  171. package/dist/core/schema/config.d.ts +13 -0
  172. package/dist/core/schema/config.js +16 -1
  173. package/dist/core/schema/harness.d.ts +1 -0
  174. package/dist/core/schema/harness.js +5 -0
  175. package/dist/core/schema/sandbox.d.ts +6 -0
  176. package/dist/core/schema/sandbox.js +20 -3
  177. package/dist/core/schema/vpn.d.ts +2 -1
  178. package/dist/core/schema/vpn.js +3 -3
  179. package/dist/core/types.d.ts +23 -5
  180. package/dist/core/util/fs.d.ts +2 -0
  181. package/dist/core/util/fs.js +9 -0
  182. package/dist/core/util/index.d.ts +1 -1
  183. package/dist/core/util/index.js +1 -1
  184. package/dist/guest/agents/agent-files.d.ts +5 -0
  185. package/dist/guest/agents/agent-files.js +4 -0
  186. package/dist/guest/agents/local-state.d.ts +2 -0
  187. package/dist/guest/agents/local-state.js +21 -1
  188. package/dist/guest/boot/boot.js +2 -1
  189. package/dist/guest/daemon/daemon.js +4 -0
  190. package/dist/guest/daemon/sessions.d.ts +5 -0
  191. package/dist/guest/daemon/sessions.js +17 -3
  192. package/dist/guest/entries/daemon.js +3 -0
  193. package/dist/guest/governor/decide.d.ts +61 -0
  194. package/dist/guest/governor/decide.js +182 -0
  195. package/dist/guest/governor/governor.d.ts +42 -0
  196. package/dist/guest/governor/governor.js +214 -0
  197. package/dist/guest/governor/index.d.ts +2 -0
  198. package/dist/guest/governor/index.js +2 -0
  199. package/dist/guest/runtime/csc.d.ts +1 -0
  200. package/dist/guest/runtime/csc.js +1 -0
  201. package/dist/guest/sessions/viewer.js +3 -1
  202. package/dist/guest/toolchains/native/rust-extras.js +4 -2
  203. package/dist/guest/vpn/vpn.js +69 -21
  204. package/dist/guest/vpn/wireguard.d.ts +32 -0
  205. package/dist/guest/vpn/wireguard.js +132 -0
  206. package/dist/host/agent-commands/commands.d.ts +4 -0
  207. package/dist/host/agent-commands/commands.js +31 -7
  208. package/dist/host/audit/log.d.ts +1 -1
  209. package/dist/host/channel/attach.d.ts +3 -1
  210. package/dist/host/channel/attach.js +5 -2
  211. package/dist/host/channel/channel.d.ts +2 -0
  212. package/dist/host/channel/channel.js +4 -0
  213. package/dist/host/engines/engine.d.ts +12 -0
  214. package/dist/host/engines/engine.js +1 -0
  215. package/dist/host/engines/hcs/check.d.ts +25 -0
  216. package/dist/host/engines/hcs/check.js +95 -0
  217. package/dist/host/engines/hcs/documents.d.ts +44 -0
  218. package/dist/host/engines/hcs/documents.js +155 -0
  219. package/dist/host/engines/hcs/engine.d.ts +39 -0
  220. package/dist/host/engines/hcs/engine.js +171 -0
  221. package/dist/host/engines/hcs/helper.d.ts +43 -0
  222. package/dist/host/engines/hcs/helper.js +173 -0
  223. package/dist/host/engines/hcs/images.d.ts +37 -0
  224. package/dist/host/engines/hcs/images.js +152 -0
  225. package/dist/host/engines/index.d.ts +7 -0
  226. package/dist/host/engines/index.js +5 -0
  227. package/dist/host/engines/registry.d.ts +16 -0
  228. package/dist/host/engines/registry.js +30 -0
  229. package/dist/host/engines/types.d.ts +58 -0
  230. package/dist/host/engines/types.js +1 -0
  231. package/dist/host/engines/windows-sandbox/engine.d.ts +16 -0
  232. package/dist/host/engines/windows-sandbox/engine.js +63 -0
  233. package/dist/host/engines/windows-sandbox/wsb-text.d.ts +2 -0
  234. package/dist/host/engines/windows-sandbox/wsb-text.js +29 -0
  235. package/dist/host/launch/generate.d.ts +5 -1
  236. package/dist/host/launch/generate.js +50 -8
  237. package/dist/host/launch/index.d.ts +3 -1
  238. package/dist/host/launch/index.js +3 -1
  239. package/dist/host/launch/launch-plan.d.ts +13 -0
  240. package/dist/host/launch/launch-plan.js +26 -0
  241. package/dist/host/launch/mappings.js +2 -1
  242. package/dist/host/launch/risk-notes.d.ts +10 -0
  243. package/dist/host/launch/risk-notes.js +18 -0
  244. package/dist/host/launch/session-file.d.ts +2 -0
  245. package/dist/host/launch/session-file.js +7 -1
  246. package/dist/host/launch/wsb-file.d.ts +28 -4
  247. package/dist/host/launch/wsb-file.js +61 -42
  248. package/dist/host/life/crash-report.d.ts +27 -1
  249. package/dist/host/life/crash-report.js +173 -7
  250. package/dist/host/life/host-memory.d.ts +40 -0
  251. package/dist/host/life/host-memory.js +137 -0
  252. package/dist/host/life/index.d.ts +2 -0
  253. package/dist/host/life/index.js +2 -0
  254. package/dist/host/life/stop-events.d.ts +2 -0
  255. package/dist/host/life/stop-events.js +20 -3
  256. package/dist/host/life/stop-warning.js +1 -1
  257. package/dist/host/life/watchdog.d.ts +54 -0
  258. package/dist/host/life/watchdog.js +108 -0
  259. package/dist/host/native.d.ts +3 -2
  260. package/dist/host/native.js +22 -3
  261. package/dist/host/profile/claude-login.js +3 -2
  262. package/dist/host/sandbox/contained-deps.d.ts +2 -0
  263. package/dist/host/sandbox/contained-deps.js +17 -0
  264. package/dist/host/sandbox/index.d.ts +2 -0
  265. package/dist/host/sandbox/index.js +2 -0
  266. package/dist/host/sandbox/platform.d.ts +2 -0
  267. package/dist/host/sandbox/platform.js +7 -7
  268. package/dist/host/sandbox/tasklist.d.ts +13 -0
  269. package/dist/host/sandbox/tasklist.js +47 -0
  270. package/dist/host/secrets/launch-secrets.js +2 -1
  271. package/dist/host/sharing/current.js +2 -6
  272. package/dist/host/storage/contained/check.d.ts +9 -0
  273. package/dist/host/storage/contained/check.js +37 -0
  274. package/dist/host/storage/contained/contained-storage.d.ts +66 -0
  275. package/dist/host/storage/contained/contained-storage.js +168 -0
  276. package/dist/host/storage/contained/disk-port.d.ts +43 -0
  277. package/dist/host/storage/contained/disk-port.js +122 -0
  278. package/dist/host/storage/contained/index.d.ts +9 -0
  279. package/dist/host/storage/contained/index.js +8 -0
  280. package/dist/host/storage/contained/layout.d.ts +28 -0
  281. package/dist/host/storage/contained/layout.js +45 -0
  282. package/dist/host/storage/contained/resolve.d.ts +4 -0
  283. package/dist/host/storage/contained/resolve.js +30 -0
  284. package/dist/host/storage/contained/setting.d.ts +1 -0
  285. package/dist/host/storage/contained/setting.js +5 -0
  286. package/dist/host/storage/contained/state.d.ts +89 -0
  287. package/dist/host/storage/contained/state.js +166 -0
  288. package/dist/host/storage/contained/transfer.d.ts +24 -0
  289. package/dist/host/storage/contained/transfer.js +121 -0
  290. package/dist/host/storage/index.d.ts +2 -0
  291. package/dist/host/storage/index.js +2 -0
  292. package/dist/host/storage/providers/contained.d.ts +15 -0
  293. package/dist/host/storage/providers/contained.js +39 -0
  294. package/dist/host/storage/providers/folder.d.ts +12 -0
  295. package/dist/host/storage/providers/folder.js +20 -0
  296. package/dist/host/storage/providers/index.d.ts +4 -0
  297. package/dist/host/storage/providers/index.js +3 -0
  298. package/dist/host/storage/providers/registry.d.ts +9 -0
  299. package/dist/host/storage/providers/registry.js +14 -0
  300. package/dist/host/storage/providers/types.d.ts +33 -0
  301. package/dist/host/storage/providers/types.js +1 -0
  302. package/dist/host/tools/conpty.js +3 -2
  303. package/dist/host/tools/windows-terminal.js +8 -7
  304. package/dist/host/vpn/index.d.ts +1 -1
  305. package/dist/host/vpn/index.js +1 -1
  306. package/dist/host/vpn/prepare.d.ts +2 -0
  307. package/dist/host/vpn/prepare.js +63 -2
  308. package/dist/host/web/browser.d.ts +2 -0
  309. package/dist/host/web/browser.js +14 -1
  310. package/dist/host/web/index.d.ts +3 -2
  311. package/dist/host/web/index.js +3 -2
  312. package/dist/host/web/rpc.d.ts +24 -0
  313. package/dist/host/web/rpc.js +149 -0
  314. package/dist/host/web/runner.d.ts +2 -0
  315. package/dist/host/web/runner.js +1 -2
  316. package/dist/host/web/server.d.ts +7 -0
  317. package/dist/host/web/server.js +23 -3
  318. package/dist/runtime/agent.js +69 -8
  319. package/dist/runtime/daemon.js +1058 -624
  320. package/dist/runtime/db.js +69 -8
  321. package/dist/runtime/main.js +624 -182
  322. package/dist/runtime/netproxy.js +69 -8
  323. package/dist/runtime/view.js +87 -13
  324. package/dist/selftest/agent-paths.test.js +11 -1
  325. package/dist/selftest/app.test.d.ts +2 -0
  326. package/dist/selftest/app.test.js +324 -0
  327. package/dist/selftest/channel.test.js +13 -0
  328. package/dist/selftest/cli.test.js +2 -1
  329. package/dist/selftest/config.test.js +59 -0
  330. package/dist/selftest/contained.test.d.ts +2 -0
  331. package/dist/selftest/contained.test.js +544 -0
  332. package/dist/selftest/credentials.test.js +1 -1
  333. package/dist/selftest/engine.test.d.ts +2 -0
  334. package/dist/selftest/engine.test.js +127 -0
  335. package/dist/selftest/hcs.test.d.ts +2 -0
  336. package/dist/selftest/hcs.test.js +482 -0
  337. package/dist/selftest/heavy-load.test.d.ts +2 -0
  338. package/dist/selftest/heavy-load.test.js +329 -0
  339. package/dist/selftest/index.js +12 -0
  340. package/dist/selftest/layout.test.js +12 -0
  341. package/dist/selftest/menu-perf.test.d.ts +2 -0
  342. package/dist/selftest/menu-perf.test.js +248 -0
  343. package/dist/selftest/menu-screens.js +4 -2
  344. package/dist/selftest/menu.test.js +36 -8
  345. package/dist/selftest/support/engine-cases.d.ts +8 -0
  346. package/dist/selftest/support/engine-cases.js +65 -0
  347. package/dist/selftest/support/engine-golden.d.ts +3 -0
  348. package/dist/selftest/support/engine-golden.js +66 -0
  349. package/dist/selftest/support/fixtures.d.ts +7 -1
  350. package/dist/selftest/support/hcs-probes.d.ts +17 -0
  351. package/dist/selftest/support/hcs-probes.js +41 -0
  352. package/dist/selftest/vpn.test.js +136 -3
  353. package/dist/selftest/web.test.js +101 -3
  354. package/dist/shared/channel/run-dir.d.ts +4 -1
  355. package/dist/shared/channel/run-dir.js +7 -1
  356. package/dist/shared/channel/schema.d.ts +35 -1
  357. package/dist/shared/channel/schema.js +27 -0
  358. package/dist/shared/channel/secrets.d.ts +1 -0
  359. package/dist/shared/channel/secrets.js +6 -0
  360. package/dist/shared/memory/index.d.ts +1 -0
  361. package/dist/shared/memory/index.js +1 -0
  362. package/dist/shared/memory/policy.d.ts +33 -0
  363. package/dist/shared/memory/policy.js +55 -0
  364. package/dist/shared/pty/output-filter.d.ts +14 -1
  365. package/dist/shared/pty/output-filter.js +22 -4
  366. package/dist/shared/pty/terminal.d.ts +4 -1
  367. package/dist/shared/pty/terminal.js +4 -2
  368. package/dist/shared/system.d.ts +1 -0
  369. package/dist/shared/system.js +1 -0
  370. package/dist/shared/vpn/download.d.ts +16 -0
  371. package/dist/shared/vpn/download.js +16 -0
  372. package/dist/shared/vpn/wireguard.d.ts +51 -0
  373. package/dist/shared/vpn/wireguard.js +227 -0
  374. package/dist/sync/sync-cycle.js +5 -5
  375. package/dist/sync/watcher.d.ts +13 -0
  376. package/dist/sync/watcher.js +92 -3
  377. package/dist/web/index.html +4 -3
  378. package/dist/web/main-NRRS5O6Z.js +157 -0
  379. package/dist/web/main-T5DMCHYV.css +1 -0
  380. package/native/csharp/HcsHost/AssemblyInfo.cs +14 -0
  381. package/native/csharp/HcsHost/Guard.cs +100 -0
  382. package/native/csharp/HcsHost/Hcs.cs +256 -0
  383. package/native/csharp/HcsHost/Json.cs +78 -0
  384. package/native/csharp/HcsHost/Program.cs +185 -0
  385. package/native/csharp/HcsHost/VirtualDisk.cs +95 -0
  386. package/native/csharp/HostTools/AssemblyInfo.cs +14 -0
  387. package/native/csharp/HostTools/MemoryStatus.cs +107 -0
  388. package/native/csharp/HostTools/Program.cs +58 -17
  389. package/native/scripts/check-contained.ps1 +28 -0
  390. package/native/scripts/contained-common.ps1 +241 -0
  391. package/native/scripts/dismount-contained.ps1 +66 -0
  392. package/native/scripts/memory-status.ps1 +34 -0
  393. package/native/scripts/mount-contained.ps1 +139 -0
  394. package/native/scripts/run-elevated.ps1 +17 -4
  395. package/native/scripts/stop-events.ps1 +23 -8
  396. package/package.json +9 -2
  397. package/sandbox/csharp/MemGov.cs +398 -0
  398. package/sandbox/csharp/PtyHost.cs +111 -5
  399. package/schemas/config.schema.json +60 -6
  400. package/schemas/sandbox-config.schema.json +3 -3
  401. package/dist/cli/commands/sessions/control.d.ts +0 -4
  402. package/dist/cli/commands/sessions/control.js +0 -66
  403. package/dist/cli/commands/sessions/list.d.ts +0 -2
  404. package/dist/cli/commands/sessions/list.js +0 -48
  405. package/dist/cli/commands/sessions/status.d.ts +0 -4
  406. package/dist/cli/commands/sessions/status.js +0 -114
  407. package/dist/cli/commands/sessions/window.d.ts +0 -3
  408. package/dist/cli/commands/sessions/window.js +0 -18
  409. package/dist/cli/menu/settings/path-kind.js +0 -44
  410. package/dist/web/main-CXESL347.js +0 -45
  411. package/dist/web/main-VLR7DVQ4.css +0 -1
  412. /package/dist/{cli/menu/settings → app/kernel}/schema-node.d.ts +0 -0
  413. /package/dist/{cli/menu/settings → app/kernel}/schema-node.js +0 -0
@@ -0,0 +1,329 @@
1
+ // Heavy load must slow builds down, not close the sandbox: memory sizing with the PC's commit, the agents' memory
2
+ // limit, the guest governor (thresholds, hysteresis, which programs), the host watchdog, the crash report and the C#
3
+ // helpers behind them.
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { spawnSync } from 'node:child_process';
7
+ import { DEFAULTS } from '../core/config/index.js';
8
+ import { isWin } from '../core/util/index.js';
9
+ import { SYSTEM } from '../shared/system.js';
10
+ import { GuestRequestSchema, PressureStatusSchema } from '../shared/channel/index.js';
11
+ import { GUEST_THRESHOLDS, HOST_THRESHOLDS, cargoJobs, effectiveCpuLimit, gentleCpuLimit, } from '../shared/memory/index.js';
12
+ import { agentMemoryLimitMb, decideMemory, memoryNote, resolveMemoryMb } from '../host/launch/index.js';
13
+ import { vgpuWarning, GENTLE_NOTE } from '../host/launch/risk-notes.js';
14
+ import { bugcheckCode, cpuPercentBetween, explainStop, findDumps, findingLines, freezeLine, hostPressure, lowReason, pageFileRisk, parseHostMemory, crashReportText, watchdogStep, WATCHDOG_START, } from '../host/life/index.js';
15
+ import { canLower, canPause, decide, GovernorCore, INITIAL_STATE, } from '../guest/governor/index.js';
16
+ const GB = 1024;
17
+ const MB_SANDBOX = DEFAULTS.sandbox;
18
+ const proc = (pid, name, mb, prio = 'normal') => ({
19
+ pid,
20
+ name,
21
+ mb,
22
+ prio,
23
+ });
24
+ const sample = (ramFreePercent, commitPercent, procs) => ({
25
+ ramTotalMb: 10000,
26
+ ramAvailMb: ramFreePercent * 100,
27
+ commitLimitMb: 10000,
28
+ commitAvailMb: (100 - commitPercent) * 100,
29
+ procs,
30
+ });
31
+ const pc = (over = {}) => ({
32
+ totalMb: 32768,
33
+ availableMb: 20000,
34
+ commitLimitMb: 49152,
35
+ commitAvailableMb: 40000,
36
+ pageFile: 'auto',
37
+ pageFileMaxMb: 0,
38
+ ...over,
39
+ });
40
+ export const heavyLoadSuite = {
41
+ name: 'heavy-load',
42
+ title: 'heavy load: memory sizing, agent memory limit, governor, watchdog, crash report',
43
+ run: async (t, f) => {
44
+ t.section('memory sizing looks at the commit as well as free RAM');
45
+ const base = decideMemory(MB_SANDBOX, 20 * GB, 32 * GB, null);
46
+ t.check(base.mb === 12 * GB, 'without a commit reading: free RAM minus the reserve', String(base.mb));
47
+ const tight = decideMemory(MB_SANDBOX, 20 * GB, 32 * GB, 14 * GB);
48
+ t.check(tight.mb === 6 * GB && tight.limitedBy === 'commit', 'a small commit lowers it (14 GB left - 8 GB reserve = 6 GB)', JSON.stringify(tight));
49
+ const roomy = decideMemory(MB_SANDBOX, 20 * GB, 32 * GB, 60 * GB);
50
+ t.check(roomy.mb === base.mb && roomy.limitedBy === 'free', 'plenty of commit changes nothing');
51
+ t.check(resolveMemoryMb(MB_SANDBOX, 20 * GB * 1048576, 32 * GB * 1048576, 14 * GB) === 6 * GB, 'resolveMemoryMb uses it');
52
+ t.check(memoryNote(tight)?.includes('6 GB of memory instead of 12 GB') === true, 'the launch note says plainly what happened');
53
+ t.check(memoryNote(base) === null && memoryNote(decideMemory(MB_SANDBOX, 20 * GB, 32 * GB, 19 * GB)) === null, 'no note when it hardly changed');
54
+ let refused = '';
55
+ try {
56
+ resolveMemoryMb(MB_SANDBOX, 20 * GB * 1048576, 32 * GB * 1048576, 10 * GB);
57
+ }
58
+ catch (e) {
59
+ refused = String(e instanceof Error ? e.message : e);
60
+ }
61
+ t.check(refused.includes('RAM plus paging file'), 'too little commit refuses with the real reason', refused);
62
+ t.check(resolveMemoryMb({ ...MB_SANDBOX, memoryMb: 5000 }, 1, 1, 1) === 5000, 'a fixed memoryMb is never changed');
63
+ t.section("the agents' memory limit");
64
+ t.check(agentMemoryLimitMb(32768, 'auto') === 32768 - 3276, 'auto: sandbox memory minus 10 %');
65
+ t.check(agentMemoryLimitMb(8192, 'auto') === 8192 - 2048, 'auto: at least 2 GB of headroom');
66
+ t.check(agentMemoryLimitMb(4096, 'auto') === 2048, 'a small sandbox keeps at least half for agents');
67
+ t.check(agentMemoryLimitMb(16384, 1000) === 15384 && agentMemoryLimitMb(16384, 'none') === null, 'a number, or none');
68
+ const gen = await f.launch({}, { args: ['--version'] });
69
+ const session = JSON.parse(fs.readFileSync(gen.sessionPath, 'utf8'));
70
+ t.check(session.agentMemoryLimitMb === agentMemoryLimitMb(gen.memoryMb, 'auto') &&
71
+ session.pressureResponse === true &&
72
+ session.loadProfile === 'normal', 'session.json carries the limit, the governor switch and the profile (all on by default)', JSON.stringify(session.agentMemoryLimitMb));
73
+ const vgpuConfig = f.makeConfig();
74
+ vgpuConfig.sandbox.vGpu = true;
75
+ const gentle = await f.launch({}, { args: ['--version'], config: vgpuConfig });
76
+ const gs = JSON.parse(fs.readFileSync(gentle.sessionPath, 'utf8'));
77
+ t.check(gs.loadProfile === 'gentle' && gs.cpuLimitPercent === 65, 'vGPU on: the gentle profile and a CPU cap 15 points lower (80 -> 65)', JSON.stringify([gs.loadProfile, gs.cpuLimitPercent]));
78
+ t.check(gentleCpuLimit(60) === 50 && gentleCpuLimit('none') === 85, 'the gentle cap never goes below 50 %');
79
+ t.check(effectiveCpuLimit('none', 'normal') === null && effectiveCpuLimit(80, 'normal') === 80, 'normal profile: unchanged');
80
+ t.check(vgpuWarning('your settings').includes('can freeze the whole PC') && GENTLE_NOTE.includes('gentler'), 'the vGPU texts');
81
+ t.section('cargo jobs fit the memory and the sessions');
82
+ t.check(cargoJobs(16, 32, 1) === 4, '16 CPUs, 32 GB: 4 jobs');
83
+ t.check(cargoJobs(16, 8, 1) === 2 && cargoJobs(16, 3, 1) === 1, 'about 4 GB per job');
84
+ t.check(cargoJobs(16, 32, 3) === 2 && cargoJobs(16, 32, 8) === 1, 'fewer when several sessions build');
85
+ t.section('the governor: which programs');
86
+ t.check(canPause('rustc.exe') && canPause('link.exe') && canPause('ld.lld.exe'), 'compilers and linkers may be paused');
87
+ t.check(!canPause('node.exe') && canLower('node.exe') && canLower('MSBuild.exe'), 'build tools are only slowed down');
88
+ t.check([
89
+ 'claude.exe',
90
+ 'codex.exe',
91
+ 'cmd.exe',
92
+ 'powershell.exe',
93
+ 'ptyhost.exe',
94
+ 'git.exe',
95
+ 'svchost.exe',
96
+ 'memgov.exe',
97
+ ].every((n) => !canLower(n) && !canPause(n)), 'agents, shells, ptyhost, git and system programs are never touched');
98
+ t.section('the governor: thresholds and hysteresis');
99
+ const normal = GUEST_THRESHOLDS.normal;
100
+ const procs = [
101
+ proc(1, 'rustc.exe', 2800),
102
+ proc(2, 'rustc.exe', 2000),
103
+ proc(3, 'claude.exe', 900),
104
+ proc(4, 'link.exe', 500),
105
+ ];
106
+ const calm = decide(INITIAL_STATE, sample(50, 50, procs), 1000, normal, 'normal');
107
+ t.check(calm.level === 'ok' && calm.actions.length === 0, '50 % free: nothing happens');
108
+ const edge = decide(INITIAL_STATE, sample(9, 91, procs), 1000, normal, 'normal');
109
+ t.check(edge.level === 'ok', '9 % free and 91 % commit are still fine (limits: 8 % and 92 %)');
110
+ const low = decide(INITIAL_STATE, sample(7, 50, procs), 1000, normal, 'normal');
111
+ t.check(low.level === 'throttled' &&
112
+ low.actions
113
+ .filter((a) => a.kind === 'priority')
114
+ .map((a) => a.kind === 'priority' && a.pid)
115
+ .join() === '1,2,4', '7 % free: the compilers go below normal, the agent does not');
116
+ const lowCommit = decide(INITIAL_STATE, sample(50, 93, procs), 1000, normal, 'normal');
117
+ t.check(lowCommit.level === 'throttled', 'commit above 92 % counts too');
118
+ let s2 = INITIAL_STATE;
119
+ const kinds = [];
120
+ for (let i = 0; i < 6; i++) {
121
+ const d = decide(s2, sample(5, 50, procs), i * 2000, normal, 'normal');
122
+ s2 = d.state;
123
+ kinds.push(d.level);
124
+ }
125
+ t.check(kinds[0] === 'throttled' && kinds.includes('suspending'), 'throttled first, paused later: ' + kinds.join());
126
+ const oneStep = decide(INITIAL_STATE, sample(5, 50, procs), 0, normal, 'normal');
127
+ t.check(!oneStep.actions.some((a) => a.kind === 'pause'), 'never paused on the first sample');
128
+ // Hysteresis: 10 % free is above the 8 % entry but below the 12 % exit: still under pressure.
129
+ let h = decide(INITIAL_STATE, sample(5, 50, procs), 0, normal, 'normal').state;
130
+ h = decide(h, sample(10, 50, procs), 2000, normal, 'normal').state;
131
+ t.check(h.pressure, 'between the entry and exit limits it stays under pressure (no flapping)');
132
+ for (let i = 0; i < normal.calmSamples; i++)
133
+ h = decide(h, sample(30, 50, procs), 4000 + i * 2000, normal, 'normal').state;
134
+ t.check(!h.pressure, 'ends only after ' + normal.calmSamples + ' calm samples');
135
+ const back = decide({ ...INITIAL_STATE, pressure: true, calm: normal.calmSamples - 1, lowered: { 1: 'below' } }, sample(30, 50, [proc(1, 'rustc.exe', 2800, 'below')]), 9000, normal, 'normal');
136
+ t.check(back.level === 'ok' &&
137
+ back.actions.length === 1 &&
138
+ back.actions[0].kind === 'priority' &&
139
+ back.actions[0].to === 'normal', 'when it ends the compilers get their normal priority back');
140
+ t.check(decide(INITIAL_STATE, sample(5, 50, [proc(1, 'rustc.exe', 100)]), 0, normal, 'normal').actions.length === 1 &&
141
+ !decide({ ...INITIAL_STATE, samples: 10 }, sample(5, 50, [proc(1, 'rustc.exe', 100)]), 99999, normal, 'normal').actions.some((a) => a.kind === 'pause'), 'a small compiler (under 300 MB) is never worth pausing');
142
+ const hostAsked = decide({ ...INITIAL_STATE, hostUntil: 5000 }, sample(60, 40, procs), 1000, normal, 'normal');
143
+ t.check(hostAsked.level === 'throttled', 'the PC asking for it counts as pressure while the request lasts');
144
+ t.section('the gentle profile (vGPU on)');
145
+ const gentleT = GUEST_THRESHOLDS.gentle;
146
+ t.check(gentleT.enterAvailablePercent === 15 && normal.enterAvailablePercent === 8, 'it acts at 15 % free instead of 8 %');
147
+ const g = decide(INITIAL_STATE, sample(50, 50, procs), 0, gentleT, 'gentle');
148
+ t.check(g.level === 'ok' &&
149
+ g.actions.length === 3 &&
150
+ g.actions.every((a) => a.kind === 'priority' && a.to === 'below' && a.pid !== 3), 'compilers start below normal even with plenty of memory (the agent does not)');
151
+ t.check(decide(INITIAL_STATE, sample(14, 50, procs), 0, gentleT, 'gentle').level === 'throttled', '14 % free is pressure');
152
+ t.section('the governor over a port (fake Windows)');
153
+ const calls = [];
154
+ const port = {
155
+ setPriority: (pid, to) => calls.push('prio ' + pid + ' ' + to),
156
+ pause: (pid, ms) => calls.push('pause ' + pid + ' ' + ms),
157
+ };
158
+ const logs = [];
159
+ const statuses = [];
160
+ let clock = 0;
161
+ const core = new GovernorCore({
162
+ port,
163
+ profile: 'normal',
164
+ now: () => clock,
165
+ logLine: (l) => logs.push(l),
166
+ saveStatus: (s) => statuses.push(s),
167
+ });
168
+ for (let i = 0; i < 6; i++) {
169
+ clock = i * 2000;
170
+ core.onSample(sample(4, 60, procs));
171
+ }
172
+ t.check(calls.includes('prio 1 below') && calls.includes('pause 1 5000') && !calls.some((c) => c.includes(' 3 ')), 'priority first, then a pause of the biggest; the agent untouched', calls.join('; '));
173
+ t.check(logs.some((l) => l.includes('memory is low')) && logs.some((l) => l.includes('paused rustc')), 'what it did goes to the memory log');
174
+ t.check(statuses.length > 0 && PressureStatusSchema.safeParse(statuses[statuses.length - 1]).success, 'its status file matches the schema the host reads');
175
+ core.hostPressure(60, 'test');
176
+ t.check(core.current.hostUntil === clock + 60000, 'a host request is remembered for its seconds');
177
+ t.section("the PC's watchdog");
178
+ const input = (memory, nowMs, cpu = 10, profile = 'normal') => ({
179
+ memory,
180
+ cpuPercent: cpu,
181
+ intervalSeconds: 10,
182
+ nowMs,
183
+ reserveHostMb: 8192,
184
+ profile,
185
+ });
186
+ t.check(watchdogStep(WATCHDOG_START, input(pc(), 0)).state.low === false, 'plenty of memory: quiet');
187
+ t.check(lowReason(pc({ availableMb: 3000 }), 8192, HOST_THRESHOLDS.normal, 1) !== '', 'under 4 GB of RAM: low');
188
+ t.check(lowReason(pc({ availableMb: 5000 }), 8192, HOST_THRESHOLDS.normal, 1) === '', '5 GB free on a 32 GB PC is fine (limit max(4 GB, 12 % = 3.9 GB))');
189
+ t.check(lowReason(pc({ totalMb: 65536, availableMb: 7000 }), 8192, HOST_THRESHOLDS.normal, 1) !== '', '12 % of 64 GB = 7.7 GB: 7 GB is low');
190
+ t.check(lowReason(pc({ commitAvailableMb: 6000 }), 8192, HOST_THRESHOLDS.normal, 1) !== '', 'commit under 15 % of the limit: low');
191
+ t.check(lowReason(pc({ availableMb: 5000 }), 8192, HOST_THRESHOLDS.gentle, 1) !== '', 'the gentle profile acts at 6 GB');
192
+ const first = watchdogStep(WATCHDOG_START, input(pc({ availableMb: 2000 }), 100000));
193
+ t.check(first.send && first.changed && first.state.low, 'low: asks the sandbox at once');
194
+ const second = watchdogStep(first.state, input(pc({ availableMb: 2000 }), 110000));
195
+ t.check(!second.send, 'and not again within 30 s');
196
+ t.check(watchdogStep(second.state, input(pc({ availableMb: 2000 }), 131000)).send, 'but repeats every 30 s while it lasts');
197
+ let w = first.state;
198
+ w = watchdogStep(w, input(pc({ availableMb: 4500 }), 140000)).state;
199
+ t.check(w.low, 'just above the limit is not recovered yet (needs 1.25 times)');
200
+ for (let i = 0; i < 3; i++)
201
+ w = watchdogStep(w, input(pc({ availableMb: 12000 }), 150000 + i * 10000)).state;
202
+ t.check(!w.low, 'recovered after 3 good samples');
203
+ let cpu = WATCHDOG_START;
204
+ let sent = false;
205
+ for (let i = 0; i < 7; i++) {
206
+ const s = watchdogStep(cpu, input(pc(), i * 10000, 97));
207
+ cpu = s.state;
208
+ sent = sent || s.send;
209
+ }
210
+ t.check(sent && cpu.low, 'CPU above 95 % for 60 s: asks the sandbox to slow down');
211
+ t.check(!watchdogStep(WATCHDOG_START, input(pc(), 0, 97)).state.low, 'a short CPU peak is nothing');
212
+ t.check(cpuPercentBetween([{ times: { user: 0, nice: 0, sys: 0, idle: 0, irq: 0 } }], [{ times: { user: 90, nice: 0, sys: 0, idle: 10, irq: 0 } }]) === 90, 'CPU use from two readings');
213
+ t.check(GuestRequestSchema.safeParse({ kind: 'pressure', id: 'p1', reason: 'low', seconds: 90, createdAt: 'now' })
214
+ .success &&
215
+ !GuestRequestSchema.safeParse({ kind: 'pressure', id: 'p1', reason: 'x', seconds: 99999, createdAt: 'now' })
216
+ .success &&
217
+ !GuestRequestSchema.safeParse({ kind: 'pressure', id: '../x', reason: 'x', seconds: 30, createdAt: 'now' })
218
+ .success &&
219
+ !GuestRequestSchema.safeParse({
220
+ kind: 'pressure',
221
+ id: 'p1',
222
+ reason: 'x',
223
+ seconds: 30,
224
+ createdAt: 'now',
225
+ extra: 1,
226
+ }).success, 'the pressure request is validated (id, seconds, no extra fields)');
227
+ t.check(hostPressure(pc({ commitAvailableMb: 3000 }), 8192).low && !hostPressure(pc(), 8192).low, 'hostPressure (launch-time helper)');
228
+ t.section('host memory reading and the page file warning');
229
+ t.check(parseHostMemory('{"totalMb":32766,"availableMb":23596,"commitLimitMb":49150,"commitAvailableMb":38910,"pageFile":"fixed","pageFileMaxMb":16384}')?.pageFile === 'fixed' &&
230
+ parseHostMemory('not json') === null &&
231
+ parseHostMemory('{"totalMb":0}') === null &&
232
+ parseHostMemory('{"totalMb":1,"availableMb":1,"commitLimitMb":1,"commitAvailableMb":1}')?.pageFile === 'auto', 'memory-status output is parsed and checked');
233
+ t.check(pageFileRisk(pc(), 20000) === null, 'Windows manages the page file: no warning');
234
+ const risk = pageFileRisk(pc({ pageFile: 'fixed', commitLimitMb: 40000, commitAvailableMb: 10000 }), 20000);
235
+ t.check(risk !== null &&
236
+ risk.text.includes('closes the sandbox instead of slowing it down') &&
237
+ risk.text.includes('Automatically manage paging file size') &&
238
+ risk.neededGb >= 1, 'a fixed small page file: warns in plain words and names the size', JSON.stringify(risk));
239
+ t.check(pageFileRisk(pc({ pageFile: 'none', commitLimitMb: 32768, commitAvailableMb: 30000 }), 31000) !== null, 'no page file at all warns too');
240
+ t.check(pageFileRisk(pc({ pageFile: 'fixed', commitLimitMb: 90000, commitAvailableMb: 80000 }), 20000) === null, 'a fixed but large one is fine');
241
+ t.section('the crash report');
242
+ const ev = (id, provider, at, process = '') => ({ id, provider, at, process });
243
+ t.check(bugcheckCode('BugcheckCode 209') === '0xD1' && bugcheckCode('BugcheckCode 0') === null, 'Kernel-Power 41 stop code');
244
+ const cause = explainStop([ev(41, 'Microsoft-Windows-Kernel-Power', '2026-10-15T20:53:47Z', 'BugcheckCode 0')]);
245
+ t.check(cause?.kind === 'crash' && cause.text.includes('freeze'), 'no stop code: a freeze, crash or power cut');
246
+ t.check(explainStop([
247
+ ev(41, 'Microsoft-Windows-Kernel-Power', '2026-10-15T20:53:47Z', 'BugcheckCode 209'),
248
+ ])?.text.includes('0xD1') === true, 'with a stop code: a blue screen');
249
+ t.check(freezeLine(cause, '2026-10-15T19:40:57Z')?.includes('73 minutes later') === true &&
250
+ freezeLine(cause, '2026-10-15T20:53:00Z') === null, 'a long gap says the PC stopped responding; a short one says nothing');
251
+ const events = [
252
+ ev(2004, 'Microsoft-Windows-Resource-Exhaustion-Detector', '2026-10-15T19:41:00Z', 'low virtual memory'),
253
+ ev(41, 'Microsoft-Windows-Kernel-Power', '2026-10-15T20:53:47Z', 'BugcheckCode 0'),
254
+ ev(19, 'Microsoft-Windows-WHEA-Logger', '2026-10-15T19:41:10Z', 'corrected hardware error'),
255
+ ev(1000, 'Application Error', '2026-10-15T19:41:12Z', 'vmwp.exe crashed'),
256
+ ];
257
+ const meaning = findingLines(events).join('\n');
258
+ t.check(meaning.includes('memory ran out') &&
259
+ meaning.includes('froze, lost power') &&
260
+ meaning.includes('hardware error') &&
261
+ meaning.includes('vmwp.exe'), 'what each finding usually means, in plain words', meaning);
262
+ const dumps = path.join(t.at('crash-dumps'), 'Minidump');
263
+ fs.mkdirSync(dumps, { recursive: true });
264
+ fs.writeFileSync(path.join(dumps, '101526-1.dmp'), 'x');
265
+ t.check(findDumps([dumps], new Date(Date.now() - 3600000)).length === 1 &&
266
+ findDumps([dumps], new Date(Date.now() + 3600000)).length === 0 &&
267
+ findDumps([path.join(dumps, 'none')], new Date(0)).length === 0, 'dumps: names and times only, newer than the start, a missing folder is fine');
268
+ const report = crashReportText(cause, [...events, events[0]], 'time | RAM\n19:40:45 | 9400/27600', '2026-10-15T19:40:57Z', {
269
+ hostMemoryLog: '2026-10-15T19:40:50Z | RAM free/total MB 900/32768',
270
+ dumps: [{ name: 'C:\\Windows\\Minidump\\a.dmp', at: '2026-10-15T20:54:00Z' }],
271
+ vgpu: true,
272
+ });
273
+ t.check(report.includes('stopped responding') &&
274
+ report.includes('What that usually means') &&
275
+ report.includes('RAM free/total MB 900/32768') &&
276
+ report.includes('a.dmp') &&
277
+ report.includes('vGPU was on') &&
278
+ report.split('Resource-Exhaustion-Detector 2004').length === 3, "the report has the freeze, the meanings, this PC's memory, dumps and vGPU; a repeated event is shown once", report);
279
+ t.section('the C# helpers compile (C# 5, the csc that ships with Windows)');
280
+ if (!isWin || !fs.existsSync(SYSTEM.csc())) {
281
+ t.check(true, 'skipped: no Windows csc on this machine');
282
+ return;
283
+ }
284
+ const out = t.at('heavy-csc');
285
+ fs.mkdirSync(out, { recursive: true });
286
+ const build = (name, files, target = 'exe') => {
287
+ const exe = path.join(out, name + '.exe');
288
+ const r = spawnSync(SYSTEM.csc(), ['/nologo', '/target:' + target, '/out:' + exe, ...files], {
289
+ encoding: 'utf8',
290
+ windowsHide: true,
291
+ });
292
+ t.check(r.status === 0, name + ' compiles', r.stdout);
293
+ return exe;
294
+ };
295
+ const sandboxCs = (n) => path.join(t.packageRoot, 'sandbox', 'csharp', n);
296
+ build('ptyhost', [sandboxCs('PtyHost.cs')]);
297
+ const memgov = build('memgov', [sandboxCs('MemGov.cs')]);
298
+ const hostDir = path.join(t.packageRoot, 'native', 'csharp', 'HostTools');
299
+ const tools = build('HostTools', fs
300
+ .readdirSync(hostDir)
301
+ .filter((n) => n.endsWith('.cs'))
302
+ .map((n) => path.join(hostDir, n)));
303
+ const status = spawnSync(tools, ['memory-status'], { encoding: 'utf8', windowsHide: true });
304
+ const parsed = parseHostMemory(status.stdout);
305
+ t.check(parsed !== null && parsed.commitLimitMb >= parsed.totalMb, 'HostTools memory-status answers with valid JSON', status.stdout);
306
+ const usage = spawnSync(memgov, [], { encoding: 'utf8', windowsHide: true });
307
+ t.check(usage.status === 2, 'memgov without a command is a usage error (it starts nothing)');
308
+ const served = spawnSync(memgov, ['serve', '--interval', '1'], {
309
+ encoding: 'utf8',
310
+ windowsHide: true,
311
+ input: '',
312
+ timeout: 15000,
313
+ });
314
+ const firstLine = (served.stdout ?? '').split(/\r?\n/)[0] ?? '';
315
+ let sampleOk = false;
316
+ try {
317
+ const parsedSample = JSON.parse(firstLine);
318
+ sampleOk = Array.isArray(parsedSample.procs) && parsedSample.procs.length === 0 && parsedSample.ramTotalMb > 0;
319
+ }
320
+ catch {
321
+ // Not JSON: the check below fails.
322
+ }
323
+ t.check(sampleOk && served.status === 0, 'memgov serve prints a sample (no job yet: no processes) and ends when its input closes', firstLine);
324
+ for (const script of ['memory-status.ps1', 'stop-events.ps1']) {
325
+ const text = fs.readFileSync(path.join(t.packageRoot, 'native', 'scripts', script), 'utf8');
326
+ t.check(text.startsWith('#Requires -Version 5.1'), script + ' says its PowerShell version');
327
+ }
328
+ },
329
+ };
@@ -15,6 +15,7 @@ import { credentialsSuite } from './credentials.test.js';
15
15
  import { vpnSuite } from './vpn.test.js';
16
16
  import { agentCommandsSuite } from './agent-commands.test.js';
17
17
  import { channelSuite } from './channel.test.js';
18
+ import { heavyLoadSuite } from './heavy-load.test.js';
18
19
  import { cliSuite } from './cli.test.js';
19
20
  import { agentPathsSuite } from './agent-paths.test.js';
20
21
  import { cmdlineSuite } from './cmdline.test.js';
@@ -29,6 +30,9 @@ import { sharingSuite } from './sharing.test.js';
29
30
  import { dataSuite } from './data.test.js';
30
31
  import { detectSuite } from './detect.test.js';
31
32
  import { generateSuite } from './generate.test.js';
33
+ import { engineSuite } from './engine.test.js';
34
+ import { containedSuite } from './contained.test.js';
35
+ import { hcsSuite } from './hcs.test.js';
32
36
  import { gitAccessSuite } from './git-access.test.js';
33
37
  import { guestBootSuite } from './guest-boot.test.js';
34
38
  import { hostileInputSuite } from './hostile-input.test.js';
@@ -55,9 +59,11 @@ import { workspaceSuite } from './workspace.test.js';
55
59
  import { workspaceViewSuite } from './workspace-view.test.js';
56
60
  import { liveNetworkSuite } from './live-network.test.js';
57
61
  import { liveTerminalSuite } from './live-terminal.test.js';
62
+ import { appSuite } from './app.test.js';
58
63
  import { auditSuite } from './audit.test.js';
59
64
  import { layoutSuite } from './layout.test.js';
60
65
  import { menuSuite } from './menu.test.js';
66
+ import { menuPerfSuite } from './menu-perf.test.js';
61
67
  import { resumeSuite } from './resume.test.js';
62
68
  /** Every suite, in the order they run. The live ones come last: they are the slowest and need Windows. */
63
69
  export const SUITES = [
@@ -74,6 +80,9 @@ export const SUITES = [
74
80
  localConfigSuite,
75
81
  // the generated sandbox and the guest that boots it
76
82
  generateSuite,
83
+ engineSuite,
84
+ containedSuite,
85
+ hcsSuite,
77
86
  guestBootSuite,
78
87
  mirrorSuite,
79
88
  projectsSuite,
@@ -88,6 +97,7 @@ export const SUITES = [
88
97
  // an untrusted sandbox: what the host refuses to do with what it finds
89
98
  linksSuite,
90
99
  channelSuite,
100
+ heavyLoadSuite,
91
101
  gitAccessSuite,
92
102
  repoGuardSuite,
93
103
  secretsSuite,
@@ -106,8 +116,10 @@ export const SUITES = [
106
116
  dataSuite,
107
117
  repairSuite,
108
118
  healthSuite,
119
+ appSuite,
109
120
  cliSuite,
110
121
  menuSuite,
122
+ menuPerfSuite,
111
123
  agentCommandsSuite,
112
124
  // every command as its own process
113
125
  hostSimSuite,
@@ -129,5 +129,17 @@ export const layoutSuite = {
129
129
  .filter((d) => d.startsWith('guest/entries/'))
130
130
  .map((d) => f + ' -> ' + d));
131
131
  t.check(!intoEntries.length, 'nothing imports an entry point (guest/entries)', list(intoEntries));
132
+ t.section('the shared core');
133
+ const pure = (f) => f.startsWith('app/kernel/') || /^app\/features\/(.+\/)?[^/]+\.def\.js$/.test(f) || f === 'app/features/defs.js';
134
+ const pureReach = new Set(files.filter(pure).flatMap((f) => [...closure(modules, f)]));
135
+ const strays = [...pureReach].filter((f) => !pure(f) && f !== 'core/util/errors.js');
136
+ const packages = [...pureReach].flatMap((f) => modules.get(f)?.bare ?? []).filter((b) => b !== 'zod');
137
+ t.check(files.some((f) => f === 'app/features/defs.js') && !strays.length && !packages.length, 'the kernel and the *.def files (what the web bundle imports) reach only each other, core/util/errors and zod', list([...strays, ...packages]));
138
+ const intoApp = files
139
+ .filter((f) => !['app', 'cli', 'selftest', 'bin'].includes(area(f)) && f !== 'api.js')
140
+ .flatMap((f) => [...modules.get(f).statics, ...modules.get(f).dynamics]
141
+ .filter((d) => area(d) === 'app' && !(area(f) === 'host' && d.startsWith('app/kernel/')))
142
+ .map((d) => f + ' -> ' + d));
143
+ t.check(!intoApp.length, 'below the CLI only host code uses the shared core, and only its kernel', list(intoApp));
132
144
  },
133
145
  };
@@ -0,0 +1,2 @@
1
+ import type { Suite } from './support/suite.js';
2
+ export declare const menuPerfSuite: Suite;