@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
@@ -52,6 +52,8 @@
52
52
  * idle transition; headless runs an explicit await loop), but the accounting +
53
53
  * stop decision live here in one pure, unit-tested place: decideContinuation().
54
54
  */
55
+ import { createHash } from 'node:crypto';
56
+ import { formatGoalPlateau, hasFailedCompileObservation, makeGoalPlateau, observeGoalPlateau, parseGoalPlateauCriteria, parseGoalPlateauState, parseGoalExitReason, parseSustainedGoalAuthority } from './goal_exit.js';
55
57
  /**
56
58
  * Whether the finished turn did anything observable: it called a tool, or it said
57
59
  * something (assistant text or reasoning summary). Mirrors Codex's `has_activity`,
@@ -331,6 +333,10 @@ export const AGENT_GOAL_CONTROL_REFUSAL = 'Only the user can resume, replace, or
331
333
  */
332
334
  export function goalFinalNote(goal) {
333
335
  const tallies = `${goal.turns} turn(s), ${goal.tokensUsed.toLocaleString()} tokens`;
336
+ if (goal.status === 'complete' && goal.exitReason?.kind === 'measured_plateau') {
337
+ return `Goal stopped at its configured measured plateau: "${goal.objective}" (${tallies}). `
338
+ + `${goal.exitReason.reason} Evidence: ${goal.exitReason.evidenceIds.join(', ')}.`;
339
+ }
334
340
  if (goal.status === 'complete') {
335
341
  return `✅ Goal complete: "${goal.objective}" (${tallies}).`;
336
342
  }
@@ -408,12 +414,35 @@ export function parseGoalArgs(args) {
408
414
  const objectiveTokens = [];
409
415
  let tokenBudget;
410
416
  let maxTurns;
417
+ let attempts;
418
+ let benchmarkScope;
419
+ let minImprovementPercent = 0;
420
+ let hasThreshold = false;
411
421
  for (let i = 0; i < args.length; i++) {
412
422
  const tok = args[i];
413
423
  const eq = tok.indexOf('=');
414
424
  const flag = eq >= 0 ? tok.slice(0, eq) : tok;
415
425
  const inlineVal = eq >= 0 ? tok.slice(eq + 1) : undefined;
416
426
  const lower = flag.toLowerCase();
427
+ if (lower === '--plateau') {
428
+ attempts = parsePositiveInt(inlineVal ?? args[++i]) ?? undefined;
429
+ if (attempts === undefined || attempts > 32)
430
+ return { error: '--plateau requires 1–32 comparable attempts.' };
431
+ continue;
432
+ }
433
+ if (lower === '--benchmark-scope') {
434
+ benchmarkScope = inlineVal ?? args[++i];
435
+ continue;
436
+ }
437
+ if (lower === '--min-improvement-percent') {
438
+ const raw = inlineVal ?? args[++i];
439
+ minImprovementPercent = raw?.trim() ? Number(raw) : NaN;
440
+ hasThreshold = true;
441
+ if (!Number.isFinite(minImprovementPercent) || minImprovementPercent < 0 || minImprovementPercent > 100) {
442
+ return { error: '--min-improvement-percent requires a finite percentage from 0 through 100.' };
443
+ }
444
+ continue;
445
+ }
417
446
  if (lower === '--budget' || lower === '--tokens') {
418
447
  const raw = inlineVal ?? args[++i];
419
448
  const parsed = parsePositiveInt(raw);
@@ -450,7 +479,11 @@ export function parseGoalArgs(args) {
450
479
  if (/goal[ _]?blocked/i.test(objective)) {
451
480
  return { error: `Objective must not contain "${GOAL_BLOCKED_SENTINEL}" — that token is reserved to signal a stalled goal.` };
452
481
  }
453
- return { objective, ...(tokenBudget != null ? { tokenBudget } : {}), ...(maxTurns != null ? { maxTurns } : {}) };
482
+ const plateau = attempts === undefined ? undefined : parseGoalPlateauCriteria({ scope: benchmarkScope, attempts, minImprovementPercent });
483
+ if ((attempts !== undefined && !plateau) || (attempts === undefined && (benchmarkScope !== undefined || hasThreshold))) {
484
+ return { error: 'A plateau requires --plateau <1–32> and --benchmark-scope benchmark:cpu_integer_sum; other adapters remain unsupported.' };
485
+ }
486
+ return { objective, ...(tokenBudget != null ? { tokenBudget } : {}), ...(maxTurns != null ? { maxTurns } : {}), ...(plateau ? { plateau } : {}) };
454
487
  }
455
488
  function parsePositiveInt(raw) {
456
489
  if (raw == null)
@@ -467,6 +500,7 @@ function parsePositiveInt(raw) {
467
500
  export function buildKickPrompt(goal) {
468
501
  return [
469
502
  `GOAL: ${goal.objective}`,
503
+ ...(goal.plateau ? [formatGoalPlateau(goal.plateau), 'Only retained host-admitted comparisons count. Failed builds, rejected ideas and interrupted runs are not measured attempts. The host evaluates this criterion; do not claim a plateau or emit completion from reported scores. Later user steering, scope, budget and interruption remain authoritative.'] : []),
470
504
  '',
471
505
  'You are now in autonomous goal mode. Work toward this objective across as many steps',
472
506
  'as needed without waiting for confirmation between steps. Use your tools to make',
@@ -496,6 +530,7 @@ export function buildContinuationPrompt(goal) {
496
530
  return [
497
531
  `Continue working toward your goal (turn ${goal.turns + 1}):`,
498
532
  goal.objective,
533
+ ...(goal.plateau ? [formatGoalPlateau(goal.plateau), 'Continue the next authorized experiment without routine reapproval. Respect later user steering; the host evaluates plateau evidence, not completion prose.'] : []),
499
534
  '',
500
535
  'Briefly assess what is done and what remains, then take the next concrete step with your tools.',
501
536
  '',
@@ -529,7 +564,7 @@ export function buildContinuationPrompt(goal) {
529
564
  */
530
565
  export function goalPinTask(goal) {
531
566
  const objective = goal?.objective.trim() ?? '';
532
- return objective.length > 0 ? `GOAL: ${objective}` : null;
567
+ return objective.length > 0 ? `GOAL: ${objective}${goal?.plateau ? '\n' + formatGoalPlateau(goal.plateau) : ''}` : null;
533
568
  }
534
569
  /** Short status line posted to the user when a continuation is fired. */
535
570
  export function progressNote(goal) {
@@ -560,6 +595,8 @@ export function formatGoalStatus(goal, now) {
560
595
  ` Turns: ${turns}`,
561
596
  ` Tokens: ${budget}`,
562
597
  ` Age: ${ageSec}s`,
598
+ ...(goal.plateau ? [` ${formatGoalPlateau(goal.plateau)}`] : []),
599
+ ...(goal.exitReason ? [` Exit decision: ${goal.exitReason.kind}: ${goal.exitReason.reason}`] : []),
563
600
  ...(goal.blockedReason ? [` Reason: ${goal.blockedReason}`] : []),
564
601
  hint,
565
602
  ].join('\n');
@@ -583,7 +620,11 @@ export function decideContinuation(goal, facts, now) {
583
620
  // Codex's execution-unavailable rule: a turn that ran a command which failed
584
621
  // with nothing succeeding is evidence the environment, not the agent, is the
585
622
  // problem. Three in a row block the goal.
586
- const executionFailure = isExecutionFailureTurn(facts);
623
+ const executionFailure = isExecutionFailureTurn(facts)
624
+ && !(goal.plateau && hasFailedCompileObservation(facts.evidence, goal.updatedAt));
625
+ const reportedBlocker = (goal.plateau || goal.sustained) && facts.blockedReason
626
+ ? facts.blockedReason.replace(/\s+/gu, ' ').trim().slice(0, MAX_BLOCK_REASON_LEN) : '';
627
+ const condition = reportedBlocker.toLowerCase();
587
628
  const next = {
588
629
  ...goal,
589
630
  tokensUsed: goal.tokensUsed + turnTokens,
@@ -597,9 +638,15 @@ export function decideContinuation(goal, facts, now) {
597
638
  // clear), so an unrelated turn must not launder the streak.
598
639
  : (facts.hadSuccessfulTool ? 0 : goal.executionFailureStreak),
599
640
  updatedAt: now,
641
+ ...(goal.plateau ? { plateau: observeGoalPlateau(goal.plateau, facts.evidence, goal.createdAt) } : {}),
642
+ blockedAudit: condition ? { condition, streak: goal.blockedAudit?.condition === condition
643
+ ? Math.min(3, goal.blockedAudit.streak + 1) : 1 } : undefined,
600
644
  };
645
+ if (!condition)
646
+ delete next.blockedAudit;
601
647
  if (next.tokenBudget != null && next.tokensUsed >= next.tokenBudget) {
602
648
  next.status = 'budget_limited';
649
+ next.exitReason = { kind: 'budget_limited', reason: 'Explicit token budget exhausted.', evidenceIds: [] };
603
650
  return {
604
651
  next,
605
652
  decision: {
@@ -615,6 +662,7 @@ export function decideContinuation(goal, facts, now) {
615
662
  // (the default) has no maxTurns to compare against.
616
663
  if (next.maxTurns != null && next.turns >= next.maxTurns) {
617
664
  next.status = 'paused';
665
+ next.exitReason = { kind: 'turn_cap', reason: 'Explicit turn cap reached.', evidenceIds: [] };
618
666
  return {
619
667
  next,
620
668
  decision: {
@@ -626,8 +674,29 @@ export function decideContinuation(goal, facts, now) {
626
674
  },
627
675
  };
628
676
  }
677
+ // Adopted requests use the same completion channel as explicit goals. Caps
678
+ // above still take precedence, and explicit measurement criteria stay authoritative.
679
+ if (next.sustained && !next.plateau && detectGoalCompletion(facts.turnSummary)) {
680
+ next.status = 'complete';
681
+ next.exitReason = { kind: 'objective_complete', reason: 'Objective completion declared.', evidenceIds: [] };
682
+ return { next, decision: { kind: 'stop', status: 'complete', reason: 'objective complete', note: goalFinalNote(next) } };
683
+ }
684
+ if (next.plateau?.enabled && next.plateau.consecutiveNoImprovement >= next.plateau.criteria.attempts) {
685
+ next.status = 'complete';
686
+ next.exitReason = { kind: 'measured_plateau', reason: formatGoalPlateau(next.plateau), evidenceIds: [...next.plateau.comparisonIds] };
687
+ return { next, decision: { kind: 'stop', status: 'complete', reason: 'measured plateau',
688
+ note: `${next.exitReason.reason} Evidence: ${next.exitReason.evidenceIds.join(', ')}. Objective: ${next.objective}` } };
689
+ }
690
+ if (next.blockedAudit?.streak === 3) {
691
+ next.status = 'blocked';
692
+ next.blockedSource = 'agent';
693
+ next.blockedReason = reportedBlocker;
694
+ next.exitReason = { kind: 'blocked', reason: `Agent reported the same missing prerequisite for three consecutive turns: ${reportedBlocker}`, evidenceIds: [] };
695
+ return { next, decision: { kind: 'stop', status: 'blocked', reason: reportedBlocker, note: goalFinalNote(next) } };
696
+ }
629
697
  if (next.noProgressStreak >= NO_PROGRESS_LIMIT) {
630
698
  next.status = 'paused';
699
+ next.exitReason = { kind: 'no_progress', reason: 'Three automatic turns produced no observable activity.', evidenceIds: [] };
631
700
  return {
632
701
  next,
633
702
  decision: {
@@ -641,6 +710,7 @@ export function decideContinuation(goal, facts, now) {
641
710
  }
642
711
  if (next.stalledStreak >= STALL_LIMIT) {
643
712
  next.status = 'paused';
713
+ next.exitReason = { kind: 'stalled', reason: 'Repeated narration without new work.', evidenceIds: [] };
644
714
  return {
645
715
  next,
646
716
  decision: {
@@ -657,6 +727,7 @@ export function decideContinuation(goal, facts, now) {
657
727
  next.status = 'blocked';
658
728
  next.blockedSource = 'execution';
659
729
  next.blockedReason = `the command tool failed for ${next.executionFailureStreak} consecutive turns`;
730
+ next.exitReason = { kind: 'blocked', reason: next.blockedReason, evidenceIds: [] };
660
731
  return {
661
732
  next,
662
733
  decision: {
@@ -693,16 +764,72 @@ export class GoalManager {
693
764
  * gets a fresh final turn.
694
765
  */
695
766
  finalTurnAccounted = false;
767
+ sustainedFirstTurnPending = false;
696
768
  constructor(clock = realClock) {
697
769
  this.clock = clock;
698
770
  }
699
771
  /** A defensive copy so callers cannot mutate internal state. */
700
772
  get() {
701
- return this.goal ? { ...this.goal } : null;
773
+ return this.goal ? structuredClone(this.goal) : null;
774
+ }
775
+ /** Admit an explicit authored sustained-work request into the existing loop, without deriving extra scope or budget. */
776
+ adoptUserIntent(message, opts = {}) {
777
+ if (message.role !== 'user' || message.metadata?.synthetic || message.metadata?.compactionSummary || message.metadata?.toolResult)
778
+ return null;
779
+ const text = message.content;
780
+ // Steering stays ordinary user context. Replacing an existing goal requires /goal.
781
+ if (this.goal && this.goal.status !== 'complete')
782
+ return null;
783
+ if (!/\b(?:keep|continue)\s+(?:working|iterating|optimizing|doing|going)\b/iu.test(text)
784
+ || !/\buntil\b[\s\S]*\b(?:interrupt|stop|done|complete|plateau)\b/iu.test(text) || text.length > MAX_OBJECTIVE_LEN)
785
+ return null;
786
+ const parsed = parseGoalArgs(text.split(/\s+/u));
787
+ if ('error' in parsed)
788
+ return null;
789
+ const statedBudgets = [...text.matchAll(/\b(?:budget(?: of)?|limit(?: (?:total )?(?:token )?usage)? to|within|up to)\s+([\d,_]+)\s+tokens\b/giu)]
790
+ .map(match => parsePositiveInt(match[1]));
791
+ const budgets = [...new Set([...(parsed.tokenBudget === undefined ? [] : [parsed.tokenBudget]), ...statedBudgets])];
792
+ if (budgets.some(value => value === null || !Number.isSafeInteger(value)) || budgets.length > 1)
793
+ return null;
794
+ if (budgets[0] !== undefined && budgets[0] !== null)
795
+ parsed.tokenBudget = budgets[0];
796
+ this.set(parsed.objective, { ...parsed, maxTurns: resolveGoalTurnCap(parsed.maxTurns, opts.configuredMaxTurns) });
797
+ this.goal.sustained = { sourceMessageId: message.id,
798
+ sourceTextSha256: createHash('sha256').update(text).digest('hex'), hostExitOnly: false };
799
+ this.kick = buildKickPrompt(this.goal);
800
+ this.sustainedFirstTurnPending = true;
801
+ return this.get();
802
+ }
803
+ /** The authored opening turn spends the same budget as later automatic turns. */
804
+ accountSustainedFirstTurn(facts) {
805
+ if (!this.sustainedFirstTurnPending)
806
+ return null;
807
+ this.sustainedFirstTurnPending = false;
808
+ const decision = this.onTurnComplete(facts);
809
+ this.kick = decision.kind === 'continue' ? decision.prompt : null;
810
+ if (decision.kind === 'stop')
811
+ this.finalTurnAccounted = true;
812
+ return decision;
813
+ }
814
+ /** Host wait events retain an owned job reference; tool text never establishes waiting. */
815
+ observeHostWait(event) {
816
+ if (!this.goal || this.goal.status !== 'active')
817
+ return this.get();
818
+ if (event.type === 'command_wait') {
819
+ this.goal.exitReason = { kind: 'waiting', reason: `Waiting for owned managed command ${event.waiting.jobId}.`,
820
+ evidenceIds: [event.waiting.toolCallId] };
821
+ }
822
+ else if (this.goal.exitReason?.kind === 'waiting' && this.goal.exitReason.evidenceIds.includes(event.toolCallId)) {
823
+ delete this.goal.exitReason;
824
+ }
825
+ return this.get();
702
826
  }
703
827
  /** Start a brand-new goal (replaces any existing one) and arm the first turn. */
704
828
  set(objective, opts = {}) {
705
829
  const now = this.clock.now();
830
+ const plateau = opts.plateau === undefined ? undefined : parseGoalPlateauCriteria(opts.plateau);
831
+ if (opts.plateau !== undefined && !plateau)
832
+ throw new TypeError('Invalid explicit goal plateau criteria.');
706
833
  // No implicit cap: absent means uncapped. Callers that want the configured
707
834
  // default compose it with any explicit flag via resolveGoalTurnCap().
708
835
  const maxTurns = opts.maxTurns != null ? clampMaxTurns(opts.maxTurns) : undefined;
@@ -726,19 +853,23 @@ export class GoalManager {
726
853
  executionFailureStreak: 0,
727
854
  createdAt: now,
728
855
  updatedAt: now,
856
+ ...(plateau ? { plateau: makeGoalPlateau(plateau) } : {}),
729
857
  };
730
858
  this.kick = buildKickPrompt(this.goal);
731
859
  this.finalTurnAccounted = false;
732
- return { ...this.goal };
860
+ this.sustainedFirstTurnPending = false;
861
+ return structuredClone(this.goal);
733
862
  }
734
- pause() {
863
+ pause(kind = 'user_pause') {
735
864
  if (!this.goal)
736
865
  return null;
737
866
  if (this.goal.status === 'active')
738
867
  this.goal.status = 'paused';
739
868
  this.goal.updatedAt = this.clock.now();
869
+ this.goal.exitReason = { kind, reason: kind === 'user_cancelled' ? 'User interrupted the active work.' : 'User paused the goal.', evidenceIds: [] };
740
870
  this.kick = null;
741
- return { ...this.goal };
871
+ this.sustainedFirstTurnPending = false;
872
+ return structuredClone(this.goal);
742
873
  }
743
874
  /**
744
875
  * Re-activate a paused / budget-limited goal and arm a continuation turn.
@@ -756,7 +887,7 @@ export class GoalManager {
756
887
  if (!this.goal)
757
888
  return null;
758
889
  if (this.goal.status === 'complete')
759
- return { ...this.goal };
890
+ return structuredClone(this.goal);
760
891
  const g = this.goal;
761
892
  g.noProgressStreak = 0;
762
893
  g.stalledStreak = 0;
@@ -764,6 +895,8 @@ export class GoalManager {
764
895
  g.executionFailureStreak = 0;
765
896
  delete g.blockedReason;
766
897
  delete g.blockedSource;
898
+ delete g.blockedAudit;
899
+ delete g.exitReason;
767
900
  if (g.maxTurns != null && g.turns >= g.maxTurns)
768
901
  g.maxTurns = clampMaxTurns(g.turns + TURN_CAP_STEP);
769
902
  if (g.tokenBudget != null && g.tokensUsed >= g.tokenBudget)
@@ -773,13 +906,13 @@ export class GoalManager {
773
906
  this.kick = buildContinuationPrompt(g);
774
907
  // A resumed goal gets a fresh final turn to account.
775
908
  this.finalTurnAccounted = false;
776
- return { ...g };
909
+ return structuredClone(g);
777
910
  }
778
911
  clear() {
779
912
  const prev = this.goal;
780
913
  this.goal = null;
781
914
  this.kick = null;
782
- return prev ? { ...prev } : null;
915
+ return prev ? structuredClone(prev) : null;
783
916
  }
784
917
  /**
785
918
  * Account one goal-driven turn without touching the status. Used when the goal
@@ -800,7 +933,7 @@ export class GoalManager {
800
933
  this.accountTurn(facts);
801
934
  this.finalTurnAccounted = true;
802
935
  this.goal.updatedAt = this.clock.now();
803
- return { ...this.goal };
936
+ return structuredClone(this.goal);
804
937
  }
805
938
  /**
806
939
  * Mark the goal complete. When `facts` is supplied (sentinel-driven completion
@@ -817,9 +950,10 @@ export class GoalManager {
817
950
  this.finalTurnAccounted = true;
818
951
  }
819
952
  this.goal.status = 'complete';
953
+ this.goal.exitReason = { kind: 'objective_complete', reason: 'Objective completion declared.', evidenceIds: [] };
820
954
  this.goal.updatedAt = this.clock.now();
821
955
  this.kick = null;
822
- return { ...this.goal };
956
+ return structuredClone(this.goal);
823
957
  }
824
958
  /**
825
959
  * Mark the goal blocked: the agent declared it cannot reach the objective. Same
@@ -847,9 +981,10 @@ export class GoalManager {
847
981
  }
848
982
  this.goal.blockedSource = 'agent';
849
983
  this.goal.status = 'blocked';
984
+ this.goal.exitReason = { kind: 'blocked', reason: cleaned || 'Agent reported a missing prerequisite.', evidenceIds: [] };
850
985
  this.goal.updatedAt = this.clock.now();
851
986
  this.kick = null;
852
- return { ...this.goal };
987
+ return structuredClone(this.goal);
853
988
  }
854
989
  /** Fold one turn's token delta + turn count into the running totals. */
855
990
  accountTurn(facts) {
@@ -866,8 +1001,16 @@ export class GoalManager {
866
1001
  onTurnComplete(facts) {
867
1002
  if (!this.goal)
868
1003
  return { kind: 'idle' };
1004
+ if (this.sustainedFirstTurnPending && !facts.automaticGoalTurn) {
1005
+ this.sustainedFirstTurnPending = false;
1006
+ this.kick = null;
1007
+ }
869
1008
  const { next, decision } = decideContinuation(this.goal, facts, this.clock.now());
870
1009
  this.goal = next;
1010
+ if (decision.kind === 'stop' && next.exitReason?.kind === 'objective_complete') {
1011
+ this.finalTurnAccounted = true;
1012
+ this.kick = null;
1013
+ }
871
1014
  return decision;
872
1015
  }
873
1016
  /** Read-and-clear the pending kick prompt (first/continuation turn trigger). */
@@ -881,7 +1024,7 @@ export class GoalManager {
881
1024
  }
882
1025
  /** Snapshot for session persistence. */
883
1026
  serialize() {
884
- return this.goal ? { ...this.goal } : null;
1027
+ return this.goal ? structuredClone(this.goal) : null;
885
1028
  }
886
1029
  /**
887
1030
  * Restore from session persistence on resume. Arms no kick (no auto-start).
@@ -892,11 +1035,15 @@ export class GoalManager {
892
1035
  */
893
1036
  hydrate(record) {
894
1037
  this.kick = null;
1038
+ this.sustainedFirstTurnPending = false;
895
1039
  if (!record || !isValidGoalRecord(record)) {
896
1040
  this.goal = null;
897
1041
  return;
898
1042
  }
899
1043
  const now = this.clock.now();
1044
+ const plateau = record.plateau === undefined ? undefined : parseGoalPlateauState(record.plateau);
1045
+ const exitReason = parseGoalExitReason(record.exitReason);
1046
+ const sustained = parseSustainedGoalAuthority(record.sustained);
900
1047
  const finiteOr = (v, fallback) => (typeof v === 'number' && Number.isFinite(v)) ? v : fallback;
901
1048
  const nonNegInt = (v) => Math.max(0, Math.floor(finiteOr(v, 0)));
902
1049
  let tokenBudget;
@@ -930,6 +1077,14 @@ export class GoalManager {
930
1077
  : {}),
931
1078
  createdAt: finiteOr(record.createdAt, now),
932
1079
  updatedAt: finiteOr(record.updatedAt, now),
1080
+ ...(plateau ? { plateau } : {}),
1081
+ ...(exitReason ? { exitReason } : {}),
1082
+ ...(sustained ? { sustained } : {}),
1083
+ ...(record.blockedAudit && typeof record.blockedAudit.condition === 'string' && record.blockedAudit.condition.trim()
1084
+ && record.blockedAudit.condition.length <= MAX_BLOCK_REASON_LEN && Number.isInteger(record.blockedAudit.streak)
1085
+ && record.blockedAudit.streak >= 1 && record.blockedAudit.streak <= 3 ? { blockedAudit: structuredClone(record.blockedAudit) } : {}),
1086
+ ...((record.plateau !== undefined && !plateau) || (record.sustained !== undefined && !sustained) ? { status: 'paused',
1087
+ exitReason: { kind: 'criteria_unavailable', reason: 'Saved sustained authority or plateau criteria are invalid; explicit user replacement is required.', evidenceIds: [] } } : {}),
933
1088
  };
934
1089
  }
935
1090
  }
@@ -1038,6 +1193,10 @@ export const goalCommand = {
1038
1193
  }
1039
1194
  case 'complete':
1040
1195
  case 'done': {
1196
+ if (ctx.commandOrigin === 'agent' && existing?.plateau) {
1197
+ ctx.addMessage({ role: 'system', content: 'This sustained goal requires its configured host exit criterion, explicit user stop or budget. Completion prose cannot substitute for admitted measurements.' });
1198
+ return;
1199
+ }
1041
1200
  const g = goalManager.complete();
1042
1201
  ctx.addMessage({
1043
1202
  role: 'system',
@@ -1064,6 +1223,7 @@ export const goalCommand = {
1064
1223
  return;
1065
1224
  }
1066
1225
  const g = goalManager.set(parsed.objective, {
1226
+ ...(parsed.plateau ? { plateau: parsed.plateau } : {}),
1067
1227
  ...(parsed.tokenBudget != null ? { tokenBudget: parsed.tokenBudget } : {}),
1068
1228
  // Explicit --max-turns outranks the configured default; nothing here writes
1069
1229
  // config, so a per-goal cap never changes the global setting or the next
@@ -0,0 +1,36 @@
1
+ import { type EvidenceSnapshot } from '../runtime/evidence.js';
2
+ export interface GoalPlateauCriteria {
3
+ scope: 'benchmark:cpu_integer_sum';
4
+ attempts: number;
5
+ minImprovementPercent: number;
6
+ }
7
+ export interface GoalPlateauState {
8
+ criteria: GoalPlateauCriteria;
9
+ enabled: boolean;
10
+ bestObservationId: string | null;
11
+ bestReceiptId: string | null;
12
+ lastMeasurementAt: number;
13
+ measuredAttempts: number;
14
+ consecutiveNoImprovement: number;
15
+ comparisonIds: string[];
16
+ }
17
+ export interface GoalExitReason {
18
+ kind: 'objective_complete' | 'measured_plateau' | 'user_pause' | 'user_cancelled' | 'budget_limited' | 'turn_cap' | 'no_progress' | 'stalled' | 'blocked' | 'waiting' | 'criteria_unavailable';
19
+ reason: string;
20
+ evidenceIds: string[];
21
+ }
22
+ export declare function parseGoalPlateauCriteria(value: unknown): GoalPlateauCriteria | null;
23
+ export declare function makeGoalPlateau(criteria: GoalPlateauCriteria): GoalPlateauState;
24
+ export declare function parseGoalPlateauState(value: unknown): GoalPlateauState | null;
25
+ export declare function parseGoalExitReason(value: unknown): GoalExitReason | null;
26
+ export interface SustainedGoalAuthority {
27
+ sourceMessageId: string;
28
+ sourceTextSha256: string;
29
+ hostExitOnly: boolean;
30
+ }
31
+ export declare function parseSustainedGoalAuthority(value: unknown): SustainedGoalAuthority | null;
32
+ /** Consume canonical admitted comparisons; references and a monotonic original-run watermark are not another evidence ledger. */
33
+ export declare function observeGoalPlateau(state: GoalPlateauState, evidence: EvidenceSnapshot | undefined, createdAt: number): GoalPlateauState;
34
+ /** A real failed compile is an unmeasured attempt, not proof that the environment is inaccessible. */
35
+ export declare function hasFailedCompileObservation(evidence: EvidenceSnapshot | undefined, since: number): boolean;
36
+ export declare function formatGoalPlateau(state: GoalPlateauState): string;
@@ -0,0 +1,120 @@
1
+ import { parseEvidenceSnapshot } from '../runtime/evidence.js';
2
+ const integer = (value, minimum, maximum) => typeof value === 'number' && Number.isSafeInteger(value) && value >= minimum && value <= maximum;
3
+ const identity = (value) => typeof value === 'string' && value.trim().length > 0
4
+ && new TextEncoder().encode(value).length <= 256 && !/[\u0000-\u001f\u007f]/u.test(value);
5
+ function record(value) {
6
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
7
+ && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
8
+ }
9
+ function keys(value, allowed) {
10
+ return Object.keys(value).length === allowed.length && allowed.every(key => Object.hasOwn(value, key));
11
+ }
12
+ export function parseGoalPlateauCriteria(value) {
13
+ if (!record(value) || !keys(value, ['scope', 'attempts', 'minImprovementPercent']) || value.scope !== 'benchmark:cpu_integer_sum'
14
+ || !integer(value.attempts, 1, 32) || typeof value.minImprovementPercent !== 'number'
15
+ || !Number.isFinite(value.minImprovementPercent) || value.minImprovementPercent < 0 || value.minImprovementPercent > 100)
16
+ return null;
17
+ return { scope: value.scope, attempts: value.attempts, minImprovementPercent: value.minImprovementPercent };
18
+ }
19
+ export function makeGoalPlateau(criteria) {
20
+ return { criteria: structuredClone(criteria), enabled: true, bestObservationId: null, bestReceiptId: null,
21
+ lastMeasurementAt: 0, measuredAttempts: 0, consecutiveNoImprovement: 0, comparisonIds: [] };
22
+ }
23
+ export function parseGoalPlateauState(value) {
24
+ const required = ['criteria', 'bestObservationId', 'bestReceiptId', 'lastMeasurementAt',
25
+ 'measuredAttempts', 'consecutiveNoImprovement', 'comparisonIds'];
26
+ if (!record(value) || !keys(value, Object.hasOwn(value, 'enabled') ? [...required, 'enabled'] : required)
27
+ || (Object.hasOwn(value, 'enabled') && typeof value.enabled !== 'boolean'))
28
+ return null;
29
+ const criteria = parseGoalPlateauCriteria(value.criteria);
30
+ if (!criteria || !(value.bestObservationId === null || identity(value.bestObservationId))
31
+ || !(value.bestReceiptId === null || identity(value.bestReceiptId))
32
+ || (value.bestObservationId === null) !== (value.bestReceiptId === null)
33
+ || !integer(value.lastMeasurementAt, 0, Number.MAX_SAFE_INTEGER)
34
+ || !integer(value.measuredAttempts, 0, Number.MAX_SAFE_INTEGER)
35
+ || !integer(value.consecutiveNoImprovement, 0, criteria.attempts)
36
+ || value.consecutiveNoImprovement > value.measuredAttempts
37
+ || !Array.isArray(value.comparisonIds) || value.comparisonIds.length > 32 || !value.comparisonIds.every(identity)
38
+ || value.comparisonIds.length !== value.consecutiveNoImprovement
39
+ || (value.enabled !== false && value.measuredAttempts > 0 && value.bestObservationId === null)
40
+ || new Set(value.comparisonIds).size !== value.comparisonIds.length)
41
+ return null;
42
+ return { ...structuredClone(value), enabled: value.enabled ?? true };
43
+ }
44
+ export function parseGoalExitReason(value) {
45
+ if (!record(value) || !keys(value, ['kind', 'reason', 'evidenceIds']) || typeof value.kind !== 'string'
46
+ || !['objective_complete', 'measured_plateau', 'user_pause', 'user_cancelled', 'budget_limited',
47
+ 'turn_cap', 'no_progress', 'stalled', 'blocked', 'waiting', 'criteria_unavailable'].includes(value.kind)
48
+ || typeof value.reason !== 'string' || !value.reason.trim() || new TextEncoder().encode(value.reason).length > 2048
49
+ || !Array.isArray(value.evidenceIds) || value.evidenceIds.length > 32 || !value.evidenceIds.every(identity)
50
+ || new Set(value.evidenceIds).size !== value.evidenceIds.length)
51
+ return null;
52
+ return structuredClone(value);
53
+ }
54
+ export function parseSustainedGoalAuthority(value) {
55
+ if (!record(value) || !keys(value, ['sourceMessageId', 'sourceTextSha256', 'hostExitOnly'])
56
+ || !identity(value.sourceMessageId) || typeof value.sourceTextSha256 !== 'string'
57
+ || !/^[a-f0-9]{64}$/u.test(value.sourceTextSha256) || typeof value.hostExitOnly !== 'boolean')
58
+ return null;
59
+ return structuredClone(value);
60
+ }
61
+ /** Consume canonical admitted comparisons; references and a monotonic original-run watermark are not another evidence ledger. */
62
+ export function observeGoalPlateau(state, evidence, createdAt) {
63
+ const next = structuredClone(state);
64
+ const snapshot = parseEvidenceSnapshot(evidence);
65
+ if (!next.enabled || !snapshot)
66
+ return next;
67
+ for (const row of snapshot.records) {
68
+ if (row.kind !== 'observation' || row.availability === 'unavailable')
69
+ continue;
70
+ const comparison = row.source.benchmarkComparison;
71
+ if (!comparison || comparison.outcome !== 'comparable' || comparison.scope !== next.criteria.scope
72
+ || !comparison.baseline || !comparison.candidate)
73
+ continue;
74
+ const candidate = snapshot.records.find(item => item.id === comparison.candidate.observation_id);
75
+ const receipt = candidate?.source.verification;
76
+ if (candidate?.kind !== 'observation' || candidate.availability === 'unavailable'
77
+ || receipt?.receipt_id !== comparison.candidate.receipt_id || !receipt.end_source)
78
+ continue;
79
+ const measuredAt = Date.parse(receipt.end_source.captured_at);
80
+ // A newer comparison of an old run is not a new experiment, including after resume or bounded history eviction.
81
+ if (!Number.isSafeInteger(measuredAt) || measuredAt < createdAt || measuredAt <= next.lastMeasurementAt)
82
+ continue;
83
+ if (next.bestObservationId !== null && (comparison.baseline.observation_id !== next.bestObservationId
84
+ || comparison.baseline.receipt_id !== next.bestReceiptId))
85
+ continue;
86
+ next.bestObservationId ??= comparison.baseline.observation_id;
87
+ next.bestReceiptId ??= comparison.baseline.receipt_id;
88
+ next.lastMeasurementAt = measuredAt;
89
+ next.measuredAttempts++;
90
+ const improvement = -comparison.relative_change_percent;
91
+ if (improvement > 0 && improvement >= next.criteria.minImprovementPercent) {
92
+ next.bestObservationId = comparison.candidate.observation_id;
93
+ next.bestReceiptId = comparison.candidate.receipt_id;
94
+ next.consecutiveNoImprovement = 0;
95
+ next.comparisonIds = [];
96
+ }
97
+ else {
98
+ next.consecutiveNoImprovement++;
99
+ next.comparisonIds = [...next.comparisonIds, row.id].slice(-32);
100
+ }
101
+ if (next.consecutiveNoImprovement >= next.criteria.attempts)
102
+ break;
103
+ }
104
+ return next;
105
+ }
106
+ /** A real failed compile is an unmeasured attempt, not proof that the environment is inaccessible. */
107
+ export function hasFailedCompileObservation(evidence, since) {
108
+ return parseEvidenceSnapshot(evidence)?.records.some(row => row.kind === 'observation'
109
+ && row.source.origin === 'host_receipt' && row.source.toolName === 'run_command'
110
+ && Date.parse(row.recordedAt) >= since && row.source.verification?.purpose === 'compile'
111
+ && row.source.verification.process_outcome === 'failed') ?? false;
112
+ }
113
+ export function formatGoalPlateau(state) {
114
+ if (!state.enabled)
115
+ return `Plateau criterion suspended after scope steering: ${state.criteria.scope}; `
116
+ + `${state.measuredAttempts} earlier admitted measurements. A new applicable criterion requires explicit user selection.`;
117
+ return `Plateau criterion: ${state.criteria.attempts} comparable ${state.criteria.scope} attempts without `
118
+ + `${state.criteria.minImprovementPercent}% improvement (${state.consecutiveNoImprovement}/${state.criteria.attempts}); `
119
+ + `${state.measuredAttempts} admitted measurements. A measured delta is not a causal performance claim.`;
120
+ }
@@ -1,4 +1,5 @@
1
1
  import { buildHelpIntroduction } from '../../onboarding/first_run.js';
2
+ import { STATUS_LINE_ITEMS, STATUS_LINE_ITEM_LABELS, STATUS_LINE_ITEM_DESCRIPTIONS } from '../../ui/status_line_config.js';
2
3
  export function makeHelpCommand(getCommands) {
3
4
  return {
4
5
  name: 'help',
@@ -6,6 +7,7 @@ export function makeHelpCommand(getCommands) {
6
7
  agentRunnable: true,
7
8
  category: 'core',
8
9
  handler: (_, ctx) => {
10
+ const statusHelp = STATUS_LINE_ITEMS.map(item => ` ${STATUS_LINE_ITEM_LABELS[item]}: ${STATUS_LINE_ITEM_DESCRIPTIONS[item]}`).join('\n');
9
11
  const helpText = getCommands()
10
12
  .map(c => {
11
13
  const cmdLine = c.usage ? ` ${c.usage}` : ` /${c.name}`;
@@ -14,7 +16,7 @@ export function makeHelpCommand(getCommands) {
14
16
  .join('\n\n');
15
17
  ctx.addMessage({
16
18
  role: 'system',
17
- content: `${buildHelpIntroduction()}\n\nAvailable commands:\n\n${helpText || ' No commands registered.'}`
19
+ content: `${buildHelpIntroduction()}\n\nKeyboard actions:\n Esc twice within 2 seconds confirms stop of the running turn.\n In the queue editor (Option+Up), Esc removes only the selected queued message.\n Forms, choices and completions close with one Esc; idle Esc keeps the draft and queue.\n /rewind opens the Ratatui history picker; Ctrl+B ? opens zmux shortcut help.\n\nMouse and scrolling:\n /settings mouseCapture toggles terminal mouse capture.\n /settings wheelScrollLines sets 1–20 lines per wheel event (default 3).\n These preferences require a compatible native renderer; otherwise they are saved for the next compatible launch.\n\nStatus line fields:\n${statusHelp}\n\nAvailable commands:\n\n${helpText || ' No commands registered.'}`
18
20
  });
19
21
  }
20
22
  };
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  export const clearCommand = {
2
3
  name: 'clear',
3
4
  description: 'Clear message history',
@@ -11,7 +12,8 @@ export const clearCommand = {
11
12
  ctx.clearTransientState?.();
12
13
  ctx.addMessage({
13
14
  role: 'system',
14
- content: 'Message history cleared.'
15
+ content: 'Message history cleared.',
16
+ metadata: { taskHandoffReset: randomUUID() },
15
17
  });
16
18
  }
17
19
  };
@@ -0,0 +1,2 @@
1
+ import type { Command } from './types.js';
2
+ export declare const inboxCommand: Command;