@zergai/ztc 0.4.0-beta.1 → 0.5.0-beta.1

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 (718) hide show
  1. package/README.md +398 -45
  2. package/RUST_THIRD_PARTY_LICENSES.txt +1080 -822
  3. package/THIRD_PARTY_NOTICES.md +273 -12
  4. package/bin/zmux-darwin-arm64 +0 -0
  5. package/bin/ztc-audio-darwin-arm64 +0 -0
  6. package/bin/ztc-capture-darwin-arm64 +0 -0
  7. package/bin/ztc-computer-darwin-arm64 +0 -0
  8. package/bin/ztc-llm-darwin-arm64 +0 -0
  9. package/bin/ztc-tts-darwin-arm64 +0 -0
  10. package/bin/ztc-tui-darwin-arm64 +0 -0
  11. package/bin/ztc-zlicky-overlay-darwin-arm64 +0 -0
  12. package/bin/zterm-darwin-arm64 +0 -0
  13. package/dist/App.js +1206 -209
  14. package/dist/agent/agent.d.ts +74 -8
  15. package/dist/agent/agent.js +1073 -184
  16. package/dist/agent/backends/account_rotation.d.ts +4 -0
  17. package/dist/agent/backends/account_rotation.js +8 -2
  18. package/dist/agent/backends/anthropic.d.ts +13 -0
  19. package/dist/agent/backends/anthropic.js +169 -28
  20. package/dist/agent/backends/claude_cli.js +18 -8
  21. package/dist/agent/backends/codex_app_server.d.ts +1 -0
  22. package/dist/agent/backends/codex_app_server.js +55 -3
  23. package/dist/agent/backends/codex_auth.d.ts +1 -0
  24. package/dist/agent/backends/codex_auth.js +67 -13
  25. package/dist/agent/backends/codex_buffered_recovery.d.ts +27 -0
  26. package/dist/agent/backends/codex_buffered_recovery.js +293 -0
  27. package/dist/agent/backends/gemini.js +3 -1
  28. package/dist/agent/backends/http_error.d.ts +26 -0
  29. package/dist/agent/backends/http_error.js +221 -0
  30. package/dist/agent/backends/index.d.ts +9 -2
  31. package/dist/agent/backends/index.js +22 -2
  32. package/dist/agent/backends/openai.d.ts +0 -6
  33. package/dist/agent/backends/openai.js +5 -2
  34. package/dist/agent/backends/openai_compatible.d.ts +5 -4
  35. package/dist/agent/backends/openai_compatible.js +26 -19
  36. package/dist/agent/backends/openai_responses.d.ts +8 -3
  37. package/dist/agent/backends/openai_responses.js +77 -33
  38. package/dist/agent/backends/provider_ids.d.ts +1 -0
  39. package/dist/agent/backends/provider_ids.js +4 -0
  40. package/dist/agent/backends/request_metrics.js +12 -2
  41. package/dist/agent/backends/types.d.ts +109 -6
  42. package/dist/agent/backends/types.js +5 -1
  43. package/dist/agent/backends/zrouter_stream.d.ts +6 -1
  44. package/dist/agent/backends/zrouter_stream.js +160 -42
  45. package/dist/agent/background_registry.d.ts +2 -0
  46. package/dist/agent/background_registry.js +1 -0
  47. package/dist/agent/claim_observation.d.ts +6 -0
  48. package/dist/agent/claim_observation.js +54 -0
  49. package/dist/agent/commands/accounts.js +46 -177
  50. package/dist/agent/commands/attention.d.ts +2 -0
  51. package/dist/agent/commands/attention.js +67 -0
  52. package/dist/agent/commands/auth.js +18 -2
  53. package/dist/agent/commands/board.d.ts +2 -0
  54. package/dist/agent/commands/board.js +169 -0
  55. package/dist/agent/commands/clipboard.js +50 -1
  56. package/dist/agent/commands/compact.js +21 -13
  57. package/dist/agent/commands/config.js +4 -1
  58. package/dist/agent/commands/context.js +6 -1
  59. package/dist/agent/commands/desktop.d.ts +2 -0
  60. package/dist/agent/commands/desktop.js +29 -0
  61. package/dist/agent/commands/effort.js +14 -6
  62. package/dist/agent/commands/environment.d.ts +3 -0
  63. package/dist/agent/commands/environment.js +109 -0
  64. package/dist/agent/commands/evidence.d.ts +2 -0
  65. package/dist/agent/commands/evidence.js +9 -0
  66. package/dist/agent/commands/fork.js +4 -3
  67. package/dist/agent/commands/goal.d.ts +33 -1
  68. package/dist/agent/commands/goal.js +174 -14
  69. package/dist/agent/commands/goal_exit.d.ts +36 -0
  70. package/dist/agent/commands/goal_exit.js +120 -0
  71. package/dist/agent/commands/help.js +3 -1
  72. package/dist/agent/commands/history.js +3 -1
  73. package/dist/agent/commands/inbox.d.ts +2 -0
  74. package/dist/agent/commands/inbox.js +148 -0
  75. package/dist/agent/commands/index.js +16 -1
  76. package/dist/agent/commands/input_mode.js +8 -6
  77. package/dist/agent/commands/job.d.ts +2 -0
  78. package/dist/agent/commands/job.js +93 -0
  79. package/dist/agent/commands/keybindings.js +4 -1
  80. package/dist/agent/commands/label.d.ts +2 -0
  81. package/dist/agent/commands/label.js +77 -0
  82. package/dist/agent/commands/layout.d.ts +2 -0
  83. package/dist/agent/commands/layout.js +20 -0
  84. package/dist/agent/commands/mirror.js +16 -1
  85. package/dist/agent/commands/model.js +12 -2
  86. package/dist/agent/commands/permissions.d.ts +3 -1
  87. package/dist/agent/commands/permissions.js +79 -89
  88. package/dist/agent/commands/plan.js +5 -15
  89. package/dist/agent/commands/profile.js +21 -2
  90. package/dist/agent/commands/provider_selection.js +20 -1
  91. package/dist/agent/commands/rename.js +1 -1
  92. package/dist/agent/commands/resources.d.ts +2 -0
  93. package/dist/agent/commands/resources.js +67 -0
  94. package/dist/agent/commands/rewind.d.ts +3 -0
  95. package/dist/agent/commands/rewind.js +16 -0
  96. package/dist/agent/commands/runbooks.d.ts +2 -0
  97. package/dist/agent/commands/runbooks.js +73 -0
  98. package/dist/agent/commands/runbooks_lazy.d.ts +2 -0
  99. package/dist/agent/commands/runbooks_lazy.js +8 -0
  100. package/dist/agent/commands/sessions.d.ts +1 -1
  101. package/dist/agent/commands/sessions.js +33 -5
  102. package/dist/agent/commands/settings.js +185 -39
  103. package/dist/agent/commands/setup.d.ts +2 -0
  104. package/dist/agent/commands/setup.js +78 -0
  105. package/dist/agent/commands/share.d.ts +2 -0
  106. package/dist/agent/commands/share.js +64 -0
  107. package/dist/agent/commands/status.js +14 -2
  108. package/dist/agent/commands/types.d.ts +99 -6
  109. package/dist/agent/commands/update.js +8 -0
  110. package/dist/agent/commands/usage.d.ts +2 -0
  111. package/dist/agent/commands/usage.js +8 -0
  112. package/dist/agent/factory.d.ts +11 -0
  113. package/dist/agent/factory.js +113 -88
  114. package/dist/agent/loop_policy.d.ts +6 -3
  115. package/dist/agent/loop_policy.js +12 -3
  116. package/dist/agent/measurement_guidance.d.ts +2 -0
  117. package/dist/agent/measurement_guidance.js +5 -0
  118. package/dist/agent/request_encoder.d.ts +8 -1
  119. package/dist/agent/request_encoder.js +95 -23
  120. package/dist/agent/runtime/benchmark_comparison.d.ts +30 -0
  121. package/dist/agent/runtime/benchmark_comparison.js +94 -0
  122. package/dist/agent/runtime/benchmark_contract.d.ts +48 -0
  123. package/dist/agent/runtime/benchmark_contract.js +90 -0
  124. package/dist/agent/runtime/checked_commands.d.ts +32 -0
  125. package/dist/agent/runtime/checked_commands.js +119 -0
  126. package/dist/agent/runtime/command_execution_policy.d.ts +26 -0
  127. package/dist/agent/runtime/command_execution_policy.js +91 -0
  128. package/dist/agent/runtime/command_jobs.d.ts +36 -18
  129. package/dist/agent/runtime/command_jobs.js +151 -13
  130. package/dist/agent/runtime/command_panes.d.ts +59 -0
  131. package/dist/agent/runtime/command_panes.js +398 -0
  132. package/dist/agent/runtime/command_wait.d.ts +19 -0
  133. package/dist/agent/runtime/command_wait.js +167 -0
  134. package/dist/agent/runtime/cpu_benchmark.d.ts +30 -0
  135. package/dist/agent/runtime/cpu_benchmark.js +126 -0
  136. package/dist/agent/runtime/delegated_evidence.d.ts +26 -0
  137. package/dist/agent/runtime/delegated_evidence.js +80 -0
  138. package/dist/agent/runtime/evidence.d.ts +127 -0
  139. package/dist/agent/runtime/evidence.js +468 -0
  140. package/dist/agent/runtime/execution_context.d.ts +7 -0
  141. package/dist/agent/runtime/execution_context.js +39 -3
  142. package/dist/agent/runtime/json_verifier_recipe.d.ts +8 -0
  143. package/dist/agent/runtime/json_verifier_recipe.js +66 -0
  144. package/dist/agent/runtime/measurements.d.ts +110 -0
  145. package/dist/agent/runtime/measurements.js +317 -0
  146. package/dist/agent/runtime/policy.d.ts +4 -0
  147. package/dist/agent/runtime/policy.js +31 -20
  148. package/dist/agent/runtime/provider_native_evidence.d.ts +20 -0
  149. package/dist/agent/runtime/provider_native_evidence.js +86 -0
  150. package/dist/agent/runtime/recovery.d.ts +2 -0
  151. package/dist/agent/runtime/recovery.js +45 -2
  152. package/dist/agent/runtime/remote_broker_transport.d.ts +10 -0
  153. package/dist/agent/runtime/remote_broker_transport.js +84 -0
  154. package/dist/agent/runtime/remote_deletion_receipts.d.ts +3 -0
  155. package/dist/agent/runtime/remote_deletion_receipts.js +43 -0
  156. package/dist/agent/runtime/remote_journal_replay.d.ts +13 -0
  157. package/dist/agent/runtime/remote_journal_replay.js +233 -0
  158. package/dist/agent/runtime/remote_mutation_journal.d.ts +25 -0
  159. package/dist/agent/runtime/remote_mutation_journal.js +208 -0
  160. package/dist/agent/runtime/remote_resource_endpoint.d.ts +7 -0
  161. package/dist/agent/runtime/remote_resource_endpoint.js +6 -0
  162. package/dist/agent/runtime/remote_resource_errors.d.ts +5 -0
  163. package/dist/agent/runtime/remote_resource_errors.js +9 -0
  164. package/dist/agent/runtime/remote_resource_script.d.ts +2 -0
  165. package/dist/agent/runtime/remote_resource_script.js +1009 -0
  166. package/dist/agent/runtime/remote_resources.d.ts +29 -0
  167. package/dist/agent/runtime/remote_resources.js +160 -0
  168. package/dist/agent/runtime/source_verification.d.ts +12 -0
  169. package/dist/agent/runtime/source_verification.js +210 -0
  170. package/dist/agent/runtime/source_verification_contract.d.ts +75 -0
  171. package/dist/agent/runtime/source_verification_contract.js +203 -0
  172. package/dist/agent/runtime/tool_checkpoints.d.ts +11 -0
  173. package/dist/agent/runtime/tool_checkpoints.js +26 -0
  174. package/dist/agent/runtime/tool_effects.d.ts +5 -0
  175. package/dist/agent/runtime/tool_progress.d.ts +12 -0
  176. package/dist/agent/runtime/tool_progress.js +76 -0
  177. package/dist/agent/runtime/tool_runtime.d.ts +16 -1
  178. package/dist/agent/runtime/tool_runtime.js +204 -10
  179. package/dist/agent/runtime/tracing.d.ts +1 -1
  180. package/dist/agent/runtime/verifier_capture.d.ts +9 -0
  181. package/dist/agent/runtime/verifier_capture.js +100 -0
  182. package/dist/agent/runtime/verifier_contract.d.ts +24 -0
  183. package/dist/agent/runtime/verifier_contract.js +41 -0
  184. package/dist/agent/subagent.d.ts +20 -10
  185. package/dist/agent/subagent.js +266 -29
  186. package/dist/agent/tool_response_directory.d.ts +24 -0
  187. package/dist/agent/tool_response_directory.js +61 -0
  188. package/dist/agent/tool_response_source.d.ts +8 -0
  189. package/dist/agent/tool_response_source.js +49 -0
  190. package/dist/agent/tool_response_store.d.ts +75 -4
  191. package/dist/agent/tool_response_store.js +583 -64
  192. package/dist/agent/tools/ask_user.d.ts +3 -1
  193. package/dist/agent/tools/ask_user.js +30 -11
  194. package/dist/agent/tools/background.js +1 -0
  195. package/dist/agent/tools/benchmark_cpu.d.ts +2 -0
  196. package/dist/agent/tools/benchmark_cpu.js +102 -0
  197. package/dist/agent/tools/compare_benchmarks.d.ts +2 -0
  198. package/dist/agent/tools/compare_benchmarks.js +53 -0
  199. package/dist/agent/tools/deferred.js +1 -0
  200. package/dist/agent/tools/delegate.js +18 -2
  201. package/dist/agent/tools/helper_requirements.d.ts +7 -0
  202. package/dist/agent/tools/helper_requirements.js +19 -0
  203. package/dist/agent/tools/index.d.ts +1 -0
  204. package/dist/agent/tools/index.js +3 -0
  205. package/dist/agent/tools/measurement_report.d.ts +22 -0
  206. package/dist/agent/tools/measurement_report.js +190 -0
  207. package/dist/agent/tools/pane.d.ts +0 -7
  208. package/dist/agent/tools/pane.js +5 -4
  209. package/dist/agent/tools/project_context.d.ts +3 -0
  210. package/dist/agent/tools/project_context.js +45 -0
  211. package/dist/agent/tools/recall_tool_response.d.ts +3 -5
  212. package/dist/agent/tools/recall_tool_response.js +19 -29
  213. package/dist/agent/tools/registry.d.ts +1 -0
  214. package/dist/agent/tools/registry.js +23 -0
  215. package/dist/agent/tools/related_sessions.d.ts +2 -0
  216. package/dist/agent/tools/related_sessions.js +156 -0
  217. package/dist/agent/tools/routine.js +13 -3
  218. package/dist/agent/tools/session_evidence.d.ts +3 -0
  219. package/dist/agent/tools/session_evidence.js +72 -0
  220. package/dist/agent/tools/shell.d.ts +4 -3
  221. package/dist/agent/tools/shell.js +174 -47
  222. package/dist/agent/tools/tool_search.js +3 -2
  223. package/dist/agent/tools/types.d.ts +28 -0
  224. package/dist/agent/tools/verify_artifact.d.ts +2 -0
  225. package/dist/agent/tools/verify_artifact.js +60 -0
  226. package/dist/agent/tools/workflow.js +1 -0
  227. package/dist/app/activity.d.ts +6 -1
  228. package/dist/app/activity.js +81 -12
  229. package/dist/app/agent_runner.d.ts +6 -1
  230. package/dist/app/agent_runner.js +34 -19
  231. package/dist/app/command_context.js +106 -10
  232. package/dist/app/controller.d.ts +15 -4
  233. package/dist/app/controller.js +29 -3
  234. package/dist/app/escape_stop.d.ts +11 -0
  235. package/dist/app/escape_stop.js +15 -0
  236. package/dist/app/liveness.d.ts +6 -4
  237. package/dist/app/liveness.js +13 -3
  238. package/dist/app/model_catalog_cache.d.ts +5 -0
  239. package/dist/app/model_catalog_cache.js +138 -0
  240. package/dist/app/ordered_transcript.js +43 -4
  241. package/dist/app/prompt_turn.d.ts +14 -0
  242. package/dist/app/prompt_turn.js +53 -0
  243. package/dist/app/recap.d.ts +3 -0
  244. package/dist/app/recap.js +9 -3
  245. package/dist/app/restart.d.ts +3 -2
  246. package/dist/app/restart.js +22 -7
  247. package/dist/app/rewind.d.ts +3 -3
  248. package/dist/app/rewind.js +3 -3
  249. package/dist/app/selection_completion.d.ts +17 -2
  250. package/dist/app/selection_completion.js +84 -9
  251. package/dist/app/session_manager.d.ts +38 -6
  252. package/dist/app/session_manager.js +263 -60
  253. package/dist/app/session_messages.d.ts +3 -0
  254. package/dist/app/session_messages.js +60 -0
  255. package/dist/app/task_scope_router.d.ts +20 -0
  256. package/dist/app/task_scope_router.js +173 -0
  257. package/dist/app/transcript_window.d.ts +2 -0
  258. package/dist/app/transcript_window.js +4 -0
  259. package/dist/app/workspace_admission_details.d.ts +3 -0
  260. package/dist/app/workspace_admission_details.js +26 -0
  261. package/dist/app/workspace_layout_controller.d.ts +11 -0
  262. package/dist/app/workspace_layout_controller.js +88 -0
  263. package/dist/app/workspace_monitor.d.ts +1 -0
  264. package/dist/app/workspace_monitor.js +216 -0
  265. package/dist/app/workspace_presets.d.ts +29 -0
  266. package/dist/app/workspace_presets.js +192 -0
  267. package/dist/attention/queue.d.ts +37 -0
  268. package/dist/attention/queue.js +183 -0
  269. package/dist/bench/rf_shared.d.ts +2 -0
  270. package/dist/board/binding.d.ts +42 -0
  271. package/dist/board/binding.js +38 -0
  272. package/dist/board/client.d.ts +42 -0
  273. package/dist/board/client.js +60 -0
  274. package/dist/cli.js +1 -1
  275. package/dist/cli_args.js +19 -17
  276. package/dist/cli_main.js +110 -13
  277. package/dist/cli_ratatui.d.ts +183 -16
  278. package/dist/cli_ratatui.js +3989 -1255
  279. package/dist/components/ActivityLine.d.ts +3 -2
  280. package/dist/components/ActivityLine.js +2 -2
  281. package/dist/components/InputArea.d.ts +19 -1
  282. package/dist/components/InputArea.js +264 -190
  283. package/dist/components/MessageList.d.ts +2 -0
  284. package/dist/components/MessageList.js +3 -1
  285. package/dist/components/SingleMessage.d.ts +2 -0
  286. package/dist/components/SingleMessage.js +4 -2
  287. package/dist/components/StatusBar.d.ts +4 -2
  288. package/dist/components/StatusBar.js +3 -1
  289. package/dist/conductor_branch.js +3 -0
  290. package/dist/config/api_retry.d.ts +6 -1
  291. package/dist/config/api_retry.js +19 -1
  292. package/dist/config/defaults.d.ts +2 -1
  293. package/dist/config/defaults.js +9 -2
  294. package/dist/config/message_display.d.ts +1 -0
  295. package/dist/config/message_display.js +17 -2
  296. package/dist/config/permissions.d.ts +21 -0
  297. package/dist/config/permissions.js +89 -0
  298. package/dist/config/resolved.d.ts +2 -2
  299. package/dist/config/types.d.ts +32 -5
  300. package/dist/config.d.ts +38 -4
  301. package/dist/config.js +290 -42
  302. package/dist/context/project_intelligence.d.ts +44 -0
  303. package/dist/context/project_intelligence.js +246 -0
  304. package/dist/desktop/cli_launch.d.ts +8 -0
  305. package/dist/desktop/cli_launch.js +6 -0
  306. package/dist/desktop/cli_shim.d.ts +8 -0
  307. package/dist/desktop/cli_shim.js +120 -0
  308. package/dist/desktop/runtime.d.ts +16 -0
  309. package/dist/desktop/runtime.js +161 -0
  310. package/dist/desktop/worker_launch.d.ts +7 -0
  311. package/dist/desktop/worker_launch.js +7 -0
  312. package/dist/diagnostics/cargo_mutants_selection.d.ts +27 -0
  313. package/dist/diagnostics/cargo_mutants_selection.js +48 -0
  314. package/dist/diagnostics/native_terminal_benchmark.d.ts +58 -0
  315. package/dist/diagnostics/native_terminal_benchmark.js +1247 -0
  316. package/dist/diagnostics/session_evidence_package.d.ts +40 -0
  317. package/dist/diagnostics/session_evidence_package.js +234 -0
  318. package/dist/diagnostics/session_export.d.ts +93 -0
  319. package/dist/diagnostics/session_export.js +634 -0
  320. package/dist/emulation/tool_adapters.js +48 -18
  321. package/dist/emulation/ztc_addendum.d.ts +1 -0
  322. package/dist/emulation/ztc_addendum.js +13 -12
  323. package/dist/environment/service_runner.d.ts +1 -0
  324. package/dist/environment/service_runner.js +68 -0
  325. package/dist/environment/store.d.ts +120 -0
  326. package/dist/environment/store.js +387 -0
  327. package/dist/events.d.ts +40 -1
  328. package/dist/events.js +10 -17
  329. package/dist/goal_contract.d.ts +25 -0
  330. package/dist/goal_contract.js +44 -0
  331. package/dist/headless.d.ts +31 -0
  332. package/dist/headless.js +578 -70
  333. package/dist/headless_cli.js +8 -0
  334. package/dist/headless_cli_args.d.ts +1 -0
  335. package/dist/headless_cli_args.js +1 -0
  336. package/dist/intake/cli.d.ts +1 -0
  337. package/dist/intake/cli.js +33 -0
  338. package/dist/intake/format.d.ts +2 -0
  339. package/dist/intake/format.js +14 -0
  340. package/dist/intake/notifications.d.ts +16 -0
  341. package/dist/intake/notifications.js +132 -0
  342. package/dist/intake/store.d.ts +56 -0
  343. package/dist/intake/store.js +238 -0
  344. package/dist/library.d.ts +8 -0
  345. package/dist/library.js +19 -10
  346. package/dist/mcp/client.d.ts +1 -0
  347. package/dist/mcp/client.js +20 -0
  348. package/dist/modes/builtin/plan.yaml +2 -2
  349. package/dist/modes/handlers.js +1 -1
  350. package/dist/onboarding/first_run.d.ts +3 -0
  351. package/dist/onboarding/first_run.js +33 -25
  352. package/dist/onboarding/setup.d.ts +32 -0
  353. package/dist/onboarding/setup.js +133 -0
  354. package/dist/onboarding/setup_agent_health.d.ts +17 -0
  355. package/dist/onboarding/setup_agent_health.js +79 -0
  356. package/dist/onboarding/setup_environment.d.ts +66 -0
  357. package/dist/onboarding/setup_environment.js +219 -0
  358. package/dist/onboarding/setup_workspace.d.ts +17 -0
  359. package/dist/onboarding/setup_workspace.js +129 -0
  360. package/dist/optimize/adapters/index.d.ts +4 -1
  361. package/dist/optimize/adapters/index.js +7 -0
  362. package/dist/optimize/adapters/kernelbench.js +14 -5
  363. package/dist/optimize/adapters/popcorn.js +3 -2
  364. package/dist/optimize/adapters/profile_benchmark.js +13 -7
  365. package/dist/optimize/adapters/rfbench.js +25 -14
  366. package/dist/optimize/adapters/types.d.ts +3 -0
  367. package/dist/optimize/adapters/zergpod.js +5 -2
  368. package/dist/optimize/baseline.js +10 -21
  369. package/dist/optimize/branch.js +9 -12
  370. package/dist/optimize/combine.js +2 -3
  371. package/dist/optimize/executor.js +34 -48
  372. package/dist/optimize/measurements.d.ts +55 -0
  373. package/dist/optimize/measurements.js +173 -0
  374. package/dist/optimize/results.d.ts +1 -0
  375. package/dist/optimize/results.js +11 -33
  376. package/dist/optimize/tge.js +2 -1
  377. package/dist/panes/initial_input.d.ts +19 -0
  378. package/dist/panes/initial_input.js +206 -0
  379. package/dist/panes/labels.d.ts +16 -0
  380. package/dist/panes/labels.js +42 -0
  381. package/dist/panes/model_catalog.d.ts +3 -3
  382. package/dist/panes/model_catalog.js +28 -4
  383. package/dist/panes/pane_registry.js +6 -2
  384. package/dist/panes/types.d.ts +3 -0
  385. package/dist/panes/ztc_launch.js +19 -0
  386. package/dist/plugin/optimization.d.ts +2 -0
  387. package/dist/plugin/optimization.js +1 -0
  388. package/dist/plugin/runtime.d.ts +2 -0
  389. package/dist/plugin/simulation.d.ts +6 -1
  390. package/dist/plugin/simulation_contract.d.ts +836 -1
  391. package/dist/plugin/simulation_documents.d.ts +22 -0
  392. package/dist/plugin/simulation_documents.js +1 -0
  393. package/dist/plugin/simulation_interventions.d.ts +103 -0
  394. package/dist/plugin/simulation_interventions.js +1 -0
  395. package/dist/plugin/simulation_living.d.ts +1 -0
  396. package/dist/plugin/simulation_living.js +3 -0
  397. package/dist/plugin/simulation_meetings.d.ts +121 -0
  398. package/dist/plugin/simulation_meetings.js +1 -0
  399. package/dist/plugin/simulation_story_review.d.ts +111 -0
  400. package/dist/plugin/simulation_story_review.js +1 -0
  401. package/dist/plugin/simulation_storyteller.d.ts +91 -0
  402. package/dist/plugin/simulation_storyteller.js +1 -0
  403. package/dist/plugin/simulation_structured.d.ts +2 -0
  404. package/dist/plugin/simulation_structured.js +2 -0
  405. package/dist/plugin/simulation_toolkit.d.ts +21 -0
  406. package/dist/plugin/simulation_toolkit.js +24 -0
  407. package/dist/prompts/tool_delegate_task.j2 +1 -1
  408. package/dist/remote-broker/Dockerfile +10 -0
  409. package/dist/remote-broker/archive.py +1227 -0
  410. package/dist/remote-broker/cutover.py +761 -0
  411. package/dist/remote-broker/requirements.txt +5 -0
  412. package/dist/remote-broker/resources.json +6 -0
  413. package/dist/remote-broker/resources.write-staging.example.json +18 -0
  414. package/dist/remote-broker/retained.py +686 -0
  415. package/dist/remote-broker/retained_cleanup.py +550 -0
  416. package/dist/remote-broker/server.py +648 -0
  417. package/dist/remote-broker/worker.py +1007 -0
  418. package/dist/router_auth.d.ts +31 -0
  419. package/dist/router_auth.js +155 -9
  420. package/dist/runbooks/catalog.d.ts +3 -0
  421. package/dist/runbooks/catalog.js +26 -0
  422. package/dist/runbooks/library.d.ts +11 -0
  423. package/dist/runbooks/library.js +95 -0
  424. package/dist/runbooks/package.d.ts +43 -0
  425. package/dist/runbooks/package.js +102 -0
  426. package/dist/session.d.ts +65 -13
  427. package/dist/session.js +548 -43
  428. package/dist/session_handoff.d.ts +25 -0
  429. package/dist/session_handoff.js +322 -0
  430. package/dist/session_handoff_contract.d.ts +89 -0
  431. package/dist/session_handoff_contract.js +179 -0
  432. package/dist/session_media.d.ts +41 -0
  433. package/dist/session_media.js +357 -0
  434. package/dist/session_ownership.d.ts +16 -0
  435. package/dist/session_ownership.js +221 -0
  436. package/dist/session_public.d.ts +10 -2
  437. package/dist/session_public.js +6 -1
  438. package/dist/simulation/dynamic_history.d.ts +42 -0
  439. package/dist/simulation/dynamic_history.js +173 -0
  440. package/dist/simulation/engines/swarm/pane_manager.js +7 -6
  441. package/dist/simulation/inference.d.ts +3 -1
  442. package/dist/simulation/inference.js +19 -1
  443. package/dist/simulation/intervention_generation.d.ts +27 -0
  444. package/dist/simulation/intervention_generation.js +246 -0
  445. package/dist/simulation/intervention_material.d.ts +4 -0
  446. package/dist/simulation/intervention_material.js +81 -0
  447. package/dist/simulation/living/context.d.ts +3130 -0
  448. package/dist/simulation/living/context.js +944 -0
  449. package/dist/simulation/living/definer.d.ts +12 -0
  450. package/dist/simulation/living/definer.js +223 -0
  451. package/dist/simulation/living/definition.d.ts +257 -0
  452. package/dist/simulation/living/definition.js +341 -0
  453. package/dist/simulation/living/frame.d.ts +259 -0
  454. package/dist/simulation/living/frame.js +223 -0
  455. package/dist/simulation/living/identifiers.d.ts +2 -0
  456. package/dist/simulation/living/identifiers.js +12 -0
  457. package/dist/simulation/living/index.d.ts +15 -0
  458. package/dist/simulation/living/index.js +15 -0
  459. package/dist/simulation/living/inference.d.ts +219 -0
  460. package/dist/simulation/living/inference.js +576 -0
  461. package/dist/simulation/living/mechanics.d.ts +54 -0
  462. package/dist/simulation/living/mechanics.js +588 -0
  463. package/dist/simulation/living/model-input.d.ts +25 -0
  464. package/dist/simulation/living/model-input.js +215 -0
  465. package/dist/simulation/living/open-world.d.ts +257 -0
  466. package/dist/simulation/living/open-world.js +102 -0
  467. package/dist/simulation/living/projection.d.ts +7 -0
  468. package/dist/simulation/living/projection.js +31 -0
  469. package/dist/simulation/living/recall.d.ts +17 -0
  470. package/dist/simulation/living/recall.js +25 -0
  471. package/dist/simulation/living/reduce.d.ts +15 -0
  472. package/dist/simulation/living/reduce.js +1853 -0
  473. package/dist/simulation/living/replay.d.ts +6 -0
  474. package/dist/simulation/living/replay.js +22 -0
  475. package/dist/simulation/living/runtime.d.ts +140 -0
  476. package/dist/simulation/living/runtime.js +3020 -0
  477. package/dist/simulation/living/shared-kinds.d.ts +24 -0
  478. package/dist/simulation/living/shared-kinds.js +96 -0
  479. package/dist/simulation/living/types.d.ts +2785 -0
  480. package/dist/simulation/living/types.js +669 -0
  481. package/dist/simulation/llm.d.ts +3 -1
  482. package/dist/simulation/llm.js +90 -30
  483. package/dist/simulation/memory/embedding.d.ts +1 -1
  484. package/dist/simulation/memory/embedding.js +9 -3
  485. package/dist/simulation/memory/filesystem.d.ts +2 -0
  486. package/dist/simulation/memory/filesystem.js +5 -1
  487. package/dist/simulation/memory/filesystem_file_tree.d.ts +4 -1
  488. package/dist/simulation/memory/filesystem_file_tree.js +41 -10
  489. package/dist/simulation/memory/filesystem_invariants.js +1 -2
  490. package/dist/simulation/memory/filesystem_types.d.ts +1 -0
  491. package/dist/simulation/memory/memory.d.ts +2 -0
  492. package/dist/simulation/memory/memory.js +5 -1
  493. package/dist/simulation/orchestration/intent.js +0 -2
  494. package/dist/simulation/orchestration/lifecycle.js +0 -2
  495. package/dist/simulation/plugin_host.d.ts +25 -1
  496. package/dist/simulation/plugin_host.js +334 -17
  497. package/dist/simulation/session_documents.d.ts +20 -0
  498. package/dist/simulation/session_documents.js +62 -0
  499. package/dist/simulation/session_input_validation.d.ts +43 -0
  500. package/dist/simulation/session_input_validation.js +364 -0
  501. package/dist/simulation/session_inputs.d.ts +32 -0
  502. package/dist/simulation/session_inputs.js +154 -0
  503. package/dist/simulation/telemetry.d.ts +11 -14
  504. package/dist/simulation/telemetry.js +177 -54
  505. package/dist/simulation/toolkit/bounded_turns.d.ts +13 -0
  506. package/dist/simulation/toolkit/bounded_turns.js +80 -0
  507. package/dist/simulation/toolkit/dynamic_agents.d.ts +25 -0
  508. package/dist/simulation/toolkit/dynamic_agents.js +218 -0
  509. package/dist/simulation/toolkit/dynamic_digest.d.ts +1 -0
  510. package/dist/simulation/toolkit/dynamic_digest.js +8 -0
  511. package/dist/simulation/toolkit/dynamic_documents.d.ts +7 -0
  512. package/dist/simulation/toolkit/dynamic_documents.js +71 -0
  513. package/dist/simulation/toolkit/dynamic_driver.d.ts +8 -0
  514. package/dist/simulation/toolkit/dynamic_driver.js +269 -0
  515. package/dist/simulation/toolkit/dynamic_game.d.ts +53 -0
  516. package/dist/simulation/toolkit/dynamic_game.js +805 -0
  517. package/dist/simulation/toolkit/dynamic_knowledge.d.ts +15 -0
  518. package/dist/simulation/toolkit/dynamic_knowledge.js +91 -0
  519. package/dist/simulation/toolkit/dynamic_mechanics.d.ts +22 -0
  520. package/dist/simulation/toolkit/dynamic_mechanics.js +910 -0
  521. package/dist/simulation/toolkit/dynamic_meetings.d.ts +239 -0
  522. package/dist/simulation/toolkit/dynamic_meetings.js +350 -0
  523. package/dist/simulation/toolkit/dynamic_progress.d.ts +131 -0
  524. package/dist/simulation/toolkit/dynamic_progress.js +214 -0
  525. package/dist/simulation/toolkit/dynamic_projection.d.ts +9 -0
  526. package/dist/simulation/toolkit/dynamic_projection.js +219 -0
  527. package/dist/simulation/toolkit/dynamic_runtime.d.ts +412 -0
  528. package/dist/simulation/toolkit/dynamic_runtime.js +6536 -0
  529. package/dist/simulation/toolkit/dynamic_state.d.ts +111 -0
  530. package/dist/simulation/toolkit/dynamic_state.js +1967 -0
  531. package/dist/simulation/toolkit/dynamic_story_review.d.ts +508 -0
  532. package/dist/simulation/toolkit/dynamic_story_review.js +333 -0
  533. package/dist/simulation/toolkit/dynamic_storyteller.d.ts +77 -0
  534. package/dist/simulation/toolkit/dynamic_storyteller.js +114 -0
  535. package/dist/simulation/toolkit/dynamic_storyteller_runtime.d.ts +26 -0
  536. package/dist/simulation/toolkit/dynamic_storyteller_runtime.js +126 -0
  537. package/dist/simulation/toolkit/dynamic_world.d.ts +22 -0
  538. package/dist/simulation/toolkit/dynamic_world.js +377 -0
  539. package/dist/simulation/toolkit/structured_output.d.ts +5 -0
  540. package/dist/simulation/toolkit/structured_output.js +321 -0
  541. package/dist/simulation/types/world.d.ts +2 -0
  542. package/dist/simulation/world/artifact_store.js +1 -1
  543. package/dist/simulation/world/memory_manager.d.ts +5 -0
  544. package/dist/simulation/world/memory_manager.js +17 -2
  545. package/dist/simulation/world/state.d.ts +3 -2
  546. package/dist/simulation/world/state.js +15 -5
  547. package/dist/skills/bundled/measurement-validation/SKILL.md +144 -0
  548. package/dist/terminal_attach.d.ts +1 -0
  549. package/dist/terminal_attach.js +113 -0
  550. package/dist/tool_progress.d.ts +3 -0
  551. package/dist/tool_progress.js +27 -0
  552. package/dist/types.d.ts +145 -10
  553. package/dist/types.js +3 -0
  554. package/dist/ui/core/input.d.ts +3 -0
  555. package/dist/ui/core/input_segments.d.ts +18 -1
  556. package/dist/ui/core/input_segments.js +131 -47
  557. package/dist/ui/core/input_state.d.ts +12 -0
  558. package/dist/ui/core/layout_yoga.d.ts +1 -1
  559. package/dist/ui/core/turn_metadata.d.ts +5 -0
  560. package/dist/ui/core/turn_metadata.js +22 -0
  561. package/dist/ui/ink/render.d.ts +2 -1
  562. package/dist/ui/ink/render.js +6 -5
  563. package/dist/ui/ratatui/headless_pane_manager.d.ts +14 -1
  564. package/dist/ui/ratatui/headless_pane_manager.js +293 -104
  565. package/dist/ui/ratatui/index.d.ts +1 -0
  566. package/dist/ui/ratatui/input.d.ts +4 -0
  567. package/dist/ui/ratatui/input.js +15 -0
  568. package/dist/ui/ratatui/ipc_path.d.ts +2 -0
  569. package/dist/ui/ratatui/ipc_path.js +29 -1
  570. package/dist/ui/ratatui/mux_persistence.d.ts +3 -1
  571. package/dist/ui/ratatui/mux_persistence.js +139 -1
  572. package/dist/ui/ratatui/pane_relay.d.ts +1 -1
  573. package/dist/ui/ratatui/pane_relay.js +55 -27
  574. package/dist/ui/ratatui/process.d.ts +17 -1
  575. package/dist/ui/ratatui/process.js +80 -7
  576. package/dist/ui/ratatui/protocol.d.ts +236 -1
  577. package/dist/ui/ratatui/protocol.js +90 -0
  578. package/dist/ui/scrollback.d.ts +2 -1
  579. package/dist/ui/scrollback.js +9 -4
  580. package/dist/ui/stream_typewriter.d.ts +8 -3
  581. package/dist/ui/stream_typewriter.js +30 -1
  582. package/dist/ui/streaming_scrollback.d.ts +1 -0
  583. package/dist/ui/streaming_scrollback.js +1 -1
  584. package/dist/ui/transcript_render_cache.js +10 -0
  585. package/dist/ui/views/activity_line.d.ts +5 -3
  586. package/dist/ui/views/activity_line.js +65 -7
  587. package/dist/ui/views/app.d.ts +6 -3
  588. package/dist/ui/views/app.js +17 -6
  589. package/dist/ui/views/completion_menu.js +10 -5
  590. package/dist/ui/views/input_area.d.ts +7 -3
  591. package/dist/ui/views/input_area.js +15 -9
  592. package/dist/ui/views/message_list.d.ts +4 -1
  593. package/dist/ui/views/message_list.js +89 -19
  594. package/dist/ui/views/queue_panel.d.ts +3 -1
  595. package/dist/ui/views/queue_panel.js +9 -2
  596. package/dist/ui/views/status_bar.d.ts +4 -2
  597. package/dist/ui/views/status_bar.js +28 -13
  598. package/dist/ui/views/theme.d.ts +2 -0
  599. package/dist/ui/views/theme.js +2 -0
  600. package/dist/ui/widgets/color_panel.js +18 -0
  601. package/dist/ui/widgets/form.js +8 -0
  602. package/dist/ui/widgets/log_view.js +7 -0
  603. package/dist/ui/widgets/navigator_panel.js +8 -0
  604. package/dist/ui/widgets/prompt_viewer.js +2 -0
  605. package/dist/ui/widgets/questionnaire.d.ts +2 -0
  606. package/dist/ui/widgets/questionnaire.js +79 -16
  607. package/dist/ui/widgets/resume_panel.d.ts +2 -0
  608. package/dist/ui/widgets/resume_panel.js +26 -15
  609. package/dist/ui/widgets/rewind_panel.d.ts +2 -2
  610. package/dist/ui/widgets/rewind_panel.js +4 -2
  611. package/dist/ui/widgets/select.js +16 -27
  612. package/dist/ui/widgets/settings_panel.js +16 -0
  613. package/dist/ui/widgets/status_line_panel.d.ts +1 -0
  614. package/dist/ui/widgets/status_line_panel.js +30 -4
  615. package/dist/ui/widgets/text_input.d.ts +2 -0
  616. package/dist/ui/widgets/text_input.js +15 -1
  617. package/dist/ui/widgets/types.d.ts +2 -0
  618. package/dist/usage_projection.d.ts +24 -0
  619. package/dist/usage_projection.js +130 -0
  620. package/dist/usage_snapshot.d.ts +36 -0
  621. package/dist/usage_snapshot.js +131 -0
  622. package/dist/utils/assistant_message.d.ts +2 -0
  623. package/dist/utils/assistant_message.js +5 -0
  624. package/dist/utils/atomic_write.d.ts +6 -2
  625. package/dist/utils/atomic_write.js +29 -4
  626. package/dist/utils/checked_shell.d.ts +25 -0
  627. package/dist/utils/checked_shell.js +107 -0
  628. package/dist/utils/compaction.d.ts +4 -1
  629. package/dist/utils/compaction.js +31 -7
  630. package/dist/utils/context.d.ts +4 -4
  631. package/dist/utils/context.js +14 -12
  632. package/dist/utils/deepseek.d.ts +2 -2
  633. package/dist/utils/deepseek.js +13 -5
  634. package/dist/utils/ephemeral.js +4 -0
  635. package/dist/utils/ephemeral_tools.d.ts +18 -0
  636. package/dist/utils/ephemeral_tools.js +97 -0
  637. package/dist/utils/jev_client.d.ts +4 -0
  638. package/dist/utils/jev_client.js +15 -0
  639. package/dist/utils/model_cache.d.ts +15 -0
  640. package/dist/utils/model_cache.js +143 -0
  641. package/dist/utils/models.d.ts +4 -2
  642. package/dist/utils/models.js +12 -16
  643. package/dist/utils/reasoning.d.ts +8 -1
  644. package/dist/utils/reasoning.js +31 -11
  645. package/dist/utils/router_catalog.d.ts +49 -0
  646. package/dist/utils/router_catalog.js +271 -0
  647. package/dist/utils/sandbox.d.ts +9 -0
  648. package/dist/utils/sandbox.js +118 -15
  649. package/dist/utils/shell.d.ts +7 -0
  650. package/dist/utils/shell.js +98 -34
  651. package/dist/utils/subprocess_env.d.ts +3 -0
  652. package/dist/utils/subprocess_env.js +27 -1
  653. package/dist/web/accounts_mirror.d.ts +3 -1
  654. package/dist/web/accounts_mirror.js +13 -9
  655. package/dist/web/child_publication.d.ts +17 -0
  656. package/dist/web/child_publication.js +45 -0
  657. package/dist/web/mirror_authenticator.d.ts +31 -11
  658. package/dist/web/mirror_authenticator.js +67 -17
  659. package/dist/web/mirror_client.d.ts +31 -4
  660. package/dist/web/mirror_client.js +189 -23
  661. package/dist/web/mirror_stream.d.ts +84 -22
  662. package/dist/web/mirror_stream.js +676 -95
  663. package/dist/web/observer_query_redaction.d.ts +6 -0
  664. package/dist/web/observer_query_redaction.js +58 -0
  665. package/dist/web/pane_registry.d.ts +2 -0
  666. package/dist/web/pane_registry.js +86 -22
  667. package/dist/web/tool_image.d.ts +6 -0
  668. package/dist/web/tool_image.js +17 -0
  669. package/dist/web/view_plugin.d.ts +14 -0
  670. package/dist/web/view_plugin.js +23 -1
  671. package/dist/worker/executor.js +31 -12
  672. package/dist/worker/index.d.ts +1 -0
  673. package/dist/worker/toolsets.js +3 -1
  674. package/dist/worker/types.d.ts +12 -1
  675. package/dist/workflows/registry.js +1 -0
  676. package/dist/workflows/registry_handle.d.ts +2 -0
  677. package/dist/workflows/runtime.d.ts +2 -0
  678. package/dist/workflows/runtime.js +1 -0
  679. package/dist/workspace_agent.d.ts +7 -0
  680. package/dist/workspace_agent.js +36 -0
  681. package/dist/workspace_collision.d.ts +76 -0
  682. package/dist/workspace_collision.js +688 -0
  683. package/dist/workspace_layout.d.ts +18 -0
  684. package/dist/workspace_layout.js +121 -0
  685. package/dist/workspace_runtime.d.ts +44 -0
  686. package/dist/workspace_runtime.js +82 -0
  687. package/dist/workspace_session_context.d.ts +62 -0
  688. package/dist/workspace_session_context.js +160 -0
  689. package/dist/zlm-embed.mjs +32518 -9615
  690. package/dist/zlm.js +1 -0
  691. package/node_modules/@zerg/model-contracts/LICENSE.md +375 -0
  692. package/node_modules/@zerg/model-contracts/README.md +90 -0
  693. package/node_modules/@zerg/model-contracts/index.d.ts +20 -0
  694. package/node_modules/@zerg/model-contracts/index.js +223 -0
  695. package/node_modules/@zerg/model-contracts/package.json +8 -0
  696. package/node_modules/glob/node_modules/brace-expansion/index.js +78 -22
  697. package/node_modules/glob/node_modules/brace-expansion/package.json +1 -1
  698. package/node_modules/readdir-glob/node_modules/brace-expansion/index.js +78 -22
  699. package/node_modules/readdir-glob/node_modules/brace-expansion/package.json +1 -1
  700. package/package.json +45 -24
  701. package/packages/model-contracts/LICENSE.md +375 -0
  702. package/packages/model-contracts/README.md +90 -0
  703. package/packages/model-contracts/index.d.ts +20 -0
  704. package/packages/model-contracts/index.js +223 -0
  705. package/packages/model-contracts/package.json +8 -0
  706. package/remote-broker/Dockerfile +10 -0
  707. package/remote-broker/README.md +308 -0
  708. package/remote-broker/archive.py +1227 -0
  709. package/remote-broker/cutover.py +761 -0
  710. package/remote-broker/requirements.txt +5 -0
  711. package/remote-broker/resources.example.json +6 -0
  712. package/remote-broker/resources.write-staging.example.json +18 -0
  713. package/remote-broker/retained.py +686 -0
  714. package/remote-broker/retained_cleanup.py +550 -0
  715. package/remote-broker/server.py +648 -0
  716. package/scripts/build-remote-broker.mjs +13 -0
  717. package/scripts/ensure-local-packages.mjs +6 -0
  718. package/scripts/node-pty-helpers.mjs +103 -0
@@ -0,0 +1,119 @@
1
+ const MAX_PLAN_BYTES = 16 * 1024;
2
+ const MAX_STEPS = 8;
3
+ const MAX_STAGES = 8;
4
+ const utf8 = new TextEncoder();
5
+ const stepId = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;
6
+ function object(value) {
7
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
8
+ return false;
9
+ const prototype = Object.getPrototypeOf(value);
10
+ return prototype === Object.prototype || prototype === null;
11
+ }
12
+ function keys(value, required, optional = []) {
13
+ return required.every(key => Object.hasOwn(value, key))
14
+ && Object.keys(value).every(key => required.includes(key) || optional.includes(key));
15
+ }
16
+ function string(value, maxBytes, allowEmpty = false) {
17
+ return typeof value === 'string' && (allowEmpty || value.length > 0)
18
+ && !value.includes('\0') && utf8.encode(value).byteLength <= maxBytes;
19
+ }
20
+ function jsonBytes(value) {
21
+ try {
22
+ const encoded = JSON.stringify(value);
23
+ return encoded === undefined ? Infinity : utf8.encode(encoded).byteLength;
24
+ }
25
+ catch {
26
+ return Infinity;
27
+ }
28
+ }
29
+ function exitCode(value) {
30
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 && value <= 255;
31
+ }
32
+ function codes(value) {
33
+ if (!Array.isArray(value) || value.length < 1 || value.length > 8
34
+ || ![...value].every(exitCode) || new Set(value).size !== value.length)
35
+ return null;
36
+ return [...value];
37
+ }
38
+ /** Parse a bounded literal process plan; shell text is never inferred from its arguments. */
39
+ export function parseCheckedCommandPlan(value) {
40
+ if (jsonBytes(value) > MAX_PLAN_BYTES || !object(value) || !keys(value, ['steps'])
41
+ || !Array.isArray(value.steps) || value.steps.length < 1 || value.steps.length > MAX_STEPS)
42
+ return null;
43
+ const steps = [];
44
+ const ids = new Set();
45
+ for (const rawStep of value.steps) {
46
+ if (!object(rawStep) || !keys(rawStep, ['id', 'pipeline']) || typeof rawStep.id !== 'string'
47
+ || !stepId.test(rawStep.id) || ids.has(rawStep.id) || !Array.isArray(rawStep.pipeline)
48
+ || rawStep.pipeline.length < 1 || rawStep.pipeline.length > MAX_STAGES)
49
+ return null;
50
+ const pipeline = [];
51
+ for (const rawStage of rawStep.pipeline) {
52
+ if (!object(rawStage) || !keys(rawStage, ['executable', 'args'], ['acceptable_exit_codes'])
53
+ || !string(rawStage.executable, 512) || !Array.isArray(rawStage.args) || rawStage.args.length > 64
54
+ || ![...rawStage.args].every(arg => string(arg, 4096, true)))
55
+ return null;
56
+ const accepted = Object.hasOwn(rawStage, 'acceptable_exit_codes') ? codes(rawStage.acceptable_exit_codes) : [0];
57
+ if (!accepted)
58
+ return null;
59
+ pipeline.push({ executable: rawStage.executable, args: [...rawStage.args], acceptable_exit_codes: accepted });
60
+ }
61
+ ids.add(rawStep.id);
62
+ steps.push({ id: rawStep.id, pipeline });
63
+ }
64
+ const parsed = { steps };
65
+ return jsonBytes(parsed) <= MAX_PLAN_BYTES ? parsed : null;
66
+ }
67
+ /** Parse declared process outcomes without turning them into source or build qualification. */
68
+ export function parseCheckedCommandResult(value) {
69
+ if (!object(value) || !keys(value, ['schema_version', 'status', 'verification', 'plan_sha256', 'steps'], ['reason'])
70
+ || value.schema_version !== 1 || value.verification !== 'unknown'
71
+ || (value.status !== 'passed' && value.status !== 'failed' && value.status !== 'incomplete'
72
+ && value.status !== 'timed_out' && value.status !== 'cancelled')
73
+ || typeof value.plan_sha256 !== 'string' || !/^[a-f0-9]{64}$/.test(value.plan_sha256)
74
+ || (Object.hasOwn(value, 'reason') && !string(value.reason, 256, true))
75
+ || !Array.isArray(value.steps) || value.steps.length < 1 || value.steps.length > MAX_STEPS)
76
+ return null;
77
+ const steps = [];
78
+ const ids = new Set();
79
+ let predecessorUnaccepted = false;
80
+ let observedFailure = false;
81
+ for (const rawStep of value.steps) {
82
+ if (!object(rawStep) || !keys(rawStep, ['id', 'status', 'stages']) || typeof rawStep.id !== 'string'
83
+ || !stepId.test(rawStep.id) || ids.has(rawStep.id)
84
+ || (rawStep.status !== 'passed' && rawStep.status !== 'failed' && rawStep.status !== 'skipped' && rawStep.status !== 'unknown')
85
+ || !Array.isArray(rawStep.stages) || rawStep.stages.length < 1 || rawStep.stages.length > MAX_STAGES)
86
+ return null;
87
+ const stages = [];
88
+ for (const rawStage of rawStep.stages) {
89
+ if (!object(rawStage) || !keys(rawStage, ['exit_code', 'acceptable_exit_codes', 'accepted']))
90
+ return null;
91
+ const acceptedCodes = codes(rawStage.acceptable_exit_codes);
92
+ if (!acceptedCodes || (rawStage.exit_code !== null && !exitCode(rawStage.exit_code)))
93
+ return null;
94
+ const accepted = rawStage.exit_code === null ? null : acceptedCodes.includes(rawStage.exit_code);
95
+ if (rawStage.accepted !== accepted)
96
+ return null;
97
+ stages.push({ exit_code: rawStage.exit_code, acceptable_exit_codes: acceptedCodes, accepted });
98
+ }
99
+ const allKnown = stages.every(stage => stage.exit_code !== null);
100
+ const anyKnown = stages.some(stage => stage.exit_code !== null);
101
+ const failed = stages.some(stage => stage.accepted === false);
102
+ if ((rawStep.status === 'passed' && (!allKnown || failed))
103
+ || (rawStep.status === 'failed' && (!allKnown || !failed))
104
+ || (rawStep.status === 'unknown' && allKnown)
105
+ || (rawStep.status === 'skipped' && anyKnown)
106
+ || (predecessorUnaccepted && anyKnown))
107
+ return null;
108
+ if (rawStep.status !== 'passed')
109
+ predecessorUnaccepted = true;
110
+ observedFailure ||= failed;
111
+ ids.add(rawStep.id);
112
+ steps.push({ id: rawStep.id, status: rawStep.status, stages });
113
+ }
114
+ if ((value.status === 'passed' && !steps.every(step => step.status === 'passed'))
115
+ || (value.status === 'failed' && !observedFailure))
116
+ return null;
117
+ return { schema_version: 1, status: value.status, verification: 'unknown', plan_sha256: value.plan_sha256, steps,
118
+ ...(typeof value.reason === 'string' ? { reason: value.reason } : {}) };
119
+ }
@@ -0,0 +1,26 @@
1
+ /** Declared execution limits and cleanup policy, never evidence that cleanup succeeded. */
2
+ export interface CommandExecutionPolicy {
3
+ schema_version: 1;
4
+ mode: 'foreground' | 'background';
5
+ timeout_ms: number | null;
6
+ timeout_source: 'default' | 'explicit' | 'unlimited';
7
+ started_at: string;
8
+ deadline_at: string | null;
9
+ cleanup: {
10
+ scope: 'local_process_group' | 'local_process';
11
+ term_grace_ms: 250;
12
+ turn_interrupt: 'cancel' | 'preserve' | 'unknown';
13
+ host_shutdown: 'cancel';
14
+ remote: 'unknown';
15
+ };
16
+ }
17
+ /** A host observation of elapsed execution time, independent of wall-clock drift. */
18
+ export interface CommandExecutionObservation {
19
+ observed_at: string;
20
+ elapsed_ms: number;
21
+ }
22
+ export declare const COMMAND_EXECUTION_POLICY_MAX_BYTES = 2048;
23
+ /** Validate a bounded, detached execution policy for runtime and browser consumers. */
24
+ export declare function parseCommandExecutionPolicy(value: unknown): CommandExecutionPolicy | null;
25
+ /** Validate an observation without inferring elapsed time from its wall-clock timestamp. */
26
+ export declare function parseCommandExecutionObservation(value: unknown, startedAt: string): CommandExecutionObservation | null;
@@ -0,0 +1,91 @@
1
+ export const COMMAND_EXECUTION_POLICY_MAX_BYTES = 2048;
2
+ const encoder = new TextEncoder();
3
+ function record(value, fields) {
4
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
5
+ return null;
6
+ const prototype = Object.getPrototypeOf(value);
7
+ if (prototype !== Object.prototype && prototype !== null)
8
+ return null;
9
+ const keys = Reflect.ownKeys(value);
10
+ if (keys.length !== fields.length || keys.some(key => typeof key !== 'string' || !fields.includes(key)))
11
+ return null;
12
+ if (keys.some(key => !Object.hasOwn(Object.getOwnPropertyDescriptor(value, key), 'value')))
13
+ return null;
14
+ return value;
15
+ }
16
+ function instant(value) {
17
+ if (typeof value !== 'string')
18
+ return null;
19
+ const milliseconds = Date.parse(value);
20
+ return Number.isFinite(milliseconds) && new Date(milliseconds).toISOString() === value ? milliseconds : null;
21
+ }
22
+ function member(value, choices) {
23
+ return typeof value === 'string' && choices.includes(value);
24
+ }
25
+ function bounded(value) {
26
+ return encoder.encode(JSON.stringify(value)).byteLength <= COMMAND_EXECUTION_POLICY_MAX_BYTES;
27
+ }
28
+ /** Validate a bounded, detached execution policy for runtime and browser consumers. */
29
+ export function parseCommandExecutionPolicy(value) {
30
+ try {
31
+ const row = record(value, ['schema_version', 'mode', 'timeout_ms', 'timeout_source', 'started_at', 'deadline_at', 'cleanup']);
32
+ if (!row || row.schema_version !== 1 || !member(row.mode, ['foreground', 'background'])
33
+ || !member(row.timeout_source, ['default', 'explicit', 'unlimited']))
34
+ return null;
35
+ const cleanup = record(row.cleanup, ['scope', 'term_grace_ms', 'turn_interrupt', 'host_shutdown', 'remote']);
36
+ if (!cleanup || !member(cleanup.scope, ['local_process_group', 'local_process'])
37
+ || cleanup.term_grace_ms !== 250 || !member(cleanup.turn_interrupt, ['cancel', 'preserve', 'unknown'])
38
+ || cleanup.host_shutdown !== 'cancel' || cleanup.remote !== 'unknown')
39
+ return null;
40
+ const started = instant(row.started_at);
41
+ if (started === null)
42
+ return null;
43
+ let timeout;
44
+ let deadline;
45
+ if (row.timeout_source === 'unlimited') {
46
+ if (row.timeout_ms !== null || row.deadline_at !== null)
47
+ return null;
48
+ timeout = null;
49
+ deadline = null;
50
+ }
51
+ else {
52
+ if (typeof row.timeout_ms !== 'number' || !Number.isSafeInteger(row.timeout_ms)
53
+ || row.timeout_ms < 1 || row.timeout_ms > 86400000)
54
+ return null;
55
+ if (row.timeout_source === 'default' && row.timeout_ms !== 30000 && row.timeout_ms !== 120000)
56
+ return null;
57
+ const end = instant(row.deadline_at);
58
+ if (end === null || end !== started + row.timeout_ms)
59
+ return null;
60
+ timeout = row.timeout_ms;
61
+ deadline = row.deadline_at;
62
+ }
63
+ if (!bounded(row))
64
+ return null;
65
+ return {
66
+ schema_version: 1, mode: row.mode, timeout_ms: timeout, timeout_source: row.timeout_source,
67
+ started_at: row.started_at, deadline_at: deadline,
68
+ cleanup: { scope: cleanup.scope, term_grace_ms: 250, turn_interrupt: cleanup.turn_interrupt,
69
+ host_shutdown: 'cancel', remote: 'unknown' },
70
+ };
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ /** Validate an observation without inferring elapsed time from its wall-clock timestamp. */
77
+ export function parseCommandExecutionObservation(value, startedAt) {
78
+ try {
79
+ const row = record(value, ['observed_at', 'elapsed_ms']);
80
+ if (!row || typeof row.elapsed_ms !== 'number' || !Number.isSafeInteger(row.elapsed_ms) || row.elapsed_ms < 0)
81
+ return null;
82
+ const started = instant(startedAt);
83
+ const observed = instant(row.observed_at);
84
+ if (started === null || observed === null || observed < started || !bounded(row))
85
+ return null;
86
+ return { observed_at: row.observed_at, elapsed_ms: row.elapsed_ms };
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ }
@@ -1,4 +1,8 @@
1
1
  import { type RunShellCommandOptions } from '../../utils/shell.js';
2
+ import type { CheckedCommandResult } from './checked_commands.js';
3
+ import type { CommandVerificationReceipt, CurrentVerificationProjection } from './source_verification_contract.js';
4
+ import { type SourceInspectionGate } from './source_verification.js';
5
+ import { type CommandExecutionPolicy } from './command_execution_policy.js';
2
6
  export type CommandStatus = 'running' | 'completed' | 'failed' | 'cancelled' | 'timed_out' | 'interrupted';
3
7
  export interface CommandReceipt {
4
8
  job_id: string;
@@ -13,6 +17,28 @@ export interface CommandReceipt {
13
17
  owner_pid?: number;
14
18
  output_truncated?: boolean;
15
19
  dropped_bytes?: number;
20
+ checked?: CheckedCommandResult;
21
+ verification?: CommandVerificationReceipt;
22
+ verification_current?: CurrentVerificationProjection;
23
+ execution_policy?: CommandExecutionPolicy;
24
+ /** Host observation time; a terminal duration stays fixed after process completion. */
25
+ observed_at?: string;
26
+ elapsed_ms?: number;
27
+ }
28
+ export interface CommandReadResult extends CommandReceipt {
29
+ output: string;
30
+ cursor: number;
31
+ has_more: boolean;
32
+ }
33
+ export interface ManagedCommandObservation {
34
+ sessionId: string;
35
+ result: CommandReadResult;
36
+ requestedWaitMs: number;
37
+ kind: 'read' | 'launch';
38
+ }
39
+ export interface CommandProgressResult {
40
+ reason: 'output' | 'terminal' | 'deadline';
41
+ result: CommandReadResult;
16
42
  }
17
43
  export declare function subscribeCommandJobs(sessionId: string, listener: (jobs: CommandReceipt[]) => void): () => void;
18
44
  export declare function listCommandJobs(sessionId: string): CommandReceipt[];
@@ -24,24 +50,16 @@ export declare function startCommandJob(options: {
24
50
  shell: RunShellCommandOptions;
25
51
  maxJobs: number;
26
52
  signal?: AbortSignal;
53
+ verification?: CommandVerificationReceipt;
54
+ canInspectVerificationSource?: SourceInspectionGate;
27
55
  }): Promise<CommandReceipt>;
28
- export declare function readCommandJob(sessionId: string, jobId: string, cursor?: number, waitMs?: number, signal?: AbortSignal): Promise<{
29
- output: string;
30
- cursor: number;
31
- has_more: boolean;
32
- job_id: string;
33
- status: CommandStatus;
34
- command: string;
35
- cwd: string;
36
- started_at: string;
37
- ended_at?: string;
38
- exit_code?: number;
39
- error?: string;
40
- log_path: string;
41
- owner_pid?: number;
42
- output_truncated?: boolean;
43
- dropped_bytes?: number;
44
- }>;
45
- export declare function stopCommandJob(sessionId: string, jobId: string): Promise<CommandReceipt>;
56
+ export declare function readCommandJob(sessionId: string, jobId: string, cursor?: number, waitMs?: number, signal?: AbortSignal, canInspectSource?: SourceInspectionGate): Promise<CommandReadResult>;
57
+ export declare function waitForCommandProgress(sessionId: string, jobId: string, options: {
58
+ cursor?: number;
59
+ maxWaitMs: number;
60
+ signal?: AbortSignal;
61
+ canInspectVerificationSource?: SourceInspectionGate;
62
+ }): Promise<CommandProgressResult>;
63
+ export declare function stopCommandJob(sessionId: string, jobId: string, canInspectSource?: SourceInspectionGate): Promise<CommandReceipt>;
46
64
  export declare function shutdownCommandJobs(sessionId?: string): Promise<void>;
47
65
  export declare function interruptCommandJobs(sessionId: string): Promise<void>;
@@ -3,6 +3,9 @@ import { appendFileSync, closeSync, mkdirSync, openSync, readFileSync, readSync,
3
3
  import { homedir } from 'node:os';
4
4
  import { join } from 'node:path';
5
5
  import { runShellCommand } from '../../utils/shell.js';
6
+ import { finishCommandVerification, projectCurrentVerification } from './source_verification.js';
7
+ import { parseCommandExecutionPolicy } from './command_execution_policy.js';
8
+ import { writeFileAtomicSync } from '../../utils/atomic_write.js';
6
9
  const MAX_LOG_BYTES = 16 * 1024 * 1024;
7
10
  const MAX_RETAINED_JOBS = 64;
8
11
  const RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
@@ -27,6 +30,10 @@ function publish(sessionId) {
27
30
  catch { /* a view cannot change command lifecycle */ }
28
31
  }
29
32
  }
33
+ function notifyActivity(job) {
34
+ for (const listener of job.activity)
35
+ listener();
36
+ }
30
37
  /** Bound completed logs across all sessions; active processes keep their logs. */
31
38
  function pruneCommandLogs() {
32
39
  const root = join(process.env.ZTC_CONFIG_DIR || join(homedir(), '.ztc'), 'command-jobs');
@@ -100,12 +107,14 @@ function appendCommandOutput(sessionId, job, text) {
100
107
  if (first)
101
108
  save(sessionId, job.receipt);
102
109
  }
110
+ if (count > 0 || count < bytes.length)
111
+ notifyActivity(job);
103
112
  }
104
113
  function directory(sessionId) {
105
114
  return join(process.env.ZTC_CONFIG_DIR || join(homedir(), '.ztc'), 'command-jobs', createHash('sha256').update(sessionId).digest('hex').slice(0, 32));
106
115
  }
107
116
  function save(sessionId, receipt) {
108
- writeFileSync(join(directory(sessionId), `${receipt.job_id}.json`), JSON.stringify(receipt), { mode: 0o600 });
117
+ writeFileAtomicSync(join(directory(sessionId), `${receipt.job_id}.json`), JSON.stringify(receipt), { mode: 0o600 });
109
118
  }
110
119
  function resolveJob(sessionId, jobId) {
111
120
  if (!/^[0-9a-f-]{36}$/.test(jobId))
@@ -120,15 +129,43 @@ function resolveJob(sessionId, jobId) {
120
129
  catch {
121
130
  throw new Error('Command job not found in this session');
122
131
  }
132
+ const policy = parseCommandExecutionPolicy(receipt.execution_policy);
133
+ if (policy && policy.started_at === receipt.started_at)
134
+ receipt.execution_policy = policy;
135
+ else
136
+ delete receipt.execution_policy;
123
137
  if (receipt.status === 'running') {
124
- receipt = { ...receipt, status: 'interrupted', ended_at: new Date().toISOString(), error: 'Owning ZTC process ended; inspect output before retrying.' };
138
+ receipt = { ...receipt, status: 'interrupted', error: 'Owning ZTC process ended; inspect output before retrying.',
139
+ ...(receipt.verification?.process_outcome === 'running' ? { verification: { ...receipt.verification,
140
+ process_outcome: 'interrupted', source_binding: 'unknown' } } : {}) };
141
+ // Recovery observes missing ownership, not the original process's end time.
142
+ delete receipt.ended_at;
143
+ delete receipt.observed_at;
144
+ delete receipt.elapsed_ms;
125
145
  save(sessionId, receipt);
126
146
  }
127
- return { receipt, controller: new AbortController(), done: Promise.resolve(), loggedBytes: statSync(receipt.log_path).size };
147
+ return { receipt, controller: new AbortController(), done: Promise.resolve(), loggedBytes: statSync(receipt.log_path).size, activity: new Set(),
148
+ canInspectVerificationSource: () => false };
128
149
  }
129
150
  export function listCommandJobs(sessionId) {
130
151
  const jobs = [...(sessions.get(sessionId)?.values() ?? [])];
131
- return [...jobs.filter(job => job.receipt.status === 'running'), ...jobs.filter(job => job.receipt.status !== 'running').slice(-28)].map(job => ({ ...job.receipt }));
152
+ return [...jobs.filter(job => job.receipt.status === 'running'), ...jobs.filter(job => job.receipt.status !== 'running').slice(-28)].map(job => observeReceipt(job.receipt));
153
+ }
154
+ function observeReceipt(receipt) {
155
+ const result = structuredClone(receipt);
156
+ const now = Date.now();
157
+ const started = Date.parse(receipt.started_at);
158
+ const ended = receipt.status === 'running' ? now : Date.parse(receipt.ended_at ?? '');
159
+ const elapsed = ended - started;
160
+ if (Number.isSafeInteger(elapsed) && elapsed >= 0 && now >= started) {
161
+ result.observed_at = new Date(now).toISOString();
162
+ result.elapsed_ms = elapsed;
163
+ }
164
+ else {
165
+ delete result.observed_at;
166
+ delete result.elapsed_ms;
167
+ }
168
+ return result;
132
169
  }
133
170
  export async function startCommandJob(options) {
134
171
  const { sessionId } = options;
@@ -148,9 +185,11 @@ export async function startCommandJob(options) {
148
185
  const logPath = join(directory(sessionId), `${jobId}.log`);
149
186
  writeFileSync(logPath, '', { mode: 0o600 });
150
187
  const controller = new AbortController();
151
- const job = { controller, done: Promise.resolve(), loggedBytes: 0, receipt: {
188
+ const job = { controller, done: Promise.resolve(), loggedBytes: 0, activity: new Set(),
189
+ canInspectVerificationSource: options.canInspectVerificationSource ?? (() => true), receipt: {
152
190
  job_id: jobId, status: 'running', command: options.command, cwd: options.cwd,
153
191
  started_at: new Date().toISOString(), log_path: logPath, owner_pid: process.pid,
192
+ ...(options.verification ? { verification: structuredClone(options.verification) } : {}),
154
193
  } };
155
194
  save(sessionId, job.receipt);
156
195
  registry.set(jobId, job);
@@ -159,19 +198,40 @@ export async function startCommandJob(options) {
159
198
  options.signal?.addEventListener('abort', abort, { once: true });
160
199
  job.done = runShellCommand(options.command, options.cwd, controller.signal, options.timeoutMs, {
161
200
  ...options.shell, noTimeout: options.timeoutMs === undefined,
201
+ executionMode: 'background', turnInterruptPolicy: options.signal ? 'cancel' : 'preserve',
202
+ onExecutionPolicy: policy => {
203
+ job.receipt.execution_policy = structuredClone(policy);
204
+ job.receipt.started_at = policy.started_at;
205
+ options.shell.onExecutionPolicy?.(structuredClone(policy));
206
+ save(sessionId, job.receipt);
207
+ publish(sessionId);
208
+ },
162
209
  onOutput: (_stream, text) => appendCommandOutput(sessionId, job, text),
210
+ onCheckedProgress: checked => { job.receipt.checked = structuredClone(checked); save(sessionId, job.receipt); publish(sessionId); },
163
211
  }).then(result => {
164
212
  job.receipt.exit_code = result.exitCode;
165
- job.receipt.status = result.exitCode === 124 ? 'timed_out' : result.exitCode === 0 ? 'completed' : 'failed';
213
+ if (result.checked)
214
+ job.receipt.checked = structuredClone(result.checked);
215
+ if (job.receipt.status !== 'interrupted')
216
+ job.receipt.status = result.checked
217
+ ? result.checked.status === 'passed' ? 'completed' : result.checked.status === 'timed_out' ? 'timed_out'
218
+ : result.checked.status === 'cancelled' ? 'cancelled' : 'failed'
219
+ : result.timedOut === true ? 'timed_out' : result.exitCode === 0 ? 'completed' : 'failed';
166
220
  if (result.exitCode !== 0)
167
221
  job.receipt.error = result.stderr.slice(-4096) || `Command exited with code ${result.exitCode}`;
222
+ job.receipt.ended_at = new Date().toISOString();
168
223
  }, error => {
169
224
  if (job.receipt.status !== 'interrupted')
170
225
  job.receipt.status = controller.signal.aborted ? 'cancelled' : 'failed';
171
226
  job.receipt.error = error.message;
172
- }).finally(() => {
173
- options.signal?.removeEventListener('abort', abort);
174
227
  job.receipt.ended_at = new Date().toISOString();
228
+ }).finally(async () => {
229
+ options.signal?.removeEventListener('abort', abort);
230
+ if (job.receipt.verification) {
231
+ const outcome = job.receipt.status === 'completed' ? 'passed' : job.receipt.status === 'running' ? 'unknown' : job.receipt.status;
232
+ job.receipt.verification = await finishCommandVerification(job.receipt.verification, outcome, job.canInspectVerificationSource);
233
+ job.receipt.verification_current = await projectCurrentVerification(job.receipt.verification, job.canInspectVerificationSource);
234
+ }
175
235
  try {
176
236
  save(sessionId, job.receipt);
177
237
  }
@@ -184,16 +244,19 @@ export async function startCommandJob(options) {
184
244
  const terminal = [...registry.entries()].filter(([, entry]) => entry.receipt.status !== 'running');
185
245
  for (const [id] of terminal.slice(0, Math.max(0, terminal.length - 64)))
186
246
  registry.delete(id);
247
+ notifyActivity(job);
187
248
  publish(sessionId);
188
249
  });
189
- return { ...job.receipt };
250
+ return observeReceipt(job.receipt);
190
251
  }
191
- export async function readCommandJob(sessionId, jobId, cursor = 0, waitMs = 0, signal) {
252
+ export async function readCommandJob(sessionId, jobId, cursor = 0, waitMs = 0, signal, canInspectSource) {
192
253
  if (!Number.isSafeInteger(cursor) || cursor < 0)
193
254
  throw new Error('cursor must be a non-negative byte offset');
194
255
  if (!Number.isSafeInteger(waitMs) || waitMs < 0 || waitMs > 60000)
195
256
  throw new Error('wait_ms must be an integer between 0 and 60000');
196
257
  const job = resolveJob(sessionId, jobId);
258
+ if (canInspectSource)
259
+ job.canInspectVerificationSource = canInspectSource;
197
260
  const cancelled = () => new Error(`Command read cancelled; inspect job ${jobId} before retrying. The job may still be running.`);
198
261
  if (signal?.aborted)
199
262
  throw cancelled();
@@ -214,6 +277,19 @@ export async function readCommandJob(sessionId, jobId, cursor = 0, waitMs = 0, s
214
277
  signal?.removeEventListener('abort', onAbort);
215
278
  }
216
279
  }
280
+ const result = await refreshReadVerification(job, readOutput(job, cursor), canInspectSource);
281
+ return observeReceipt(result);
282
+ }
283
+ async function refreshReadVerification(job, result, canInspectSource) {
284
+ if (!result.verification)
285
+ return result;
286
+ const original = job.receipt.verification;
287
+ const current = await projectCurrentVerification(result.verification, canInspectSource ?? job.canInspectVerificationSource);
288
+ if (job.receipt.verification === original)
289
+ job.receipt.verification_current = structuredClone(current);
290
+ return { ...result, verification_current: current };
291
+ }
292
+ function readOutput(job, cursor) {
217
293
  const size = statSync(job.receipt.log_path).size;
218
294
  if (cursor > size)
219
295
  throw new Error('cursor is beyond the command output');
@@ -240,15 +316,77 @@ export async function readCommandJob(sessionId, jobId, cursor = 0, waitMs = 0, s
240
316
  throw new Error('cursor must be at a UTF-8 character boundary');
241
317
  }
242
318
  }
243
- return { ...job.receipt, output, cursor: cursor + count, has_more: cursor + count < size };
319
+ return { ...observeReceipt(job.receipt), output, cursor: cursor + count, has_more: cursor + count < size };
320
+ }
321
+ export async function waitForCommandProgress(sessionId, jobId, options) {
322
+ const cursor = options.cursor ?? 0;
323
+ if (!Number.isSafeInteger(cursor) || cursor < 0)
324
+ throw new Error('cursor must be a non-negative byte offset');
325
+ if (!Number.isSafeInteger(options.maxWaitMs) || options.maxWaitMs < 0 || options.maxWaitMs > 60000) {
326
+ throw new Error('maxWaitMs must be an integer between 0 and 60000');
327
+ }
328
+ const job = resolveJob(sessionId, jobId);
329
+ if (options.canInspectVerificationSource)
330
+ job.canInspectVerificationSource = options.canInspectVerificationSource;
331
+ const cancelled = () => new Error(`Command read cancelled; inspect job ${jobId} before retrying. The job may still be running.`);
332
+ if (options.signal?.aborted)
333
+ throw cancelled();
334
+ const progress = await new Promise((resolve, reject) => {
335
+ let settled = false;
336
+ let timer;
337
+ const cleanup = () => {
338
+ settled = true;
339
+ job.activity.delete(onActivity);
340
+ if (timer !== undefined)
341
+ clearTimeout(timer);
342
+ options.signal?.removeEventListener('abort', onAbort);
343
+ };
344
+ const onAbort = () => { if (!settled) {
345
+ cleanup();
346
+ reject(cancelled());
347
+ } };
348
+ const inspect = (deadline) => {
349
+ if (settled)
350
+ return;
351
+ if (options.signal?.aborted) {
352
+ onAbort();
353
+ return;
354
+ }
355
+ try {
356
+ const result = readOutput(job, cursor);
357
+ const reason = result.status !== 'running' ? 'terminal' : result.output.length > 0 ? 'output' : deadline ? 'deadline' : null;
358
+ if (reason !== null) {
359
+ cleanup();
360
+ resolve({ reason, result });
361
+ }
362
+ }
363
+ catch (error) {
364
+ cleanup();
365
+ reject(error);
366
+ }
367
+ };
368
+ const onActivity = () => inspect(false);
369
+ // Register before checking bytes/status so output or completion cannot be lost.
370
+ job.activity.add(onActivity);
371
+ options.signal?.addEventListener('abort', onAbort, { once: true });
372
+ if (options.maxWaitMs > 0)
373
+ timer = setTimeout(() => inspect(true), options.maxWaitMs);
374
+ inspect(options.maxWaitMs === 0);
375
+ });
376
+ const result = await refreshReadVerification(job, progress.result, options.canInspectVerificationSource);
377
+ return { reason: progress.reason, result: observeReceipt(result) };
244
378
  }
245
- export async function stopCommandJob(sessionId, jobId) {
379
+ export async function stopCommandJob(sessionId, jobId, canInspectSource) {
246
380
  const job = resolveJob(sessionId, jobId);
381
+ if (canInspectSource)
382
+ job.canInspectVerificationSource = canInspectSource;
247
383
  if (job.receipt.status === 'running') {
248
384
  job.controller.abort();
249
385
  await job.done;
250
386
  }
251
- return { ...job.receipt };
387
+ if (job.receipt.verification)
388
+ job.receipt.verification_current = await projectCurrentVerification(job.receipt.verification, job.canInspectVerificationSource);
389
+ return observeReceipt(job.receipt);
252
390
  }
253
391
  export async function shutdownCommandJobs(sessionId) {
254
392
  const registries = sessionId ? [sessions.get(sessionId)] : [...sessions.values()];
@@ -0,0 +1,59 @@
1
+ import type { RunShellCommandOptions } from '../../utils/shell.js';
2
+ export type CommandPaneState = 'suspended' | 'running' | 'completed' | 'failed' | 'unknown';
3
+ export interface CommandPaneView {
4
+ id: string;
5
+ name: string;
6
+ command: string;
7
+ cwd: string;
8
+ environmentKeys: string[];
9
+ state: CommandPaneState;
10
+ attempt: string;
11
+ exitCode?: number;
12
+ error?: string;
13
+ output: string;
14
+ evidence?: {
15
+ path: string;
16
+ sha256: string;
17
+ };
18
+ }
19
+ /** Durable definitions and command receipts are authoritative; panes are projections. */
20
+ export declare class CommandPaneManager {
21
+ private readonly sessionId;
22
+ private readonly shellOptions;
23
+ private readonly file;
24
+ private readonly sessionDirectory;
25
+ private readonly listeners;
26
+ private readonly localJobs;
27
+ private readonly admittedJobs;
28
+ private timer?;
29
+ private refreshTask?;
30
+ private closed;
31
+ private lastPublished?;
32
+ constructor(sessionId: string, sessionCwd: string, shellOptions: () => RunShellCommandOptions);
33
+ private read;
34
+ private mutate;
35
+ private find;
36
+ pin(options: {
37
+ name: string;
38
+ command: string;
39
+ cwd: string;
40
+ env?: Record<string, string>;
41
+ suspended?: boolean;
42
+ }): Promise<CommandPaneView>;
43
+ /** expectedAttempt binds an action to the snapshot it was offered on. */
44
+ run(name: string, expectedAttempt: string): Promise<CommandPaneView>;
45
+ stop(name: string, expectedAttempt: string): Promise<void>;
46
+ unpin(name: string): Promise<void>;
47
+ private output;
48
+ list(): Promise<CommandPaneView[]>;
49
+ attachEvidence(name: string, expectedAttempt: string): Promise<{
50
+ path: string;
51
+ sha256: string;
52
+ }>;
53
+ subscribe(listener: (commands: CommandPaneView[]) => void): () => void;
54
+ private watch;
55
+ refresh(): Promise<void>;
56
+ private publish;
57
+ dispose(): Promise<void>;
58
+ }
59
+ export declare function commandPaneText(command: CommandPaneView): string;