@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
@@ -10,9 +10,11 @@ import { Tool } from './types.js';
10
10
  export interface AskUserOption {
11
11
  label: string;
12
12
  description: string;
13
+ /** Optional short explanation of what happens after this option is chosen. */
14
+ preview?: string;
13
15
  /**
14
16
  * Marks the option you would pick. At most one option per question may set
15
- * this; the TUI badges it and starts the cursor on it.
17
+ * this; it appears first and the TUI badges it and starts the cursor on it.
16
18
  */
17
19
  recommended?: boolean;
18
20
  }
@@ -83,6 +83,12 @@ function validateOptionsArray(options) {
83
83
  if (opt.label.length > MAX_LABEL_LENGTH || opt.description.length > MAX_LABEL_LENGTH) {
84
84
  return `option label/description exceeds ${MAX_LABEL_LENGTH} character limit.`;
85
85
  }
86
+ if (opt.preview !== undefined && typeof opt.preview !== 'string') {
87
+ return 'option preview must be a string when provided.';
88
+ }
89
+ if (opt.preview !== undefined && opt.preview.length > MAX_LABEL_LENGTH) {
90
+ return `option preview exceeds ${MAX_LABEL_LENGTH} character limit.`;
91
+ }
86
92
  // Accept the boolean and its string spelling, keep the first recommended
87
93
  // option, and drop duplicates instead of failing the whole call.
88
94
  const isRecommended = !recommendedSeen && (opt.recommended === true || opt.recommended === 'true');
@@ -91,10 +97,14 @@ function validateOptionsArray(options) {
91
97
  normalized.push({
92
98
  label: String(opt.label),
93
99
  description: String(opt.description),
100
+ ...(opt.preview !== undefined ? { preview: opt.preview } : {}),
94
101
  ...(isRecommended ? { recommended: true } : {}),
95
102
  });
96
103
  }
97
- return normalized;
104
+ const recommendation = normalized.findIndex(option => option.recommended === true);
105
+ return recommendation > 0
106
+ ? [normalized[recommendation], ...normalized.filter((_option, index) => index !== recommendation)]
107
+ : normalized;
98
108
  }
99
109
  function parseOptions(raw) {
100
110
  let parsed;
@@ -117,7 +127,15 @@ function normalizeOptions(raw) {
117
127
  return 'options_json must be an array of {label, description} options, not a single object.';
118
128
  return parseOptions(String(raw ?? ''));
119
129
  }
130
+ function registrationFailure(message) {
131
+ const detail = message.trim();
132
+ return detail
133
+ ? `Error: ${detail}`
134
+ : 'Error: The interactive question could not be registered. Retry when question input is available.';
135
+ }
120
136
  export const askUserTool = {
137
+ // Validation and UI registration failures must use the runtime's failure path.
138
+ isErrorResult: (content) => /^Error[: ]/u.test(content),
121
139
  definition: {
122
140
  name: 'ask_user',
123
141
  description: `Ask the user one or more questions with predefined options. Use this to get user preferences, clarify requirements, or confirm approach before proceeding.
@@ -132,11 +150,12 @@ Use "questions_json" to ask multiple questions at once. This is more efficient t
132
150
 
133
151
  ### options_json format
134
152
  JSON array of objects with "label" and "description" fields.
135
- Add "recommended": true to the single option you would pick; it is badged and pre-selected for the user. Never mark more than one option per question.
136
- Example: [{"label": "Option A", "description": "Use approach A", "recommended": true}, {"label": "Option B", "description": "Use approach B"}]
153
+ Put the option you would pick first and add "recommended": true; it is badged and pre-selected for the user. Never mark more than one option per question.
154
+ Optionally add "preview" (a short string, maximum 500 characters) to explain what happens next after choosing that option. The highlighted option shows this separately as "Next:". Keep descriptions about the choice and previews about its next step.
155
+ Example: [{"label": "Option A", "description": "Use approach A", "recommended": true, "preview": "Run the checks, then apply approach A"}, {"label": "Option B", "description": "Use approach B"}]
137
156
 
138
157
  ### questions_json format
139
- JSON array of question objects, each with "question" (string) and "options" (same format as options_json).
158
+ JSON array of question objects, each with "question" (string) and "options" (same format as options_json, including optional recommended and preview fields).
140
159
  Example: [{"question": "Which framework?", "options": [{"label": "React", "description": "Use React", "recommended": true}, {"label": "Vue", "description": "Use Vue"}]}, {"question": "Which database?", "options": [{"label": "Postgres", "description": "PostgreSQL"}, {"label": "SQLite", "description": "SQLite"}]}]`,
141
160
  parameters: {
142
161
  type: 'object',
@@ -147,11 +166,11 @@ Example: [{"question": "Which framework?", "options": [{"label": "React", "descr
147
166
  },
148
167
  options_json: {
149
168
  type: 'string',
150
- description: 'JSON array of options for single question mode. Each with "label" (1-5 words) and "description", plus "recommended": true on the one option you suggest (at most one per question). Provide 2-4 options.',
169
+ description: 'JSON array of options for single question mode. Each with "label" (1-5 words) and "description"; put the one recommended option first and mark "recommended": true (at most one per question). Optional "preview" (string, max 500 characters) briefly explains what happens next. Provide 2-4 options.',
151
170
  },
152
171
  questions_json: {
153
172
  type: 'string',
154
- description: 'JSON array of question objects for multi-question mode. Each has "question" (string) and "options" (array of {label, description, recommended?}). Use this to ask 2+ questions at once.',
173
+ description: 'JSON array of question objects for multi-question mode. Each has "question" (string) and "options" (array of {label, description, recommended?, preview?}); recommended option first, optional preview is a string of at most 500 characters. Use this to ask 2+ questions at once.',
155
174
  },
156
175
  allow_other: {
157
176
  type: 'boolean',
@@ -169,7 +188,7 @@ Example: [{"question": "Which framework?", "options": [{"label": "React", "descr
169
188
  debugLog('execute called:', { hasQuestion: !!question, hasOptionsJson: !!optionsJson, hasQuestionsJson: !!questionsJson, alreadyCalled: askUserCalledThisTurn });
170
189
  if (!askUserCallback) {
171
190
  debugLog('ERROR: no callback registered');
172
- return 'ask_user is not available in this context.';
191
+ return 'Error: ask_user is not available in this context. Use an interactive ZTC session with question input enabled.';
173
192
  }
174
193
  // If ask_user was already called this turn (parallel tool calls), the questions
175
194
  // were merged via the callback. Return a dedup message so the LLM doesn't re-ask.
@@ -228,8 +247,8 @@ Example: [{"question": "Which framework?", "options": [{"label": "React", "descr
228
247
  questions.push({ question: q.question, options: opts, allow_other: allowOther });
229
248
  }
230
249
  const error = askUserCallback(questions);
231
- if (error)
232
- return error;
250
+ if (error !== null)
251
+ return registrationFailure(error);
233
252
  const wasDuplicate = askUserCalledThisTurn;
234
253
  askUserCalledThisTurn = true;
235
254
  if (wasDuplicate) {
@@ -253,8 +272,8 @@ Example: [{"question": "Which framework?", "options": [{"label": "React", "descr
253
272
  return `Error: ${parsed}`;
254
273
  }
255
274
  const error = askUserCallback([{ question, options: parsed, allow_other: allowOther }]);
256
- if (error)
257
- return error;
275
+ if (error !== null)
276
+ return registrationFailure(error);
258
277
  const wasDuplicate = askUserCalledThisTurn;
259
278
  askUserCalledThisTurn = true;
260
279
  if (wasDuplicate) {
@@ -47,6 +47,7 @@ export const spawnBackgroundAgentTool = {
47
47
  const taskId = registry.spawn(task, {
48
48
  maxIterations,
49
49
  cwd: context?.cwd || process.cwd(),
50
+ onUsage: context?.onUsage,
50
51
  });
51
52
  return `Background agent spawned (${taskId}). I'll continue working while it runs. You'll be notified when it completes.`;
52
53
  }
@@ -0,0 +1,2 @@
1
+ import type { Tool } from './types.js';
2
+ export declare const benchmarkCPUTool: Tool;
@@ -0,0 +1,102 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { cpus, release } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { CPU_CHECKER_SHA256, CPU_HOST_INSTANCE_ID, CPU_PROGRAM_SHA256, CPU_RECIPE_SHA256, integerSumOracle, parseCPUWorkload, runCPUWorkload } from '../runtime/cpu_benchmark.js';
5
+ import { parseBenchmarkVerifierDecision } from '../runtime/benchmark_contract.js';
6
+ import { ToolCapability } from '../runtime/capabilities.js';
7
+ import { captureVerifierInputs } from '../runtime/verifier_capture.js';
8
+ import { parseCommandVerificationReceipt, parseVerificationRequest } from '../runtime/source_verification_contract.js';
9
+ export const benchmarkCPUTool = Object.freeze({
10
+ capabilities: Object.freeze([ToolCapability.FILE_READ, ToolCapability.SHELL_EXEC]), effect: 'write',
11
+ definition: { name: 'benchmark_cpu',
12
+ description: 'Execute the registered bounded CPU integer-sum benchmark using immutable captured JSON data and config, actual monotonic measurements and an independent exact oracle. Input is1–1024 integers with absolute value≤1000000. Config: {schema_version:1,variant:"for_loop"|"array_reduce",iterations:1–2048,warmup:0–4,samples:3|5|7|9}. Admits only this fixture; never project code, reported scores, generic command results, production/GPU performance or a plateau. Local execution and exact source-read permissions required; guarded remote sessions cannot use this adapter. Each file≤65536B.',
13
+ parameters: { type: 'object', additionalProperties: false, properties: {
14
+ adapter_id: { type: 'string', enum: ['cpu_integer_sum'] }, input_path: { type: 'string' }, config_path: { type: 'string' },
15
+ }, required: ['adapter_id', 'input_path', 'config_path'] } },
16
+ execute: async (args, context) => {
17
+ if (!context)
18
+ throw new Error('benchmark_cpu requires a host execution context');
19
+ if (Object.keys(args).some(key => !['adapter_id', 'input_path', 'config_path'].includes(key)) || args.adapter_id !== 'cpu_integer_sum') {
20
+ throw new TypeError('benchmark_cpu accepts only the registered CPU adapter and input/config paths');
21
+ }
22
+ const request = parseVerificationRequest({ purpose: 'benchmark', scope: 'benchmark:cpu_integer_sum',
23
+ source_paths: [args.input_path, args.config_path], instrumentation: 'production' });
24
+ if (!request)
25
+ throw new TypeError('benchmark_cpu requires two distinct bounded relative input/config paths');
26
+ const captured = await captureVerifierInputs(context, request.source_paths);
27
+ const processors = cpus();
28
+ if (processors.length === 0)
29
+ throw new Error('The benchmark CPU execution conditions are unavailable');
30
+ const receipt = { schema_version: 1, receipt_id: randomUUID(), source: captured.source,
31
+ end_source: null, purpose: 'benchmark', scope: 'benchmark:cpu_integer_sum', command_sha256: CPU_RECIPE_SHA256,
32
+ command_kind: 'host_verifier', build_identity: CPU_RECIPE_SHA256, instrumentation: 'unknown',
33
+ environment: { platform: process.platform, arch: process.arch, node_version: process.version, declared_id: null },
34
+ process_outcome: 'unknown', source_binding: 'unknown', qualification: 'unverified', artifact_refs: [] };
35
+ const input = captured.documents.get(String(args.input_path));
36
+ const config = captured.documents.get(String(args.config_path));
37
+ const binding = input !== undefined && config !== undefined && !context.signal?.aborted ? 'immutable_bytes' : 'unknown';
38
+ const workload = binding === 'immutable_bytes' ? parseCPUWorkload(input, config) : null;
39
+ let decision = { schema_version: 1, adapter_id: 'cpu_integer_sum', recipe_version: 1,
40
+ execution: 'host_node_subprocess', recipe_sha256: CPU_RECIPE_SHA256, receipt_id: receipt.receipt_id, source_id: receipt.source.source_id,
41
+ scope: 'benchmark:cpu_integer_sum', input_path: String(args.input_path), config_path: String(args.config_path), input_binding: binding,
42
+ outcome: 'unknown', checks_total: 0, checks_passed: 0, reason: 'Complete supported immutable input/config data was unavailable.',
43
+ benchmark_eligibility: 'unknown', variant: workload?.config.variant ?? null,
44
+ program_sha256: workload ? CPU_PROGRAM_SHA256[workload.config.variant] : null, checker_sha256: CPU_CHECKER_SHA256,
45
+ conditions: { host_instance_id: CPU_HOST_INSTANCE_ID, cpu_model: processors[0].model, logical_cpus: processors.length, os_release: release() },
46
+ workload: workload ? { id: 'cpu_integer_sum/v1', input_sha256: captured.source.files.find(row => row.path === args.input_path).sha256,
47
+ length: workload.values.length, iterations: workload.config.iterations, warmup: workload.config.warmup, samples: workload.config.samples } : null,
48
+ measurement: null };
49
+ if (workload) {
50
+ const run = await runCPUWorkload(workload, context);
51
+ receipt.process_outcome = run.outcome;
52
+ receipt.environment.declared_id = run.executionPolicyId;
53
+ decision.reason = 'The actual registered process did not produce a complete supported measured result.';
54
+ decision.benchmark_eligibility = 'ineligible';
55
+ if (run.outcome === 'passed') {
56
+ let output;
57
+ try {
58
+ output = JSON.parse(run.output);
59
+ }
60
+ catch {
61
+ output = null;
62
+ }
63
+ const row = output;
64
+ if (row && typeof row === 'object' && !Array.isArray(row)
65
+ && Object.keys(row).length === 8 && row.schema_version === 1 && row.variant === workload.config.variant
66
+ && Number.isSafeInteger(row.pid) && Number(row.pid) > 0
67
+ && row.node_version === process.version && row.platform === process.platform && row.arch === process.arch
68
+ && Array.isArray(row.samples_ms) && row.samples_ms.length === workload.config.samples
69
+ && row.samples_ms.every(value => typeof value === 'number' && Number.isFinite(value) && value > 0 && value <= 60000)
70
+ && Array.isArray(row.checksums) && row.checksums.length === workload.config.samples
71
+ && row.checksums.every(value => typeof value === 'number' && Number.isSafeInteger(value))) {
72
+ const expected = integerSumOracle(workload.values) * workload.config.iterations;
73
+ receipt.instrumentation = 'production';
74
+ const passed = row.checksums.filter(value => value === expected).length;
75
+ const samples = row.samples_ms;
76
+ decision = { ...decision, outcome: passed === workload.config.samples ? 'passed' : 'failed',
77
+ checks_total: workload.config.samples, checks_passed: passed,
78
+ benchmark_eligibility: passed === workload.config.samples ? 'eligible' : 'ineligible',
79
+ reason: passed === workload.config.samples ? 'Every measured checksum matched the independent integer oracle.' : 'A measured checksum failed the independent integer oracle.',
80
+ measurement: { samples_ms: samples, value_ms: [...samples].sort((a, b) => a - b)[Math.floor(samples.length / 2)],
81
+ unit: 'ms', timing_domain: 'node_performance_now', scope: 'integer_sum_kernel', rank: 0, world_size: 1 } };
82
+ }
83
+ }
84
+ }
85
+ receipt.end_source = (await captureVerifierInputs(context, request.source_paths)).source;
86
+ receipt.source_binding = receipt.source.coverage === 'complete' && receipt.end_source.coverage === 'complete'
87
+ && receipt.source.source_id === receipt.end_source.source_id ? 'observed_endpoints' : 'unknown';
88
+ receipt.artifact_refs = receipt.source.files.filter(file => file.kind === 'file').map(file => ({ origin: 'local',
89
+ path: join(receipt.source.cwd, file.path), sha256: file.sha256 }));
90
+ if (decision.benchmark_eligibility === 'eligible' && receipt.source_binding !== 'observed_endpoints') {
91
+ decision.benchmark_eligibility = 'ineligible';
92
+ decision.reason = 'Inputs/configuration changed or became unavailable during the measured run.';
93
+ }
94
+ const admitted = parseBenchmarkVerifierDecision(decision, receipt);
95
+ if (!admitted || !parseCommandVerificationReceipt(receipt))
96
+ throw new Error('The CPU adapter produced an invalid bounded decision');
97
+ context.onVerificationReceipt?.(receipt);
98
+ if (!context.signal?.aborted)
99
+ context.onHostVerifier?.(receipt, admitted);
100
+ return JSON.stringify({ verification: receipt, verifier: admitted });
101
+ },
102
+ });
@@ -0,0 +1,2 @@
1
+ import type { Tool } from './types.js';
2
+ export declare const compareBenchmarksTool: Tool;
@@ -0,0 +1,53 @@
1
+ import { parseBenchmarkVerifierDecision } from '../runtime/benchmark_contract.js';
2
+ import { compareRegisteredBenchmarks, parseBenchmarkComparisonDecision } from '../runtime/benchmark_comparison.js';
3
+ import { ToolCapability } from '../runtime/capabilities.js';
4
+ import { parseCommandVerificationReceipt } from '../runtime/source_verification_contract.js';
5
+ async function observed(id, context) {
6
+ const row = context.toolResponseStore.evidence.getSnapshot().records.find(record => record.id === id);
7
+ if (!row || row.kind !== 'observation' || row.partial || row.isError || row.availability === 'unavailable'
8
+ || row.source.origin !== 'host_receipt' || row.source.toolName !== 'benchmark_cpu' || !row.source.toolCallId)
9
+ return null;
10
+ const receipt = parseCommandVerificationReceipt(row.source.verification);
11
+ const decision = receipt && parseBenchmarkVerifierDecision(row.source.verifier, receipt);
12
+ if (!receipt || !decision)
13
+ return null;
14
+ try {
15
+ const original = await context.toolResponseStore.getChunk(row.source.toolCallId, { cursor: 0, maxBytes: 32768 });
16
+ if (!original || original.totalBytes > 65536 || original.observationId !== row.id || original.sha256 !== row.resultSha256)
17
+ return null;
18
+ if (!original.complete) {
19
+ const tail = await context.toolResponseStore.getChunk(row.source.toolCallId, { cursor: original.nextCursor, maxBytes: 32768 });
20
+ if (!tail || !tail.complete || tail.observationId !== row.id || tail.sha256 !== row.resultSha256)
21
+ return null;
22
+ }
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ return { id: row.id, receipt, decision };
28
+ }
29
+ export const compareBenchmarksTool = Object.freeze({
30
+ capabilities: Object.freeze([ToolCapability.FILE_READ]), effect: 'read', parallelSafe: true,
31
+ definition: { name: 'compare_benchmarks',
32
+ description: 'Compare two retained host-admitted benchmark_cpu observations by their original observation IDs. Require independent measured runs with the same captured input/workload, checker, runner and declared host/runtime/measurement conditions; registered program/source identities may differ. Copied JSON, generic command output, incomplete or unavailable records cannot admit eligibility. Returns only the scoped historical CPU-fixture comparison; a measured delta never proves a causal win, production/GPU performance or a plateau.',
33
+ parameters: { type: 'object', additionalProperties: false, properties: {
34
+ observation_ids: { type: 'array', items: { type: 'string' }, minItems: 2, maxItems: 2, uniqueItems: true },
35
+ }, required: ['observation_ids'] } },
36
+ execute: async (args, context) => {
37
+ if (!context)
38
+ throw new Error('compare_benchmarks requires a host evidence context');
39
+ const ids = args.observation_ids;
40
+ if (Object.keys(args).length !== 1 || !Array.isArray(ids) || ids.length !== 2
41
+ || ids.some(id => typeof id !== 'string' || !id.trim() || Buffer.byteLength(id) > 256 || /[\u0000-\u001f\u007f]/u.test(id))
42
+ || ids[0] === ids[1])
43
+ throw new TypeError('compare_benchmarks requires two distinct bounded original observation IDs');
44
+ const baseline = await observed(ids[0], context);
45
+ const candidate = await observed(ids[1], context);
46
+ const decision = parseBenchmarkComparisonDecision(compareRegisteredBenchmarks(baseline, candidate));
47
+ if (!decision)
48
+ throw new Error('The host comparator produced an invalid bounded decision');
49
+ if (!context.signal?.aborted)
50
+ context.onHostBenchmarkComparison?.(decision);
51
+ return JSON.stringify(decision);
52
+ },
53
+ });
@@ -14,6 +14,7 @@
14
14
  export const CORE_DISCOVERY_TOOL_NAMES = new Set([
15
15
  'tool_search',
16
16
  'recall_tool_response',
17
+ 'session_evidence',
17
18
  ]);
18
19
  export const ALWAYS_LOADED_TOOL_NAMES = new Set([
19
20
  // Core file + shell + search (analogues of claw-code's shell/read/write/edit/glob/grep)
@@ -5,6 +5,7 @@
5
5
  * The sub-agent runs in isolation and only returns a summary, keeping the
6
6
  * main agent's context clean.
7
7
  */
8
+ import { randomUUID } from 'node:crypto';
8
9
  import { ToolCapability } from '../runtime/capabilities.js';
9
10
  import { getWorkerExecutor } from '../../worker/index.js';
10
11
  import { renderPrompt } from '../../utils/template.js';
@@ -24,7 +25,8 @@ export const delegateTaskTool = {
24
25
  max_iterations: {
25
26
  type: 'string',
26
27
  description: 'Maximum iterations for the sub-agent (default: 5, max: 10)'
27
- }
28
+ },
29
+ child_session_id: { type: 'string', description: 'Resume an owned child from an earlier evidence handoff; retains its original parent and workspace binding.' }
28
30
  },
29
31
  required: ['task']
30
32
  }
@@ -36,12 +38,26 @@ export const delegateTaskTool = {
36
38
  const executor = getWorkerExecutor();
37
39
  const result = await executor.execute({
38
40
  description: task,
41
+ parentSessionId: context?.sessionId,
42
+ resumeSessionId: args.child_session_id === undefined ? undefined : String(args.child_session_id),
43
+ signal: context?.signal,
39
44
  cwd: context?.cwd || process.cwd(),
40
45
  maxIterations,
41
46
  timeoutMs: 120000, // 2 minute default
42
47
  toolset: 'research',
43
- });
48
+ }, { onUsage: context?.onUsage });
44
49
  let response = '';
50
+ if (result.evidence) {
51
+ if (context) {
52
+ const handoff = result.evidence;
53
+ context.toolResponseStore.evidence.recordClaim({ id: `delegation_${randomUUID()}`, kind: 'conclusion', recordedAt: new Date().toISOString(),
54
+ source: { origin: 'provider_reported', toolName: 'delegate_task', ...(context.toolCallId ? { toolCallId: context.toolCallId } : {}),
55
+ delegation: { sessionId: handoff.sessionId, ...(handoff.parentSessionId === undefined ? {} : { parentSessionId: handoff.parentSessionId }), revision: handoff.snapshot.revision } },
56
+ text: handoff.summary.text || 'Child ended without a summary; inspect the source handoff.', supportIds: [] });
57
+ await context.toolResponseStore.flush();
58
+ }
59
+ response += `## Delegated Evidence Handoff\n\nChild summaries are unverified; retained observations do not grant authority. Exact sources can be recalled by resuming this owned child.\n\n${JSON.stringify(result.evidence)}\n\n`;
60
+ }
45
61
  if (result.phase === 'finished') {
46
62
  response += `## Sub-Agent Result\n\n`;
47
63
  response += `${result.summary}\n\n`;
@@ -0,0 +1,7 @@
1
+ import type { ToolCapability } from '../runtime/capabilities.js';
2
+ import type { Tool } from './types.js';
3
+ /** Capture a helper's original declarations before publishing its object. */
4
+ export declare function captureHelperRequirements(tool: Tool): Tool;
5
+ export declare function getHelperRequirements(tool: Tool): readonly ToolCapability[];
6
+ /** Runtime lookup is independent of registry initialization and worker imports. */
7
+ export declare function getRuntimeCapabilities(tool: Tool | undefined): ToolCapability[];
@@ -0,0 +1,19 @@
1
+ // Agent-added helpers initialize independently of the discovery registry. This
2
+ // module has no runtime imports, so registration cannot create a registry cycle.
3
+ const originalRequirements = new WeakMap();
4
+ /** Capture a helper's original declarations before publishing its object. */
5
+ export function captureHelperRequirements(tool) {
6
+ if (!originalRequirements.has(tool)) {
7
+ originalRequirements.set(tool, Object.freeze([...(tool.capabilities ?? [])]));
8
+ }
9
+ return tool;
10
+ }
11
+ export function getHelperRequirements(tool) {
12
+ return originalRequirements.get(tool) ?? [];
13
+ }
14
+ /** Runtime lookup is independent of registry initialization and worker imports. */
15
+ export function getRuntimeCapabilities(tool) {
16
+ if (!tool)
17
+ return [];
18
+ return [...new Set([...getHelperRequirements(tool), ...(tool.capabilities ?? [])])];
19
+ }
@@ -6,6 +6,7 @@ export declare function getTool(name: string, tools?: Tool[]): Tool | undefined;
6
6
  export declare function executeTool(name: string, args: Record<string, unknown>, tools?: Tool[], context?: ToolContext): Promise<string>;
7
7
  export { readFileTool, writeFileTool, editFileTool, listDirectoryTool } from './file.js';
8
8
  export { searchTool } from './search.js';
9
+ export { relatedSessionsTool } from './related_sessions.js';
9
10
  export { listSkillsTool, invokeSkillTool } from './skills.js';
10
11
  export { runCommandTool } from './shell.js';
11
12
  export { zergQueryTool, zergTaskStatusTool, zergListTool } from './zerg.js';
@@ -2,6 +2,7 @@ import { defaultTools as baseDefaultTools } from './registry.js';
2
2
  import { sendMessageTool, askZtcPaneTool, contactExternalTool } from './bus_message.js';
3
3
  import { toolSearchTool } from './tool_search.js';
4
4
  import { recallToolResponseTool } from './recall_tool_response.js';
5
+ import { sessionEvidenceTool } from './session_evidence.js';
5
6
  import { proposeWorldMutationTool } from './world_mutation.js';
6
7
  import { adaptationRunTool } from './adaptation.js';
7
8
  // --- Tool Registry ---
@@ -9,6 +10,7 @@ export const defaultTools = [
9
10
  ...baseDefaultTools,
10
11
  toolSearchTool,
11
12
  recallToolResponseTool,
13
+ sessionEvidenceTool,
12
14
  adaptationRunTool,
13
15
  ];
14
16
  export function getToolDefinitions(tools = defaultTools) {
@@ -26,6 +28,7 @@ export async function executeTool(name, args, tools = defaultTools, context) {
26
28
  }
27
29
  export { readFileTool, writeFileTool, editFileTool, listDirectoryTool } from './file.js';
28
30
  export { searchTool } from './search.js';
31
+ export { relatedSessionsTool } from './related_sessions.js';
29
32
  export { listSkillsTool, invokeSkillTool } from './skills.js';
30
33
  export { runCommandTool } from './shell.js';
31
34
  export { zergQueryTool, zergTaskStatusTool, zergListTool } from './zerg.js';
@@ -0,0 +1,22 @@
1
+ import { type MeasurementComparison, type MeasurementCompatibility, type MeasurementCompletion, type MeasurementReason, type MeasurementReport } from '../runtime/measurements.js';
2
+ import type { Tool } from './types.js';
3
+ export interface MeasurementSourceLink {
4
+ observationId: string;
5
+ toolCallId: string;
6
+ resultSha256: string;
7
+ jobId: string;
8
+ }
9
+ export interface MeasurementToolResult {
10
+ ok: boolean;
11
+ verification: 'unknown';
12
+ benchmarkEligibility: 'unknown';
13
+ compatibility: MeasurementCompatibility;
14
+ completion: MeasurementCompletion;
15
+ execution: 'completed' | 'running' | 'failed' | 'unknown';
16
+ reports: MeasurementReport[];
17
+ comparison: MeasurementComparison | null;
18
+ sources: MeasurementSourceLink[];
19
+ reasons: MeasurementReason[];
20
+ }
21
+ /** Read an original retained managed receipt before assessing producer measurement JSON. */
22
+ export declare const measurementReportTool: Tool;
@@ -0,0 +1,190 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { assessMeasurements, compareMeasurements, parseMeasurementEnvelope, parseMeasurementRequirements } from '../runtime/measurements.js';
3
+ import { ToolCapability } from '../runtime/capabilities.js';
4
+ import { ToolResponseIntegrityError } from '../tool_response_store.js';
5
+ const observationIdsSchema = { type: 'array', description: 'One retained observation, or baseline then candidate observations.',
6
+ items: { type: 'string' }, minItems: 1, maxItems: 2, uniqueItems: true };
7
+ const measurementParameters = {
8
+ type: 'object',
9
+ additionalProperties: false,
10
+ properties: {
11
+ observation_ids: observationIdsSchema,
12
+ requirements: { type: 'object', description: 'Expected workload, instrumentation, selected metrics, units, timing domain, scope, ranks and smoke fields.' },
13
+ },
14
+ required: ['observation_ids', 'requirements'],
15
+ };
16
+ const SOURCE_BYTES = 32768;
17
+ const REPORT_BYTES = 65536;
18
+ const managedTools = new Set(['run_command', 'read_command']);
19
+ const statuses = new Set(['running', 'completed', 'failed', 'cancelled', 'timed_out', 'interrupted']);
20
+ const reason = (code, message) => ({ code, message });
21
+ function unknown(reasons, sources = [], execution = 'unknown') {
22
+ return { ok: false, verification: 'unknown', benchmarkEligibility: 'unknown', compatibility: 'unknown',
23
+ completion: execution === 'running' ? 'incomplete' : 'unknown', execution, reports: [], comparison: null, sources, reasons };
24
+ }
25
+ function prefix(text, maxBytes) {
26
+ let kept = '';
27
+ let size = 0;
28
+ for (const character of text) {
29
+ const bytes = Buffer.byteLength(character);
30
+ if (size + bytes > maxBytes)
31
+ break;
32
+ kept += character;
33
+ size += bytes;
34
+ }
35
+ return kept;
36
+ }
37
+ function serialize(result) {
38
+ const bounded = (rows) => rows.slice(0, 32).map(row => ({ code: prefix(row.code, 128), message: prefix(row.message, 512) }));
39
+ result.reasons = bounded(result.reasons);
40
+ for (const report of result.reports)
41
+ report.reasons = bounded(report.reasons);
42
+ if (result.comparison) {
43
+ result.comparison.reasons = bounded(result.comparison.reasons);
44
+ result.comparison.baseline.reasons = bounded(result.comparison.baseline.reasons);
45
+ result.comparison.candidate.reasons = bounded(result.comparison.candidate.reasons);
46
+ }
47
+ const output = JSON.stringify(result);
48
+ return Buffer.byteLength(output) <= REPORT_BYTES ? output : JSON.stringify(unknown([
49
+ reason('report_too_large', 'The aggregate measurement report exceeds65536 UTF8 bytes; narrow the selected metrics.'),
50
+ ], result.sources));
51
+ }
52
+ function validReceipt(value, observation, context) {
53
+ if (!value || typeof value !== 'object' || Array.isArray(value))
54
+ return false;
55
+ const row = value;
56
+ const job = observation.source.job;
57
+ if (!job || (context.sessionId !== undefined && job.sessionId !== context.sessionId)
58
+ || typeof row.job_id !== 'string' || row.job_id !== job.jobId || typeof row.status !== 'string' || !statuses.has(row.status) || row.status !== job.status
59
+ || typeof row.cwd !== 'string' || typeof row.command !== 'string' || typeof row.log_path !== 'string'
60
+ || (observation.source.cwd !== undefined && row.cwd !== observation.source.cwd)
61
+ || (observation.source.artifact !== undefined && row.log_path !== observation.source.artifact.path)
62
+ || typeof row.started_at !== 'string' || !Number.isFinite(Date.parse(row.started_at)) || row.started_at !== job.startedAt
63
+ || row.ended_at !== job.endedAt || (row.exit_code ?? null) !== job.exitCode
64
+ || (row.exit_code !== undefined && !Number.isSafeInteger(row.exit_code))
65
+ || typeof row.output !== 'string' || !Number.isSafeInteger(row.cursor) || row.cursor < Buffer.byteLength(row.output)
66
+ || row.cursor !== job.cursor || typeof row.has_more !== 'boolean' || row.has_more !== job.hasMore
67
+ || (row.output_truncated !== undefined && typeof row.output_truncated !== 'boolean')
68
+ || Boolean(row.output_truncated) !== job.outputTruncated)
69
+ return false;
70
+ if (row.status === 'running')
71
+ return row.ended_at === undefined && row.exit_code === undefined;
72
+ return typeof row.ended_at === 'string' && Number.isFinite(Date.parse(row.ended_at))
73
+ && Date.parse(row.ended_at) >= Date.parse(row.started_at) && Number.isSafeInteger(row.exit_code);
74
+ }
75
+ async function capture(id, context) {
76
+ const store = context.toolResponseStore;
77
+ const row = store.evidence.getSnapshot().records.find(record => record.id === id);
78
+ if (row?.kind !== 'observation')
79
+ return { error: reason('missing_observation', 'The requested retained observation is unavailable or is an interpretation.') };
80
+ if (row.source.origin !== 'host_receipt' || !managedTools.has(row.source.toolName ?? '') || !row.source.job
81
+ || !row.source.toolCallId || !/^[A-Za-z0-9_-]{1,256}$/.test(row.source.toolCallId)) {
82
+ return { error: reason('untrusted_source', 'Measurement assessment requires original host receipt provenance from a managed command.') };
83
+ }
84
+ if (row.partial || row.availability === 'unavailable')
85
+ return { error: reason('source_incomplete', 'The original source is partial or unavailable.') };
86
+ if (row.resultBytes > SOURCE_BYTES)
87
+ return { error: reason('source_too_large', 'The original receipt exceeds the32768 byte complete source retrieval limit.') };
88
+ let chunk;
89
+ try {
90
+ chunk = await store.getChunk(row.source.toolCallId, { cursor: 0, maxBytes: SOURCE_BYTES });
91
+ }
92
+ catch (error) {
93
+ if (!(error instanceof ToolResponseIntegrityError))
94
+ throw error;
95
+ return { error: reason('source_integrity', 'The original retained source failed its identity or SHA256 integrity check.') };
96
+ }
97
+ if (!chunk || !chunk.complete || chunk.availability === 'unavailable')
98
+ return { error: reason('source_incomplete', 'A complete original retained receipt is unavailable.') };
99
+ const meta = store.getMeta(row.source.toolCallId);
100
+ if (chunk.toolUseId !== row.source.toolCallId || chunk.observationId !== row.id || chunk.cursor !== 0
101
+ || chunk.totalBytes !== row.resultBytes || chunk.nextCursor !== chunk.totalBytes || chunk.sha256 !== row.resultSha256
102
+ || createHash('sha256').update(chunk.content).digest('hex') !== row.resultSha256
103
+ || meta?.observation_id !== row.id || meta.tool_name !== row.source.toolName) {
104
+ return { error: reason('source_integrity', 'The retrieved source identity, byte count or SHA256 digest disagrees with its retained observation.') };
105
+ }
106
+ let receipt;
107
+ try {
108
+ receipt = JSON.parse(chunk.content);
109
+ }
110
+ catch (error) {
111
+ if (!(error instanceof SyntaxError))
112
+ throw error;
113
+ return { error: reason('invalid_receipt', 'The original managed receipt must be an entire JSON document.') };
114
+ }
115
+ if (!validReceipt(receipt, row, context))
116
+ return { error: reason('receipt_mismatch', 'The original receipt does not match its retained job identity or lifecycle fields.') };
117
+ const captured = { link: { observationId: row.id, toolCallId: row.source.toolCallId,
118
+ resultSha256: row.resultSha256, jobId: receipt.job_id }, sessionId: row.source.job.sessionId, receipt };
119
+ if (receipt.cursor !== Buffer.byteLength(receipt.output) || receipt.has_more || receipt.output_truncated) {
120
+ return { ...captured, error: reason('source_incomplete', 'The managed receipt does not contain complete command output from byte0, or its output is truncated.') };
121
+ }
122
+ if (receipt.status !== 'completed' || receipt.exit_code !== 0)
123
+ return captured;
124
+ if (row.isError)
125
+ return { ...captured, error: reason('source_error', 'The original captured source is marked as an execution error.') };
126
+ let output;
127
+ try {
128
+ output = JSON.parse(receipt.output);
129
+ }
130
+ catch (error) {
131
+ if (!(error instanceof SyntaxError))
132
+ throw error;
133
+ return { ...captured, error: reason('invalid_output', 'Measurement output must be an entire JSON document; surrounding prose is not removed.') };
134
+ }
135
+ const envelope = parseMeasurementEnvelope(output);
136
+ return envelope ? { ...captured, envelope }
137
+ : { ...captured, error: reason('invalid_output', 'The original JSON document is not a supported bounded measurement envelope.') };
138
+ }
139
+ /** Read an original retained managed receipt before assessing producer measurement JSON. */
140
+ export const measurementReportTool = {
141
+ capabilities: [ToolCapability.FILE_READ],
142
+ effect: 'read',
143
+ parallelSafe: true,
144
+ definition: {
145
+ name: 'measurement_report',
146
+ description: 'Assess or compare structured measurements from one or two retained managed-command observations. Supply observation IDs and measurement requirements, never copied values or receipts. Compatibility does not establish verification or benchmark eligibility.',
147
+ parameters: measurementParameters,
148
+ },
149
+ execute: async (args, context) => {
150
+ const unsupported = Object.keys(args).find(key => key !== 'observation_ids' && key !== 'requirements');
151
+ if (unsupported)
152
+ throw new TypeError(`measurement_report: unsupported argument ${unsupported}`);
153
+ const ids = args.observation_ids;
154
+ if (!Array.isArray(ids) || ids.length < 1 || ids.length > 2 || ids.some(id => typeof id !== 'string' || !id.trim()
155
+ || Buffer.byteLength(id) > 256 || /[\u0000-\u001f\u007f]/u.test(id)) || new Set(ids).size !== ids.length) {
156
+ throw new TypeError('measurement_report: observation_ids must contain one or two unique bounded nonempty observation IDs');
157
+ }
158
+ const required = parseMeasurementRequirements(args.requirements);
159
+ if (!required)
160
+ throw new TypeError('measurement_report: requirements must match the supported bounded measurement schema');
161
+ if (!context)
162
+ throw new Error('measurement_report: store unavailable');
163
+ const captures = [];
164
+ for (const id of ids)
165
+ captures.push(await capture(id, context));
166
+ const sources = captures.flatMap(item => item.link ? [item.link] : []);
167
+ const errors = captures.flatMap(item => item.error ? [item.error] : []);
168
+ if (errors.length)
169
+ return serialize(unknown(errors, sources));
170
+ if (captures.length === 2 && captures[0].sessionId === captures[1].sessionId
171
+ && captures[0].receipt.job_id === captures[1].receipt.job_id) {
172
+ return serialize(unknown([reason('alias_source', 'Two observations of the same canonical managed job are not independent comparison runs.')], sources));
173
+ }
174
+ if (captures.some(item => item.receipt.status !== 'completed' && item.receipt.status !== 'running'
175
+ || (item.receipt.exit_code !== undefined && item.receipt.exit_code !== 0))) {
176
+ return serialize(unknown([reason('execution_failed', 'The original managed process did not complete successfully; measurement admission is unavailable.')], sources, 'failed'));
177
+ }
178
+ if (captures.some(item => item.receipt.status === 'running')) {
179
+ return serialize(unknown([reason('execution_running', 'The original managed job is still running; a passed-false progress report is incomplete.')], sources, 'running'));
180
+ }
181
+ const comparison = captures.length === 2 ? compareMeasurements(captures[0].envelope, captures[1].envelope, required) : null;
182
+ const reports = comparison ? [comparison.baseline, comparison.candidate] : [assessMeasurements(captures[0].envelope, required)];
183
+ const completion = reports.some(report => report.completion === 'reported_fail') ? 'reported_fail'
184
+ : reports.some(report => report.completion === 'incomplete') ? 'incomplete'
185
+ : reports.every(report => report.completion === 'reported_pass') ? 'reported_pass' : 'unknown';
186
+ return serialize({ ok: true, verification: 'unknown', benchmarkEligibility: 'unknown', execution: 'completed', completion,
187
+ compatibility: comparison?.compatibility ?? reports[0].compatibility, reports, comparison, sources,
188
+ reasons: comparison?.reasons ?? reports[0].reasons });
189
+ },
190
+ };