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
@@ -28,25 +28,10 @@ import re
28
28
  import sys
29
29
  from pathlib import Path
30
30
 
31
- REPO_ROOT = Path(__file__).resolve().parents[1]
32
- SCRIPTS_DIR = REPO_ROOT / "scripts"
33
- HOME_LIB = (
34
- Path(os.environ.get("OKSTRA_HOME", str(Path.home() / ".okstra")))
35
- / "lib"
36
- / "python"
37
- )
31
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
32
+ from okstra_bootstrap import prefer_colocated_modules # noqa: E402
38
33
 
39
- # Prefer dev sources when present, fall back to install. Without this
40
- # order, a stale install (~/.okstra/lib/python/okstra_ctl) without the
41
- # report_views module shadows the in-repo copy during development.
42
- if (SCRIPTS_DIR / "okstra_ctl" / "report_views.py").is_file():
43
- if str(SCRIPTS_DIR) in sys.path:
44
- sys.path.remove(str(SCRIPTS_DIR))
45
- sys.path.insert(0, str(SCRIPTS_DIR))
46
- if HOME_LIB.is_dir() and str(HOME_LIB) not in sys.path:
47
- sys.path.append(str(HOME_LIB))
48
- elif HOME_LIB.is_dir() and str(HOME_LIB) not in sys.path:
49
- sys.path.insert(0, str(HOME_LIB))
34
+ prefer_colocated_modules(__file__, "okstra_ctl/report_views.py")
50
35
 
51
36
  from okstra_ctl.clarification_items import STRUCTURED_REPORT_VERSIONS # noqa: E402
52
37
  from okstra_ctl.report_views import infer_run_meta, render_html_view # noqa: E402
@@ -56,6 +41,7 @@ from okstra_ctl.final_report_paths import ( # noqa: E402
56
41
  )
57
42
 
58
43
 
44
+ REPO_ROOT = Path(__file__).resolve().parents[1]
59
45
  _OKSTRA_HOME = Path(os.environ.get("OKSTRA_HOME", str(Path.home() / ".okstra")))
60
46
  # Search order:
61
47
  # 1) dev tree (`<repo>/templates/reports`) — wins when this script runs from
@@ -168,8 +154,29 @@ def _elapsed_ms(report_path, task_type: str, seq: str) -> int | None:
168
154
  return wall_clock_ms(state) or None if isinstance(state, dict) else None
169
155
 
170
156
 
157
+ _CLI_EPILOG = r"""A thin spawn shim over `scripts/okstra-render-report-views.py` (installed
158
+ at `$HOME/.okstra/bin/okstra-render-report-views.py`). Resolves the final-
159
+ report data and Markdown pair, then writes a single sibling:
160
+
161
+ <stem>.html — single-file self-contained human view; schema v2 is
162
+ always generated, while v1/quick remains conditional
163
+
164
+ Usage:
165
+ okstra render-views <path-to-final-report.data.json|path-to-final-report.md>
166
+ [--task-key <key>] [--task-type <type>] [--seq <NNN>]
167
+ [--source-report <project-relative-path>]
168
+
169
+ Schema v2 data is rendered directly into its task-specific HTML view and is
170
+ always generated. Schema v1 and quick reports keep the legacy conditional
171
+ Markdown view. Optional flags override inferred report metadata.
172
+ """
173
+
174
+
171
175
  def main(argv: list[str] | None = None) -> int:
172
176
  parser = argparse.ArgumentParser(
177
+ prog="okstra render-views",
178
+ epilog=_CLI_EPILOG,
179
+ formatter_class=argparse.RawDescriptionHelpFormatter,
173
180
  description="Render the self-contained HTML view of an okstra final-report."
174
181
  )
175
182
  parser.add_argument("report_path", type=Path)
@@ -29,24 +29,10 @@ import os
29
29
  import sys
30
30
  from pathlib import Path
31
31
 
32
- REPO_ROOT = Path(__file__).resolve().parents[1]
33
- SCRIPTS_DIR = REPO_ROOT / "scripts"
34
- HOME_LIB = (
35
- Path(os.environ.get("OKSTRA_HOME", str(Path.home() / ".okstra")))
36
- / "lib"
37
- / "python"
38
- )
32
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
33
+ from okstra_bootstrap import prefer_colocated_modules # noqa: E402
39
34
 
40
- # Prefer dev sources when present, fall back to install — a stale install
41
- # without this module would otherwise shadow the in-repo copy.
42
- if (SCRIPTS_DIR / "okstra_ctl" / "report_translation.py").is_file():
43
- if str(SCRIPTS_DIR) in sys.path:
44
- sys.path.remove(str(SCRIPTS_DIR))
45
- sys.path.insert(0, str(SCRIPTS_DIR))
46
- if HOME_LIB.is_dir() and str(HOME_LIB) not in sys.path:
47
- sys.path.append(str(HOME_LIB))
48
- elif HOME_LIB.is_dir() and str(HOME_LIB) not in sys.path:
49
- sys.path.insert(0, str(HOME_LIB))
35
+ prefer_colocated_modules(__file__, "okstra_ctl/report_translation.py")
50
36
 
51
37
  from okstra_ctl.report_translation import ( # noqa: E402
52
38
  HANGUL_PROSE_LIMIT,
@@ -353,9 +339,35 @@ def cmd_check_source(args: argparse.Namespace) -> int:
353
339
  return 0
354
340
 
355
341
 
342
+ _CLI_EPILOG = r"""A thin spawn shim over `scripts/okstra-report-translate.py` (installed at
343
+ `$HOME/.okstra/bin/okstra-report-translate.py`).
344
+
345
+ The final-report data.json is authored in English and stays the SSOT. When the
346
+ resolved report language is not English, Phase 7 dispatches a translator that
347
+ writes a sidecar beside the report; `render-views` overlays it so only the
348
+ human HTML is localized.
349
+
350
+ Usage:
351
+ okstra report-translate extract <path-to-final-report.data.json>
352
+ okstra report-translate source --run-manifest <path>
353
+ okstra report-translate write --run-manifest <path> --source-digest <sha256> --translations <markdown>
354
+ okstra report-translate check-data --run-manifest <path>
355
+ Write <stem>.translation-source.json — every pointer the report holds a
356
+ translatable string at, paired with its English text. The translator
357
+ fills in the values, so a sidecar cannot cite a path the report lacks.
358
+
359
+ okstra report-translate check <path-to-final-report.i18n.<lang>.json>
360
+ Resolve every pointer in a filled sidecar against the report it names
361
+ and report what is still English. Exits non-zero on a pointer that
362
+ resolves nowhere — the translator's own gate before it returns.
363
+ """
364
+
365
+
356
366
  def _parser() -> argparse.ArgumentParser:
357
367
  parser = argparse.ArgumentParser(
358
- prog="okstra-report-translate.py",
368
+ epilog=_CLI_EPILOG,
369
+ formatter_class=argparse.RawDescriptionHelpFormatter,
370
+ prog="okstra report-translate",
359
371
  description="Build and verify the final-report translation sidecar.",
360
372
  )
361
373
  sub = parser.add_subparsers(dest="op", required=True)
@@ -49,6 +49,9 @@ import sys
49
49
  from pathlib import Path
50
50
 
51
51
  sys.path.insert(0, str(Path(__file__).resolve().parent))
52
+ from okstra_bootstrap import prefer_colocated_modules # noqa: E402
53
+
54
+ prefer_colocated_modules(__file__, "okstra_ctl/next_phase.py")
52
55
 
53
56
  from okstra_ctl import next_phase # noqa: E402
54
57
  from okstra_ctl.final_report_paths import final_report_markdown_path # noqa: E402
@@ -251,6 +254,7 @@ def _spawn_one(
251
254
 
252
255
  def main(argv: list[str]) -> int:
253
256
  parser = argparse.ArgumentParser(
257
+ prog="okstra spawn-followups",
254
258
  description="Spawn follow-up task stubs from a final-report data.json.",
255
259
  )
256
260
  parser.add_argument(
@@ -12,6 +12,9 @@ import sys
12
12
  from pathlib import Path
13
13
 
14
14
  sys.path.insert(0, str(Path(__file__).resolve().parent))
15
+ from okstra_bootstrap import prefer_colocated_modules # noqa: E402
16
+
17
+ prefer_colocated_modules(__file__, "okstra_token_usage/cli.py")
15
18
 
16
19
  from okstra_token_usage.cli import main # noqa: E402
17
20
  # Re-exports for callers that access attributes off this module directly.
@@ -254,6 +254,7 @@ done
254
254
  [[ -n "${STAGE-}" ]] && PY_ARGS+=(--stage "$STAGE")
255
255
  [[ -n "${STAGES-}" ]] && PY_ARGS+=(--stages "$STAGES")
256
256
  [[ -n "${QA_WAIVER-}" ]] && PY_ARGS+=(--qa-waiver "$QA_WAIVER")
257
+ [[ -n "${TERMINAL_BACKEND-}" ]] && PY_ARGS+=(--terminal-backend "$TERMINAL_BACKEND")
257
258
  [[ "$RENDER_ONLY" == "true" ]] && PY_ARGS+=(--render-only)
258
259
  [[ "$PLAN_VERIFICATION_ENABLED" == "false" ]] && PY_ARGS+=(--no-plan-verification)
259
260
 
@@ -285,8 +286,9 @@ if [[ -z "$LAUNCH_JSON" ]]; then
285
286
  exit 1
286
287
  fi
287
288
 
288
- # Note: per-session --settings injection was removed. okstra-ctl prepare
289
- # provisions <PROJECT_ROOT>/.claude/settings.local.json as a symlink to
289
+ # Note: per-session --settings injection was removed. `okstra setup` and the
290
+ # prepare path (okstra_ctl/seeding.py) provision
291
+ # <PROJECT_ROOT>/.claude/settings.local.json as a symlink to
290
292
  # ~/.okstra/templates/settings.local.json, which Claude Code auto-loads
291
293
  # whenever it runs inside that project — no CLI flag required.
292
294
  execute_launch_plan \
@@ -0,0 +1,58 @@
1
+ """진입 스크립트가 자기와 같은 배치의 모듈 트리를 import 하게 만든다.
2
+
3
+ okstra 의 파이썬 진입 스크립트는 두 배치 중 하나에 놓인다.
4
+
5
+ * 레포 체크아웃 — `scripts/okstra-*.py` 옆에 `scripts/okstra_ctl/` 이 있다.
6
+ * 설치본 — `~/.okstra/bin/okstra-*.py` 의 짝은 `~/.okstra/lib/python/` 이다.
7
+
8
+ 짝을 `sys.path` **맨 앞**에 두어야 하는 이유는 상속된 `PYTHONPATH` 다.
9
+ `okstra <cmd>` 는 자식 프로세스에 npm 패키지의 `runtime/python` 을 먼저 담은
10
+ `PYTHONPATH` 를 물려준다(`src/lib/paths.mts` 의 `buildPythonpath`). 짝을 뒤에
11
+ 붙이면 설치본 스크립트가 npm 패키지 쪽 모듈을 import 하게 되고, 설치본과 npm
12
+ 패키지의 버전이 어긋나 있으면 그 스크립트는 import 에서 죽는다. 실행되는
13
+ 스크립트와 그 스크립트가 읽는 모듈은 항상 같은 버전이어야 한다.
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import os
18
+ import sys
19
+ from pathlib import Path
20
+
21
+
22
+ def _home_lib() -> Path:
23
+ home = Path(os.environ.get("OKSTRA_HOME", str(Path.home() / ".okstra")))
24
+ return home / "lib" / "python"
25
+
26
+
27
+ def _prepend(path: Path) -> None:
28
+ text = str(path)
29
+ if text in sys.path:
30
+ sys.path.remove(text)
31
+ sys.path.insert(0, text)
32
+
33
+
34
+ def _append(path: Path) -> None:
35
+ text = str(path)
36
+ if path.is_dir() and text not in sys.path:
37
+ sys.path.append(text)
38
+
39
+
40
+ def prefer_colocated_modules(entry_file: str, probe: str) -> None:
41
+ """`entry_file` 의 짝이 되는 모듈 트리를 `sys.path` 맨 앞에 둔다.
42
+
43
+ `probe` 는 그 트리 안에 있어야 하는 파일의 상대 경로다
44
+ (예: `okstra_ctl/report_views.py`). 디렉터리 존재만 보면 그 스크립트가
45
+ 필요로 하는 새 모듈이 아직 없는 낡은 설치본도 후보로 뽑히므로, 실제로
46
+ 쓰는 파일이 있는 쪽을 고른다. 어느 쪽에도 없으면 설치본을 앞에 둔다 —
47
+ 빠진 모듈은 상속된 경로에서 채워질 수 있고, 채워지지 않으면 ImportError
48
+ 로 드러난다.
49
+ """
50
+ entry_dir = Path(entry_file).resolve().parent
51
+ home_lib = _home_lib()
52
+ if (entry_dir / probe).is_file():
53
+ primary, fallback = entry_dir, home_lib
54
+ else:
55
+ primary, fallback = home_lib, entry_dir
56
+ if primary.is_dir():
57
+ _prepend(primary)
58
+ _append(fallback)
@@ -64,7 +64,7 @@ Per-file checks miss cross-cutting issues; each commit can be individually clean
64
64
 
65
65
  - [ ] **Domain-literal sweep:** `grep -rn` every domain enum value / predicate you added or touched in WHERE clauses, filters, or branches. The same literal at 2+ I/O sites is a *candidate* scattered decision — ask: would these sites change together when the business rule changes? Same decision → consolidate into one named constant or query builder in the domain layer and make every site reference it. Different decisions that merely share a value → leave them separate; coupling incidental duplication is worse than the repetition. (The identifier grep above does NOT catch this — sweep *values*, not just names.)
66
66
  - [ ] **Stand-alone name test for exports:** for each exported identifier, look at its siblings — can a caller pick the right one from the names alone? If a comment must explain which to use, the name fails; encode the distinguishing fact in it (e.g., the input shape: `parseRows` vs `parseRowsFromFlatItems`).
67
- - [ ] **Self-mock sweep:** for every test file you added or edited, `grep` it for the SUT-stubbing patterns of this language (full list in `languages/*.md` → "Self-mock signals to refuse") — e.g. `spyOn(sut`, `sut.<method> = jest.fn`, `spyk(sut`, `Mockito.spy(`, `@Spy` paired with `@InjectMocks`, `patch(`-ing the class under test, `mockall::mock!` of the unit itself, plus private-reach hacks (`(sut as any).`, `ReflectionTestUtils.invokeMethod(sut`). Any hit where the stubbed/replaced target **is the unit under test** — not an injected collaborator — is a refused self-mock: delete the stub and exercise the real method, or the test only proves its own wiring and survives even if the real implementation is deleted. Mocking injected collaborators at the boundary stays fine; this sweep targets only stubs on the SUT itself. If a method on the SUT feels too painful to leave real, that's a design signal (extract it to a collaborator), not a license to stub it. Enforced by `validators/detect_self_mock.py` (static); absent `qa/self-mock-*.json` sidecar BLOCKS at `validate-run.py`.
67
+ - [ ] **Self-mock sweep:** for every test file you added or edited, `grep` it for the SUT-stubbing patterns of this language (full list in `languages/*.md` → "Self-mock signals to refuse") — e.g. `spyOn(sut`, `sut.<method> = jest.fn`, `spyk(sut`, `Mockito.spy(`, `@Spy` paired with `@InjectMocks`, `patch(`-ing the class under test, `mockall::mock!` of the unit itself, plus private-reach hacks (`(sut as any).`, `ReflectionTestUtils.invokeMethod(sut`). Any hit where the stubbed/replaced target **is the unit under test** — not an injected collaborator — is a refused self-mock: delete the stub and exercise the real method, or the test only proves its own wiring and survives even if the real implementation is deleted. Mocking injected collaborators at the boundary stays fine; this sweep targets only stubs on the SUT itself. If a method on the SUT feels too painful to leave real, that's a design signal (extract it to a collaborator), not a license to stub it. Enforced by `validators/detect_self_mock.py` (static) — **run by the implementation verifier, never by the author of the diff.** This sweep is the manual half and ends at your own reading; the detector run and its `qa/self-mock-*.json` sidecar are the verifier's duty (`prompts/profiles/_implementation-verifier.md` §"Self-mock detection"), and it is that sidecar's absence that BLOCKS at `validate-run.py` — on the verifier's report, not on your diff. Running the detector yourself does not pre-satisfy the gate: the sidecar is outside an executor attempt's `writePolicy.artifactPolicy.allowedPaths`, so writing it makes okstra's write audit close the attempt as `error` (`artifact-root change exceeds batch policy union`), and the verifier writes the same file again under its own duty.
68
68
  - [ ] **No documented forks:** two deliberate variants of one capability must not survive as parallel implementations with a comment explaining the delta. Re-read both bodies and check the deltas are genuinely parametric: if they reduce to a few orthogonal options, collapse into one implementation taking explicit option parameters that encode them. If encoding the delta would take more than ~3 options, or add more branching than the duplication it removes, they are two capabilities — keep two implementations with distinct honest names and delete the "variant of" framing. Either way the comment-documented fork dies. "The divergence is documented" stays a refused rationalization, and a two-capabilities verdict must come from reading the bodies, not from reluctance to refactor.
69
69
 
70
70
  ## Boundaries
@@ -13,7 +13,7 @@ Produce an executable implementation plan without writing the implementation.
13
13
 
14
14
  ### Selected-direction responsibility
15
15
 
16
- When `selected-direction.json` is present, read it and the requirements ledger first. Preserve the selected direction's core mechanism, architecture boundaries, user constraints, and planning invariants. Concretize only its files, interfaces, stages, validation, and rollback. Link every file and stage back to original requirements, and link every original requirement forward to its files, stages, and checks. If current code evidence requires changing the direction, return `direction-invalidated` with evidence and stop. Direction selection remains upstream of this branch.
16
+ When `selected-direction.json` is present, read it and the requirements ledger (the brief's `EB-` / `PB-` / `EO-` end-state sections, carried in the analysis packet's `## Task-Specific Brief Extract`) first. Preserve the selected direction's core mechanism, architecture boundaries, user constraints, and planning invariants. Concretize only its files, interfaces, stages, validation, and rollback. Link every file and stage back to original requirements, and link every original requirement forward to its files, stages, and checks. If current code evidence requires changing the direction, return `direction-invalidated` with evidence and stop. Direction selection remains upstream of this branch.
17
17
 
18
18
  ### Legacy candidate-comparison compatibility
19
19
 
@@ -5,15 +5,29 @@
5
5
 
6
6
  ## Progress reporting (BLOCKING)
7
7
 
8
+ **Enforced:** `validators/validate_session_conformance.py` reads the selected adapter's evidence within the run window and reports a missing checkpoint. Missing lines are advisories, not failures — by the time the validator runs the session that would have emitted the line has ended, so the finding records that the run is hard to follow, not that its work is wrong.
9
+
8
10
  Emit one `PROGRESS: <phase-id> <verb-phrase>` line as plain user-facing text at every checkpoint enumerated in the lifecycle core contract (`{{OKSTRA_LEAD_CONTRACT_PATH}}` "Progress reporting (BLOCKING)") — phase-1-intake start/complete, phase-2-prompts, phase-3-team-create, phase-4-dispatch (per worker), phase-5-collect (per worker), phase-5.5-convergence (per round), phase-6-synthesis, phase-7-persist, and final `complete`. One line per checkpoint, never batched, never replaced with prose. This is the only signal the user has during multi-minute silent windows.
9
11
 
10
12
  When the run manifest declares `activityContractVersion: 1`, call `okstra agent-activity append` before each required activity boundary. Only after the structured append succeeds, emit the matching `PROGRESS:` line and the immediately following `ACTIVITY:` projection from the same fields. If the structured append fails, do not mark that boundary completed. Never reconstruct structured activity by parsing `ACTIVITY:` conversation text.
11
13
 
12
14
  For a new `implementation-planning` run, the plan-body sequence is initial verification → one planner self-fix → targeted re-verification → user gate. The initial verification is round 1, the targeted re-verification is round 2, and a second automatic self-fix is a contract violation. A user-directed correction does not consume the automatic self-fix limit, and a verification failure after that correction does not restart the automatic loop.
13
15
 
16
+ ## Asking the user (BLOCKING)
17
+
18
+ Any question this run puts to the user — an approval blocker, a re-verification scope, a routing fork, a wizard step you relay — follows the same three rules. Full text in the lifecycle core contract (`{{OKSTRA_LEAD_CONTRACT_PATH}}` "Asking the user").
19
+
20
+ 1. Investigate first: read the artifacts the answer turns on. If that settles it, do not ask. If it does not, what you read is what the options are made of.
21
+ 2. Offer two or three concrete options, recommendation first with one clause saying why, each naming its outcome. The free-input escape is always last, never first.
22
+ 3. Never hand over a blank you could have filled. Naming a finding in chat and then offering only free input is the failure this rule exists for.
23
+
24
+ Relaying a wizard step does not change the option set — relay every `options[]` entry unchanged and in order, and put your investigation and your recommendation in the question body.
25
+
26
+ **Enforced:** `scripts/okstra_ctl/wizard.py` `Prompt.__post_init__` refuses a wizard step whose free-input option is not last. The investigate-first half is a contract on you, in the lifecycle core contract's section of the same name.
27
+
14
28
  ## Current Phase Boundary
15
29
 
16
- - Current lifecycle phase: `{{WORKFLOW_CURRENT_PHASE}}`
30
+ - Current lifecycle phase: `{{WORKFLOW_CURRENT_PHASE}}` (step {{WORKFLOW_PHASE_POSITION}} of the lifecycle)
17
31
  - Allowed outputs in this phase:
18
32
  {{PHASE_ALLOWED_OUTPUTS}}
19
33
  - Forbidden actions in this phase:
@@ -29,12 +43,21 @@ For a new `implementation-planning` run, the plan-body sequence is initial verif
29
43
 
30
44
  After Phase 7 persistence, the last user-facing message of this run is the next command. A status dump is not a close. A prohibition (`do not start implementation`) is not a next action. This applies to every task type.
31
45
 
46
+ **Read the pointer from the `report-finalize` result — do not re-derive it.** Its top-level `nextRecommendedPhase` object (`phase`, `status`, `rationale`) is the value every row below branches on, and the same three values are repeated on stderr as `next phase status:` / `next phase:` / `next phase rationale:`. You did not write that object and you cannot recompute it: you author your task type's routing field, and Phase 7 projects the pointer from it plus the approval state — for `implementation-planning` there is no routing field at all. If the result carries `nextRecommendedPhaseError`, say in one line that the pointer could not be read, then close on the `validate-run` row below. The same result also carries `nextCommand` — `{command, note}`, the table below already applied to this run. When `command` is non-empty it is the close; when it is empty the `note` says what to do with the `rationale` instead.
47
+
32
48
  Close with one command the user can run now. The first matching row wins:
33
49
 
34
- - Open `blocks: approval` rows → `/okstra-user-response` (name the `C-NNN` ids). An `accept-risk` / `select` / `answer` already recorded is not an open blocker.
35
- - `workflow.awaitingApproval` is true → `/okstra-run` → `implementation` or `--approve`. Do not propose another planning run.
36
- - Phase 7 `validate-run` failed → one line naming the blocking cause, then `/okstra-run` to re-run this phase, or `/okstra-inspect recap`.
37
- - Pointer `status: ready` → `/okstra-run` for that `phase`.
50
+ - Open `blocks: approval` rows, or a `blocked-by-disagreement` gate whose approval rows carry no progress disposition → `/okstra-user-response` (name the `C-NNN` ids). An `accept-risk` / `select` / `answer` already recorded is not an open blocker. A report published with those rows open is not a failed run — the answers are the missing input, and a planning re-run without them reproduces the same block.
51
+
52
+ After `implementation-planning`, stop on the rows above. No open approval blocker → `/okstra-run` → `implementation` or `--approve`. Do not propose another planning run. Do not say `/okstra-inspect`. A blocking `validate-run` failure is named in one line, then this same command; a `validate-run` advisory is named in one line and nothing else — it did not fail the run.
53
+
54
+ For every other task type:
55
+
56
+ - Pointer `status: ready` → `/okstra-run` for that `phase`. Quote the pointer's `rationale` — that sentence is this run's report saying why that phase comes next, and it is the analysis the user asked for.
57
+ - Pointer `status: terminal` → the lifecycle ends here. Say the task is finished and quote the pointer's `rationale`. Do not propose a run and do not send the user to `/okstra-inspect`: the decision is already made, so there is nothing to inspect. If this run registered follow-up tasks, name them and the command that starts one.
58
+ - Pointer `status: blocked` → the pointer's `rationale` names what is in the way and what to run. Quote it and issue that command — `/okstra-user-response` for the `C-NNN` ids it lists, or `/okstra-run` for the phase it names.
59
+ - Pointer `status: pending` with a `rationale` → the comparison finished and the user's own choice is what comes next. Quote the `rationale` and issue the command it names. Do not re-run the phase that just completed, and do not send the user to `/okstra-inspect`: a finished phase has nothing to inspect, and re-running it discards the result the user is being asked to choose from.
60
+ - Phase 7 `validate-run` failed → one line naming the blocking cause, then `/okstra-run` to re-run this phase. Only a failure matching the blocking allowlist (`okstra_ctl.blocking_checks`) reaches this row; every other finding was demoted to an advisory, printed as `validate-run: advisory — <finding>`, and the run passed. Name those advisories in one line and take the command from the matching pointer row above — an advisory is not a reason to re-run.
38
61
  - Otherwise → `/okstra-inspect status` for this task.
39
62
 
40
63
  Do not end the turn after the validator result. Task-qualified report paths and the same table live in the lifecycle core contract (`{{OKSTRA_LEAD_CONTRACT_PATH}}` "After persistence").
@@ -43,6 +66,8 @@ Do not end the turn after the validator result. Task-qualified report paths and
43
66
 
44
67
  ## Project Root
45
68
 
69
+ **Enforced:** emitted by `okstra_ctl.worker_prompt_headers` and required of every worker-facing prompt through `worker_prompt_policy` / `worker_prompt_contract`, so a dispatch without it fails before the worker starts.
70
+
46
71
  - Absolute project root: `{{PROJECT_ROOT}}`
47
72
  - All other paths in this prompt are relative to this root unless they begin with `/`.
48
73
  - When dispatching workers, you MUST include this absolute root in every worker prompt header so that workers do not depend on inherited cwd to resolve relative paths.
@@ -117,6 +142,7 @@ The **default is full re-verification**. Narrow this re-run to the impacted stag
117
142
  0. **Honour the scope the user already pinned (not a judgement — an instruction).** The wizard asks for a re-verification scope whenever this re-run is narrowable or an answered id traces to no stage, and the answer arrives as two tokens: mode `{{REVERIFY_SCOPE_MODE}}`, stages `{{REVERIFY_SCOPE_STAGES}}`. Apply it before you form your own view:
118
143
  - `auto` — the user left the decision to this procedure. Run steps 1–7 exactly as written; nothing is pinned. If the CLI returns `mode == "incremental"`, keep it; do not upgrade to full.
119
144
  - `full` — the user asked for full re-verification. Still call the CLI once (the record is the audit trail), passing `--full-reason "user requested full re-verification"` and every other CSV empty. Do not argue the user out of it with a narrower `--impacted`: the answer already weighed the cost.
145
+ - `carry-all` — the user said this re-run only ADDS stages: every prior stage is `done` and none is being re-opened, so there is no stage number to pin. Call the CLI once with `--carry-all-reason "user pinned carry-all: this re-run only adds stages"` and every other CSV empty. Do not substitute `--impacted` with prior stage numbers: `incremental-carry` then demands those stages from the current snapshot, which no longer holds a `done` stage. The CLI still applies the base-ref check, so a moved branch correctly degrades the decision to `full`.
120
146
  - `stages` — the user named the stages that must be re-verified. Put **every** number in `{{REVERIFY_SCOPE_STAGES}}` into `--impacted`, unioned with any stage you resolve yourself. Never drop one because your own back-trace did not reach it — the user is telling you about a blast radius the prior report failed to record, which is exactly what the back-trace cannot see. The CLI still applies the dependency closure and the cutoff on top, so a wide enough pin correctly ends in `mode == "full"`.
121
147
  1. **List the answered clarifications (a fact, not a judgement).** Collect the `C-NNN` ids you reconciled as answered in §1, and the IDs of any PREP items changed by the carried response. Pass the ids through `--answered-clarifications`; the CLI resolves which Stage Map stages each one touches by reading the prior run's own links — the `P-*` plan item that carried that `clarificationId`, and the requirement-coverage row blocked on `C-NNN` in either its `status` or its `approvalDisposition` (a `documented-deviation` row records the block in the latter). Do NOT map answers to stage numbers yourself.
122
148
  - An id that traces to no stage in the prior report does **not** force `mode == "full"` for the whole re-run. The CLI returns `mode == "unresolved"` and names the ids. Ask the user for the stage numbers those answers affect, then call the CLI again with those numbers in `--impacted`. Do not drop the unlinked id from `--answered-clarifications`. Do not treat `unresolved` as full, and do not silently narrow to the ids that did trace. An approval blocker in this shape should have failed the prior report's back-trace; naming stages is the remaining outlet.
@@ -129,6 +155,7 @@ The **default is full re-verification**. Narrow this re-run to the impacted stag
129
155
  ```
130
156
  okstra incremental-scope \
131
157
  --prev-data runs/implementation-planning/reports/final-report-implementation-planning-<prev-seq>.data.json \
158
+ --run-manifest {{RUN_MANIFEST_RELATIVE_PATH}} \
132
159
  --cur-base-sha {{EXECUTOR_WORKTREE_BASE_REF}} \
133
160
  --prev-base-sha <prior baseRef from step 2> \
134
161
  --impacted <csv of impacted stage numbers, empty for full> \
@@ -136,19 +163,18 @@ The **default is full re-verification**. Narrow this re-run to the impacted stag
136
163
  --answered-clarifications <csv of answered C-NNN ids, empty when none> \
137
164
  --full-reason "<empty, or what structural change forces full>"
138
165
  ```
139
- The CLI reads the plan's dependency graph from the prior `implementationPlanning.stageMap`, which is authoritative for the impacted stage numbers. The CLI prints JSON `{mode, reverify_stages, carry_stages, reason}`. Instruct the report writer to record this decision in its narrative as `implementationPlanning.incrementalDecision`, using camel-case array keys `reverifyStages` and `carryStages`. Final report assembly preserves that writer-owned decision.
166
+ The CLI reads the plan's dependency graph from the prior `implementationPlanning.stageMap`, which is authoritative for the impacted stage numbers. The CLI prints JSON `{mode, reverify_stages, carry_stages, reason}` **and writes the same decision** to the record this run's manifest names in `incrementalDecisionPath`. You do not transcribe it: the report writer receives it through its authoring contract, and `incremental-carry` reads the same record. An `unresolved` result is a question back to you and is deliberately not recorded.
140
167
  4. **`mode == "full"`** → run the existing full re-verification path unchanged; ignore `reverify_stages` / `carry_stages`.
141
168
  5. **`mode == "incremental"`** → scope every worker dispatch prompt to `reverify_stages` only (the downstream closure of the impacted stages). Do NOT re-analyze `carry_stages` — their prior plan-item verdicts are carried forward verbatim (see `prompts/profiles/implementation-planning.md` "Cross-verification mode" and `prompts/lead/convergence.md` "Convergence scope"). When the pin in step 0 was `auto`, this is the decision — do not upgrade it to full.
142
169
  6. **`mode == "unresolved"`** → ask the user for stage numbers; re-enter step 3 with those numbers in `--impacted`. Do not fall back to full. Do not record `unresolved` as `incrementalDecision`. Then continue from the new `mode`.
143
- 7. **Merge carried-forward verdicts.** In `incremental` mode, the report writer includes every `carry_stages` stage row unchanged in its narrative. After `okstra plan-items seed --narrative ... --state ...`, the lead runs:
170
+ 7. **Merge carried-forward verdicts.** In `incremental` mode the report writer receives the carried stage rows as a packet source and is told, in its own authoring contract, to copy them unchanged — you do not repeat that instruction to it. After `okstra plan-items seed --narrative ... --state ...`, the lead runs:
144
171
  ```
145
172
  okstra incremental-carry \
146
173
  --prev-data runs/implementation-planning/reports/final-report-implementation-planning-<prev-seq>.data.json \
147
174
  --cur-narrative <this run's report-writer narrative> \
148
175
  --state <this run's plan-body-verification state> \
149
176
  --prev-seq <prev-seq> \
150
- --carry-stages <csv from incrementalDecision.carry_stages> \
151
- --reverify-stages <csv from incrementalDecision.reverify_stages> \
177
+ --decision {{INCREMENTAL_DECISION_STATE_RELATIVE_PATH}} \
152
178
  --out-state <this run's plan-body-verification state>
153
179
  ```
154
180
  A non-zero exit means the writer changed or omitted a carried stage, the item set drifted, or the stage scopes conflict. Fall back to **full** and re-verify every stage. The command writes only the convergence-owned plan state. It never patches the writer narrative or final `data.json`. `verdictCard` / `finalVerdict` are never carried.