talos-code 0.0.1 → 0.2.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 (407) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +661 -0
  3. package/README.md +116 -3
  4. package/THIRD_PARTY_NOTICES.md +40 -0
  5. package/dist/archive/zip.js +73 -0
  6. package/dist/args.js +100 -0
  7. package/dist/automations/history-store.js +34 -0
  8. package/dist/automations/policy-store.js +43 -0
  9. package/dist/automations/runner.js +107 -0
  10. package/dist/automations/schedule.js +85 -0
  11. package/dist/automations/windows-task.js +53 -0
  12. package/dist/commands/advanced-cli.js +233 -0
  13. package/dist/commands/checkpoint-cli.js +45 -0
  14. package/dist/commands/config-cli.js +107 -0
  15. package/dist/commands/context.js +17 -0
  16. package/dist/commands/extensions-cli.js +207 -0
  17. package/dist/commands/project-cli.js +74 -0
  18. package/dist/commands/project-commands.js +143 -0
  19. package/dist/commands/provider-cli.js +244 -0
  20. package/dist/commands/services-cli.js +248 -0
  21. package/dist/commands/session-cli.js +171 -0
  22. package/dist/commands/system-cli.js +405 -0
  23. package/dist/config/commands.js +60 -0
  24. package/dist/config/load.js +382 -0
  25. package/dist/config/migrations.js +48 -0
  26. package/dist/config/types.js +11 -0
  27. package/dist/diagnostics/development-log.js +154 -0
  28. package/dist/diagnostics/doctor.js +104 -0
  29. package/dist/diagnostics/redact.js +80 -0
  30. package/dist/diagnostics/zip.js +52 -0
  31. package/dist/errors.js +156 -0
  32. package/dist/events/bridge.js +130 -0
  33. package/dist/extensions/installer.js +178 -0
  34. package/dist/extensions/package-schema.js +24 -0
  35. package/dist/headless/result.js +84 -0
  36. package/dist/headless/run.js +230 -0
  37. package/dist/i18n/en/approval.js +46 -0
  38. package/dist/i18n/en/common.js +9 -0
  39. package/dist/i18n/en/credentials.js +92 -0
  40. package/dist/i18n/en/errors.js +267 -0
  41. package/dist/i18n/en/firstrun.js +101 -0
  42. package/dist/i18n/en/providers.js +37 -0
  43. package/dist/i18n/en/screen.js +774 -0
  44. package/dist/i18n/en/tools.js +127 -0
  45. package/dist/i18n/en.js +14 -0
  46. package/dist/i18n/error-view.js +307 -0
  47. package/dist/i18n/index.js +19 -0
  48. package/dist/i18n/kernel-map.js +139 -0
  49. package/dist/io.js +45 -0
  50. package/dist/main.js +331 -0
  51. package/dist/paths.js +41 -0
  52. package/dist/protocol/v2/codec.js +9 -0
  53. package/dist/protocol/v2/events.js +555 -0
  54. package/dist/protocol/v2/index.js +4 -0
  55. package/dist/protocol/v2/replay.js +28 -0
  56. package/dist/protocol/v2/types.js +1 -0
  57. package/dist/provider/control-plane.js +135 -0
  58. package/dist/provider/environment-keys.js +275 -0
  59. package/dist/provider/health.js +110 -0
  60. package/dist/provider/missing-key.js +48 -0
  61. package/dist/provider/model-catalog.js +168 -0
  62. package/dist/provider/openrouter-login.js +172 -0
  63. package/dist/provider/provider-text.js +13 -0
  64. package/dist/provider/store.js +95 -0
  65. package/dist/provider/system-keyring.js +214 -0
  66. package/dist/runtime/active-run.js +63 -0
  67. package/dist/runtime/agent-tree.js +74 -0
  68. package/dist/runtime/attachments.js +84 -0
  69. package/dist/runtime/brokered-executor.js +395 -0
  70. package/dist/runtime/context-archive.js +69 -0
  71. package/dist/runtime/context-status.js +76 -0
  72. package/dist/runtime/create-runtime.js +111 -0
  73. package/dist/runtime/model-profile.js +361 -0
  74. package/dist/runtime/output-store.js +137 -0
  75. package/dist/runtime/provider-attempts.js +185 -0
  76. package/dist/runtime/replay-buffer.js +153 -0
  77. package/dist/runtime/repo.js +95 -0
  78. package/dist/runtime/session-facade.js +135 -0
  79. package/dist/runtime/session-summary.js +125 -0
  80. package/dist/runtime/supervisor.js +265 -0
  81. package/dist/runtime/talos-composition.js +1011 -0
  82. package/dist/runtime/types.js +5 -0
  83. package/dist/runtime/usage-snapshot.js +82 -0
  84. package/dist/security/auto-classifier.js +38 -0
  85. package/dist/security/credential-free-environment.js +54 -0
  86. package/dist/security/evaluate.js +243 -0
  87. package/dist/security/execution-backends.js +236 -0
  88. package/dist/security/execution-broker.js +102 -0
  89. package/dist/security/forge-scan.js +74 -0
  90. package/dist/security/from-approval.js +39 -0
  91. package/dist/security/mxc-execution-backend.js +281 -0
  92. package/dist/security/permission-engine.js +138 -0
  93. package/dist/security/permission-explanation.js +54 -0
  94. package/dist/security/persist.js +179 -0
  95. package/dist/security/plugin-guard.js +230 -0
  96. package/dist/security/process-tree-evidence-store.js +74 -0
  97. package/dist/security/process-tree-probe.js +554 -0
  98. package/dist/security/project-resource-inventory.js +186 -0
  99. package/dist/security/project-trust-gate.js +38 -0
  100. package/dist/security/project-trust.js +367 -0
  101. package/dist/security/rule-parser.js +201 -0
  102. package/dist/security/shell-segmentation.js +68 -0
  103. package/dist/security/trust-authority.js +324 -0
  104. package/dist/security/types.js +1 -0
  105. package/dist/security/workspace-identity.js +102 -0
  106. package/dist/services/automation-facade.js +59 -0
  107. package/dist/services/forge-facade.js +77 -0
  108. package/dist/services/hook-facade.js +240 -0
  109. package/dist/services/index.js +16 -0
  110. package/dist/services/library-facade.js +174 -0
  111. package/dist/services/mcp-facade.js +348 -0
  112. package/dist/services/memory-facade.js +126 -0
  113. package/dist/services/notes-facade.js +157 -0
  114. package/dist/services/plugin-facade.js +308 -0
  115. package/dist/services/research-facade.js +110 -0
  116. package/dist/services/task-board-facade.js +236 -0
  117. package/dist/services/workflow-catalog.js +246 -0
  118. package/dist/sessions/export-format.js +98 -0
  119. package/dist/sessions/metadata-store.js +160 -0
  120. package/dist/sessions/share.js +122 -0
  121. package/dist/sessions/transfer.js +16 -0
  122. package/dist/subcommands.js +62 -0
  123. package/dist/tui/agent-roster.js +36 -0
  124. package/dist/tui/agent-view.js +51 -0
  125. package/dist/tui/app.js +4098 -0
  126. package/dist/tui/approval.js +36 -0
  127. package/dist/tui/boot/boot-sequence.js +76 -0
  128. package/dist/tui/boot/cinematic.js +243 -0
  129. package/dist/tui/boot/desktop-logo.js +82 -0
  130. package/dist/tui/boot.js +3 -0
  131. package/dist/tui/busy-input.js +58 -0
  132. package/dist/tui/catalog-service.js +560 -0
  133. package/dist/tui/components/assistant-stream.js +1 -0
  134. package/dist/tui/components/command-menu.js +68 -0
  135. package/dist/tui/components/composer.js +219 -0
  136. package/dist/tui/components/diff.js +35 -0
  137. package/dist/tui/components/footer.js +48 -0
  138. package/dist/tui/components/header.js +6 -0
  139. package/dist/tui/components/markdown.js +305 -0
  140. package/dist/tui/components/status-indicator.js +38 -0
  141. package/dist/tui/components/terminal-shell.js +214 -0
  142. package/dist/tui/components/thinking-row.js +19 -0
  143. package/dist/tui/components/tool-row.js +97 -0
  144. package/dist/tui/components/transcript-virtualizer.js +165 -0
  145. package/dist/tui/components/transcript.js +43 -0
  146. package/dist/tui/descendant-approvals.js +104 -0
  147. package/dist/tui/diff-model.js +77 -0
  148. package/dist/tui/editor-history.js +21 -0
  149. package/dist/tui/editor.js +210 -0
  150. package/dist/tui/event-adapter.js +436 -0
  151. package/dist/tui/exit-output.js +58 -0
  152. package/dist/tui/external-editor.js +53 -0
  153. package/dist/tui/file-completion.js +89 -0
  154. package/dist/tui/focus-manager.js +5 -0
  155. package/dist/tui/highlight.js +30 -0
  156. package/dist/tui/input-router.js +18 -0
  157. package/dist/tui/interrupt.js +99 -0
  158. package/dist/tui/keybindings.js +194 -0
  159. package/dist/tui/keymap-resolver.js +91 -0
  160. package/dist/tui/launch-state.js +148 -0
  161. package/dist/tui/line-diff.js +57 -0
  162. package/dist/tui/live-activity.js +56 -0
  163. package/dist/tui/metrics.js +123 -0
  164. package/dist/tui/onboarding.js +36 -0
  165. package/dist/tui/overlays/agent-tree.js +43 -0
  166. package/dist/tui/overlays/approval-dialog.js +642 -0
  167. package/dist/tui/overlays/automation-center.js +51 -0
  168. package/dist/tui/overlays/checkpoint-picker.js +47 -0
  169. package/dist/tui/overlays/context-inspector.js +36 -0
  170. package/dist/tui/overlays/effort-line.js +110 -0
  171. package/dist/tui/overlays/forge-center.js +46 -0
  172. package/dist/tui/overlays/help-dialog.js +16 -0
  173. package/dist/tui/overlays/history-picker.js +37 -0
  174. package/dist/tui/overlays/hook-center.js +70 -0
  175. package/dist/tui/overlays/library-center.js +55 -0
  176. package/dist/tui/overlays/mcp-center.js +60 -0
  177. package/dist/tui/overlays/memory-center.js +63 -0
  178. package/dist/tui/overlays/model-picker.js +77 -0
  179. package/dist/tui/overlays/notes-center.js +53 -0
  180. package/dist/tui/overlays/overlay-host.js +8 -0
  181. package/dist/tui/overlays/plugin-center.js +76 -0
  182. package/dist/tui/overlays/provider-picker.js +171 -0
  183. package/dist/tui/overlays/queue-editor.js +32 -0
  184. package/dist/tui/overlays/research-center.js +59 -0
  185. package/dist/tui/overlays/scroll-window.js +234 -0
  186. package/dist/tui/overlays/session-picker.js +115 -0
  187. package/dist/tui/overlays/tasks-center.js +83 -0
  188. package/dist/tui/overlays/theme-picker.js +21 -0
  189. package/dist/tui/overlays/transcript-search.js +58 -0
  190. package/dist/tui/overlays/trust-center.js +29 -0
  191. package/dist/tui/overlays/workflow-center.js +46 -0
  192. package/dist/tui/project-file-index.js +214 -0
  193. package/dist/tui/project-references.js +85 -0
  194. package/dist/tui/project-trust-prompt.js +289 -0
  195. package/dist/tui/prompt-history-store.js +116 -0
  196. package/dist/tui/queue-store.js +110 -0
  197. package/dist/tui/regions/budget.js +59 -0
  198. package/dist/tui/regions/views.js +96 -0
  199. package/dist/tui/render-coordinator.js +148 -0
  200. package/dist/tui/render-scheduler.js +4 -0
  201. package/dist/tui/run.js +69 -0
  202. package/dist/tui/selection-list.js +29 -0
  203. package/dist/tui/session-controller.js +791 -0
  204. package/dist/tui/session-export.js +54 -0
  205. package/dist/tui/setup-wizard.js +46 -0
  206. package/dist/tui/shell-input.js +35 -0
  207. package/dist/tui/shell-layout.js +48 -0
  208. package/dist/tui/shell-model.js +98 -0
  209. package/dist/tui/slash-commands.js +82 -0
  210. package/dist/tui/state.js +151 -0
  211. package/dist/tui/status-bar.js +125 -0
  212. package/dist/tui/status-view.js +40 -0
  213. package/dist/tui/terminal-capabilities.js +9 -0
  214. package/dist/tui/terminal-session.js +11 -0
  215. package/dist/tui/text-width.js +66 -0
  216. package/dist/tui/theme-catalog.js +27 -0
  217. package/dist/tui/theme-store.js +23 -0
  218. package/dist/tui/theme.js +23 -0
  219. package/dist/tui/tool-display.js +135 -0
  220. package/dist/tui/tool-facts.js +1 -0
  221. package/dist/tui/tools/bash-renderer.js +32 -0
  222. package/dist/tui/tools/change.js +61 -0
  223. package/dist/tui/tools/edit-renderer.js +17 -0
  224. package/dist/tui/tools/generic-renderer.js +13 -0
  225. package/dist/tui/tools/list-renderer.js +14 -0
  226. package/dist/tui/tools/read-renderer.js +13 -0
  227. package/dist/tui/tools/registry.js +20 -0
  228. package/dist/tui/tools/row-format.js +187 -0
  229. package/dist/tui/tools/search-renderer.js +38 -0
  230. package/dist/tui/tools/shared.js +97 -0
  231. package/dist/tui/tools/write-renderer.js +15 -0
  232. package/dist/tui/transcript-model.js +441 -0
  233. package/dist/tui/ui-preferences.js +79 -0
  234. package/dist/tui/usage-view.js +77 -0
  235. package/dist/tui/vim-mode.js +99 -0
  236. package/dist/update/check.js +15 -0
  237. package/dist/update/npm.js +51 -0
  238. package/dist/update/run.js +129 -0
  239. package/dist/version.js +2 -0
  240. package/dist/workspace/checkpoint-store.js +210 -0
  241. package/dist/workspace/checkpoint.js +413 -0
  242. package/dist/workspace/restore.js +232 -0
  243. package/package.json +64 -5
  244. package/vendor/context-engine/package.json +11 -0
  245. package/vendor/context-engine/src/compaction-planner.mjs +57 -0
  246. package/vendor/context-engine/src/contracts.mjs +48 -0
  247. package/vendor/context-engine/src/engine.mjs +445 -0
  248. package/vendor/context-engine/src/node/context-export.mjs +164 -0
  249. package/vendor/context-engine/src/node/legacy-import.mjs +92 -0
  250. package/vendor/context-engine/src/node/migrations/001-context.sql +126 -0
  251. package/vendor/context-engine/src/node/sqlite-store.mjs +85 -0
  252. package/vendor/context-engine/src/node/sqlite-worker.mjs +559 -0
  253. package/vendor/context-engine/src/profiles.mjs +10 -0
  254. package/vendor/context-engine/src/retrieval.mjs +104 -0
  255. package/vendor/context-engine/src/summary.mjs +97 -0
  256. package/vendor/context-engine/src/usage.mjs +34 -0
  257. package/vendor/harness-ui/package.json +38 -0
  258. package/vendor/harness-ui/src/acp-agent.mjs +350 -0
  259. package/vendor/harness-ui/src/agent-service.mjs +2188 -0
  260. package/vendor/harness-ui/src/agui-events.mjs +452 -0
  261. package/vendor/harness-ui/src/ambiente-solo-server.mjs +121 -0
  262. package/vendor/harness-ui/src/artifact-store.mjs +39 -0
  263. package/vendor/harness-ui/src/assistenza.mjs +123 -0
  264. package/vendor/harness-ui/src/automation-scheduler.mjs +69 -0
  265. package/vendor/harness-ui/src/automation-store.mjs +145 -0
  266. package/vendor/harness-ui/src/browser-annota.mjs +639 -0
  267. package/vendor/harness-ui/src/browser-frame.mjs +211 -0
  268. package/vendor/harness-ui/src/browser-proxy-universale.mjs +519 -0
  269. package/vendor/harness-ui/src/browser-proxy.mjs +87 -0
  270. package/vendor/harness-ui/src/browser-sessione-viva.mjs +329 -0
  271. package/vendor/harness-ui/src/browser-stream.mjs +445 -0
  272. package/vendor/harness-ui/src/browser-vivo.mjs +694 -0
  273. package/vendor/harness-ui/src/chat-image-attachments.mjs +72 -0
  274. package/vendor/harness-ui/src/config.mjs +697 -0
  275. package/vendor/harness-ui/src/contesto-del-progetto.mjs +385 -0
  276. package/vendor/harness-ui/src/context-asset-adapter.mjs +72 -0
  277. package/vendor/harness-ui/src/context-desktop-service.mjs +253 -0
  278. package/vendor/harness-ui/src/context-embedding-runtime.mjs +252 -0
  279. package/vendor/harness-ui/src/context-inference-scheduler.mjs +81 -0
  280. package/vendor/harness-ui/src/context-native-compaction.mjs +75 -0
  281. package/vendor/harness-ui/src/context-provider-adapter.mjs +141 -0
  282. package/vendor/harness-ui/src/context-runtime.mjs +118 -0
  283. package/vendor/harness-ui/src/context-token-counters.mjs +184 -0
  284. package/vendor/harness-ui/src/context-tool-catalog.mjs +86 -0
  285. package/vendor/harness-ui/src/context-tool-output.mjs +72 -0
  286. package/vendor/harness-ui/src/costo-elenco.mjs +252 -0
  287. package/vendor/harness-ui/src/custom-task.mjs +171 -0
  288. package/vendor/harness-ui/src/doctor.mjs +142 -0
  289. package/vendor/harness-ui/src/document-filename.mjs +97 -0
  290. package/vendor/harness-ui/src/document-generator.mjs +493 -0
  291. package/vendor/harness-ui/src/document-report.mjs +331 -0
  292. package/vendor/harness-ui/src/duckduckgo-search.mjs +155 -0
  293. package/vendor/harness-ui/src/elenco-profondo.mjs +337 -0
  294. package/vendor/harness-ui/src/favicon-proxy.mjs +113 -0
  295. package/vendor/harness-ui/src/forge-contract.mjs +221 -0
  296. package/vendor/harness-ui/src/frequent-dirs.mjs +134 -0
  297. package/vendor/harness-ui/src/generated-image-store.mjs +147 -0
  298. package/vendor/harness-ui/src/generation-idle.mjs +332 -0
  299. package/vendor/harness-ui/src/gguf-header.mjs +207 -0
  300. package/vendor/harness-ui/src/git-service.mjs +626 -0
  301. package/vendor/harness-ui/src/gitignore-elenco.mjs +604 -0
  302. package/vendor/harness-ui/src/harness-receipt-keypair.mjs +207 -0
  303. package/vendor/harness-ui/src/hf-direct-transfer.mjs +170 -0
  304. package/vendor/harness-ui/src/hf-hub-client.mjs +106 -0
  305. package/vendor/harness-ui/src/hf-image-proxy.mjs +105 -0
  306. package/vendor/harness-ui/src/hf-model-transfer.mjs +245 -0
  307. package/vendor/harness-ui/src/hook-registry.mjs +186 -0
  308. package/vendor/harness-ui/src/http-app.mjs +6259 -0
  309. package/vendor/harness-ui/src/http-lifecycle.mjs +132 -0
  310. package/vendor/harness-ui/src/id-archivio.mjs +27 -0
  311. package/vendor/harness-ui/src/image-generator.mjs +143 -0
  312. package/vendor/harness-ui/src/istruzioni-di-progetto.mjs +234 -0
  313. package/vendor/harness-ui/src/kernel/dist/kernelPerIlBanco.js +518 -0
  314. package/vendor/harness-ui/src/kernel/talosHarness.mjs +10437 -0
  315. package/vendor/harness-ui/src/library-policy-store.mjs +175 -0
  316. package/vendor/harness-ui/src/library-store.mjs +652 -0
  317. package/vendor/harness-ui/src/llama-server-supervisor.mjs +629 -0
  318. package/vendor/harness-ui/src/local-model-store.mjs +339 -0
  319. package/vendor/harness-ui/src/local-runtime-contract.mjs +66 -0
  320. package/vendor/harness-ui/src/local-runtime-events.mjs +44 -0
  321. package/vendor/harness-ui/src/local-runtime-llama-server.mjs +244 -0
  322. package/vendor/harness-ui/src/local-runtime-probe.mjs +401 -0
  323. package/vendor/harness-ui/src/machine-capacity.mjs +66 -0
  324. package/vendor/harness-ui/src/mappa-cartelle.mjs +491 -0
  325. package/vendor/harness-ui/src/mcp-client.mjs +98 -0
  326. package/vendor/harness-ui/src/mcp-registry.mjs +157 -0
  327. package/vendor/harness-ui/src/mcp-session.mjs +177 -0
  328. package/vendor/harness-ui/src/memory-store.mjs +227 -0
  329. package/vendor/harness-ui/src/model-catalog-models-dev.mjs +276 -0
  330. package/vendor/harness-ui/src/model-catalog.mjs +129 -0
  331. package/vendor/harness-ui/src/model-destination.mjs +189 -0
  332. package/vendor/harness-ui/src/modifica-ancorata.mjs +177 -0
  333. package/vendor/harness-ui/src/native-provider-adapter.mjs +205 -0
  334. package/vendor/harness-ui/src/notes-store.mjs +250 -0
  335. package/vendor/harness-ui/src/openai-compatible-runtime.mjs +428 -0
  336. package/vendor/harness-ui/src/openrouter-oauth.mjs +339 -0
  337. package/vendor/harness-ui/src/path-policy.mjs +442 -0
  338. package/vendor/harness-ui/src/plugin-registry.mjs +780 -0
  339. package/vendor/harness-ui/src/plugin-session.mjs +180 -0
  340. package/vendor/harness-ui/src/process-policy.mjs +345 -0
  341. package/vendor/harness-ui/src/prompt-enhancer-provider.mjs +94 -0
  342. package/vendor/harness-ui/src/provider-auth-cloud.mjs +95 -0
  343. package/vendor/harness-ui/src/provider-credential-store.mjs +541 -0
  344. package/vendor/harness-ui/src/provider-probe.mjs +582 -0
  345. package/vendor/harness-ui/src/provider-registry.mjs +1633 -0
  346. package/vendor/harness-ui/src/pty-terminal.mjs +312 -0
  347. package/vendor/harness-ui/src/public-problem.mjs +109 -0
  348. package/vendor/harness-ui/src/research/card.mjs +235 -0
  349. package/vendor/harness-ui/src/research/citations.mjs +142 -0
  350. package/vendor/harness-ui/src/research/collector.mjs +275 -0
  351. package/vendor/harness-ui/src/research/deposito-a-pezzi.mjs +139 -0
  352. package/vendor/harness-ui/src/research/dossier.mjs +114 -0
  353. package/vendor/harness-ui/src/research/esportazioni.mjs +560 -0
  354. package/vendor/harness-ui/src/research/fetch-cache.mjs +465 -0
  355. package/vendor/harness-ui/src/research/fidelity.mjs +122 -0
  356. package/vendor/harness-ui/src/research/independence.mjs +159 -0
  357. package/vendor/harness-ui/src/research/ledger.mjs +166 -0
  358. package/vendor/harness-ui/src/research/markdown-server.mjs +565 -0
  359. package/vendor/harness-ui/src/research/narration.mjs +181 -0
  360. package/vendor/harness-ui/src/research/open-cards.mjs +131 -0
  361. package/vendor/harness-ui/src/research/opposing.mjs +305 -0
  362. package/vendor/harness-ui/src/research/outline.mjs +111 -0
  363. package/vendor/harness-ui/src/research/page-budget.mjs +209 -0
  364. package/vendor/harness-ui/src/research/pdf.mjs +291 -0
  365. package/vendor/harness-ui/src/research/plan.mjs +301 -0
  366. package/vendor/harness-ui/src/research/raccolta-viva.mjs +452 -0
  367. package/vendor/harness-ui/src/research/recheck-document.mjs +69 -0
  368. package/vendor/harness-ui/src/research/recheck-history.mjs +192 -0
  369. package/vendor/harness-ui/src/research/recheck.mjs +194 -0
  370. package/vendor/harness-ui/src/research/report.mjs +203 -0
  371. package/vendor/harness-ui/src/research/run.mjs +527 -0
  372. package/vendor/harness-ui/src/research/synthesis.mjs +318 -0
  373. package/vendor/harness-ui/src/research/verification.mjs +572 -0
  374. package/vendor/harness-ui/src/research-orchestrator.mjs +2679 -0
  375. package/vendor/harness-ui/src/research-store.mjs +1133 -0
  376. package/vendor/harness-ui/src/runtime-build-manifest.mjs +26 -0
  377. package/vendor/harness-ui/src/runtime-contract.mjs +59 -0
  378. package/vendor/harness-ui/src/runtime-owner-adapter.mjs +1348 -0
  379. package/vendor/harness-ui/src/runtime-owner-contract.mjs +32 -0
  380. package/vendor/harness-ui/src/scheda-di-lavoro.mjs +249 -0
  381. package/vendor/harness-ui/src/search-source-store.mjs +172 -0
  382. package/vendor/harness-ui/src/session-registry.mjs +6095 -0
  383. package/vendor/harness-ui/src/session-store.mjs +220 -0
  384. package/vendor/harness-ui/src/sessione-pronta.mjs +73 -0
  385. package/vendor/harness-ui/src/setup-stato.mjs +31 -0
  386. package/vendor/harness-ui/src/sezioni-istruzioni.mjs +204 -0
  387. package/vendor/harness-ui/src/skill-registry.mjs +120 -0
  388. package/vendor/harness-ui/src/sse-replay-coalescente.mjs +0 -0
  389. package/vendor/harness-ui/src/static-files.mjs +96 -0
  390. package/vendor/harness-ui/src/stream-partition.mjs +123 -0
  391. package/vendor/harness-ui/src/subagent-orchestrator.mjs +453 -0
  392. package/vendor/harness-ui/src/task-catalog.mjs +65 -0
  393. package/vendor/harness-ui/src/tasks-store.mjs +220 -0
  394. package/vendor/harness-ui/src/terminal-registry.mjs +312 -0
  395. package/vendor/harness-ui/src/terminal-ws.mjs +170 -0
  396. package/vendor/harness-ui/src/tool-forge-store.mjs +299 -0
  397. package/vendor/harness-ui/src/tool-schema-normalize.mjs +100 -0
  398. package/vendor/harness-ui/src/usage-cache.mjs +315 -0
  399. package/vendor/harness-ui/src/workspace-browser.mjs +213 -0
  400. package/vendor/harness-ui/src/workspace-context.mjs +124 -0
  401. package/vendor/harness-ui/src/workspace-disk.mjs +62 -0
  402. package/vendor/harness-ui/src/workspace-files.mjs +589 -0
  403. package/vendor/harness-ui/src/workspace-info.mjs +189 -0
  404. package/vendor/harness-ui/src/workspace-launch-store.mjs +150 -0
  405. package/vendor/harness-ui/src/workspace-tree.mjs +67 -0
  406. package/vendor/harness-ui/src/workspace-watcher.mjs +161 -0
  407. package/vendor/manifest.json +170 -0
@@ -0,0 +1,395 @@
1
+ import { t } from "../i18n/index.js";
2
+ import { randomUUID } from 'node:crypto';
3
+ import path from 'node:path';
4
+ import { TalosError } from "../errors.js";
5
+ import { TOOL_OUTPUT_LIMIT, cutToolOutput, hasKernelCutMarker, replaceKernelCutMarker } from "./output-store.js";
6
+ /*
7
+ * ⭐⭐⭐ B1 slice 8 — IL COMANDO SCRITTO DALLA PERSONA PASSA DAL BROKER, e lo DICE.
8
+ *
9
+ * Questa e' l'unica implementazione nuova della corsia: un adattatore che si infila nel seam che il
10
+ * kernel espone GIA' — `eseguiComandoDiretto({eseguiComandoSandboxatoFn})` in
11
+ * `harness-ui/src/agent-service.mjs` (L1975) — e che quindi eredita, senza riscriverli, il
12
+ * vocabolario di eventi, l'accorpamento dei pezzi e la cucitura nella cronologia. (Il tracciamento
13
+ * della cartella di lavoro NO: dal round 5 della fetta 12 il ramo brokerato non appende la coda della
14
+ * cartella — vedi sotto.)
15
+ *
16
+ * ⛔ La firma e' quella POSIZIONALE del kernel (`eseguiComandoSandboxato(comando, cartella, opzioni)`),
17
+ * non una nuova: il CLI si conforma al kernel, mai il contrario.
18
+ * ⛔ `harness-ui/` si LEGGE e non si scrive: la regola di troncamento (`uscitaUtile`) e l'esecutore di
19
+ * ripiego arrivano dal kernel per iniezione. `staccaCartellaFinale` e `codaCheStampaLaCartella`
20
+ * restano nel contratto degli aiutanti perche' il kernel li espone, ma il ramo brokerato non li usa.
21
+ */
22
+ /** ⛔ I due codici di uscita documentati dal kernel: 124 = tempo scaduto, 130 = 128 + SIGINT. */
23
+ export const KERNEL_EXIT = { timeout: 124, stoppedOnRequest: 130 };
24
+ /*
25
+ * ⭐⭐⭐ B1 slice 12, round 5 — SUL RAMO BROKERATO NON SI APPENDE NIENTE AL COMANDO.
26
+ *
27
+ * Tre round di fila hanno ricostruito il codice d'uscita dopo la coda della cartella, e ognuno ha
28
+ * aperto un buco nel codice d'uscita:
29
+ * · round 2, marcatore stampato: un'ultima riga senza a-capo lo incollava e la persona leggeva
30
+ * «exit 0» col token; un comando poteva stamparne uno e falsificare il codice nei due versi;
31
+ * · round 4, stato del processo via `call set` / `call exit`: DENTRO la sandbox MXC quei due nomi si
32
+ * risolvono in un `set.bat`/`set.cmd`/`exit.bat`/`exit.cmd` della cartella di lavoro. Misurato
33
+ * il 17/09/2026 con `findstr /c:zzz talos_absent.txt` (vero: 1): cmd dell'host 1, sandbox semplice
34
+ * 1, ramo brokerato **0** con quei file presenti. E per `type mancante & echo ok` il ramo brokerato
35
+ * dava 1 mentre `cmd /c` semplice e il ripiego del kernel davano 0.
36
+ * La coda esisteva solo perche' quella della cartella sovrascrive il codice d'uscita, e la coda della
37
+ * cartella sul ramo cmd NON FUNZIONA comunque (`cartella: null` su cmd, misurato al round 2, sia qui
38
+ * sia nel kernel). Costava onesta' e non comprava niente che funzioni oggi.
39
+ *
40
+ * ⇒ Si esegue `%ComSpec% /d /s /c <comando>` e basta. Il codice che la persona vede e' lo stato
41
+ * d'uscita del processo nella sandbox, riportato da `mxcSandboxedSpawn`; niente viene stampato,
42
+ * letto o tolto che il comando non abbia prodotto da se'.
43
+ * ⛔ COSTO DICHIARATO, NON UNA REGRESSIONE: sul ramo brokerato un `cd` non persiste fra un comando e
44
+ * l'altro (`cartellaFinale` e' sempre null, e il registro tiene la cartella di prima). E' identico a
45
+ * oggi sul ramo cmd, dove la persistenza e' gia' rotta dal parser della cartella del kernel.
46
+ */
47
+ /*
48
+ * ⭐ B1 slice 12, round 2 — UN BROKER CHE NON SI E' POTUTO COSTRUIRE NON E' «NON CONFIGURATO».
49
+ * Chi compone ripiega sull'esecuzione (fail-open) ma deve poterlo DIRE: questo sostituto rifiuta
50
+ * ogni esecuzione con un codice che il ramo di ripiego riconosce, e porta il codice dell'errore
51
+ * vero. Un difetto di contratto (un TypeError) arriva a schermo con il suo nome invece di sparire.
52
+ */
53
+ export const BROKER_CONSTRUCTION_FAILED = 'EXECUTION_BROKER_CONSTRUCTION_FAILED';
54
+ export function createUnbuildableExecutionBroker(cause) {
55
+ const code = typeof cause?.code === 'string' ? String(cause.code) : cause instanceof Error ? cause.name : 'UNKNOWN_ERROR';
56
+ const message = (cause instanceof Error ? cause.message : String(cause)).split(/\r?\n/u)[0].slice(0, 300);
57
+ const detail = `${code}: ${message}`;
58
+ return { async execute(request) { throw new TalosError({ code: BROKER_CONSTRUCTION_FAILED, component: 'execution-broker', retryable: false, hint: detail, traceId: request.id }, cause); } };
59
+ }
60
+ /*
61
+ * The words of the execution row. R2 (gate E1, Q-R2-1): they live in the one dictionary, `src/i18n/en/screen.ts`
62
+ * (`screen.exec.*`); this object keeps the shape its callers use. The `marker` block is NOT screen text: it is a
63
+ * byte-identical copy of kernel constants (gate E2) and never enters the dictionary.
64
+ *
65
+ * ⛔⛔⛔ E la riga `enforcement` NON si accorcia. Misurato il 16/09/2026: una ricerca nel binario di
66
+ * Claude Code per una resa a schermo del suo flag «senza sandbox» torna ZERO, e il suo comando
67
+ * digitato dall'utente gira sempre fuori dall'isolamento senza dirlo; la barra di stato di Hermes,
68
+ * documentata campo per campo, non ha un campo isolamento. Entrambi approvano i comandi in
69
+ * allowlist in silenzio. Questa stringa e' l'unico posto in cui una persona scopre che il suo
70
+ * comando NON era isolato e PERCHE': toglierle la ragione la rende inutile.
71
+ */
72
+ export const EXECUTION_TEXT = {
73
+ isolation: {
74
+ /** Un backend ha eseguito e ha portato le prove: si nomina il backend. */
75
+ sandbox: (backend) => t('screen.exec.isolation.sandbox', { backend }),
76
+ /** Il giro isolato e' finito prima di dire come: non si promette un isolamento che non e' provato. */
77
+ sandboxWithoutEvidence: t('screen.exec.isolation.sandboxWithoutEvidence'),
78
+ host: t('screen.exec.isolation.host'),
79
+ /**
80
+ * R0 lane S, owner decision 1 (review §J.1): the row of a command the PRODUCT wanted in the sandbox and ran on the
81
+ * host. ⛔ Never "secure" or "safe" anywhere on this path (gate E6): MXC itself is "contained", not a boundary.
82
+ */
83
+ hostNotIsolated: t('screen.exec.isolation.hostNotIsolated'),
84
+ wsl2: t('screen.exec.isolation.wsl2'),
85
+ device: t('screen.exec.isolation.device'),
86
+ other: (name) => t('screen.exec.isolation.named', { name }),
87
+ },
88
+ reason: {
89
+ verified: (evidence) => t('screen.exec.reason.verified', { appContainer: t(evidence.appContainer ? 'screen.exec.on' : 'screen.exec.off'), filesystem: evidence.filesystem, network: evidence.network, processTree: evidence.processTree }),
90
+ backendUnavailable: (why) => t('screen.exec.reason.backendUnavailable', { why }),
91
+ brokerNotConfigured: t('screen.exec.reason.brokerNotConfigured'),
92
+ /** The broker exists in this build but could not be BUILT: never the same sentence as «not configured». */
93
+ brokerConstructionFailed: (detail) => t('screen.exec.reason.brokerConstructionFailed', { detail }),
94
+ destinationMobile: t('screen.exec.reason.destinationMobile'),
95
+ destinationWsl2: t('screen.exec.reason.destinationWsl2'),
96
+ platformNotWindows: (platform) => t('screen.exec.reason.platformNotWindows', { platform }),
97
+ timedOut: (ms) => t('screen.exec.reason.timedOut', { seconds: Math.round(ms / 1_000) }),
98
+ stoppedOnRequest: t('screen.exec.reason.stoppedOnRequest'),
99
+ /*
100
+ * ⛔ R0 lane S — the declared host fallback. These rows are shared by the person's `!` commands AND the model's
101
+ * shell tool (M1-E: one executor), so they do not say who typed the command; the approval that precedes the
102
+ * run is the permission engine's, not this executor's.
103
+ */
104
+ sandboxUnverified: (why) => t('screen.exec.reason.sandboxUnverified', { why }),
105
+ brokerUnbuildable: (detail) => t('screen.exec.reason.brokerUnbuildable', { detail }),
106
+ hostPlatform: (platform) => t('screen.exec.reason.hostPlatform', { platform }),
107
+ hostNoBroker: t('screen.exec.reason.hostNoBroker'),
108
+ },
109
+ /*
110
+ * ⛔ Le tre marche del kernel, riprodotte LETTERA PER LETTERA perche' il kernel non le esporta
111
+ * (`MARCA_FERMATO_MENTRE_GIRAVA` e `USCITA_FERMATO_SU_RICHIESTA` sono `const` di modulo, non
112
+ * `export`). Una prova legge il sorgente del kernel e verifica che siano ancora identiche: e'
113
+ * l'unico modo per accorgersi di una deriva, visto che la copia e' inevitabile.
114
+ */
115
+ marker: {
116
+ stoppedOnRequest: '⛔ Fermato su richiesta:',
117
+ stoppedOnRequestSentence: 'il comando e stato interrotto mentre girava.',
118
+ timedOut: (ms) => `⛔ Fermato allo scadere dei ${Math.round(ms / 1_000)} secondi: non ha finito da solo.`,
119
+ },
120
+ /** ⛔ Un comando senza sessione si RIFIUTA a voce alta: farlo sparire e' peggio che negarlo. */
121
+ shellSessionRequired: t('screen.exec.shellSessionRequired'),
122
+ };
123
+ /** The most of a fallback command's streamed output kept for its file (the kernel itself holds 160,000 characters). */
124
+ const CAPTURE_MAX = 8_000_000;
125
+ function isolationForKernelEnforcement(value) {
126
+ if (value === 'wsl2')
127
+ return EXECUTION_TEXT.isolation.wsl2;
128
+ if (value === 'adb-shell-on-device')
129
+ return EXECUTION_TEXT.isolation.device;
130
+ if (value === 'none' || !value)
131
+ return EXECUTION_TEXT.isolation.host;
132
+ return EXECUTION_TEXT.isolation.other(value);
133
+ }
134
+ function annotate(isolation, reason) { return `${isolation} — ${reason}`; }
135
+ export function createBrokeredKernelExecutor(options) {
136
+ const platform = options.platform ?? process.platform;
137
+ /*
138
+ * ⛔ LA RETE SEGUE IL MOTORE DEI PERMESSI, non una costante inventata qui. Il motore di oggi
139
+ * (`cli/src/security/permission-engine.ts`) non ha ancora una regola che parli della rete di un
140
+ * sottoprocesso: `WebFetch` riguarda le richieste del MODELLO, non quelle che un comando apre
141
+ * per conto suo. ⇒ Il default e' il valore che CONSERVA il comportamento di oggi (il kernel
142
+ * esegue senza alcun confine di rete), e il buco e' dichiarato nel rapporto invece di essere
143
+ * colmato inventando un motore nuovo. Chi compone puo' gia' passare `network` quando il motore
144
+ * imparera' a decidere deny/ask/allow.
145
+ */
146
+ const network = options.network ?? 'internet-client';
147
+ /*
148
+ * ⛔ `restricted-process` e non `windows-sandbox`: con `windows-sandbox` il broker LANCIA
149
+ * `SANDBOX_REQUIRED_UNAVAILABLE` (execution-broker.ts L85) invece di declinare, e un backend
150
+ * assente diventerebbe un errore duro invece del ripiego che lo scenario 2 pretende. Con
151
+ * `restricted-process` il broker prende comunque `windows-sandbox` se ce l'ha (L82-84) e
152
+ * declina con `EXECUTION_BACKEND_UNAVAILABLE` quando non ha niente (L87).
153
+ */
154
+ const requiredEnforcement = options.requiredEnforcement ?? 'restricted-process';
155
+ const requireVerifiedIsolation = options.requireVerifiedIsolation ?? false;
156
+ /*
157
+ * ⭐⭐⭐ R0 lane S — THE DECLARED HOST FALLBACK (owner decision 1, 2026-09-23; review D-01/E-01).
158
+ * F16 (`dd9620d9b`) made the product refuse every command whose isolation could not be proven, and on a host where
159
+ * the probe itself was broken that meant NO command ran at all. The product still ASKS for the Windows sandbox
160
+ * (`requiredEnforcement:'windows-sandbox'`, network denied), still never accepts a weaker sandbox in its place, and
161
+ * still lets a sandbox that exists and fails propagate (below). What changes: when no verified sandbox exists, the
162
+ * command runs through the kernel's own executor on the host, and the row says so — `⛶ host · not isolated` and
163
+ * the backend's own reason. Claude Code does the same by default ("shows a warning and runs commands without
164
+ * sandboxing", code.claude.com/docs/en/sandboxing, v2.1.271, 2026-09-14); the approval before it is the permission
165
+ * engine's (gate §0.2 rule 2).
166
+ */
167
+ const declaredHost = !requireVerifiedIsolation && requiredEnforcement === 'windows-sandbox';
168
+ const timeoutMs = options.timeoutMs ?? 120_000;
169
+ const newId = options.newId ?? (() => randomUUID());
170
+ let loading = null;
171
+ const loadKernel = () => (loading ??= options.kernel());
172
+ /*
173
+ * ⛔ CHI NON PUO' ANDARE NEL BROKER, E PERCHE'. Un AppContainer non puo' ospitare una `adb shell`
174
+ * ne' una distribuzione WSL2: mandarceli sarebbe la cura di una malattia che non esiste, e
175
+ * cambierebbe in silenzio DOVE gira il comando — esattamente il difetto che D-10F ha chiuso.
176
+ */
177
+ function declineReason(opts) {
178
+ if (opts.mobile === true)
179
+ return EXECUTION_TEXT.reason.destinationMobile;
180
+ if (opts.dove === 'wsl2')
181
+ return EXECUTION_TEXT.reason.destinationWsl2;
182
+ if (platform !== 'win32')
183
+ return declaredHost ? EXECUTION_TEXT.reason.hostPlatform(String(platform)) : EXECUTION_TEXT.reason.platformNotWindows(String(platform));
184
+ if (!options.broker)
185
+ return declaredHost ? EXECUTION_TEXT.reason.hostNoBroker : EXECUTION_TEXT.reason.brokerNotConfigured;
186
+ return null;
187
+ }
188
+ async function fallback(helpers, comando, cartella, opts, reason) {
189
+ /*
190
+ * R5a lane R, S6: the kernel's executor cuts its output itself (`uscitaUtile`) and returns only the cut; every piece it
191
+ * reads is also handed to `onPezzo` as it arrives (talosHarness.mjs `eseguiComandoSandboxato`, D-10B). The pieces are
192
+ * kept here, in arrival order, so a cut output can still be saved whole; the caller's listener still gets every piece.
193
+ */
194
+ const keep = options.keepFullOutput;
195
+ let captured = '';
196
+ let capturedAll = true;
197
+ const listener = opts.onPezzo;
198
+ const withCapture = keep ? { ...opts, onPezzo: (piece) => {
199
+ if (captured.length < CAPTURE_MAX)
200
+ captured += piece.testo;
201
+ else
202
+ capturedAll = false;
203
+ listener?.(piece);
204
+ } } : opts;
205
+ const kernelResult = await helpers.eseguiComandoSandboxato(comando, cartella, withCapture);
206
+ let result = kernelResult;
207
+ if (keep && hasKernelCutMarker(String(kernelResult.testo ?? ''))) {
208
+ const full = capturedAll ? captured : captured.slice(0, CAPTURE_MAX);
209
+ let saved = null;
210
+ try {
211
+ saved = full ? await keep(full) : null;
212
+ }
213
+ catch {
214
+ saved = null;
215
+ }
216
+ result = { ...kernelResult, testo: replaceKernelCutMarker(String(kernelResult.testo), saved) };
217
+ }
218
+ const kernelEnforcement = String(result.enforcement ?? '');
219
+ /* ⛔ Only a plain host run takes the declared label: WSL2 and the device keep naming where they ran. */
220
+ const isolation = declaredHost && (kernelEnforcement === 'none' || !kernelEnforcement) ? EXECUTION_TEXT.isolation.hostNotIsolated : isolationForKernelEnforcement(kernelEnforcement);
221
+ return { ...result, enforcement: annotate(isolation, reason) };
222
+ }
223
+ /* R5a lane R, S6: the same head and tail as the kernel's cut, and with `keepFullOutput` the English marker naming the file. */
224
+ async function cutOutput(helpers, full) {
225
+ const keep = options.keepFullOutput;
226
+ if (!keep)
227
+ return helpers.uscitaUtile(full, 4_000, 0.25);
228
+ if (full.length <= TOOL_OUTPUT_LIMIT)
229
+ return full;
230
+ let saved = null;
231
+ try {
232
+ saved = await keep(full);
233
+ }
234
+ catch {
235
+ saved = null;
236
+ }
237
+ return cutToolOutput(full, saved);
238
+ }
239
+ return async function brokeredKernelExecutor(comando, cartella, opts = {}) {
240
+ const helpers = await loadKernel();
241
+ const declined = declineReason(opts);
242
+ if (declined !== null) {
243
+ if (requireVerifiedIsolation) {
244
+ let why = t('screen.exec.why.unverified');
245
+ if (opts.mobile === true)
246
+ why = t('screen.exec.why.mobile');
247
+ else if (opts.dove === 'wsl2')
248
+ why = t('screen.exec.why.wsl2');
249
+ else if (platform !== 'win32')
250
+ why = t('screen.exec.why.platform', { platform: String(platform) });
251
+ else if (!options.broker)
252
+ why = t('screen.exec.why.noBroker');
253
+ throw new TalosError({
254
+ code: 'SANDBOX_REQUIRED_UNAVAILABLE',
255
+ component: 'execution-broker',
256
+ retryable: false,
257
+ hint: t('screen.exec.why.notRun', { why }),
258
+ traceId: newId(),
259
+ });
260
+ }
261
+ return fallback(helpers, comando, cartella, opts, declined);
262
+ }
263
+ const broker = options.broker;
264
+ /*
265
+ * ⛔ Round 5: nessuna coda, nemmeno con `tracciaCartella`. Vedi il blocco in testa al file.
266
+ *
267
+ * ⛔ Invocazione NON INTERATTIVA, identica a quella che Node stesso costruisce per
268
+ * `spawn(comando,{shell:true})` su Windows: `%ComSpec% /d /s /c <comando>`. `/d` spegne gli
269
+ * AutoRun del registro, che dentro un isolamento sarebbero un ingresso non dichiarato.
270
+ * ⛔ La RADICE DEL VOLUME in sola lettura e' OBBLIGATORIA, non una comodita': upstream
271
+ * microsoft/mxc#1109 (SDK 0.8.0) dimostra che una concessione in scrittura su una cartella di
272
+ * profilo utente e' inutilizzabile se la radice del volume non sta anche fra le sole letture.
273
+ */
274
+ const request = {
275
+ id: newId(),
276
+ executable: options.shellExecutable ?? process.env['ComSpec'] ?? 'cmd.exe',
277
+ args: ['/d', '/s', '/c', comando],
278
+ cwd: cartella,
279
+ readWritePaths: [cartella],
280
+ readOnlyPaths: [path.parse(path.resolve(cartella)).root],
281
+ network,
282
+ requiredEnforcement,
283
+ timeoutMs,
284
+ ...(opts.segnaleStop ? { signal: opts.segnaleStop } : {}),
285
+ };
286
+ /*
287
+ * ⛔⛔ I DUE FERMI DEL KERNEL NON SONO RIPRODUCIBILI ATTRAVERSO LA FORMA DEL BROKER: il contratto
288
+ * di risultato di un backend porta `exitCode/stdout/stderr/applied` e nient'altro, quindi
289
+ * «ucciso dal tempo» e «fermato da te» non tornano indietro. Si ricostruiscono QUI, con gli
290
+ * stessi codici (124 / 130) e le stesse marche del kernel. Dichiarato, non nascosto.
291
+ */
292
+ const work = broker.execute(request).then((value) => ({ kind: 'ok', value }), (error) => ({ kind: 'error', error }));
293
+ let timer;
294
+ const expired = new Promise((resolve) => { timer = setTimeout(() => resolve({ kind: 'timeout' }), timeoutMs); });
295
+ const stopped = new Promise((resolve) => {
296
+ const signal = opts.segnaleStop;
297
+ if (!signal)
298
+ return;
299
+ if (signal.aborted) {
300
+ resolve({ kind: 'stopped' });
301
+ return;
302
+ }
303
+ signal.addEventListener('abort', () => resolve({ kind: 'stopped' }), { once: true });
304
+ });
305
+ let outcome;
306
+ try {
307
+ outcome = await Promise.race([work, expired, stopped]);
308
+ }
309
+ finally {
310
+ if (timer)
311
+ clearTimeout(timer);
312
+ }
313
+ if (outcome.kind === 'timeout')
314
+ return {
315
+ codice: KERNEL_EXIT.timeout,
316
+ fermatoDalTempo: true,
317
+ testo: `\n\n${EXECUTION_TEXT.marker.timedOut(timeoutMs)}`.trim(),
318
+ enforcement: annotate(EXECUTION_TEXT.isolation.sandboxWithoutEvidence, EXECUTION_TEXT.reason.timedOut(timeoutMs)),
319
+ cartellaFinale: null,
320
+ };
321
+ if (outcome.kind === 'stopped')
322
+ return {
323
+ codice: KERNEL_EXIT.stoppedOnRequest,
324
+ fermatoSuRichiesta: true,
325
+ testo: `\n\n${EXECUTION_TEXT.marker.stoppedOnRequest} ${EXECUTION_TEXT.marker.stoppedOnRequestSentence}`.trim(),
326
+ enforcement: annotate(EXECUTION_TEXT.isolation.sandboxWithoutEvidence, EXECUTION_TEXT.reason.stoppedOnRequest),
327
+ cartellaFinale: null,
328
+ };
329
+ if (outcome.kind === 'error') {
330
+ const failure = outcome.error;
331
+ /*
332
+ * ⛔⛔⛔ UN SOLO ERRORE E' CONDIZIONE DI RIPIEGO: «non esiste nessun backend». Tutto il resto —
333
+ * e in particolare `SANDBOX_EVIDENCE_MISMATCH` — RISALE. Una sandbox che esiste e ha
334
+ * RIFIUTATO non si aggira in silenzio: sarebbe la peggiore delle bugie, perche' il comando
335
+ * girerebbe fuori dall'isolamento proprio nel caso in cui l'isolamento aveva qualcosa da dire.
336
+ */
337
+ /* ⛔ Il broker non si e' potuto COSTRUIRE: nessun isolamento esiste, quindi si esegue fuori, e
338
+ la riga dice perche' con il codice dell'errore — mai «non configurato in questa build». */
339
+ if (failure?.code === BROKER_CONSTRUCTION_FAILED) {
340
+ if (requireVerifiedIsolation)
341
+ throw outcome.error;
342
+ const detail = failure.hint ?? t('screen.exec.why.noDetail');
343
+ return fallback(helpers, comando, cartella, opts, declaredHost ? EXECUTION_TEXT.reason.brokerUnbuildable(detail) : EXECUTION_TEXT.reason.brokerConstructionFailed(detail));
344
+ }
345
+ /*
346
+ * ⛔ R0 lane S: `SANDBOX_REQUIRED_UNAVAILABLE` from the BROKER is the same fact as EXECUTION_BACKEND_UNAVAILABLE —
347
+ * no verified backend exists — for a request that required the Windows sandbox (execution-broker.ts). Its
348
+ * cause carries the backend's own reason (for example the probe's). Everything else still propagates:
349
+ * EXECUTION_BACKEND_FAILED, SANDBOX_EVIDENCE_MISMATCH, SANDBOX_PATH_INVALID, SANDBOX_CWD_NOT_GRANTED.
350
+ */
351
+ if (declaredHost && failure?.code === 'SANDBOX_REQUIRED_UNAVAILABLE') {
352
+ const cause = outcome.error?.cause;
353
+ const why = cause instanceof Error && cause.message ? cause.message : failure.hint ?? t('screen.exec.why.noBackend');
354
+ return fallback(helpers, comando, cartella, opts, EXECUTION_TEXT.reason.sandboxUnverified(why));
355
+ }
356
+ if (failure?.code !== 'EXECUTION_BACKEND_UNAVAILABLE')
357
+ throw outcome.error;
358
+ if (requireVerifiedIsolation)
359
+ throw outcome.error;
360
+ const why = failure.hint ?? failure.message ?? t('screen.exec.why.noEnforcement');
361
+ return fallback(helpers, comando, cartella, opts, declaredHost ? EXECUTION_TEXT.reason.sandboxUnverified(why) : EXECUTION_TEXT.reason.backendUnavailable(why));
362
+ }
363
+ const { exitCode, stdout, stderr, evidence } = outcome.value;
364
+ /*
365
+ * ⛔ Round 5: nessuna coda, quindi niente da staccare. Stdout e stderr arrivano come il comando li ha
366
+ * scritti — anche se contengono qualcosa che somiglia a un marcatore: e' uscita del comando.
367
+ * ⛔ Round 2, ancora vero: stderr non si perde mai, e non si unisce a stdout prima di un taglio.
368
+ */
369
+ const out = String(stdout ?? '').replace(/[\r\n]+$/u, '');
370
+ const err = String(stderr ?? '').replace(/[\r\n]+$/u, '');
371
+ /*
372
+ * ⛔ DEBITO B1.10, DICHIARATO: sul ramo brokerato l'uscita dal vivo NON esiste — il contratto di
373
+ * risultato del backend non ha un canale di streaming. Si emette il testo intero UNA volta
374
+ * prima di tornare, cosi' chi ascolta vede qualcosa; il ramo di ripiego continua a trasmettere
375
+ * a pezzi come sempre.
376
+ * ⛔ E per la stessa ragione l'ORDINE fra i due flussi non esiste qui: prima stdout, poi stderr.
377
+ * Il ripiego del kernel li intreccia nell'ordine d'arrivo; questo contratto non lo permette.
378
+ */
379
+ if (out)
380
+ opts.onPezzo?.({ flusso: 'fuori', testo: out });
381
+ if (err)
382
+ opts.onPezzo?.({ flusso: 'errori', testo: out ? `\n${err}` : err });
383
+ return {
384
+ /* ⛔ Lo stato d'uscita del PROCESSO `cmd /d /s /c <comando>`, lo stesso di `cmd /c` semplice. Mai un
385
+ numero letto dal testo. */
386
+ codice: exitCode,
387
+ /* ⛔ Il taglio e' quello del KERNEL, non una seconda regola: persona e modello devono leggere
388
+ lo stesso testo sotto lo stesso nome. */
389
+ testo: await cutOutput(helpers, `${out}\n${err}`.trim()),
390
+ enforcement: annotate(EXECUTION_TEXT.isolation.sandbox(evidence.backend), EXECUTION_TEXT.reason.verified(evidence)),
391
+ /* ⛔ Nessuna coda, nessuna cartella finale: il registro tiene quella di prima. */
392
+ cartellaFinale: null,
393
+ };
394
+ };
395
+ }
@@ -0,0 +1,69 @@
1
+ /*
2
+ * P12 (owner, 2026-09-25, "quando riprendo sessione mi dà CTX_HISTORY_DIVERGED"). Measured on a copy of the owner's
3
+ * session and Context Engine archive: the archive held 10 messages, the last an assistant message with a tool call and NO
4
+ * result (12:16:45, the turn interrupted there); the session's own history had dropped that unanswered call, as it must (a
5
+ * call without its result is not sent back to a model), and gone on with the next person's messages. From then on the
6
+ * archive was no longer a prefix of the history, `syncOriginals` (harness-ui/src/context-desktop-service.mjs:202) refused
7
+ * every turn, and the session could not be resumed.
8
+ * Where the unanswered call came from: the kernel archives the whole history at several points of a turn, among them
9
+ * right after the model's answer, BEFORE the tools run (talosHarness.mjs `capture` reason 'response'). The cure, on the
10
+ * CLI's side of the bridge (the kernel and the service are not edited): `capture` never archives an assistant message
11
+ * whose tool calls do not all have a result yet, nor the partial results after it. The next capture, once the results
12
+ * are in, archives the exchange whole; if the turn stops first, nothing unanswered was archived. The archive stays a
13
+ * prefix of the history in both cases.
14
+ */
15
+ /** The longest prefix of `messages` that does not end inside an unanswered tool exchange. */
16
+ export function archivableHistory(messages) {
17
+ const rows = messages;
18
+ for (let index = rows.length - 1; index >= 0; index--) {
19
+ const message = rows[index];
20
+ if (message?.role !== 'assistant' || !Array.isArray(message.tool_calls) || message.tool_calls.length === 0)
21
+ continue;
22
+ const wanted = new Set(message.tool_calls.map((call) => call?.id).filter((id) => typeof id === 'string' && id));
23
+ for (let later = index + 1; later < rows.length && rows[later]?.role === 'tool'; later++)
24
+ wanted.delete(rows[later].tool_call_id);
25
+ /* The last tool exchange decides: complete, the whole history is archivable; unanswered, it and what follows wait. */
26
+ return wanted.size === 0 ? [...messages] : messages.slice(0, index);
27
+ }
28
+ return [...messages];
29
+ }
30
+ /*
31
+ * The same measurement found a race: `syncOriginals` reads the session revision, then appends with it
32
+ * (context-desktop-service.mjs:199-204), while a Context Engine compaction running in the background can commit a version
33
+ * in between (outside that session's queue). The append is then refused with CTX_STALE_REVISION and the TURN failed
34
+ * (r5a-coord-ce-compaction: 3 of 8 runs once capture waited for whole tool exchanges, 0 of 11 before; the race existed
35
+ * before too, only rarer). A retry is safe: `syncOriginals` rereads the revision and appends only what is missing, and
36
+ * `prepare` recomputes from the archive. So `capture` and `prepare` retry a stale revision, briefly.
37
+ * The shape follows Hermes' SQLite write retry (hermes_state.py:467-489, read 2026-09-26): patience is TIME-based, since
38
+ * "attempt-counted budgets destroyed turns on a healthy store", and each wait is RANDOM (20-150 ms), so two writers that
39
+ * lost the same race do not collide again in step (the "full jitter" of AWS's "Exponential Backoff and Jitter"). The
40
+ * budget is short, like Hermes' wait on a live compression lock: a compaction's commit is one write, and the revision reread
41
+ * after it succeeds; a revision that keeps moving for two seconds is a real conflict, and the error goes on.
42
+ */
43
+ const STALE_PATIENCE_MS = 2_000, STALE_WAIT_MIN_MS = 20, STALE_WAIT_MAX_MS = 150;
44
+ async function retryStale(operation, patienceMs) {
45
+ const deadline = Date.now() + patienceMs;
46
+ for (;;) {
47
+ try {
48
+ return await operation();
49
+ }
50
+ catch (error) {
51
+ const remaining = deadline - Date.now();
52
+ if (error?.code !== 'CTX_STALE_REVISION' || remaining <= 0)
53
+ throw error;
54
+ const wait = STALE_WAIT_MIN_MS + Math.random() * (STALE_WAIT_MAX_MS - STALE_WAIT_MIN_MS);
55
+ await new Promise(resolve => setTimeout(resolve, Math.min(wait, remaining)));
56
+ }
57
+ }
58
+ }
59
+ /** The service's kernel hooks: `capture` archives only whole tool exchanges; `capture` and `prepare` retry a stale revision. */
60
+ export function withArchivableCapture(hooks, { stalePatienceMs = STALE_PATIENCE_MS } = {}) {
61
+ if (!hooks || typeof hooks.capture !== 'function')
62
+ return hooks;
63
+ const capture = hooks.capture, prepare = hooks.prepare;
64
+ return {
65
+ ...hooks,
66
+ capture: (input) => retryStale(() => capture({ ...input, messages: Array.isArray(input?.messages) ? archivableHistory(input.messages) : input?.messages }), stalePatienceMs),
67
+ ...(typeof prepare === 'function' ? { prepare: (input) => retryStale(() => prepare(input), stalePatienceMs) } : {}),
68
+ };
69
+ }
@@ -0,0 +1,76 @@
1
+ const DEFAULT_TRIGGER_RATIO = 0.5;
2
+ function finite(value) { return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : null; }
3
+ function positive(value) { const n = finite(value); return n !== null && n > 0 ? n : null; }
4
+ function ratio(value, fallback = null) { const n = finite(value); return n !== null && n > 0 && n < 1 ? n : fallback; }
5
+ function percent(numerator, denominator) { return Math.round((numerator / denominator) * 1000) / 10; }
6
+ function integer(value) { return Number.isSafeInteger(value) && Number(value) >= 0 ? Number(value) : null; }
7
+ function text(value) { return typeof value === 'string' && value.trim() ? value.trim() : null; }
8
+ export function unavailableContextStatus(sessionId, reason) {
9
+ return {
10
+ schema: 'talos.cli.context-status.v1', sessionId, available: false, reason,
11
+ measurement: null, budget: null,
12
+ autoCompaction: { enabled: true, triggerRatio: DEFAULT_TRIGGER_RATIO, triggerPercent: 50, targetRatio: null, provenance: 'CLI owner policy; active only when Context Engine measurement is available' },
13
+ cache: { promptTokens: null, cachedTokens: null, percent: null, provenance: 'not measured' },
14
+ cost: { usd: null, provenance: 'not reported by runtime' },
15
+ sources: { activeVersionId: null, activeSourceCount: null, summaryCitationCount: null, provenance: 'no measured Context Engine snapshot' },
16
+ };
17
+ }
18
+ export function buildContextStatus({ sessionId, snapshot, sessionUsage }) {
19
+ if (!snapshot || typeof snapshot !== 'object')
20
+ return unavailableContextStatus(sessionId, 'not-measured');
21
+ const revision = integer(snapshot.revision);
22
+ const measured = snapshot.measurement && typeof snapshot.measurement === 'object' ? snapshot.measurement : null;
23
+ const tokens = measured?.tokens && typeof measured.tokens === 'object' ? measured.tokens : null;
24
+ const inputTokens = integer(tokens?.inputTokens), windowTokens = positive(tokens?.windowTokens), responseReserve = integer(tokens?.responseReserve);
25
+ const method = ['runtime', 'provider', 'heuristic'].includes(tokens?.method) ? tokens.method : null;
26
+ const measurement = inputTokens !== null && windowTokens !== null && responseReserve !== null && method ? {
27
+ inputTokens, windowTokens, responseReserve,
28
+ percentOfWindow: percent(inputTokens, windowTokens),
29
+ method, exact: tokens?.exact === true,
30
+ measuredAt: text(measured?.measuredAt),
31
+ revision: integer(measured?.revision),
32
+ stale: revision !== null && integer(measured?.revision) !== revision,
33
+ estimatedMarginTokens: integer(tokens?.estimatedMarginTokens),
34
+ } : null;
35
+ const settings = snapshot.settings && typeof snapshot.settings === 'object' ? snapshot.settings : {};
36
+ const triggerRatio = ratio(settings.triggerRatio, DEFAULT_TRIGGER_RATIO) ?? DEFAULT_TRIGGER_RATIO;
37
+ const targetRatio = ratio(settings.targetRatio, null);
38
+ const promptTokens = integer(sessionUsage?.promptTokens);
39
+ const cachedTokens = integer(sessionUsage?.cachedTokens);
40
+ const cacheMeasured = promptTokens !== null && promptTokens > 0 && cachedTokens !== null && cachedTokens <= promptTokens;
41
+ const active = snapshot.activeVersion && typeof snapshot.activeVersion === 'object' ? snapshot.activeVersion : null;
42
+ const sourceIds = Array.isArray(active?.sourceIds) ? active.sourceIds : null;
43
+ const citations = Array.isArray(active?.summary?.sources) ? active.summary.sources : null;
44
+ const profile = snapshot.cliProfileEvidence && typeof snapshot.cliProfileEvidence === 'object' ? snapshot.cliProfileEvidence : null;
45
+ const profileSource = text(profile?.source);
46
+ const profileDate = text(profile?.date);
47
+ const safetyMarginTokens = measurement ? Math.max(measurement.method === 'heuristic' ? 1024 : 256, Math.ceil(measurement.windowTokens * (measurement.method === 'heuristic' ? 0.15 : 0.05))) : null;
48
+ const inputLimitTokens = measurement && safetyMarginTokens !== null ? Math.max(0, measurement.windowTokens - measurement.responseReserve - safetyMarginTokens) : null;
49
+ const budget = measurement && safetyMarginTokens !== null && inputLimitTokens !== null ? {
50
+ windowTokens: measurement.windowTokens, responseReserve: measurement.responseReserve,
51
+ safetyMarginTokens, inputLimitTokens, triggerTokens: Math.floor(inputLimitTokens * triggerRatio),
52
+ estimatedMarginTokens: measurement.estimatedMarginTokens,
53
+ provenance: (profileSource ? 'model profile: ' + profileSource + (profileDate ? ' (' + profileDate + ')' : '') : measurement.method + ' prepared-request measurement') + '; Context Engine effective-input safety budget',
54
+ } : null;
55
+ return {
56
+ schema: 'talos.cli.context-status.v1', sessionId, available: true, reason: measurement ? null : 'not-measured',
57
+ measurement, budget,
58
+ autoCompaction: {
59
+ enabled: settings.auto === true,
60
+ triggerRatio, triggerPercent: Math.round(triggerRatio * 1000) / 10, targetRatio,
61
+ provenance: 'Context Engine session settings; CLI owner trigger policy is 0.50',
62
+ },
63
+ cache: {
64
+ promptTokens, cachedTokens,
65
+ percent: cacheMeasured ? percent(cachedTokens, promptTokens) : null,
66
+ provenance: cacheMeasured ? 'whole-session measured usage' : 'not measured',
67
+ },
68
+ cost: { usd: null, provenance: 'not reported by runtime' },
69
+ sources: {
70
+ activeVersionId: text(active?.id),
71
+ activeSourceCount: sourceIds ? sourceIds.length : null,
72
+ summaryCitationCount: citations ? citations.length : null,
73
+ provenance: active ? 'Context Engine active version' : 'no active compacted version',
74
+ },
75
+ };
76
+ }