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,96 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+
4
+ const MAX_STATIC_BYTES = 4_194_304;
5
+ /** ⭐ Riconciliazione con la copia mobile (24/8) — vedi harness-ui-due-copie-divergenti.md: stessi 10 file .woff2, stesso font/weight/subset. */
6
+ const FONT_FILES = Object.freeze([
7
+ 'instrument-sans-latin-ext-400-normal.woff2',
8
+ 'instrument-sans-latin-400-normal.woff2',
9
+ 'instrument-sans-latin-ext-500-normal.woff2',
10
+ 'instrument-sans-latin-500-normal.woff2',
11
+ 'instrument-sans-latin-ext-600-normal.woff2',
12
+ 'instrument-sans-latin-600-normal.woff2',
13
+ 'jetbrains-mono-latin-ext-400-normal.woff2',
14
+ 'jetbrains-mono-latin-400-normal.woff2',
15
+ 'jetbrains-mono-latin-ext-500-normal.woff2',
16
+ 'jetbrains-mono-latin-500-normal.woff2',
17
+ ]);
18
+ const STATIC_ASSETS = Object.freeze({
19
+ '/': { file: 'index.html', contentType: 'text/html; charset=utf-8' },
20
+ '/index.html': { file: 'index.html', contentType: 'text/html; charset=utf-8' },
21
+ '/styles.css': { file: 'styles.css', contentType: 'text/css; charset=utf-8' },
22
+ '/app.js': { file: 'app.js', contentType: 'text/javascript; charset=utf-8' },
23
+ /*
24
+ * ⭐⭐⭐ 11/09 — la schermata d'avvio. È un file a parte, e non un pezzo di `app.js`, perché deve
25
+ * arrivare PRIMA del primo disegno: `app.js` è il bundle grosso, cioè proprio il tempo che il
26
+ * velo esiste per coprire.
27
+ * ⛔ Senza questa riga il server risponde **404** e non lo dice a nessuno: il velo resta a schermo
28
+ * per sempre, e sotto c'è la app che nessuno può toccare. Trovato dal vivo, non da un test —
29
+ * la pagina non lanciava un solo errore.
30
+ * ⛔ Questa mappa è cablata apposta: `file` non si costruisce MAI dal `pathname` della richiesta
31
+ * (vedi la nota qui sotto su DEC-053), e una voce in più è il solo modo di aggiungere un asset.
32
+ */
33
+ '/avvio.js': { file: 'avvio.js', contentType: 'text/javascript; charset=utf-8' },
34
+ /*
35
+ * ⭐⭐⭐ 26/8, DEC-053 — MAI PIÙ una copia locale sincronizzata a mano
36
+ * (harness-ui-due-copie-divergenti.md era esattamente questo difetto).
37
+ * publicDir ora È mobile/public/harness-ui/: `talos/brand/` è FRATELLO
38
+ * di `harness-ui/`, non figlio — `../` risale alla radice condivisa
39
+ * `mobile/public/` una volta sola, verso l'UNICO file reale che l'app
40
+ * mobile stessa monta a runtime. `file` qui è un valore CABLATO nel
41
+ * sorgente, mai costruito da `pathname` della richiesta: il `..` non
42
+ * apre un varco di traversal, sceglie solo quale asset fisso servire.
43
+ */
44
+ '/talos/brand/logo-short.svg': { file: 'talos/brand/logo-short.svg', contentType: 'image/svg+xml' },
45
+ '/talos/browser-annota.js': { file: 'talos/browser-annota.js', contentType: 'text/javascript; charset=utf-8' }, // 06/9: l'overlay iniettato dal proxy
46
+ ...Object.fromEntries(FONT_FILES.map((name) => [
47
+ `/fonts/${name}`,
48
+ { file: `fonts/${name}`, contentType: 'font/woff2' },
49
+ ])),
50
+ /*
51
+ * ⭐⭐⭐ 28/8 — Terminale REALE (LEDGER-TERMINALE-REALE.md): xterm.js
52
+ * vendorizzato (mai una CDN, stesso principio dei font sopra). Trovato
53
+ * dalla verifica dal vivo — senza queste tre righe la allowlist
54
+ * rispondeva 404 su tutti e tre i file e la UI mostrava onestamente
55
+ * "xterm.js non caricato" invece di fingersi connessa.
56
+ */
57
+ '/vendor/xterm/xterm.js': { file: 'vendor/xterm/xterm.js', contentType: 'text/javascript; charset=utf-8' },
58
+ '/vendor/xterm/xterm.css': { file: 'vendor/xterm/xterm.css', contentType: 'text/css; charset=utf-8' },
59
+ '/vendor/xterm/addon-fit.js': { file: 'vendor/xterm/addon-fit.js', contentType: 'text/javascript; charset=utf-8' },
60
+ /** ⭐ 28/8 — renderer WebGL: la vista Terminale ha bisogno di questo per i colori ANSI, vedi il commento in montaTerminaleSeServe() (app.js) e vendor/xterm/README.md per il perché. */
61
+ '/vendor/xterm/addon-webgl.js': { file: 'vendor/xterm/addon-webgl.js', contentType: 'text/javascript; charset=utf-8' },
62
+ /**
63
+ * ⭐⭐⭐ 02/9 — formattatore dei blocchi di codice: Prism 1.30.0
64
+ * vendorizzato (core + 19 linguaggi in un file solo, vedi
65
+ * `vendor/prism/README.md`), stesso principio di xterm qui sopra — mai
66
+ * una CDN. ⛔ Questa riga NON è facoltativa: la allowlist è esplicita, e
67
+ * senza risponderebbe 404 lasciando ogni blocco senza evidenziazione —
68
+ * esattamente il difetto già pagato con xterm il 28/8, quattro righe più
69
+ * su, dove è costato una verifica dal vivo per accorgersene.
70
+ */
71
+ '/vendor/prism/prism.js': { file: 'vendor/prism/prism.js', contentType: 'text/javascript; charset=utf-8' },
72
+ });
73
+
74
+ export function createStaticHandler(publicDir, fsAdapter = { readFile }) {
75
+ return async function staticHandler(pathname) {
76
+ const asset = STATIC_ASSETS[pathname];
77
+ if (!asset) return null;
78
+ let body;
79
+ try {
80
+ body = await fsAdapter.readFile(join(publicDir, asset.file));
81
+ } catch (error) {
82
+ // ⭐ 26/8 — un asset MAPPATO ma fisicamente assente (percorso di
83
+ // sviluppo diverso, TALOS_HARNESS_UI_PUBLIC_DIR di test senza la
84
+ // radice condivisa accanto) è un 404 onesto, non un 500 generico:
85
+ // la richiesta era legittima, manca solo il file.
86
+ if (error?.code === 'ENOENT') return null;
87
+ throw error;
88
+ }
89
+ if (body.length > MAX_STATIC_BYTES) {
90
+ const error = new Error('Asset statico oltre limite');
91
+ error.code = 'PAYLOAD_LIMIT';
92
+ throw error;
93
+ }
94
+ return { statusCode: 200, contentType: asset.contentType, body };
95
+ };
96
+ }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Partitions provider text streams before they reach the UI. Provider
3
+ * delimiters are transport syntax, never user-visible assistant text.
4
+ */
5
+
6
+ const OPEN_TAGS = Object.freeze([
7
+ { tag: '<think>', mode: 'reasoning' },
8
+ { tag: '<thinking>', mode: 'reasoning' },
9
+ { tag: '<tool_call>', mode: 'tool' },
10
+ { tag: '<tool_call_start>', mode: 'tool' },
11
+ ]);
12
+ const CLOSE_TAGS = Object.freeze([
13
+ '</think>',
14
+ '</thinking>',
15
+ '</tool_call>',
16
+ '<tool_call_end>',
17
+ ]);
18
+ const MAX_TAG_LENGTH = Math.max(...OPEN_TAGS.map(({ tag }) => tag.length), ...CLOSE_TAGS.map((tag) => tag.length));
19
+
20
+ function partialTagLength(value, tags) {
21
+ const limit = Math.min(value.length, MAX_TAG_LENGTH - 1);
22
+ for (let length = limit; length > 0; length -= 1) {
23
+ const suffix = value.slice(-length);
24
+ if (tags.some((tag) => tag.startsWith(suffix))) return length;
25
+ }
26
+ return 0;
27
+ }
28
+
29
+ function emitText(callback, value) {
30
+ if (typeof value === 'string' && value !== '') callback(value);
31
+ }
32
+
33
+ function parseToolPayload(value) {
34
+ const raw = String(value ?? '').trim();
35
+ if (!raw) return { name: 'provider_tool', arguments: '{}' };
36
+ try {
37
+ const parsed = JSON.parse(raw);
38
+ if (parsed && typeof parsed === 'object') {
39
+ const name = typeof parsed.name === 'string' && parsed.name.trim() ? parsed.name.trim()
40
+ : typeof parsed.tool === 'string' && parsed.tool.trim() ? parsed.tool.trim() : 'provider_tool';
41
+ const argumentsValue = Object.hasOwn(parsed, 'arguments') ? parsed.arguments
42
+ : Object.hasOwn(parsed, 'args') ? parsed.args : parsed;
43
+ return { ...(typeof parsed.id === 'string' && parsed.id ? { id: parsed.id } : {}), name, arguments: typeof argumentsValue === 'string' ? argumentsValue : JSON.stringify(argumentsValue ?? {}) };
44
+ }
45
+ } catch { /* alcuni provider usano una sintassi chiamata non-JSON: la conserviamo come argomento */ }
46
+ const call = /^\[?\s*([A-Za-z][\w.-]*)\s*\((.*)\)\s*\]?$/us.exec(raw);
47
+ if (call) return { name: call[1], arguments: call[2].trim() || '{}' };
48
+ return { name: 'provider_tool', arguments: raw };
49
+ }
50
+
51
+ export function createStreamPartitioner({ onText = () => {}, onReasoning = () => {}, onToolCall = () => {} } = {}) {
52
+ let buffer = '';
53
+ let mode = 'text';
54
+ let toolBuffer = '';
55
+ let finished = false;
56
+
57
+ const emitMode = (value) => {
58
+ if (mode === 'text') emitText(onText, value);
59
+ else if (mode === 'reasoning') emitText(onReasoning, value);
60
+ else if (mode === 'tool') toolBuffer += value;
61
+ };
62
+
63
+ const drain = (final = false) => {
64
+ while (buffer) {
65
+ if (mode === 'text') {
66
+ let found = null;
67
+ for (const candidate of OPEN_TAGS) {
68
+ const index = buffer.indexOf(candidate.tag);
69
+ if (index >= 0 && (!found || index < found.index)) found = { ...candidate, index };
70
+ }
71
+ if (!found) {
72
+ const keep = final ? 0 : partialTagLength(buffer, OPEN_TAGS.map(({ tag }) => tag));
73
+ const emitLength = Math.max(0, buffer.length - keep);
74
+ emitMode(buffer.slice(0, emitLength));
75
+ buffer = buffer.slice(emitLength);
76
+ if (!final && buffer.length) return;
77
+ continue;
78
+ }
79
+ emitMode(buffer.slice(0, found.index));
80
+ buffer = buffer.slice(found.index + found.tag.length);
81
+ mode = found.mode;
82
+ toolBuffer = '';
83
+ continue;
84
+ }
85
+
86
+ let close = null;
87
+ for (const tag of CLOSE_TAGS) {
88
+ const index = buffer.indexOf(tag);
89
+ if (index >= 0 && (!close || index < close.index)) close = { tag, index };
90
+ }
91
+ if (!close) {
92
+ const keep = final ? 0 : partialTagLength(buffer, CLOSE_TAGS);
93
+ const emitLength = Math.max(0, buffer.length - keep);
94
+ emitMode(buffer.slice(0, emitLength));
95
+ buffer = buffer.slice(emitLength);
96
+ if (!final && buffer.length) return;
97
+ continue;
98
+ }
99
+ emitMode(buffer.slice(0, close.index));
100
+ buffer = buffer.slice(close.index + close.tag.length);
101
+ if (mode === 'tool') onToolCall(parseToolPayload(toolBuffer));
102
+ mode = 'text';
103
+ toolBuffer = '';
104
+ }
105
+ };
106
+
107
+ const push = (chunk) => {
108
+ if (finished || chunk === null || chunk === undefined) return;
109
+ buffer += String(chunk);
110
+ drain(false);
111
+ };
112
+ const finish = () => {
113
+ if (finished) return;
114
+ finished = true;
115
+ drain(true);
116
+ if (mode === 'tool' && toolBuffer) onToolCall(parseToolPayload(toolBuffer));
117
+ toolBuffer = '';
118
+ mode = 'text';
119
+ };
120
+ return Object.freeze({ push, finish });
121
+ }
122
+
123
+ export { parseToolPayload };
@@ -0,0 +1,453 @@
1
+ /**
2
+ * subagent-orchestrator.mjs — FASE C (sub-agenti), piano
3
+ * `elegant-spinning-dongarra.md`. Delega isolata verso una sessione
4
+ * figlia — un differenziatore diretto rispetto allo stato dell'arte
5
+ * (vincolo persistente dell'owner). Vedi `.claude/LEDGER-FASE-C-SUBAGENTI.md`
6
+ * per il ledger completo, il confronto competitivo e le decisioni
7
+ * prese in corso d'opera.
8
+ *
9
+ * ⛔ Zero registro proprio: opera sulla STESSA `Map` `sessioni` di
10
+ * `session-registry.mjs`, iniettata — mai una seconda fonte di verità
11
+ * su quali sessioni esistono.
12
+ *
13
+ * ⭐⭐⭐ I numeri sotto sono quelli VERI trovati in ricerca, letti da un
14
+ * repository open source dello stesso spazio clonato il 28/8 — non
15
+ * inventati, non presi da doc secondari (due correzioni fatte quel
16
+ * giorno su claim sbagliati di doc secondari, vedi il ledger): un
17
+ * tetto di 10 figli concorrenti di default, e una profondità massima
18
+ * di delega di 2, con la nota nel codice sorgente "for parity with the
19
+ * original MAX_DEPTH constant".
20
+ */
21
+
22
+ /** Fonte: ricerca su un progetto open source dello stesso spazio, letto il 28/8. */
23
+ import { existsSync, statSync } from 'node:fs';
24
+ import { parse as parsePath } from 'node:path';
25
+
26
+ export const LIMITE_FIGLI_CONCORRENTI = 10;
27
+
28
+ /**
29
+ * Fonte: la stessa ricerca sopra. A differenza dell'approccio trovato
30
+ * (che non ha un tetto duro oltre il default, solo un avviso in log),
31
+ * questa prima fetta applica un tetto DURO — scelta più prudente
32
+ * finché non c'è una misura reale che dica se serve di più (stesso
33
+ * principio "si aggiunge quando serve" già in uso per `GIRI_MASSIMI`
34
+ * nel kernel).
35
+ */
36
+ export const LIMITE_PROFONDITA_DELEGA = 2;
37
+
38
+ const TOOL_ERRORE_ESPLICITO = /^(?:\s*(?:error\b|exit\s+[1-9]\d*\b)|.*\b(?:ENOENT|no such file or directory|could not|unable to|failed to|not accessible|no file matches|non riesco|problema di configurazione)\b)/i;
39
+ const TASK_SCRITTURA_ESPLICITA = /\b(?:scriv\w*|modific\w*|aggiorn\w*|cre\w*|aggiung\w*|elimin\w*|rinomin\w*|implement\w*|write|modify|update|create|add|delete|rename|implement)\b/i;
40
+
41
+ /** Una richiesta esplicita di modifica richiede una prova di file/artefatto, non solo una risposta tool. */
42
+ export function taskRichiedeEvidenzaScrittura(task) {
43
+ const testo = typeof task === 'string' ? task : task?.consegna ?? task?.consegnaCorta ?? '';
44
+ return TASK_SCRITTURA_ESPLICITA.test(String(testo));
45
+ }
46
+
47
+ /**
48
+ * Riassume soltanto i segnali operativi già emessi dal figlio. Il testo
49
+ * finale del modello non è una prova di scrittura: una delega può dichiarare
50
+ * "fatto" anche quando ogni terminale ha risposto con un errore.
51
+ *
52
+ * @param {Array<object>|undefined|null} eventi
53
+ * @returns {{scritture:number, artefatti:number, toolCalls:number, toolCallsOk:number, toolCallsFalliti:number, verificabile:boolean}|null}
54
+ */
55
+ export function analizzaEvidenzaDelega(eventi) {
56
+ if (!Array.isArray(eventi)) return null;
57
+ let scritture = 0;
58
+ let artefatti = 0;
59
+ let toolCalls = 0;
60
+ let toolCallsOk = 0;
61
+ let toolCallsFalliti = 0;
62
+ for (const evento of eventi) {
63
+ if (evento?.type === 'ArtifactCreated') artefatti += 1;
64
+ if (evento?.type === 'StateDelta') {
65
+ const delta = Array.isArray(evento.delta) ? evento.delta : [];
66
+ scritture += delta.filter((voce) => typeof voce?.path === 'string' && voce.path.startsWith('/file/')).length;
67
+ }
68
+ if (evento?.type !== 'ToolCallResult') continue;
69
+ toolCalls += 1;
70
+ if (TOOL_ERRORE_ESPLICITO.test(String(evento.content ?? ''))) toolCallsFalliti += 1;
71
+ else toolCallsOk += 1;
72
+ }
73
+ return {
74
+ scritture,
75
+ artefatti,
76
+ toolCalls,
77
+ toolCallsOk,
78
+ toolCallsFalliti,
79
+ verificabile: scritture > 0 || artefatti > 0 || toolCallsOk > 0,
80
+ };
81
+ }
82
+
83
+ function motivoEvidenzaMancante(evidenza, richiestaScrittura = false) {
84
+ const dettaglio = richiestaScrittura
85
+ ? 'la richiesta prevedeva una modifica ma non risultano scritture o artefatti'
86
+ : `${evidenza.toolCallsFalliti} tool su ${evidenza.toolCalls} hanno fallito e non risultano scritture o artefatti`;
87
+ return `Il sotto-agente ha dichiarato successo, ma non ha lasciato evidenza verificabile: ${dettaglio}. Il lavoro non è considerato concluso.`;
88
+ }
89
+
90
+ /**
91
+ * Traduce il risultato di `agent-service.avviaSessione` (il "risultato"
92
+ * catturato dentro il `.then()`/`.catch()` di `avviaESegui`) nella
93
+ * forma onesta che il kernel (`onDelega`) si aspetta — mai un successo
94
+ * inventato quando la figlia non ha concluso per davvero.
95
+ *
96
+ * @param {{ok?: boolean, esito?: object|null, erroreInterno?: string|null}|null} risultato
97
+ * @param {Array<object>|undefined|null} [eventi] eventi AG-UI persistiti dalla figlia
98
+ * @param {{task?:string|object}} [contesto] richiesta originale, per distinguere una lettura da una modifica
99
+ */
100
+ export function esitoDelegaDaRisultato(risultato, eventi, contesto = {}) {
101
+ if (risultato?.ok) {
102
+ const evidenza = analizzaEvidenzaDelega(eventi);
103
+ const richiestaScrittura = taskRichiedeEvidenzaScrittura(contesto.task);
104
+ // Se il figlio ha ricevuto una richiesta di modifica, una risposta tool
105
+ // riuscita non dimostra che il file sia stato scritto: serve StateDelta o
106
+ // ArtifactCreated. Per richieste puramente informative resta sufficiente
107
+ // una tool-call riuscita; una delega senza tool conserva il contratto.
108
+ if (evidenza && evidenza.toolCalls > 0 && ((!evidenza.verificabile) || (richiestaScrittura && evidenza.scritture === 0 && evidenza.artefatti === 0))) {
109
+ return {
110
+ riassunto: risultato.esito?.detto || '(il sotto-agente non ha lasciato un riassunto testuale)',
111
+ esito: 'fallito',
112
+ motivo: motivoEvidenzaMancante(evidenza, richiestaScrittura),
113
+ };
114
+ }
115
+ return {
116
+ riassunto: risultato.esito?.detto || '(il sotto-agente non ha lasciato un riassunto testuale)',
117
+ esito: 'concluso',
118
+ };
119
+ }
120
+ if (risultato?.esito) {
121
+ // giri-esauriti / fermato: la figlia ha girato, non ha chiuso il task.
122
+ return {
123
+ riassunto: risultato.esito.detto || `Il sotto-task non si è concluso (${risultato.esito.comeFinita}).`,
124
+ esito: 'fallito',
125
+ };
126
+ }
127
+ // erroreInterno: avviaSessione dichiara di non lanciare mai, ma un ripiego onesto resta necessario (stesso principio già in uso nel .catch() di avviaESegui).
128
+ return { riassunto: null, esito: 'fallito', motivo: risultato?.erroreInterno ?? 'errore sconosciuto nella sessione figlia' };
129
+ }
130
+
131
+ /** Ricostruisce il verdetto di una figlia dopo il riavvio del server. */
132
+ export function esitoDelegaDaEventi(eventi, contesto = {}) {
133
+ if (!Array.isArray(eventi)) return null;
134
+ const terminale = [...eventi].reverse().find((evento) => evento?.type === 'RunFinished' || evento?.type === 'RunError');
135
+ if (!terminale) return null;
136
+ if (terminale.type === 'RunError') return 'fallito';
137
+ return esitoDelegaDaRisultato({ ok: true, esito: { detto: terminale.result?.detto ?? '', comeFinita: 'concluso' } }, eventi, contesto).esito;
138
+ }
139
+
140
+ /**
141
+ * @param {Map<string, object>} sessioni — la STESSA Map di session-registry.mjs.
142
+ * @param {Function} avviaESeguiFn — la funzione interna avviaESegui di session-registry.mjs, non una sua copia.
143
+ */
144
+ /** Uno dei due controlli sul percorso che il kernel non può fare: esiste, ed è una cartella. */
145
+ export function esisteCartella(percorso, { esiste = existsSync, stato = statSync } = {}) {
146
+ const p = String(percorso || '');
147
+ if (!p.trim()) return false;
148
+ try { return esiste(p) && stato(p).isDirectory(); } catch { return false; }
149
+ }
150
+
151
+ /**
152
+ * La FORMA di un percorso: come è ancorato, non dove porta. È la sola cosa che distingue
153
+ * «C:\progetto» da «/mnt/c/progetto» PRIMA di toccare il disco.
154
+ *
155
+ * ⛔⛔⛔ 13/09/2026 — MISURATO SU QUESTA MACCHINA (Windows 11, Node v24.18.0), non dedotto.
156
+ * `esisteCartella` da sola NON ferma un percorso di un altro sistema operativo, perché su
157
+ * Windows un percorso che comincia con `/` è ANCORATO ALL'UNITÀ CORRENTE, non rifiutato:
158
+ * esisteCartella('/tmp') → true (il disco risponde per C:\tmp)
159
+ * esisteCartella('/Users') → true (il disco risponde per C:\Users)
160
+ * esisteCartella('src') → true (relativo: risolto sulla cartella del SERVER, non su
161
+ * quella della madre — la figlia finirebbe in harness-ui)
162
+ * Cioè: tre forme storte ACCETTATE IN SILENZIO, e la figlia parte in una cartella che nessuno
163
+ * ha scelto. Le due che il difetto dell'08/09 nominava (`/mnt/c/…`, `/home/user/app`) venivano
164
+ * fermate solo per caso — perché `C:\mnt` e `C:\home` non esistono su QUESTA macchina.
165
+ *
166
+ * Fonte (documentazione ufficiale Node v24, modulo `path` e modulo `fs`, letta il 13/09/2026 via
167
+ * ctx7): `path.isAbsolute('//server')` e `path.isAbsolute('\\\\server')` sono `true` su Windows, e
168
+ * «On Windows, Node.js follows the concept of per-drive working directory» — cioè `isAbsolute` da
169
+ * solo NON distingue le due forme, mentre `path.parse().root` sì: `'/'` per un percorso ancorato
170
+ * alla sola radice, `'C:\'` per un'unità, `'\\server\share\'` per la rete, `''` per un relativo.
171
+ * ⛔ Ricerca web NON disponibile in questa sessione (budget esaurito, 200/200): la citazione è la
172
+ * documentazione ufficiale del runtime, che per questa domanda è la fonte primaria.
173
+ *
174
+ * @returns {'assente'|'relativo'|'radice-sola'|'unita'|'unita-senza-radice'|'rete'}
175
+ */
176
+ export function formaDelPercorso(percorso) {
177
+ const p = String(percorso ?? '');
178
+ if (!p.trim()) return 'assente';
179
+ const radice = parsePath(p).root;
180
+ if (radice === '') return 'relativo';
181
+ if (/^[A-Za-z]:$/u.test(radice)) return 'unita-senza-radice'; // «C:progetto»: relativo alla cartella corrente DI QUELL'UNITÀ
182
+ if (/^[A-Za-z]:[\\/]$/u.test(radice)) return 'unita';
183
+ if (radice === '/' || radice === '\\') return 'radice-sola';
184
+ return 'rete';
185
+ }
186
+
187
+ /**
188
+ * Il percorso che il MODELLO ha proposto per la figlia è utilizzabile su questo computer?
189
+ *
190
+ * ⛔ La misura NON è «assomiglia a Windows»: è «ha la STESSA FORMA della cartella in cui la madre
191
+ * sta già lavorando». Quella cartella l'ha scelta una persona ed è vera per costruzione, quindi
192
+ * è il metro giusto — e si tara da sé, senza una riga che nomini un sistema operativo. Il kernel
193
+ * non può farlo: non sa in che forma è il disco (`talosHarness.mjs`, `delega_sottotask`, che per
194
+ * questo delega il no a `onDelega`).
195
+ *
196
+ * ⛔ Percorso assente ⇒ nessun giudizio: si lavora dove lavora la madre, ed è il caso NORMALE
197
+ * (stato dell'arte letto il 06/09/2026: i sotto-agenti condividono la cartella del padre).
198
+ *
199
+ * @returns {{ok:true}|{ok:false, motivo:string}} mai un'eccezione: un rifiuto è un esito.
200
+ */
201
+ export function percorsoDellaFigliaUsabile(proposto, cartellaMadre) {
202
+ const forma = formaDelPercorso(proposto);
203
+ if (forma === 'assente') return { ok: true };
204
+ const formaMadre = formaDelPercorso(cartellaMadre);
205
+ if (forma === formaMadre) return { ok: true };
206
+ /*
207
+ * ⛔ Il motivo PORTA la cartella giusta, scritta per esteso. Un rifiuto che dice solo «no»
208
+ * lascia il modello a indovinare, ed è esattamente così che sono morte tre deleghe di fila:
209
+ * vedeva un REFUSED, inventava un'altra forma, ne vedeva un altro. Chi rifiuta e conosce la
210
+ * risposta la dice.
211
+ */
212
+ const spiegazione = forma === 'relativo' || forma === 'unita-senza-radice'
213
+ ? `la cartella «${proposto}» non è un percorso assoluto`
214
+ : `la cartella «${proposto}» è scritta nella forma di un altro sistema operativo`;
215
+ if (formaMadre === 'assente') {
216
+ return { ok: false, motivo: `${spiegazione}. Ometti la cartella per lavorare dove lavora chi ti ha delegato.` };
217
+ }
218
+ return {
219
+ ok: false,
220
+ motivo: `${spiegazione}: su questo computer i percorsi si scrivono come «${cartellaMadre}». `
221
+ + `Ometti la cartella per lavorare dove lavora chi ti ha delegato, oppure usa esattamente «${cartellaMadre}».`,
222
+ };
223
+ }
224
+
225
+ /*
226
+ * `cartellaEsisteFn` si inietta: le prove costruiscono sessioni con cartelle che sul disco non
227
+ * esistono, e il controllo vero (quello che ferma un percorso in forma WSL) resta acceso in produzione.
228
+ */
229
+ /**
230
+ * Il COMPITO dentro il prompt che il kernel costruisce per una figlia.
231
+ * ⛔ `Compito:` è il marcatore del kernel dell'owner (`mobile/scripts/harness-talos`), che non è di questa
232
+ * lane: se un giorno cambia, il nome torna a essere il preambolo — brutto e visibile, mai un silenzio.
233
+ * Senza marcatore si restituisce la stringa intera: non si indovina dove finisce un preambolo che non c'è.
234
+ */
235
+ export function compitoDaPromptDiDelega(prompt) {
236
+ const testo = typeof prompt === 'string' ? prompt : prompt?.consegna ?? '';
237
+ const marcatore = new RegExp(String.raw`(?:^|[.` + String.fromCharCode(10) + String.raw`])\s*Compito\s*:\s*`, 'u').exec(testo);
238
+ if (!marcatore) return testo;
239
+ const dopo = testo.slice(marcatore.index + marcatore[0].length).trim();
240
+ return dopo || testo;
241
+ }
242
+
243
+ export function creaSubagentOrchestrator({ sessioni, avviaESeguiFn, cartellaEsisteFn = esisteCartella }) {
244
+ function contaFigliAttivi(sessionPadreId) {
245
+ let n = 0;
246
+ for (const voce of sessioni.values()) {
247
+ if (voce.padreId === sessionPadreId && !voce.conclusa) n += 1;
248
+ }
249
+ return n;
250
+ }
251
+
252
+ /** Per il foglio "Albero sessione" (C.3) — ordinati per avvio, il più vecchio prima. */
253
+ function elencaFigli(sessionPadreId) {
254
+ const figli = [];
255
+ for (const [sessionId, voce] of sessioni.entries()) {
256
+ if (voce.padreId === sessionPadreId) {
257
+ figli.push({
258
+ sessionId,
259
+ task: voce.task?.consegna ?? null,
260
+ /*
261
+ * ⛔ 09/09, visto nella FOTO della scheda «Agenti» dopo il giro vero della delega (D2): le due
262
+ * schede si chiamavano ENTRAMBE «Sei una sessione di lavoro autonoma; non hai altro …», cioè
263
+ * il preambolo del kernel, che è identico per ogni figlia. La barra era già stata curata poche
264
+ * ore prima; qui no, perché la scheda legge QUESTA funzione e non `elenca()`. Stesso difetto,
265
+ * secondo consumatore — la cura non si copia, si espone il dato una volta sola.
266
+ * ⛔ `task` resta la consegna INTERA: il foglio «Albero sessione» la mostra per esteso, e
267
+ * togliere informazione a un consumatore per aggiustarne un altro è esattamente il modo di
268
+ * rifare il giro fra un mese. Il nome corto viaggia accanto.
269
+ */
270
+ taskCorto: voce.task?.consegnaCorta ?? (voce.task?.consegna ? compitoDaPromptDiDelega(voce.task.consegna) : null),
271
+ /*
272
+ * ⛔ D3 — i file che QUESTA figlia ha scritto e che anche un'altra sorella ha toccato. La
273
+ * lista sta sulla madre (il registro la scrive mentre gli eventi passano); qui esce filtrata
274
+ * per la figlia, perché la scheda «Agenti» parla di una delega alla volta. Vuota quasi
275
+ * sempre: se non lo è, due deleghe si sono pestate i piedi e va detto.
276
+ */
277
+ collisioni: (sessioni.get(voce.padreId)?.collisioniDiScrittura ?? [])
278
+ .filter((c) => c.prima === sessionId || c.poi === sessionId)
279
+ .map((c) => ({ percorso: c.percorso, primaDi: c.prima === sessionId ? null : c.prima, dopoDi: c.poi === sessionId ? null : c.poi })),
280
+ conclusa: voce.conclusa,
281
+ /*
282
+ * ⛔ 06/9, T05-D3 un piano più sotto: senza questo campo un sotto-agente ucciso dalla
283
+ * morte del processo restava «In corso» per sempre nella scheda Agenti e nel foglio
284
+ * dell'albero — e il frontend non aveva NIENTE con cui dire il vero, perché il dato
285
+ * non usciva da qui. Il registro la conosce (`interrotta: !conclusa` al ripristino).
286
+ */
287
+ interrotta: voce.interrotta === true,
288
+ esitoDelega: voce.esitoDelega ?? null,
289
+ evidenzaDelega: voce.evidenzaDelega ?? null,
290
+ avviataAlle: voce.avviataAlle ?? null,
291
+ });
292
+ }
293
+ }
294
+ figli.sort((a, b) => String(a.avviataAlle).localeCompare(String(b.avviataAlle)));
295
+ return figli;
296
+ }
297
+
298
+ /**
299
+ * @returns {Promise<{riassunto?: string, esito: 'concluso'|'fallito'|'rifiutato', motivo?: string}>}
300
+ * Non lancia MAI — un rifiuto (cartella invalida, tetto raggiunto,
301
+ * padre scomparso) è un `esito:'rifiutato'` con `motivo`, non
302
+ * un'eccezione: il dispatcher del kernel lo traduce in un REFUSED
303
+ * onesto per il modello, stessa disciplina di ogni altro cancello.
304
+ */
305
+ function delegaSottoTask({ sessionPadreId, task, cartella }) {
306
+ return new Promise((resolve) => {
307
+ const padre = sessioni.get(sessionPadreId);
308
+ if (!padre) {
309
+ resolve({ esito: 'rifiutato', motivo: 'la sessione padre non esiste più' });
310
+ return;
311
+ }
312
+ /*
313
+ * ⛔⛔⛔ 06/9 — questa guardia diceva «la cartella della delega deve essere diversa da quella
314
+ * del padre», e insieme alla gemella nel kernel produceva il difetto misurato dal vivo: un
315
+ * giro con UNA delega, quattro sessioni figlie, otto giri, 76,8k token, tutte fallite. Il
316
+ * modello vedeva un rifiuto sul caso normale — delegare un pezzo dello STESSO progetto — e
317
+ * aggirava riscrivendo il percorso in forma WSL (`/mnt/c/…`), che qui passava e su Windows
318
+ * non esiste: il figlio partiva con una cartella inesistente e moriva.
319
+ * Stato dell'arte (letto 06/09/2026): per difetto i
320
+ * sotto-agenti CONDIVIDONO la cartella del padre; l'isolamento vero, quando serve, si fa con
321
+ * un worktree, non con una cartella diversa a caso.
322
+ * ⇒ Restano DUE controlli, quelli che il kernel non può fare: la FORMA del percorso e la sua
323
+ * ESISTENZA.
324
+ * ⛔⛔ 13/09/2026 — la seconda metà di questa cura MANCAVA, e il difetto è misurato nella doc
325
+ * di `formaDelPercorso`: su Windows `/tmp`, `/Users` e `src` passavano `esisteCartella`
326
+ * (rispettivamente `C:\tmp`, `C:\Users` e la cartella del SERVER) e la figlia partiva in
327
+ * una cartella che nessuno aveva scelto. `/mnt/c/…` veniva fermato solo perché `C:\mnt`
328
+ * non esiste QUI: una guardia che dipende da quali cartelle ha la macchina non è una
329
+ * guardia. La forma si controlla PRIMA del disco, e il rifiuto dice quale sia la giusta.
330
+ */
331
+ const proposta = typeof cartella === 'string' && cartella.trim() !== '' ? cartella : null;
332
+ const dove = proposta ?? padre.cartella;
333
+ const forma = percorsoDellaFigliaUsabile(proposta, padre.cartella);
334
+ if (!forma.ok) {
335
+ resolve({ esito: 'rifiutato', motivo: forma.motivo });
336
+ return;
337
+ }
338
+ if (!cartellaEsisteFn(dove)) {
339
+ /* ⛔ Anche qui il motivo porta la cartella della madre — tranne quando è LEI a non esistere:
340
+ consigliare la cartella che ha appena fallito sarebbe un consiglio falso. */
341
+ /* ⛔⛔ 13/09/2026, revisione avversariale: il commento qui sopra prometteva questo, il
342
+ codice NON lo faceva. `dove === padre.cartella` riconosce solo il caso in cui il modello
343
+ RIPETE la cartella della madre; se ne propone un'altra e la cartella della madre nel
344
+ frattempo è sparita (cancellata a sessione viva), il rifiuto consigliava una cartella
345
+ inesistente — il consiglio falso che la riga sopra dice di evitare. Ora la condizione è
346
+ quella dichiarata: si consiglia solo una cartella che il disco conferma. */
347
+ const madreConsigliabile = dove !== padre.cartella && cartellaEsisteFn(padre.cartella);
348
+ const invece = madreConsigliabile
349
+ ? ` Ometti la cartella per lavorare dove lavora chi ti ha delegato, oppure usa esattamente «${padre.cartella}».`
350
+ : '';
351
+ resolve({ esito: 'rifiutato', motivo: `la cartella ${dove} non esiste su questo computer.${invece}` });
352
+ return;
353
+ }
354
+ const profonditaVoluta = (padre.profonditaDelega ?? 0) + 1;
355
+ if (profonditaVoluta > LIMITE_PROFONDITA_DELEGA) {
356
+ resolve({ esito: 'rifiutato', motivo: `profondità di delega massima raggiunta (limite ${LIMITE_PROFONDITA_DELEGA})` });
357
+ return;
358
+ }
359
+ if (contaFigliAttivi(sessionPadreId) >= LIMITE_FIGLI_CONCORRENTI) {
360
+ resolve({ esito: 'rifiutato', motivo: `limite di ${LIMITE_FIGLI_CONCORRENTI} figli concorrenti raggiunto` });
361
+ return;
362
+ }
363
+ let figlioId = null;
364
+ let conclusioneRicevuta = null;
365
+ let conclusioneGestita = false;
366
+ const completaConclusione = (risultatoSessione) => {
367
+ if (conclusioneGestita) return;
368
+ if (!figlioId) {
369
+ conclusioneRicevuta = risultatoSessione;
370
+ return;
371
+ }
372
+ conclusioneGestita = true;
373
+ const voceFiglia = sessioni.get(figlioId);
374
+ const eventi = voceFiglia?.eventi;
375
+ const esito = esitoDelegaDaRisultato(risultatoSessione, eventi, { task });
376
+ if (voceFiglia) {
377
+ voceFiglia.esitoDelega = esito.esito;
378
+ voceFiglia.evidenzaDelega = analizzaEvidenzaDelega(eventi);
379
+ }
380
+ resolve(esito);
381
+ };
382
+ /*
383
+ * ⛔⛔⛔ 06/9, stessa misura: i figli partivano con `glm-4.7-flash` mentre la sessione madre
384
+ * aveva scelto `glm-5.3-flash`, e nessuna riga a schermo lo diceva. Un sotto-agente eredita
385
+ * gli strumenti del padre (stesso principio trovato in ricerca: i sotto-agenti ereditano
386
+ * gli strumenti abilitati del padre); a
387
+ * maggior ragione deve ereditare il MODELLO, altrimenti chi paga non sa cosa sta pagando.
388
+ * Si eredita anche lo sforzo di ragionamento e i permessi: il figlio non è più libero del padre.
389
+ */
390
+ const risultatoAvvio = avviaESeguiFn({
391
+ taskId: `delega:${sessionPadreId}`,
392
+ cartella: dove,
393
+ /*
394
+ * ⛔⛔⛔ 08/09/2026 — SENZA QUESTA RIGA LA FIGLIA LAVORA IN `C:\`, LA RADICE DEL DISCO.
395
+ *
396
+ * Misurato sulla run vera dell'owner (tre sessioni in `.sessions-store/`): l'intestazione
397
+ * della figlia porta la cartella giusta, e il `contesto` di `RunStarted` porta `C:\`. La
398
+ * cartella corretta viene passata qui, scritta su disco, e allargata un istante dopo da
399
+ * `cartellaEffettivaPerPermessi` (session-registry), che senza `cartellaGiaScelta` traduce
400
+ * «Full access» in `parsePath(cartella).root`. La figlia eredita Full access dalla madre —
401
+ * ed è giusto che lo erediti — quindi finiva nella radice.
402
+ *
403
+ * ⇒ Il difetto non è l'eredità dei permessi: è che una FIGLIA NON HA NIENTE DA CUI
404
+ * ALLARGARSI. La sua cartella è per definizione esattamente quella della madre, già
405
+ * scelta da una persona. È il caso (d) della famiglia documentata sopra
406
+ * `cartellaEffettivaPerPermessi` (a: allowlist — l'unico che deve allargare; b:
407
+ * avviaLibero, curato 03/9; c: avvia() dei task di catalogo, curato 04/9): la delega non
408
+ * era mai stata considerata.
409
+ *
410
+ * Il danno misurato prima della cura, su 37 chiamate delle due figlie: `scrivi` →
411
+ * `EPERM mkdir 'C:\'`; `document_create` → sei tentativi tutti EPERM; `leggi package.json`
412
+ * → `ENOENT 'C:\package.json'`. Zero file scritti nel workspace, e la delega ha consegnato
413
+ * un artefatto al posto del documento chiesto senza che nessuno protestasse.
414
+ *
415
+ * Ricerca 08/09/2026 — dev.to «Giving an AI agent permission to spawn sub-agents (without
416
+ * losing control)»: il wrapper della delega «resolves the workspace **against the parent's
417
+ * root**», e l'eredità dev'essere «explicit and **downgraded by default**: parent can
418
+ * delegate only permissions it actually has» — «if every subagent inherits the parent
419
+ * token, it recreates sudo with better branding». Qui la cartella è la prima delega da
420
+ * restringere.
421
+ */
422
+ cartellaGiaScelta: true,
423
+ /*
424
+ * ⛔ 09/09/2026 — trovato dal giro vero sul 4174: nella barra e nella scheda «Agenti» le due figlie
425
+ * si chiamavano entrambe «Sei una sessione di lavoro autonoma; non hai altro …». Il kernel non
426
+ * passa il compito nudo: passa il PROMPT INTERO della figlia (825 caratteri, letti dal JSONL),
427
+ * che comincia con un preambolo di sistema e mette il compito dopo «Compito:». Chi legge la barra
428
+ * vedeva due righe identiche e doveva aprirle per sapere quale fosse quale.
429
+ * ⇒ La forma corta si costruisce QUI, dove si sa che quella stringa è il prompt di una delega:
430
+ * `session-registry` non può saperlo, e il kernel dell'owner non è mio.
431
+ */
432
+ task: { consegna: task, consegnaCorta: compitoDaPromptDiDelega(task) },
433
+ padreId: sessionPadreId,
434
+ profonditaDelega: profonditaVoluta,
435
+ modelloRichiesta: padre.modello ?? null,
436
+ reasoningRichiesto: padre.reasoning ?? null,
437
+ permessiRichiesti: padre.permessi ?? null,
438
+ permessiPerAttrezzoRichiesti: padre.permessiPerAttrezzo ?? null,
439
+ onConclusioneFn: (risultatoSessione) => {
440
+ completaConclusione(risultatoSessione);
441
+ },
442
+ });
443
+ figlioId = risultatoAvvio?.sessionId ?? null;
444
+ if (conclusioneRicevuta) completaConclusione(conclusioneRicevuta);
445
+ // ⛔ AL CONTRARIO: avviaESeguiFn può rifiutare PRIMA di avviare (es. chiave API non configurata) — mai una Promise appesa in eterno se onConclusioneFn non scatterà mai.
446
+ if (!conclusioneGestita && !conclusioneRicevuta && risultatoAvvio?.erroreAvvio) {
447
+ resolve({ esito: 'rifiutato', motivo: risultatoAvvio.erroreAvvio });
448
+ }
449
+ });
450
+ }
451
+
452
+ return Object.freeze({ delegaSottoTask, contaFigliAttivi, elencaFigli });
453
+ }