okstra 0.173.0 → 0.175.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 (402) hide show
  1. package/README.md +18 -9
  2. package/bin/okstra +8 -4
  3. package/dist/cli-registry.d.mts +16 -0
  4. package/dist/cli-registry.mjs +560 -0
  5. package/dist/cli-registry.mjs.map +1 -0
  6. package/dist/commands/execute/agent-prompt.d.mts +1 -0
  7. package/{src → dist}/commands/execute/agent-prompt.mjs +10 -11
  8. package/dist/commands/execute/agent-prompt.mjs.map +1 -0
  9. package/dist/commands/execute/codex-dispatch.d.mts +3 -0
  10. package/dist/commands/execute/codex-dispatch.mjs +6 -0
  11. package/dist/commands/execute/codex-dispatch.mjs.map +1 -0
  12. package/dist/commands/execute/codex-run.d.mts +3 -0
  13. package/{src → dist}/commands/execute/codex-run.mjs +30 -37
  14. package/dist/commands/execute/codex-run.mjs.map +1 -0
  15. package/dist/commands/execute/convergence.d.mts +1 -0
  16. package/{src → dist}/commands/execute/convergence.mjs +15 -16
  17. package/dist/commands/execute/convergence.mjs.map +1 -0
  18. package/dist/commands/execute/error-log.d.mts +1 -0
  19. package/{src → dist}/commands/execute/error-log.mjs +2 -3
  20. package/dist/commands/execute/error-log.mjs.map +1 -0
  21. package/dist/commands/execute/git-reconcile.d.mts +1 -0
  22. package/{src → dist}/commands/execute/git-reconcile.mjs +10 -11
  23. package/dist/commands/execute/git-reconcile.mjs.map +1 -0
  24. package/dist/commands/execute/handoff.d.mts +1 -0
  25. package/{src → dist}/commands/execute/handoff.mjs +10 -11
  26. package/dist/commands/execute/handoff.mjs.map +1 -0
  27. package/dist/commands/execute/incremental-carry.d.mts +1 -0
  28. package/{src → dist}/commands/execute/incremental-carry.mjs +2 -3
  29. package/dist/commands/execute/incremental-carry.mjs.map +1 -0
  30. package/dist/commands/execute/incremental-scope.d.mts +1 -0
  31. package/{src → dist}/commands/execute/incremental-scope.mjs +2 -3
  32. package/dist/commands/execute/incremental-scope.mjs.map +1 -0
  33. package/dist/commands/execute/integrate-stages.d.mts +1 -0
  34. package/{src → dist}/commands/execute/integrate-stages.mjs +10 -11
  35. package/dist/commands/execute/integrate-stages.mjs.map +1 -0
  36. package/dist/commands/execute/pane-title.d.mts +1 -0
  37. package/dist/commands/execute/pane-title.mjs +20 -0
  38. package/dist/commands/execute/pane-title.mjs.map +1 -0
  39. package/dist/commands/execute/plan-items.d.mts +1 -0
  40. package/dist/commands/execute/plan-items.mjs +9 -0
  41. package/dist/commands/execute/plan-items.mjs.map +1 -0
  42. package/dist/commands/execute/plan-validate.d.mts +1 -0
  43. package/dist/commands/execute/plan-validate.mjs +68 -0
  44. package/dist/commands/execute/plan-validate.mjs.map +1 -0
  45. package/dist/commands/execute/plan-verify.d.mts +1 -0
  46. package/{src → dist}/commands/execute/plan-verify.mjs +13 -16
  47. package/dist/commands/execute/plan-verify.mjs.map +1 -0
  48. package/dist/commands/execute/render-bundle.d.mts +3 -0
  49. package/{src → dist}/commands/execute/render-bundle.mjs +65 -61
  50. package/dist/commands/execute/render-bundle.mjs.map +1 -0
  51. package/dist/commands/execute/run.d.mts +24 -0
  52. package/dist/commands/execute/run.mjs +196 -0
  53. package/dist/commands/execute/run.mjs.map +1 -0
  54. package/dist/commands/execute/spawn-followups.d.mts +1 -0
  55. package/{src → dist}/commands/execute/spawn-followups.mjs +6 -7
  56. package/dist/commands/execute/spawn-followups.mjs.map +1 -0
  57. package/dist/commands/execute/team.d.mts +3 -0
  58. package/dist/commands/execute/team.mjs +56 -0
  59. package/dist/commands/execute/team.mjs.map +1 -0
  60. package/dist/commands/execute/token-usage.d.mts +1 -0
  61. package/{src → dist}/commands/execute/token-usage.mjs +2 -3
  62. package/dist/commands/execute/token-usage.mjs.map +1 -0
  63. package/dist/commands/execute/wizard.d.mts +8 -0
  64. package/dist/commands/execute/wizard.mjs +191 -0
  65. package/dist/commands/execute/wizard.mjs.map +1 -0
  66. package/dist/commands/execute/worker-audit-check.d.mts +1 -0
  67. package/{src → dist}/commands/execute/worker-audit-check.mjs +11 -12
  68. package/dist/commands/execute/worker-audit-check.mjs.map +1 -0
  69. package/dist/commands/execute/worker-dispatch.d.mts +7 -0
  70. package/{src → dist}/commands/execute/worker-dispatch.mjs +34 -46
  71. package/dist/commands/execute/worker-dispatch.mjs.map +1 -0
  72. package/dist/commands/execute/worker-state.d.mts +1 -0
  73. package/{src → dist}/commands/execute/worker-state.mjs +15 -16
  74. package/dist/commands/execute/worker-state.mjs.map +1 -0
  75. package/dist/commands/execute/worktree-lookup.d.mts +1 -0
  76. package/{src → dist}/commands/execute/worktree-lookup.mjs +38 -37
  77. package/dist/commands/execute/worktree-lookup.mjs.map +1 -0
  78. package/dist/commands/execute/worktree-status.d.mts +1 -0
  79. package/dist/commands/execute/worktree-status.mjs +115 -0
  80. package/dist/commands/execute/worktree-status.mjs.map +1 -0
  81. package/dist/commands/inspect/code-review.d.mts +1 -0
  82. package/{src → dist}/commands/inspect/code-review.mjs +16 -19
  83. package/dist/commands/inspect/code-review.mjs.map +1 -0
  84. package/dist/commands/inspect/container.d.mts +1 -0
  85. package/{src → dist}/commands/inspect/container.mjs +11 -13
  86. package/dist/commands/inspect/container.mjs.map +1 -0
  87. package/dist/commands/inspect/context-cost.d.mts +1 -0
  88. package/{src → dist}/commands/inspect/context-cost.mjs +11 -13
  89. package/dist/commands/inspect/context-cost.mjs.map +1 -0
  90. package/dist/commands/inspect/design-prep.d.mts +1 -0
  91. package/{src → dist}/commands/inspect/design-prep.mjs +10 -11
  92. package/dist/commands/inspect/design-prep.mjs.map +1 -0
  93. package/dist/commands/inspect/error-report.d.mts +1 -0
  94. package/{src → dist}/commands/inspect/error-report.mjs +11 -13
  95. package/dist/commands/inspect/error-report.mjs.map +1 -0
  96. package/dist/commands/inspect/error-zip.d.mts +1 -0
  97. package/{src → dist}/commands/inspect/error-zip.mjs +11 -12
  98. package/dist/commands/inspect/error-zip.mjs.map +1 -0
  99. package/dist/commands/inspect/log-report.d.mts +1 -0
  100. package/{src → dist}/commands/inspect/log-report.mjs +11 -13
  101. package/dist/commands/inspect/log-report.mjs.map +1 -0
  102. package/dist/commands/inspect/profile-show.d.mts +1 -0
  103. package/{src → dist}/commands/inspect/profile-show.mjs +10 -11
  104. package/dist/commands/inspect/profile-show.mjs.map +1 -0
  105. package/dist/commands/inspect/recap.d.mts +1 -0
  106. package/{src → dist}/commands/inspect/recap.mjs +11 -13
  107. package/dist/commands/inspect/recap.mjs.map +1 -0
  108. package/dist/commands/inspect/resolve-task-key.d.mts +1 -0
  109. package/{src → dist}/commands/inspect/resolve-task-key.mjs +11 -13
  110. package/dist/commands/inspect/resolve-task-key.mjs.map +1 -0
  111. package/dist/commands/inspect/rollup.d.mts +1 -0
  112. package/{src → dist}/commands/inspect/rollup.mjs +11 -13
  113. package/dist/commands/inspect/rollup.mjs.map +1 -0
  114. package/dist/commands/inspect/run-audit.d.mts +1 -0
  115. package/{src → dist}/commands/inspect/run-audit.mjs +11 -12
  116. package/dist/commands/inspect/run-audit.mjs.map +1 -0
  117. package/dist/commands/inspect/set-work-status.d.mts +1 -0
  118. package/{src → dist}/commands/inspect/set-work-status.mjs +11 -13
  119. package/dist/commands/inspect/set-work-status.mjs.map +1 -0
  120. package/dist/commands/inspect/stage-map.d.mts +1 -0
  121. package/dist/commands/inspect/stage-map.mjs +110 -0
  122. package/dist/commands/inspect/stage-map.mjs.map +1 -0
  123. package/dist/commands/inspect/task-list.d.mts +1 -0
  124. package/dist/commands/inspect/task-list.mjs +103 -0
  125. package/dist/commands/inspect/task-list.mjs.map +1 -0
  126. package/dist/commands/inspect/task-show.d.mts +1 -0
  127. package/dist/commands/inspect/task-show.mjs +108 -0
  128. package/dist/commands/inspect/task-show.mjs.map +1 -0
  129. package/dist/commands/inspect/time-report.d.mts +1 -0
  130. package/{src → dist}/commands/inspect/time-report.mjs +11 -13
  131. package/dist/commands/inspect/time-report.mjs.map +1 -0
  132. package/dist/commands/inspect/usage-report.d.mts +1 -0
  133. package/{src → dist}/commands/inspect/usage-report.mjs +11 -13
  134. package/dist/commands/inspect/usage-report.mjs.map +1 -0
  135. package/dist/commands/inspect/user-response.d.mts +1 -0
  136. package/{src → dist}/commands/inspect/user-response.mjs +10 -11
  137. package/dist/commands/inspect/user-response.mjs.map +1 -0
  138. package/dist/commands/inspect/worker-liveness.d.mts +1 -0
  139. package/{src → dist}/commands/inspect/worker-liveness.mjs +11 -13
  140. package/dist/commands/inspect/worker-liveness.mjs.map +1 -0
  141. package/dist/commands/lifecycle/check-project.d.mts +21 -0
  142. package/dist/commands/lifecycle/check-project.mjs +175 -0
  143. package/dist/commands/lifecycle/check-project.mjs.map +1 -0
  144. package/dist/commands/lifecycle/config.d.mts +1 -0
  145. package/dist/commands/lifecycle/config.mjs +369 -0
  146. package/dist/commands/lifecycle/config.mjs.map +1 -0
  147. package/dist/commands/lifecycle/doctor.d.mts +10 -0
  148. package/dist/commands/lifecycle/doctor.mjs +317 -0
  149. package/dist/commands/lifecycle/doctor.mjs.map +1 -0
  150. package/dist/commands/lifecycle/install.d.mts +17 -0
  151. package/dist/commands/lifecycle/install.mjs +1077 -0
  152. package/dist/commands/lifecycle/install.mjs.map +1 -0
  153. package/dist/commands/lifecycle/migrate.d.mts +1 -0
  154. package/{src → dist}/commands/lifecycle/migrate.mjs +10 -11
  155. package/dist/commands/lifecycle/migrate.mjs.map +1 -0
  156. package/dist/commands/lifecycle/model.d.mts +1 -0
  157. package/dist/commands/lifecycle/model.mjs +22 -0
  158. package/dist/commands/lifecycle/model.mjs.map +1 -0
  159. package/dist/commands/lifecycle/paths.d.mts +1 -0
  160. package/dist/commands/lifecycle/paths.mjs +102 -0
  161. package/dist/commands/lifecycle/paths.mjs.map +1 -0
  162. package/dist/commands/lifecycle/preflight.d.mts +1 -0
  163. package/dist/commands/lifecycle/preflight.mjs +124 -0
  164. package/dist/commands/lifecycle/preflight.mjs.map +1 -0
  165. package/dist/commands/lifecycle/setup.d.mts +1 -0
  166. package/dist/commands/lifecycle/setup.mjs +297 -0
  167. package/dist/commands/lifecycle/setup.mjs.map +1 -0
  168. package/dist/commands/lifecycle/uninstall.d.mts +4 -0
  169. package/dist/commands/lifecycle/uninstall.mjs +262 -0
  170. package/dist/commands/lifecycle/uninstall.mjs.map +1 -0
  171. package/dist/commands/manager.d.mts +3 -0
  172. package/{src → dist}/commands/manager.mjs +25 -32
  173. package/dist/commands/manager.mjs.map +1 -0
  174. package/dist/commands/memory/memory.d.mts +1 -0
  175. package/dist/commands/memory/memory.mjs +569 -0
  176. package/dist/commands/memory/memory.mjs.map +1 -0
  177. package/dist/commands/pr/pr.d.mts +33 -0
  178. package/dist/commands/pr/pr.mjs +296 -0
  179. package/dist/commands/pr/pr.mjs.map +1 -0
  180. package/dist/commands/report/agent-activity.d.mts +1 -0
  181. package/{src → dist}/commands/report/agent-activity.mjs +11 -12
  182. package/dist/commands/report/agent-activity.mjs.map +1 -0
  183. package/dist/commands/report/finalize.d.mts +4 -0
  184. package/dist/commands/report/finalize.mjs +64 -0
  185. package/dist/commands/report/finalize.mjs.map +1 -0
  186. package/dist/commands/report/inject-report-index.d.mts +1 -0
  187. package/{src → dist}/commands/report/inject-report-index.mjs +6 -7
  188. package/dist/commands/report/inject-report-index.mjs.map +1 -0
  189. package/dist/commands/report/render-final-report.d.mts +1 -0
  190. package/{src → dist}/commands/report/render-final-report.mjs +6 -7
  191. package/dist/commands/report/render-final-report.mjs.map +1 -0
  192. package/dist/commands/report/render-views.d.mts +1 -0
  193. package/{src → dist}/commands/report/render-views.mjs +6 -7
  194. package/dist/commands/report/render-views.mjs.map +1 -0
  195. package/dist/commands/report/translate.d.mts +1 -0
  196. package/{src → dist}/commands/report/translate.mjs +6 -7
  197. package/dist/commands/report/translate.mjs.map +1 -0
  198. package/dist/lib/helper-scripts.d.mts +3 -0
  199. package/{src → dist}/lib/helper-scripts.mjs +11 -14
  200. package/dist/lib/helper-scripts.mjs.map +1 -0
  201. package/dist/lib/host-registry-client.d.mts +25 -0
  202. package/dist/lib/host-registry-client.mjs +152 -0
  203. package/dist/lib/host-registry-client.mjs.map +1 -0
  204. package/dist/lib/install-assets.d.mts +8 -0
  205. package/{src → dist}/lib/install-assets.mjs +17 -20
  206. package/dist/lib/install-assets.mjs.map +1 -0
  207. package/dist/lib/okstra-dirs.d.mts +4 -0
  208. package/{src → dist}/lib/okstra-dirs.mjs +3 -6
  209. package/dist/lib/okstra-dirs.mjs.map +1 -0
  210. package/dist/lib/paths.d.mts +4 -0
  211. package/dist/lib/paths.mjs +78 -0
  212. package/dist/lib/paths.mjs.map +1 -0
  213. package/dist/lib/proc.d.mts +3 -0
  214. package/dist/lib/proc.mjs +31 -0
  215. package/dist/lib/proc.mjs.map +1 -0
  216. package/dist/lib/python-helper.d.mts +8 -0
  217. package/dist/lib/python-helper.mjs +123 -0
  218. package/dist/lib/python-helper.mjs.map +1 -0
  219. package/dist/lib/runtime-manifest.d.mts +7 -0
  220. package/dist/lib/runtime-manifest.mjs +73 -0
  221. package/dist/lib/runtime-manifest.mjs.map +1 -0
  222. package/dist/lib/skill-catalog.d.mts +4 -0
  223. package/dist/lib/skill-catalog.mjs +50 -0
  224. package/dist/lib/skill-catalog.mjs.map +1 -0
  225. package/dist/lib/types.d.mts +129 -0
  226. package/dist/lib/types.mjs +2 -0
  227. package/dist/lib/types.mjs.map +1 -0
  228. package/dist/lib/version.d.mts +2 -0
  229. package/dist/lib/version.mjs +27 -0
  230. package/dist/lib/version.mjs.map +1 -0
  231. package/docs/architecture/storage-model.md +17 -3
  232. package/docs/architecture.md +12 -22
  233. package/docs/cli.md +29 -8
  234. package/docs/container.md +1 -1
  235. package/docs/contributor-change-matrix.md +3 -3
  236. package/docs/project-structure-overview.md +29 -20
  237. package/docs/task-process/README.md +3 -1
  238. package/docs/task-process/implementation-planning.md +2 -2
  239. package/docs/task-process/implementation.md +1 -1
  240. package/package.json +11 -5
  241. package/runtime/BUILD.json +2 -2
  242. package/runtime/agents/workers/claude-worker.md +3 -2
  243. package/runtime/agents/workers/report-writer-worker.md +3 -1
  244. package/runtime/agents/workers/translator-worker.md +3 -1
  245. package/runtime/bin/lib/okstra/cli.sh +12 -0
  246. package/runtime/bin/lib/okstra/globals.sh +4 -1
  247. package/runtime/bin/lib/okstra/usage.sh +4 -4
  248. package/runtime/bin/okstra-error-log.py +27 -0
  249. package/runtime/bin/okstra-provider-exec.py +245 -16
  250. package/runtime/bin/okstra-trace-cleanup.sh +58 -129
  251. package/runtime/bin/okstra.sh +10 -0
  252. package/runtime/prompts/lead/adapters/cmux.md +2 -0
  253. package/runtime/prompts/lead/convergence.md +27 -18
  254. package/runtime/prompts/lead/okstra-lead-contract.md +4 -2
  255. package/runtime/prompts/lead/plan-body-verification.md +13 -6
  256. package/runtime/prompts/lead/report-writer.md +6 -6
  257. package/runtime/prompts/lead/team-contract.md +1 -1
  258. package/runtime/prompts/profiles/_common-contract.md +2 -2
  259. package/runtime/prompts/profiles/_implementation-executor.md +2 -0
  260. package/runtime/prompts/profiles/_implementation-verifier.md +2 -2
  261. package/runtime/prompts/profiles/change-impact-analysis.md +16 -0
  262. package/runtime/prompts/profiles/error-analysis.md +21 -1
  263. package/runtime/prompts/profiles/feature-analysis.md +16 -0
  264. package/runtime/prompts/profiles/final-verification.md +16 -0
  265. package/runtime/prompts/profiles/implementation-option-selection.md +16 -0
  266. package/runtime/prompts/profiles/implementation-planning.md +32 -9
  267. package/runtime/prompts/profiles/implementation.md +17 -1
  268. package/runtime/prompts/profiles/improvement-discovery.md +16 -0
  269. package/runtime/prompts/profiles/project-analysis.md +16 -0
  270. package/runtime/prompts/profiles/release-handoff.md +5 -1
  271. package/runtime/prompts/profiles/requirements-discovery.md +20 -0
  272. package/runtime/prompts/wizard/prompts.ko.json +18 -0
  273. package/runtime/python/okstra_ctl/adapters/dispatch/__init__.py +1 -6
  274. package/runtime/python/okstra_ctl/adapters/dispatch/cli_wrapper.py +8 -0
  275. package/runtime/python/okstra_ctl/adapters/dispatch/cmux.py +8 -0
  276. package/runtime/python/okstra_ctl/adapters/dispatch/native_team.py +13 -0
  277. package/runtime/python/okstra_ctl/adapters/hosts/antigravity/adapter.py +2 -2
  278. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +25 -5
  279. package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +2 -2
  280. package/runtime/python/okstra_ctl/adapters/hosts/external/adapter.py +4 -1
  281. package/runtime/python/okstra_ctl/adapters/hosts/external/relay.md +4 -4
  282. package/runtime/python/okstra_ctl/adapters/hosts/grok/adapter.py +2 -2
  283. package/runtime/python/okstra_ctl/adapters/hosts/kimi/adapter.py +2 -2
  284. package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +79 -11
  285. package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +100 -25
  286. package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +59 -14
  287. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +55 -9
  288. package/runtime/python/okstra_ctl/adapters/providers/kimi/adapter.py +51 -12
  289. package/runtime/python/okstra_ctl/agent_activity.py +5 -1
  290. package/runtime/python/okstra_ctl/agent_invocation.py +608 -14
  291. package/runtime/python/okstra_ctl/agent_prompt_cli.py +249 -50
  292. package/runtime/python/okstra_ctl/application/resolve_assignment.py +53 -12
  293. package/runtime/python/okstra_ctl/assignment_environment.py +102 -0
  294. package/runtime/python/okstra_ctl/assignment_resolver.py +790 -0
  295. package/runtime/python/okstra_ctl/attempt_evidence.py +342 -0
  296. package/runtime/python/okstra_ctl/conformance.py +68 -0
  297. package/runtime/python/okstra_ctl/convergence.py +409 -3
  298. package/runtime/python/okstra_ctl/convergence_engine.py +248 -15
  299. package/runtime/python/okstra_ctl/convergence_store.py +170 -1
  300. package/runtime/python/okstra_ctl/dispatch_core.py +1181 -102
  301. package/runtime/python/okstra_ctl/dispatch_state.py +835 -22
  302. package/runtime/python/okstra_ctl/doctor.py +16 -2
  303. package/runtime/python/okstra_ctl/domain/host.py +32 -1
  304. package/runtime/python/okstra_ctl/domain/provider.py +212 -6
  305. package/runtime/python/okstra_ctl/domain/role.py +125 -0
  306. package/runtime/python/okstra_ctl/domain/wizard/interaction.py +13 -0
  307. package/runtime/python/okstra_ctl/domain/worker_exec.py +39 -1
  308. package/runtime/python/okstra_ctl/domain/worker_role.py +13 -3
  309. package/runtime/python/okstra_ctl/domain/worker_stream.py +24 -0
  310. package/runtime/python/okstra_ctl/error_log_write.py +9 -0
  311. package/runtime/python/okstra_ctl/error_report.py +21 -1
  312. package/runtime/python/okstra_ctl/execution_identity.py +529 -0
  313. package/runtime/python/okstra_ctl/execution_manifest.py +1281 -0
  314. package/runtime/python/okstra_ctl/execution_mutation_audit.py +619 -0
  315. package/runtime/python/okstra_ctl/final_report_schema.py +5 -4
  316. package/runtime/python/okstra_ctl/index.py +6 -2
  317. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +43 -3
  318. package/runtime/python/okstra_ctl/legacy_model_selection.py +490 -0
  319. package/runtime/python/okstra_ctl/model_cli.py +278 -0
  320. package/runtime/python/okstra_ctl/model_defaults.py +46 -0
  321. package/runtime/python/okstra_ctl/model_discovery.py +26 -7
  322. package/runtime/python/okstra_ctl/model_pool.py +501 -0
  323. package/runtime/python/okstra_ctl/models.py +47 -27
  324. package/runtime/python/okstra_ctl/mutation_recovery.py +293 -0
  325. package/runtime/python/okstra_ctl/pane_reclaim.py +13 -22
  326. package/runtime/python/okstra_ctl/pane_title.py +151 -0
  327. package/runtime/python/okstra_ctl/ports/host_model.py +48 -17
  328. package/runtime/python/okstra_ctl/ports/worker_dispatch.py +4 -0
  329. package/runtime/python/okstra_ctl/registry/provider_registry.py +8 -4
  330. package/runtime/python/okstra_ctl/render.py +78 -10
  331. package/runtime/python/okstra_ctl/render_final_report.py +34 -19
  332. package/runtime/python/okstra_ctl/report_contract.py +39 -1
  333. package/runtime/python/okstra_ctl/report_finalize.py +84 -9
  334. package/runtime/python/okstra_ctl/report_html/render.py +1 -0
  335. package/runtime/python/okstra_ctl/role_requirements.py +217 -0
  336. package/runtime/python/okstra_ctl/run.py +1250 -260
  337. package/runtime/python/okstra_ctl/run_index_row.py +7 -1
  338. package/runtime/python/okstra_ctl/schema_excerpt.py +1 -1
  339. package/runtime/python/okstra_ctl/scope_provenance.py +1 -1
  340. package/runtime/python/okstra_ctl/session.py +69 -12
  341. package/runtime/python/okstra_ctl/team.py +51 -25
  342. package/runtime/python/okstra_ctl/time_report.py +38 -4
  343. package/runtime/python/okstra_ctl/tmux.py +19 -149
  344. package/runtime/python/okstra_ctl/usage_identity.py +86 -0
  345. package/runtime/python/okstra_ctl/usage_report.py +15 -3
  346. package/runtime/python/okstra_ctl/wizard.py +1253 -62
  347. package/runtime/python/okstra_ctl/worker_audit_ledger.py +68 -65
  348. package/runtime/python/okstra_ctl/worker_request.py +9 -1
  349. package/runtime/python/okstra_ctl/worker_runner.py +130 -5
  350. package/runtime/python/okstra_ctl/workers.py +7 -5
  351. package/runtime/python/okstra_ctl/worktree.py +69 -3
  352. package/runtime/python/okstra_ctl/write_policy.py +571 -0
  353. package/runtime/python/okstra_token_usage/cli.py +1 -1
  354. package/runtime/python/okstra_token_usage/collect.py +66 -6
  355. package/runtime/schemas/convergence-groups-v2.0.schema.json +128 -0
  356. package/runtime/schemas/execution-manifest-v2.schema.json +340 -0
  357. package/runtime/schemas/final-report-v2.0.schema.json +25 -0
  358. package/runtime/skills/okstra-run/SKILL.md +9 -9
  359. package/runtime/skills/okstra-setup/references/project-config.md +11 -0
  360. package/runtime/templates/report-writer-prompt-preamble.md +2 -0
  361. package/runtime/templates/reports/final-report-v2.template.md +7 -1
  362. package/runtime/templates/reports/html/base.template.html +21 -0
  363. package/runtime/templates/reports/html/i18n/en.json +4 -0
  364. package/runtime/templates/reports/html/i18n/ko.json +4 -0
  365. package/runtime/templates/reports/settings.template.json +0 -24
  366. package/runtime/templates/worker-prompt-preamble.md +6 -2
  367. package/runtime/validators/lib/fixtures.sh +98 -33
  368. package/runtime/validators/validate-implementation-plan-stages.py +63 -3
  369. package/runtime/validators/validate-run.py +443 -508
  370. package/runtime/validators/validate_session_conformance.py +26 -8
  371. package/runtime/bin/okstra-subagent-reclaim.sh +0 -26
  372. package/runtime/schemas/final-report-v1.0.schema.json +0 -6366
  373. package/runtime/templates/reports/final-report.template.md +0 -1258
  374. package/src/cli-registry.mjs +0 -532
  375. package/src/commands/execute/codex-dispatch.mjs +0 -10
  376. package/src/commands/execute/plan-items.mjs +0 -9
  377. package/src/commands/execute/plan-validate.mjs +0 -68
  378. package/src/commands/execute/run.mjs +0 -208
  379. package/src/commands/execute/team.mjs +0 -63
  380. package/src/commands/execute/wizard.mjs +0 -167
  381. package/src/commands/inspect/stage-map.mjs +0 -98
  382. package/src/commands/inspect/task-list.mjs +0 -97
  383. package/src/commands/inspect/task-show.mjs +0 -100
  384. package/src/commands/lifecycle/check-project.mjs +0 -187
  385. package/src/commands/lifecycle/config.mjs +0 -385
  386. package/src/commands/lifecycle/doctor.mjs +0 -308
  387. package/src/commands/lifecycle/install.mjs +0 -1172
  388. package/src/commands/lifecycle/paths.mjs +0 -104
  389. package/src/commands/lifecycle/preflight.mjs +0 -125
  390. package/src/commands/lifecycle/setup.mjs +0 -333
  391. package/src/commands/lifecycle/uninstall.mjs +0 -279
  392. package/src/commands/memory/memory.mjs +0 -524
  393. package/src/commands/pr/pr.mjs +0 -261
  394. package/src/commands/report/finalize.mjs +0 -64
  395. package/src/lib/host-registry-client.mjs +0 -176
  396. package/src/lib/paths.mjs +0 -86
  397. package/src/lib/proc.mjs +0 -31
  398. package/src/lib/python-helper.mjs +0 -142
  399. package/src/lib/runtime-manifest.mjs +0 -70
  400. package/src/lib/skill-catalog.mjs +0 -53
  401. package/src/lib/version.mjs +0 -20
  402. /package/{src → dist}/commands/pr/default.md +0 -0
@@ -72,6 +72,7 @@ def _build_parser():
72
72
  grp.add_argument("--stderr-excerpt-file", default=None)
73
73
  obs.add_argument("--context-json", default=None,
74
74
  help="JSON object string for context")
75
+ _add_identity_flags(obs)
75
76
 
76
77
  dump = sub.add_parser("append-from-worker",
77
78
  help="Dump worker sidecar errors[] into errors.jsonl")
@@ -81,9 +82,33 @@ def _build_parser():
81
82
  dump.add_argument("--agent", required=True, choices=sorted(ALLOWED_AGENTS))
82
83
  dump.add_argument("--agent-role", required=True, choices=sorted(ALLOWED_AGENT_ROLES))
83
84
  dump.add_argument("--model", required=True)
85
+ _add_identity_flags(dump)
84
86
  return p
85
87
 
86
88
 
89
+ def _add_identity_flags(parser):
90
+ parser.add_argument("--participant-ref", default="")
91
+ parser.add_argument("--role-execution-ref", default="")
92
+ parser.add_argument("--invocation-ref", default="")
93
+ parser.add_argument("--attempt", type=int, default=None)
94
+ parser.add_argument("--execution-label", default="")
95
+
96
+
97
+ def _identity_from_args(args):
98
+ payload = {}
99
+ if args.participant_ref:
100
+ payload["participantRef"] = args.participant_ref
101
+ if args.role_execution_ref:
102
+ payload["roleExecutionRef"] = args.role_execution_ref
103
+ if args.invocation_ref:
104
+ payload["invocationRef"] = args.invocation_ref
105
+ if args.attempt is not None:
106
+ payload["attempt"] = args.attempt
107
+ if args.execution_label:
108
+ payload["executionLabel"] = args.execution_label
109
+ return payload or None
110
+
111
+
87
112
  def _read_stderr(args):
88
113
  if args.stderr_excerpt_file:
89
114
  return Path(args.stderr_excerpt_file).read_text()
@@ -114,6 +139,7 @@ def main(argv=None):
114
139
  message=args.message,
115
140
  stderr_excerpt=_read_stderr(args),
116
141
  context=_read_context(args),
142
+ identity=_identity_from_args(args),
117
143
  )
118
144
  return 0
119
145
  if args.cmd == "append-from-worker":
@@ -124,6 +150,7 @@ def main(argv=None):
124
150
  agent=args.agent,
125
151
  agent_role=args.agent_role,
126
152
  model=args.model,
153
+ identity=_identity_from_args(args),
127
154
  )
128
155
  print(n)
129
156
  return 0
@@ -8,12 +8,13 @@ write scope in the order the CLIs are told it, and the role's idle budget.
8
8
  """
9
9
  from __future__ import annotations
10
10
 
11
+ import json
11
12
  import os
12
13
  import shutil
13
14
  import sys
14
15
  from dataclasses import dataclass
15
16
  from pathlib import Path
16
- from typing import Any, Mapping
17
+ from typing import Any, Callable, Mapping
17
18
 
18
19
  _HERE = Path(__file__).resolve().parent
19
20
  # ``okstra_ctl`` sits beside this file in the repo (``scripts/``) but under
@@ -26,7 +27,13 @@ sys.path.insert(0, str(_HERE))
26
27
  if _HOME_LIB.is_dir() and str(_HOME_LIB) not in sys.path:
27
28
  sys.path.append(str(_HOME_LIB))
28
29
 
29
- from okstra_ctl.domain.provider import ProviderSpec, UnknownProviderError # noqa: E402
30
+ from okstra_ctl.domain.provider import ( # noqa: E402
31
+ ProviderSpec,
32
+ ServedModelAttestation,
33
+ ServedModelNormalizer,
34
+ UnknownProviderError,
35
+ )
36
+ from okstra_ctl.domain.role import normalize_role, role_for_duty # noqa: E402
30
37
  from okstra_ctl.domain.worker_exec import ( # noqa: E402
31
38
  ExecutionStrategy,
32
39
  WorkerExecRequest,
@@ -36,14 +43,32 @@ from okstra_ctl.registry.provider_registry import ( # noqa: E402
36
43
  )
37
44
  from okstra_ctl.worker_request import build_request, idle_timeout # noqa: E402
38
45
  from okstra_ctl.worker_runner import LIVE, QUIET, run_worker # noqa: E402
46
+ from okstra_ctl.dispatch_core import verify_served_model # noqa: E402
47
+ from okstra_ctl.dispatch_state import DispatchError # noqa: E402
48
+ from okstra_ctl.execution_manifest import read_execution_manifest # noqa: E402
49
+ from okstra_ctl.write_policy import ( # noqa: E402
50
+ WriteEnforcement,
51
+ WritePolicy,
52
+ write_enforcement_from_payload,
53
+ write_policy_from_payload,
54
+ )
55
+ from okstra_ctl.model_pool import ModelPool # noqa: E402
56
+ from okstra_ctl.agent_invocation import ( # noqa: E402
57
+ AgentInvocationError,
58
+ agent_model_assignment_from_payload,
59
+ invocation_metadata_identity,
60
+ )
39
61
 
40
62
  _USAGE = (
41
63
  "usage: okstra-provider-exec.py <provider> <project-root> "
42
64
  "<model-execution-value> <prompt-path> [worktree-path] [role] "
43
- "[idle-timeout-seconds] [--presentation live|quiet]"
65
+ "[idle-timeout-seconds] [--presentation live|quiet] [--session-id <uuid>] "
66
+ "[--invocation-metadata path]"
44
67
  )
45
68
 
46
69
  _PRESENTATION_FLAG = "--presentation"
70
+ _SESSION_ID_FLAG = "--session-id"
71
+ _INVOCATION_METADATA_FLAG = "--invocation-metadata"
47
72
  _PRESENTATIONS = (LIVE, QUIET)
48
73
 
49
74
 
@@ -61,11 +86,25 @@ class Invocation:
61
86
  log_path: Path
62
87
  status_path: Path
63
88
  status_extra: Mapping[str, Any]
89
+ served_model_normalizer: ServedModelNormalizer | None
90
+ served_model_verifier: Callable[[ServedModelAttestation], str] | None
91
+
92
+
93
+ @dataclass(frozen=True)
94
+ class _V2InvocationContext:
95
+ status_extra: Mapping[str, Any]
96
+ verify_attestation: Callable[[ServedModelAttestation], str]
97
+ write_policy: WritePolicy
98
+ write_enforcement: WriteEnforcement
64
99
 
65
100
 
66
101
  def parse_invocation(argv: list[str]) -> Invocation:
67
102
  """Resolve the wrapper's positional contract into one runnable dispatch."""
68
103
  positional, presentation = _take_presentation(argv)
104
+ # Empty unless the dispatcher issued one. Without it the CLI picks its own
105
+ # id and nothing downstream can map that session back to this worker.
106
+ positional, session_id = _take_flag(positional, _SESSION_ID_FLAG, "")
107
+ positional, metadata_raw = _take_flag(positional, _INVOCATION_METADATA_FLAG, "")
69
108
  if not 4 <= len(positional) <= 7:
70
109
  raise PreflightError(64, _USAGE)
71
110
  provider_id, project_root_raw, model, prompt_raw = positional[:4]
@@ -73,7 +112,6 @@ def parse_invocation(argv: list[str]) -> Invocation:
73
112
  role = positional[5] if len(positional) >= 6 and positional[5] else "worker"
74
113
  timeout_raw = positional[6] if len(positional) >= 7 and positional[6] else ""
75
114
 
76
- spec = _provider_spec(provider_id)
77
115
  project_root = _existing_dir(project_root_raw, 65, "project-root")
78
116
  if not model:
79
117
  raise PreflightError(66, "model-execution-value is empty")
@@ -82,6 +120,32 @@ def parse_invocation(argv: list[str]) -> Invocation:
82
120
  worktree = (
83
121
  _existing_dir(worktree_raw, 68, "worktree-path") if worktree_raw else None
84
122
  )
123
+ spec = _provider_spec(provider_id)
124
+ status_extra: dict[str, Any] = {"wrapper": spec.wrapper, "role": role}
125
+ served_model_normalizer: ServedModelNormalizer | None = None
126
+ served_model_verifier: Callable[[ServedModelAttestation], str] | None = None
127
+ write_policy: WritePolicy | None = None
128
+ write_enforcement: WriteEnforcement | None = None
129
+ if metadata_raw:
130
+ context = _v2_status_extra(
131
+ metadata_path=_existing_file(
132
+ metadata_raw, 64, "invocation-metadata"
133
+ ),
134
+ project_root=project_root,
135
+ prompt_path=prompt_path,
136
+ provider_id=provider_id,
137
+ model=model,
138
+ role=role,
139
+ )
140
+ status_extra.update(context.status_extra)
141
+ served_model_normalizer = spec.served_model_normalizer
142
+ served_model_verifier = context.verify_attestation
143
+ write_policy = context.write_policy
144
+ write_enforcement = context.write_enforcement
145
+ if not spec.supports_role(role):
146
+ raise PreflightError(
147
+ 64, f"provider {provider_id!r} does not support role {role!r}"
148
+ )
85
149
 
86
150
  request = build_request(
87
151
  prompt_text=prompt_path.read_text(encoding="utf-8"),
@@ -90,6 +154,9 @@ def parse_invocation(argv: list[str]) -> Invocation:
90
154
  worktree_path=worktree,
91
155
  role=role,
92
156
  idle_timeout_seconds=idle_timeout_seconds,
157
+ session_id=session_id,
158
+ write_policy=write_policy,
159
+ write_enforcement=write_enforcement,
93
160
  )
94
161
  strategy = spec.exec_strategy
95
162
  _check_command(strategy, request)
@@ -99,31 +166,45 @@ def parse_invocation(argv: list[str]) -> Invocation:
99
166
  presentation=presentation,
100
167
  log_path=_log_path(prompt_path),
101
168
  status_path=Path(f"{prompt_path}.status.json"),
102
- status_extra={"wrapper": spec.wrapper, "role": role},
169
+ status_extra=status_extra,
170
+ served_model_normalizer=served_model_normalizer,
171
+ served_model_verifier=served_model_verifier,
103
172
  )
104
173
 
105
174
 
106
- def _take_presentation(argv: list[str]) -> tuple[list[str], str]:
107
- """Split the one flag out of an otherwise positional argv.
175
+ def _take_flag(argv: list[str], flag: str, default: str) -> tuple[list[str], str]:
176
+ """Split one value-carrying flag out of an otherwise positional argv.
108
177
 
109
- Defaults to ``quiet``. ``live`` is only ever right where a screen was
110
- declared, and the only callers that can declare one are the pane backends —
111
- which pass the flag explicitly. Defaulting the other way assumed a screen
112
- that a subagent dispatch does not have, and sent every worker's progress
113
- into its caller's context window instead.
178
+ The wrapper's contract is positional, so every flag it grows has to be
179
+ lifted out before the positions are counted. Written once because the flags
180
+ differ only in the value they carry: a second copy of this loop is where
181
+ their refusals of a flag with no value would drift apart.
114
182
  """
115
183
  positional: list[str] = []
116
- presentation = QUIET
184
+ value = default
117
185
  index = 0
118
186
  while index < len(argv):
119
- if argv[index] != _PRESENTATION_FLAG:
187
+ if argv[index] != flag:
120
188
  positional.append(argv[index])
121
189
  index += 1
122
190
  continue
123
191
  if index + 1 >= len(argv):
124
- raise PreflightError(64, f"{_PRESENTATION_FLAG} needs a value: {_USAGE}")
125
- presentation = argv[index + 1]
192
+ raise PreflightError(64, f"{flag} needs a value: {_USAGE}")
193
+ value = argv[index + 1]
126
194
  index += 2
195
+ return positional, value
196
+
197
+
198
+ def _take_presentation(argv: list[str]) -> tuple[list[str], str]:
199
+ """``_take_flag`` plus the allowlist only this flag has.
200
+
201
+ Defaults to ``quiet``. ``live`` is only ever right where a screen was
202
+ declared, and the only callers that can declare one are the pane backends —
203
+ which pass the flag explicitly. Defaulting the other way assumed a screen
204
+ that a subagent dispatch does not have, and sent every worker's progress
205
+ into its caller's context window instead.
206
+ """
207
+ positional, presentation = _take_flag(argv, _PRESENTATION_FLAG, QUIET)
127
208
  if presentation not in _PRESENTATIONS:
128
209
  allowed = " | ".join(_PRESENTATIONS)
129
210
  raise PreflightError(
@@ -132,6 +213,152 @@ def _take_presentation(argv: list[str]) -> tuple[list[str], str]:
132
213
  return positional, presentation
133
214
 
134
215
 
216
+ def _v2_status_extra(
217
+ *,
218
+ metadata_path: Path,
219
+ project_root: Path,
220
+ prompt_path: Path,
221
+ provider_id: str,
222
+ model: str,
223
+ role: str,
224
+ ) -> _V2InvocationContext:
225
+ try:
226
+ metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
227
+ except (OSError, UnicodeDecodeError, json.JSONDecodeError) as exc:
228
+ raise PreflightError(64, "invocation metadata is invalid") from exc
229
+ if not isinstance(metadata, dict):
230
+ raise PreflightError(64, "invocation metadata must be an object")
231
+ try:
232
+ identity = invocation_metadata_identity(metadata)
233
+ assignment = agent_model_assignment_from_payload(
234
+ metadata.get("modelAssignment")
235
+ )
236
+ except AgentInvocationError as exc:
237
+ raise PreflightError(64, str(exc)) from exc
238
+ if identity is None:
239
+ raise PreflightError(64, "new worker dispatch requires v2 invocation metadata")
240
+ if (
241
+ assignment.provider != provider_id
242
+ or assignment.model_execution_value != model
243
+ ):
244
+ raise PreflightError(64, "invocation metadata model assignment does not match wrapper")
245
+ try:
246
+ expected_role = role_for_duty(identity.duty_id)
247
+ actual_role = normalize_role(role)
248
+ except ValueError as exc:
249
+ raise PreflightError(64, f"invocation metadata role is invalid: {exc}") from exc
250
+ if expected_role != actual_role:
251
+ raise PreflightError(64, "invocation metadata duty does not match role")
252
+ prompt = metadata.get("prompt")
253
+ recorded_path = prompt.get("path") if isinstance(prompt, Mapping) else None
254
+ if not isinstance(recorded_path, str):
255
+ raise PreflightError(64, "invocation metadata prompt path is invalid")
256
+ recorded = Path(recorded_path)
257
+ if not recorded.is_absolute():
258
+ recorded = project_root / recorded
259
+ if recorded.resolve(strict=False) != prompt_path.resolve(strict=True):
260
+ raise PreflightError(64, "invocation metadata prompt does not match wrapper")
261
+ role_execution, invocation, pool = _execution_authority(
262
+ metadata=metadata,
263
+ project_root=project_root,
264
+ role_execution_ref=identity.role_execution_ref,
265
+ invocation_ref=identity.invocation_ref,
266
+ )
267
+ binding = role_execution.binding
268
+ if (
269
+ role_execution.participant_ref != identity.participant_ref
270
+ or role_execution.role != expected_role
271
+ or role_execution.provider != assignment.provider
272
+ or binding is None
273
+ or binding.runner != assignment.runner
274
+ or binding.resolved_execution_value != assignment.model_execution_value
275
+ ):
276
+ raise PreflightError(
277
+ 64, "invocation metadata role execution binding does not match run manifest"
278
+ )
279
+ if role_execution.execution_label != identity.execution_label:
280
+ raise PreflightError(
281
+ 64, "invocation metadata execution label does not match run manifest"
282
+ )
283
+
284
+ def verify_attestation(attestation: ServedModelAttestation) -> str:
285
+ try:
286
+ verify_served_model(role_execution, attestation, pool=pool)
287
+ except DispatchError as exc:
288
+ return str(exc)
289
+ return ""
290
+
291
+ try:
292
+ write_policy = write_policy_from_payload(invocation.write_policy)
293
+ write_enforcement = write_enforcement_from_payload(
294
+ invocation.write_enforcement
295
+ )
296
+ except ValueError as exc:
297
+ raise PreflightError(64, f"invocation write contract is invalid: {exc}") from exc
298
+
299
+ return _V2InvocationContext({
300
+ "schemaVersion": "2.0",
301
+ "executionIdentityVersion": 2,
302
+ "participantRef": identity.participant_ref,
303
+ "roleExecutionRef": identity.role_execution_ref,
304
+ "executionLabel": identity.execution_label,
305
+ "dutyId": identity.duty_id,
306
+ "invocationRef": identity.invocation_ref,
307
+ "attempt": identity.attempt,
308
+ "servedModelAttestation": {
309
+ "observedModel": None,
310
+ "normalizedModelRef": None,
311
+ "level": "unknown",
312
+ "source": "unavailable",
313
+ },
314
+ "writePolicyDigest": invocation.write_policy_digest,
315
+ "writeEnforcement": write_enforcement.to_payload(),
316
+ }, verify_attestation, write_policy, write_enforcement)
317
+
318
+
319
+ def _execution_authority(
320
+ *,
321
+ metadata: Mapping[str, Any],
322
+ project_root: Path,
323
+ role_execution_ref: str,
324
+ invocation_ref: str,
325
+ ):
326
+ source = metadata.get("contractSource")
327
+ manifest_raw = source.get("runManifestPath") if isinstance(source, Mapping) else None
328
+ if not isinstance(manifest_raw, str) or not manifest_raw:
329
+ raise PreflightError(64, "invocation metadata run manifest is invalid")
330
+ manifest_path = Path(manifest_raw)
331
+ if not manifest_path.is_absolute():
332
+ manifest_path = project_root / manifest_path
333
+ try:
334
+ manifest_path = manifest_path.resolve(strict=True)
335
+ manifest_path.relative_to(project_root.resolve(strict=True))
336
+ manifest = read_execution_manifest(manifest_path)
337
+ except (OSError, ValueError) as exc:
338
+ raise PreflightError(64, "invocation metadata run manifest is invalid") from exc
339
+ role_execution = next((
340
+ row for row in manifest.role_executions
341
+ if row.role_execution_ref == role_execution_ref
342
+ ), None)
343
+ if role_execution is None:
344
+ raise PreflightError(
345
+ 64, "invocation metadata role execution does not match run manifest"
346
+ )
347
+ invocation = next((
348
+ row for row in manifest.invocations
349
+ if row.invocation_ref == invocation_ref
350
+ ), None)
351
+ if invocation is None or invocation.role_execution_ref != role_execution_ref:
352
+ raise PreflightError(
353
+ 64, "invocation metadata invocation does not match run manifest"
354
+ )
355
+ return (
356
+ role_execution,
357
+ invocation,
358
+ ModelPool.from_registry(default_provider_registry()),
359
+ )
360
+
361
+
135
362
  def _provider_spec(provider_id: str) -> ProviderSpec:
136
363
  try:
137
364
  spec = default_provider_registry().resolve(provider_id)
@@ -197,6 +424,8 @@ def main(argv: list[str]) -> int:
197
424
  log_path=invocation.log_path,
198
425
  status_path=invocation.status_path,
199
426
  status_extra=invocation.status_extra,
427
+ served_model_normalizer=invocation.served_model_normalizer,
428
+ served_model_verifier=invocation.served_model_verifier,
200
429
  )
201
430
  except PreflightError as exc:
202
431
  print(f"okstra-provider-exec: {exc}", file=sys.stderr)