okstra 0.174.0 → 0.176.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) 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/{src → dist}/commands/execute/team.mjs +29 -36
  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/{src → dist}/commands/execute/worktree-status.mjs +52 -46
  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/{src → dist}/commands/report/finalize.mjs +25 -32
  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 +6 -2
  232. package/docs/architecture.md +29 -20
  233. package/docs/cli.md +40 -16
  234. package/docs/contributor-change-matrix.md +2 -2
  235. package/docs/for-ai/skills/okstra-inspect.md +2 -3
  236. package/docs/for-ai/skills/okstra-rollup.md +1 -0
  237. package/docs/project-structure-overview.md +72 -62
  238. package/docs/task-process/README.md +12 -8
  239. package/docs/task-process/common-flow.md +13 -16
  240. package/docs/task-process/error-analysis.md +9 -10
  241. package/docs/task-process/final-verification.md +7 -7
  242. package/docs/task-process/implementation-planning.md +9 -9
  243. package/docs/task-process/implementation.md +6 -6
  244. package/docs/task-process/release-handoff.md +8 -7
  245. package/docs/task-process/requirements-discovery.md +8 -8
  246. package/package.json +11 -5
  247. package/runtime/BUILD.json +2 -2
  248. package/runtime/agents/workers/claude-worker.md +2 -1
  249. package/runtime/agents/workers/report-writer-worker.md +3 -1
  250. package/runtime/agents/workers/translator-worker.md +3 -1
  251. package/runtime/bin/lib/okstra/cli.sh +12 -0
  252. package/runtime/bin/lib/okstra/globals.sh +3 -0
  253. package/runtime/bin/lib/okstra/interactive.sh +12 -6
  254. package/runtime/bin/lib/okstra/usage.sh +7 -6
  255. package/runtime/bin/okstra-error-log.py +27 -0
  256. package/runtime/bin/okstra-provider-exec.py +217 -5
  257. package/runtime/bin/okstra-spawn-followups.py +4 -2
  258. package/runtime/bin/okstra.sh +10 -0
  259. package/runtime/prompts/launch.template.md +2 -2
  260. package/runtime/prompts/lead/context-loader.md +1 -2
  261. package/runtime/prompts/lead/convergence.md +27 -18
  262. package/runtime/prompts/lead/okstra-lead-contract.md +6 -5
  263. package/runtime/prompts/lead/plan-body-verification.md +10 -3
  264. package/runtime/prompts/lead/report-writer.md +15 -1
  265. package/runtime/prompts/lead/team-contract.md +17 -13
  266. package/runtime/prompts/profiles/_implementation-deliverable.md +1 -1
  267. package/runtime/prompts/profiles/_implementation-executor.md +0 -3
  268. package/runtime/prompts/profiles/_implementation-verifier.md +3 -7
  269. package/runtime/prompts/profiles/change-impact-analysis.md +20 -0
  270. package/runtime/prompts/profiles/error-analysis.md +27 -1
  271. package/runtime/prompts/profiles/feature-analysis.md +20 -0
  272. package/runtime/prompts/profiles/final-verification.md +20 -1
  273. package/runtime/prompts/profiles/implementation-option-selection.md +20 -0
  274. package/runtime/prompts/profiles/implementation-planning.md +26 -0
  275. package/runtime/prompts/profiles/implementation.md +19 -0
  276. package/runtime/prompts/profiles/improvement-discovery.md +21 -1
  277. package/runtime/prompts/profiles/project-analysis.md +20 -0
  278. package/runtime/prompts/profiles/release-handoff.md +4 -0
  279. package/runtime/prompts/profiles/requirements-discovery.md +27 -1
  280. package/runtime/prompts/wizard/prompts.ko.json +35 -0
  281. package/runtime/python/okstra_ctl/adapters/dispatch/cli_wrapper.py +8 -0
  282. package/runtime/python/okstra_ctl/adapters/dispatch/cmux.py +8 -0
  283. package/runtime/python/okstra_ctl/adapters/dispatch/native_team.py +13 -0
  284. package/runtime/python/okstra_ctl/adapters/hosts/antigravity/adapter.py +2 -2
  285. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +25 -5
  286. package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +2 -2
  287. package/runtime/python/okstra_ctl/adapters/hosts/external/adapter.py +4 -1
  288. package/runtime/python/okstra_ctl/adapters/hosts/grok/adapter.py +2 -2
  289. package/runtime/python/okstra_ctl/adapters/hosts/kimi/adapter.py +2 -2
  290. package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +79 -11
  291. package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +95 -25
  292. package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +59 -14
  293. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +55 -9
  294. package/runtime/python/okstra_ctl/adapters/providers/kimi/adapter.py +51 -12
  295. package/runtime/python/okstra_ctl/adapters/runtime/__init__.py +1 -0
  296. package/runtime/python/okstra_ctl/adapters/runtime/assembly.py +27 -0
  297. package/runtime/python/okstra_ctl/adapters/runtime/cli_wrapper.py +49 -0
  298. package/runtime/python/okstra_ctl/adapters/runtime/cmux.py +74 -0
  299. package/runtime/python/okstra_ctl/agent_activity.py +5 -1
  300. package/runtime/python/okstra_ctl/agent_invocation.py +608 -14
  301. package/runtime/python/okstra_ctl/agent_prompt_cli.py +249 -50
  302. package/runtime/python/okstra_ctl/application/open_worker.py +29 -0
  303. package/runtime/python/okstra_ctl/application/resolve_assignment.py +53 -12
  304. package/runtime/python/okstra_ctl/assignment_environment.py +102 -0
  305. package/runtime/python/okstra_ctl/assignment_resolver.py +790 -0
  306. package/runtime/python/okstra_ctl/attempt_evidence.py +342 -0
  307. package/runtime/python/okstra_ctl/convergence.py +409 -3
  308. package/runtime/python/okstra_ctl/convergence_engine.py +248 -15
  309. package/runtime/python/okstra_ctl/convergence_store.py +170 -1
  310. package/runtime/python/okstra_ctl/dispatch_core.py +1204 -155
  311. package/runtime/python/okstra_ctl/dispatch_state.py +696 -11
  312. package/runtime/python/okstra_ctl/doctor.py +14 -0
  313. package/runtime/python/okstra_ctl/domain/host.py +34 -1
  314. package/runtime/python/okstra_ctl/domain/provider.py +212 -6
  315. package/runtime/python/okstra_ctl/domain/role.py +125 -0
  316. package/runtime/python/okstra_ctl/domain/wizard/interaction.py +18 -0
  317. package/runtime/python/okstra_ctl/domain/worker_exec.py +34 -1
  318. package/runtime/python/okstra_ctl/domain/worker_role.py +13 -3
  319. package/runtime/python/okstra_ctl/domain/worker_runtime.py +44 -0
  320. package/runtime/python/okstra_ctl/domain/worker_stream.py +24 -0
  321. package/runtime/python/okstra_ctl/error_log_write.py +9 -0
  322. package/runtime/python/okstra_ctl/error_report.py +21 -1
  323. package/runtime/python/okstra_ctl/execution_identity.py +529 -0
  324. package/runtime/python/okstra_ctl/execution_manifest.py +1281 -0
  325. package/runtime/python/okstra_ctl/execution_mutation_audit.py +619 -0
  326. package/runtime/python/okstra_ctl/implementation_outcome.py +21 -5
  327. package/runtime/python/okstra_ctl/index.py +6 -2
  328. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +43 -3
  329. package/runtime/python/okstra_ctl/legacy_model_selection.py +578 -0
  330. package/runtime/python/okstra_ctl/manager_sync.py +4 -1
  331. package/runtime/python/okstra_ctl/model_cli.py +278 -0
  332. package/runtime/python/okstra_ctl/model_defaults.py +46 -0
  333. package/runtime/python/okstra_ctl/model_discovery.py +26 -7
  334. package/runtime/python/okstra_ctl/model_pool.py +501 -0
  335. package/runtime/python/okstra_ctl/models.py +47 -27
  336. package/runtime/python/okstra_ctl/mutation_recovery.py +293 -0
  337. package/runtime/python/okstra_ctl/next_phase.py +236 -0
  338. package/runtime/python/okstra_ctl/pane_title.py +151 -0
  339. package/runtime/python/okstra_ctl/ports/host_model.py +48 -17
  340. package/runtime/python/okstra_ctl/ports/worker_dispatch.py +4 -0
  341. package/runtime/python/okstra_ctl/ports/worker_runtime.py +26 -0
  342. package/runtime/python/okstra_ctl/recap.py +4 -1
  343. package/runtime/python/okstra_ctl/registry/provider_registry.py +8 -4
  344. package/runtime/python/okstra_ctl/render.py +124 -57
  345. package/runtime/python/okstra_ctl/render_final_report.py +19 -0
  346. package/runtime/python/okstra_ctl/report_contract.py +39 -0
  347. package/runtime/python/okstra_ctl/report_finalize.py +16 -0
  348. package/runtime/python/okstra_ctl/report_html/render.py +1 -0
  349. package/runtime/python/okstra_ctl/role_requirements.py +210 -0
  350. package/runtime/python/okstra_ctl/rollup.py +4 -1
  351. package/runtime/python/okstra_ctl/run.py +1210 -258
  352. package/runtime/python/okstra_ctl/run_index_row.py +7 -1
  353. package/runtime/python/okstra_ctl/stage_fix_carry.py +17 -1
  354. package/runtime/python/okstra_ctl/team.py +14 -18
  355. package/runtime/python/okstra_ctl/time_report.py +38 -4
  356. package/runtime/python/okstra_ctl/usage_identity.py +86 -0
  357. package/runtime/python/okstra_ctl/usage_report.py +15 -3
  358. package/runtime/python/okstra_ctl/wizard.py +1449 -66
  359. package/runtime/python/okstra_ctl/worker_audit_ledger.py +68 -65
  360. package/runtime/python/okstra_ctl/worker_prompt_body.py +18 -2
  361. package/runtime/python/okstra_ctl/worker_prompt_contract.py +40 -9
  362. package/runtime/python/okstra_ctl/worker_prompt_headers.py +16 -1
  363. package/runtime/python/okstra_ctl/worker_request.py +7 -1
  364. package/runtime/python/okstra_ctl/worker_runner.py +130 -5
  365. package/runtime/python/okstra_ctl/workers.py +7 -5
  366. package/runtime/python/okstra_ctl/workflow.py +18 -32
  367. package/runtime/python/okstra_ctl/worktree.py +3 -3
  368. package/runtime/python/okstra_ctl/worktree_registry.py +5 -4
  369. package/runtime/python/okstra_ctl/write_policy.py +571 -0
  370. package/runtime/python/okstra_project/state.py +54 -6
  371. package/runtime/schemas/convergence-groups-v2.0.schema.json +128 -0
  372. package/runtime/schemas/execution-manifest-v2.schema.json +340 -0
  373. package/runtime/schemas/final-report-v2.0.schema.json +68 -5
  374. package/runtime/skills/okstra-inspect/facets/recap.md +2 -0
  375. package/runtime/skills/okstra-inspect/facets/report.md +1 -1
  376. package/runtime/skills/okstra-inspect/facets/status.md +15 -13
  377. package/runtime/skills/okstra-rollup/SKILL.md +1 -0
  378. package/runtime/skills/okstra-run/SKILL.md +14 -14
  379. package/runtime/templates/implementation-worker-preamble.md +3 -18
  380. package/runtime/templates/project-docs/task-index.template.md +0 -1
  381. package/runtime/templates/report-writer-prompt-preamble.md +2 -0
  382. package/runtime/templates/reports/final-report-v2.template.md +7 -1
  383. package/runtime/templates/reports/html/base.template.html +21 -0
  384. package/runtime/templates/reports/html/i18n/en.json +4 -0
  385. package/runtime/templates/reports/html/i18n/ko.json +4 -0
  386. package/runtime/templates/reports/html/macros/forms.html +5 -4
  387. package/runtime/templates/reports/html/tasks/final-verification.template.html +1 -1
  388. package/runtime/templates/reports/html/tasks/implementation.template.html +1 -1
  389. package/runtime/templates/worker-prompt-preamble.md +6 -35
  390. package/runtime/validators/lib/fixtures.sh +49 -16
  391. package/runtime/validators/validate-run.py +486 -134
  392. package/runtime/validators/validate_session_conformance.py +25 -7
  393. package/src/cli-registry.mjs +0 -539
  394. package/src/commands/execute/codex-dispatch.mjs +0 -10
  395. package/src/commands/execute/plan-items.mjs +0 -9
  396. package/src/commands/execute/plan-validate.mjs +0 -68
  397. package/src/commands/execute/run.mjs +0 -208
  398. package/src/commands/execute/wizard.mjs +0 -167
  399. package/src/commands/inspect/stage-map.mjs +0 -98
  400. package/src/commands/inspect/task-list.mjs +0 -97
  401. package/src/commands/inspect/task-show.mjs +0 -100
  402. package/src/commands/lifecycle/check-project.mjs +0 -187
  403. package/src/commands/lifecycle/config.mjs +0 -385
  404. package/src/commands/lifecycle/doctor.mjs +0 -308
  405. package/src/commands/lifecycle/install.mjs +0 -1170
  406. package/src/commands/lifecycle/paths.mjs +0 -104
  407. package/src/commands/lifecycle/preflight.mjs +0 -125
  408. package/src/commands/lifecycle/setup.mjs +0 -333
  409. package/src/commands/lifecycle/uninstall.mjs +0 -279
  410. package/src/commands/memory/memory.mjs +0 -524
  411. package/src/commands/pr/pr.mjs +0 -261
  412. package/src/lib/host-registry-client.mjs +0 -176
  413. package/src/lib/paths.mjs +0 -86
  414. package/src/lib/proc.mjs +0 -31
  415. package/src/lib/python-helper.mjs +0 -142
  416. package/src/lib/runtime-manifest.mjs +0 -70
  417. package/src/lib/skill-catalog.mjs +0 -53
  418. package/src/lib/version.mjs +0 -20
  419. /package/{src → dist}/commands/pr/default.md +0 -0
@@ -13,19 +13,23 @@ Okstra tasks use one lead plus the exact worker assignments selected in the prep
13
13
 
14
14
  ### Role Definitions
15
15
 
16
- **All analysis workers (Claude / Codex / Antigravity) share an identical core responsibility.** Specialization is additive — it lives in optional Section 6 of the worker output, NOT in differentiated core questions. This is intentional: cross-verification only converges if all three workers are answering the same questions against the same brief. Disjoint per-worker scopes produce union-of-perspectives, not triangulation.
16
+ The start screen assigns a **model ref** (`provider/model`) to each **canonical role** slot: `leader`, `analyser`, `critic`, `designer`, `planner`, `implementer`, `verifier`, `report-writer`, `translator`. A provider name is the front of a model ref, not a role. Every `analyser` in the run shares an identical core responsibility. Specialization is additive — it lives in optional Section 6 of the worker output, NOT in differentiated core questions. Cross-verification only converges if every rostered analyser answers the same questions against the same brief.
17
17
 
18
- | Role | Core responsibility | Specialization lens (Section 6 only) | Assignment key | Notes |
19
- |------|------|------|---------------|------|
20
- | Lead | orchestration + convergence supervision + final-report review/approval | runtime-specific | -- | Does not author the final report when `Report writer worker` is rostered |
21
- | Claude worker | Answer every brief question across feasibility, requirement interpretation, hidden assumptions, and alternatives — with file:line evidence | broad reasoning depth, hidden assumptions, execution-risk surfacing | claude-worker | `agents/workers/claude-worker.md` |
22
- | Codex worker | Same core responsibility as Claude worker — identical questions, identical sections 1–5 | implementation realism, code-path implications, edge cases, technical trade-offs | codex-worker | final prompt composed from the invocation duty and task instructions; CLI execution uses `worker-dispatch` |
23
- | Antigravity worker | Same core responsibility as Claude worker — identical questions, identical sections 1–5 | requirement interpretation, consistency, safety, alternative viewpoints | antigravity-worker | final prompt composed from the invocation duty and task instructions; CLI execution uses `worker-dispatch` |
24
- | Report writer worker | **Authors** the final-report file in Phase 6. NOT an analysis worker. | — | report-writer-worker | `agents/workers/report-writer-worker.md`. Excluded from Phase 4/5 and convergence |
18
+ | Canonical role | Core responsibility | Notes |
19
+ |------|------|------|
20
+ | `leader` | orchestration + convergence supervision + final-report review/approval | Does not author the final report when `report-writer` is rostered |
21
+ | `analyser` | Answer every brief question across feasibility, requirement interpretation, hidden assumptions, and alternatives — with file:line evidence | Same sections 1–5 for every model ref |
22
+ | `critic` | Audit coverage gaps or challenge acceptance, per the attached duty | Not an analysis voter |
23
+ | `designer` | Compare or validate implementation directions | Used by `implementation-option-selection` |
24
+ | `planner` | Produce an executable plan without writing the implementation | Used by `implementation-planning` |
25
+ | `implementer` | Sole change author for one approved stage | Used by `implementation` |
26
+ | `verifier` | Independent review of the assigned duty's subject | Duty varies by task type |
27
+ | `report-writer` | **Authors** the final-report file in Phase 6 | Excluded from Phase 4/5 and convergence |
28
+ | `translator` | Translates the designated sidecar only | Phase 7 |
25
29
 
26
- **Model assignment has no default.** The model for every role comes from `resultContract.requiredWorkerRoles[*].modelExecutionValue` in `task-manifest.json` (and lead model metadata). There is no per-role hard-coded fallback — see "Model Assignment Rules" below.
30
+ **Dispatch does not invent a missing model assignment.** Launch-time empty slots are filled by the model default chain before the run starts. At dispatch the model for every role comes from `resultContract.requiredWorkerRoles[*].modelExecutionValue` in `task-manifest.json` (and lead model metadata). There is no per-role hard-coded fallback — see "Model Assignment Rules" below.
27
31
 
28
- **Dispatch-prompt invariant.** Lead's dispatch prompt body for Claude / Codex / Antigravity workers MUST be byte-identical except for the role label and any wrapper-specific path headers (e.g. `**Worktree:**`, `**Errors sidecar path:**`). Lead MUST NOT bias the brief by inserting per-worker emphasis sentences ("you focus on X") into the body. Bias-by-prompt reproduces the historical failure mode where Claude commented only on assumptions, Codex only on code paths, and Antigravity only on requirements — leaving convergence with nothing to converge on.
32
+ **Dispatch-prompt invariant.** Lead's dispatch prompt body for every rostered analysis worker MUST be byte-identical except for the role label and any wrapper-specific path headers (e.g. `**Worktree:**`, `**Errors sidecar path:**`). The role label is the ONLY identity form the normalizer erases, and it erases exactly the label `worker_prompt_body.analysis_worker_label` renders for the run's own worker ids — so a provider outside that function's display map (`grok`, `kimi`, an installed adapter) is covered as it comes. Naming the worker any other way (a model name, a host name, a provider's product name) survives normalization and fails the equality group before publication. **Enforced:** `okstra_ctl.worker_prompt_contract.normalise_analysis_prompt`, pinned by `tests/contract/test_analysis_prompt_identity_normalization.py`. Lead MUST NOT bias the brief by inserting per-worker emphasis sentences ("you focus on X") into the body. Bias-by-prompt reproduces the historical failure mode where Claude commented only on assumptions, Codex only on code paths, and Antigravity only on requirements — leaving convergence with nothing to converge on.
29
33
 
30
34
  Disjoint initial scopes are invalid triangulation. Every selected analysis worker owns the same common verification requirements; provider diversity supplies independent observations, not separate coverage slices. Do not shard the common scope by worker, provider, or model. Worker-specific depth belongs only in the non-voting Specialization Lens after the shared analysis is complete.
31
35
 
@@ -65,7 +69,7 @@ Only workers selected from `recommendedWorkers` in `task-manifest.json` and `res
65
69
 
66
70
  `okstra_ctl.initial_prompt_materialization` is the canonical owner of roster-derived initial prompt rendering, validation, and immutable publication. Code-backed `dispatch_worker` mappings leave missing roster prompts to `materialize_initial_prompts()` and pass the selected adapter's declared `initialPromptDeliveryMode`; they do not compose or overwrite those prompts themselves. Native in-process dispatch uses the same headers and the adapter's declared `lazy-path-reference` mode, persists the prompt before dispatch, and remains outside reverify and critic handling.
67
71
 
68
- Every worker prompt MUST start with the anchor headers rendered by `okstra_ctl.worker_prompt_headers.worker_prompt_headers()` (the generating SSOT — never hand-author or reorder them). Every persisted initial prompt also carries exactly one non-empty `**Prompt Delivery Mode:** <mode>` header whose value is `eager-include` or `lazy-path-reference`. Redispatch reuses that persisted initial prompt byte-for-byte; it never regenerates or overwrites it. The generated absolute `**Audit sidecar path:**` is derived by `audit_sidecar_rel()` from the canonical worker result path; workers write to that header and never synthesize a `runs/<task-type>/...` destination. Their meaning and extraction rules for workers are documented in the worker preamble §"Anchor headers". Phase-specific extra headers (implementation worktree, final-verification target snapshot, improvement-discovery grilling log) are listed there too.
72
+ Every worker prompt MUST start with the anchor headers rendered by `okstra_ctl.worker_prompt_headers.worker_prompt_headers()` (the generating SSOT — never hand-author or reorder them). Every persisted initial prompt also carries exactly one non-empty `**Prompt Delivery Mode:** <mode>` header whose value is `eager-include` or `lazy-path-reference`. Redispatch reuses that persisted initial prompt byte-for-byte; it never regenerates or overwrites it. The generated absolute `**Audit sidecar path:**` is derived by `audit_sidecar_rel()` from the canonical worker result path; workers write to that header and never synthesize a `runs/<task-type>/...` destination. Their meaning and extraction rules for workers are owned by `okstra_ctl.worker_prompt_headers.worker_prompt_headers()`. Phase-specific extra headers (implementation worktree, final-verification target snapshot, improvement-discovery grilling log) are emitted there too.
69
73
 
70
74
  The `**Coding preflight pack:**` anchor is emitted only for the `implementation-executor` and `implementation-verifier` audiences. An implementation report-writer never receives it. A pane display role named `verifier` during `final-verification` is still an initial analysis worker; it neither receives implementation conventions nor becomes a Phase 5.5 reverify dispatch. Reverify is identified by the `-reverify-r<N>-` prompt/result path contract in [convergence](./convergence.md).
71
75
 
@@ -99,7 +103,7 @@ Audience-scoped file enumeration (performance optimization — mandatory):
99
103
 
100
104
  | Recipient | Files the lead lists under `## Inputs` |
101
105
  |---|---|
102
- | Claude / Codex / Antigravity analysis workers | `analysis-packet.md` as primary input; for `final-verification`, no source/fallback list is copied into the prompt |
106
+ | Any rostered analysis worker | `analysis-packet.md` as primary input; for `final-verification`, no source/fallback list is copied into the prompt |
103
107
  | Report writer worker (Phase 6) | task-brief, analysis-profile, analysis-material, reference-expectations, clarification-response (if carry-in), **plus** the instruction-set-local `final-report-template.md` (phase-stripped) and `final-report-schema.json` (per-task-type excerpt) — NOT the full `templates/reports/...` / `schemas/...` sources |
104
108
  | Reverify dispatches | none — the lead provides only the items to reverify |
105
109
 
@@ -164,7 +168,7 @@ After each worker attempt returns (regardless of role), Lead MUST verify the can
164
168
  - The result file exists but its audit sidecar does not, at `runs/<task-type>/worker-results/<worker>-audit-<task-type>-<seq>.md`. Workers write both in the same step, so a result without a sidecar means the Reading Confirmation block — the only evidence the worker read its inputs — was never produced. `validate-run.py` fails the run on this at Phase 7 either way (`validate_worker_results_audit`); checking it here spends the existing one-retry budget while the role can still be re-dispatched, instead of surfacing hours later when the worker session is gone.
165
169
  - `okstra worker-audit-check --run-dir <runs/<task-type>/> --task-type <t> --seq <n> --worker <id>` exits 2 on a backticked `path:line` citation in the worker's result that has no matching Evidence read row in its audit sidecar. Run it the moment you collect each result. Phase 7 enforces the same rules from the same implementation (`okstra_ctl.worker_audit_ledger`), but by then the worker session is gone and the only remaining moves are editing the result yourself — which destroys the audit chain the ledger exists to provide — or ending the run `contract-violated`. While the session is alive, `SendMessage` to the worker so it corrects its own citation; that costs about a minute against a re-dispatch or a failed run.
166
170
 
167
- The same audit check parses command evidence from canonical rows such as `- Evidence command: {"command":"npm run check","cwd":"<project-root>","exitCode":0,"outputSummary":"all checks passed"}`. Workers record only commands that produced or verified a conclusion, not exploratory `rg`, `ls`, or file-opening commands. Environment variable values, tokens, credentials, and authorization headers are excluded. A malformed row or potential sensitive material is a contract failure returned by `okstra_ctl.worker_audit_ledger`; send the failure to the worker while its session is still available.
171
+ The same audit check parses command evidence from canonical rows such as `- Evidence command: {"command":"npm run check","cwd":"<project-root>","exitCode":0,"outputSummary":"all checks passed"}`. Workers record only commands that produced or verified a conclusion, not exploratory `rg`, `ls`, or file-opening commands. A malformed row is a contract failure returned by `okstra_ctl.worker_audit_ledger`; send the failure to the worker while its session is still available. Nothing scans these rows for secrets, so a row is never refused for how a setting is named — `AUTH_MODE=off` and `TOKEN_TTL=60` record verbatim. Do not tell a worker to drop or paraphrase a row on those grounds: a worker that cannot record the command it ran has no way to satisfy the evidence ledger that demands it.
168
172
 
169
173
  **One-retry policy:**
170
174
 
@@ -37,7 +37,7 @@ are collected and convergence finished. Phase 1-5 do not need it.
37
37
  evidence and add one `recommendedNextSteps` item with environment
38
38
  prerequisites and the expected `QA-RESULT`. This is user-owned verification;
39
39
  do not route back or fail implementation solely for this advisory.
40
- - **Routing recommendation for `final-verification`**: brief note on whether the changes are ready for final-verification phase or need a new error-analysis / planning loop first.
40
+ - **Routing recommendation**: `implementation.routingRecommendation` is an **object** with exactly two fields — `target`, one of `final-verification`, `error-analysis`, `implementation-planning`, `implementation`, and `rationale`, one or two sentences on why that target and nothing else. It is not a prose note: Phase 7 projects `workflow.nextRecommendedPhase` from `target` alone, so a phase named only in the prose does not route the task. Pick `final-verification` when this stage's plan items landed and validation passed; `error-analysis` when a failure's cause is not understood; `implementation-planning` when the approved plan itself no longer fits the evidence; `implementation` when work remains inside this stage and the next run is a fix run. **Enforced:** `schemas/final-report-v2.0.schema.json` rejects a `target` outside the enum, a missing `rationale`, and a string in place of the object.
41
41
  - **Follow-up tasks (Section 4 of the final report)**: every item discovered during this run that was *not* delivered MUST appear in the final report's `## 4. Follow-up Tasks` table with a concrete `Origin`, `New Task ID`, `Suggested task-type`, `Scope`, and `Reason / Why deferred`. Sources include: out-of-scope discoveries that the executor consciously chose not to fold into this run, verifier concerns the executor declined to fix in-place, scope-boundary items from the approved plan that turned out to need their own ticket, and any unresolved `## 1. Clarification Items` row carried over from the approved plan (`Status` ∈ `{open, answered}` at approval time). An empty section is acceptable but only when expressed as the single line `- No follow-up tasks.` — silence is treated as a contract violation. Rows with `Auto-spawn? = yes` will be materialised by `scripts/okstra-spawn-followups.py` in Phase 7; rows with `Auto-spawn? = no` MUST also appear in `Section 3. Recommended Next Steps` so the user knows to act manually.
42
42
 
43
43
  ## Self-review pass before finalising the report (the Okstra lead runs this; do not delegate it)
@@ -7,11 +7,8 @@ until Phase 5 ends, then drop from active context for Phase 6/7.
7
7
 
8
8
  # Implementation profile — Executor sidecar
9
9
 
10
- > **When to read**: lead reads this file ONCE at the start of Phase 5 (after Stage Map parse, before issuing the Executor's first `Edit` / `Write`). The body governs ONLY the Executor role's behaviour. Verifier / report-writer behaviour lives in sibling sidecars.
11
-
12
10
  ## Executor role binding (carried over from the thin core)
13
11
 
14
- - **Executor dispatch labelling.** The core functional role label is `<provider>-executor` (e.g. `codex-executor`). Provider, role, and model identity are owned by `prompts/lead/okstra-lead-contract.md` "Model assignments"; the selected runtime adapter owns provider-native dispatch-label mapping (including any `name` / `**Pane role:**` fields) and token-attribution wiring under its "Semantic operation mapping". This functional label is NOT what the run's PROGRESS checkpoints carry: `phase-4-dispatch` / `phase-5-collect` name the roster role team-state records (`Codex worker`), because that is the entry the Phase 7 conformance check matches them against.
15
12
  - The `Executor` (bound in `implementation.md` thin core) is the **only worker permitted to mutate project files**. All other workers run read-only. A `runner=native-session` executor uses the selected host adapter's native edit and command primitives. A `runner=cli-wrapper` executor mutates files inside its provider CLI's auto-edit mode. The safety rules in this sidecar apply identically to both runners.
16
13
  - When the thin core's Task worktree block resolves status to `created` or `reused`, the Executor MUST run every Edit / Write / build / test / commit command with the worktree path as cwd. Treat it as `project_root` for the duration of this run. Do NOT mutate the caller's original checkout. Do NOT `cd` out of the worktree to reach files. If a file outside the worktree is genuinely needed, treat it as a planning gap: record it in `Out-of-plan edits` and continue.
17
14
  - **How to set the working directory**: every command and native edit MUST target `{{EXECUTOR_WORKTREE_PATH}}`, never the lead session's original project directory. The selected runtime adapter owns the exact native command syntax. Provider CLI wrappers inject the worktree at the CLI layer. For tools that accept an explicit working-directory flag (`git -C <path>`, `cargo --manifest-path`, `pytest --rootdir`), prefer that form.
@@ -5,14 +5,10 @@ at Phase 5, BEFORE constructing the verifier worker dispatch prompts.
5
5
 
6
6
  # Implementation profile — Verifier sidecar
7
7
 
8
- > **When to read**: lead reads this file ONCE in Phase 5, between executor stage completion and the first verifier dispatch. Carries the two-tier command lookup, deny-list, discrepancy rule, and verifier-specific forbidden actions.
8
+ ## Verifier independence
9
9
 
10
- ## Verifier roles (resolved at run-prep time)
11
-
12
- - **Verifier dispatch labelling.** The core functional role label is `<provider>-verifier` (here, and identically in `final-verification`). Provider, role, and model identity are owned by `prompts/lead/okstra-lead-contract.md` "Model assignments"; the selected runtime adapter owns provider-native dispatch-label mapping (including any `name` / `**Pane role:**` fields) and token-attribution wiring under its "Semantic operation mapping". This functional label is NOT what the run's PROGRESS checkpoints carry: `phase-4-dispatch` / `phase-5-collect` name the roster role team-state records (`Claude worker`, `Codex worker`), because that is the entry the Phase 7 conformance check matches them against.
13
- - The verifier slots are `Claude verifier` and `Codex verifier`, plus `Antigravity verifier` **only when `antigravity` is in the resolved `--workers` roster**. Every verifier in the resolved roster is dispatched except the one whose worker ID holds the executor role this run: that ID materializes as the executor on every dispatch (`scripts/okstra_ctl/worker_prompt_policy.py`), so the executor's own provider has no separate verifier session in the current plumbing — a follow-up design item. Independence still holds where it counts: every verdict comes from a fresh CLI session with no shared context, never from the session that wrote the diff. Verifiers MUST NOT call Edit, Write, or any Bash command that mutates files outside the run's artifact directories. If a verifier wants a fix, it records the recommendation in its worker result; it does not apply the fix itself.
14
- - Session isolation — not model-variant divergence — is the primary self-review safeguard: each verifier is a separate CLI invocation with its own context window, so a verifier reusing the executor's model variant is acceptable. Different model variants (e.g. executor=opus / Claude verifier=sonnet) remain recommended when available.
15
- - Phase-specific model defaults override the shared defaults: `Claude verifier`=`opus`, `Codex verifier`=`gpt-5.6-sol`, `Antigravity verifier`=`gemini-3.1-pro` (only when present in the roster). The `Executor`'s model is taken from the provider-specific worker model corresponding to `--executor`: claude→`--claude-model` (default `opus`), codex→`--codex-model` (default `gpt-5.6-sol`), antigravity→`--antigravity-model` (default `gemini-3.1-pro`).
10
+ - Every verdict comes from a fresh session with no shared context, never from the session that wrote the diff. Verifiers MUST NOT call Edit, Write, or any Bash command that mutates files outside the run's artifact directories. If a verifier wants a fix, it records the recommendation in its worker result; it does not apply the fix itself.
11
+ - Session isolation is the primary self-review safeguard: each verifier is a separate invocation with its own context window. Reusing the executor's model is acceptable. The model comes from the run's stored assignment.
16
12
  - Verifiers read from the SAME working tree path the Executor used so they observe the exact diff the Executor produced. Verifiers remain strictly read-only there.
17
13
 
18
14
  ## Verifier QA duties (independent re-run mandate)
@@ -1,5 +1,25 @@
1
1
  # Change Impact Analysis Profile
2
2
 
3
+ ```yaml
4
+ roles:
5
+ - role: analyser
6
+ min: 2
7
+ recommended: 2
8
+ max: 5
9
+ duty: analysis-worker
10
+ - role: report-writer
11
+ min: 1
12
+ recommended: 1
13
+ max: 1
14
+ duty: report-writer
15
+ - role: verifier
16
+ min: 0
17
+ recommended: 0
18
+ max: 0
19
+ duty: reverification-worker
20
+ dynamic: true
21
+ ```
22
+
3
23
  - Purpose: assess the read-only impact of a proposed change, including preserved behavior, affected dependencies, and constraints that a later planning phase must resolve
4
24
  - Required workers:
5
25
  - claude
@@ -1,5 +1,30 @@
1
1
  # Error Analysis Profile
2
2
 
3
+ ```yaml
4
+ roles:
5
+ - role: analyser
6
+ min: 2
7
+ recommended: 2
8
+ max: 5
9
+ duty: diagnosis-worker
10
+ - role: critic
11
+ min: 0
12
+ recommended: 0
13
+ max: 1
14
+ duty: scope-critic
15
+ - role: report-writer
16
+ min: 1
17
+ recommended: 1
18
+ max: 1
19
+ duty: report-writer
20
+ - role: verifier
21
+ min: 0
22
+ recommended: 0
23
+ max: 0
24
+ duty: reverification-worker
25
+ dynamic: true
26
+ ```
27
+
3
28
  - Purpose: analyse reported errors or incidents and identify likely causes, missing evidence, and validation paths
4
29
  - Required workers:
5
30
  - claude
@@ -17,13 +42,14 @@
17
42
  - any `intent-inference` augmentation that re-characterises the symptom (e.g. classifying a vague reporter phrase like "it sometimes doesn't work" as "intermittent failure on a specific code path") is a **hypothesis**, not a confirmed symptom. If `[CONFIRMED …]` appears on the matching `intent-check:` row, treat that confirmation as the symptom. Otherwise follow the precondition's `skipped` branch above and keep the inference labelled as a hypothesis in the root-cause analysis.
18
43
  - `conversion-block:` rows mean the brief could not map a reporter statement to project vocabulary; never invent the missing mapping in this phase.
19
44
  - Worker diagnosis procedure:
45
+ - **Ticket Tagging.** Tag every section 1–5 item with its related ticket. Use `Issue / Ticket`, fall back to Task ID, then `unknown`; comma-separate multiple tickets.
20
46
  - **Symptom lock:** state the reporter's symptom verbatim, then translate it into one observable failure condition. If no observable condition can be derived from the brief, record that gap as the first blocker instead of guessing.
21
47
  - **Pass condition lock:** the brief's `EB-NNN` items state what the system must do once the defect is gone. State, per id, the observation that would show the symptom resolved — this is the upper bound on the fix. A diagnosis that leaves "how far do we fix this" open is what lets the later plan expand. Record each as an `endStateCoverage` row whose `coveredBy` names the root-cause candidate or next diagnostic that accounts for it. **Enforced:** `validators/validate-run.py` `_validate_end_state_coverage`.
22
48
  - **Reproduction status:** classify the run as `reproduced`, `not-reproduced`, or `blocked-before-repro`. Cite the command/log/file evidence used. If no command can be run safely in this phase, explain the read-only evidence path and the exact material needed next.
23
49
  - **Falsifiable cause candidates:** every root-cause candidate must include supporting evidence, the strongest falsifying evidence checked, confidence, and the next diagnostic action that would disprove it. A candidate that cannot be falsified is too vague for this phase.
24
50
  - **Graph-aware scope:** a graph edge can explain ordering or duplication, but it is not proof of cause by itself. Cite code/log evidence before claiming an upstream related task caused the current symptom.
25
51
  - **Sharp next diagnostic:** end with the single highest-value diagnostic command, log capture, or file inspection that should happen next, plus the expected signal that would confirm or reject the leading cause.
26
- - **Fix-design boundary:** do not design the implementation fix beyond what is necessary to validate the cause. If the cause is credible, route to `implementation-option-selection` with the verified evidence; if the cause is still unclear, route to another `error-analysis` run with the next diagnostic.
52
+ - **Fix-design boundary:** do not design the implementation fix beyond what is necessary to validate the cause. If the cause is credible, recommend `implementation-option-selection` with the verified evidence; if the cause is still unclear, recommend another `error-analysis` run with the next diagnostic. The lead's Phase Routing settles the next phase.
27
53
  - Structured diagnosis and routing contract:
28
54
  - `errorAnalysis` is the source of truth for reproduction status, `EA-NNN` cause candidates, the sharp next diagnostic, and the next route.
29
55
  - A route to `implementation-option-selection` requires a credible leading cause referenced by `routing.leadingCauseId` and `begin-option-selection` as the direction. A route back to `error-analysis` requires the sharp next diagnostic and `continue-investigation` as the direction.
@@ -1,5 +1,25 @@
1
1
  # Feature Analysis Profile
2
2
 
3
+ ```yaml
4
+ roles:
5
+ - role: analyser
6
+ min: 2
7
+ recommended: 2
8
+ max: 5
9
+ duty: analysis-worker
10
+ - role: report-writer
11
+ min: 1
12
+ recommended: 1
13
+ max: 1
14
+ duty: report-writer
15
+ - role: verifier
16
+ min: 0
17
+ recommended: 0
18
+ max: 0
19
+ duty: reverification-worker
20
+ dynamic: true
21
+ ```
22
+
3
23
  - Purpose: analyse a confirmed feature target's behavior, rules, state changes, external calls, and test coverage scope without designing or changing an implementation
4
24
  - Required workers:
5
25
  - claude
@@ -1,5 +1,24 @@
1
1
  # Final Verification Profile
2
2
 
3
+ ```yaml
4
+ roles:
5
+ - role: verifier
6
+ min: 2
7
+ recommended: 2
8
+ max: 5
9
+ duty: acceptance-verifier
10
+ - role: critic
11
+ min: 0
12
+ recommended: 0
13
+ max: 1
14
+ duty: acceptance-critic
15
+ - role: report-writer
16
+ min: 1
17
+ recommended: 1
18
+ max: 1
19
+ duty: report-writer
20
+ ```
21
+
3
22
  - Purpose: analyse completed work and identify remaining defects, omissions, and delivery risk before final acceptance
4
23
  - Required workers:
5
24
  - claude
@@ -63,7 +82,7 @@
63
82
  - **Validation Evidence**: for every requirement in the originating plan or task brief, cite the artifact (commit SHA, test output, log line, MCP SELECT result) that demonstrates coverage. Paraphrased "verified" claims without an artifact are rejected.
64
83
  - **Read-only command log**: any pre-existing test/validation command touched during this run MUST be listed with its exact command line and one honest status — `executed` (ran; carries its exit code) / `advisory` (external Tier 3 did not PASS; carries observed/expected results and remains user-owned) / `env-unavailable` (should run but cannot in this environment — missing replica DB, container, or service; carries the reason, never a faked pass) / `not-configured` (no such qa-command tier) / `rejected` (a mutating/denied token — skipped, carries the denied token). A check that could not run locally is recorded as `env-unavailable` or `advisory` according to the external QA policy — never silently dropped and never reported as `executed` with an invented exit code. Mutating-command prohibition is the shared read-only boundary (see Non-goals); it is not restated per row.
65
84
  - **Could-not-verify roll-up (§5.8.9)**: the template mechanically aggregates every not-confirmed check into one scannable list — `gap` requirement-coverage rows, `advisory` / `not-configured` / `env-unavailable` / `rejected` command rows, and `blocked` manual tests. You do not hand-author it, but you MUST give those rows their honest status so nothing unverified hides across sections: a check silently recorded as `executed`/`covered` will not surface in the roll-up. This is okstra's answer to "say what could not be verified this run."
66
- - **Routing recommendation**: the next safe phase — one of `release-handoff`, `done`, `error-analysis`, `implementation-option-selection`, `implementation-planning` — tied to the verdict and blocker list. `release-handoff` is allowed ONLY when the Verdict Token is `accepted`. `release-handoff` is additionally allowed ONLY when the verification scope (the `Verification scope:` line of the injected `VERIFICATION_TARGET` block, recorded as the report's `verificationScope` field) is `whole-task`; a `single-stage` accepted run routes to `release-handoff(stage-group)` (or `implementation` / `done`); plain `release-handoff` remains whole-task-only. Enforcement: `validators/validate-run.py` rejects a `single-stage` report whose routing cites plain `release-handoff`.
85
+ - **Routing recommendation**: `finalVerification.routingRecommendation` is an **object** with exactly two fields — `target`, one value of the enum below, and `rationale`, the sentence tying that choice to the verdict and the blocker list. Free routing prose is not the field; a target named only in the prose does not route the task, because Phase 7 projects `workflow.nextRecommendedPhase` from `target` alone. The seven allowed targets are `release-handoff`, `release-handoff(stage-group)`, `error-analysis`, `implementation-option-selection`, `implementation-planning`, `implementation`, and `done`. Both `release-handoff` forms are allowed ONLY when the Verdict Token is `accepted`. Plain `release-handoff` is additionally allowed ONLY when the verification scope (the `Verification scope:` line of the injected `VERIFICATION_TARGET` block, recorded as the report's `verificationScope` field) is `whole-task`; a `single-stage` accepted run routes to `release-handoff(stage-group)` (or `implementation` / `done`) instead. `done` ends the lifecycle here. Enforcement: `schemas/final-report-v2.0.schema.json` rejects a `target` outside the enum, a missing `rationale`, and a string in place of the object; `validators/validate-run.py` rejects a missing `target`, a non-`accepted` verdict routed to either `release-handoff` form, and a `single-stage` report whose routing cites plain `release-handoff`.
67
86
  - **Verified-row recording** (single-stage scope only): when the Verdict Token is `accepted`, the lead MUST run `okstra handoff record-verified --plan-run-root <plan-run-root> --stage <N> --report-path <final-report.md path> --data-json <final-report data.json path>` and quote the command + exit code in the report. The helper re-validates taskType/scope/verdict from data.json, so a non-accepted or whole-task report is rejected at the tool layer. **Enforced:** `validators/validate-run.py` `_validate_verified_row_recorded` requires a `verified` row in `runs/implementation-planning/consumers.jsonl` for every accepted stage — the helper validated its own inputs but nothing checked it had ever run, leaving reports that said `accepted` while the registry said unverified, so the stage was never offered for a stage-group PR.
68
87
  - Clarification request policy (phase-specific addendum — shared policy is in `_common-contract.md`):
69
88
  - populate `## 1. Clarification Items` only when a blocker hinges on information only the user can supply (deployment intent, intended target environment, business-rule interpretation); use `Blocks=next-phase` for items that gate continuing to release-handoff
@@ -1,5 +1,25 @@
1
1
  # Implementation Option Selection Profile
2
2
 
3
+ ```yaml
4
+ roles:
5
+ - role: designer
6
+ min: 3
7
+ recommended: 3
8
+ max: 5
9
+ duty: direction-selection-worker
10
+ - role: report-writer
11
+ min: 1
12
+ recommended: 1
13
+ max: 1
14
+ duty: report-writer
15
+ - role: verifier
16
+ min: 0
17
+ recommended: 0
18
+ max: 0
19
+ duty: reverification-worker
20
+ dynamic: true
21
+ ```
22
+
3
23
  - Purpose: compare feasible implementation directions before planning, preserving a read-only record of the evidence and trade-offs that selects the direction to plan
4
24
  - Required workers:
5
25
  - claude
@@ -1,5 +1,30 @@
1
1
  # Implementation Planning Profile
2
2
 
3
+ ```yaml
4
+ roles:
5
+ - role: planner
6
+ min: 2
7
+ recommended: 2
8
+ max: 5
9
+ duty: planning-worker
10
+ - role: critic
11
+ min: 0
12
+ recommended: 0
13
+ max: 1
14
+ duty: acceptance-critic
15
+ - role: report-writer
16
+ min: 1
17
+ recommended: 1
18
+ max: 1
19
+ duty: report-writer
20
+ - role: verifier
21
+ min: 0
22
+ recommended: 0
23
+ max: 0
24
+ duty: reverification-worker
25
+ dynamic: true
26
+ ```
27
+
3
28
  - Purpose: turn an upstream-selected direction into an executable plan; legacy reruns may retain candidate comparison
4
29
  - Required workers:
5
30
  - claude
@@ -16,6 +41,7 @@
16
41
  - never plan around an unconfirmed `intent-inference` augmentation as if it were a settled requirement. Treat the inference as settled ONLY when a `[CONFIRMED …]` marker sits on the matching `intent-check:` row after the precondition runs; absent the marker it stays a `Blocks=approval` clarification item per the precondition's `skipped` branch.
17
42
  - `conversion-block:` rows are handled by the precondition; planning around an untranslated reporter phrase is forbidden until it is resolved.
18
43
  - Worker planning procedure:
44
+ - **Ticket Tagging.** Tag every section 1–5 item with its related ticket. Use `Issue / Ticket`, fall back to Task ID, then `unknown`; comma-separate multiple tickets.
19
45
  - route by the planning input contract before analysis. A run carrying `selected-direction.json` uses the selected-direction procedure. Only a legacy rerun without that snapshot uses candidate comparison.
20
46
  - **Selected-direction planning procedure** — perform these steps in order and no others:
21
47
  1. Read `selected-direction.json` and the original requirements ledger end-to-end.
@@ -1,5 +1,24 @@
1
1
  # Implementation Profile
2
2
 
3
+ ```yaml
4
+ roles:
5
+ - role: implementer
6
+ min: 1
7
+ recommended: 1
8
+ max: 1
9
+ duty: implementation-executor
10
+ - role: verifier
11
+ min: 2
12
+ recommended: 2
13
+ max: 3
14
+ duty: implementation-verifier
15
+ - role: report-writer
16
+ min: 1
17
+ recommended: 1
18
+ max: 1
19
+ duty: report-writer
20
+ ```
21
+
3
22
  - Purpose: realise the approved `implementation-planning` deliverable as actual source changes, with cross-model verification, while keeping the run reversible
4
23
  - **Run-level fixed cost:** the verifier set, Phase 5.5 convergence, and the Phase 6 report-writer run exactly once per implementation run, over this run's single stage diff — never once per step.
5
24
  - **Fix run (profile carries a "Fix-Run Carry" block):** the executor's scope is the carried blocking findings plus the previous routing recommendation — it MUST NOT re-execute plan steps the previous run completed. Verifiers apply the "Fix-run incremental scope" section of `_implementation-verifier.md`; the report writer applies "Fix-run incremental authoring" in `report-writer.md`. The full validation-command re-run is NOT reduced.
@@ -1,5 +1,25 @@
1
1
  # Improvement Discovery Profile
2
2
 
3
+ ```yaml
4
+ roles:
5
+ - role: analyser
6
+ min: 3
7
+ recommended: 3
8
+ max: 5
9
+ duty: discovery-worker
10
+ - role: report-writer
11
+ min: 1
12
+ recommended: 1
13
+ max: 1
14
+ duty: report-writer
15
+ - role: verifier
16
+ min: 0
17
+ recommended: 0
18
+ max: 0
19
+ duty: reverification-worker
20
+ dynamic: true
21
+ ```
22
+
3
23
  - Purpose: scan a codebase scope through a fixed lens whitelist and surface ranked improvement candidates with multi-worker consensus classification
4
24
  - Required workers:
5
25
  - claude
@@ -41,7 +61,7 @@
41
61
  - Stop conditions (OR): all questions resolved / budget exhausted / user signals proceed.
42
62
  - Lead persists the round at `<RUN_DIR>/state/phase-1.5-grilling.md` with one section per question (question / recommended / user answer) and a closing `Resolved scope` / `Resolved lenses` block. Worker prompts use this resolved block as the authoritative scope and lens definition.
43
63
  - The same log includes `## Primary Pass Assignments` with a `Worker ID | Primary lens` table. It contains every selected analyser exactly once in `requiredWorkerRoles` order; the lead derives it from the resolved roster and lenses rather than provider catalog order.
44
- - After writing the log and before Phase 4 dispatch, the lead injects its **absolute path** into every analyser prompt as the `**Phase 1.5 Grilling Log:** <absolute-path>` anchor header (see `templates/worker-prompt-preamble.md` §"Anchor headers"). This is the improvement-discovery counterpart to the `**Worktree:**` / `**Verification …:**` anchors that implementation / final-verification inject: workers read the log from this explicit path rather than re-deriving `<RUN_DIR>`. The path is byte-identical across all analysers, so it does not break the dispatch-prompt invariant.
64
+ - After writing the log and before Phase 4 dispatch, the lead injects its **absolute path** into every analyser prompt as the `**Phase 1.5 Grilling Log:** <absolute-path>` anchor header (see `okstra_ctl.worker_prompt_headers.worker_prompt_headers()`). This is the improvement-discovery counterpart to the `**Worktree:**` / `**Verification …:**` anchors that implementation / final-verification inject: workers read the log from this explicit path rather than re-deriving `<RUN_DIR>`. The path is byte-identical across all analysers, so it does not break the dispatch-prompt invariant.
45
65
  - Decision-tree walk (bounded):
46
66
  - When candidates branch on a structural question (e.g. "is module X meant to own this responsibility?"), resolve via `Read` / `Grep` first. Only escalate to the user inside the Phase 1.5 budget.
47
67
  - Expected output emphasis:
@@ -1,5 +1,25 @@
1
1
  # Project Analysis Profile
2
2
 
3
+ ```yaml
4
+ roles:
5
+ - role: analyser
6
+ min: 2
7
+ recommended: 2
8
+ max: 5
9
+ duty: analysis-worker
10
+ - role: report-writer
11
+ min: 1
12
+ recommended: 1
13
+ max: 1
14
+ duty: report-writer
15
+ - role: verifier
16
+ min: 0
17
+ recommended: 0
18
+ max: 0
19
+ duty: reverification-worker
20
+ dynamic: true
21
+ ```
22
+
3
23
  - Purpose: map a bounded project area so later work can navigate components, dependencies, entry points, repositories, and external integrations without changing the source
4
24
  - Required workers:
5
25
  - claude
@@ -1,5 +1,9 @@
1
1
  # Release Handoff Profile
2
2
 
3
+ ```yaml
4
+ roles: []
5
+ ```
6
+
3
7
  - Record the handoff shape in `releaseHandoff.handoffScope`: `mode` always, plus `stages`
4
8
  and `collectorBranch` in stage-group mode. The report is the only place a reader learns
5
9
  which stages shipped — the collector branch name does not say.
@@ -1,5 +1,30 @@
1
1
  # Requirements Discovery Profile
2
2
 
3
+ ```yaml
4
+ roles:
5
+ - role: analyser
6
+ min: 2
7
+ recommended: 2
8
+ max: 5
9
+ duty: discovery-worker
10
+ - role: critic
11
+ min: 0
12
+ recommended: 0
13
+ max: 1
14
+ duty: scope-critic
15
+ - role: report-writer
16
+ min: 1
17
+ recommended: 1
18
+ max: 1
19
+ duty: report-writer
20
+ - role: verifier
21
+ min: 0
22
+ recommended: 0
23
+ max: 0
24
+ duty: reverification-worker
25
+ dynamic: true
26
+ ```
27
+
3
28
  - Purpose: classify the work request, identify missing requirement evidence, and route the task to the safest next lifecycle phase before implementation starts
4
29
  - Required workers:
5
30
  - claude
@@ -17,7 +42,8 @@
17
42
  - `intent-inference` augmentations whose paired `intent-check:` row carries `[CONFIRMED …]` are treated as **confirmed**; trust the confirmation text in `## Reporter Confirmations` over the original inference if they differ. Unconfirmed `intent-inference` rows under `reporter-confirmations: skipped` follow the precondition's `skipped` branch above.
18
43
  - `conversion-block:` rows are explicit "translation failed" signals — never attempt to resolve them by inference here; the precondition above already handled them.
19
44
  - Worker discovery procedure:
20
- - classify the request and cite the evidence that determines both its work category and safest next phase
45
+ - **Ticket Tagging.** Tag every section 1–5 item with its related ticket. Use `Issue / Ticket`, fall back to Task ID, then `unknown`; comma-separate multiple tickets.
46
+ - classify the request and cite the evidence that supports a recommended work category and safest next phase. The lead's Phase Routing settles the next phase.
21
47
  - identify independently startable decomposition candidates without publishing or rendering fan-out artifacts; preserve every directed dependency from `Related Task Graph`
22
48
  - resolve codebase-answerable ambiguity by inspection and record file:line evidence; return only human-owned decisions as clarification candidates with the evidence already checked
23
49
  - state the reporter's rejection criteria, missing routing inputs, and the evidence boundary behind each recommendation
@@ -480,6 +480,39 @@
480
480
  "no": "아니오 — 단계별로 다시 입력"
481
481
  }
482
482
  },
483
+ "leader_session": {
484
+ "label": "리더는 현재 세션 모델을 씁니다 (읽기 전용): {model_ref}{effort_suffix}",
485
+ "echo_template": "leader-session: {value}",
486
+ "options": {
487
+ "continue": "계속"
488
+ },
489
+ "effort_suffix": " · effort {effort}"
490
+ },
491
+ "role_count": {
492
+ "label": "{role} 역할 인스턴스 수를 선택하세요 ({minimum}..{maximum}, 적정 {default})",
493
+ "echo_template": "role-count: {value}",
494
+ "options": {
495
+ "count": "{count}개{default_suffix}",
496
+ "default_suffix": " (적정)"
497
+ }
498
+ },
499
+ "role_add": {
500
+ "label": "선택 역할 {role} 을(를) 이번 run 에 추가할까요? (최대 {maximum}개, 기본: 추가 안 함)",
501
+ "echo_template": "role-add: {value}",
502
+ "options": {
503
+ "skip": "추가 안 함{default_suffix}",
504
+ "add": "{count}개 추가",
505
+ "default_suffix": " (기본)"
506
+ }
507
+ },
508
+ "role_model": {
509
+ "label": "{role} 역할 {ordinal}/{count} 인스턴스의 모델을 선택하세요",
510
+ "echo_template": "role-model: {value}",
511
+ "options": {
512
+ "model": "{model_ref} — {display}{default_suffix}",
513
+ "default_suffix": " (기본 후보)"
514
+ }
515
+ },
483
516
  "defaults_or_custom": {
484
517
  "label": "역할별 모델 선택 단계입니다 (참여 워커 구성을 바꾸는 게 아닙니다).\n이번 run 에서 모델을 고를 역할:\n{role_models}\n· 기본값으로 진행 — 위 추천 모델을 그대로 쓰고, directive·관련 task 없이 바로 넘어갑니다.\n· 커스터마이즈 — 위 역할별 모델을 직접 고르고, 추가 directive·관련 task 도 지정합니다.\n(추천 값은 runtime 기본값으로 해소됩니다. 분석에 참여하지 않는 역할은 위 목록에 나오지 않습니다 — 예: antigravity 는 implementation 의 executor 로 선택했을 때만 표시됩니다.)",
485
518
  "echo_template": "customize: {value}",
@@ -587,6 +620,8 @@
587
620
  },
588
621
  "confirmation": {
589
622
  "header": "선택 확인:",
623
+ "static_role": " static-role : {role}#{ordinal} / {model}",
624
+ "dynamic_role": " dynamic-role : {role} / reuse selected participant model",
590
625
  "workers_implementation_default": " workers : (프로필 기본 — executor + verifier 2 + report-writer)",
591
626
  "base_ref_stage_isolated": " base-ref : (stage 격리 — 의존 stage 기준으로 run 준비 시점에 자동 해소)",
592
627
  "base_ref_reuse_task_dir": " base-ref : (기존 `{task_key}` 디렉터리 재사용 — 최초 base 유지)",
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
  from collections.abc import Mapping
5
5
 
6
6
  from ... import dispatch_core
7
+ from ...domain.worker_exec import WorkerWriteCapability
7
8
  from ...ports.worker_dispatch import WorkerDispatchPlan, WorkerDispatchRequest
8
9
 
9
10
 
@@ -17,6 +18,9 @@ class CliWrapperDispatchPort:
17
18
  default_backend: str = dispatch_core.BACKEND_CLI_WRAPPER,
18
19
  cli_wrapper_assignments_only: bool = False,
19
20
  default_provider_by_worker_id: Mapping[str, str] | None = None,
21
+ worker_write_capability: WorkerWriteCapability = WorkerWriteCapability(
22
+ "none"
23
+ ),
20
24
  ) -> None:
21
25
  self._supported_worker_wrappers = supported_worker_wrappers or {}
22
26
  self._unsupported_worker_label = unsupported_worker_label
@@ -26,6 +30,7 @@ class CliWrapperDispatchPort:
26
30
  self._default_provider_by_worker_id = dict(
27
31
  default_provider_by_worker_id or {}
28
32
  )
33
+ self._worker_write_capability = worker_write_capability
29
34
 
30
35
  def build_plan(self, request: WorkerDispatchRequest) -> WorkerDispatchPlan:
31
36
  backend_plan = None
@@ -52,3 +57,6 @@ class CliWrapperDispatchPort:
52
57
  backend_plan=backend_plan,
53
58
  dispatch_mode="render-only",
54
59
  )
60
+
61
+ def worker_write_capability(self) -> WorkerWriteCapability:
62
+ return self._worker_write_capability
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
  from collections.abc import Mapping
5
5
 
6
6
  from ... import dispatch_core
7
+ from ...domain.worker_exec import WorkerWriteCapability
7
8
  from ...ports.worker_dispatch import (
8
9
  WorkerDispatchPlan,
9
10
  WorkerDispatchPort,
@@ -25,6 +26,9 @@ class CmuxDispatchPort:
25
26
  required_lead_runtime: str | None = None,
26
27
  cli_wrapper_assignments_only: bool = False,
27
28
  default_provider_by_worker_id: Mapping[str, str] | None = None,
29
+ worker_write_capability: WorkerWriteCapability = WorkerWriteCapability(
30
+ "none"
31
+ ),
28
32
  ) -> None:
29
33
  self._backend_port = CliWrapperDispatchPort(
30
34
  supported_worker_wrappers=supported_worker_wrappers,
@@ -33,6 +37,7 @@ class CmuxDispatchPort:
33
37
  default_backend=dispatch_core.BACKEND_CMUX_PANE,
34
38
  cli_wrapper_assignments_only=cli_wrapper_assignments_only,
35
39
  default_provider_by_worker_id=default_provider_by_worker_id,
40
+ worker_write_capability=worker_write_capability,
36
41
  )
37
42
 
38
43
  def build_plan(self, request: WorkerDispatchRequest) -> WorkerDispatchPlan:
@@ -46,6 +51,9 @@ class CmuxDispatchPort:
46
51
  relay_contract=CMUX_RELAY_CONTRACT,
47
52
  )
48
53
 
54
+ def worker_write_capability(self) -> WorkerWriteCapability:
55
+ return self._backend_port.worker_write_capability()
56
+
49
57
 
50
58
  def dispatch_port_for_terminal_backend(
51
59
  terminal_backend: str,
@@ -1,13 +1,26 @@
1
1
  """Native host-team dispatch planning."""
2
2
  from __future__ import annotations
3
3
 
4
+ from ...domain.worker_exec import WorkerWriteCapability
4
5
  from ...ports.worker_dispatch import WorkerDispatchPlan, WorkerDispatchRequest
5
6
 
6
7
 
7
8
  class NativeTeamDispatchPort:
9
+ def __init__(
10
+ self,
11
+ *,
12
+ worker_write_capability: WorkerWriteCapability = WorkerWriteCapability(
13
+ "none"
14
+ ),
15
+ ) -> None:
16
+ self._worker_write_capability = worker_write_capability
17
+
8
18
  def build_plan(self, request: WorkerDispatchRequest) -> WorkerDispatchPlan:
9
19
  return WorkerDispatchPlan(
10
20
  mode="native-team",
11
21
  request=request,
12
22
  dispatch_mode="team",
13
23
  )
24
+
25
+ def worker_write_capability(self) -> WorkerWriteCapability:
26
+ return self._worker_write_capability