okstra 0.206.0 → 0.207.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 (259) hide show
  1. package/README.md +3 -3
  2. package/dist/cli-registry.mjs +7 -1
  3. package/dist/cli-registry.mjs.map +1 -1
  4. package/dist/commands/lifecycle/install.mjs +1 -1
  5. package/dist/commands/lifecycle/install.mjs.map +1 -1
  6. package/docs/architecture/storage-model.md +1 -0
  7. package/docs/architecture.md +40 -16
  8. package/docs/cli.md +17 -15
  9. package/docs/contributor-change-matrix.md +3 -2
  10. package/docs/performance-improvement-plan-v2.md +1 -1
  11. package/docs/project-structure-overview.md +43 -20
  12. package/package.json +1 -1
  13. package/runtime/BUILD.json +2 -2
  14. package/runtime/agents/operations/code-review.json +1 -1
  15. package/runtime/bin/lib/okstra/usage.sh +3 -3
  16. package/runtime/bin/okstra-compact-reminder.sh +1 -1
  17. package/runtime/bin/okstra-spawn-followups.py +2 -2
  18. package/runtime/prompts/duties/direction-selection-worker.json +1 -1
  19. package/runtime/prompts/launch.template.md +2 -2
  20. package/runtime/prompts/lead/adapters/cmux.md +4 -3
  21. package/runtime/prompts/lead/context-loader.md +1 -1
  22. package/runtime/prompts/lead/convergence.md +44 -12
  23. package/runtime/prompts/lead/okstra-lead-contract.md +44 -73
  24. package/runtime/prompts/lead/phase-routing.md +64 -0
  25. package/runtime/prompts/lead/report-writer.md +10 -8
  26. package/runtime/prompts/lead/team-contract.md +1 -1
  27. package/runtime/prompts/profiles/_clarification-recommendation.md +4 -4
  28. package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
  29. package/runtime/prompts/profiles/_common-contract.md +2 -2
  30. package/runtime/prompts/profiles/_coverage-critic.md +1 -1
  31. package/runtime/prompts/profiles/forbidden-actions.json +0 -94
  32. package/runtime/prompts/wizard/prompts.ko.json +2 -1
  33. package/runtime/python/okstra_ctl/adapters/hosts/antigravity/relay.md +1 -1
  34. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +5 -5
  35. package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +1 -1
  36. package/runtime/python/okstra_ctl/adapters/hosts/external/relay.md +3 -2
  37. package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +1 -1
  38. package/runtime/python/okstra_ctl/adapters/hosts/kimi/relay.md +1 -1
  39. package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +17 -26
  40. package/runtime/python/okstra_ctl/agent/prompt_cli/batch.py +183 -0
  41. package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +60 -10
  42. package/runtime/python/okstra_ctl/agent/prompt_cli/corrections.py +1 -1
  43. package/runtime/python/okstra_ctl/agent/prompt_cli/jobs.py +21 -4
  44. package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +10 -1
  45. package/runtime/python/okstra_ctl/analysis_inputs.py +0 -39
  46. package/runtime/python/okstra_ctl/analysis_scope.py +31 -0
  47. package/runtime/python/okstra_ctl/approval_decisions.py +32 -2
  48. package/runtime/python/okstra_ctl/asset_roots.py +19 -0
  49. package/runtime/python/okstra_ctl/assignment_resolver.py +8 -0
  50. package/runtime/python/okstra_ctl/blocking_checks.py +7 -0
  51. package/runtime/python/okstra_ctl/code_review_target.py +92 -6
  52. package/runtime/python/okstra_ctl/consumers.py +12 -0
  53. package/runtime/python/okstra_ctl/dispatch_checkpoints.py +121 -0
  54. package/runtime/python/okstra_ctl/dispatch_core.py +54 -32
  55. package/runtime/python/okstra_ctl/dispatch_state.py +34 -5
  56. package/runtime/python/okstra_ctl/doctor.py +2 -1
  57. package/runtime/python/okstra_ctl/domain/provider.py +5 -0
  58. package/runtime/python/okstra_ctl/domain/worker_presentation.py +21 -2
  59. package/runtime/python/okstra_ctl/domain/write_policy.py +2 -1
  60. package/runtime/python/okstra_ctl/execution_mutation_audit.py +46 -9
  61. package/runtime/python/okstra_ctl/handoff.py +11 -466
  62. package/runtime/python/okstra_ctl/handoff_error.py +5 -0
  63. package/runtime/python/okstra_ctl/implementation_direction.py +0 -477
  64. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +13 -1
  65. package/runtime/python/okstra_ctl/lead_progress.py +33 -1
  66. package/runtime/python/okstra_ctl/manager_view.py +26 -19
  67. package/runtime/python/okstra_ctl/model_io/lines.py +21 -4
  68. package/runtime/python/okstra_ctl/models.py +4 -1
  69. package/runtime/python/okstra_ctl/operation_invocation.py +11 -2
  70. package/runtime/python/okstra_ctl/option_comparison.py +3 -165
  71. package/runtime/python/okstra_ctl/option_votes.py +3 -191
  72. package/runtime/python/okstra_ctl/paths.py +8 -6
  73. package/runtime/python/okstra_ctl/phases/catalog.py +56 -12
  74. package/runtime/python/okstra_ctl/phases/change_impact_analysis/boundary.json +11 -0
  75. package/runtime/python/okstra_ctl/phases/change_impact_analysis/entry.py +39 -0
  76. package/runtime/python/okstra_ctl/{report_html/view_models/change_impact_analysis.py → phases/change_impact_analysis/report.py} +3 -3
  77. package/runtime/python/okstra_ctl/phases/change_impact_analysis/spec.md +26 -0
  78. package/runtime/python/okstra_ctl/phases/change_impact_analysis/validation.py +23 -0
  79. package/runtime/python/okstra_ctl/phases/error_analysis/__init__.py +1 -0
  80. package/runtime/python/okstra_ctl/phases/error_analysis/boundary.json +9 -0
  81. package/runtime/{prompts/profiles/error-analysis.md → python/okstra_ctl/phases/error_analysis/profile.md} +2 -2
  82. package/runtime/python/okstra_ctl/{report_html/view_models/error_analysis.py → phases/error_analysis/report.py} +9 -8
  83. package/runtime/{templates/reports → python/okstra_ctl/phases/error_analysis/report_assets}/error-analysis-input.template.md +1 -1
  84. package/runtime/python/okstra_ctl/phases/error_analysis/spec.md +118 -0
  85. package/runtime/python/okstra_ctl/phases/error_analysis/validation.py +241 -0
  86. package/runtime/python/okstra_ctl/phases/feature_analysis/__init__.py +1 -0
  87. package/runtime/python/okstra_ctl/phases/feature_analysis/boundary.json +8 -0
  88. package/runtime/python/okstra_ctl/phases/feature_analysis/entry.py +63 -0
  89. package/runtime/python/okstra_ctl/{report_html/view_models/feature_analysis.py → phases/feature_analysis/report.py} +12 -5
  90. package/runtime/python/okstra_ctl/phases/feature_analysis/spec.md +22 -0
  91. package/runtime/python/okstra_ctl/phases/feature_analysis/validation.py +27 -0
  92. package/runtime/python/okstra_ctl/phases/feature_analysis/wizard.py +95 -0
  93. package/runtime/python/okstra_ctl/phases/final_verification/boundary.json +8 -0
  94. package/runtime/python/okstra_ctl/phases/final_verification/profile.md +2 -2
  95. package/runtime/{templates/reports → python/okstra_ctl/phases/final_verification/report_assets}/final-verification-input.template.md +1 -1
  96. package/runtime/python/okstra_ctl/phases/final_verification/spec.md +1 -1
  97. package/runtime/python/okstra_ctl/phases/implementation/__init__.py +1 -0
  98. package/runtime/python/okstra_ctl/phases/implementation/boundary.json +17 -0
  99. package/runtime/python/okstra_ctl/{implementation_stage.py → phases/implementation/entry.py} +22 -10
  100. package/runtime/{prompts/host-orchestration/implementation.md → python/okstra_ctl/phases/implementation/host-rules.md} +1 -1
  101. package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-deliverable.md +1 -1
  102. package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-executor.md +4 -3
  103. package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-verifier.md +18 -7
  104. package/runtime/{prompts/profiles/implementation.md → python/okstra_ctl/phases/implementation/profile.md} +5 -5
  105. package/runtime/python/okstra_ctl/{report_html/view_models/implementation.py → phases/implementation/report.py} +3 -3
  106. package/runtime/{templates/reports → python/okstra_ctl/phases/implementation/report_assets}/implementation-input.template.md +1 -1
  107. package/runtime/python/okstra_ctl/phases/implementation/spec.md +238 -0
  108. package/runtime/python/okstra_ctl/phases/implementation/validation.py +205 -0
  109. package/runtime/python/okstra_ctl/phases/implementation/wizard.py +39 -0
  110. package/runtime/python/okstra_ctl/phases/implementation_option_selection/__init__.py +1 -0
  111. package/runtime/python/okstra_ctl/phases/implementation_option_selection/authoring.py +80 -0
  112. package/runtime/python/okstra_ctl/phases/implementation_option_selection/boundary.json +10 -0
  113. package/runtime/python/okstra_ctl/phases/implementation_option_selection/comparison.py +168 -0
  114. package/runtime/python/okstra_ctl/phases/implementation_option_selection/entry.py +27 -0
  115. package/runtime/{prompts/profiles/implementation-option-selection.md → python/okstra_ctl/phases/implementation_option_selection/profile.md} +3 -3
  116. package/runtime/python/okstra_ctl/{report_html/view_models/implementation_option_selection.py → phases/implementation_option_selection/report.py} +2 -2
  117. package/runtime/python/okstra_ctl/phases/implementation_option_selection/spec.md +83 -0
  118. package/runtime/python/okstra_ctl/{implementation_options.py → phases/implementation_option_selection/validation.py} +3 -3
  119. package/runtime/python/okstra_ctl/phases/implementation_option_selection/votes.py +194 -0
  120. package/runtime/python/okstra_ctl/phases/implementation_planning/__init__.py +1 -0
  121. package/runtime/python/okstra_ctl/phases/implementation_planning/authoring.py +2345 -0
  122. package/runtime/python/okstra_ctl/phases/implementation_planning/boundary.json +12 -0
  123. package/runtime/python/okstra_ctl/phases/implementation_planning/entry.py +161 -0
  124. package/runtime/python/okstra_ctl/phases/implementation_planning/guidance.py +178 -0
  125. package/runtime/{prompts/lead → python/okstra_ctl/phases/implementation_planning/instructions}/plan-body-verification.md +61 -51
  126. package/runtime/python/okstra_ctl/phases/implementation_planning/plan_body.py +3295 -0
  127. package/runtime/{prompts/profiles/implementation-planning.md → python/okstra_ctl/phases/implementation_planning/profile.md} +74 -25
  128. package/runtime/python/okstra_ctl/phases/implementation_planning/report.py +237 -0
  129. package/runtime/{templates/reports → python/okstra_ctl/phases/implementation_planning/report_assets}/implementation-planning-input.template.md +2 -2
  130. package/runtime/python/okstra_ctl/phases/implementation_planning/spec.md +204 -0
  131. package/runtime/python/okstra_ctl/phases/implementation_planning/validation.py +597 -0
  132. package/runtime/python/okstra_ctl/phases/implementation_planning/wizard.py +166 -0
  133. package/runtime/python/okstra_ctl/phases/improvement_discovery/boundary.json +12 -0
  134. package/runtime/python/okstra_ctl/{improvement_lenses.py → phases/improvement_discovery/lenses.py} +1 -6
  135. package/runtime/{prompts/profiles/improvement-discovery.md → python/okstra_ctl/phases/improvement_discovery/profile.md} +5 -5
  136. package/runtime/python/okstra_ctl/{report_html/view_models/improvement_discovery.py → phases/improvement_discovery/report.py} +3 -3
  137. package/runtime/{templates/reports → python/okstra_ctl/phases/improvement_discovery/report_assets}/improvement-discovery-input.template.md +1 -2
  138. package/runtime/python/okstra_ctl/phases/improvement_discovery/spec.md +29 -0
  139. package/runtime/{validators/validate_improvement_report.py → python/okstra_ctl/phases/improvement_discovery/validation.py} +5 -14
  140. package/runtime/python/okstra_ctl/phases/project_analysis/__init__.py +1 -0
  141. package/runtime/python/okstra_ctl/phases/project_analysis/boundary.json +8 -0
  142. package/runtime/python/okstra_ctl/phases/project_analysis/entry.py +11 -0
  143. package/runtime/python/okstra_ctl/{report_html/view_models/project_analysis.py → phases/project_analysis/report.py} +3 -3
  144. package/runtime/python/okstra_ctl/phases/project_analysis/spec.md +33 -0
  145. package/runtime/python/okstra_ctl/phases/project_analysis/validation.py +55 -0
  146. package/runtime/python/okstra_ctl/phases/release_handoff/__init__.py +1 -0
  147. package/runtime/python/okstra_ctl/phases/release_handoff/boundary.json +17 -0
  148. package/runtime/python/okstra_ctl/phases/release_handoff/entry.py +147 -0
  149. package/runtime/python/okstra_ctl/phases/release_handoff/operations.py +446 -0
  150. package/runtime/{prompts/profiles/release-handoff.md → python/okstra_ctl/phases/release_handoff/profile.md} +3 -3
  151. package/runtime/python/okstra_ctl/{report_html/view_models/release_handoff.py → phases/release_handoff/report.py} +3 -3
  152. package/runtime/{templates/reports → python/okstra_ctl/phases/release_handoff/report_assets}/release-handoff-input.template.md +1 -1
  153. package/runtime/python/okstra_ctl/phases/release_handoff/spec.md +233 -0
  154. package/runtime/python/okstra_ctl/phases/release_handoff/wizard.py +84 -0
  155. package/runtime/python/okstra_ctl/phases/requirements_discovery/__init__.py +1 -0
  156. package/runtime/python/okstra_ctl/phases/requirements_discovery/boundary.json +9 -0
  157. package/runtime/{prompts/profiles/requirements-discovery.md → python/okstra_ctl/phases/requirements_discovery/profile.md} +2 -3
  158. package/runtime/python/okstra_ctl/{report_html/view_models/requirements_discovery.py → phases/requirements_discovery/report.py} +3 -3
  159. package/runtime/python/okstra_ctl/phases/requirements_discovery/spec.md +132 -0
  160. package/runtime/{validators/validate_fanout.py → python/okstra_ctl/phases/requirements_discovery/validation.py} +11 -12
  161. package/runtime/python/okstra_ctl/phases/technical_verification/__init__.py +1 -0
  162. package/runtime/python/okstra_ctl/phases/technical_verification/boundary.json +9 -0
  163. package/runtime/python/okstra_ctl/phases/technical_verification/entry.py +100 -0
  164. package/runtime/{prompts/profiles/technical-verification.md → python/okstra_ctl/phases/technical_verification/profile.md} +2 -2
  165. package/runtime/python/okstra_ctl/{report_html/view_models/technical_verification.py → phases/technical_verification/report.py} +2 -2
  166. package/runtime/python/okstra_ctl/phases/technical_verification/spec.md +37 -0
  167. package/runtime/python/okstra_ctl/phases/technical_verification/validation.py +90 -0
  168. package/runtime/python/okstra_ctl/plan_approval.py +70 -0
  169. package/runtime/python/okstra_ctl/plan_items_cli.py +2 -2130
  170. package/runtime/python/okstra_ctl/process_group.py +118 -0
  171. package/runtime/python/okstra_ctl/profile_show.py +3 -3
  172. package/runtime/python/okstra_ctl/render.py +15 -4
  173. package/runtime/python/okstra_ctl/report_assembly.py +28 -92
  174. package/runtime/python/okstra_ctl/report_finalize.py +106 -2
  175. package/runtime/python/okstra_ctl/report_html/context_links.py +1 -1
  176. package/runtime/python/okstra_ctl/report_projections.py +1 -36
  177. package/runtime/python/okstra_ctl/report_routing.py +23 -0
  178. package/runtime/python/okstra_ctl/report_synthesis_packet.py +4 -73
  179. package/runtime/python/okstra_ctl/report_validation_identity.py +38 -0
  180. package/runtime/python/okstra_ctl/report_views.py +1 -1
  181. package/runtime/python/okstra_ctl/run.py +68 -350
  182. package/runtime/python/okstra_ctl/run_artifact_prune.py +200 -0
  183. package/runtime/python/okstra_ctl/stage_map.py +13 -0
  184. package/runtime/python/okstra_ctl/team.py +108 -9
  185. package/runtime/python/okstra_ctl/technical_verification_facts.py +52 -0
  186. package/runtime/python/okstra_ctl/wizard/__init__.py +31 -31
  187. package/runtime/python/okstra_ctl/wizard/api.py +18 -0
  188. package/runtime/python/okstra_ctl/wizard/outcome.py +3 -12
  189. package/runtime/python/okstra_ctl/wizard/registry.py +20 -12
  190. package/runtime/python/okstra_ctl/wizard/steps_analysis.py +0 -97
  191. package/runtime/python/okstra_ctl/wizard/steps_options.py +8 -0
  192. package/runtime/python/okstra_ctl/wizard/steps_plan.py +10 -263
  193. package/runtime/python/okstra_ctl/wizard/steps_roles.py +2 -1
  194. package/runtime/python/okstra_ctl/work_categories.py +1 -1
  195. package/runtime/python/okstra_ctl/worker_dispatch.py +44 -3
  196. package/runtime/python/okstra_ctl/worker_prompt_contract.py +36 -0
  197. package/runtime/python/okstra_ctl/worker_prompt_policy.py +19 -0
  198. package/runtime/python/okstra_ctl/worker_runner.py +21 -3
  199. package/runtime/python/okstra_ctl/workflow.py +26 -143
  200. package/runtime/python/okstra_ctl/write_policy.py +57 -7
  201. package/runtime/python/okstra_project/dirs.py +14 -0
  202. package/runtime/python/okstra_project/resolver.py +2 -1
  203. package/runtime/schemas/execution-manifest-v2.schema.json +2 -1
  204. package/runtime/skills/okstra-brief-gen/SKILL.md +3 -3
  205. package/runtime/skills/okstra-code-review/SKILL.md +70 -32
  206. package/runtime/skills/okstra-code-review/references/review-calibration.md +26 -6
  207. package/runtime/skills/okstra-run/SKILL.md +3 -3
  208. package/runtime/templates/manager/view.template.html +18 -1
  209. package/runtime/templates/reports/quick-input.template.md +1 -1
  210. package/runtime/templates/reports/task-brief.template.md +1 -1
  211. package/runtime/validators/validate-brief.py +2 -2
  212. package/runtime/validators/validate-run.py +299 -3940
  213. package/runtime/validators/validate_analysis_report.py +14 -126
  214. package/runtime/python/okstra_ctl/report_html/view_models/implementation_planning.py +0 -147
  215. package/runtime/python/okstra_ctl/technical_verification.py +0 -195
  216. /package/runtime/{prompts/profiles/change-impact-analysis.json → python/okstra_ctl/phases/change_impact_analysis/profile.json} +0 -0
  217. /package/runtime/{prompts/profiles/change-impact-analysis.md → python/okstra_ctl/phases/change_impact_analysis/profile.md} +0 -0
  218. /package/runtime/{templates/reports → python/okstra_ctl/phases/change_impact_analysis/report_assets}/change-impact-analysis-input.template.md +0 -0
  219. /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/change_impact_analysis/report_assets}/change-impact-analysis.template.html +0 -0
  220. /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/change_impact_analysis/report_assets}/change-impact-analysis.template.md +0 -0
  221. /package/runtime/{prompts/profiles/error-analysis.json → python/okstra_ctl/phases/error_analysis/profile.json} +0 -0
  222. /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/error_analysis/report_assets}/error-analysis.template.html +0 -0
  223. /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/error_analysis/report_assets}/error-analysis.template.md +0 -0
  224. /package/runtime/{prompts/profiles/feature-analysis.json → python/okstra_ctl/phases/feature_analysis/profile.json} +0 -0
  225. /package/runtime/{prompts/profiles/feature-analysis.md → python/okstra_ctl/phases/feature_analysis/profile.md} +0 -0
  226. /package/runtime/{templates/reports → python/okstra_ctl/phases/feature_analysis/report_assets}/feature-analysis-input.template.md +0 -0
  227. /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/feature_analysis/report_assets}/feature-analysis.template.html +0 -0
  228. /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/feature_analysis/report_assets}/feature-analysis.template.md +0 -0
  229. /package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-diff-review.md +0 -0
  230. /package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-self-check.md +0 -0
  231. /package/runtime/{prompts/profiles/implementation.json → python/okstra_ctl/phases/implementation/profile.json} +0 -0
  232. /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/implementation/report_assets}/implementation.template.html +0 -0
  233. /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/implementation/report_assets}/implementation.template.md +0 -0
  234. /package/runtime/{prompts/profiles/implementation-option-selection.json → python/okstra_ctl/phases/implementation_option_selection/profile.json} +0 -0
  235. /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/implementation_option_selection/report_assets}/implementation-option-selection.template.html +0 -0
  236. /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/implementation_option_selection/report_assets}/implementation-option-selection.template.md +0 -0
  237. /package/runtime/{prompts/host-orchestration/implementation-planning.md → python/okstra_ctl/phases/implementation_planning/host-rules.md} +0 -0
  238. /package/runtime/{prompts/profiles/implementation-planning.json → python/okstra_ctl/phases/implementation_planning/profile.json} +0 -0
  239. /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/implementation_planning/report_assets}/implementation-planning.template.html +0 -0
  240. /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/implementation_planning/report_assets}/implementation-planning.template.md +0 -0
  241. /package/runtime/{prompts/profiles/improvement-discovery.json → python/okstra_ctl/phases/improvement_discovery/profile.json} +0 -0
  242. /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/improvement_discovery/report_assets}/improvement-discovery.template.html +0 -0
  243. /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/improvement_discovery/report_assets}/improvement-discovery.template.md +0 -0
  244. /package/runtime/{prompts/profiles/project-analysis.json → python/okstra_ctl/phases/project_analysis/profile.json} +0 -0
  245. /package/runtime/{prompts/profiles/project-analysis.md → python/okstra_ctl/phases/project_analysis/profile.md} +0 -0
  246. /package/runtime/{templates/reports → python/okstra_ctl/phases/project_analysis/report_assets}/project-analysis-input.template.md +0 -0
  247. /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/project_analysis/report_assets}/project-analysis.template.html +0 -0
  248. /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/project_analysis/report_assets}/project-analysis.template.md +0 -0
  249. /package/runtime/{prompts/profiles/release-handoff.json → python/okstra_ctl/phases/release_handoff/profile.json} +0 -0
  250. /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/release_handoff/report_assets}/release-handoff.template.html +0 -0
  251. /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/release_handoff/report_assets}/release-handoff.template.md +0 -0
  252. /package/runtime/python/okstra_ctl/{fanout.py → phases/requirements_discovery/fanout.py} +0 -0
  253. /package/runtime/{prompts/profiles/requirements-discovery.json → python/okstra_ctl/phases/requirements_discovery/profile.json} +0 -0
  254. /package/runtime/{templates/reports → python/okstra_ctl/phases/requirements_discovery/report_assets}/fan-out-unit.template.md +0 -0
  255. /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/requirements_discovery/report_assets}/requirements-discovery.template.html +0 -0
  256. /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/requirements_discovery/report_assets}/requirements-discovery.template.md +0 -0
  257. /package/runtime/{prompts/profiles/technical-verification.json → python/okstra_ctl/phases/technical_verification/profile.json} +0 -0
  258. /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/technical_verification/report_assets}/technical-verification.template.html +0 -0
  259. /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/technical_verification/report_assets}/technical-verification.template.md +0 -0
@@ -22,7 +22,7 @@ Report assembly reads the role-owned inputs, validates them, derives links and s
22
22
  | design-preparation snapshot | design-surface detector | `designPreparationPath` |
23
23
  | final report record | report assembly | `expectedReportRecordPath` |
24
24
 
25
- An active clarification exists only in `activeClarifications[]`. A decision carried from a previous run exists only in `carriedDecisions[]`; do not recreate it as an active question.
25
+ An active clarification exists only in `activeClarifications[]`. A decision carried from a previous run exists only in `carriedDecisions[]`; do not recreate it as an active question. When the user replaces a carried decision in this run, open the new question with `--supersedes <carried C-NNN>`. Once the new row is resolved, report assembly publishes the carried row as `obsolete`, and the next run does not carry it (`scripts/okstra_ctl/report_assembly.py` `_clarifications`, `scripts/okstra_ctl/approval_decisions.py` `seed_carried_decisions`). Without it the replaced answer stays `answered` and is carried next to its replacement.
26
26
 
27
27
  Prepare seeds `carriedDecisions[]` when it creates the ledger: every clarification the run's carry-in record answered or resolved, plus every row that record's user-responses sidecars answered, arrives carried (`scripts/okstra_ctl/approval_decisions.py` `seed_carried_decisions`). The carry-in record is the `--clarification-response` file; for a new plan it is the option-selection record `--selected-direction` names, and for an implementation run the approved plan `--approved-plan` names (`render._carry_in_source`) — the same pointer assembly writes to `clarificationCarryIn.sourceFile`, so the page links those ids to the prior run's page. A carried plan row's `requirementCoverage[].decisionRefs` may still name a `C-NNN` the carry-in record does not answer — a decision from an older run. Carry it before assembly: `okstra approval-decision carry --ledger <approvalDecisionsPath> --from-responses <launch prompt "Clarification Response Carried In" → Source path> --clarification-id C-NNN` — repeat `--clarification-id` to take several in one call. That bundle is the source of truth for an earlier run's answer: it is task-level and cumulative, so no prior run seq has to be located, and each response section names the report that posed the question, which is where the row's `statement`, `expectedForm`, and options come from. A carried row lands as `answered`, not `resolved` — it was resolved in another run, and `resolution.checkRefs` names *this* run's activity rows. Carrying an answer also obliges a `supersessionLedger` entry for it.
28
28
 
@@ -71,7 +71,7 @@ Materialize the duty prompt with `okstra agent-prompt materialize --audience rep
71
71
 
72
72
  The errors sidecar anchor reserves the runtime-owned write-artifact path used by dispatch validation. No model-authored error JSON file is part of report-writer dispatch; failures use the typed error-log command from the worker error contract.
73
73
 
74
- After materialization, generate a v2 jobs file with `okstra agent-prompt jobs --project-root <root> --run-manifest <manifest> --dispatch-kind report-writer --metadata <returned-meta.json> --out <run-state>/report-writer-jobs.json`. Pass the generated file through the selected deterministic dispatcher's `--jobs-file`. The generator reads the narrative and worker-result headers and validates their existing manifest contract. For host-native dispatch, use `okstra agent-prompt record-dispatch` and `link-result`; deterministic dispatchers record their own invocation lifecycle.
74
+ Add `--jobs-out <run-state>/report-writer-jobs.json` to that materialize call: it writes the verified v2 jobs file as `okstra agent-prompt jobs --project-root <root> --run-manifest <manifest> --dispatch-kind report-writer --metadata <returned-meta.json> --out <run-state>/report-writer-jobs.json` would, without a second call. Pass the generated file through the selected deterministic dispatcher's `--jobs-file`. The generator reads the narrative and worker-result headers and validates their existing manifest contract. For host-native dispatch, use `okstra agent-prompt record-dispatch` and `link-result`; deterministic dispatchers record their own invocation lifecycle.
75
75
 
76
76
  When `terminalBackend` is `cmux-pane`, use `okstra team dispatch --project-root <root> --run-manifest <manifest> --jobs-file <jobs-file>`. For a CLI wrapper, use `okstra worker-dispatch --project-root <root> --run-manifest <manifest> --jobs-file <jobs-file>`. Both paths use `okstra team await` to collect completion.
77
77
 
@@ -93,7 +93,7 @@ This section adds report-specific checks to [okstra-lead-contract](./okstra-lead
93
93
  2. The ledger lives at `runs/<task-type>/state/report-writer-corrections-<task-type>-<seq>-a<N>.json` (schema `schemas/report-writer-corrections-v1.0.schema.json`) and holds one entry per defect: `replace` with the exact replacement value (add `current` when you want it checked), `remove` for an item or optional field, `rewrite` with a `rule` when the writer has to re-author prose. Paths use the validator's grammar (`implementationOptionSelection.rankedOptions[1].coverageSummary.coveragePercent`), so a report-assembly refusal can be copied into the ledger verbatim. Never write an indirect instruction such as `use the schema value`, `use the valid status`, or `fix the enum`: a `replacement` is the literal, and a `rule` names the required outcome. You do not copy allowed enum literals by hand — okstra attaches each `rewrite`'s schema constraint from the frozen schema.
94
94
  3. Run `okstra agent-prompt check-corrections --project-root <root> --run-manifest <path> --corrections <ledger>` until it reports no defect. It applies the ledger to a scratch copy of the base narrative and validates the complete proposed narrative against the writer-owned value schema and the task's semantic validator, listing every defect at once. Validating only the edited field is insufficient because one replacement can select a different schema branch, which is why the check covers the whole narrative.
95
95
  4. When the check reports `mechanical: true` and has corrections, run `okstra agent-prompt apply-corrections` with the same arguments: okstra writes the corrected narrative to `reportNarrativePath` and records a `lead-correction-applied` activity row naming the ledger and its correction ids. This includes validated `replace`, `remove`, `add`, `move`, and derived step counts. No writer dispatch, `record-dispatch`, or `link-result` follows; the roster row's result already exists.
96
- 5. Otherwise materialize the writer prompt with the same `--corrections <ledger>` under a new invocation id and prompt path (retire the first attempt's link with `reject-result` as [plan-body-verification](./plan-body-verification.md) describes). okstra renders the correction-only field values, evidence, schema constraints, replacement-file contract, application command, and output paths. Put context in the ledger; the initial instruction body is not sent to the correction writer.
96
+ 5. Otherwise materialize the writer prompt with the same `--corrections <ledger>` under a new invocation id and prompt path (retire the first attempt's link with `reject-result` as `plan-body-verification` (the absolute path in **Okstra Runtime Resources**) describes). okstra renders the correction-only field values, evidence, schema constraints, replacement-file contract, application command, and output paths. Put context in the ledger; the initial instruction body is not sent to the correction writer.
97
97
 
98
98
  A report-writer materialization without `--corrections` whose narrative already exists and parses is refused before any prompt is written — free-form corrections cannot be checked before the writer runs, and four of six re-runs in the 2026-09-03 measurement were lead instructions that contradicted the authoring contract. Only a narrative whose structure does not parse (line grammar, an unknown top-level field) is re-authored, not corrected: that dispatch needs no ledger, and its body quotes the parser's message. Because re-authoring overwrites the live file in place, okstra copies the existing narrative to `worker-results/<narrative-name>.pre-<invocation-id>.md` at materialization and renders a `## Previous Attempt` section naming that copy (**Enforced:** `_preserve_reauthored_narrative` in `scripts/okstra_ctl/agent/prompt_cli/materialize.py`); the 2026-09-09 dev-10642 run lost a 579-line attempt to a failed in-place re-indent command with no copy to fall back on. A narrative that breaks the line grammar is not a produced artifact: the dispatcher settles that attempt as `required worker artifact is unusable: narrative does not parse: …` and retries it inside the same batch, so you see the parser's message at collection, not at Phase 7 assembly (**Enforced:** `okstra_ctl.dispatch_state.unusable_result_defect`, read by `missing_completion_paths` and the `team await` record path). The synthesis packet's Authoring Contract carries the line grammar itself (`report_narrative.NARRATIVE_GRAMMAR_INSTRUCTIONS`), so a writer that reads only the packet still sees it. Value defects — an id outside its pattern, a value outside its enum, a missing required field — leave the structure readable and are exactly what the ledger fixes; the a3 attempt of the 2026-09-03 run carried twenty `SC-` ids that assembly refused and was still a corrective base.
99
99
 
@@ -106,7 +106,7 @@ A report-writer materialization without `--corrections` whose narrative already
106
106
  3. Run initial plan-body verification as round 1.
107
107
  4. Apply at most one automatic planner self-fix to the narrative. Skip this step when `gating` is `false`.
108
108
  5. Run targeted re-verification as round 2 when needed. Skip this step when `gating` is `false`.
109
- 6. Persist the completed `planBodyVerification` value in convergence state. Run `okstra plan-items next-dispatch`: after the single automatic self-fix, settle eligible judgements with `resolve-dissent`; ask the user immediately for decisions outside lead authority. Preserve dissent and do not restart the automatic loop. The exact procedure and enforced authority checks are in `prompts/lead/plan-body-verification.md` step 8.
109
+ 6. Persist the completed `planBodyVerification` value in convergence state. Run `okstra plan-items next-dispatch`: after the single automatic self-fix, settle eligible judgements with `resolve-dissent`; ask the user immediately for decisions outside lead authority. Preserve dissent and do not restart the automatic loop. The exact procedure and enforced authority checks are in `scripts/okstra_ctl/phases/implementation_planning/instructions/plan-body-verification.md` step 8.
110
110
  7. Complete the design-surface detector snapshot: `okstra design-snapshot --narrative <reportNarrativePath> --output <designPreparationPath>`, taking both paths from the run manifest. Nothing else writes that snapshot, and step 8 fails without it — `report_inputs._PLANNING_INPUT_FIELDS` lists `designPreparationPath` as a required planning input.
111
111
  8. Run Phase 7 report assembly.
112
112
 
@@ -129,7 +129,7 @@ For historical schema-v1 Markdown only, the following heading table remains a re
129
129
 
130
130
  **Enforced:** `okstra_ctl.report_finalize.V3_STEP_ORDER` is the order — `report-finalize` runs the steps from that tuple, so the sequence cannot be reordered by a caller. Running the steps by hand is what this rule forbids, and that path is not reachable through the CLI.
131
131
 
132
- Do not run the nine steps below manually. Invoke `okstra report-finalize`; contract 3.0 runs them in this order:
132
+ Do not run the eleven steps below manually. Invoke `okstra report-finalize`; contract 3.0 runs them in this order:
133
133
 
134
134
  1. **`token-usage`** — collect usage into team state without touching the final record.
135
135
  2. **`project-activity`** — report assembly validates every owner input and publishes the final record once.
@@ -137,9 +137,11 @@ Do not run the nine steps below manually. Invoke `okstra report-finalize`; contr
137
137
  4. **`translate`** — for a non-English `reportLanguage`, materialize and dispatch the translator worker and require its `*.i18n.<lang>.json` sidecar; a no-op for English or when the sidecar already exists.
138
138
  5. **`render-views`** — render the Markdown reading copy and human HTML, with the translation sidecar overlaid.
139
139
  6. **`spawn-followups`** — materialize registered follow-up tasks.
140
- 7. **`validate-run`** — validate the record, views, run manifest, and team state.
141
- 8. **`record-group-memory`** — write this run's conclusion (headline, decisions, watch-outs, open follow-ups, record path, next phase) and the group's start order into the task-group's `group-context.md` okstra region, creating the file when the group has none; skipped, like teardown, when an earlier step failed. Sibling tasks read it as `## Task-Group Memory`.
142
- 9. **`teardown-stages`** — remove eligible stage worktrees after successful validation.
140
+ 7. **`record-verified`** — for a final-verification whose verdict clears the work for release, run `okstra handoff record-verified` once per stage in `finalVerification.stageReports`, so the `verified` rows exist before validation reads them; a no-op for other task types and for a verdict that blocks release. Do not run `handoff record-verified` by hand.
141
+ 8. **`validate-run`** — validate the record, views, run manifest, and team state.
142
+ 9. **`record-group-memory`** — write this run's conclusion (headline, decisions, watch-outs, open follow-ups, record path, next phase) and the group's start order into the task-group's `group-context.md` okstra region, creating the file when the group has none; skipped, like teardown, when an earlier step failed. Sibling tasks read it as `## Task-Group Memory`.
143
+ 10. **`teardown-stages`** — remove eligible stage worktrees after successful validation.
144
+ 11. **`prune-run-artifacts`** — remove every `node_modules` and `.next` directory under the run directory, and the dispatch snapshots (`*.mutation-audit.json`) and publication locks (`*.publish.lock`) recorded by a run whose validation passed or by an earlier run in the same run directory as a passed run; it runs even after a failed step.
143
145
 
144
146
  After `report-finalize` returns with `ok: true`, the lead closes the run with the launch prompt's User closeout. A generated HTML file alone does not establish successful validation.
145
147
 
@@ -5,7 +5,7 @@
5
5
  - When verifying worker team composition and operational rules
6
6
  - When applying model assignment rules
7
7
 
8
- **Not applicable to `release-handoff`** — that profile is lead-only and intentionally has no `Required workers:` block (see `prompts/profiles/release-handoff.md`). The worker-dispatch contract in this document does not engage during `release-handoff` runs.
8
+ **Not applicable to `release-handoff`** — that profile is lead-only and intentionally has no `Required workers:` block (see `scripts/okstra_ctl/phases/release_handoff/profile.md`). The worker-dispatch contract in this document does not engage during `release-handoff` runs.
9
9
 
10
10
  ## Team Structure
11
11
 
@@ -1,15 +1,15 @@
1
1
  - every `Kind=decision` clarification row is recorded by the lead in the approval decision ledger — one `okstra approval-decision open --ledger <approvalDecisionsPath>` call per row, before report assembly runs. Assembly reads `clarificationItems[]` from that ledger and from nowhere else, so a decision that exists only as narrative prose reaches no reader and no answer channel: `okstra user-response` cannot offer a row the ledger never carried, and the HTML prints "No further decision is needed" over the top of it. Each option is an object with eight fields:
2
2
  - `role` — `recommended` for the single best answer, `alternative` for the rest. Exactly one option per row is `recommended`.
3
3
  - `answer` — the choice itself, phrased so the user can pick it as-is. Keep it to a short phrase (roughly 120 characters); the reasoning and the consequences have their own fields below.
4
- - `rationale` — one sentence on why this option is on the board.
4
+ - `rationale` — why this option is on the board, as long as the reason needs.
5
5
  - `reach` — exactly one of `in-repo` or `cross-repo`.
6
6
  - `scopeEffects` — optional tokens drawn from `{new-schema, deferrable}`.
7
- - `addedWork` — one sentence naming the work this choice creates that the other choices do not. Name the files, stages, or commands; do not substitute a cost adjective.
8
- - `directionChange` — one sentence naming what this choice reverses: an approved plan item, a recorded decision, an earlier answer. Name that item. When it reverses nothing, say so.
7
+ - `addedWork` — the work this choice creates that the other choices do not. Name the files, stages, or commands; do not substitute a cost adjective.
8
+ - `directionChange` — what this choice reverses: an approved plan item, a recorded decision, an earlier answer. Name that item. When it reverses nothing, say so.
9
9
  - `disposition` — the effect of selecting the option. Use `select` for `user-decision`. Use `accept-risk` on any classification, including `correctness-critical`, when the user ends the gate and leaves the DISAGREE on the record. Use `request-revision` or `reject` when the option sends the plan back.
10
10
  - report assembly derives `approvalContext`, status, and resolution. `approvalContext` contains only `classification`, `unblockCondition`, and `recommendedDisposition`; it never copies plan or activity identifiers.
11
11
  - a `C-NNN` you name outside the row itself must be a row that exists. One place is checked: a `blocked` `endStateCoverage` row's `blockedBy.ref`, when its `kind` is `clarification` — see each phase profile's `blockedBy` rule and `validators/validate-run.py` `_validate_end_state_blocked_by`. Everywhere else — `coveredBy`, `rationale`, `verdictCard.nextStep`, `finalVerdict.nextStep`, `humanSummary.actions[]`, `recommendedNextSteps[].text` — is free prose and stays uncheckable: a shipped report legitimately writes `C-057 through C-068 are applied or carried` or `C-201 does not apply`, and a validator scanning those fields for ids would fail 15 of the 56 reports on disk. There it is on you not to send a reader after an id with no row. An id an earlier run already answered reaches this report as a carried decision — prepare seeds `carriedDecisions[]` from the run's carry-in record, and `okstra approval-decision carry` admits one that record does not answer — never by citing it bare. `crossVerification` rows are numbered `CV-NNN` so a `C-NNN` has exactly one meaning.
12
- - the three impact fields answer three different questions — how far the change reaches, what new work it creates, and what it overturns. Someone choosing between options needs all three, so never fold them into one sentence: whichever axis is easiest to write would silently stand in for the other two.
12
+ - the three impact fields answer three different questions — how far the change reaches, what new work it creates, and what it overturns. Someone choosing between options needs all three, so never fold them into one field: whichever axis is easiest to write would silently stand in for the other two.
13
13
  - a row that omits `options[]`, offers fewer than two, or marks zero or two options as `recommended` is incomplete and must be completed before the report is finalised.
14
14
  - `expectedForm` states only the *shape* of the answer — one of the options, a file path, a number, a date. It never lists the choices again; two sources for one fact leave consumers disagreeing about which is authoritative.
15
15
  - **Enforced:** `scripts/okstra_ctl/approval_decisions.py`, `schemas/final-report-v3.0.schema.json`, and `scripts/okstra_ctl/report_assembly.py`.
@@ -16,7 +16,7 @@ prompt through `prepare_agent_invocation()` before `worker-dispatch`.
16
16
  Load the applicable coding conventions for every language the diff will touch, then state in ONE line which conventions apply (e.g. `Applying TS + hexagonal overlay; domain at src/domains/*/domain/`). Lint/test green is necessary but NOT sufficient — self-mocked tests, interaction-only assertions, and untruthful names all pass a green pipeline; this gate is what keeps them out of the diff.
17
17
 
18
18
  - **Resource selection — read the routed pack, never inline it here.** Use this worker prompt's `**Coding preflight pack:**` anchor header as the absolute path to the installed routed pack. Detect each touched file's language and framework from its extension or project manifest (`package.json`, `Cargo.toml`, `pyproject.toml`, `pom.xml`, `build.gradle*`, `prisma/schema.prisma`), then read that pack's resources via the Read tool by absolute path. Always read `overview.md` (the router) + `clean-code.md`, then select per the router's three ordered stages — Stage 1 language → `languages/<lang>.md`, Stage 2 framework → `frameworks/<fw>.md` (e.g. `frameworks/node-server.md` for server-side Node), Stage 3 architecture → `architectures/<arch>.md` (e.g. `architectures/hexagonal.md` for ports-and-adapters / NestJS-hex). Each stage is a list of rules; include EVERY matching resource (a change set can touch multiple languages/frameworks/architectures) — do not stop at the first match. These files are runtime resources, not Skill-tool skills, so always read them by path.
19
- - **Project policy projection:** before selecting resources, run `okstra model-io project-context --project-root <PROJECT_ROOT> --task-ref <task-ref>`. Consume its `Architecture style`, `Project Review Rule Packs`, and `Project QA Commands` sections; do not open Okstra-owned JSON storage.
19
+ - **Project policy projection:** before selecting resources, run `okstra model-io project-context --project-root <PROJECT_ROOT> --task-ref <TASK_KEY>` (the full `Task key` your dispatch prompt names). Consume its `Architecture style`, `Project Review Rule Packs`, and `Project QA Commands` sections; do not open Okstra-owned JSON storage.
20
20
  - **Declared architecture style — an authoritative Stage 3 input, and it binds.** A projected `hexagonal` selects `architectures/hexagonal.md` even when none of Stage 3's layout signals matched, so the declaration — not the directory shape — decides. A projected `layered` has no pack resource; its invariant applies from this line: dependencies run one direction only — an upper layer may import a lower one, never the reverse — and a variation point is extracted onto a layer boundary. A declared style makes this overlay binding rather than advisory, and which rule binds follows the style: under `hexagonal` the overlay's otherwise-advisory concrete-adapter item is blocking, so a service dependency you add or modify goes through a port instead of a concrete implementation and that placement violation is fixed before the write rather than recorded as a note; under `layered` what binds is the direction invariant just stated — your own judgement over the import list of every file the diff touches, plus extracting a variation point onto a layer boundary — while the concrete-adapter item stays advisory, since `layered` has no ports to route it through. An absent or `none` projected style leaves Stage 3 detection-driven and its overlay advisory. The verifier re-grades the same diff under the same declaration (`_implementation-verifier.md` → Static design & test-quality review), so a placement violation missed here returns as a verdict `FAIL`.
21
21
  - **Project review rule packs:** a pack applies when either source names it — the task brief's `Source Material` / `Reporter Confirmations` cites its exact `SKILL.md` path, or the project-context projection lists it as a standing standard. The two sources are a union. Read only those files and the `references/*.md` files they directly name; a declared path that will not open is recorded as `project-review-rules: declared <path> unreadable`, never silently dropped. Do not search parent directories or host skill catalogs. Apply those rules during implementation as a prevention pass, not a PR-comment generation workflow: do not dispatch reviewer subagents from the executor. For Fonts Ninja-style PR review packs, the executor must avoid newly introduced duplicate helper stacks, tautological tests that merely re-call the delegated helper, self-mocking, domain rules in adapters/ports, domain objects outside `domain/`, dead APIs, weak public names, and functions that fail the plain-English read.
22
22
  - **Language-agnostic principles that ALWAYS bind (the TDD loop MUST satisfy them):** (1) no self-mocking of the SUT — stub/spy only injected collaborators, never the subject's own methods; (2) behavioral assertions on outcomes (return value, state, persisted rows, events, boundary calls) — never `toHaveBeenCalled*` on an internal helper as the only/primary assertion; (3) truthful names — a `get*` / `find*` that writes/inserts, or a name encoding the caller's use-case (`*ForInit`) or hiding a domain rule (`findValid*`), is a defect; (4) single-purpose functions ≤50 effective lines, plain-English readability. Self-mocking (1) — Enforced by `validators/detect_self_mock.py` (static), which the implementation **verifier** runs; it is never delegated to the executor (`_implementation-verifier.md` §"Self-mock detection"). Naming the enforcement here says who will check your diff, not that you should run the check: the executor's half is satisfying principle (1) in the code it writes, and it MUST NOT invoke the detector or write `<task_root>/qa/self-mock-*.json`. **Enforced:** that sidecar is not among the paths an executor attempt's `writePolicy.artifactPolicy.allowedPaths` carries, so writing it closes an otherwise-passing stage as `error` with `artifact-root change exceeds batch policy union` (`scripts/okstra_ctl/execution_mutation_audit.py`). The sidecar's absence BLOCKS at `validate-run.py` on the verifier's report.
@@ -5,7 +5,7 @@ Edit here once; every profile picks the change up at next render. Do NOT
5
5
  add phase-specific rules to this file — phase rules stay in the per-
6
6
  profile document.
7
7
  -->
8
- - Team contract (shared): roster roles, model-assignment rules, dispatch invariants, and required-worker attempt rules are canonical in the team contract (`prompts/lead/team-contract.md`). Two consequences every phase honours: the host-native Okstra lead is synthesis-only (in `implementation`, distinct from the `Executor` and verifiers), and unnamed generic parallel workers never replace or extend the per-profile `Required workers:` roster. Prep-time model recommendations come from the catalog defaults in `okstra_ctl.models` (for example, `Codex worker` → `gpt-6-sol`); at dispatch time the task-manifest's materialized assignment is the only source — there is no dispatch-time fallback.
8
+ - Team contract (shared): roster roles, model-assignment rules, dispatch invariants, and required-worker attempt rules are canonical in the team contract (`prompts/lead/team-contract.md`). Two consequences every phase honours: the host-native Okstra lead is synthesis-only (in `implementation`, distinct from the `Executor` and verifiers), and unnamed generic parallel workers never replace or extend the per-profile `Required workers:` roster. Prep-time model recommendations come from the catalog defaults in `okstra_ctl.models` (for example, `Codex worker` → `gpt-6.1-sol`); at dispatch time the task-manifest's materialized assignment is the only source — there is no dispatch-time fallback.
9
9
  - Worker interaction model (shared — read before inferring behaviour from the roster):
10
10
  - the per-profile `Required workers:` block is a **roster**, not a behaviour contract. Each role's interaction mode changes across operating phases of the same run.
11
11
  - **Phase 4 / 5 (independent analysis)**: every analyser in the resolved provider assignment roster produces findings independently and has no access to another worker's output. `report-writer` does not analyse.
@@ -91,7 +91,7 @@ profile document.
91
91
  - if a schema-v1 table or an analysis-worker result table requires a recommended answer, alternatives, or an evidence-check note, encode it inside the existing 4-column schema: put evidence notes in `Statement` as `Evidence checked: <path:line>` or `Evidence checked: none — <human-only reason>`, and put recommendations/options in `Expected form` as `Recommended: (a) <answer> — <rationale>; Alternatives: (b) <option> (c) <option>`. The recommended answer is always the first option and MUST carry the `(a)` label; alternatives continue the same letter sequence from `(b)` (a lone alternative is `(b) <option>`, never restart at `(a)`), so the full option set reads `(a) (b) (c) …` in order and renders each as its own selectable option. Do **not** append a pick-one answer-space summary such as `(pick 1 of A / B)` or `(pick N of …)` to `<options>` — the rendered `<select>` already enforces single choice, and that annotation leaks verbatim into an option label. Do not add `Recommended`, `Evidence`, `Alternatives`, or `evidence-checked` columns, and do not break the merged record-meta cell back into separate columns.
92
92
  - For schema v2, data.json is canonical and the HTML exports answers to a user-response sidecar; the source report is never edited. `--resume-clarification` carries those answers into the next run. The lower-level `--clarification-response <path>` remains available for scripted runs.
93
93
  - When a response is carried in, reconcile every prior `clarificationItems[]` row against new evidence and update its status to `resolved` or `obsolete` before issuing the next verdict. Schema-v1 compatibility Markdown may additionally render its conditional Section 0; the schema-v2 full reading copy records decisions under `## Clarification and User Decisions`.
94
- - **Supersession (BLOCKING).** Reconciling the `C-*` row is only half of incorporating an answer. An answer does not merely *add* a decision — it *invalidates* whatever the previous run wrote under the opposite assumption. Before issuing the next decision, walk the prior deliverable prose for every statement the answer makes false and **delete or rewrite it**, then record the retirement. Adding the new decision while leaving the contradicting sentence in place puts two opposite instructions for the same symbol in one document; the implementer must then guess which is live, and the next verification round correctly blocks on it. In `implementation-planning` this record is `implementationPlanning.supersessionLedger[]` — one entry per answered clarification, either `disposition: superseded` (with the retired statement, its replacement, and the sections revised) or `disposition: no-dependent-statement` (with a rationale). A plan built from a selected direction inherits the answers the option-selection record carried before it has any statement to retire, so those carried rows need no entry; the rows this plan itself raised and settled still do. **Enforced:** `validators/validate-run.py` `_validate_supersession_ledger` requires an entry per answered clarification, exempting the ledger's `carriedDecisions[]` ids on a selected-direction plan; whether the claim is *true* is what the §5.5.9 adversarial round tests.
94
+ - **Supersession (BLOCKING).** Reconciling the `C-*` row is only half of incorporating an answer. An answer does not merely *add* a decision — it *invalidates* whatever the previous run wrote under the opposite assumption. Before issuing the next decision, walk the prior deliverable prose for every statement the answer makes false and **delete or rewrite it**, then record the retirement. Adding the new decision while leaving the contradicting sentence in place puts two opposite instructions for the same symbol in one document; the implementer must then guess which is live, and the next verification round correctly blocks on it. In `implementation-planning` this record is `implementationPlanning.supersessionLedger[]` — one entry per answered clarification, either `disposition: superseded` (with the retired statement, its replacement, and the sections revised) or `disposition: no-dependent-statement` (with a rationale). A plan built from a selected direction inherits the answers the option-selection record carried before it has any statement to retire, so those carried rows need no entry; the rows this plan itself raised and settled still do. **Enforced:** `scripts/okstra_ctl/phases/implementation_planning/plan_body.py` `_validate_supersession_ledger` requires an entry per answered clarification, exempting the ledger's `carriedDecisions[]` ids on a selected-direction plan; whether the claim is *true* is what the §5.5.9 adversarial round tests.
95
95
  - Verdict Card data consistency (shared; schema-v1 Markdown keeps the legacy visible card):
96
96
  - The Card carries no verdict token — the token lives once, in `finalVerdict.verdictToken`, and every gate reads it there. `verdictCard.direction` byte-matches `finalVerdict.direction`; next-step routing agrees with `recommendedNextSteps[0]`. The full reading copy and human summary are derived from the data fields without repeating both visible sections. **Enforced in part:** the v3.0 schema's `verdictCard` is `additionalProperties: false` with no verdict-token property, so the token cannot be duplicated onto the Card, and `scripts/okstra_ctl/report_narrative.py` `writer_owned_schema` applies the finished report's `$defs.Direction` enum to the narrative, rejecting an off-enum `direction` while the writer can still be re-run. The byte-match between the two `direction` fields is not compared by anything — assembly overwrites `nextStep` on both when the plan-body gate passes (`scripts/okstra_ctl/report_assembly.py:590-604`) but leaves `direction` as the writer wrote it.
97
97
  - Cross-worker traceability (shared — applies to every analysis worker output and to the lead's `## 6.` / `## 2.` tables in the final-report):
@@ -14,4 +14,4 @@ mode:" when the include directive (placed at column 0) is resolved in-place.
14
14
  Do NOT write the literal include directive token in this file's body — the
15
15
  resolver matches it anywhere and would recurse on this file itself.
16
16
  -->
17
- - **Coverage critic (opt-in, one slot)**: critic `min` is 0 and `recommended`/`max` are 1 — the wizard asks whether to add the slot with 1 recommended, and the user picks the model when they add it (`--role-model critic=<provider>/<model>` or the wizard role-model step). `--critic off` and a 0-count selection are both accepted; the run then dispatches no critic pass, and an analyser 1-1 tie stays `needs-reverify` with no slot to settle it — `okstra plan-items next-dispatch` answers `user-decision` for those items and the lead opens an approval decision instead of another round. A reused-worker critic pass is dispatched concurrently with the first convergence reverify round to surface **both** findings nobody covered and work the findings propose that no requirement asked for (`category: "unrequested-scope"`); its candidates are judged only after a 1-round adversarial reverify that follows convergence. The two halves are disposed of differently — a contested coverage gap is dropped as a hallucination, while a contested over-scope candidate is recorded as a `## 5. Missing Information and Risks` row instead of vanishing. In `implementation-planning`, the same critic slot also settles plan-body 1-1 splits (`critic-worker` on `--tie-vote` items only). See `prompts/lead/convergence.md` "Coverage critic pass" and `prompts/lead/plan-body-verification.md` even-split rule.
17
+ - **Coverage critic (opt-in, one slot)**: critic `min` is 0 and `recommended`/`max` are 1 — the wizard asks whether to add the slot with 1 recommended, and the user picks the model when they add it (`--role-model critic=<provider>/<model>` or the wizard role-model step). `--critic off` and a 0-count selection are both accepted; the run then dispatches no critic pass, and an analyser 1-1 tie stays `needs-reverify` with no slot to settle it — `okstra plan-items next-dispatch` answers `user-decision` for those items and the lead opens an approval decision instead of another round. A reused-worker critic pass is dispatched concurrently with the first convergence reverify round to surface **both** findings nobody covered and work the findings propose that no requirement asked for (`category: "unrequested-scope"`); its candidates are judged only after a 1-round adversarial reverify that follows convergence. The two halves are disposed of differently — a contested coverage gap is dropped as a hallucination, while a contested over-scope candidate is recorded as a `## 5. Missing Information and Risks` row instead of vanishing. In `implementation-planning`, the same critic slot also settles plan-body 1-1 splits (`critic-worker` on `--tie-vote` items only). See `prompts/lead/convergence.md` "Coverage critic pass" and `scripts/okstra_ctl/phases/implementation_planning/instructions/plan-body-verification.md` even-split rule.
@@ -1,100 +1,6 @@
1
1
  {
2
- "requirements-discovery": [
3
- "source code edits of any kind",
4
- "implementation planning or detailed design beyond what is required to choose the next phase",
5
- "executing builds, migrations, deployments, or any state-mutating command",
6
- "starting `error-analysis`, `implementation-planning`, or `implementation` inside this run (each must be a separate run, and `implementation` additionally requires an approved `implementation-planning` deliverable)"
7
- ],
8
- "improvement-discovery": [
9
- "source code edits of any kind",
10
- "implementation planning, root-cause analysis, builds, migrations, or deployments",
11
- "starting `implementation-planning`, `implementation`, `error-analysis`, or any other lifecycle phase inside this run",
12
- "generating candidates outside the lens whitelist (Lens enum violation rejects the report)",
13
- "exceeding the candidate cap (absolute cap 12)",
14
- "free external data fetch beyond the brief's Source Material or Phase 1.5 resolved scope",
15
- "interpreting user phrases like `다음 단계 진행해` as authorisation to enter another phase"
16
- ],
17
- "project-analysis": [
18
- "source or configuration edits",
19
- "tests, builds, migrations, or deployments",
20
- "starting any other lifecycle phase inside this run"
21
- ],
22
- "feature-analysis": [
23
- "source or configuration edits",
24
- "tests, builds, migrations, or deployments",
25
- "starting any other lifecycle phase inside this run"
26
- ],
27
- "change-impact-analysis": [
28
- "source or configuration edits",
29
- "tests, builds, migrations, or deployments",
30
- "starting any other lifecycle phase inside this run",
31
- "implementation alternatives",
32
- "file change specifications",
33
- "stepwise execution plans"
34
- ],
35
- "error-analysis": [
36
- "source code edits, refactors, or fix attempts",
37
- "implementation design or planning artifacts",
38
- "executing builds, migrations, deployments, or any state-mutating command",
39
- "starting `implementation-planning` or `implementation` inside this run (each must be a separate run, and `implementation` additionally requires an approved `implementation-planning` deliverable)"
40
- ],
41
- "implementation-option-selection": [
42
- "source or configuration edits, refactors, or fix attempts",
43
- "tests, builds, migrations, deployments, or any state-mutating command",
44
- "detailed file lists, stage maps, execution commands, or plan approval",
45
- "starting `implementation-planning` or `implementation` inside this run",
46
- "displaying more than three merged candidates or omitting rejected-candidate audit records"
47
- ],
48
- "implementation-planning": [
49
- "source code edits of any kind (Edit/Write on project source files is forbidden)",
50
- "file writes outside the run`s artifact directories (`reports/`, `prompts/`, `state/`, `manifests/`, `worker-results/`, `status/`, `sessions/`), including task-root QA scripts, manifest, and tsconfig (planning declares conformance commands and required dependencies; implementation writes these files); in particular, do not write to `docs/superpowers/specs/` or `docs/superpowers/plans/`",
51
- "executing builds, migrations, deployments, or any state-mutating command",
52
- "starting `implementation` inside this run (must be a separate run authorised by an approved deliverable from this phase), even if the user says \"다음 단계 진행해\"",
53
- "dispatching parallel sub-agents beyond the required worker roster (okstra owns worker fan-out)",
54
- "leaving placeholders such as TBD / TODO / \"handle edge cases\" / \"similar to Option N\" in the report",
55
- "delegating the self-review pass — the Okstra lead must run it"
56
- ],
57
- "implementation": [
58
- "any Edit/Write or state-mutating Bash before the pre-implementation gate passes (gate requires --approved-plan pointing to a final-report.md whose frontmatter has `approved: true`)",
59
- "`git push` of any kind (including `--dry-run` against a real remote that produces side-effects), `npm publish` / `cargo publish` / `pip publish`, `gh release`, `docker push`",
60
- "real database migrations, schema changes against shared environments, or writes to non-local datastores",
61
- "production credentials, deploy commands, infra mutation (`terraform apply`, `kubectl apply` against non-local cluster, etc.)",
62
- "external API write calls (POST/PUT/PATCH/DELETE) to third-party services other than localhost test fixtures",
63
- "source edits or Bash mutations performed by any verifier role (`Antigravity verifier`, `Codex verifier`, `Claude verifier` are read-only — recommend, do not apply)",
64
- "dispatching parallel sub-agents beyond the required worker roster",
65
- "silent scope expansion: every file edited outside the approved plan list MUST appear in the `Out-of-plan edits` block with rationale",
66
- "leaving placeholders such as TBD / TODO / \"implement later\" / \"handle edge cases\" in newly-added lines of this run (check via `git diff <base>..HEAD | grep -E '^\\+[^+].*\\b(TBD|TODO|FIXME|XXX|implement later|handle edge cases|similar to|placeholder)\\b'`; pre-existing strings in untouched regions are out of scope)",
67
- "lead substituting its own verdict when every verifier present in the resolved roster returned a non-result terminal status (`timeout`/`error`/`not-run`); in that case the run MUST end as `blocked` with routing recommendation back to `error-analysis`, never with a lead-only verdict",
68
- "declaring overall task acceptance — that is `final-verification` ownership; this phase reports only \"ready for final-verification\" or \"needs new planning loop\"",
69
- "delegating the self-review pass — the Okstra lead must run it"
70
- ],
71
- "final-verification": [
72
- "source code edits, follow-up bug fixes, or scope expansion",
73
- "state-mutating commands against the project or shared environments; permitted mutations are limited to the run's own `.okstra` artifacts (reports, state, `<task_root>/qa/result-*.json` sidecars, `okstra handoff record-verified` on acceptance) and Tier3 conformance scripts that mutate only their qaEnv replica datastore — everything else is read-only execution of pre-existing test or validation commands",
74
- "starting any follow-up phase inside this run; record findings and end the run"
75
- ],
76
- "release-handoff": [
77
- "entering this phase when the cited final-verification `Verdict Token` is `conditional-accept` or `blocked`, or when no final-verification report is cited",
78
- "local commit commands of any kind (`git add`, `git commit`, `git restore --staged`, `git stash`), and any direct `git merge` / `git rebase` / `git rebase --onto` / `git cherry-pick` / `git commit --amend` run by the lead. The single exception is the merge commits `okstra handoff pr-plan` itself creates on a `merge-base` branch — the lead never merges by hand. Rewriting a stage branch breaks the PR stack that sits on it.",
79
- "any git push variant that rewrites remote history, regardless of intent or whether the user said \"force it\": `git push --force`, `git push --force-with-lease`, `git push -f`, `git push +<refspec>`, or any other history-rewriting invocation",
80
- "pushing directly to a release base branch — i.e. `git push origin <branch>` where `<branch>` is `main`, `master`, `prod`, `preprod`, `staging`, `dev`, or the branch the user chose as the release base in this run. The only permitted push targets are the branches `okstra handoff pr-plan` listed for this run (each stage `head_branch`, and any `merge-base` branch).",
81
- "bypassing repo safeguards: `--no-verify` / `-n` on `git push`, bypassing GPG signing, disabling safeguards via equivalent flags, or any hook bypass.",
82
- "release-publishing commands: `gh release create`, `gh release edit`, `npm publish`, `cargo publish`, `pip publish`, `twine upload`, `docker push`, `terraform apply`, `kubectl apply` against any non-local cluster.",
83
- "source-code edits, refactors, or any modification to files outside the run's own artifact directories (`reports/`, `prompts/`, `state/`, `manifests/`, `worker-results/`, `status/`, `sessions/`). The diff being shipped MUST be exactly what the prior `implementation` run produced; release-handoff packages it, it does not re-author it.",
84
- "executing any mutating command the user did NOT select. Examples: opening a PR when the user picked `local checkout`; pushing when the user picked `skip`; switching the release base branch silently after the user already chose one; opening a PR for a stage outside `HANDOFF_STAGES`.",
85
- "squash-merging, or instructing anyone to squash-merge, a stage PR — and `gh pr merge` in any form. A squash replaces the commits the next stage's PR base points at, so the stack breaks; the PR body states merge-commit-or-rebase and the lead never merges.",
86
- "retrying a failed git / gh command with weaker safety flags. If `git push` fails with non-fast-forward, the lead MUST stop, explain the failure to the user, and ask for instructions — it MUST NOT add `--force`.",
87
- "worker dispatch of any kind, or any other parallel sub-agent fan-out. This phase runs entirely under the Okstra lead.",
88
- "silently treating an unrecognised user reply as one of the menu options. If the user's answer does not match a presented choice, re-ask the question verbatim."
89
- ],
90
2
  "unknown": [
91
3
  "any action that belongs to a different lifecycle phase",
92
4
  "source code edits or state-mutating commands unless this task type explicitly authorises them"
93
- ],
94
- "technical-verification": [
95
- "source edits or installs in the project checkout, task worktree, or another worker's experiment copy",
96
- "production credentials, remote writes, deployments, migrations, publishing, commits or merging experiments into product branches",
97
- "marking candidates feasible, selecting a direction, approving a plan, or declaring task acceptance",
98
- "starting another lifecycle phase inside this run; return the evidence to implementation-option-selection"
99
5
  ]
100
6
  }
@@ -391,7 +391,8 @@
391
391
  "__free_input__": "직접 입력"
392
392
  },
393
393
  "labels": {
394
- "siblings": "같은 group 의 task-id 사용: {snippet}"
394
+ "siblings": "같은 group 의 다른 task 전부 사용: {snippet}",
395
+ "siblings_count": " — 총 {count}개"
395
396
  },
396
397
  "echo_suffixes": {
397
398
  "skip": "related-tasks: (none)",
@@ -81,7 +81,7 @@ Render every numbered item as its option label followed by its description verba
81
81
  | `await_workers` | Await native host workers through the host primitive and CLI workers through their status sidecars, then verify terminal state and Result Paths. |
82
82
  | `redispatch_worker` | Materialize and verify a fresh invocation, then start a fresh native worker or deterministic `worker-dispatch` attempt according to the persisted runner. |
83
83
  | `shutdown_workers` | Perform host or process cleanup only for resources owned by this run. |
84
- | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
84
+ | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint the command performing that step does not record itself (the lead contract "Progress reporting" lists the ones `team dispatch`, `team await`, `team reclaim`, `worker-dispatch` and `report-finalize` record; emit the `PROGRESS:` lines they print instead) and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
85
85
  | `collect_usage` | Collect host- or artifact-backed usage through the existing Okstra token-usage path; do not substitute another runtime's session log. |
86
86
 
87
87
  ## Antigravity dispatch details
@@ -162,7 +162,7 @@ The `confirm` prompt's `label` is the selection summary (one line per resolved i
162
162
  | `await_workers` | Arm one background shell poll for the pending Result Paths; the spawn acknowledgement is not completion. |
163
163
  | `redispatch_worker` | Materialize and verify a fresh invocation, then use a fresh native `Agent(...)` session or `okstra worker-dispatch` attempt according to the persisted runner. |
164
164
  | `shutdown_workers` | For each confirmed-complete worker selected for cleanup, send `SendMessage(to: <name>, message: { type: "shutdown_request" })` to idle the roster member **and** call `TaskStop(task_id: "<name>")` to stop its background task. Both are required; neither subsumes the other. |
165
- | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`, including activity-contract-v1 records. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
165
+ | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`, including activity-contract-v1 records. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint the command performing that step does not record itself (the lead contract "Progress reporting" lists the ones `team dispatch`, `team await`, `team reclaim`, `worker-dispatch` and `report-finalize` record; emit the `PROGRESS:` lines they print instead) and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
166
166
  | `collect_usage` | Run `okstra token-usage` against the team-state; it reads the run-scoped `~/.claude/projects` session JSONL evidence. |
167
167
 
168
168
  ## Dispatch variants
@@ -190,7 +190,7 @@ The `confirm` prompt's `label` is the selection summary (one line per resolved i
190
190
  ### Reverify, critic, and report-writer assignments
191
191
 
192
192
  - For convergence reverify, consume the persisted round plan exactly. This adapter may map and transport each returned batch, but it cannot change batch membership and does not classify findings or branch on task type, provider, or model identity.
193
- - Reverify dispatch materializes `reverification-worker`, verifies its metadata, then uses a fresh one-shot native call named `<workerId>-worker-reverify-r<N>` or a fresh deterministic `worker-dispatch` attempt according to the persisted runner.
193
+ - Reverify dispatch materializes `reverification-worker` for every worker of the round in one `materialize --batch` call (convergence "Invocation materialization gate"), verifies its metadata, then uses a fresh one-shot native call named `<workerId>-worker-reverify-r<N>` or a fresh deterministic `worker-dispatch` attempt according to the persisted runner.
194
194
  - Critic dispatch uses `name: "<provider>-worker-critic"`, `dispatchKind: "critic"`, and the exact mapped model from `config.critic.modelExecutionValue`. If that value cannot be mapped, record `critic-skipped: model-unresolved` and do not dispatch.
195
195
  - Report-writer dispatch uses `name: "report-writer"` only for a native Claude assignment and passes `hostModelValue`. A CLI assignment goes through `worker-dispatch` with `modelExecutionValue`.
196
196
  - Each variant persists its prompt path, Result Path, worker-results path, error paths, and `dispatchKind` before dispatch. Completion uses the shared background Result Path poll; an Agent acknowledgement never completes the variant.
@@ -223,9 +223,9 @@ The `confirm` prompt's `label` is the selection summary (one line per resolved i
223
223
 
224
224
  - At run start, record `teamName` as the audit label in team-state and populate `lead.sessionId`; the session transcript lives under `~/.claude/projects/<encoded-cwd>/<sessionId>.jsonl`. You do NOT write `teamCreate`: `okstra team dispatch` records the implicit-team marker (`{ attempted: false, status: "implicit" }`) itself, on every dispatch path, because v2.1.178 made that value a constant rather than a judgment. The one marker that IS yours is the concurrent-run decision — a concurrent run records `teamCreate: { attempted: false, status: "skipped", reason: "concurrent-run" }` **before** the first dispatch, and dispatch then leaves it alone.
225
225
  - Collect and persist token usage before any live-roster cleanup, including cleanup between batches and the run-end shutdown sequence.
226
- - Before each new worker batch (and before the next phase's render-bundle), close the panes of the dispatches that finished in the prior round, in two passes. First count: `okstra team reclaim --project-root "<PROJECT_ROOT>" --run-manifest "<RUN_MANIFEST_PATH>" --dry-run` closes nothing and prints one `<paneId>\t<kind>` line per pane it would close — count those lines as `<n>`. Then run the same command **without** `--dry-run` to close them, and emit the neutral contract's `PROGRESS: phase-batch-cleanup panes=<n>` checkpoint with that count. Call both passes after collecting that round's results and token usage and before the next dispatch. The command reads each dispatch's recorded status, so an in-progress worker keeps its pane whichever moment you call it — you do not scope the pass by hand. It closes only the panes okstra opened and recorded; a pane the harness opened for itself carries no recorded id and is not okstra's to close. A `cli-wrapper` run holds no pane at all, so `<n>` is `0` — still emit the checkpoint.
227
- - Reclaiming a pane does not stop the worker's background task. Every `dispatch_worker` Agent runs with `run_in_background: true`, so a worker whose result is already collected stays a live background task for the rest of the session — that residue is what fills the harness's exit-time `Background work is running` list. At the same batch boundary, right after the pane reclaim, call `TaskStop(task_id: "<name>")` once per worker of the completed batch, passing the exact `name` used at dispatch (`<workerId>-worker`, `<workerId>-worker-reverify-r<N>`, `<provider>-worker-critic`, `report-writer`). Stop only workers whose results were already collected — never an in-flight worker, never the lead, and keep `report-writer` while it is in flight, matching the pane pass's `--keep report-writer-worker`. `TaskStop` on an already-finished task is a no-op; treat a failure as benign, record nothing, and continue the boundary. This runs even when the pane passes found nothing to close, because the background tasks exist either way.
228
- - Before any `prompt_user`/`AskUserQuestion` that follows worker dispatch — an approval, clarification, or decision gate — run the same two passes used at a round boundary: `okstra team reclaim … --dry-run` to count `<n>`, then the same command without `--dry-run` to close, and emit `PROGRESS: phase-gate-cleanup panes=<n>`. Then `TaskStop(task_id: "<name>")` each completed worker, exactly as at a batch boundary. A bare `TaskStop` idles the roster task and closes no pane, so it is never cleanup on its own. This keeps the user from being shown a gate while finished worker panes are still open. After that cleanup, follow the lead contract "User confirmation before an approval blocker": read cited plan items, worker findings, and files before asking, and ask in the user's language with each option's outcome.
226
+ - Before each new worker batch (and before the next phase's render-bundle), close the panes of the dispatches that finished in the prior round with `okstra team reclaim --project-root "<PROJECT_ROOT>" --run-manifest "<RUN_MANIFEST_PATH>"`. It records the neutral contract's `phase-batch-cleanup panes=<n>` checkpoint with the number it closed and prints that `PROGRESS:` line last; emit it as printed and do not call `okstra lead-progress append` for it. Call it after collecting that round's results and token usage and before the next dispatch. The command reads each dispatch's recorded status, so an in-progress worker keeps its pane whichever moment you call it — you do not scope the pass by hand. It closes only the panes okstra opened and recorded; a pane the harness opened for itself carries no recorded id and is not okstra's to close. A `cli-wrapper` run holds no pane at all and `team reclaim` refuses it, so record the checkpoint there with `okstra lead-progress append … --phase phase-batch-cleanup --field panes=0`.
227
+ - Reclaiming a pane does not stop the worker's background task. Every `dispatch_worker` Agent runs with `run_in_background: true`, so a worker whose result is already collected stays a live background task for the rest of the session — that residue is what fills the harness's exit-time `Background work is running` list. At the same batch boundary, right after the pane reclaim, call `TaskStop(task_id: "<name>")` once per worker of the completed batch, passing the exact `name` used at dispatch (`<workerId>-worker`, `<workerId>-worker-reverify-r<N>`, `<provider>-worker-critic`, `report-writer`). Stop only workers whose results were already collected — never an in-flight worker, never the lead, and keep `report-writer` while it is in flight, matching the pane pass's `--keep report-writer-worker`. `TaskStop` on an already-finished task is a no-op; treat a failure as benign, record nothing, and continue the boundary. This runs even when the pane pass found nothing to close, because the background tasks exist either way.
228
+ - Before any `prompt_user`/`AskUserQuestion` that follows worker dispatch — an approval, clarification, or decision gate — run `okstra team reclaim … --gate`: it closes the finished panes and prints `PROGRESS: phase-gate-cleanup panes=<n>` for you to emit, without recording a batch cleanup. Then `TaskStop(task_id: "<name>")` each completed worker, exactly as at a batch boundary. A bare `TaskStop` idles the roster task and closes no pane, so it is never cleanup on its own. This keeps the user from being shown a gate while finished worker panes are still open. After that cleanup, follow the lead contract "User confirmation before an approval blocker": read cited plan items, worker findings, and files before asking, and ask in the user's language with each option's outcome.
229
229
  - After batch cleanup, record the current live session generation with `okstra token-usage "<TEAM_STATE_PATH>" --record-observed-session --project-root "<PROJECT_ROOT>"`. This protects usage accounting when Claude Code re-issues the session id after resume or compaction.
230
230
  - Claude Code cannot delete the implicit team or surgically remove an idle roster entry. Explain that teammates may remain visible until session end and, when needed, give the manual action `Delete team <teamName> in Teams/FleetView`.
231
231
 
@@ -173,7 +173,7 @@ Display the question only through the selected tool. Do not print it or its opti
173
173
  | `await_workers` | Await native host workers through the host primitive and CLI workers through synchronous dispatch, then verify team-state terminal records and Result Paths for both. |
174
174
  | `redispatch_worker` | Materialize and verify a fresh invocation, then start a fresh native worker or `okstra worker-dispatch` attempt according to the persisted runner. |
175
175
  | `shutdown_workers` | Perform process cleanup when a wrapper remains live; otherwise this operation is a no-op recorded in state. |
176
- | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
176
+ | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint the command performing that step does not record itself (the lead contract "Progress reporting" lists the ones `team dispatch`, `team await`, `team reclaim`, `worker-dispatch` and `report-finalize` record; emit the `PROGRESS:` lines they print instead) and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
177
177
  | `collect_usage` | Collect artifact/rollout-backed usage through the existing Okstra token-usage path; never read Claude session JSONL as a substitute. |
178
178
 
179
179
  ## Codex execution permissions
@@ -81,7 +81,7 @@ Render every numbered item as its option label followed by its description verba
81
81
  | `await_workers` | Run `okstra team await --project-root <root> --run-manifest <path>` through the host's asynchronous shell facility. |
82
82
  | `redispatch_worker` | Create the core-specified fresh jobs file and dispatch it with a new `dispatchKind`; never reuse a live worker conversation. |
83
83
  | `shutdown_workers` | Run `okstra team teardown --project-root <root> --run-manifest <path>` only after the user-approved cleanup gate. |
84
- | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
84
+ | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint the command performing that step does not record itself (the lead contract "Progress reporting" lists the ones `team dispatch`, `team await`, `team reclaim`, `worker-dispatch` and `report-finalize` record; emit the `PROGRESS:` lines they print instead) and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
85
85
  | `collect_usage` | Collect artifact/CLI-log-backed usage through the existing Okstra token-usage path; never substitute another runtime's session log. |
86
86
 
87
87
  ## External dispatch details
@@ -91,7 +91,8 @@ Render every numbered item as its option label followed by its description verba
91
91
  - Worker completion is valid only from `workerDispatches[]`, terminal status sidecars, and required Result Paths. Pane creation alone is not completion.
92
92
  - Reverify uses a fresh jobs file at `runs/<task-type>/state/reverify-jobs-r<N>-<task-type>-<seq>.json`, sets `dispatchKind: "reverify-r<N>"`, and dispatches with `okstra team dispatch --project-root <root> --run-manifest <path> --dispatch-kind reverify-r<N> --jobs-file <jobs-file>`.
93
93
  - Report-writer uses a fresh one-job jobs file with `dispatchKind: "report-writer"` and the same schema, then dispatches through `okstra team dispatch --project-root <root> --run-manifest <path> --jobs-file <jobs-file>`.
94
- - Generate v2 reverify and report-writer jobs files with `okstra agent-prompt jobs --project-root <root> --run-manifest <path> --dispatch-kind <kind> --metadata <prompt-meta.json> [--metadata <prompt-meta.json>] --out <jobs-file>`. It verifies the inputs and derives canonical identity, role, result paths, and all five digests. Reverify uses role `verifier`; its round belongs to `dispatchKind`. Do not transcribe metadata fields or add `workerId` to v2 files. Existing v1 jobs-file consumers remain available. Report-writer completion uses the narrative and worker-result pointer; Phase 7 later assembles `data.json`.
94
+ - Build a batch's jobs file in the call that materializes it: one `materialize --batch <file> --jobs-out <jobs-file>` call for every worker of the batch (convergence "Invocation materialization gate"), or one `materialize … --jobs-out <jobs-file>` call for the report writer, chained with `&& okstra team dispatch … --jobs-file <jobs-file>` in the same shell command. One materialize, verify, or jobs call per worker adds one lead turn over the whole context per worker; `team dispatch` verifies every invocation of the jobs file, so no `agent-prompt verify` call precedes it.
95
+ - For metadata already materialized (a retry), generate v2 reverify and report-writer jobs files with `okstra agent-prompt jobs --project-root <root> --run-manifest <path> --dispatch-kind <kind> --metadata <prompt-meta.json> [--metadata <prompt-meta.json>] --out <jobs-file>`. It verifies the inputs and derives canonical identity, role, result paths, and all five digests. Reverify uses role `verifier`; its round belongs to `dispatchKind`. Do not transcribe metadata fields or add `workerId` to v2 files. Existing v1 jobs-file consumers remain available. Report-writer completion uses the narrative and worker-result pointer; Phase 7 later assembles `data.json`.
95
96
  - After either dispatch, run `okstra team await --project-root <root> --run-manifest <path>` before evaluating terminal status or completion paths.
96
97
 
97
98
  ## Completion, cleanup, and resume
@@ -158,7 +158,7 @@ For a `host-text` mapping, render each numbered item as its option label followe
158
158
  | `await_workers` | Await through the selected common dispatch backend, then verify terminal state and Result Paths. |
159
159
  | `redispatch_worker` | Start a fresh attempt from the persisted assignment and record the supplied dispatch kind. |
160
160
  | `shutdown_workers` | Clean up only host or process resources owned by this run. |
161
- | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
161
+ | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint the command performing that step does not record itself (the lead contract "Progress reporting" lists the ones `team dispatch`, `team await`, `team reclaim`, `worker-dispatch` and `report-finalize` record; emit the `PROGRESS:` lines they print instead) and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
162
162
  | `collect_usage` | Return explicit unavailable lead usage until Grok registers a session transcript or CLI usage artifact contract. |
163
163
 
164
164
  - This host declares no worker session contract. A `runner=native-session` worker therefore receives no host session rules beyond its duty contract, the selected preamble, and the task instructions; the dispatch prompt carries no `**Host Session Contract Path:**` header. Declaring one means adding `workerSessionContract` to this adapter's `manifest.json` and descriptor — it is never installed into a host-global discovery path.
@@ -80,7 +80,7 @@ Render every numbered item as its option label followed by its description verba
80
80
  | `await_workers` | Await through the selected common dispatch backend, then verify terminal state and Result Paths. |
81
81
  | `redispatch_worker` | Start a fresh attempt from the persisted assignment and record the supplied dispatch kind. |
82
82
  | `shutdown_workers` | Clean up only host or process resources owned by this run. |
83
- | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
83
+ | `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --phase <phase-id>` for a checkpoint the command performing that step does not record itself (the lead contract "Progress reporting" lists the ones `team dispatch`, `team await`, `team reclaim`, `worker-dispatch` and `report-finalize` record; emit the `PROGRESS:` lines they print instead) and `okstra agent-activity append --kind <kind>` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
84
84
  | `collect_usage` | Return explicit unavailable lead usage until Kimi registers a session transcript or CLI usage artifact contract. |
85
85
 
86
86
  - This host declares no worker session contract. A `runner=native-session` worker therefore receives no host session rules beyond its duty contract, the selected preamble, and the task instructions; the dispatch prompt carries no `**Host Session Contract Path:**` header. Declaring one means adding `workerSessionContract` to this adapter's `manifest.json` and descriptor — it is never installed into a host-global discovery path.
@@ -16,22 +16,6 @@ from okstra_ctl.domain.worker_presentation import SplitText
16
16
  import okstra_ctl.model_discovery as model_discovery
17
17
 
18
18
 
19
- # 모델 식별자와 순서는 Codex의 `~/.codex/models_cache.json`을 따른다
20
- # (2026-09-23 확인, 클라이언트 0.155.0): gpt-6 astra / sol / luna 와 5.6 계열의
21
- # sol / terra / luna. `gpt-5.6` is not a slug that catalog offers at all, so it
22
- # is gone from here; its rate moved to `_LEGACY_CODEX_PRICING` so past runs
23
- # still price.
24
- #
25
- # 노출 규칙: 티어(astra·sol·terra·luna)마다, **이 계정이 실제로 서빙하는** 최신
26
- # 세대 하나만 selectable 로 둔다. 카탈로그가 슬러그를 내놓는 것과 계정이 그것을
27
- # 실행하는 것은 다르다 — 실측 2026-09-23(jobs dev-10860
28
- # implementation-option-selection-002): ChatGPT 계정으로 로그인한 이 기계에서
29
- # `gpt-6-sol` 디스패치가 두 번 다 400 으로 거절됐다
30
- # ("The 'gpt-6-sol' model is not supported when using Codex with a ChatGPT
31
- # account"). 같은 계정의 `models_cache.json` 도 6세대로는 astra 만 싣는다.
32
- # 그래서 sol·luna 티어는 5.6 행이 선택 가능한 행이고, gpt-6 의 두 행은 엔트리만
33
- # 남긴다 — 서빙하는 계정이 그 값을 쓰거나 과거 run 을 정산할 때 필요하다.
34
- # astra 는 이 계정에서 실제로 돌아 gpt-6 행이 선택 가능하다.
35
19
  CODEX = {
36
20
  # 비용은 계정이 구독이든 API 든 공개 API 단가(입력·캐시 입력·출력 USD/1M)로
37
21
  # 추정한다 — 리포트가 답하는 것은 "얼마나 썼는가" 이지 "청구서에 얼마가
@@ -41,16 +25,19 @@ CODEX = {
41
25
  # (morphllm.com/openai-api-pricing, cloudzero.com/blog/openai-pricing,
42
26
  # layer3labs.io/guides/gpt-6-astra-api-pricing).
43
27
  # gpt-6 단가는 OpenAI 모델 문서의 표준 등급(2026-09-23 확인):
44
- # developers.openai.com/api/docs/models/gpt-6-sol, .../gpt-6-luna.
28
+ # developers.openai.com/api/docs/models/gpt-6-sol, .../gpt-6-luna, .../gpt-6.1-sol
29
+ # (gpt-6.1-sol 은 2026-09-30 확인: 캐시 입력만 $0.10 으로 gpt-6-sol 과 다르다).
45
30
  "gpt-6-astra": ModelSpec("gpt-6-astra", "gpt-6-astra", "gpt-6-astra", pricing=(10.0, 1.0, 50.0)),
46
- # picker 에서는 감춘다: 이 계정이 400 으로 거절한다(위 노출 규칙). 엔트리는
47
- # 남긴다 — 서빙하는 계정의 값이고, 과거 run 의 단가도 이 표에서 찾는다.
31
+ # 카탈로그 기본 effort 는 low 라, config.toml 에 값이 없는 기계에서는 low 로 돈다.
32
+ "gpt-6.1-sol": ModelSpec(
33
+ "gpt-6.1-sol", "gpt-6.1-sol", "gpt-6.1-sol", pricing=(2.0, 0.10, 10.0),
34
+ cli_args=("-c", "model_reasoning_effort=high"),
35
+ ),
48
36
  "gpt-6-sol": ModelSpec("gpt-6-sol", "gpt-6-sol", "gpt-6-sol", pricing=(2.0, 0.20, 10.0), selectable=False),
49
- "gpt-6-luna": ModelSpec("gpt-6-luna", "gpt-6-luna", "gpt-6-luna", pricing=(0.10, 0.01, 0.50), selectable=False),
50
- "gpt-5.6-terra": ModelSpec("gpt-5.6-terra", "gpt-5.6-terra", "gpt-5.6-terra", pricing=(2.0, 0.20, 12.0)),
51
- "gpt-5.6-sol": ModelSpec("gpt-5.6-sol", "gpt-5.6-sol", "gpt-5.6-sol", pricing=(5.0, 0.50, 30.0)),
52
- "gpt-5.6-luna": ModelSpec("gpt-5.6-luna", "gpt-5.6-luna", "gpt-5.6-luna", pricing=(0.20, 0.02, 1.20)),
53
- # picker 에서는 감춘다(사유는 위와 동일 — 더 이상 카탈로그가 내놓지 않는다).
37
+ "gpt-6-luna": ModelSpec("gpt-6-luna", "gpt-6-luna", "gpt-6-luna", pricing=(0.10, 0.01, 0.50)),
38
+ "gpt-5.6-terra": ModelSpec("gpt-5.6-terra", "gpt-5.6-terra", "gpt-5.6-terra", pricing=(2.0, 0.20, 12.0), selectable=False),
39
+ "gpt-5.6-sol": ModelSpec("gpt-5.6-sol", "gpt-5.6-sol", "gpt-5.6-sol", pricing=(5.0, 0.50, 30.0), selectable=False),
40
+ "gpt-5.6-luna": ModelSpec("gpt-5.6-luna", "gpt-5.6-luna", "gpt-5.6-luna", pricing=(0.20, 0.02, 1.20), selectable=False),
54
41
  "gpt-5.4-mini": ModelSpec("gpt-5.4-mini", "gpt-5.4-mini", "gpt-5.4-mini", pricing=(0.75, 0.075, 4.50), selectable=False),
55
42
  "codex-auto-review": ModelSpec("codex-auto-review", "codex-auto-review", "codex-auto-review", selectable=False),
56
43
  }
@@ -116,7 +103,11 @@ class CodexExecution:
116
103
  for directory in request.policy.write_scope:
117
104
  if directory != request.project_root:
118
105
  argv += ["--add-dir", str(directory)]
119
- argv += ["--model", request.model, "--sandbox", "danger-full-access"]
106
+ argv += ["--model", request.model]
107
+ spec = CODEX.get(request.model)
108
+ if spec is not None:
109
+ argv += spec.cli_args
110
+ argv += ["--sandbox", "danger-full-access"]
120
111
  if request.policy.auto_approve:
121
112
  argv += ["-c", "approval_policy=never"]
122
113
  argv.append("-")
@@ -141,7 +132,7 @@ def create_provider() -> ProviderSpec:
141
132
  display_label="Codex",
142
133
  models=CODEX,
143
134
  default_models={
144
- role: "gpt-5.6-sol"
135
+ role: "gpt-6.1-sol"
145
136
  for role in ("lead", "analyser", "critic", "designer", "planner", "executor", "verifier", "report-writer", "translator")
146
137
  },
147
138
  wrapper="okstra-codex-exec.sh",