okstra 0.186.7 → 0.188.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 (546) hide show
  1. package/README.md +1 -1
  2. package/dist/cli-registry.d.mts +88 -1
  3. package/dist/cli-registry.mjs +68 -111
  4. package/dist/cli-registry.mjs.map +1 -1
  5. package/dist/commands/execute/render-bundle.mjs +0 -1
  6. package/dist/commands/execute/render-bundle.mjs.map +1 -1
  7. package/dist/commands/execute/run.mjs +8 -3
  8. package/dist/commands/execute/run.mjs.map +1 -1
  9. package/dist/commands/lifecycle/check-project.mjs +1 -14
  10. package/dist/commands/lifecycle/check-project.mjs.map +1 -1
  11. package/dist/commands/lifecycle/config.mjs +38 -40
  12. package/dist/commands/lifecycle/config.mjs.map +1 -1
  13. package/dist/commands/lifecycle/doctor.d.mts +22 -7
  14. package/dist/commands/lifecycle/doctor.mjs +77 -49
  15. package/dist/commands/lifecycle/doctor.mjs.map +1 -1
  16. package/dist/commands/lifecycle/install.d.mts +12 -10
  17. package/dist/commands/lifecycle/install.mjs +107 -40
  18. package/dist/commands/lifecycle/install.mjs.map +1 -1
  19. package/dist/commands/lifecycle/paths.mjs +8 -3
  20. package/dist/commands/lifecycle/paths.mjs.map +1 -1
  21. package/dist/commands/lifecycle/preflight.mjs +2 -1
  22. package/dist/commands/lifecycle/preflight.mjs.map +1 -1
  23. package/dist/commands/lifecycle/setup.mjs +22 -36
  24. package/dist/commands/lifecycle/setup.mjs.map +1 -1
  25. package/dist/commands/lifecycle/uninstall.d.mts +4 -2
  26. package/dist/commands/lifecycle/uninstall.mjs +59 -15
  27. package/dist/commands/lifecycle/uninstall.mjs.map +1 -1
  28. package/dist/commands/memory/memory.mjs +7 -1
  29. package/dist/commands/memory/memory.mjs.map +1 -1
  30. package/dist/lib/helper-scripts.d.mts +1 -1
  31. package/dist/lib/helper-scripts.mjs +10 -18
  32. package/dist/lib/helper-scripts.mjs.map +1 -1
  33. package/dist/lib/host-config.d.mts +72 -0
  34. package/dist/lib/host-config.mjs +404 -0
  35. package/dist/lib/host-config.mjs.map +1 -0
  36. package/dist/lib/host-registry-client.d.mts +2 -2
  37. package/dist/lib/host-registry-client.mjs +0 -3
  38. package/dist/lib/host-registry-client.mjs.map +1 -1
  39. package/dist/lib/install-assets.d.mts +1 -0
  40. package/dist/lib/install-assets.mjs +4 -0
  41. package/dist/lib/install-assets.mjs.map +1 -1
  42. package/dist/lib/proc.d.mts +2 -0
  43. package/dist/lib/proc.mjs +12 -0
  44. package/dist/lib/proc.mjs.map +1 -1
  45. package/dist/lib/python-command.d.mts +2 -0
  46. package/dist/lib/python-command.mjs +52 -0
  47. package/dist/lib/python-command.mjs.map +1 -0
  48. package/dist/lib/python-helper.d.mts +2 -5
  49. package/dist/lib/python-helper.mjs +3 -52
  50. package/dist/lib/python-helper.mjs.map +1 -1
  51. package/dist/lib/runtime-payload.d.mts +23 -0
  52. package/dist/lib/runtime-payload.mjs +57 -0
  53. package/dist/lib/runtime-payload.mjs.map +1 -0
  54. package/dist/lib/types.d.mts +24 -13
  55. package/docs/architecture/storage-model.md +21 -5
  56. package/docs/architecture.md +39 -38
  57. package/docs/cli.md +55 -76
  58. package/docs/coding-rules.md +295 -0
  59. package/docs/container.md +10 -36
  60. package/docs/contributor-change-matrix.md +1 -1
  61. package/docs/for-ai/skills/okstra-code-review.md +0 -1
  62. package/docs/for-ai/skills/okstra-container-build.md +8 -41
  63. package/docs/for-ai/skills/okstra-inspect.md +4 -4
  64. package/docs/for-ai/skills/okstra-manager.md +2 -2
  65. package/docs/for-ai/skills/okstra-rollup.md +0 -1
  66. package/docs/for-ai/skills/okstra-run.md +3 -3
  67. package/docs/for-ai/skills/okstra-user-response.md +0 -1
  68. package/docs/performance-improvement-plan-v2.md +1 -1
  69. package/docs/project-structure-overview.md +62 -62
  70. package/docs/task-process/README.md +3 -3
  71. package/docs/task-process/common-flow.md +1 -1
  72. package/docs/task-process/error-analysis.md +3 -3
  73. package/docs/task-process/implementation-planning.md +3 -1
  74. package/docs/task-process/release-handoff.md +1 -1
  75. package/package.json +3 -2
  76. package/runtime/BUILD.json +2 -2
  77. package/runtime/agents/workers/claude-worker.md +6 -11
  78. package/runtime/agents/workers/report-writer-worker.md +1 -1
  79. package/runtime/bin/lib/okstra/cli.sh +4 -0
  80. package/runtime/bin/lib/okstra/globals.sh +2 -0
  81. package/runtime/bin/lib/okstra/interactive.sh +26 -173
  82. package/runtime/bin/lib/okstra/project-resolver.sh +23 -61
  83. package/runtime/bin/lib/okstra/usage.sh +3 -3
  84. package/runtime/bin/okstra-compact-reminder.sh +1 -5
  85. package/runtime/bin/okstra-error-log.py +19 -2
  86. package/runtime/bin/okstra-import-check.py +26 -0
  87. package/runtime/bin/okstra-inject-report-index.py +5 -4
  88. package/runtime/bin/okstra-provider-exec.py +22 -17
  89. package/runtime/bin/okstra-render-final-report.py +16 -6
  90. package/runtime/bin/okstra-render-report-views.py +47 -22
  91. package/runtime/bin/okstra-report-translate.py +30 -18
  92. package/runtime/bin/okstra-spawn-followups.py +4 -0
  93. package/runtime/bin/okstra-token-usage.py +3 -0
  94. package/runtime/bin/okstra.sh +4 -2
  95. package/runtime/bin/okstra_bootstrap.py +58 -0
  96. package/runtime/prompts/coding-preflight/overview.md +1 -1
  97. package/runtime/prompts/duties/planning-worker.md +1 -1
  98. package/runtime/prompts/launch.template.md +35 -9
  99. package/runtime/prompts/lead/adapters/cmux.md +3 -3
  100. package/runtime/prompts/lead/convergence.md +99 -88
  101. package/runtime/prompts/lead/okstra-lead-contract.md +63 -12
  102. package/runtime/prompts/lead/plan-body-verification.md +65 -46
  103. package/runtime/prompts/lead/report-writer.md +35 -5
  104. package/runtime/prompts/lead/team-contract.md +4 -1
  105. package/runtime/prompts/profiles/_clarification-recommendation.md +2 -1
  106. package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
  107. package/runtime/prompts/profiles/_common-contract.md +3 -3
  108. package/runtime/prompts/profiles/_coverage-critic.md +1 -1
  109. package/runtime/prompts/profiles/_implementation-deliverable.md +2 -2
  110. package/runtime/prompts/profiles/_implementation-executor.md +3 -1
  111. package/runtime/prompts/profiles/_implementation-verifier.md +16 -2
  112. package/runtime/prompts/profiles/error-analysis.md +4 -3
  113. package/runtime/prompts/profiles/final-verification.md +2 -2
  114. package/runtime/prompts/profiles/implementation-planning.md +22 -17
  115. package/runtime/prompts/profiles/implementation.md +3 -2
  116. package/runtime/prompts/profiles/requirements-discovery.md +2 -1
  117. package/runtime/prompts/wizard/prompts.ko.json +29 -8
  118. package/runtime/python/okstra_ctl/__init__.py +6 -27
  119. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -5
  120. package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +21 -2
  121. package/runtime/python/okstra_ctl/adapters/hosts/external/adapter.py +3 -12
  122. package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +63 -22
  123. package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +20 -21
  124. package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +37 -20
  125. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +86 -14
  126. package/runtime/python/okstra_ctl/adapters/providers/kimi/adapter.py +12 -12
  127. package/runtime/python/okstra_ctl/adapters/runtime/cmux.py +4 -7
  128. package/runtime/python/okstra_ctl/agent/__init__.py +1 -0
  129. package/runtime/python/okstra_ctl/{agent_activity.py → agent/activity.py} +16 -2
  130. package/runtime/python/okstra_ctl/{agent_invocation.py → agent/invocation.py} +34 -5
  131. package/runtime/python/okstra_ctl/agent/prompt_cli/__init__.py +19 -0
  132. package/runtime/python/okstra_ctl/agent/prompt_cli/__main__.py +11 -0
  133. package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +228 -0
  134. package/runtime/python/okstra_ctl/agent/prompt_cli/dynamic_verifier.py +155 -0
  135. package/runtime/python/okstra_ctl/agent/prompt_cli/emit.py +66 -0
  136. package/runtime/python/okstra_ctl/agent/prompt_cli/inputs.py +138 -0
  137. package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +605 -0
  138. package/runtime/python/okstra_ctl/agent/prompt_cli/results.py +197 -0
  139. package/runtime/python/okstra_ctl/agent/prompt_cli/run_identity.py +107 -0
  140. package/runtime/python/okstra_ctl/analysis_packet.py +47 -4
  141. package/runtime/python/okstra_ctl/approval_decisions.py +287 -10
  142. package/runtime/python/okstra_ctl/assignment_resolver.py +0 -12
  143. package/runtime/python/okstra_ctl/attempt_evidence.py +12 -24
  144. package/runtime/python/okstra_ctl/blocking_checks.py +251 -0
  145. package/runtime/python/okstra_ctl/brief_frontmatter.py +0 -7
  146. package/runtime/python/okstra_ctl/clarification_items/__init__.py +102 -0
  147. package/runtime/python/okstra_ctl/clarification_items/carry.py +224 -0
  148. package/runtime/python/okstra_ctl/clarification_items/dispositions.py +135 -0
  149. package/runtime/python/okstra_ctl/clarification_items/parsing.py +253 -0
  150. package/runtime/python/okstra_ctl/clarification_items/rows.py +115 -0
  151. package/runtime/python/okstra_ctl/clarification_items/scan.py +215 -0
  152. package/runtime/python/okstra_ctl/clarification_items/sidecars.py +211 -0
  153. package/runtime/python/okstra_ctl/cmux.py +38 -31
  154. package/runtime/python/okstra_ctl/code_review_target.py +163 -1
  155. package/runtime/python/okstra_ctl/conformance.py +23 -0
  156. package/runtime/python/okstra_ctl/container.py +38 -421
  157. package/runtime/python/okstra_ctl/context_cost.py +32 -4
  158. package/runtime/python/okstra_ctl/contract_graph_cli.py +7 -0
  159. package/runtime/python/okstra_ctl/convergence.py +107 -16
  160. package/runtime/python/okstra_ctl/convergence_critic_prompt.py +345 -0
  161. package/runtime/python/okstra_ctl/convergence_engine.py +382 -70
  162. package/runtime/python/okstra_ctl/convergence_store.py +5 -29
  163. package/runtime/python/okstra_ctl/design_prep.py +108 -12
  164. package/runtime/python/okstra_ctl/design_snapshot.py +11 -1
  165. package/runtime/python/okstra_ctl/design_surfaces.py +29 -2
  166. package/runtime/python/okstra_ctl/dispatch_core.py +236 -49
  167. package/runtime/python/okstra_ctl/dispatch_state.py +417 -41
  168. package/runtime/python/okstra_ctl/doctor_cli.py +48 -0
  169. package/runtime/python/okstra_ctl/domain/worker_exec.py +10 -5
  170. package/runtime/python/okstra_ctl/domain/worker_presentation.py +28 -1
  171. package/runtime/python/okstra_ctl/domain/worker_stream.py +52 -21
  172. package/runtime/python/okstra_ctl/domain/write_policy.py +219 -0
  173. package/runtime/python/okstra_ctl/entrypoints/hosts.py +9 -2
  174. package/runtime/python/okstra_ctl/error_log_core.py +1 -1
  175. package/runtime/python/okstra_ctl/error_report.py +14 -0
  176. package/runtime/python/okstra_ctl/error_zip.py +18 -2
  177. package/runtime/python/okstra_ctl/exact_coverage.py +5 -0
  178. package/runtime/python/okstra_ctl/execution_identity.py +100 -7
  179. package/runtime/python/okstra_ctl/execution_manifest.py +67 -20
  180. package/runtime/python/okstra_ctl/execution_mutation_audit.py +90 -8
  181. package/runtime/python/okstra_ctl/final_report_paths.py +17 -0
  182. package/runtime/python/okstra_ctl/final_report_schema.py +319 -17
  183. package/runtime/python/okstra_ctl/git_reconcile.py +22 -2
  184. package/runtime/python/okstra_ctl/handoff.py +24 -1
  185. package/runtime/python/okstra_ctl/ids.py +6 -16
  186. package/runtime/python/okstra_ctl/implementation_direction.py +142 -33
  187. package/runtime/python/okstra_ctl/implementation_options.py +32 -13
  188. package/runtime/python/okstra_ctl/implementation_outcome.py +5 -2
  189. package/runtime/python/okstra_ctl/improvement_lenses.py +0 -14
  190. package/runtime/python/okstra_ctl/incremental_carry.py +69 -8
  191. package/runtime/python/okstra_ctl/incremental_scope.py +173 -12
  192. package/runtime/python/okstra_ctl/index.py +2 -2
  193. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +48 -8
  194. package/runtime/python/okstra_ctl/interactive_cli.py +223 -0
  195. package/runtime/python/okstra_ctl/json_boundary.py +10 -0
  196. package/runtime/python/okstra_ctl/listing.py +0 -91
  197. package/runtime/python/okstra_ctl/locks.py +5 -19
  198. package/runtime/python/okstra_ctl/log_report.py +14 -0
  199. package/runtime/python/okstra_ctl/manager_cli.py +22 -3
  200. package/runtime/python/okstra_ctl/manager_launch.py +4 -8
  201. package/runtime/python/okstra_ctl/material.py +2 -2
  202. package/runtime/python/okstra_ctl/migrate.py +23 -1
  203. package/runtime/python/okstra_ctl/model_cli.py +19 -5
  204. package/runtime/python/okstra_ctl/model_discovery.py +46 -47
  205. package/runtime/python/okstra_ctl/model_io/__init__.py +1 -0
  206. package/runtime/python/okstra_ctl/model_io/lines.py +163 -0
  207. package/runtime/python/okstra_ctl/model_io/references.py +370 -0
  208. package/runtime/python/okstra_ctl/model_io/renderers.py +498 -0
  209. package/runtime/python/okstra_ctl/model_io_cli.py +30 -945
  210. package/runtime/python/okstra_ctl/model_pool.py +10 -6
  211. package/runtime/python/okstra_ctl/models.py +8 -8
  212. package/runtime/python/okstra_ctl/mutation_recovery.py +5 -63
  213. package/runtime/python/okstra_ctl/next_phase.py +121 -69
  214. package/runtime/python/okstra_ctl/pane_reclaim.py +23 -0
  215. package/runtime/python/okstra_ctl/pane_title.py +11 -8
  216. package/runtime/python/okstra_ctl/path_hints.py +36 -11
  217. package/runtime/python/okstra_ctl/paths.py +76 -8
  218. package/runtime/python/okstra_ctl/plan_items.py +132 -16
  219. package/runtime/python/okstra_ctl/plan_items_cli.py +486 -36
  220. package/runtime/python/okstra_ctl/plan_run_root.py +1 -1
  221. package/runtime/python/okstra_ctl/plan_validate_cli.py +51 -0
  222. package/runtime/python/okstra_ctl/plan_verify_cli.py +80 -0
  223. package/runtime/python/okstra_ctl/prepare_error.py +20 -0
  224. package/runtime/python/okstra_ctl/prior_planning.py +157 -0
  225. package/runtime/python/okstra_ctl/profile_show.py +18 -1
  226. package/runtime/python/okstra_ctl/project_setup_cli.py +140 -0
  227. package/runtime/python/okstra_ctl/recap.py +22 -1
  228. package/runtime/python/okstra_ctl/reconcile.py +84 -0
  229. package/runtime/python/okstra_ctl/registry/host_registry.py +18 -1
  230. package/runtime/python/okstra_ctl/render.py +98 -32
  231. package/runtime/python/okstra_ctl/render_final_report.py +4 -8
  232. package/runtime/python/okstra_ctl/report_assembly.py +297 -7
  233. package/runtime/python/okstra_ctl/report_contract.py +30 -7
  234. package/runtime/python/okstra_ctl/report_finalize.py +213 -16
  235. package/runtime/python/okstra_ctl/report_html/common.py +2 -2
  236. package/runtime/python/okstra_ctl/report_html/render.py +8 -12
  237. package/runtime/python/okstra_ctl/report_language.py +8 -4
  238. package/runtime/python/okstra_ctl/report_narrative.py +220 -34
  239. package/runtime/python/okstra_ctl/report_projections.py +8 -2
  240. package/runtime/python/okstra_ctl/report_synthesis_packet.py +393 -1
  241. package/runtime/python/okstra_ctl/report_translation.py +2 -35
  242. package/runtime/python/okstra_ctl/report_view_artifacts.py +42 -2
  243. package/runtime/python/okstra_ctl/report_views.py +4 -22
  244. package/runtime/python/okstra_ctl/resolve_task_key.py +13 -0
  245. package/runtime/python/okstra_ctl/rollup.py +13 -0
  246. package/runtime/python/okstra_ctl/run.py +639 -138
  247. package/runtime/python/okstra_ctl/run_audit.py +13 -0
  248. package/runtime/python/okstra_ctl/run_index_row.py +0 -12
  249. package/runtime/python/okstra_ctl/seeding.py +21 -11
  250. package/runtime/python/okstra_ctl/sequence.py +1 -1
  251. package/runtime/python/okstra_ctl/session.py +64 -14
  252. package/runtime/python/okstra_ctl/set_work_status.py +18 -0
  253. package/runtime/python/okstra_ctl/stage_integrate.py +15 -1
  254. package/runtime/python/okstra_ctl/stage_ledger.py +1 -1
  255. package/runtime/python/okstra_ctl/stage_map.py +57 -11
  256. package/runtime/python/okstra_ctl/stage_map_cli.py +83 -0
  257. package/runtime/python/okstra_ctl/stage_map_view.py +65 -0
  258. package/runtime/python/okstra_ctl/stage_targets.py +3 -12
  259. package/runtime/python/okstra_ctl/task_list_cli.py +138 -0
  260. package/runtime/python/okstra_ctl/task_show_cli.py +66 -0
  261. package/runtime/python/okstra_ctl/task_target.py +4 -16
  262. package/runtime/python/okstra_ctl/team.py +49 -2
  263. package/runtime/python/okstra_ctl/time_report.py +17 -2
  264. package/runtime/python/okstra_ctl/usage_report.py +11 -0
  265. package/runtime/python/okstra_ctl/user_response.py +55 -218
  266. package/runtime/python/okstra_ctl/user_response_values.py +242 -0
  267. package/runtime/python/okstra_ctl/validation_contract.py +3 -0
  268. package/runtime/python/okstra_ctl/verdict_blocks.py +28 -8
  269. package/runtime/python/okstra_ctl/verification_target.py +68 -0
  270. package/runtime/python/okstra_ctl/wizard.py +457 -92
  271. package/runtime/python/okstra_ctl/worker_artifacts.py +75 -16
  272. package/runtime/python/okstra_ctl/worker_audit_check.py +22 -0
  273. package/runtime/python/okstra_ctl/worker_dispatch.py +21 -0
  274. package/runtime/python/okstra_ctl/worker_liveness.py +33 -0
  275. package/runtime/python/okstra_ctl/worker_prompt_body.py +15 -2
  276. package/runtime/python/okstra_ctl/worker_prompt_contract.py +98 -7
  277. package/runtime/python/okstra_ctl/worker_prompt_headers.py +24 -2
  278. package/runtime/python/okstra_ctl/worker_prompt_policy.py +18 -3
  279. package/runtime/python/okstra_ctl/worker_request.py +2 -1
  280. package/runtime/python/okstra_ctl/worker_runner.py +58 -17
  281. package/runtime/python/okstra_ctl/worker_state.py +16 -1
  282. package/runtime/python/okstra_ctl/workflow.py +18 -1
  283. package/runtime/python/okstra_ctl/worktree/__init__.py +92 -0
  284. package/runtime/python/okstra_ctl/worktree/cleanliness.py +89 -0
  285. package/runtime/python/okstra_ctl/worktree/decisions.py +127 -0
  286. package/runtime/python/okstra_ctl/worktree/git_ops.py +165 -0
  287. package/runtime/python/okstra_ctl/worktree/linking.py +249 -0
  288. package/runtime/python/okstra_ctl/worktree/naming.py +91 -0
  289. package/runtime/python/okstra_ctl/worktree/provision.py +385 -0
  290. package/runtime/python/okstra_ctl/worktree/sync_config.py +181 -0
  291. package/runtime/python/okstra_ctl/worktree_cli.py +75 -0
  292. package/runtime/python/okstra_ctl/worktree_lookup_cli.py +39 -0
  293. package/runtime/python/okstra_ctl/worktree_registry.py +7 -0
  294. package/runtime/python/okstra_ctl/worktree_status_cli.py +53 -0
  295. package/runtime/python/okstra_ctl/write_policy.py +90 -213
  296. package/runtime/python/okstra_project/__init__.py +0 -4
  297. package/runtime/python/okstra_project/dirs.py +2 -2
  298. package/runtime/python/okstra_project/phase_pointer.py +84 -0
  299. package/runtime/python/okstra_project/slug.py +24 -0
  300. package/runtime/python/okstra_project/state.py +22 -230
  301. package/runtime/python/okstra_token_usage/antigravity.py +50 -12
  302. package/runtime/python/okstra_token_usage/claude.py +9 -1
  303. package/runtime/python/okstra_token_usage/cli.py +3 -1
  304. package/runtime/python/okstra_token_usage/collect.py +171 -36
  305. package/runtime/python/okstra_token_usage/cursor.py +2 -0
  306. package/runtime/python/okstra_token_usage/grok.py +1 -5
  307. package/runtime/python/okstra_token_usage/paths.py +26 -0
  308. package/runtime/python/okstra_token_usage/pricing.py +23 -8
  309. package/runtime/schemas/convergence-critic-results-v1.0.schema.json +5 -0
  310. package/runtime/schemas/execution-manifest-v2.schema.json +10 -10
  311. package/runtime/schemas/final-report-v2.0.schema.json +9 -26
  312. package/runtime/schemas/final-report-v3.0.schema.json +173 -41
  313. package/runtime/schemas/report-narrative-v3.0.schema.json +3 -2
  314. package/runtime/skills/okstra-brief-gen/SKILL.md +35 -2
  315. package/runtime/skills/okstra-container-build/SKILL.md +16 -47
  316. package/runtime/skills/okstra-inspect/facets/history.md +1 -1
  317. package/runtime/skills/okstra-inspect/facets/status.md +7 -6
  318. package/runtime/skills/okstra-pr-gen/SKILL.md +1 -1
  319. package/runtime/skills/okstra-run/SKILL.md +7 -5
  320. package/runtime/templates/report-writer-prompt-preamble.md +3 -1
  321. package/runtime/templates/reports/brief.template.md +6 -2
  322. package/runtime/templates/reports/error-analysis-input.template.md +2 -0
  323. package/runtime/templates/reports/final-verification-input.template.md +2 -0
  324. package/runtime/templates/reports/implementation-input.template.md +7 -1
  325. package/runtime/templates/reports/implementation-planning-input.template.md +4 -0
  326. package/runtime/templates/reports/quick-input.template.md +2 -0
  327. package/runtime/templates/reports/release-handoff-input.template.md +6 -1
  328. package/runtime/templates/reports/report.js +20 -3
  329. package/runtime/templates/reports/schedule.template.md +2 -0
  330. package/runtime/templates/reports/settings.template.json +0 -10
  331. package/runtime/templates/reports/task-brief.template.md +3 -0
  332. package/runtime/templates/reports/user-response.template.md +7 -3
  333. package/runtime/validators/checks/fixtures-01.py +57 -0
  334. package/runtime/validators/checks/fixtures-02.py +565 -0
  335. package/runtime/validators/checks/runners-01.py +108 -0
  336. package/runtime/validators/checks/validate-assets-01.py +60 -0
  337. package/runtime/validators/checks/validate-prompt-metadata-01.py +261 -0
  338. package/runtime/validators/checks/validate-tasks-01.py +46 -0
  339. package/runtime/validators/checks/validate-tasks-02.py +85 -0
  340. package/runtime/validators/checks/validate-tasks-03.py +61 -0
  341. package/runtime/validators/checks/validate-tasks-04.py +118 -0
  342. package/runtime/validators/forbidden_actions.py +73 -3
  343. package/runtime/validators/lib/common.sh +5 -0
  344. package/runtime/validators/lib/fixtures.sh +7 -591
  345. package/runtime/validators/lib/paths.sh +13 -0
  346. package/runtime/validators/lib/runners.sh +6 -104
  347. package/runtime/validators/lib/summary.sh +1 -1
  348. package/runtime/validators/lib/validate-assets.sh +6 -56
  349. package/runtime/validators/lib/validate-prompt-metadata.sh +6 -257
  350. package/runtime/validators/lib/validate-tasks.sh +9 -294
  351. package/runtime/validators/validate-implementation-plan-stages.py +4 -4
  352. package/runtime/validators/validate-run.py +1363 -2643
  353. package/runtime/validators/validate-workflow.sh +56 -16
  354. package/runtime/validators/validate_improvement_report.py +2 -1
  355. package/runtime/validators/validate_session_conformance.py +295 -49
  356. package/dist/commands/execute/agent-prompt.d.mts +0 -1
  357. package/dist/commands/execute/agent-prompt.mjs +0 -24
  358. package/dist/commands/execute/agent-prompt.mjs.map +0 -1
  359. package/dist/commands/execute/codex-dispatch.d.mts +0 -3
  360. package/dist/commands/execute/codex-dispatch.mjs +0 -6
  361. package/dist/commands/execute/codex-dispatch.mjs.map +0 -1
  362. package/dist/commands/execute/codex-run.d.mts +0 -3
  363. package/dist/commands/execute/codex-run.mjs +0 -62
  364. package/dist/commands/execute/codex-run.mjs.map +0 -1
  365. package/dist/commands/execute/convergence.d.mts +0 -1
  366. package/dist/commands/execute/convergence.mjs +0 -38
  367. package/dist/commands/execute/convergence.mjs.map +0 -1
  368. package/dist/commands/execute/error-log.d.mts +0 -1
  369. package/dist/commands/execute/error-log.mjs +0 -18
  370. package/dist/commands/execute/error-log.mjs.map +0 -1
  371. package/dist/commands/execute/git-reconcile.d.mts +0 -1
  372. package/dist/commands/execute/git-reconcile.mjs +0 -30
  373. package/dist/commands/execute/git-reconcile.mjs.map +0 -1
  374. package/dist/commands/execute/handoff.d.mts +0 -1
  375. package/dist/commands/execute/handoff.mjs +0 -31
  376. package/dist/commands/execute/handoff.mjs.map +0 -1
  377. package/dist/commands/execute/incremental-carry.d.mts +0 -1
  378. package/dist/commands/execute/incremental-carry.mjs +0 -20
  379. package/dist/commands/execute/incremental-carry.mjs.map +0 -1
  380. package/dist/commands/execute/incremental-scope.d.mts +0 -1
  381. package/dist/commands/execute/incremental-scope.mjs +0 -29
  382. package/dist/commands/execute/incremental-scope.mjs.map +0 -1
  383. package/dist/commands/execute/integrate-stages.d.mts +0 -1
  384. package/dist/commands/execute/integrate-stages.mjs +0 -24
  385. package/dist/commands/execute/integrate-stages.mjs.map +0 -1
  386. package/dist/commands/execute/pane-title.d.mts +0 -1
  387. package/dist/commands/execute/pane-title.mjs +0 -20
  388. package/dist/commands/execute/pane-title.mjs.map +0 -1
  389. package/dist/commands/execute/plan-items.d.mts +0 -1
  390. package/dist/commands/execute/plan-items.mjs +0 -9
  391. package/dist/commands/execute/plan-items.mjs.map +0 -1
  392. package/dist/commands/execute/plan-validate.d.mts +0 -1
  393. package/dist/commands/execute/plan-validate.mjs +0 -68
  394. package/dist/commands/execute/plan-validate.mjs.map +0 -1
  395. package/dist/commands/execute/plan-verify.d.mts +0 -1
  396. package/dist/commands/execute/plan-verify.mjs +0 -43
  397. package/dist/commands/execute/plan-verify.mjs.map +0 -1
  398. package/dist/commands/execute/spawn-followups.d.mts +0 -1
  399. package/dist/commands/execute/spawn-followups.mjs +0 -22
  400. package/dist/commands/execute/spawn-followups.mjs.map +0 -1
  401. package/dist/commands/execute/team.d.mts +0 -3
  402. package/dist/commands/execute/team.mjs +0 -66
  403. package/dist/commands/execute/team.mjs.map +0 -1
  404. package/dist/commands/execute/token-usage.d.mts +0 -1
  405. package/dist/commands/execute/token-usage.mjs +0 -19
  406. package/dist/commands/execute/token-usage.mjs.map +0 -1
  407. package/dist/commands/execute/worker-audit-check.d.mts +0 -1
  408. package/dist/commands/execute/worker-audit-check.mjs +0 -34
  409. package/dist/commands/execute/worker-audit-check.mjs.map +0 -1
  410. package/dist/commands/execute/worker-dispatch.d.mts +0 -7
  411. package/dist/commands/execute/worker-dispatch.mjs +0 -64
  412. package/dist/commands/execute/worker-dispatch.mjs.map +0 -1
  413. package/dist/commands/execute/worker-state.d.mts +0 -1
  414. package/dist/commands/execute/worker-state.mjs +0 -28
  415. package/dist/commands/execute/worker-state.mjs.map +0 -1
  416. package/dist/commands/execute/worktree-lookup.d.mts +0 -1
  417. package/dist/commands/execute/worktree-lookup.mjs +0 -92
  418. package/dist/commands/execute/worktree-lookup.mjs.map +0 -1
  419. package/dist/commands/execute/worktree-status.d.mts +0 -1
  420. package/dist/commands/execute/worktree-status.mjs +0 -121
  421. package/dist/commands/execute/worktree-status.mjs.map +0 -1
  422. package/dist/commands/inspect/code-review.d.mts +0 -1
  423. package/dist/commands/inspect/code-review.mjs +0 -32
  424. package/dist/commands/inspect/code-review.mjs.map +0 -1
  425. package/dist/commands/inspect/container.d.mts +0 -1
  426. package/dist/commands/inspect/container.mjs +0 -25
  427. package/dist/commands/inspect/container.mjs.map +0 -1
  428. package/dist/commands/inspect/context-cost.d.mts +0 -1
  429. package/dist/commands/inspect/context-cost.mjs +0 -25
  430. package/dist/commands/inspect/context-cost.mjs.map +0 -1
  431. package/dist/commands/inspect/design-prep.d.mts +0 -1
  432. package/dist/commands/inspect/design-prep.mjs +0 -22
  433. package/dist/commands/inspect/design-prep.mjs.map +0 -1
  434. package/dist/commands/inspect/error-report.d.mts +0 -1
  435. package/dist/commands/inspect/error-report.mjs +0 -25
  436. package/dist/commands/inspect/error-report.mjs.map +0 -1
  437. package/dist/commands/inspect/error-zip.d.mts +0 -1
  438. package/dist/commands/inspect/error-zip.mjs +0 -24
  439. package/dist/commands/inspect/error-zip.mjs.map +0 -1
  440. package/dist/commands/inspect/log-report.d.mts +0 -1
  441. package/dist/commands/inspect/log-report.mjs +0 -26
  442. package/dist/commands/inspect/log-report.mjs.map +0 -1
  443. package/dist/commands/inspect/model-io.d.mts +0 -1
  444. package/dist/commands/inspect/model-io.mjs +0 -25
  445. package/dist/commands/inspect/model-io.mjs.map +0 -1
  446. package/dist/commands/inspect/profile-show.d.mts +0 -1
  447. package/dist/commands/inspect/profile-show.mjs +0 -28
  448. package/dist/commands/inspect/profile-show.mjs.map +0 -1
  449. package/dist/commands/inspect/recap.d.mts +0 -1
  450. package/dist/commands/inspect/recap.mjs +0 -30
  451. package/dist/commands/inspect/recap.mjs.map +0 -1
  452. package/dist/commands/inspect/resolve-task-key.d.mts +0 -1
  453. package/dist/commands/inspect/resolve-task-key.mjs +0 -24
  454. package/dist/commands/inspect/resolve-task-key.mjs.map +0 -1
  455. package/dist/commands/inspect/rollup.d.mts +0 -1
  456. package/dist/commands/inspect/rollup.mjs +0 -25
  457. package/dist/commands/inspect/rollup.mjs.map +0 -1
  458. package/dist/commands/inspect/run-audit.d.mts +0 -1
  459. package/dist/commands/inspect/run-audit.mjs +0 -25
  460. package/dist/commands/inspect/run-audit.mjs.map +0 -1
  461. package/dist/commands/inspect/set-work-status.d.mts +0 -1
  462. package/dist/commands/inspect/set-work-status.mjs +0 -29
  463. package/dist/commands/inspect/set-work-status.mjs.map +0 -1
  464. package/dist/commands/inspect/stage-map.d.mts +0 -1
  465. package/dist/commands/inspect/stage-map.mjs +0 -131
  466. package/dist/commands/inspect/stage-map.mjs.map +0 -1
  467. package/dist/commands/inspect/task-list.d.mts +0 -1
  468. package/dist/commands/inspect/task-list.mjs +0 -149
  469. package/dist/commands/inspect/task-list.mjs.map +0 -1
  470. package/dist/commands/inspect/task-show.d.mts +0 -1
  471. package/dist/commands/inspect/task-show.mjs +0 -108
  472. package/dist/commands/inspect/task-show.mjs.map +0 -1
  473. package/dist/commands/inspect/time-report.d.mts +0 -1
  474. package/dist/commands/inspect/time-report.mjs +0 -24
  475. package/dist/commands/inspect/time-report.mjs.map +0 -1
  476. package/dist/commands/inspect/usage-report.d.mts +0 -1
  477. package/dist/commands/inspect/usage-report.mjs +0 -23
  478. package/dist/commands/inspect/usage-report.mjs.map +0 -1
  479. package/dist/commands/inspect/user-response.d.mts +0 -1
  480. package/dist/commands/inspect/user-response.mjs +0 -35
  481. package/dist/commands/inspect/user-response.mjs.map +0 -1
  482. package/dist/commands/inspect/worker-liveness.d.mts +0 -1
  483. package/dist/commands/inspect/worker-liveness.mjs +0 -45
  484. package/dist/commands/inspect/worker-liveness.mjs.map +0 -1
  485. package/dist/commands/lifecycle/contract-check.d.mts +0 -1
  486. package/dist/commands/lifecycle/contract-check.mjs +0 -18
  487. package/dist/commands/lifecycle/contract-check.mjs.map +0 -1
  488. package/dist/commands/lifecycle/migrate.d.mts +0 -1
  489. package/dist/commands/lifecycle/migrate.mjs +0 -30
  490. package/dist/commands/lifecycle/migrate.mjs.map +0 -1
  491. package/dist/commands/lifecycle/model.d.mts +0 -1
  492. package/dist/commands/lifecycle/model.mjs +0 -22
  493. package/dist/commands/lifecycle/model.mjs.map +0 -1
  494. package/dist/commands/manager.d.mts +0 -3
  495. package/dist/commands/manager.mjs +0 -50
  496. package/dist/commands/manager.mjs.map +0 -1
  497. package/dist/commands/report/agent-activity.d.mts +0 -1
  498. package/dist/commands/report/agent-activity.mjs +0 -20
  499. package/dist/commands/report/agent-activity.mjs.map +0 -1
  500. package/dist/commands/report/approval-decision.d.mts +0 -1
  501. package/dist/commands/report/approval-decision.mjs +0 -21
  502. package/dist/commands/report/approval-decision.mjs.map +0 -1
  503. package/dist/commands/report/design-snapshot.d.mts +0 -1
  504. package/dist/commands/report/design-snapshot.mjs +0 -19
  505. package/dist/commands/report/design-snapshot.mjs.map +0 -1
  506. package/dist/commands/report/finalize.d.mts +0 -4
  507. package/dist/commands/report/finalize.mjs +0 -64
  508. package/dist/commands/report/finalize.mjs.map +0 -1
  509. package/dist/commands/report/inject-report-index.d.mts +0 -1
  510. package/dist/commands/report/inject-report-index.mjs +0 -21
  511. package/dist/commands/report/inject-report-index.mjs.map +0 -1
  512. package/dist/commands/report/render-final-report.d.mts +0 -1
  513. package/dist/commands/report/render-final-report.mjs +0 -23
  514. package/dist/commands/report/render-final-report.mjs.map +0 -1
  515. package/dist/commands/report/render-views.d.mts +0 -1
  516. package/dist/commands/report/render-views.mjs +0 -27
  517. package/dist/commands/report/render-views.mjs.map +0 -1
  518. package/dist/commands/report/translate.d.mts +0 -1
  519. package/dist/commands/report/translate.mjs +0 -33
  520. package/dist/commands/report/translate.mjs.map +0 -1
  521. package/runtime/bin/lib/okstra/tmux-pane.sh +0 -40
  522. package/runtime/bin/lib/okstra-ctl/cmd-batch.sh +0 -59
  523. package/runtime/bin/lib/okstra-ctl/cmd-list.sh +0 -35
  524. package/runtime/bin/lib/okstra-ctl/cmd-open.sh +0 -36
  525. package/runtime/bin/lib/okstra-ctl/cmd-projects.sh +0 -26
  526. package/runtime/bin/lib/okstra-ctl/cmd-reconcile.sh +0 -29
  527. package/runtime/bin/lib/okstra-ctl/cmd-reindex.sh +0 -38
  528. package/runtime/bin/lib/okstra-ctl/cmd-rerun.sh +0 -345
  529. package/runtime/bin/lib/okstra-ctl/cmd-show.sh +0 -27
  530. package/runtime/bin/lib/okstra-ctl/cmd-tail.sh +0 -92
  531. package/runtime/bin/lib/okstra-ctl/main.sh +0 -41
  532. package/runtime/bin/lib/okstra-ctl/prepare.sh +0 -31
  533. package/runtime/bin/lib/okstra-ctl/usage.sh +0 -23
  534. package/runtime/bin/okstra-central.sh +0 -152
  535. package/runtime/bin/okstra-incremental-carry.py +0 -10
  536. package/runtime/bin/okstra-incremental-scope.py +0 -10
  537. package/runtime/bin/okstra-team-reconcile.sh +0 -36
  538. package/runtime/python/okstra_ctl/agent_prompt_cli.py +0 -1156
  539. package/runtime/python/okstra_ctl/batch.py +0 -60
  540. package/runtime/python/okstra_ctl/clarification_items.py +0 -1050
  541. package/runtime/python/okstra_ctl/container_registry.py +0 -72
  542. package/runtime/python/okstra_ctl/improvement_assignment.py +0 -61
  543. package/runtime/python/okstra_ctl/resolver.py +0 -54
  544. package/runtime/python/okstra_ctl/team_reconcile.py +0 -275
  545. package/runtime/python/okstra_ctl/tmux.py +0 -134
  546. package/runtime/python/okstra_ctl/worktree.py +0 -1099
@@ -42,11 +42,15 @@ from dataclasses import dataclass
42
42
  from pathlib import Path
43
43
  from typing import Any, Callable, Mapping, Sequence
44
44
 
45
- from .agent_activity import ActivityProjectionError, project_agent_activity
45
+ from .agent.activity import ActivityProjectionError, project_agent_activity
46
46
  from .report_contract import apply_execution_roles
47
47
  from .report_assembly import ReportAssemblyError, assemble_report
48
48
  from .dispatch_state import DispatchError, link_agent_dispatch_result
49
- from .final_report_paths import final_report_data_path, final_report_markdown_path
49
+ from .final_report_paths import (
50
+ final_report_data_path,
51
+ final_report_markdown_path,
52
+ sidecar_source_rel,
53
+ )
50
54
  from .paths import task_dir, task_manifest_file
51
55
  from .release_gate import release_handoff_allowed
52
56
  from .json_boundary import JsonBoundaryError, load_owned_object, write_owned_object_atomic
@@ -57,6 +61,16 @@ from .stage_targets import (
57
61
  )
58
62
  from .session import observe_lead_session
59
63
 
64
+ # 포인터 값 타입만 쓴다. `okstra_project.phase_pointer` 는 okstra 안의
65
+ # 어떤 것도 import 하지 않는 leaf 라 순환이 없다 — 그 모듈 도크스트링.
66
+ from okstra_project.phase_pointer import (
67
+ STATUS_BLOCKED,
68
+ STATUS_PENDING,
69
+ STATUS_READY,
70
+ STATUS_TERMINAL,
71
+ promote as promote_next_phase,
72
+ )
73
+
60
74
 
61
75
  STEP_PROJECT_ACTIVITY = "project-activity"
62
76
  STEP_CHECK_SOURCE = "check-source"
@@ -120,13 +134,6 @@ def resolve_optional_path(project_root: Path, value: Any) -> Path | None:
120
134
  return resolve_project_path(project_root, value)
121
135
 
122
136
 
123
- def project_relative_path(project_root: Path, path: Path) -> str:
124
- try:
125
- return path.relative_to(project_root).as_posix()
126
- except ValueError:
127
- return str(path)
128
-
129
-
130
137
  def task_group(manifest: Mapping[str, Any]) -> str:
131
138
  value = string_value(manifest.get("taskGroup"))
132
139
  if value:
@@ -337,8 +344,15 @@ def build_commands(ctx: FinalizeContext) -> list[tuple[str, list[str]]]:
337
344
  ctx.task_type,
338
345
  "--seq",
339
346
  ctx.seq,
347
+ # 사이드카가 되짚는 기준은 태스크 루트다. 프로젝트 루트
348
+ # 기준으로 넘기던 동안 HTML Export 가 만든 사이드카는
349
+ # 방향 선택 게이트를 통과할 수 없었다.
340
350
  "--source-report",
341
- project_relative_path(ctx.project_root, markdown_path),
351
+ sidecar_source_rel(markdown_path),
352
+ # 머리말 소요 시간의 출처. 보고서 seq 로 되짚으면 seq 가 갈린
353
+ # run 의 team-state 를 읽는다 — 여기서는 이미 알고 있다.
354
+ "--team-state",
355
+ str(ctx.team_state_path),
342
356
  ],
343
357
  ),
344
358
  (
@@ -491,9 +505,47 @@ def run_finalize(
491
505
  steps.append(step_payload(name, command, result))
492
506
  if result.returncode != 0 and not first_failure:
493
507
  first_failure = f"{name} failed with exit code {result.returncode}"
494
- if first_failure:
495
- return {"ok": False, "reason": first_failure, "steps": steps}
496
- return {"ok": True, "reason": "", "steps": steps}
508
+ pointer, pointer_error = _recorded_next_phase(ctx)
509
+ payload: dict[str, Any] = {
510
+ "ok": not first_failure,
511
+ "reason": first_failure,
512
+ "steps": steps,
513
+ "nextRecommendedPhase": pointer,
514
+ }
515
+ if pointer_error:
516
+ payload["nextRecommendedPhaseError"] = pointer_error
517
+ # closeout 이 실제로 건넬 명령. 표를 리드의 기억에 맡기지 않는다.
518
+ payload["nextCommand"] = closeout_command(payload)
519
+ return payload
520
+
521
+
522
+ def _recorded_next_phase(ctx: FinalizeContext) -> tuple[dict[str, str], str]:
523
+ """`validate-run` 이 방금 태스크 매니페스트에 쓴 다음 phase 포인터.
524
+
525
+ 리드의 closeout 표는 이 포인터의 `status` / `rationale` 로 분기하는데,
526
+ 포인터는 리드가 쓰는 필드가 아니고(`prompts/lead/report-writer.md`
527
+ "Nobody writes this pointer by hand"), 이 시퀀스의 결과에도 실리지
528
+ 않았다. 값 없이 표만 받은 리드에게 남는 행동은 상태를 늘어놓고 턴을
529
+ 끝내는 것뿐이다.
530
+
531
+ 여기서 다시 계산하지 않는다 — 투영은 `validate-run` 의
532
+ `update_workflow_metadata` 가 하고, 이 함수는 그것이 파일에 남긴 값을
533
+ 읽어 옮기기만 한다. `--only` 로 `validate-run` 을 건너뛴 호출에서는
534
+ 이전 run 이 남긴 값이 그대로 읽히므로, 이번 시퀀스가 그 단계를 돌았는지는
535
+ `steps` 로 판단한다.
536
+
537
+ 읽기가 실패하면 값을 지어내지 않고 사유를 함께 돌려준다.
538
+ """
539
+ try:
540
+ manifest = load_owned_object(
541
+ ctx.task_manifest_path, artifact="task-manifest"
542
+ )
543
+ except (JsonBoundaryError, OSError) as exc:
544
+ return promote_next_phase(None), f"{ctx.task_manifest_path}: {exc}"
545
+ workflow = manifest.get("workflow")
546
+ if not isinstance(workflow, Mapping):
547
+ return promote_next_phase(None), ""
548
+ return promote_next_phase(workflow.get("nextRecommendedPhase")), ""
497
549
 
498
550
 
499
551
  def _run_finalize_step(
@@ -529,6 +581,7 @@ def _run_project_activity(
529
581
  try:
530
582
  if ctx.report_contract_version == "3.0":
531
583
  assembled = assemble_report(ctx.project_root, ctx.manifest_path)
584
+ _point_task_manifest_at_report(ctx)
532
585
  count = len(assembled.get("agentActivity") or [])
533
586
  else:
534
587
  rows = project_agent_activity(
@@ -556,6 +609,34 @@ def write_execution_roles(ctx: FinalizeContext) -> None:
556
609
  write_owned_object_atomic(ctx.data_path, updated, artifact="final report record")
557
610
 
558
611
 
612
+ def _point_task_manifest_at_report(ctx: FinalizeContext) -> None:
613
+ """게시한 data.json 을 latestReport 로 올린다.
614
+
615
+ render-only prepare 는 기존 포인터를 보존한다. 조립이 새 리포트를 썼는데도
616
+ task-manifest 가 예전 seq 를 가리키면 검사가 통과해도 상태가 004 에 남는다.
617
+ """
618
+ path = ctx.task_manifest_path
619
+ if not path.is_file() or not ctx.data_path.is_file():
620
+ return
621
+ try:
622
+ payload = load_owned_object(path, artifact="task manifest")
623
+ except (OSError, JsonBoundaryError):
624
+ return
625
+ if not isinstance(payload, Mapping):
626
+ return
627
+ try:
628
+ relative = ctx.data_path.resolve().relative_to(
629
+ ctx.project_root.resolve()
630
+ ).as_posix()
631
+ except ValueError:
632
+ relative = str(ctx.data_path)
633
+ if payload.get("latestReportRecordPath") == relative:
634
+ return
635
+ updated = dict(payload)
636
+ updated["latestReportRecordPath"] = relative
637
+ write_owned_object_atomic(path, updated, artifact="task manifest")
638
+
639
+
559
640
  def _link_lead_result_for_validation(ctx: FinalizeContext) -> None:
560
641
  """Link the lead-authored synthesis artifact before Phase 7 validation."""
561
642
  manifest = _load_manifest(ctx.manifest_path)
@@ -566,8 +647,11 @@ def _link_lead_result_for_validation(ctx: FinalizeContext) -> None:
566
647
  lead_dispatches = [
567
648
  row for row in (team_state.get("agentDispatches") or [])
568
649
  if isinstance(row, Mapping)
569
- and row.get("audience") == "lead"
570
- and row.get("workerId") == "lead"
650
+ and (
651
+ row.get("audience") == "lead"
652
+ or row.get("workerId") == "lead"
653
+ or str(row.get("assignmentRef") or "") in {"lead", "lead/lead"}
654
+ )
571
655
  ]
572
656
  if len(lead_dispatches) != 1:
573
657
  return
@@ -621,8 +705,41 @@ def _context_from_args(args: argparse.Namespace) -> FinalizeContext:
621
705
  )
622
706
 
623
707
 
708
+ _CLI_EPILOG = r"""Usage:
709
+ okstra report-finalize --project-root <dir> --run-manifest <path> \
710
+ --report <final-report-<task-type>-<seq>.md> [--team-state <path>]
711
+
712
+ Runs the six Phase 7 steps in their contractual order against one final-report:
713
+
714
+ 1. project-activity project the run's activity events into the data.json
715
+ 2. check-source verify the data.json is the English SSOT
716
+ 3. token-usage substitute real token/cost numbers into the data.json
717
+ 4. render-views write the schema-v2 task-specific *.html sibling; v1
718
+ keeps the legacy conditional interactive view
719
+ 5. spawn-followups turn section 4 rows into task stubs
720
+ 6. validate-run validate the finished run artifacts
721
+
722
+ Every step is idempotent, so re-running after a fixed failure is safe. The
723
+ sequence stops at the first non-zero exit and reports which step failed, except
724
+ token-usage: its input is the lead session log, so a failure there does not
725
+ take the html, follow-ups and validation after it down with it. Whenever a step
726
+ exits non-zero the command prints the --only flags that resume the sequence
727
+ from the earliest failing step — follow those rather than rerunning the failing
728
+ step alone, which would leave the html rendered before the tokens landed.
729
+
730
+ This is the same code path the Codex lead adapter runs automatically after its
731
+ report-writer completes, so a Claude-led and a Codex-led run finalize
732
+ identically.
733
+
734
+ --workspace-root is owned by this command.
735
+ """
736
+
737
+
624
738
  def _parser() -> argparse.ArgumentParser:
625
739
  parser = argparse.ArgumentParser(
740
+ prog="okstra report-finalize",
741
+ epilog=_CLI_EPILOG,
742
+ formatter_class=argparse.RawDescriptionHelpFormatter,
626
743
  description="Run the Phase 7 report post-processing sequence.",
627
744
  )
628
745
  parser.add_argument("--project-root", required=True)
@@ -632,7 +749,9 @@ def _parser() -> argparse.ArgumentParser:
632
749
  required=True,
633
750
  help="final-report record (.data.json); a leftover markdown path still locates the sibling record",
634
751
  )
635
- parser.add_argument("--workspace-root", required=True)
752
+ # `okstra report-finalize` 래퍼(src/lib/python-command.mts)가 넣고, 사용자가
753
+ # 직접 주면 거절한다. usage 에 필수로 찍히면 그 거절과 모순되므로 감춘다.
754
+ parser.add_argument("--workspace-root", required=True, help=argparse.SUPPRESS)
636
755
  parser.add_argument(
637
756
  "--team-state",
638
757
  default="",
@@ -691,6 +810,80 @@ def _recovery_step_names(
691
810
  return []
692
811
 
693
812
 
813
+ def closeout_command(result: Mapping[str, Any]) -> dict[str, str]:
814
+ """이 run 이 사용자에게 건네야 할 명령.
815
+
816
+ `prompts/launch.template.md` "User closeout (BLOCKING)" 의 표를 코드로
817
+ 내린 것이다. 그 표는 문서에만 있었고, 표가 분기하는 포인터는 리드에게
818
+ 도착하지도 않았다 — 규칙이 있고 집행이 없는 자리였다. 여기서 판정하면
819
+ 리드가 표를 기억해 따라갈 필요가 없고, 리드가 침묵해도 명령은
820
+ `report-finalize` 출력에 남는다.
821
+
822
+ 산문을 해석하지 않는다. `blocked` / `pending` 의 근거 문장은 이미 무엇을
823
+ 실행할지 말하고 있으므로(`okstra_ctl.next_phase` 의 승인 차단 근거,
824
+ `validators/validate-run.py` 의 검증 실패 근거), 그 문장을 그대로 인용할
825
+ 자리로 넘기고 명령 칸은 비운다. 근거에서 명령을 다시 뽑아내는 것은
826
+ 기록된 값의 재구현이다.
827
+
828
+ 돌려주는 것은 `command` 와 `note` 두 칸이다. `command` 가 비면 근거
829
+ 문장이 그 자리를 대신한다.
830
+ """
831
+ failed_validate = any(
832
+ step.get("name") == STEP_VALIDATE_RUN and step.get("exitCode") != 0
833
+ for step in (result.get("steps") or [])
834
+ if isinstance(step, Mapping)
835
+ )
836
+ if failed_validate:
837
+ return {
838
+ "command": "/okstra-run",
839
+ "note": "validate-run failed — name the blocking cause in one line, "
840
+ "then re-run this same phase",
841
+ }
842
+ pointer = result.get("nextRecommendedPhase")
843
+ if not isinstance(pointer, Mapping):
844
+ return {"command": "/okstra-inspect status", "note": "no pointer recorded"}
845
+ status = str(pointer.get("status") or "").strip()
846
+ phase = str(pointer.get("phase") or "").strip()
847
+ rationale = str(pointer.get("rationale") or "").strip()
848
+ if status == STATUS_READY and phase:
849
+ return {"command": f"/okstra-run → {phase}", "note": ""}
850
+ if status == STATUS_TERMINAL:
851
+ return {
852
+ "command": "",
853
+ "note": "the lifecycle ends here — say the task is finished, name any "
854
+ "follow-up tasks this run registered, and do not send the user "
855
+ "to /okstra-inspect",
856
+ }
857
+ if status in (STATUS_BLOCKED, STATUS_PENDING) and rationale:
858
+ return {
859
+ "command": "",
860
+ "note": "quote the rationale above and issue the command it names",
861
+ }
862
+ return {"command": "/okstra-inspect status", "note": ""}
863
+
864
+
865
+ def _next_phase_summary_lines(result: Mapping[str, Any]) -> list[str]:
866
+ """다음 phase 포인터와 그것이 정하는 명령을 사람이 읽는 줄로."""
867
+ pointer = result.get("nextRecommendedPhase")
868
+ if not isinstance(pointer, Mapping):
869
+ return []
870
+ lines = [
871
+ f"next phase status: {pointer.get('status') or '-'}",
872
+ f"next phase: {pointer.get('phase') or '-'}",
873
+ ]
874
+ rationale = str(pointer.get("rationale") or "").strip()
875
+ if rationale:
876
+ lines.append(f"next phase rationale: {rationale}")
877
+ error = str(result.get("nextRecommendedPhaseError") or "").strip()
878
+ if error:
879
+ lines.append(f"next phase pointer unreadable: {error}")
880
+ closeout = closeout_command(result)
881
+ lines.append(f"next command: {closeout['command'] or '-'}")
882
+ if closeout["note"]:
883
+ lines.append(f"next command note: {closeout['note']}")
884
+ return lines
885
+
886
+
694
887
  def main(argv: Sequence[str] | None = None) -> int:
695
888
  args = _parser().parse_args(argv)
696
889
  try:
@@ -708,6 +901,10 @@ def main(argv: Sequence[str] | None = None) -> int:
708
901
  print("finalize steps:", file=sys.stderr)
709
902
  for line in _step_summary_lines(result, order):
710
903
  print(line, file=sys.stderr)
904
+ # closeout 이 분기하는 값. JSON 을 파싱하지 않고 훑는 리드에게도 보이도록
905
+ # 요약 줄로 한 번 더 낸다.
906
+ for line in _next_phase_summary_lines(result):
907
+ print(line, file=sys.stderr)
711
908
  if not result["ok"]:
712
909
  print(f"error: {result['reason']}", file=sys.stderr)
713
910
  recovery = _recovery_step_names(result, order)
@@ -68,8 +68,8 @@ def _own_section_ids(data: dict, omitted_fields: tuple[str, ...] = ()) -> set[st
68
68
 
69
69
  The ledger is the fallback home for a cited row, so it must not claim an id
70
70
  that has one — two elements with the same anchor send half the links to the
71
- wrong place. `crossVerification.consensus` numbers its rows `C-001` in some
72
- runs, exactly where a clarification lives.
71
+ wrong place. `crossVerification.consensus` numbers its rows `CV-001`, a
72
+ namespace of its own, so a `C-NNN` in the report has exactly one home.
73
73
 
74
74
  `omitted_fields` names task-block fields the HTML template does not render,
75
75
  so their ids do not count as anchored.
@@ -69,25 +69,21 @@ def _report_meta(data: dict, run_meta: HtmlRunMeta) -> dict[str, object]:
69
69
 
70
70
 
71
71
  def _localize(data: dict, data_path: Path) -> tuple[dict, str]:
72
- """Apply the translation sidecar for this report's language, if there is one.
73
-
74
- The data.json is the English SSOT and is never rewritten — the sidecar is
75
- read here and overlaid onto an in-memory copy, so only this HTML document
76
- speaks the reader's language. A pointer the sidecar left untranslated
77
- renders in English; that keeps a half-finished translation readable, and
78
- the counts are printed because a silently half-empty sidecar otherwise
79
- ships looking finished.
72
+ """이 리포트 언어의 번역 사이드카를 메모리 복사본에 덮어쓴다.
73
+
74
+ data.json 은 영어 정본이고 고치지 않는다. 사람이 읽는 HTML 만 독자 언어다.
75
+ 사이드카가 빠진 포인터는 영어로 남긴다. 사이드카 파일 자체가 없으면
76
+ 크롬만 번역되고 본문은 영어로 나가므로 렌더를 거부한다.
80
77
  """
81
78
  lang = str((data.get("meta") or {}).get("reportLanguage") or "en")
82
79
  if lang == "en":
83
80
  return data, lang
84
81
  sidecar_file = translation_sidecar_path(data_path, lang)
85
82
  if not sidecar_file.is_file():
86
- sys.stdout.write(
87
- f"note: no {lang} translation sidecar at {sidecar_file.name}; "
88
- "rendering the English source\n"
83
+ raise HtmlRenderError(
84
+ f"no {lang} translation sidecar at {sidecar_file.name}; "
85
+ "human HTML cannot fall back to the English source"
89
86
  )
90
- return data, lang
91
87
  payload = load_owned_object(sidecar_file, artifact="translation sidecar")
92
88
  strings = payload.get("strings")
93
89
  if not isinstance(strings, dict):
@@ -1,8 +1,12 @@
1
- """Report-language resolution for the report-writer prompt.
1
+ """Report-language resolution — the one place the precedence lives.
2
2
 
3
- Both dispatchers stamp `**Report Language:**` into the report-writer prompt, so
4
- the precedence (project config → global config → inferred from the task brief)
5
- lives here rather than in whichever dispatcher happened to need it first.
3
+ Two surfaces need the answer and must agree: the `**Report Language:**` line
4
+ both dispatchers stamp into the report-writer prompt, and `reportLanguage` in
5
+ the run manifest, which report assembly copies into `meta.reportLanguage` and
6
+ the HTML renderer reads. When only the prompt called this, a project could ask
7
+ for `ko`, get a Korean-instructed writer, and still ship an English report.
8
+
9
+ Precedence: project config → global config → inferred from the task brief.
6
10
  """
7
11
  from __future__ import annotations
8
12