talos-code 0.0.1 → 0.1.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 (401) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +111 -3
  3. package/THIRD_PARTY_NOTICES.md +40 -0
  4. package/dist/archive/zip.js +73 -0
  5. package/dist/args.js +97 -0
  6. package/dist/automations/history-store.js +34 -0
  7. package/dist/automations/policy-store.js +43 -0
  8. package/dist/automations/runner.js +107 -0
  9. package/dist/automations/schedule.js +85 -0
  10. package/dist/automations/windows-task.js +53 -0
  11. package/dist/commands/advanced-cli.js +233 -0
  12. package/dist/commands/checkpoint-cli.js +45 -0
  13. package/dist/commands/config-cli.js +107 -0
  14. package/dist/commands/context.js +17 -0
  15. package/dist/commands/extensions-cli.js +207 -0
  16. package/dist/commands/project-cli.js +74 -0
  17. package/dist/commands/project-commands.js +143 -0
  18. package/dist/commands/provider-cli.js +185 -0
  19. package/dist/commands/services-cli.js +248 -0
  20. package/dist/commands/session-cli.js +171 -0
  21. package/dist/commands/system-cli.js +405 -0
  22. package/dist/config/commands.js +60 -0
  23. package/dist/config/load.js +382 -0
  24. package/dist/config/migrations.js +48 -0
  25. package/dist/config/types.js +11 -0
  26. package/dist/diagnostics/development-log.js +154 -0
  27. package/dist/diagnostics/doctor.js +104 -0
  28. package/dist/diagnostics/redact.js +80 -0
  29. package/dist/diagnostics/zip.js +52 -0
  30. package/dist/errors.js +156 -0
  31. package/dist/events/bridge.js +130 -0
  32. package/dist/extensions/installer.js +178 -0
  33. package/dist/extensions/package-schema.js +24 -0
  34. package/dist/headless/result.js +84 -0
  35. package/dist/headless/run.js +230 -0
  36. package/dist/i18n/en/approval.js +43 -0
  37. package/dist/i18n/en/common.js +9 -0
  38. package/dist/i18n/en/credentials.js +82 -0
  39. package/dist/i18n/en/errors.js +246 -0
  40. package/dist/i18n/en/firstrun.js +89 -0
  41. package/dist/i18n/en/providers.js +37 -0
  42. package/dist/i18n/en/screen.js +736 -0
  43. package/dist/i18n/en/tools.js +127 -0
  44. package/dist/i18n/en.js +14 -0
  45. package/dist/i18n/error-view.js +307 -0
  46. package/dist/i18n/index.js +19 -0
  47. package/dist/i18n/kernel-map.js +139 -0
  48. package/dist/io.js +45 -0
  49. package/dist/main.js +330 -0
  50. package/dist/paths.js +41 -0
  51. package/dist/protocol/v2/codec.js +9 -0
  52. package/dist/protocol/v2/events.js +555 -0
  53. package/dist/protocol/v2/index.js +4 -0
  54. package/dist/protocol/v2/replay.js +28 -0
  55. package/dist/protocol/v2/types.js +1 -0
  56. package/dist/provider/control-plane.js +135 -0
  57. package/dist/provider/environment-keys.js +275 -0
  58. package/dist/provider/health.js +110 -0
  59. package/dist/provider/missing-key.js +48 -0
  60. package/dist/provider/model-catalog.js +168 -0
  61. package/dist/provider/provider-text.js +13 -0
  62. package/dist/provider/store.js +95 -0
  63. package/dist/provider/system-keyring.js +214 -0
  64. package/dist/runtime/active-run.js +63 -0
  65. package/dist/runtime/agent-tree.js +74 -0
  66. package/dist/runtime/attachments.js +84 -0
  67. package/dist/runtime/brokered-executor.js +395 -0
  68. package/dist/runtime/context-status.js +76 -0
  69. package/dist/runtime/create-runtime.js +111 -0
  70. package/dist/runtime/model-profile.js +361 -0
  71. package/dist/runtime/output-store.js +137 -0
  72. package/dist/runtime/provider-attempts.js +185 -0
  73. package/dist/runtime/replay-buffer.js +153 -0
  74. package/dist/runtime/repo.js +95 -0
  75. package/dist/runtime/session-facade.js +135 -0
  76. package/dist/runtime/session-summary.js +125 -0
  77. package/dist/runtime/supervisor.js +262 -0
  78. package/dist/runtime/talos-composition.js +1006 -0
  79. package/dist/runtime/types.js +5 -0
  80. package/dist/runtime/usage-snapshot.js +82 -0
  81. package/dist/security/auto-classifier.js +38 -0
  82. package/dist/security/credential-free-environment.js +54 -0
  83. package/dist/security/evaluate.js +243 -0
  84. package/dist/security/execution-backends.js +236 -0
  85. package/dist/security/execution-broker.js +102 -0
  86. package/dist/security/forge-scan.js +74 -0
  87. package/dist/security/from-approval.js +39 -0
  88. package/dist/security/mxc-execution-backend.js +281 -0
  89. package/dist/security/permission-engine.js +138 -0
  90. package/dist/security/permission-explanation.js +54 -0
  91. package/dist/security/persist.js +179 -0
  92. package/dist/security/plugin-guard.js +230 -0
  93. package/dist/security/process-tree-evidence-store.js +74 -0
  94. package/dist/security/process-tree-probe.js +554 -0
  95. package/dist/security/project-resource-inventory.js +186 -0
  96. package/dist/security/project-trust-gate.js +38 -0
  97. package/dist/security/project-trust.js +367 -0
  98. package/dist/security/rule-parser.js +201 -0
  99. package/dist/security/shell-segmentation.js +68 -0
  100. package/dist/security/trust-authority.js +324 -0
  101. package/dist/security/types.js +1 -0
  102. package/dist/security/workspace-identity.js +102 -0
  103. package/dist/services/automation-facade.js +59 -0
  104. package/dist/services/forge-facade.js +77 -0
  105. package/dist/services/hook-facade.js +240 -0
  106. package/dist/services/index.js +16 -0
  107. package/dist/services/library-facade.js +174 -0
  108. package/dist/services/mcp-facade.js +348 -0
  109. package/dist/services/memory-facade.js +126 -0
  110. package/dist/services/notes-facade.js +157 -0
  111. package/dist/services/plugin-facade.js +308 -0
  112. package/dist/services/research-facade.js +110 -0
  113. package/dist/services/task-board-facade.js +236 -0
  114. package/dist/services/workflow-catalog.js +246 -0
  115. package/dist/sessions/export-format.js +98 -0
  116. package/dist/sessions/metadata-store.js +160 -0
  117. package/dist/sessions/share.js +122 -0
  118. package/dist/sessions/transfer.js +16 -0
  119. package/dist/subcommands.js +62 -0
  120. package/dist/tui/agent-roster.js +36 -0
  121. package/dist/tui/app.js +3761 -0
  122. package/dist/tui/approval.js +36 -0
  123. package/dist/tui/boot/boot-sequence.js +76 -0
  124. package/dist/tui/boot/cinematic.js +243 -0
  125. package/dist/tui/boot/desktop-logo.js +82 -0
  126. package/dist/tui/boot.js +3 -0
  127. package/dist/tui/busy-input.js +58 -0
  128. package/dist/tui/catalog-service.js +559 -0
  129. package/dist/tui/components/assistant-stream.js +1 -0
  130. package/dist/tui/components/command-menu.js +68 -0
  131. package/dist/tui/components/composer.js +219 -0
  132. package/dist/tui/components/diff.js +35 -0
  133. package/dist/tui/components/footer.js +48 -0
  134. package/dist/tui/components/header.js +6 -0
  135. package/dist/tui/components/markdown.js +305 -0
  136. package/dist/tui/components/status-indicator.js +32 -0
  137. package/dist/tui/components/terminal-shell.js +205 -0
  138. package/dist/tui/components/thinking-row.js +19 -0
  139. package/dist/tui/components/tool-row.js +97 -0
  140. package/dist/tui/components/transcript-virtualizer.js +165 -0
  141. package/dist/tui/components/transcript.js +43 -0
  142. package/dist/tui/diff-model.js +77 -0
  143. package/dist/tui/editor-history.js +21 -0
  144. package/dist/tui/editor.js +210 -0
  145. package/dist/tui/event-adapter.js +436 -0
  146. package/dist/tui/exit-output.js +58 -0
  147. package/dist/tui/external-editor.js +53 -0
  148. package/dist/tui/file-completion.js +89 -0
  149. package/dist/tui/focus-manager.js +5 -0
  150. package/dist/tui/highlight.js +30 -0
  151. package/dist/tui/input-router.js +18 -0
  152. package/dist/tui/interrupt.js +99 -0
  153. package/dist/tui/keybindings.js +194 -0
  154. package/dist/tui/keymap-resolver.js +91 -0
  155. package/dist/tui/launch-state.js +139 -0
  156. package/dist/tui/line-diff.js +57 -0
  157. package/dist/tui/live-activity.js +45 -0
  158. package/dist/tui/metrics.js +123 -0
  159. package/dist/tui/onboarding.js +36 -0
  160. package/dist/tui/overlays/agent-tree.js +39 -0
  161. package/dist/tui/overlays/approval-dialog.js +640 -0
  162. package/dist/tui/overlays/automation-center.js +51 -0
  163. package/dist/tui/overlays/checkpoint-picker.js +47 -0
  164. package/dist/tui/overlays/context-inspector.js +36 -0
  165. package/dist/tui/overlays/effort-line.js +110 -0
  166. package/dist/tui/overlays/forge-center.js +46 -0
  167. package/dist/tui/overlays/help-dialog.js +16 -0
  168. package/dist/tui/overlays/history-picker.js +37 -0
  169. package/dist/tui/overlays/hook-center.js +70 -0
  170. package/dist/tui/overlays/library-center.js +55 -0
  171. package/dist/tui/overlays/mcp-center.js +60 -0
  172. package/dist/tui/overlays/memory-center.js +63 -0
  173. package/dist/tui/overlays/model-picker.js +72 -0
  174. package/dist/tui/overlays/notes-center.js +53 -0
  175. package/dist/tui/overlays/overlay-host.js +8 -0
  176. package/dist/tui/overlays/plugin-center.js +76 -0
  177. package/dist/tui/overlays/provider-picker.js +145 -0
  178. package/dist/tui/overlays/queue-editor.js +32 -0
  179. package/dist/tui/overlays/research-center.js +59 -0
  180. package/dist/tui/overlays/scroll-window.js +234 -0
  181. package/dist/tui/overlays/session-picker.js +115 -0
  182. package/dist/tui/overlays/tasks-center.js +83 -0
  183. package/dist/tui/overlays/theme-picker.js +21 -0
  184. package/dist/tui/overlays/transcript-search.js +58 -0
  185. package/dist/tui/overlays/trust-center.js +29 -0
  186. package/dist/tui/overlays/workflow-center.js +46 -0
  187. package/dist/tui/project-file-index.js +214 -0
  188. package/dist/tui/project-references.js +85 -0
  189. package/dist/tui/project-trust-prompt.js +287 -0
  190. package/dist/tui/prompt-history-store.js +116 -0
  191. package/dist/tui/queue-store.js +110 -0
  192. package/dist/tui/regions/budget.js +59 -0
  193. package/dist/tui/regions/views.js +96 -0
  194. package/dist/tui/render-coordinator.js +148 -0
  195. package/dist/tui/render-scheduler.js +4 -0
  196. package/dist/tui/run.js +69 -0
  197. package/dist/tui/selection-list.js +29 -0
  198. package/dist/tui/session-controller.js +778 -0
  199. package/dist/tui/session-export.js +54 -0
  200. package/dist/tui/shell-input.js +35 -0
  201. package/dist/tui/shell-layout.js +48 -0
  202. package/dist/tui/shell-model.js +98 -0
  203. package/dist/tui/slash-commands.js +80 -0
  204. package/dist/tui/state.js +151 -0
  205. package/dist/tui/status-bar.js +125 -0
  206. package/dist/tui/status-view.js +40 -0
  207. package/dist/tui/terminal-capabilities.js +9 -0
  208. package/dist/tui/terminal-session.js +11 -0
  209. package/dist/tui/text-width.js +66 -0
  210. package/dist/tui/theme-catalog.js +25 -0
  211. package/dist/tui/theme-store.js +23 -0
  212. package/dist/tui/theme.js +23 -0
  213. package/dist/tui/tool-display.js +135 -0
  214. package/dist/tui/tool-facts.js +1 -0
  215. package/dist/tui/tools/bash-renderer.js +32 -0
  216. package/dist/tui/tools/change.js +61 -0
  217. package/dist/tui/tools/edit-renderer.js +17 -0
  218. package/dist/tui/tools/generic-renderer.js +13 -0
  219. package/dist/tui/tools/list-renderer.js +14 -0
  220. package/dist/tui/tools/read-renderer.js +13 -0
  221. package/dist/tui/tools/registry.js +20 -0
  222. package/dist/tui/tools/row-format.js +187 -0
  223. package/dist/tui/tools/search-renderer.js +38 -0
  224. package/dist/tui/tools/shared.js +97 -0
  225. package/dist/tui/tools/write-renderer.js +15 -0
  226. package/dist/tui/transcript-model.js +441 -0
  227. package/dist/tui/ui-preferences.js +79 -0
  228. package/dist/tui/usage-view.js +77 -0
  229. package/dist/tui/vim-mode.js +99 -0
  230. package/dist/update/check.js +15 -0
  231. package/dist/update/npm.js +51 -0
  232. package/dist/update/run.js +129 -0
  233. package/dist/version.js +2 -0
  234. package/dist/workspace/checkpoint-store.js +210 -0
  235. package/dist/workspace/checkpoint.js +413 -0
  236. package/dist/workspace/restore.js +232 -0
  237. package/package.json +63 -5
  238. package/vendor/context-engine/package.json +11 -0
  239. package/vendor/context-engine/src/compaction-planner.mjs +57 -0
  240. package/vendor/context-engine/src/contracts.mjs +48 -0
  241. package/vendor/context-engine/src/engine.mjs +445 -0
  242. package/vendor/context-engine/src/node/context-export.mjs +164 -0
  243. package/vendor/context-engine/src/node/legacy-import.mjs +92 -0
  244. package/vendor/context-engine/src/node/migrations/001-context.sql +126 -0
  245. package/vendor/context-engine/src/node/sqlite-store.mjs +85 -0
  246. package/vendor/context-engine/src/node/sqlite-worker.mjs +559 -0
  247. package/vendor/context-engine/src/profiles.mjs +10 -0
  248. package/vendor/context-engine/src/retrieval.mjs +104 -0
  249. package/vendor/context-engine/src/summary.mjs +97 -0
  250. package/vendor/context-engine/src/usage.mjs +34 -0
  251. package/vendor/harness-ui/package.json +38 -0
  252. package/vendor/harness-ui/src/acp-agent.mjs +350 -0
  253. package/vendor/harness-ui/src/agent-service.mjs +2188 -0
  254. package/vendor/harness-ui/src/agui-events.mjs +452 -0
  255. package/vendor/harness-ui/src/ambiente-solo-server.mjs +121 -0
  256. package/vendor/harness-ui/src/artifact-store.mjs +39 -0
  257. package/vendor/harness-ui/src/assistenza.mjs +123 -0
  258. package/vendor/harness-ui/src/automation-scheduler.mjs +69 -0
  259. package/vendor/harness-ui/src/automation-store.mjs +145 -0
  260. package/vendor/harness-ui/src/browser-annota.mjs +639 -0
  261. package/vendor/harness-ui/src/browser-frame.mjs +211 -0
  262. package/vendor/harness-ui/src/browser-proxy-universale.mjs +519 -0
  263. package/vendor/harness-ui/src/browser-proxy.mjs +87 -0
  264. package/vendor/harness-ui/src/browser-sessione-viva.mjs +329 -0
  265. package/vendor/harness-ui/src/browser-stream.mjs +445 -0
  266. package/vendor/harness-ui/src/browser-vivo.mjs +694 -0
  267. package/vendor/harness-ui/src/chat-image-attachments.mjs +72 -0
  268. package/vendor/harness-ui/src/config.mjs +697 -0
  269. package/vendor/harness-ui/src/contesto-del-progetto.mjs +385 -0
  270. package/vendor/harness-ui/src/context-asset-adapter.mjs +72 -0
  271. package/vendor/harness-ui/src/context-desktop-service.mjs +253 -0
  272. package/vendor/harness-ui/src/context-embedding-runtime.mjs +252 -0
  273. package/vendor/harness-ui/src/context-inference-scheduler.mjs +81 -0
  274. package/vendor/harness-ui/src/context-native-compaction.mjs +75 -0
  275. package/vendor/harness-ui/src/context-provider-adapter.mjs +141 -0
  276. package/vendor/harness-ui/src/context-runtime.mjs +118 -0
  277. package/vendor/harness-ui/src/context-token-counters.mjs +184 -0
  278. package/vendor/harness-ui/src/context-tool-catalog.mjs +86 -0
  279. package/vendor/harness-ui/src/context-tool-output.mjs +72 -0
  280. package/vendor/harness-ui/src/costo-elenco.mjs +252 -0
  281. package/vendor/harness-ui/src/custom-task.mjs +171 -0
  282. package/vendor/harness-ui/src/doctor.mjs +142 -0
  283. package/vendor/harness-ui/src/document-filename.mjs +97 -0
  284. package/vendor/harness-ui/src/document-generator.mjs +493 -0
  285. package/vendor/harness-ui/src/document-report.mjs +331 -0
  286. package/vendor/harness-ui/src/duckduckgo-search.mjs +155 -0
  287. package/vendor/harness-ui/src/elenco-profondo.mjs +337 -0
  288. package/vendor/harness-ui/src/favicon-proxy.mjs +113 -0
  289. package/vendor/harness-ui/src/forge-contract.mjs +221 -0
  290. package/vendor/harness-ui/src/frequent-dirs.mjs +134 -0
  291. package/vendor/harness-ui/src/generated-image-store.mjs +147 -0
  292. package/vendor/harness-ui/src/generation-idle.mjs +332 -0
  293. package/vendor/harness-ui/src/gguf-header.mjs +207 -0
  294. package/vendor/harness-ui/src/git-service.mjs +626 -0
  295. package/vendor/harness-ui/src/gitignore-elenco.mjs +604 -0
  296. package/vendor/harness-ui/src/harness-receipt-keypair.mjs +207 -0
  297. package/vendor/harness-ui/src/hf-direct-transfer.mjs +170 -0
  298. package/vendor/harness-ui/src/hf-hub-client.mjs +106 -0
  299. package/vendor/harness-ui/src/hf-image-proxy.mjs +105 -0
  300. package/vendor/harness-ui/src/hf-model-transfer.mjs +245 -0
  301. package/vendor/harness-ui/src/hook-registry.mjs +186 -0
  302. package/vendor/harness-ui/src/http-app.mjs +6259 -0
  303. package/vendor/harness-ui/src/http-lifecycle.mjs +132 -0
  304. package/vendor/harness-ui/src/id-archivio.mjs +27 -0
  305. package/vendor/harness-ui/src/image-generator.mjs +143 -0
  306. package/vendor/harness-ui/src/istruzioni-di-progetto.mjs +234 -0
  307. package/vendor/harness-ui/src/kernel/dist/kernelPerIlBanco.js +518 -0
  308. package/vendor/harness-ui/src/kernel/talosHarness.mjs +10437 -0
  309. package/vendor/harness-ui/src/library-policy-store.mjs +175 -0
  310. package/vendor/harness-ui/src/library-store.mjs +652 -0
  311. package/vendor/harness-ui/src/llama-server-supervisor.mjs +629 -0
  312. package/vendor/harness-ui/src/local-model-store.mjs +339 -0
  313. package/vendor/harness-ui/src/local-runtime-contract.mjs +66 -0
  314. package/vendor/harness-ui/src/local-runtime-events.mjs +44 -0
  315. package/vendor/harness-ui/src/local-runtime-llama-server.mjs +244 -0
  316. package/vendor/harness-ui/src/local-runtime-probe.mjs +401 -0
  317. package/vendor/harness-ui/src/machine-capacity.mjs +66 -0
  318. package/vendor/harness-ui/src/mappa-cartelle.mjs +491 -0
  319. package/vendor/harness-ui/src/mcp-client.mjs +98 -0
  320. package/vendor/harness-ui/src/mcp-registry.mjs +157 -0
  321. package/vendor/harness-ui/src/mcp-session.mjs +177 -0
  322. package/vendor/harness-ui/src/memory-store.mjs +227 -0
  323. package/vendor/harness-ui/src/model-catalog-models-dev.mjs +276 -0
  324. package/vendor/harness-ui/src/model-catalog.mjs +129 -0
  325. package/vendor/harness-ui/src/model-destination.mjs +189 -0
  326. package/vendor/harness-ui/src/modifica-ancorata.mjs +177 -0
  327. package/vendor/harness-ui/src/native-provider-adapter.mjs +205 -0
  328. package/vendor/harness-ui/src/notes-store.mjs +250 -0
  329. package/vendor/harness-ui/src/openai-compatible-runtime.mjs +428 -0
  330. package/vendor/harness-ui/src/openrouter-oauth.mjs +339 -0
  331. package/vendor/harness-ui/src/path-policy.mjs +442 -0
  332. package/vendor/harness-ui/src/plugin-registry.mjs +780 -0
  333. package/vendor/harness-ui/src/plugin-session.mjs +180 -0
  334. package/vendor/harness-ui/src/process-policy.mjs +345 -0
  335. package/vendor/harness-ui/src/prompt-enhancer-provider.mjs +94 -0
  336. package/vendor/harness-ui/src/provider-auth-cloud.mjs +95 -0
  337. package/vendor/harness-ui/src/provider-credential-store.mjs +541 -0
  338. package/vendor/harness-ui/src/provider-probe.mjs +582 -0
  339. package/vendor/harness-ui/src/provider-registry.mjs +1633 -0
  340. package/vendor/harness-ui/src/pty-terminal.mjs +312 -0
  341. package/vendor/harness-ui/src/public-problem.mjs +109 -0
  342. package/vendor/harness-ui/src/research/card.mjs +235 -0
  343. package/vendor/harness-ui/src/research/citations.mjs +142 -0
  344. package/vendor/harness-ui/src/research/collector.mjs +275 -0
  345. package/vendor/harness-ui/src/research/deposito-a-pezzi.mjs +139 -0
  346. package/vendor/harness-ui/src/research/dossier.mjs +114 -0
  347. package/vendor/harness-ui/src/research/esportazioni.mjs +560 -0
  348. package/vendor/harness-ui/src/research/fetch-cache.mjs +465 -0
  349. package/vendor/harness-ui/src/research/fidelity.mjs +122 -0
  350. package/vendor/harness-ui/src/research/independence.mjs +159 -0
  351. package/vendor/harness-ui/src/research/ledger.mjs +166 -0
  352. package/vendor/harness-ui/src/research/markdown-server.mjs +565 -0
  353. package/vendor/harness-ui/src/research/narration.mjs +181 -0
  354. package/vendor/harness-ui/src/research/open-cards.mjs +131 -0
  355. package/vendor/harness-ui/src/research/opposing.mjs +305 -0
  356. package/vendor/harness-ui/src/research/outline.mjs +111 -0
  357. package/vendor/harness-ui/src/research/page-budget.mjs +209 -0
  358. package/vendor/harness-ui/src/research/pdf.mjs +291 -0
  359. package/vendor/harness-ui/src/research/plan.mjs +301 -0
  360. package/vendor/harness-ui/src/research/raccolta-viva.mjs +452 -0
  361. package/vendor/harness-ui/src/research/recheck-document.mjs +69 -0
  362. package/vendor/harness-ui/src/research/recheck-history.mjs +192 -0
  363. package/vendor/harness-ui/src/research/recheck.mjs +194 -0
  364. package/vendor/harness-ui/src/research/report.mjs +203 -0
  365. package/vendor/harness-ui/src/research/run.mjs +527 -0
  366. package/vendor/harness-ui/src/research/synthesis.mjs +318 -0
  367. package/vendor/harness-ui/src/research/verification.mjs +572 -0
  368. package/vendor/harness-ui/src/research-orchestrator.mjs +2679 -0
  369. package/vendor/harness-ui/src/research-store.mjs +1133 -0
  370. package/vendor/harness-ui/src/runtime-build-manifest.mjs +26 -0
  371. package/vendor/harness-ui/src/runtime-contract.mjs +59 -0
  372. package/vendor/harness-ui/src/runtime-owner-adapter.mjs +1348 -0
  373. package/vendor/harness-ui/src/runtime-owner-contract.mjs +32 -0
  374. package/vendor/harness-ui/src/scheda-di-lavoro.mjs +249 -0
  375. package/vendor/harness-ui/src/search-source-store.mjs +172 -0
  376. package/vendor/harness-ui/src/session-registry.mjs +6095 -0
  377. package/vendor/harness-ui/src/session-store.mjs +220 -0
  378. package/vendor/harness-ui/src/sessione-pronta.mjs +73 -0
  379. package/vendor/harness-ui/src/setup-stato.mjs +31 -0
  380. package/vendor/harness-ui/src/sezioni-istruzioni.mjs +204 -0
  381. package/vendor/harness-ui/src/skill-registry.mjs +120 -0
  382. package/vendor/harness-ui/src/sse-replay-coalescente.mjs +0 -0
  383. package/vendor/harness-ui/src/static-files.mjs +96 -0
  384. package/vendor/harness-ui/src/stream-partition.mjs +123 -0
  385. package/vendor/harness-ui/src/subagent-orchestrator.mjs +453 -0
  386. package/vendor/harness-ui/src/task-catalog.mjs +65 -0
  387. package/vendor/harness-ui/src/tasks-store.mjs +220 -0
  388. package/vendor/harness-ui/src/terminal-registry.mjs +312 -0
  389. package/vendor/harness-ui/src/terminal-ws.mjs +170 -0
  390. package/vendor/harness-ui/src/tool-forge-store.mjs +299 -0
  391. package/vendor/harness-ui/src/tool-schema-normalize.mjs +100 -0
  392. package/vendor/harness-ui/src/usage-cache.mjs +315 -0
  393. package/vendor/harness-ui/src/workspace-browser.mjs +213 -0
  394. package/vendor/harness-ui/src/workspace-context.mjs +124 -0
  395. package/vendor/harness-ui/src/workspace-disk.mjs +62 -0
  396. package/vendor/harness-ui/src/workspace-files.mjs +589 -0
  397. package/vendor/harness-ui/src/workspace-info.mjs +189 -0
  398. package/vendor/harness-ui/src/workspace-launch-store.mjs +150 -0
  399. package/vendor/harness-ui/src/workspace-tree.mjs +67 -0
  400. package/vendor/harness-ui/src/workspace-watcher.mjs +161 -0
  401. package/vendor/manifest.json +170 -0
@@ -0,0 +1,554 @@
1
+ import { execFile as nodeExecFile, spawn as nodeSpawn } from 'node:child_process';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
+ import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
4
+ import { tmpdir } from 'node:os';
5
+ import path from 'node:path';
6
+ import { promisify } from 'node:util';
7
+ const SCHEMA = 'talos.cli.process-tree-evidence.v1';
8
+ const SCOPE = 'createprocess-descendant';
9
+ const HEARTBEAT = 'heartbeat.json';
10
+ const BEAT_INTERVAL_MS = 75;
11
+ const SELF_DESTRUCT_MS = 60_000;
12
+ /*
13
+ * R3 (owner, 2026-09-24): the check is interruptible. The executor reports its own pid and the pid of the descendant it
14
+ * spawned into the check's private folder the moment it has them. The report plays no part in the measurement.
15
+ * ⛔ A reported pid is only a CANDIDATE: it is ended only with a proof, at kill time, that it is still this check's
16
+ * process (`endProven` below) — Windows reuses pids, and a pid read from a file proves nothing by itself.
17
+ */
18
+ const EXECUTOR_REPORT = 'executor.json';
19
+ export function isolationCheckAborted() { return Object.assign(new Error('PROCESS_TREE_PROBE_ABORTED'), { name: 'AbortError', code: 'ABORT_ERR' }); }
20
+ /**
21
+ * Spawned by the probe; it creates one ordinary `CreateProcess` descendant and then waits.
22
+ *
23
+ * `detached: true` is load-bearing and measured, not decorative. libuv assigns every
24
+ * NON-detached Windows child to its own global job object carrying
25
+ * `JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE`, so when the executor dies Node itself tears the
26
+ * descendant down. Measured on Windows 11 Pro 10.0.26200 with Node 24.18.0: a plain descendant
27
+ * dies with its parent, a detached one survives. Without this flag the probe would be measuring
28
+ * Node's job object and would answer "kill-on-close works" on a host with no sandbox at all.
29
+ *
30
+ * libuv deliberately does NOT set `CREATE_BREAKAWAY_FROM_JOB` for detached children (it only adds
31
+ * `DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP`), so the descendant stays job-associated by
32
+ * default the way any `CreateProcess` child is. That is exactly the `createprocess-descendant`
33
+ * scope this probe claims: Node's own job is removed from the measurement, the sandbox's is not.
34
+ */
35
+ const EXECUTOR_SOURCE = `import {spawn} from 'node:child_process';
36
+ import {writeFileSync} from 'node:fs';
37
+ import path from 'node:path';
38
+ const directory = process.argv[2];
39
+ const report = descendantPid => {try {writeFileSync(path.join(directory, '${EXECUTOR_REPORT}'), JSON.stringify({executorPid: process.pid, descendantPid}));} catch {}};
40
+ report(null);
41
+ const descendant = spawn(process.execPath, [path.join(directory, 'descendant.mjs'), directory], {cwd: directory, stdio: 'ignore', windowsHide: true, detached: true});
42
+ report(descendant.pid ?? null);
43
+ descendant.unref();
44
+ setTimeout(() => process.exit(0), ${SELF_DESTRUCT_MS});
45
+ `;
46
+ /**
47
+ * The descendant is identified by a heartbeat only it can produce, inside a directory the probe
48
+ * created for this run alone. A bare process identifier would be recyclable; a moving counter
49
+ * written by this process is not.
50
+ */
51
+ const DESCENDANT_SOURCE = `import {renameSync, writeFileSync} from 'node:fs';
52
+ import path from 'node:path';
53
+ const directory = process.argv[2];
54
+ const target = path.join(directory, '${HEARTBEAT}');
55
+ const temporary = path.join(directory, 'heartbeat.' + process.pid + '.tmp');
56
+ let seq = 0;
57
+ const beat = () => {
58
+ seq += 1;
59
+ try {
60
+ writeFileSync(temporary, JSON.stringify({pid: process.pid, seq, atMs: Date.now()}));
61
+ renameSync(temporary, target);
62
+ } catch {}
63
+ };
64
+ beat();
65
+ setInterval(beat, ${BEAT_INTERVAL_MS});
66
+ setTimeout(() => process.exit(0), ${SELF_DESTRUCT_MS}).unref();
67
+ `;
68
+ /* R3 proof (see `endProven`): how often the heartbeat is read while proving, and for how long (over five beats). */
69
+ const PROOF_POLL_MS = 20;
70
+ const PROOF_WINDOW_MS = 400;
71
+ const leftoverNote = (pids) => `PROCESS_TREE_PROBE_LEFT_RUNNING: pid ${pids.join(', ')} still running and not proven to be this check's own, so not ended`;
72
+ /* An abort ends a wait at once and clears its timer, so nothing a stopped check scheduled keeps the process alive. */
73
+ const delay = (ms, signal) => new Promise(resolve => {
74
+ if (signal?.aborted) {
75
+ resolve();
76
+ return;
77
+ }
78
+ const done = () => { clearTimeout(timer); signal?.removeEventListener('abort', done); resolve(); };
79
+ const timer = setTimeout(done, ms);
80
+ signal?.addEventListener('abort', done, { once: true });
81
+ });
82
+ function defaultSignalZero(pid) {
83
+ try {
84
+ process.kill(pid, 0);
85
+ return 'alive';
86
+ }
87
+ catch (error) {
88
+ return error.code === 'ESRCH' ? 'gone' : 'unknown';
89
+ }
90
+ }
91
+ function defaultKill(pid) {
92
+ process.kill(pid, 'SIGKILL');
93
+ }
94
+ const defaultSpawn = request => {
95
+ const child = nodeSpawn(request.executable, request.args, { cwd: request.cwd, stdio: 'ignore', windowsHide: true, shell: false });
96
+ let done = () => { };
97
+ const exited = new Promise(resolve => { done = resolve; });
98
+ child.once('exit', (code, signal) => done({ exitCode: code, signal }));
99
+ child.once('error', () => done());
100
+ return { pid: child.pid, kill: () => { try {
101
+ child.kill('SIGKILL');
102
+ }
103
+ catch { } }, exited };
104
+ };
105
+ /**
106
+ * NTSTATUS values a sandboxed executor has been seen to die with, named so a person can read the
107
+ * reason. Measured on this host: `node.exe` under the production probe policy exits 3221225794
108
+ * (0xC0000142) within 73-139 ms, before its first line of JavaScript.
109
+ */
110
+ const KNOWN_STATUS = {
111
+ 0xC0000005: 'STATUS_ACCESS_VIOLATION',
112
+ 0xC0000135: 'STATUS_DLL_NOT_FOUND',
113
+ 0xC0000142: 'STATUS_DLL_INIT_FAILED',
114
+ 0xC000013A: 'STATUS_CONTROL_C_EXIT',
115
+ };
116
+ /** `3221225794 (0xC0000142 STATUS_DLL_INIT_FAILED)`; small codes stay decimal because they are ordinary exit codes. */
117
+ export function describeExitStatus(exit) {
118
+ if (!exit || (exit.exitCode === null && !exit.signal))
119
+ return 'exit status not reported by the sandbox spawner';
120
+ if (exit.exitCode === null)
121
+ return `terminated by signal ${exit.signal}`;
122
+ const status = exit.exitCode >>> 0;
123
+ if (status < 0xC0000000)
124
+ return `exit status ${exit.exitCode}`;
125
+ const hex = `0x${status.toString(16).toUpperCase().padStart(8, '0')}`;
126
+ const name = KNOWN_STATUS[status];
127
+ return `exit status ${status} (${name ? `${hex} ${name}` : hex})`;
128
+ }
129
+ /**
130
+ * `wmic` has been removed from supported Windows 11 builds, so enumeration uses the real
131
+ * `tasklist.exe` executable by absolute path with no `/FI` filter: a project incident recorded
132
+ * `tasklist /FI` returning zero rows while four processes were alive. Filtering happens here, in
133
+ * JavaScript, and an empty or unparsable table reads as `unknown` rather than as `gone`.
134
+ */
135
+ function parseTasklistPids(stdout) {
136
+ const pids = new Set();
137
+ for (const line of stdout.split(/\r?\n/u)) {
138
+ if (line.trim() === '')
139
+ continue;
140
+ const fields = line.match(/"[^"]*"/gu);
141
+ if (!fields || fields.length < 2)
142
+ continue;
143
+ const value = Number.parseInt(fields[1].slice(1, -1), 10);
144
+ if (Number.isInteger(value))
145
+ pids.add(value);
146
+ }
147
+ return pids.size > 0 ? pids : null;
148
+ }
149
+ export function createHostProcessTreeProbe(deps = {}) {
150
+ const platform = deps.platform ?? process.platform;
151
+ const now = deps.now ?? (() => Date.now());
152
+ const tempRoot = deps.tempRoot ?? tmpdir();
153
+ const systemRoot = deps.systemRoot ?? process.env.SystemRoot ?? 'C:\\Windows';
154
+ const nodeExecutable = deps.nodeExecutable ?? process.execPath;
155
+ const signal = deps.signal;
156
+ const runExecFile = deps.execFile ?? (async (file, args) => {
157
+ const { stdout } = await promisify(nodeExecFile)(file, [...args], { windowsHide: true, maxBuffer: 32 * 1024 * 1024, ...(signal ? { signal } : {}) });
158
+ return { stdout: String(stdout) };
159
+ });
160
+ const spawnSandboxed = deps.spawn ?? defaultSpawn;
161
+ const signalZero = deps.signalZero ?? defaultSignalZero;
162
+ const killPid = deps.killPid ?? defaultKill;
163
+ const enumerate = deps.enumerate ?? (async (pid) => {
164
+ let stdout;
165
+ try {
166
+ ({ stdout } = await runExecFile(path.join(systemRoot, 'System32', 'tasklist.exe'), ['/FO', 'CSV', '/NH']));
167
+ }
168
+ catch {
169
+ return 'unknown';
170
+ }
171
+ const pids = parseTasklistPids(stdout);
172
+ if (pids === null)
173
+ return 'unknown';
174
+ return pids.has(pid) ? 'alive' : 'gone';
175
+ });
176
+ const descendantTimeoutMs = deps.descendantTimeoutMs ?? 15_000;
177
+ const executorExitTimeoutMs = deps.executorExitTimeoutMs ?? 5_000;
178
+ const settleMs = deps.settleMs ?? 600;
179
+ const heartbeatWindowMs = deps.heartbeatWindowMs ?? 500;
180
+ async function readBeat(directory) {
181
+ if (deps.readHeartbeat)
182
+ return deps.readHeartbeat(directory);
183
+ try {
184
+ const value = JSON.parse(await readFile(path.join(directory, HEARTBEAT), 'utf8'));
185
+ return typeof value.pid === 'number' && typeof value.seq === 'number' ? { pid: value.pid, seq: value.seq } : null;
186
+ }
187
+ catch {
188
+ return null;
189
+ }
190
+ }
191
+ /** A rename can be observed mid-flight; a handful of retries removes that race, nothing else. */
192
+ async function readBeatSettled(directory) {
193
+ for (let attempt = 0; attempt < 6; attempt++) {
194
+ const beat = await readBeat(directory);
195
+ if (beat)
196
+ return beat;
197
+ await delay(30, signal);
198
+ }
199
+ return null;
200
+ }
201
+ /**
202
+ * Waits for the descendant's heartbeat, and stops as soon as the executor that should create it
203
+ * is gone.
204
+ *
205
+ * ⛔ Measured on this host: the sandboxed executor died in 73-139 ms and this loop then waited the
206
+ * full descendant timeout (15 s) for a heartbeat that nothing alive could write. A dead executor
207
+ * is still a NEGATIVE — it proves nothing about kill-on-close — but the answer is due when it
208
+ * dies, and it carries how it died.
209
+ * ⛔ The heartbeat is read BEFORE the exit is honoured, on every turn: a descendant that beat in
210
+ * the same tick the executor ended is not thrown away. A slow descendant under a LIVE executor
211
+ * is waited for exactly as before.
212
+ */
213
+ async function waitForDescendant(directory, exited) {
214
+ let ended = null;
215
+ void exited.then(status => { ended = { status }; }, () => { ended = { status: undefined }; });
216
+ const deadline = Date.now() + descendantTimeoutMs;
217
+ while (Date.now() < deadline && !signal?.aborted) {
218
+ const beat = await readBeat(directory);
219
+ if (beat && beat.seq >= 2)
220
+ return { appeared: beat };
221
+ const executorEnd = ended;
222
+ if (executorEnd) {
223
+ /*
224
+ * ⛔ Round 4 (review mutation M18): the exit can land while the read above is in flight, and
225
+ * the descendant's beat can land in the same instant. One more read, after the exit is
226
+ * known, so a beat written before the exit was observed is never thrown away.
227
+ */
228
+ const last = await readBeat(directory);
229
+ if (last && last.seq >= 2)
230
+ return { appeared: last };
231
+ return { executorExited: executorEnd.status };
232
+ }
233
+ await delay(40, signal);
234
+ }
235
+ return null;
236
+ }
237
+ async function waitGone(pid, timeoutMs) {
238
+ const deadline = Date.now() + timeoutMs;
239
+ while (Date.now() < deadline && signalZero(pid) === 'alive')
240
+ await delay(50);
241
+ }
242
+ /** The pids the executor and the descendant wrote into this check's folder. Candidates only — see `endProven`. */
243
+ function reportedPids(directory) {
244
+ const pids = [];
245
+ const read = (file) => { try {
246
+ return JSON.parse(readFileSync(path.join(directory, file), 'utf8'));
247
+ }
248
+ catch {
249
+ return null;
250
+ } };
251
+ const report = read(EXECUTOR_REPORT);
252
+ const beat = read(HEARTBEAT);
253
+ for (const value of [report?.descendantPid, beat?.pid, report?.executorPid])
254
+ if (typeof value === 'number' && Number.isInteger(value) && value > 0 && !pids.includes(value))
255
+ pids.push(value);
256
+ return pids;
257
+ }
258
+ /** The latest beat in the folder, read synchronously so that a kill follows the read in the same tick. */
259
+ function beatNow(directory) {
260
+ try {
261
+ const value = JSON.parse(readFileSync(path.join(directory, HEARTBEAT), 'utf8'));
262
+ return typeof value.pid === 'number' && typeof value.seq === 'number' ? { pid: value.pid, seq: value.seq } : null;
263
+ }
264
+ catch {
265
+ return null;
266
+ }
267
+ }
268
+ /*
269
+ * ⛔⛔ R3 (coordinator review; owner standing rule): a pid is ended ONLY with a proof, AT KILL TIME, that it is a process
270
+ * THIS check started. Windows reuses pids quickly: a pid read from executor.json or heartbeat.json, or seen alive a
271
+ * moment ago, can belong seconds later to an unrelated process of the person, and TerminateProcess would end it.
272
+ * · The proof is the heartbeat (proof (a)). The descendant rewrites heartbeat.json in this check's private folder,
273
+ * with its own pid, every 75 ms. A beat that MOVED since the previous read (20 ms earlier) was written by that pid
274
+ * within those 20 ms: it is this check's descendant now, and the kill follows that read in the same tick. A beat
275
+ * that does not move proves nothing (a writer that is gone, a pid that is someone else's now).
276
+ * Why not (b) creation time or (c) command line: Node cannot read either on Windows without a CIM query, measured
277
+ * here at 947-1003 ms per query (3 runs, powershell Get-CimInstance Win32_Process) — half the 2 s abort budget,
278
+ * and one more process to manage. The heartbeat costs at most one beat interval.
279
+ * · A pid seen `gone` (ESRCH) after it was reported is this check's process, ended for good: never a candidate again.
280
+ * · The executor is ended through the handle TALOS holds, never by pid.
281
+ * · No proof → no kill: the pid comes back as a leftover and the caller STATES it (never verified, never cached).
282
+ */
283
+ function noteGone(directory, gone) {
284
+ for (const pid of reportedPids(directory))
285
+ if (!gone.has(pid) && signalZero(pid) === 'gone')
286
+ gone.add(pid);
287
+ }
288
+ async function endProven(directory, candidates, gone, windowMs) {
289
+ const ended = [];
290
+ let waiting = candidates.filter(pid => !gone.has(pid));
291
+ let previous = beatNow(directory);
292
+ const deadline = Date.now() + windowMs;
293
+ for (;;) {
294
+ waiting = waiting.filter(pid => { if (signalZero(pid) !== 'gone')
295
+ return true; gone.add(pid); return false; });
296
+ if (waiting.length === 0)
297
+ break;
298
+ const beat = beatNow(directory);
299
+ if (beat && previous && beat.pid === previous.pid && beat.seq > previous.seq && waiting.includes(beat.pid)) {
300
+ /* The proof: this pid wrote a new beat in this check's folder since the previous read. End it now, in this tick. */
301
+ let killed = false;
302
+ try {
303
+ killPid(beat.pid);
304
+ killed = true;
305
+ }
306
+ catch { }
307
+ if (killed) {
308
+ ended.push(beat.pid);
309
+ waiting = waiting.filter(pid => pid !== beat.pid);
310
+ continue;
311
+ }
312
+ }
313
+ if (beat)
314
+ previous = beat;
315
+ if (Date.now() >= deadline)
316
+ break;
317
+ await delay(PROOF_POLL_MS);
318
+ }
319
+ return { ended, leftover: waiting };
320
+ }
321
+ return async () => {
322
+ const observedAtMs = now();
323
+ const startedAt = Date.now();
324
+ const signals = { heartbeat: 'unknown', signalZero: 'unknown', enumeration: 'unknown' };
325
+ const cleanup = { descendantKilled: false, executorKilled: false, directoryRemoved: false };
326
+ let reason;
327
+ if (platform !== 'win32') {
328
+ return {
329
+ verified: false,
330
+ reason: 'PROCESS_TREE_PROBE_REQUIRES_WINDOWS',
331
+ evidence: { schema: SCHEMA, scope: SCOPE, signals, executorPid: null, descendantPid: null, observedAtMs, durationMs: Date.now() - startedAt, cleanup }
332
+ };
333
+ }
334
+ if (signal?.aborted)
335
+ throw isolationCheckAborted();
336
+ const directory = await mkdtemp(path.join(tempRoot, 'talos-process-tree-'));
337
+ let handle;
338
+ let executorPid = null;
339
+ let descendantPid = null;
340
+ /* Pids of this check's processes seen gone after they were reported: ended for good, never a candidate again. */
341
+ const gone = new Set();
342
+ /*
343
+ * On abort the executor is ended at once through its handle. What it spawned is ended in the cleanup below, and only
344
+ * with a proof (`endProven`) — never a pid on trust.
345
+ */
346
+ const stopAll = () => { try {
347
+ void handle?.kill();
348
+ }
349
+ catch { } };
350
+ signal?.addEventListener('abort', stopAll, { once: true });
351
+ const checkAbort = () => { if (signal?.aborted)
352
+ throw isolationCheckAborted(); };
353
+ let failure;
354
+ try {
355
+ await writeFile(path.join(directory, 'executor.mjs'), EXECUTOR_SOURCE, 'utf8');
356
+ await writeFile(path.join(directory, 'descendant.mjs'), DESCENDANT_SOURCE, 'utf8');
357
+ checkAbort();
358
+ handle = await spawnSandboxed({ executable: nodeExecutable, args: [path.join(directory, 'executor.mjs'), directory], cwd: directory, probeDirectory: directory });
359
+ executorPid = handle.pid ?? null;
360
+ if (signal?.aborted)
361
+ stopAll();
362
+ checkAbort();
363
+ const waited = await waitForDescendant(directory, handle.exited);
364
+ checkAbort();
365
+ if (waited === null) {
366
+ reason = 'PROCESS_TREE_PROBE_DESCENDANT_NEVER_APPEARED';
367
+ }
368
+ else if ('executorExited' in waited) {
369
+ reason = `PROCESS_TREE_PROBE_EXECUTOR_EXITED: ${describeExitStatus(waited.executorExited)}`;
370
+ }
371
+ else {
372
+ const appeared = waited.appeared;
373
+ descendantPid = appeared.pid;
374
+ await handle.kill();
375
+ await Promise.race([handle.exited, delay(executorExitTimeoutMs, signal)]);
376
+ noteGone(directory, gone);
377
+ await delay(settleMs, signal);
378
+ checkAbort();
379
+ const before = await readBeatSettled(directory);
380
+ await delay(heartbeatWindowMs, signal);
381
+ const after = await readBeatSettled(directory);
382
+ checkAbort();
383
+ signals.heartbeat = before && after ? (after.seq > before.seq ? 'alive' : 'gone') : 'unknown';
384
+ signals.signalZero = signalZero(descendantPid);
385
+ if (signals.signalZero === 'gone')
386
+ gone.add(descendantPid);
387
+ signals.enumeration = await enumerate(descendantPid);
388
+ checkAbort();
389
+ const observed = [signals.heartbeat, signals.signalZero, signals.enumeration];
390
+ if (observed.includes('unknown'))
391
+ reason = 'PROCESS_TREE_PROBE_SIGNALS_INDETERMINATE';
392
+ else if (observed.every(value => value === 'gone'))
393
+ reason = undefined;
394
+ else if (observed.every(value => value === 'alive'))
395
+ reason = 'PROCESS_TREE_PROBE_DESCENDANT_SURVIVED';
396
+ else
397
+ reason = 'PROCESS_TREE_PROBE_SIGNALS_DISAGREE';
398
+ }
399
+ }
400
+ catch (error) {
401
+ failure = { error };
402
+ }
403
+ /* Cleanup, always. */
404
+ signal?.removeEventListener('abort', stopAll);
405
+ const aborted = signal?.aborted === true;
406
+ /* An aborted check confirms each step for at most half a second: TALOS is quitting and must not wait. */
407
+ const confirmMs = aborted ? 500 : 5_000;
408
+ /* 1. The executor, through the handle TALOS holds — never by pid. With kill-on-close its descendant goes with it. */
409
+ if (handle) {
410
+ const executorWasAlive = executorPid !== null && signalZero(executorPid) === 'alive';
411
+ try {
412
+ await handle.kill();
413
+ }
414
+ catch { }
415
+ if (executorWasAlive) {
416
+ cleanup.executorKilled = true;
417
+ await waitGone(executorPid, confirmMs);
418
+ }
419
+ }
420
+ /*
421
+ * 2. Everything else this check may have started (the descendant it measured, the pids reported in its folder), by pid
422
+ * and ONLY with the proof. The executor's own pid is the handle's business, never a candidate.
423
+ */
424
+ const candidates = [...new Set([...(descendantPid !== null ? [descendantPid] : []), ...reportedPids(directory)])].filter(pid => pid !== executorPid);
425
+ const proven = await endProven(directory, candidates, gone, PROOF_WINDOW_MS);
426
+ for (const pid of proven.ended)
427
+ await waitGone(pid, confirmMs);
428
+ if (proven.ended.length > 0)
429
+ cleanup.descendantKilled = true;
430
+ if (proven.leftover.length > 0)
431
+ cleanup.leftover = proven.leftover;
432
+ try {
433
+ /* Bounded on abort: a folder a leftover still holds must not keep TALOS from quitting (linear backoff). */
434
+ await rm(directory, { recursive: true, force: true, maxRetries: aborted ? 2 : 20, retryDelay: 100 });
435
+ cleanup.directoryRemoved = true;
436
+ }
437
+ catch { }
438
+ /* ⛔ No proof, no kill — and never silently: the leftover is stated in the error or in the reason. */
439
+ if (failure) {
440
+ if (proven.leftover.length > 0 && failure.error instanceof Error) {
441
+ try {
442
+ Object.assign(failure.error, { leftover: [...proven.leftover] });
443
+ failure.error.message = `${failure.error.message}; ${leftoverNote(proven.leftover)}`;
444
+ }
445
+ catch { }
446
+ }
447
+ throw failure.error;
448
+ }
449
+ if (proven.leftover.length > 0)
450
+ reason = reason === undefined ? leftoverNote(proven.leftover) : `${reason}; ${leftoverNote(proven.leftover)}`;
451
+ return {
452
+ verified: reason === undefined,
453
+ ...(reason === undefined ? {} : { reason }),
454
+ evidence: { schema: SCHEMA, scope: SCOPE, signals, executorPid, descendantPid, observedAtMs, durationMs: Date.now() - startedAt, cleanup }
455
+ };
456
+ };
457
+ }
458
+ const WORKLOAD_MARKER = 'TALOS_WORKLOAD_OK';
459
+ const GIT_BASH_UNSUPPORTED = 'unsupported: MSYS2 runtimes cannot initialise under processcontainer (microsoft/mxc#1061)';
460
+ function findOnPath(file) {
461
+ for (const entry of String(process.env.PATH ?? '').split(';')) {
462
+ if (!entry || !path.isAbsolute(entry))
463
+ continue;
464
+ const candidate = path.join(entry, file);
465
+ if (existsSync(candidate))
466
+ return candidate;
467
+ }
468
+ return null;
469
+ }
470
+ export function createSandboxWorkloadProbe(deps) {
471
+ const platform = deps.platform ?? process.platform;
472
+ const tempRoot = deps.tempRoot ?? tmpdir();
473
+ const systemRoot = deps.systemRoot ?? process.env.SystemRoot ?? 'C:\\Windows';
474
+ const comSpec = deps.comSpec ?? process.env.ComSpec ?? path.join(systemRoot, 'System32', 'cmd.exe');
475
+ const nodeExecutable = deps.nodeExecutable ?? process.execPath;
476
+ const timeoutMs = deps.timeoutMs ?? 30_000;
477
+ const signal = deps.signal;
478
+ return async () => {
479
+ if (signal?.aborted)
480
+ throw isolationCheckAborted();
481
+ const workloads = { cmd: 'not run', node: 'not run', powershell: 'not run', pwsh: 'not run', gitBash: GIT_BASH_UNSUPPORTED };
482
+ if (platform !== 'win32')
483
+ return { ok: false, reason: 'PROCESS_TREE_PROBE_REQUIRES_WINDOWS', workloads };
484
+ const pwsh = deps.pwshExecutable === undefined ? findOnPath('pwsh.exe') : deps.pwshExecutable;
485
+ const powershellArgs = (marker) => ['-NoProfile', '-NonInteractive', '-Command', `Set-Content -LiteralPath ${marker} -Value ${WORKLOAD_MARKER}`];
486
+ const plan = [
487
+ ['cmd', comSpec, ['/d', '/c', `echo ${WORKLOAD_MARKER}>cmd.ok`]],
488
+ ['node', nodeExecutable, ['-e', `require('fs').writeFileSync('node.ok','${WORKLOAD_MARKER}')`]],
489
+ ['powershell', path.join(systemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe'), powershellArgs('powershell.ok')],
490
+ ['pwsh', pwsh, powershellArgs('pwsh.ok')],
491
+ ];
492
+ const directory = await mkdtemp(path.join(tempRoot, 'talos-workloads-'));
493
+ try {
494
+ for (const [name, executable, args] of plan) {
495
+ if (signal?.aborted)
496
+ break;
497
+ if (!executable) {
498
+ workloads[name] = 'not-installed';
499
+ continue;
500
+ }
501
+ let handle;
502
+ try {
503
+ handle = await deps.spawn({ executable, args, cwd: directory, probeDirectory: directory });
504
+ }
505
+ catch (error) {
506
+ workloads[name] = `failed: spawn ${error instanceof Error ? error.message : String(error)}`.slice(0, 300);
507
+ continue;
508
+ }
509
+ let timer;
510
+ let onAbort;
511
+ const stopped = new Promise(resolve => { onAbort = () => resolve('aborted'); if (signal?.aborted)
512
+ onAbort();
513
+ else
514
+ signal?.addEventListener('abort', onAbort, { once: true }); });
515
+ const exit = await Promise.race([handle.exited, stopped, new Promise(resolve => { timer = setTimeout(() => resolve('timeout'), timeoutMs); })]).finally(() => { if (timer)
516
+ clearTimeout(timer); if (onAbort)
517
+ signal?.removeEventListener('abort', onAbort); });
518
+ if (exit === 'aborted') {
519
+ try {
520
+ await handle.kill();
521
+ }
522
+ catch { }
523
+ await Promise.race([handle.exited, delay(1_000)]);
524
+ break;
525
+ }
526
+ if (exit === 'timeout') {
527
+ try {
528
+ await handle.kill();
529
+ }
530
+ catch { }
531
+ workloads[name] = `failed: no exit within ${Math.round(timeoutMs / 1000)}s`;
532
+ continue;
533
+ }
534
+ let written = '';
535
+ try {
536
+ written = (await readFile(path.join(directory, `${name}.ok`), 'utf8')).trim();
537
+ }
538
+ catch { }
539
+ const exitCode = exit ? exit.exitCode : undefined;
540
+ workloads[name] = exitCode === 0 && written === WORKLOAD_MARKER ? 'ok' : `failed: ${describeExitStatus(exit)}${written === WORKLOAD_MARKER ? '' : ', no marker written'}`;
541
+ }
542
+ }
543
+ finally {
544
+ try {
545
+ await rm(directory, { recursive: true, force: true, maxRetries: 20, retryDelay: 100 });
546
+ }
547
+ catch { }
548
+ }
549
+ if (signal?.aborted)
550
+ throw isolationCheckAborted();
551
+ const broken = ['cmd', 'node', 'powershell'].filter(name => workloads[name] !== 'ok');
552
+ return broken.length === 0 ? { ok: true, workloads } : { ok: false, reason: `PROCESS_TREE_PROBE_WORKLOAD_FAILED: ${broken.map(name => `${name} ${workloads[name]}`).join('; ')}`, workloads };
553
+ };
554
+ }