okstra 0.186.7 → 0.187.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 (541) 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 +104 -39
  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 +37 -36
  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 +25 -18
  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/convergence.md +96 -87
  100. package/runtime/prompts/lead/okstra-lead-contract.md +63 -12
  101. package/runtime/prompts/lead/plan-body-verification.md +65 -46
  102. package/runtime/prompts/lead/report-writer.md +34 -4
  103. package/runtime/prompts/lead/team-contract.md +4 -1
  104. package/runtime/prompts/profiles/_clarification-recommendation.md +2 -1
  105. package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
  106. package/runtime/prompts/profiles/_common-contract.md +3 -3
  107. package/runtime/prompts/profiles/_coverage-critic.md +1 -1
  108. package/runtime/prompts/profiles/_implementation-deliverable.md +2 -2
  109. package/runtime/prompts/profiles/_implementation-executor.md +3 -1
  110. package/runtime/prompts/profiles/_implementation-verifier.md +16 -2
  111. package/runtime/prompts/profiles/error-analysis.md +4 -3
  112. package/runtime/prompts/profiles/final-verification.md +2 -2
  113. package/runtime/prompts/profiles/implementation-planning.md +22 -17
  114. package/runtime/prompts/profiles/implementation.md +3 -2
  115. package/runtime/prompts/profiles/requirements-discovery.md +2 -1
  116. package/runtime/prompts/wizard/prompts.ko.json +29 -8
  117. package/runtime/python/okstra_ctl/__init__.py +6 -27
  118. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -5
  119. package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +21 -2
  120. package/runtime/python/okstra_ctl/adapters/hosts/external/adapter.py +3 -12
  121. package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +40 -22
  122. package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +14 -21
  123. package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +37 -20
  124. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +86 -14
  125. package/runtime/python/okstra_ctl/adapters/providers/kimi/adapter.py +12 -12
  126. package/runtime/python/okstra_ctl/adapters/runtime/cmux.py +4 -7
  127. package/runtime/python/okstra_ctl/agent/__init__.py +1 -0
  128. package/runtime/python/okstra_ctl/{agent_activity.py → agent/activity.py} +12 -1
  129. package/runtime/python/okstra_ctl/{agent_invocation.py → agent/invocation.py} +34 -5
  130. package/runtime/python/okstra_ctl/agent/prompt_cli/__init__.py +19 -0
  131. package/runtime/python/okstra_ctl/agent/prompt_cli/__main__.py +11 -0
  132. package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +215 -0
  133. package/runtime/python/okstra_ctl/agent/prompt_cli/dynamic_verifier.py +155 -0
  134. package/runtime/python/okstra_ctl/agent/prompt_cli/emit.py +66 -0
  135. package/runtime/python/okstra_ctl/agent/prompt_cli/inputs.py +138 -0
  136. package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +408 -0
  137. package/runtime/python/okstra_ctl/agent/prompt_cli/results.py +197 -0
  138. package/runtime/python/okstra_ctl/agent/prompt_cli/run_identity.py +107 -0
  139. package/runtime/python/okstra_ctl/analysis_packet.py +47 -4
  140. package/runtime/python/okstra_ctl/approval_decisions.py +260 -8
  141. package/runtime/python/okstra_ctl/assignment_resolver.py +0 -12
  142. package/runtime/python/okstra_ctl/attempt_evidence.py +12 -24
  143. package/runtime/python/okstra_ctl/blocking_checks.py +251 -0
  144. package/runtime/python/okstra_ctl/brief_frontmatter.py +0 -7
  145. package/runtime/python/okstra_ctl/clarification_items/__init__.py +102 -0
  146. package/runtime/python/okstra_ctl/clarification_items/carry.py +224 -0
  147. package/runtime/python/okstra_ctl/clarification_items/dispositions.py +135 -0
  148. package/runtime/python/okstra_ctl/clarification_items/parsing.py +253 -0
  149. package/runtime/python/okstra_ctl/clarification_items/rows.py +115 -0
  150. package/runtime/python/okstra_ctl/clarification_items/scan.py +215 -0
  151. package/runtime/python/okstra_ctl/clarification_items/sidecars.py +211 -0
  152. package/runtime/python/okstra_ctl/cmux.py +38 -31
  153. package/runtime/python/okstra_ctl/code_review_target.py +163 -1
  154. package/runtime/python/okstra_ctl/conformance.py +23 -0
  155. package/runtime/python/okstra_ctl/container.py +38 -421
  156. package/runtime/python/okstra_ctl/context_cost.py +16 -2
  157. package/runtime/python/okstra_ctl/contract_graph_cli.py +7 -0
  158. package/runtime/python/okstra_ctl/convergence.py +101 -15
  159. package/runtime/python/okstra_ctl/convergence_critic_prompt.py +345 -0
  160. package/runtime/python/okstra_ctl/convergence_engine.py +382 -70
  161. package/runtime/python/okstra_ctl/convergence_store.py +5 -29
  162. package/runtime/python/okstra_ctl/design_prep.py +108 -12
  163. package/runtime/python/okstra_ctl/design_snapshot.py +11 -1
  164. package/runtime/python/okstra_ctl/design_surfaces.py +29 -2
  165. package/runtime/python/okstra_ctl/dispatch_core.py +102 -25
  166. package/runtime/python/okstra_ctl/dispatch_state.py +268 -39
  167. package/runtime/python/okstra_ctl/doctor_cli.py +48 -0
  168. package/runtime/python/okstra_ctl/domain/worker_exec.py +10 -5
  169. package/runtime/python/okstra_ctl/domain/worker_presentation.py +21 -1
  170. package/runtime/python/okstra_ctl/domain/worker_stream.py +52 -21
  171. package/runtime/python/okstra_ctl/domain/write_policy.py +219 -0
  172. package/runtime/python/okstra_ctl/entrypoints/hosts.py +9 -2
  173. package/runtime/python/okstra_ctl/error_log_core.py +1 -1
  174. package/runtime/python/okstra_ctl/error_report.py +14 -0
  175. package/runtime/python/okstra_ctl/error_zip.py +18 -2
  176. package/runtime/python/okstra_ctl/execution_identity.py +100 -7
  177. package/runtime/python/okstra_ctl/execution_manifest.py +67 -20
  178. package/runtime/python/okstra_ctl/execution_mutation_audit.py +90 -8
  179. package/runtime/python/okstra_ctl/final_report_paths.py +17 -0
  180. package/runtime/python/okstra_ctl/final_report_schema.py +90 -16
  181. package/runtime/python/okstra_ctl/git_reconcile.py +22 -2
  182. package/runtime/python/okstra_ctl/handoff.py +24 -1
  183. package/runtime/python/okstra_ctl/ids.py +6 -16
  184. package/runtime/python/okstra_ctl/implementation_direction.py +142 -33
  185. package/runtime/python/okstra_ctl/implementation_options.py +25 -11
  186. package/runtime/python/okstra_ctl/implementation_outcome.py +5 -2
  187. package/runtime/python/okstra_ctl/improvement_lenses.py +0 -14
  188. package/runtime/python/okstra_ctl/incremental_carry.py +69 -8
  189. package/runtime/python/okstra_ctl/incremental_scope.py +173 -12
  190. package/runtime/python/okstra_ctl/index.py +2 -2
  191. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +48 -8
  192. package/runtime/python/okstra_ctl/interactive_cli.py +223 -0
  193. package/runtime/python/okstra_ctl/json_boundary.py +10 -0
  194. package/runtime/python/okstra_ctl/listing.py +0 -91
  195. package/runtime/python/okstra_ctl/locks.py +5 -19
  196. package/runtime/python/okstra_ctl/log_report.py +14 -0
  197. package/runtime/python/okstra_ctl/manager_cli.py +22 -3
  198. package/runtime/python/okstra_ctl/manager_launch.py +4 -8
  199. package/runtime/python/okstra_ctl/material.py +2 -2
  200. package/runtime/python/okstra_ctl/migrate.py +23 -1
  201. package/runtime/python/okstra_ctl/model_cli.py +19 -5
  202. package/runtime/python/okstra_ctl/model_discovery.py +46 -47
  203. package/runtime/python/okstra_ctl/model_io/__init__.py +1 -0
  204. package/runtime/python/okstra_ctl/model_io/lines.py +163 -0
  205. package/runtime/python/okstra_ctl/model_io/references.py +370 -0
  206. package/runtime/python/okstra_ctl/model_io/renderers.py +498 -0
  207. package/runtime/python/okstra_ctl/model_io_cli.py +30 -945
  208. package/runtime/python/okstra_ctl/model_pool.py +10 -6
  209. package/runtime/python/okstra_ctl/models.py +8 -8
  210. package/runtime/python/okstra_ctl/mutation_recovery.py +5 -63
  211. package/runtime/python/okstra_ctl/next_phase.py +121 -69
  212. package/runtime/python/okstra_ctl/pane_reclaim.py +23 -0
  213. package/runtime/python/okstra_ctl/pane_title.py +11 -8
  214. package/runtime/python/okstra_ctl/path_hints.py +36 -11
  215. package/runtime/python/okstra_ctl/paths.py +76 -8
  216. package/runtime/python/okstra_ctl/plan_items.py +132 -16
  217. package/runtime/python/okstra_ctl/plan_items_cli.py +486 -36
  218. package/runtime/python/okstra_ctl/plan_run_root.py +1 -1
  219. package/runtime/python/okstra_ctl/plan_validate_cli.py +51 -0
  220. package/runtime/python/okstra_ctl/plan_verify_cli.py +80 -0
  221. package/runtime/python/okstra_ctl/prepare_error.py +20 -0
  222. package/runtime/python/okstra_ctl/prior_planning.py +157 -0
  223. package/runtime/python/okstra_ctl/profile_show.py +18 -1
  224. package/runtime/python/okstra_ctl/project_setup_cli.py +140 -0
  225. package/runtime/python/okstra_ctl/recap.py +22 -1
  226. package/runtime/python/okstra_ctl/reconcile.py +84 -0
  227. package/runtime/python/okstra_ctl/registry/host_registry.py +18 -1
  228. package/runtime/python/okstra_ctl/render.py +98 -32
  229. package/runtime/python/okstra_ctl/render_final_report.py +3 -7
  230. package/runtime/python/okstra_ctl/report_assembly.py +297 -7
  231. package/runtime/python/okstra_ctl/report_contract.py +30 -7
  232. package/runtime/python/okstra_ctl/report_finalize.py +206 -15
  233. package/runtime/python/okstra_ctl/report_html/common.py +2 -2
  234. package/runtime/python/okstra_ctl/report_html/render.py +8 -12
  235. package/runtime/python/okstra_ctl/report_language.py +8 -4
  236. package/runtime/python/okstra_ctl/report_narrative.py +90 -3
  237. package/runtime/python/okstra_ctl/report_projections.py +8 -2
  238. package/runtime/python/okstra_ctl/report_synthesis_packet.py +258 -1
  239. package/runtime/python/okstra_ctl/report_translation.py +2 -35
  240. package/runtime/python/okstra_ctl/report_views.py +4 -22
  241. package/runtime/python/okstra_ctl/resolve_task_key.py +13 -0
  242. package/runtime/python/okstra_ctl/rollup.py +13 -0
  243. package/runtime/python/okstra_ctl/run.py +639 -138
  244. package/runtime/python/okstra_ctl/run_audit.py +13 -0
  245. package/runtime/python/okstra_ctl/run_index_row.py +0 -12
  246. package/runtime/python/okstra_ctl/seeding.py +21 -11
  247. package/runtime/python/okstra_ctl/sequence.py +1 -1
  248. package/runtime/python/okstra_ctl/session.py +64 -14
  249. package/runtime/python/okstra_ctl/set_work_status.py +18 -0
  250. package/runtime/python/okstra_ctl/stage_integrate.py +15 -1
  251. package/runtime/python/okstra_ctl/stage_ledger.py +1 -1
  252. package/runtime/python/okstra_ctl/stage_map.py +57 -11
  253. package/runtime/python/okstra_ctl/stage_map_cli.py +83 -0
  254. package/runtime/python/okstra_ctl/stage_map_view.py +65 -0
  255. package/runtime/python/okstra_ctl/stage_targets.py +3 -12
  256. package/runtime/python/okstra_ctl/task_list_cli.py +138 -0
  257. package/runtime/python/okstra_ctl/task_show_cli.py +66 -0
  258. package/runtime/python/okstra_ctl/task_target.py +4 -16
  259. package/runtime/python/okstra_ctl/team.py +49 -2
  260. package/runtime/python/okstra_ctl/time_report.py +17 -2
  261. package/runtime/python/okstra_ctl/usage_report.py +11 -0
  262. package/runtime/python/okstra_ctl/user_response.py +55 -218
  263. package/runtime/python/okstra_ctl/user_response_values.py +242 -0
  264. package/runtime/python/okstra_ctl/validation_contract.py +3 -0
  265. package/runtime/python/okstra_ctl/verification_target.py +68 -0
  266. package/runtime/python/okstra_ctl/wizard.py +457 -92
  267. package/runtime/python/okstra_ctl/worker_artifacts.py +75 -16
  268. package/runtime/python/okstra_ctl/worker_audit_check.py +22 -0
  269. package/runtime/python/okstra_ctl/worker_dispatch.py +21 -0
  270. package/runtime/python/okstra_ctl/worker_liveness.py +33 -0
  271. package/runtime/python/okstra_ctl/worker_prompt_body.py +15 -2
  272. package/runtime/python/okstra_ctl/worker_prompt_contract.py +98 -7
  273. package/runtime/python/okstra_ctl/worker_prompt_headers.py +24 -2
  274. package/runtime/python/okstra_ctl/worker_prompt_policy.py +18 -3
  275. package/runtime/python/okstra_ctl/worker_request.py +2 -1
  276. package/runtime/python/okstra_ctl/worker_runner.py +16 -9
  277. package/runtime/python/okstra_ctl/worker_state.py +16 -1
  278. package/runtime/python/okstra_ctl/workflow.py +18 -1
  279. package/runtime/python/okstra_ctl/worktree/__init__.py +92 -0
  280. package/runtime/python/okstra_ctl/worktree/cleanliness.py +89 -0
  281. package/runtime/python/okstra_ctl/worktree/decisions.py +127 -0
  282. package/runtime/python/okstra_ctl/worktree/git_ops.py +165 -0
  283. package/runtime/python/okstra_ctl/worktree/linking.py +249 -0
  284. package/runtime/python/okstra_ctl/worktree/naming.py +91 -0
  285. package/runtime/python/okstra_ctl/worktree/provision.py +385 -0
  286. package/runtime/python/okstra_ctl/worktree/sync_config.py +181 -0
  287. package/runtime/python/okstra_ctl/worktree_cli.py +75 -0
  288. package/runtime/python/okstra_ctl/worktree_lookup_cli.py +39 -0
  289. package/runtime/python/okstra_ctl/worktree_registry.py +7 -0
  290. package/runtime/python/okstra_ctl/worktree_status_cli.py +53 -0
  291. package/runtime/python/okstra_ctl/write_policy.py +90 -213
  292. package/runtime/python/okstra_project/__init__.py +0 -4
  293. package/runtime/python/okstra_project/dirs.py +2 -2
  294. package/runtime/python/okstra_project/phase_pointer.py +84 -0
  295. package/runtime/python/okstra_project/slug.py +24 -0
  296. package/runtime/python/okstra_project/state.py +22 -230
  297. package/runtime/python/okstra_token_usage/claude.py +9 -1
  298. package/runtime/python/okstra_token_usage/cli.py +3 -1
  299. package/runtime/python/okstra_token_usage/collect.py +71 -10
  300. package/runtime/python/okstra_token_usage/cursor.py +2 -0
  301. package/runtime/python/okstra_token_usage/grok.py +1 -5
  302. package/runtime/python/okstra_token_usage/paths.py +26 -0
  303. package/runtime/python/okstra_token_usage/pricing.py +19 -7
  304. package/runtime/schemas/convergence-critic-results-v1.0.schema.json +5 -0
  305. package/runtime/schemas/execution-manifest-v2.schema.json +10 -10
  306. package/runtime/schemas/final-report-v2.0.schema.json +9 -26
  307. package/runtime/schemas/final-report-v3.0.schema.json +173 -41
  308. package/runtime/schemas/report-narrative-v3.0.schema.json +3 -2
  309. package/runtime/skills/okstra-brief-gen/SKILL.md +35 -2
  310. package/runtime/skills/okstra-container-build/SKILL.md +16 -47
  311. package/runtime/skills/okstra-inspect/facets/history.md +1 -1
  312. package/runtime/skills/okstra-inspect/facets/status.md +7 -6
  313. package/runtime/skills/okstra-pr-gen/SKILL.md +1 -1
  314. package/runtime/skills/okstra-run/SKILL.md +7 -5
  315. package/runtime/templates/report-writer-prompt-preamble.md +1 -1
  316. package/runtime/templates/reports/brief.template.md +6 -2
  317. package/runtime/templates/reports/error-analysis-input.template.md +2 -0
  318. package/runtime/templates/reports/final-verification-input.template.md +2 -0
  319. package/runtime/templates/reports/implementation-input.template.md +7 -1
  320. package/runtime/templates/reports/implementation-planning-input.template.md +4 -0
  321. package/runtime/templates/reports/quick-input.template.md +2 -0
  322. package/runtime/templates/reports/release-handoff-input.template.md +6 -1
  323. package/runtime/templates/reports/report.js +20 -3
  324. package/runtime/templates/reports/schedule.template.md +2 -0
  325. package/runtime/templates/reports/settings.template.json +0 -10
  326. package/runtime/templates/reports/task-brief.template.md +3 -0
  327. package/runtime/templates/reports/user-response.template.md +7 -3
  328. package/runtime/validators/checks/fixtures-01.py +57 -0
  329. package/runtime/validators/checks/fixtures-02.py +565 -0
  330. package/runtime/validators/checks/runners-01.py +108 -0
  331. package/runtime/validators/checks/validate-assets-01.py +60 -0
  332. package/runtime/validators/checks/validate-prompt-metadata-01.py +261 -0
  333. package/runtime/validators/checks/validate-tasks-01.py +46 -0
  334. package/runtime/validators/checks/validate-tasks-02.py +85 -0
  335. package/runtime/validators/checks/validate-tasks-03.py +61 -0
  336. package/runtime/validators/checks/validate-tasks-04.py +118 -0
  337. package/runtime/validators/forbidden_actions.py +73 -3
  338. package/runtime/validators/lib/common.sh +5 -0
  339. package/runtime/validators/lib/fixtures.sh +7 -591
  340. package/runtime/validators/lib/paths.sh +13 -0
  341. package/runtime/validators/lib/runners.sh +6 -104
  342. package/runtime/validators/lib/summary.sh +1 -1
  343. package/runtime/validators/lib/validate-assets.sh +6 -56
  344. package/runtime/validators/lib/validate-prompt-metadata.sh +6 -257
  345. package/runtime/validators/lib/validate-tasks.sh +9 -294
  346. package/runtime/validators/validate-implementation-plan-stages.py +4 -4
  347. package/runtime/validators/validate-run.py +1369 -2654
  348. package/runtime/validators/validate-workflow.sh +56 -16
  349. package/runtime/validators/validate_improvement_report.py +2 -1
  350. package/runtime/validators/validate_session_conformance.py +295 -49
  351. package/dist/commands/execute/agent-prompt.d.mts +0 -1
  352. package/dist/commands/execute/agent-prompt.mjs +0 -24
  353. package/dist/commands/execute/agent-prompt.mjs.map +0 -1
  354. package/dist/commands/execute/codex-dispatch.d.mts +0 -3
  355. package/dist/commands/execute/codex-dispatch.mjs +0 -6
  356. package/dist/commands/execute/codex-dispatch.mjs.map +0 -1
  357. package/dist/commands/execute/codex-run.d.mts +0 -3
  358. package/dist/commands/execute/codex-run.mjs +0 -62
  359. package/dist/commands/execute/codex-run.mjs.map +0 -1
  360. package/dist/commands/execute/convergence.d.mts +0 -1
  361. package/dist/commands/execute/convergence.mjs +0 -38
  362. package/dist/commands/execute/convergence.mjs.map +0 -1
  363. package/dist/commands/execute/error-log.d.mts +0 -1
  364. package/dist/commands/execute/error-log.mjs +0 -18
  365. package/dist/commands/execute/error-log.mjs.map +0 -1
  366. package/dist/commands/execute/git-reconcile.d.mts +0 -1
  367. package/dist/commands/execute/git-reconcile.mjs +0 -30
  368. package/dist/commands/execute/git-reconcile.mjs.map +0 -1
  369. package/dist/commands/execute/handoff.d.mts +0 -1
  370. package/dist/commands/execute/handoff.mjs +0 -31
  371. package/dist/commands/execute/handoff.mjs.map +0 -1
  372. package/dist/commands/execute/incremental-carry.d.mts +0 -1
  373. package/dist/commands/execute/incremental-carry.mjs +0 -20
  374. package/dist/commands/execute/incremental-carry.mjs.map +0 -1
  375. package/dist/commands/execute/incremental-scope.d.mts +0 -1
  376. package/dist/commands/execute/incremental-scope.mjs +0 -29
  377. package/dist/commands/execute/incremental-scope.mjs.map +0 -1
  378. package/dist/commands/execute/integrate-stages.d.mts +0 -1
  379. package/dist/commands/execute/integrate-stages.mjs +0 -24
  380. package/dist/commands/execute/integrate-stages.mjs.map +0 -1
  381. package/dist/commands/execute/pane-title.d.mts +0 -1
  382. package/dist/commands/execute/pane-title.mjs +0 -20
  383. package/dist/commands/execute/pane-title.mjs.map +0 -1
  384. package/dist/commands/execute/plan-items.d.mts +0 -1
  385. package/dist/commands/execute/plan-items.mjs +0 -9
  386. package/dist/commands/execute/plan-items.mjs.map +0 -1
  387. package/dist/commands/execute/plan-validate.d.mts +0 -1
  388. package/dist/commands/execute/plan-validate.mjs +0 -68
  389. package/dist/commands/execute/plan-validate.mjs.map +0 -1
  390. package/dist/commands/execute/plan-verify.d.mts +0 -1
  391. package/dist/commands/execute/plan-verify.mjs +0 -43
  392. package/dist/commands/execute/plan-verify.mjs.map +0 -1
  393. package/dist/commands/execute/spawn-followups.d.mts +0 -1
  394. package/dist/commands/execute/spawn-followups.mjs +0 -22
  395. package/dist/commands/execute/spawn-followups.mjs.map +0 -1
  396. package/dist/commands/execute/team.d.mts +0 -3
  397. package/dist/commands/execute/team.mjs +0 -66
  398. package/dist/commands/execute/team.mjs.map +0 -1
  399. package/dist/commands/execute/token-usage.d.mts +0 -1
  400. package/dist/commands/execute/token-usage.mjs +0 -19
  401. package/dist/commands/execute/token-usage.mjs.map +0 -1
  402. package/dist/commands/execute/worker-audit-check.d.mts +0 -1
  403. package/dist/commands/execute/worker-audit-check.mjs +0 -34
  404. package/dist/commands/execute/worker-audit-check.mjs.map +0 -1
  405. package/dist/commands/execute/worker-dispatch.d.mts +0 -7
  406. package/dist/commands/execute/worker-dispatch.mjs +0 -64
  407. package/dist/commands/execute/worker-dispatch.mjs.map +0 -1
  408. package/dist/commands/execute/worker-state.d.mts +0 -1
  409. package/dist/commands/execute/worker-state.mjs +0 -28
  410. package/dist/commands/execute/worker-state.mjs.map +0 -1
  411. package/dist/commands/execute/worktree-lookup.d.mts +0 -1
  412. package/dist/commands/execute/worktree-lookup.mjs +0 -92
  413. package/dist/commands/execute/worktree-lookup.mjs.map +0 -1
  414. package/dist/commands/execute/worktree-status.d.mts +0 -1
  415. package/dist/commands/execute/worktree-status.mjs +0 -121
  416. package/dist/commands/execute/worktree-status.mjs.map +0 -1
  417. package/dist/commands/inspect/code-review.d.mts +0 -1
  418. package/dist/commands/inspect/code-review.mjs +0 -32
  419. package/dist/commands/inspect/code-review.mjs.map +0 -1
  420. package/dist/commands/inspect/container.d.mts +0 -1
  421. package/dist/commands/inspect/container.mjs +0 -25
  422. package/dist/commands/inspect/container.mjs.map +0 -1
  423. package/dist/commands/inspect/context-cost.d.mts +0 -1
  424. package/dist/commands/inspect/context-cost.mjs +0 -25
  425. package/dist/commands/inspect/context-cost.mjs.map +0 -1
  426. package/dist/commands/inspect/design-prep.d.mts +0 -1
  427. package/dist/commands/inspect/design-prep.mjs +0 -22
  428. package/dist/commands/inspect/design-prep.mjs.map +0 -1
  429. package/dist/commands/inspect/error-report.d.mts +0 -1
  430. package/dist/commands/inspect/error-report.mjs +0 -25
  431. package/dist/commands/inspect/error-report.mjs.map +0 -1
  432. package/dist/commands/inspect/error-zip.d.mts +0 -1
  433. package/dist/commands/inspect/error-zip.mjs +0 -24
  434. package/dist/commands/inspect/error-zip.mjs.map +0 -1
  435. package/dist/commands/inspect/log-report.d.mts +0 -1
  436. package/dist/commands/inspect/log-report.mjs +0 -26
  437. package/dist/commands/inspect/log-report.mjs.map +0 -1
  438. package/dist/commands/inspect/model-io.d.mts +0 -1
  439. package/dist/commands/inspect/model-io.mjs +0 -25
  440. package/dist/commands/inspect/model-io.mjs.map +0 -1
  441. package/dist/commands/inspect/profile-show.d.mts +0 -1
  442. package/dist/commands/inspect/profile-show.mjs +0 -28
  443. package/dist/commands/inspect/profile-show.mjs.map +0 -1
  444. package/dist/commands/inspect/recap.d.mts +0 -1
  445. package/dist/commands/inspect/recap.mjs +0 -30
  446. package/dist/commands/inspect/recap.mjs.map +0 -1
  447. package/dist/commands/inspect/resolve-task-key.d.mts +0 -1
  448. package/dist/commands/inspect/resolve-task-key.mjs +0 -24
  449. package/dist/commands/inspect/resolve-task-key.mjs.map +0 -1
  450. package/dist/commands/inspect/rollup.d.mts +0 -1
  451. package/dist/commands/inspect/rollup.mjs +0 -25
  452. package/dist/commands/inspect/rollup.mjs.map +0 -1
  453. package/dist/commands/inspect/run-audit.d.mts +0 -1
  454. package/dist/commands/inspect/run-audit.mjs +0 -25
  455. package/dist/commands/inspect/run-audit.mjs.map +0 -1
  456. package/dist/commands/inspect/set-work-status.d.mts +0 -1
  457. package/dist/commands/inspect/set-work-status.mjs +0 -29
  458. package/dist/commands/inspect/set-work-status.mjs.map +0 -1
  459. package/dist/commands/inspect/stage-map.d.mts +0 -1
  460. package/dist/commands/inspect/stage-map.mjs +0 -131
  461. package/dist/commands/inspect/stage-map.mjs.map +0 -1
  462. package/dist/commands/inspect/task-list.d.mts +0 -1
  463. package/dist/commands/inspect/task-list.mjs +0 -149
  464. package/dist/commands/inspect/task-list.mjs.map +0 -1
  465. package/dist/commands/inspect/task-show.d.mts +0 -1
  466. package/dist/commands/inspect/task-show.mjs +0 -108
  467. package/dist/commands/inspect/task-show.mjs.map +0 -1
  468. package/dist/commands/inspect/time-report.d.mts +0 -1
  469. package/dist/commands/inspect/time-report.mjs +0 -24
  470. package/dist/commands/inspect/time-report.mjs.map +0 -1
  471. package/dist/commands/inspect/usage-report.d.mts +0 -1
  472. package/dist/commands/inspect/usage-report.mjs +0 -23
  473. package/dist/commands/inspect/usage-report.mjs.map +0 -1
  474. package/dist/commands/inspect/user-response.d.mts +0 -1
  475. package/dist/commands/inspect/user-response.mjs +0 -35
  476. package/dist/commands/inspect/user-response.mjs.map +0 -1
  477. package/dist/commands/inspect/worker-liveness.d.mts +0 -1
  478. package/dist/commands/inspect/worker-liveness.mjs +0 -45
  479. package/dist/commands/inspect/worker-liveness.mjs.map +0 -1
  480. package/dist/commands/lifecycle/contract-check.d.mts +0 -1
  481. package/dist/commands/lifecycle/contract-check.mjs +0 -18
  482. package/dist/commands/lifecycle/contract-check.mjs.map +0 -1
  483. package/dist/commands/lifecycle/migrate.d.mts +0 -1
  484. package/dist/commands/lifecycle/migrate.mjs +0 -30
  485. package/dist/commands/lifecycle/migrate.mjs.map +0 -1
  486. package/dist/commands/lifecycle/model.d.mts +0 -1
  487. package/dist/commands/lifecycle/model.mjs +0 -22
  488. package/dist/commands/lifecycle/model.mjs.map +0 -1
  489. package/dist/commands/manager.d.mts +0 -3
  490. package/dist/commands/manager.mjs +0 -50
  491. package/dist/commands/manager.mjs.map +0 -1
  492. package/dist/commands/report/agent-activity.d.mts +0 -1
  493. package/dist/commands/report/agent-activity.mjs +0 -20
  494. package/dist/commands/report/agent-activity.mjs.map +0 -1
  495. package/dist/commands/report/approval-decision.d.mts +0 -1
  496. package/dist/commands/report/approval-decision.mjs +0 -21
  497. package/dist/commands/report/approval-decision.mjs.map +0 -1
  498. package/dist/commands/report/design-snapshot.d.mts +0 -1
  499. package/dist/commands/report/design-snapshot.mjs +0 -19
  500. package/dist/commands/report/design-snapshot.mjs.map +0 -1
  501. package/dist/commands/report/finalize.d.mts +0 -4
  502. package/dist/commands/report/finalize.mjs +0 -64
  503. package/dist/commands/report/finalize.mjs.map +0 -1
  504. package/dist/commands/report/inject-report-index.d.mts +0 -1
  505. package/dist/commands/report/inject-report-index.mjs +0 -21
  506. package/dist/commands/report/inject-report-index.mjs.map +0 -1
  507. package/dist/commands/report/render-final-report.d.mts +0 -1
  508. package/dist/commands/report/render-final-report.mjs +0 -23
  509. package/dist/commands/report/render-final-report.mjs.map +0 -1
  510. package/dist/commands/report/render-views.d.mts +0 -1
  511. package/dist/commands/report/render-views.mjs +0 -27
  512. package/dist/commands/report/render-views.mjs.map +0 -1
  513. package/dist/commands/report/translate.d.mts +0 -1
  514. package/dist/commands/report/translate.mjs +0 -33
  515. package/dist/commands/report/translate.mjs.map +0 -1
  516. package/runtime/bin/lib/okstra/tmux-pane.sh +0 -40
  517. package/runtime/bin/lib/okstra-ctl/cmd-batch.sh +0 -59
  518. package/runtime/bin/lib/okstra-ctl/cmd-list.sh +0 -35
  519. package/runtime/bin/lib/okstra-ctl/cmd-open.sh +0 -36
  520. package/runtime/bin/lib/okstra-ctl/cmd-projects.sh +0 -26
  521. package/runtime/bin/lib/okstra-ctl/cmd-reconcile.sh +0 -29
  522. package/runtime/bin/lib/okstra-ctl/cmd-reindex.sh +0 -38
  523. package/runtime/bin/lib/okstra-ctl/cmd-rerun.sh +0 -345
  524. package/runtime/bin/lib/okstra-ctl/cmd-show.sh +0 -27
  525. package/runtime/bin/lib/okstra-ctl/cmd-tail.sh +0 -92
  526. package/runtime/bin/lib/okstra-ctl/main.sh +0 -41
  527. package/runtime/bin/lib/okstra-ctl/prepare.sh +0 -31
  528. package/runtime/bin/lib/okstra-ctl/usage.sh +0 -23
  529. package/runtime/bin/okstra-central.sh +0 -152
  530. package/runtime/bin/okstra-incremental-carry.py +0 -10
  531. package/runtime/bin/okstra-incremental-scope.py +0 -10
  532. package/runtime/bin/okstra-team-reconcile.sh +0 -36
  533. package/runtime/python/okstra_ctl/agent_prompt_cli.py +0 -1156
  534. package/runtime/python/okstra_ctl/batch.py +0 -60
  535. package/runtime/python/okstra_ctl/clarification_items.py +0 -1050
  536. package/runtime/python/okstra_ctl/container_registry.py +0 -72
  537. package/runtime/python/okstra_ctl/improvement_assignment.py +0 -61
  538. package/runtime/python/okstra_ctl/resolver.py +0 -54
  539. package/runtime/python/okstra_ctl/team_reconcile.py +0 -275
  540. package/runtime/python/okstra_ctl/tmux.py +0 -134
  541. package/runtime/python/okstra_ctl/worktree.py +0 -1099
@@ -48,8 +48,14 @@ from .path_hints import compact_active_run_context, hydrate_run_context
48
48
  from .paths import task_timeline_file
49
49
  from .json_boundary import JsonBoundaryError, load_owned_object, write_owned_object_atomic
50
50
  from .report_contract import CURRENT_REPORT_SCHEMA_VERSION
51
- from .worker_artifacts import artifacts_from_context
52
- from .workflow import PHASE_SEQUENCE
51
+ from .report_language import resolve_report_language
52
+ from .validation_contract import CURRENT_VALIDATION_CONTRACT_VERSION
53
+ from .worker_artifacts import (
54
+ artifacts_from_context,
55
+ worker_provider_id,
56
+ worker_role_suffix,
57
+ )
58
+ from .workflow import PHASE_SEQUENCE, phase_position
53
59
 
54
60
 
55
61
  class TokenRenderError(Exception):
@@ -152,7 +158,7 @@ def _runtime_resolution(ctx: dict) -> dict:
152
158
  raw = ctx.get("RUNTIME_RESOLUTION_JSON", "") or "{}"
153
159
  try:
154
160
  payload = json.loads(raw)
155
- except Exception:
161
+ except (ValueError, TypeError):
156
162
  return {}
157
163
  return payload if isinstance(payload, dict) else {}
158
164
 
@@ -350,8 +356,11 @@ def _lead_assignment(ctx: dict) -> dict:
350
356
  candidate = json.loads(raw)
351
357
  if isinstance(candidate, dict):
352
358
  parsed = candidate
353
- except json.JSONDecodeError:
354
- pass
359
+ except json.JSONDecodeError as exc:
360
+ # 조용히 넘기면 ctx 폴백으로 만든 *다른* lead assignment 가 매니페스트에
361
+ # 실린다. 호출자는 그 둘을 구별할 수 없으므로 여기서 한 줄 남긴다.
362
+ print(f"render: LEAD_ASSIGNMENT_JSON is not valid JSON, "
363
+ f"falling back to ctx fields ({exc})", file=sys.stderr)
355
364
  source = parsed or {}
356
365
  provider, runner = _resolved_lead_assignment(
357
366
  ctx,
@@ -433,8 +442,11 @@ def _worker_assignments(ctx: dict) -> list[dict]:
433
442
  parsed = json.loads(raw)
434
443
  if isinstance(parsed, list) and all(isinstance(row, dict) for row in parsed):
435
444
  return [_resolved_worker_assignment(ctx, row) for row in parsed]
436
- except json.JSONDecodeError:
437
- pass
445
+ except json.JSONDecodeError as exc:
446
+ # lead assignment 와 같은 이유 — 폴백으로 만든 로스터는 요청된 것과
447
+ # 다른데 반환값만 봐서는 구별되지 않는다.
448
+ print(f"render: WORKER_ASSIGNMENTS_JSON is not valid JSON, "
449
+ f"falling back to the worker catalog ({exc})", file=sys.stderr)
438
450
  catalog = _worker_catalog(ctx, include_assignments=False)
439
451
  return [
440
452
  {
@@ -491,7 +503,7 @@ def _worker_catalog(ctx: dict, *, include_assignments: bool = True) -> dict:
491
503
  "workerId": worker_id,
492
504
  "role": (
493
505
  "Report writer worker" if worker_id == "report-writer"
494
- else f"{provider_spec(worker_id).display_label} worker"
506
+ else _roster_role_label(provider_info.display_label, worker_id)
495
507
  ),
496
508
  "agent": provider,
497
509
  "agentLabel": provider_info.display_label,
@@ -510,15 +522,30 @@ def _worker_catalog(ctx: dict, *, include_assignments: bool = True) -> dict:
510
522
  return catalog
511
523
 
512
524
 
525
+ def _roster_role_label(display_label: str, worker_id: str) -> str:
526
+ """team-state 로스터 행의 역할 라벨.
527
+
528
+ 한 provider 가 슬롯 하나만 채우면 종전 그대로 `<Provider> worker` 다.
529
+ 두 슬롯 이상이면 worker_id 에 붙은 역할이 라벨에도 그대로 온다
530
+ (`Claude implementer`, `Claude verifier`, `Claude verifier 2`) —
531
+ 라벨이 겹치면 validate-run 이 `duplicate worker role detected` 로 런을
532
+ 실패시키므로, id 를 가르는 그 접미사가 라벨도 가른다.
533
+ """
534
+ suffix = worker_role_suffix(worker_id)
535
+ if not suffix:
536
+ return f"{display_label} worker"
537
+ return f"{display_label} {suffix.replace('-', ' ')}"
538
+
539
+
513
540
  def _fallback_worker_provider(ctx: dict, worker_id: str) -> str:
514
541
  if worker_id == "report-writer":
515
542
  return ctx.get("REPORT_WRITER_PROVIDER", "") or "claude"
516
- return worker_id
543
+ return worker_provider_id(worker_id)
517
544
 
518
545
 
519
546
  def _legacy_worker_model(ctx: dict, worker_id: str) -> tuple[str, str]:
520
547
  token = "REPORT_WRITER" if worker_id == "report-writer" else (
521
- worker_id.upper().replace("-", "_")
548
+ worker_provider_id(worker_id).upper().replace("-", "_")
522
549
  )
523
550
  return (
524
551
  ctx.get(f"{token}_WORKER_MODEL", ctx.get(f"{token}_MODEL", "")),
@@ -878,7 +905,7 @@ def render_task_catalog_discovery(output_path: str, ctx: dict) -> None:
878
905
  for manifest_path in sorted(tasks_root.rglob(TASK_MANIFEST_FILENAME)):
879
906
  try:
880
907
  manifest = load_owned_object(manifest_path, artifact="task manifest")
881
- except Exception:
908
+ except JsonBoundaryError:
882
909
  continue
883
910
  if not isinstance(manifest, dict):
884
911
  continue
@@ -896,7 +923,7 @@ def render_task_catalog_discovery(output_path: str, ctx: dict) -> None:
896
923
  if timeline_file.is_file():
897
924
  try:
898
925
  payload = load_owned_object(timeline_file, artifact="task timeline")
899
- except Exception:
926
+ except JsonBoundaryError:
900
927
  payload = {}
901
928
  runs = payload.get("runs", []) if isinstance(payload, dict) else []
902
929
  if isinstance(runs, list):
@@ -988,7 +1015,7 @@ def render_latest_task_discovery(output_path: str, ctx: dict) -> None:
988
1015
  task_manifest = load_owned_object(
989
1016
  task_manifest_path, artifact="task manifest"
990
1017
  )
991
- except Exception:
1018
+ except JsonBoundaryError:
992
1019
  task_manifest = {}
993
1020
  workflow = (
994
1021
  task_manifest.get("workflow")
@@ -1103,8 +1130,12 @@ def migrate_legacy_run_artifacts(ctx: dict) -> None:
1103
1130
  if entry.read_bytes() == destination.read_bytes():
1104
1131
  entry.unlink()
1105
1132
  path_rewrites[old_relative] = new_relative
1106
- except Exception:
1107
- pass
1133
+ except OSError as exc:
1134
+ # 읽지 못하면 두 파일이 같은지 알 수 없어 옛 경로를 남긴다.
1135
+ # 조용히 두면 이관이 끝난 것처럼 보이므로 이유를 남긴다.
1136
+ print(f"render: cannot compare legacy artifact {entry} with "
1137
+ f"{destination}, leaving it in place ({exc})",
1138
+ file=sys.stderr)
1108
1139
  break
1109
1140
  shutil.move(str(entry), str(destination))
1110
1141
  path_rewrites[old_relative] = new_relative
@@ -1117,7 +1148,7 @@ def migrate_legacy_run_artifacts(ctx: dict) -> None:
1117
1148
  continue
1118
1149
  try:
1119
1150
  original = path.read_text(encoding="utf-8")
1120
- except Exception:
1151
+ except OSError:
1121
1152
  continue
1122
1153
  updated = _rewrite_path_refs(original, path_rewrites)
1123
1154
  if updated != original:
@@ -1310,17 +1341,30 @@ def _derive_latest_pointers(existing: dict, ctx: dict, current_report_relative:
1310
1341
  "latestResumeCommandPath", existing.get("latestResumeCommandPath", "")
1311
1342
  ),
1312
1343
  },
1313
- "latestRunPath": existing.get("latestRunPath", "")
1314
- or ctx.get("LATEST_RUN_RELATIVE_PATH", ""),
1315
- "latestRunStatus": existing.get("latestRunStatus", "")
1316
- or ctx.get("CURRENT_RUN_STATUS", ""),
1317
- "latestRunPromptsPath": existing.get("latestRunPromptsPath", "")
1318
- or ctx.get("RUN_PROMPTS_RELATIVE_PATH", ""),
1344
+ # `--render-only` 은 옛 run 을 다시 그리는 것이 아니라 **새 run 을
1345
+ # 준비**한다(새 run-manifest 기록, 타임라인 갱신). 그래서 run 디렉터리
1346
+ # ·프롬프트·team-state·상태는 이번에 만들어진 것이 최신이다. 기존값을
1347
+ # 우선하면 `latest` 라는 이름의 필드가 최초로 들어온 값에 영구히 묶인다
1348
+ # — 실측(`fontsninja-nlpvibe`): implementation 의 stage run 이 전부
1349
+ # `renderOnly: true` 라 stage 10 까지 돌고도 `latestRunPath` 가
1350
+ # `stage-1`, `latestRunStatus` 가 그때의 `contract-violated` 로 남았다.
1351
+ "latestRunPath": ctx.get("LATEST_RUN_RELATIVE_PATH", "")
1352
+ or existing.get("latestRunPath", ""),
1353
+ "latestRunStatus": ctx.get("CURRENT_RUN_STATUS", "")
1354
+ or existing.get("latestRunStatus", ""),
1355
+ "latestRunPromptsPath": ctx.get("RUN_PROMPTS_RELATIVE_PATH", "")
1356
+ or existing.get("latestRunPromptsPath", ""),
1357
+ # 리포트만 반대다. render-only 는 최종 리포트를 만들지 않으므로
1358
+ # `current_report_relative` 는 아직 없는 파일을 가리킬 수 있다.
1359
+ # 마지막으로 실재했던 리포트를 지키는 쪽이 옳다.
1319
1360
  "latestReportRecordPath": existing.get("latestReportRecordPath", "")
1320
1361
  or current_report_relative,
1321
- "latestTeamStatePath": existing.get("teamStatePath", "")
1322
- or ctx.get("TEAM_STATE_RELATIVE_PATH", ""),
1323
- "latestResumeCommandPath": existing.get("latestResumeCommandPath", ""),
1362
+ "latestTeamStatePath": ctx.get("TEAM_STATE_RELATIVE_PATH", "")
1363
+ or existing.get("teamStatePath", ""),
1364
+ "latestResumeCommandPath": ctx.get(
1365
+ "CLAUDE_RESUME_COMMAND_RELATIVE_PATH", ""
1366
+ )
1367
+ or existing.get("latestResumeCommandPath", ""),
1324
1368
  }
1325
1369
  return {
1326
1370
  "lastSafeCheckpoint": {
@@ -1350,7 +1394,7 @@ def render_task_manifest(manifest_path: str, ctx: dict) -> None:
1350
1394
  if path.exists():
1351
1395
  try:
1352
1396
  existing = load_owned_object(path, artifact="task manifest")
1353
- except Exception:
1397
+ except JsonBoundaryError:
1354
1398
  existing = {}
1355
1399
  reviewers = _resolve_workers(ctx)
1356
1400
  worker_dispatch_plan = _worker_dispatch_plan(ctx)
@@ -1672,7 +1716,7 @@ def render_run_manifest(run_manifest_path: str, ctx: dict) -> None:
1672
1716
  task_manifest = load_owned_object(
1673
1717
  task_manifest_path, artifact="task manifest"
1674
1718
  )
1675
- except Exception:
1719
+ except JsonBoundaryError:
1676
1720
  task_manifest = {}
1677
1721
  reviewers = _resolve_workers(ctx)
1678
1722
  worker_dispatch_plan = _worker_dispatch_plan(ctx)
@@ -1706,7 +1750,14 @@ def render_run_manifest(run_manifest_path: str, ctx: dict) -> None:
1706
1750
  "taskKey": ctx.get("TASK_KEY", ""),
1707
1751
  "taskType": ctx.get("TASK_TYPE", ""),
1708
1752
  "runTimestamp": ctx.get("RUN_TIMESTAMP_ISO", ""),
1709
- "reportLanguage": ctx.get("REPORT_LANGUAGE", "en") or "en",
1753
+ # 리포트 언어의 유일한 해석기. 예전에는 아무도 채우지 않는
1754
+ # `REPORT_LANGUAGE` 를 읽어 항상 "en" 이 나왔고, report-writer 프롬프트만
1755
+ # `resolve_report_language()` 를 써서 프롬프트는 ko, 매니페스트는 en 으로
1756
+ # 갈렸다. 리포트 조립은 이 매니페스트 값을 `meta.reportLanguage` 로
1757
+ # 그대로 옮기므로, 갈라진 쪽이 사람이 읽는 언어를 결정했다.
1758
+ "reportLanguage": resolve_report_language(
1759
+ Path(ctx.get("PROJECT_ROOT", "")), task_manifest, {}
1760
+ ),
1710
1761
  "leadModel": ctx.get("LEAD_MODEL", ""),
1711
1762
  # Every other path in this manifest is project-relative; this is the
1712
1763
  # anchor they resolve against. Convergence reads it to place run
@@ -1783,6 +1834,7 @@ def render_run_manifest(run_manifest_path: str, ctx: dict) -> None:
1783
1834
  "approvalDecisionsPath": ctx.get("APPROVAL_DECISIONS_RELATIVE_PATH", ""),
1784
1835
  "designPreparationPath": ctx.get("DESIGN_PREPARATION_RELATIVE_PATH", ""),
1785
1836
  "planBodyVerificationPath": ctx.get("PLAN_BODY_VERIFICATION_STATE_RELATIVE_PATH", ""),
1837
+ "incrementalDecisionPath": ctx.get("INCREMENTAL_DECISION_STATE_RELATIVE_PATH", ""),
1786
1838
  "expectedStatusPath": ctx.get("FINAL_STATUS_RELATIVE_PATH", ""),
1787
1839
  "teamStatePath": ctx.get("TEAM_STATE_RELATIVE_PATH", ""),
1788
1840
  "activeRunContextPath": ctx.get("ACTIVE_RUN_CONTEXT_RELATIVE_PATH", ""),
@@ -1877,6 +1929,12 @@ def render_run_manifest(run_manifest_path: str, ctx: dict) -> None:
1877
1929
  payload["activityContractVersion"] = existing_run_manifest[
1878
1930
  "activityContractVersion"
1879
1931
  ]
1932
+ if not run_manifest_exists:
1933
+ payload["validationContractVersion"] = CURRENT_VALIDATION_CONTRACT_VERSION
1934
+ elif "validationContractVersion" in existing_run_manifest:
1935
+ payload["validationContractVersion"] = existing_run_manifest[
1936
+ "validationContractVersion"
1937
+ ]
1880
1938
  payload["reportContracts"] = (
1881
1939
  ["implementation-design-prep-v1"]
1882
1940
  if ctx.get("TASK_TYPE") == "implementation-planning"
@@ -2100,7 +2158,7 @@ def render_timeline(timeline_path: str, ctx: dict) -> None:
2100
2158
  task_manifest = load_owned_object(
2101
2159
  task_manifest_path, artifact="task manifest"
2102
2160
  )
2103
- except Exception:
2161
+ except JsonBoundaryError:
2104
2162
  task_manifest = {}
2105
2163
  reviewers = _resolve_workers(ctx)
2106
2164
  catalog = _worker_catalog(ctx)
@@ -2109,7 +2167,7 @@ def render_timeline(timeline_path: str, ctx: dict) -> None:
2109
2167
  if path.exists():
2110
2168
  try:
2111
2169
  existing = load_owned_object(path, artifact="task timeline")
2112
- except Exception:
2170
+ except JsonBoundaryError:
2113
2171
  existing = {}
2114
2172
  runs = existing.get("runs", [])
2115
2173
  current_run_manifest_path = ctx.get("RUN_MANIFEST_PATH", "")
@@ -2206,7 +2264,7 @@ def render_task_index(template_path: str, output_path: str, ctx: dict) -> None:
2206
2264
  task_manifest = load_owned_object(
2207
2265
  task_manifest_path, artifact="task manifest"
2208
2266
  )
2209
- except Exception:
2267
+ except JsonBoundaryError:
2210
2268
  task_manifest = {}
2211
2269
  workflow = (
2212
2270
  task_manifest.get("workflow", {})
@@ -2349,6 +2407,12 @@ def render_task_index(template_path: str, output_path: str, ctx: dict) -> None:
2349
2407
  "{{WORKFLOW_CURRENT_PHASE_STATE}}": workflow.get(
2350
2408
  "currentPhaseState", ctx.get("WORKFLOW_CURRENT_PHASE_STATE", "")
2351
2409
  ),
2410
+ # 매니페스트가 아니라 phase 이름에서 파생한다 — 자리표시자가 아니라
2411
+ # 결정론적 값이라 물려받을 이유가 없다.
2412
+ "{{WORKFLOW_PHASE_POSITION}}": phase_position(
2413
+ str(workflow.get("currentPhase", ctx.get("WORKFLOW_CURRENT_PHASE", "")))
2414
+ )
2415
+ or "--",
2352
2416
  "{{WORKFLOW_LAST_COMPLETED_PHASE}}": workflow.get(
2353
2417
  "lastCompletedPhase", ctx.get("WORKFLOW_LAST_COMPLETED_PHASE", "")
2354
2418
  )
@@ -2661,7 +2725,9 @@ def inject_lead_prompt_computed_tokens(ctx: dict) -> None:
2661
2725
  "- For native in-process dispatch, use the same canonical initial-prompt headers, "
2662
2726
  "persist the assigned prompt history through `write_artifact`, and apply "
2663
2727
  "the adapter-declared `lazy-path-reference` delivery mode before starting the "
2664
- "worker. This native path does not apply to reverify or critic dispatches.\n"
2728
+ "worker. The dispatch payload is a summon message carrying the persisted "
2729
+ "prompt path and the instruction to read that document in full — never the "
2730
+ "prompt body. This native path does not apply to reverify or critic dispatches.\n"
2665
2731
  "- Use `await_workers` through the selected adapter and confirm terminal state "
2666
2732
  "plus every required Result Path. File presence alone is never a signal to "
2667
2733
  "skip; worker selection and skipped status come from `team-state`.\n"
@@ -482,15 +482,15 @@ def _enforce_schema(data: dict) -> dict | None:
482
482
  _DISPLAY_CONCRETE_CLAUDE = {
483
483
  "fable": "claude-fable-5",
484
484
  "opus": "claude-opus-5",
485
- "sonnet": "claude-sonnet-4-6",
485
+ "sonnet": "claude-sonnet-5",
486
486
  "haiku": "claude-haiku-4-5",
487
487
  }
488
488
 
489
489
 
490
490
  def _model_detail(display: Any) -> str:
491
- """모델 display alias(예: 'opus')를 'opus (claude-opus-4-7)' 형태로 상세화한다.
491
+ """모델 display alias(예: 'opus')를 'opus (claude-opus-5)' 형태로 상세화한다.
492
492
 
493
- lead·report-writer 헤더 모델은 항상 claude provider 다. 구체 alias('opus-4-7'
493
+ lead·report-writer 헤더 모델은 항상 claude provider 다. 구체 alias('opus-5'
494
494
  등)는 claude 매핑의 실행 ID 를, 일반 alias('opus' 등)는 표시 전용
495
495
  `_DISPLAY_CONCRETE_CLAUDE` 의 권장 구체버전을 병기한다. 어느 쪽에도 없는 값
496
496
  (이미 실행 ID 이거나 'default' 등)은 원본을 그대로 돌려준다. 바깥 백틱은
@@ -638,10 +638,6 @@ def render_execution_roles_markdown(data: dict) -> str:
638
638
  return "\n".join(lines)
639
639
 
640
640
 
641
- def render_execution_roles_html(data: dict) -> str:
642
- return render_execution_roles_markdown(data)
643
-
644
-
645
641
  def _with_optional_defaults(data: dict) -> dict:
646
642
  """Render context with schema-optional fields filled in.
647
643