okstra 0.186.7 → 0.188.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (546) hide show
  1. package/README.md +1 -1
  2. package/dist/cli-registry.d.mts +88 -1
  3. package/dist/cli-registry.mjs +68 -111
  4. package/dist/cli-registry.mjs.map +1 -1
  5. package/dist/commands/execute/render-bundle.mjs +0 -1
  6. package/dist/commands/execute/render-bundle.mjs.map +1 -1
  7. package/dist/commands/execute/run.mjs +8 -3
  8. package/dist/commands/execute/run.mjs.map +1 -1
  9. package/dist/commands/lifecycle/check-project.mjs +1 -14
  10. package/dist/commands/lifecycle/check-project.mjs.map +1 -1
  11. package/dist/commands/lifecycle/config.mjs +38 -40
  12. package/dist/commands/lifecycle/config.mjs.map +1 -1
  13. package/dist/commands/lifecycle/doctor.d.mts +22 -7
  14. package/dist/commands/lifecycle/doctor.mjs +77 -49
  15. package/dist/commands/lifecycle/doctor.mjs.map +1 -1
  16. package/dist/commands/lifecycle/install.d.mts +12 -10
  17. package/dist/commands/lifecycle/install.mjs +107 -40
  18. package/dist/commands/lifecycle/install.mjs.map +1 -1
  19. package/dist/commands/lifecycle/paths.mjs +8 -3
  20. package/dist/commands/lifecycle/paths.mjs.map +1 -1
  21. package/dist/commands/lifecycle/preflight.mjs +2 -1
  22. package/dist/commands/lifecycle/preflight.mjs.map +1 -1
  23. package/dist/commands/lifecycle/setup.mjs +22 -36
  24. package/dist/commands/lifecycle/setup.mjs.map +1 -1
  25. package/dist/commands/lifecycle/uninstall.d.mts +4 -2
  26. package/dist/commands/lifecycle/uninstall.mjs +59 -15
  27. package/dist/commands/lifecycle/uninstall.mjs.map +1 -1
  28. package/dist/commands/memory/memory.mjs +7 -1
  29. package/dist/commands/memory/memory.mjs.map +1 -1
  30. package/dist/lib/helper-scripts.d.mts +1 -1
  31. package/dist/lib/helper-scripts.mjs +10 -18
  32. package/dist/lib/helper-scripts.mjs.map +1 -1
  33. package/dist/lib/host-config.d.mts +72 -0
  34. package/dist/lib/host-config.mjs +404 -0
  35. package/dist/lib/host-config.mjs.map +1 -0
  36. package/dist/lib/host-registry-client.d.mts +2 -2
  37. package/dist/lib/host-registry-client.mjs +0 -3
  38. package/dist/lib/host-registry-client.mjs.map +1 -1
  39. package/dist/lib/install-assets.d.mts +1 -0
  40. package/dist/lib/install-assets.mjs +4 -0
  41. package/dist/lib/install-assets.mjs.map +1 -1
  42. package/dist/lib/proc.d.mts +2 -0
  43. package/dist/lib/proc.mjs +12 -0
  44. package/dist/lib/proc.mjs.map +1 -1
  45. package/dist/lib/python-command.d.mts +2 -0
  46. package/dist/lib/python-command.mjs +52 -0
  47. package/dist/lib/python-command.mjs.map +1 -0
  48. package/dist/lib/python-helper.d.mts +2 -5
  49. package/dist/lib/python-helper.mjs +3 -52
  50. package/dist/lib/python-helper.mjs.map +1 -1
  51. package/dist/lib/runtime-payload.d.mts +23 -0
  52. package/dist/lib/runtime-payload.mjs +57 -0
  53. package/dist/lib/runtime-payload.mjs.map +1 -0
  54. package/dist/lib/types.d.mts +24 -13
  55. package/docs/architecture/storage-model.md +21 -5
  56. package/docs/architecture.md +39 -38
  57. package/docs/cli.md +55 -76
  58. package/docs/coding-rules.md +295 -0
  59. package/docs/container.md +10 -36
  60. package/docs/contributor-change-matrix.md +1 -1
  61. package/docs/for-ai/skills/okstra-code-review.md +0 -1
  62. package/docs/for-ai/skills/okstra-container-build.md +8 -41
  63. package/docs/for-ai/skills/okstra-inspect.md +4 -4
  64. package/docs/for-ai/skills/okstra-manager.md +2 -2
  65. package/docs/for-ai/skills/okstra-rollup.md +0 -1
  66. package/docs/for-ai/skills/okstra-run.md +3 -3
  67. package/docs/for-ai/skills/okstra-user-response.md +0 -1
  68. package/docs/performance-improvement-plan-v2.md +1 -1
  69. package/docs/project-structure-overview.md +62 -62
  70. package/docs/task-process/README.md +3 -3
  71. package/docs/task-process/common-flow.md +1 -1
  72. package/docs/task-process/error-analysis.md +3 -3
  73. package/docs/task-process/implementation-planning.md +3 -1
  74. package/docs/task-process/release-handoff.md +1 -1
  75. package/package.json +3 -2
  76. package/runtime/BUILD.json +2 -2
  77. package/runtime/agents/workers/claude-worker.md +6 -11
  78. package/runtime/agents/workers/report-writer-worker.md +1 -1
  79. package/runtime/bin/lib/okstra/cli.sh +4 -0
  80. package/runtime/bin/lib/okstra/globals.sh +2 -0
  81. package/runtime/bin/lib/okstra/interactive.sh +26 -173
  82. package/runtime/bin/lib/okstra/project-resolver.sh +23 -61
  83. package/runtime/bin/lib/okstra/usage.sh +3 -3
  84. package/runtime/bin/okstra-compact-reminder.sh +1 -5
  85. package/runtime/bin/okstra-error-log.py +19 -2
  86. package/runtime/bin/okstra-import-check.py +26 -0
  87. package/runtime/bin/okstra-inject-report-index.py +5 -4
  88. package/runtime/bin/okstra-provider-exec.py +22 -17
  89. package/runtime/bin/okstra-render-final-report.py +16 -6
  90. package/runtime/bin/okstra-render-report-views.py +47 -22
  91. package/runtime/bin/okstra-report-translate.py +30 -18
  92. package/runtime/bin/okstra-spawn-followups.py +4 -0
  93. package/runtime/bin/okstra-token-usage.py +3 -0
  94. package/runtime/bin/okstra.sh +4 -2
  95. package/runtime/bin/okstra_bootstrap.py +58 -0
  96. package/runtime/prompts/coding-preflight/overview.md +1 -1
  97. package/runtime/prompts/duties/planning-worker.md +1 -1
  98. package/runtime/prompts/launch.template.md +35 -9
  99. package/runtime/prompts/lead/adapters/cmux.md +3 -3
  100. package/runtime/prompts/lead/convergence.md +99 -88
  101. package/runtime/prompts/lead/okstra-lead-contract.md +63 -12
  102. package/runtime/prompts/lead/plan-body-verification.md +65 -46
  103. package/runtime/prompts/lead/report-writer.md +35 -5
  104. package/runtime/prompts/lead/team-contract.md +4 -1
  105. package/runtime/prompts/profiles/_clarification-recommendation.md +2 -1
  106. package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
  107. package/runtime/prompts/profiles/_common-contract.md +3 -3
  108. package/runtime/prompts/profiles/_coverage-critic.md +1 -1
  109. package/runtime/prompts/profiles/_implementation-deliverable.md +2 -2
  110. package/runtime/prompts/profiles/_implementation-executor.md +3 -1
  111. package/runtime/prompts/profiles/_implementation-verifier.md +16 -2
  112. package/runtime/prompts/profiles/error-analysis.md +4 -3
  113. package/runtime/prompts/profiles/final-verification.md +2 -2
  114. package/runtime/prompts/profiles/implementation-planning.md +22 -17
  115. package/runtime/prompts/profiles/implementation.md +3 -2
  116. package/runtime/prompts/profiles/requirements-discovery.md +2 -1
  117. package/runtime/prompts/wizard/prompts.ko.json +29 -8
  118. package/runtime/python/okstra_ctl/__init__.py +6 -27
  119. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -5
  120. package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +21 -2
  121. package/runtime/python/okstra_ctl/adapters/hosts/external/adapter.py +3 -12
  122. package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +63 -22
  123. package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +20 -21
  124. package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +37 -20
  125. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +86 -14
  126. package/runtime/python/okstra_ctl/adapters/providers/kimi/adapter.py +12 -12
  127. package/runtime/python/okstra_ctl/adapters/runtime/cmux.py +4 -7
  128. package/runtime/python/okstra_ctl/agent/__init__.py +1 -0
  129. package/runtime/python/okstra_ctl/{agent_activity.py → agent/activity.py} +16 -2
  130. package/runtime/python/okstra_ctl/{agent_invocation.py → agent/invocation.py} +34 -5
  131. package/runtime/python/okstra_ctl/agent/prompt_cli/__init__.py +19 -0
  132. package/runtime/python/okstra_ctl/agent/prompt_cli/__main__.py +11 -0
  133. package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +228 -0
  134. package/runtime/python/okstra_ctl/agent/prompt_cli/dynamic_verifier.py +155 -0
  135. package/runtime/python/okstra_ctl/agent/prompt_cli/emit.py +66 -0
  136. package/runtime/python/okstra_ctl/agent/prompt_cli/inputs.py +138 -0
  137. package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +605 -0
  138. package/runtime/python/okstra_ctl/agent/prompt_cli/results.py +197 -0
  139. package/runtime/python/okstra_ctl/agent/prompt_cli/run_identity.py +107 -0
  140. package/runtime/python/okstra_ctl/analysis_packet.py +47 -4
  141. package/runtime/python/okstra_ctl/approval_decisions.py +287 -10
  142. package/runtime/python/okstra_ctl/assignment_resolver.py +0 -12
  143. package/runtime/python/okstra_ctl/attempt_evidence.py +12 -24
  144. package/runtime/python/okstra_ctl/blocking_checks.py +251 -0
  145. package/runtime/python/okstra_ctl/brief_frontmatter.py +0 -7
  146. package/runtime/python/okstra_ctl/clarification_items/__init__.py +102 -0
  147. package/runtime/python/okstra_ctl/clarification_items/carry.py +224 -0
  148. package/runtime/python/okstra_ctl/clarification_items/dispositions.py +135 -0
  149. package/runtime/python/okstra_ctl/clarification_items/parsing.py +253 -0
  150. package/runtime/python/okstra_ctl/clarification_items/rows.py +115 -0
  151. package/runtime/python/okstra_ctl/clarification_items/scan.py +215 -0
  152. package/runtime/python/okstra_ctl/clarification_items/sidecars.py +211 -0
  153. package/runtime/python/okstra_ctl/cmux.py +38 -31
  154. package/runtime/python/okstra_ctl/code_review_target.py +163 -1
  155. package/runtime/python/okstra_ctl/conformance.py +23 -0
  156. package/runtime/python/okstra_ctl/container.py +38 -421
  157. package/runtime/python/okstra_ctl/context_cost.py +32 -4
  158. package/runtime/python/okstra_ctl/contract_graph_cli.py +7 -0
  159. package/runtime/python/okstra_ctl/convergence.py +107 -16
  160. package/runtime/python/okstra_ctl/convergence_critic_prompt.py +345 -0
  161. package/runtime/python/okstra_ctl/convergence_engine.py +382 -70
  162. package/runtime/python/okstra_ctl/convergence_store.py +5 -29
  163. package/runtime/python/okstra_ctl/design_prep.py +108 -12
  164. package/runtime/python/okstra_ctl/design_snapshot.py +11 -1
  165. package/runtime/python/okstra_ctl/design_surfaces.py +29 -2
  166. package/runtime/python/okstra_ctl/dispatch_core.py +236 -49
  167. package/runtime/python/okstra_ctl/dispatch_state.py +417 -41
  168. package/runtime/python/okstra_ctl/doctor_cli.py +48 -0
  169. package/runtime/python/okstra_ctl/domain/worker_exec.py +10 -5
  170. package/runtime/python/okstra_ctl/domain/worker_presentation.py +28 -1
  171. package/runtime/python/okstra_ctl/domain/worker_stream.py +52 -21
  172. package/runtime/python/okstra_ctl/domain/write_policy.py +219 -0
  173. package/runtime/python/okstra_ctl/entrypoints/hosts.py +9 -2
  174. package/runtime/python/okstra_ctl/error_log_core.py +1 -1
  175. package/runtime/python/okstra_ctl/error_report.py +14 -0
  176. package/runtime/python/okstra_ctl/error_zip.py +18 -2
  177. package/runtime/python/okstra_ctl/exact_coverage.py +5 -0
  178. package/runtime/python/okstra_ctl/execution_identity.py +100 -7
  179. package/runtime/python/okstra_ctl/execution_manifest.py +67 -20
  180. package/runtime/python/okstra_ctl/execution_mutation_audit.py +90 -8
  181. package/runtime/python/okstra_ctl/final_report_paths.py +17 -0
  182. package/runtime/python/okstra_ctl/final_report_schema.py +319 -17
  183. package/runtime/python/okstra_ctl/git_reconcile.py +22 -2
  184. package/runtime/python/okstra_ctl/handoff.py +24 -1
  185. package/runtime/python/okstra_ctl/ids.py +6 -16
  186. package/runtime/python/okstra_ctl/implementation_direction.py +142 -33
  187. package/runtime/python/okstra_ctl/implementation_options.py +32 -13
  188. package/runtime/python/okstra_ctl/implementation_outcome.py +5 -2
  189. package/runtime/python/okstra_ctl/improvement_lenses.py +0 -14
  190. package/runtime/python/okstra_ctl/incremental_carry.py +69 -8
  191. package/runtime/python/okstra_ctl/incremental_scope.py +173 -12
  192. package/runtime/python/okstra_ctl/index.py +2 -2
  193. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +48 -8
  194. package/runtime/python/okstra_ctl/interactive_cli.py +223 -0
  195. package/runtime/python/okstra_ctl/json_boundary.py +10 -0
  196. package/runtime/python/okstra_ctl/listing.py +0 -91
  197. package/runtime/python/okstra_ctl/locks.py +5 -19
  198. package/runtime/python/okstra_ctl/log_report.py +14 -0
  199. package/runtime/python/okstra_ctl/manager_cli.py +22 -3
  200. package/runtime/python/okstra_ctl/manager_launch.py +4 -8
  201. package/runtime/python/okstra_ctl/material.py +2 -2
  202. package/runtime/python/okstra_ctl/migrate.py +23 -1
  203. package/runtime/python/okstra_ctl/model_cli.py +19 -5
  204. package/runtime/python/okstra_ctl/model_discovery.py +46 -47
  205. package/runtime/python/okstra_ctl/model_io/__init__.py +1 -0
  206. package/runtime/python/okstra_ctl/model_io/lines.py +163 -0
  207. package/runtime/python/okstra_ctl/model_io/references.py +370 -0
  208. package/runtime/python/okstra_ctl/model_io/renderers.py +498 -0
  209. package/runtime/python/okstra_ctl/model_io_cli.py +30 -945
  210. package/runtime/python/okstra_ctl/model_pool.py +10 -6
  211. package/runtime/python/okstra_ctl/models.py +8 -8
  212. package/runtime/python/okstra_ctl/mutation_recovery.py +5 -63
  213. package/runtime/python/okstra_ctl/next_phase.py +121 -69
  214. package/runtime/python/okstra_ctl/pane_reclaim.py +23 -0
  215. package/runtime/python/okstra_ctl/pane_title.py +11 -8
  216. package/runtime/python/okstra_ctl/path_hints.py +36 -11
  217. package/runtime/python/okstra_ctl/paths.py +76 -8
  218. package/runtime/python/okstra_ctl/plan_items.py +132 -16
  219. package/runtime/python/okstra_ctl/plan_items_cli.py +486 -36
  220. package/runtime/python/okstra_ctl/plan_run_root.py +1 -1
  221. package/runtime/python/okstra_ctl/plan_validate_cli.py +51 -0
  222. package/runtime/python/okstra_ctl/plan_verify_cli.py +80 -0
  223. package/runtime/python/okstra_ctl/prepare_error.py +20 -0
  224. package/runtime/python/okstra_ctl/prior_planning.py +157 -0
  225. package/runtime/python/okstra_ctl/profile_show.py +18 -1
  226. package/runtime/python/okstra_ctl/project_setup_cli.py +140 -0
  227. package/runtime/python/okstra_ctl/recap.py +22 -1
  228. package/runtime/python/okstra_ctl/reconcile.py +84 -0
  229. package/runtime/python/okstra_ctl/registry/host_registry.py +18 -1
  230. package/runtime/python/okstra_ctl/render.py +98 -32
  231. package/runtime/python/okstra_ctl/render_final_report.py +4 -8
  232. package/runtime/python/okstra_ctl/report_assembly.py +297 -7
  233. package/runtime/python/okstra_ctl/report_contract.py +30 -7
  234. package/runtime/python/okstra_ctl/report_finalize.py +213 -16
  235. package/runtime/python/okstra_ctl/report_html/common.py +2 -2
  236. package/runtime/python/okstra_ctl/report_html/render.py +8 -12
  237. package/runtime/python/okstra_ctl/report_language.py +8 -4
  238. package/runtime/python/okstra_ctl/report_narrative.py +220 -34
  239. package/runtime/python/okstra_ctl/report_projections.py +8 -2
  240. package/runtime/python/okstra_ctl/report_synthesis_packet.py +393 -1
  241. package/runtime/python/okstra_ctl/report_translation.py +2 -35
  242. package/runtime/python/okstra_ctl/report_view_artifacts.py +42 -2
  243. package/runtime/python/okstra_ctl/report_views.py +4 -22
  244. package/runtime/python/okstra_ctl/resolve_task_key.py +13 -0
  245. package/runtime/python/okstra_ctl/rollup.py +13 -0
  246. package/runtime/python/okstra_ctl/run.py +639 -138
  247. package/runtime/python/okstra_ctl/run_audit.py +13 -0
  248. package/runtime/python/okstra_ctl/run_index_row.py +0 -12
  249. package/runtime/python/okstra_ctl/seeding.py +21 -11
  250. package/runtime/python/okstra_ctl/sequence.py +1 -1
  251. package/runtime/python/okstra_ctl/session.py +64 -14
  252. package/runtime/python/okstra_ctl/set_work_status.py +18 -0
  253. package/runtime/python/okstra_ctl/stage_integrate.py +15 -1
  254. package/runtime/python/okstra_ctl/stage_ledger.py +1 -1
  255. package/runtime/python/okstra_ctl/stage_map.py +57 -11
  256. package/runtime/python/okstra_ctl/stage_map_cli.py +83 -0
  257. package/runtime/python/okstra_ctl/stage_map_view.py +65 -0
  258. package/runtime/python/okstra_ctl/stage_targets.py +3 -12
  259. package/runtime/python/okstra_ctl/task_list_cli.py +138 -0
  260. package/runtime/python/okstra_ctl/task_show_cli.py +66 -0
  261. package/runtime/python/okstra_ctl/task_target.py +4 -16
  262. package/runtime/python/okstra_ctl/team.py +49 -2
  263. package/runtime/python/okstra_ctl/time_report.py +17 -2
  264. package/runtime/python/okstra_ctl/usage_report.py +11 -0
  265. package/runtime/python/okstra_ctl/user_response.py +55 -218
  266. package/runtime/python/okstra_ctl/user_response_values.py +242 -0
  267. package/runtime/python/okstra_ctl/validation_contract.py +3 -0
  268. package/runtime/python/okstra_ctl/verdict_blocks.py +28 -8
  269. package/runtime/python/okstra_ctl/verification_target.py +68 -0
  270. package/runtime/python/okstra_ctl/wizard.py +457 -92
  271. package/runtime/python/okstra_ctl/worker_artifacts.py +75 -16
  272. package/runtime/python/okstra_ctl/worker_audit_check.py +22 -0
  273. package/runtime/python/okstra_ctl/worker_dispatch.py +21 -0
  274. package/runtime/python/okstra_ctl/worker_liveness.py +33 -0
  275. package/runtime/python/okstra_ctl/worker_prompt_body.py +15 -2
  276. package/runtime/python/okstra_ctl/worker_prompt_contract.py +98 -7
  277. package/runtime/python/okstra_ctl/worker_prompt_headers.py +24 -2
  278. package/runtime/python/okstra_ctl/worker_prompt_policy.py +18 -3
  279. package/runtime/python/okstra_ctl/worker_request.py +2 -1
  280. package/runtime/python/okstra_ctl/worker_runner.py +58 -17
  281. package/runtime/python/okstra_ctl/worker_state.py +16 -1
  282. package/runtime/python/okstra_ctl/workflow.py +18 -1
  283. package/runtime/python/okstra_ctl/worktree/__init__.py +92 -0
  284. package/runtime/python/okstra_ctl/worktree/cleanliness.py +89 -0
  285. package/runtime/python/okstra_ctl/worktree/decisions.py +127 -0
  286. package/runtime/python/okstra_ctl/worktree/git_ops.py +165 -0
  287. package/runtime/python/okstra_ctl/worktree/linking.py +249 -0
  288. package/runtime/python/okstra_ctl/worktree/naming.py +91 -0
  289. package/runtime/python/okstra_ctl/worktree/provision.py +385 -0
  290. package/runtime/python/okstra_ctl/worktree/sync_config.py +181 -0
  291. package/runtime/python/okstra_ctl/worktree_cli.py +75 -0
  292. package/runtime/python/okstra_ctl/worktree_lookup_cli.py +39 -0
  293. package/runtime/python/okstra_ctl/worktree_registry.py +7 -0
  294. package/runtime/python/okstra_ctl/worktree_status_cli.py +53 -0
  295. package/runtime/python/okstra_ctl/write_policy.py +90 -213
  296. package/runtime/python/okstra_project/__init__.py +0 -4
  297. package/runtime/python/okstra_project/dirs.py +2 -2
  298. package/runtime/python/okstra_project/phase_pointer.py +84 -0
  299. package/runtime/python/okstra_project/slug.py +24 -0
  300. package/runtime/python/okstra_project/state.py +22 -230
  301. package/runtime/python/okstra_token_usage/antigravity.py +50 -12
  302. package/runtime/python/okstra_token_usage/claude.py +9 -1
  303. package/runtime/python/okstra_token_usage/cli.py +3 -1
  304. package/runtime/python/okstra_token_usage/collect.py +171 -36
  305. package/runtime/python/okstra_token_usage/cursor.py +2 -0
  306. package/runtime/python/okstra_token_usage/grok.py +1 -5
  307. package/runtime/python/okstra_token_usage/paths.py +26 -0
  308. package/runtime/python/okstra_token_usage/pricing.py +23 -8
  309. package/runtime/schemas/convergence-critic-results-v1.0.schema.json +5 -0
  310. package/runtime/schemas/execution-manifest-v2.schema.json +10 -10
  311. package/runtime/schemas/final-report-v2.0.schema.json +9 -26
  312. package/runtime/schemas/final-report-v3.0.schema.json +173 -41
  313. package/runtime/schemas/report-narrative-v3.0.schema.json +3 -2
  314. package/runtime/skills/okstra-brief-gen/SKILL.md +35 -2
  315. package/runtime/skills/okstra-container-build/SKILL.md +16 -47
  316. package/runtime/skills/okstra-inspect/facets/history.md +1 -1
  317. package/runtime/skills/okstra-inspect/facets/status.md +7 -6
  318. package/runtime/skills/okstra-pr-gen/SKILL.md +1 -1
  319. package/runtime/skills/okstra-run/SKILL.md +7 -5
  320. package/runtime/templates/report-writer-prompt-preamble.md +3 -1
  321. package/runtime/templates/reports/brief.template.md +6 -2
  322. package/runtime/templates/reports/error-analysis-input.template.md +2 -0
  323. package/runtime/templates/reports/final-verification-input.template.md +2 -0
  324. package/runtime/templates/reports/implementation-input.template.md +7 -1
  325. package/runtime/templates/reports/implementation-planning-input.template.md +4 -0
  326. package/runtime/templates/reports/quick-input.template.md +2 -0
  327. package/runtime/templates/reports/release-handoff-input.template.md +6 -1
  328. package/runtime/templates/reports/report.js +20 -3
  329. package/runtime/templates/reports/schedule.template.md +2 -0
  330. package/runtime/templates/reports/settings.template.json +0 -10
  331. package/runtime/templates/reports/task-brief.template.md +3 -0
  332. package/runtime/templates/reports/user-response.template.md +7 -3
  333. package/runtime/validators/checks/fixtures-01.py +57 -0
  334. package/runtime/validators/checks/fixtures-02.py +565 -0
  335. package/runtime/validators/checks/runners-01.py +108 -0
  336. package/runtime/validators/checks/validate-assets-01.py +60 -0
  337. package/runtime/validators/checks/validate-prompt-metadata-01.py +261 -0
  338. package/runtime/validators/checks/validate-tasks-01.py +46 -0
  339. package/runtime/validators/checks/validate-tasks-02.py +85 -0
  340. package/runtime/validators/checks/validate-tasks-03.py +61 -0
  341. package/runtime/validators/checks/validate-tasks-04.py +118 -0
  342. package/runtime/validators/forbidden_actions.py +73 -3
  343. package/runtime/validators/lib/common.sh +5 -0
  344. package/runtime/validators/lib/fixtures.sh +7 -591
  345. package/runtime/validators/lib/paths.sh +13 -0
  346. package/runtime/validators/lib/runners.sh +6 -104
  347. package/runtime/validators/lib/summary.sh +1 -1
  348. package/runtime/validators/lib/validate-assets.sh +6 -56
  349. package/runtime/validators/lib/validate-prompt-metadata.sh +6 -257
  350. package/runtime/validators/lib/validate-tasks.sh +9 -294
  351. package/runtime/validators/validate-implementation-plan-stages.py +4 -4
  352. package/runtime/validators/validate-run.py +1363 -2643
  353. package/runtime/validators/validate-workflow.sh +56 -16
  354. package/runtime/validators/validate_improvement_report.py +2 -1
  355. package/runtime/validators/validate_session_conformance.py +295 -49
  356. package/dist/commands/execute/agent-prompt.d.mts +0 -1
  357. package/dist/commands/execute/agent-prompt.mjs +0 -24
  358. package/dist/commands/execute/agent-prompt.mjs.map +0 -1
  359. package/dist/commands/execute/codex-dispatch.d.mts +0 -3
  360. package/dist/commands/execute/codex-dispatch.mjs +0 -6
  361. package/dist/commands/execute/codex-dispatch.mjs.map +0 -1
  362. package/dist/commands/execute/codex-run.d.mts +0 -3
  363. package/dist/commands/execute/codex-run.mjs +0 -62
  364. package/dist/commands/execute/codex-run.mjs.map +0 -1
  365. package/dist/commands/execute/convergence.d.mts +0 -1
  366. package/dist/commands/execute/convergence.mjs +0 -38
  367. package/dist/commands/execute/convergence.mjs.map +0 -1
  368. package/dist/commands/execute/error-log.d.mts +0 -1
  369. package/dist/commands/execute/error-log.mjs +0 -18
  370. package/dist/commands/execute/error-log.mjs.map +0 -1
  371. package/dist/commands/execute/git-reconcile.d.mts +0 -1
  372. package/dist/commands/execute/git-reconcile.mjs +0 -30
  373. package/dist/commands/execute/git-reconcile.mjs.map +0 -1
  374. package/dist/commands/execute/handoff.d.mts +0 -1
  375. package/dist/commands/execute/handoff.mjs +0 -31
  376. package/dist/commands/execute/handoff.mjs.map +0 -1
  377. package/dist/commands/execute/incremental-carry.d.mts +0 -1
  378. package/dist/commands/execute/incremental-carry.mjs +0 -20
  379. package/dist/commands/execute/incremental-carry.mjs.map +0 -1
  380. package/dist/commands/execute/incremental-scope.d.mts +0 -1
  381. package/dist/commands/execute/incremental-scope.mjs +0 -29
  382. package/dist/commands/execute/incremental-scope.mjs.map +0 -1
  383. package/dist/commands/execute/integrate-stages.d.mts +0 -1
  384. package/dist/commands/execute/integrate-stages.mjs +0 -24
  385. package/dist/commands/execute/integrate-stages.mjs.map +0 -1
  386. package/dist/commands/execute/pane-title.d.mts +0 -1
  387. package/dist/commands/execute/pane-title.mjs +0 -20
  388. package/dist/commands/execute/pane-title.mjs.map +0 -1
  389. package/dist/commands/execute/plan-items.d.mts +0 -1
  390. package/dist/commands/execute/plan-items.mjs +0 -9
  391. package/dist/commands/execute/plan-items.mjs.map +0 -1
  392. package/dist/commands/execute/plan-validate.d.mts +0 -1
  393. package/dist/commands/execute/plan-validate.mjs +0 -68
  394. package/dist/commands/execute/plan-validate.mjs.map +0 -1
  395. package/dist/commands/execute/plan-verify.d.mts +0 -1
  396. package/dist/commands/execute/plan-verify.mjs +0 -43
  397. package/dist/commands/execute/plan-verify.mjs.map +0 -1
  398. package/dist/commands/execute/spawn-followups.d.mts +0 -1
  399. package/dist/commands/execute/spawn-followups.mjs +0 -22
  400. package/dist/commands/execute/spawn-followups.mjs.map +0 -1
  401. package/dist/commands/execute/team.d.mts +0 -3
  402. package/dist/commands/execute/team.mjs +0 -66
  403. package/dist/commands/execute/team.mjs.map +0 -1
  404. package/dist/commands/execute/token-usage.d.mts +0 -1
  405. package/dist/commands/execute/token-usage.mjs +0 -19
  406. package/dist/commands/execute/token-usage.mjs.map +0 -1
  407. package/dist/commands/execute/worker-audit-check.d.mts +0 -1
  408. package/dist/commands/execute/worker-audit-check.mjs +0 -34
  409. package/dist/commands/execute/worker-audit-check.mjs.map +0 -1
  410. package/dist/commands/execute/worker-dispatch.d.mts +0 -7
  411. package/dist/commands/execute/worker-dispatch.mjs +0 -64
  412. package/dist/commands/execute/worker-dispatch.mjs.map +0 -1
  413. package/dist/commands/execute/worker-state.d.mts +0 -1
  414. package/dist/commands/execute/worker-state.mjs +0 -28
  415. package/dist/commands/execute/worker-state.mjs.map +0 -1
  416. package/dist/commands/execute/worktree-lookup.d.mts +0 -1
  417. package/dist/commands/execute/worktree-lookup.mjs +0 -92
  418. package/dist/commands/execute/worktree-lookup.mjs.map +0 -1
  419. package/dist/commands/execute/worktree-status.d.mts +0 -1
  420. package/dist/commands/execute/worktree-status.mjs +0 -121
  421. package/dist/commands/execute/worktree-status.mjs.map +0 -1
  422. package/dist/commands/inspect/code-review.d.mts +0 -1
  423. package/dist/commands/inspect/code-review.mjs +0 -32
  424. package/dist/commands/inspect/code-review.mjs.map +0 -1
  425. package/dist/commands/inspect/container.d.mts +0 -1
  426. package/dist/commands/inspect/container.mjs +0 -25
  427. package/dist/commands/inspect/container.mjs.map +0 -1
  428. package/dist/commands/inspect/context-cost.d.mts +0 -1
  429. package/dist/commands/inspect/context-cost.mjs +0 -25
  430. package/dist/commands/inspect/context-cost.mjs.map +0 -1
  431. package/dist/commands/inspect/design-prep.d.mts +0 -1
  432. package/dist/commands/inspect/design-prep.mjs +0 -22
  433. package/dist/commands/inspect/design-prep.mjs.map +0 -1
  434. package/dist/commands/inspect/error-report.d.mts +0 -1
  435. package/dist/commands/inspect/error-report.mjs +0 -25
  436. package/dist/commands/inspect/error-report.mjs.map +0 -1
  437. package/dist/commands/inspect/error-zip.d.mts +0 -1
  438. package/dist/commands/inspect/error-zip.mjs +0 -24
  439. package/dist/commands/inspect/error-zip.mjs.map +0 -1
  440. package/dist/commands/inspect/log-report.d.mts +0 -1
  441. package/dist/commands/inspect/log-report.mjs +0 -26
  442. package/dist/commands/inspect/log-report.mjs.map +0 -1
  443. package/dist/commands/inspect/model-io.d.mts +0 -1
  444. package/dist/commands/inspect/model-io.mjs +0 -25
  445. package/dist/commands/inspect/model-io.mjs.map +0 -1
  446. package/dist/commands/inspect/profile-show.d.mts +0 -1
  447. package/dist/commands/inspect/profile-show.mjs +0 -28
  448. package/dist/commands/inspect/profile-show.mjs.map +0 -1
  449. package/dist/commands/inspect/recap.d.mts +0 -1
  450. package/dist/commands/inspect/recap.mjs +0 -30
  451. package/dist/commands/inspect/recap.mjs.map +0 -1
  452. package/dist/commands/inspect/resolve-task-key.d.mts +0 -1
  453. package/dist/commands/inspect/resolve-task-key.mjs +0 -24
  454. package/dist/commands/inspect/resolve-task-key.mjs.map +0 -1
  455. package/dist/commands/inspect/rollup.d.mts +0 -1
  456. package/dist/commands/inspect/rollup.mjs +0 -25
  457. package/dist/commands/inspect/rollup.mjs.map +0 -1
  458. package/dist/commands/inspect/run-audit.d.mts +0 -1
  459. package/dist/commands/inspect/run-audit.mjs +0 -25
  460. package/dist/commands/inspect/run-audit.mjs.map +0 -1
  461. package/dist/commands/inspect/set-work-status.d.mts +0 -1
  462. package/dist/commands/inspect/set-work-status.mjs +0 -29
  463. package/dist/commands/inspect/set-work-status.mjs.map +0 -1
  464. package/dist/commands/inspect/stage-map.d.mts +0 -1
  465. package/dist/commands/inspect/stage-map.mjs +0 -131
  466. package/dist/commands/inspect/stage-map.mjs.map +0 -1
  467. package/dist/commands/inspect/task-list.d.mts +0 -1
  468. package/dist/commands/inspect/task-list.mjs +0 -149
  469. package/dist/commands/inspect/task-list.mjs.map +0 -1
  470. package/dist/commands/inspect/task-show.d.mts +0 -1
  471. package/dist/commands/inspect/task-show.mjs +0 -108
  472. package/dist/commands/inspect/task-show.mjs.map +0 -1
  473. package/dist/commands/inspect/time-report.d.mts +0 -1
  474. package/dist/commands/inspect/time-report.mjs +0 -24
  475. package/dist/commands/inspect/time-report.mjs.map +0 -1
  476. package/dist/commands/inspect/usage-report.d.mts +0 -1
  477. package/dist/commands/inspect/usage-report.mjs +0 -23
  478. package/dist/commands/inspect/usage-report.mjs.map +0 -1
  479. package/dist/commands/inspect/user-response.d.mts +0 -1
  480. package/dist/commands/inspect/user-response.mjs +0 -35
  481. package/dist/commands/inspect/user-response.mjs.map +0 -1
  482. package/dist/commands/inspect/worker-liveness.d.mts +0 -1
  483. package/dist/commands/inspect/worker-liveness.mjs +0 -45
  484. package/dist/commands/inspect/worker-liveness.mjs.map +0 -1
  485. package/dist/commands/lifecycle/contract-check.d.mts +0 -1
  486. package/dist/commands/lifecycle/contract-check.mjs +0 -18
  487. package/dist/commands/lifecycle/contract-check.mjs.map +0 -1
  488. package/dist/commands/lifecycle/migrate.d.mts +0 -1
  489. package/dist/commands/lifecycle/migrate.mjs +0 -30
  490. package/dist/commands/lifecycle/migrate.mjs.map +0 -1
  491. package/dist/commands/lifecycle/model.d.mts +0 -1
  492. package/dist/commands/lifecycle/model.mjs +0 -22
  493. package/dist/commands/lifecycle/model.mjs.map +0 -1
  494. package/dist/commands/manager.d.mts +0 -3
  495. package/dist/commands/manager.mjs +0 -50
  496. package/dist/commands/manager.mjs.map +0 -1
  497. package/dist/commands/report/agent-activity.d.mts +0 -1
  498. package/dist/commands/report/agent-activity.mjs +0 -20
  499. package/dist/commands/report/agent-activity.mjs.map +0 -1
  500. package/dist/commands/report/approval-decision.d.mts +0 -1
  501. package/dist/commands/report/approval-decision.mjs +0 -21
  502. package/dist/commands/report/approval-decision.mjs.map +0 -1
  503. package/dist/commands/report/design-snapshot.d.mts +0 -1
  504. package/dist/commands/report/design-snapshot.mjs +0 -19
  505. package/dist/commands/report/design-snapshot.mjs.map +0 -1
  506. package/dist/commands/report/finalize.d.mts +0 -4
  507. package/dist/commands/report/finalize.mjs +0 -64
  508. package/dist/commands/report/finalize.mjs.map +0 -1
  509. package/dist/commands/report/inject-report-index.d.mts +0 -1
  510. package/dist/commands/report/inject-report-index.mjs +0 -21
  511. package/dist/commands/report/inject-report-index.mjs.map +0 -1
  512. package/dist/commands/report/render-final-report.d.mts +0 -1
  513. package/dist/commands/report/render-final-report.mjs +0 -23
  514. package/dist/commands/report/render-final-report.mjs.map +0 -1
  515. package/dist/commands/report/render-views.d.mts +0 -1
  516. package/dist/commands/report/render-views.mjs +0 -27
  517. package/dist/commands/report/render-views.mjs.map +0 -1
  518. package/dist/commands/report/translate.d.mts +0 -1
  519. package/dist/commands/report/translate.mjs +0 -33
  520. package/dist/commands/report/translate.mjs.map +0 -1
  521. package/runtime/bin/lib/okstra/tmux-pane.sh +0 -40
  522. package/runtime/bin/lib/okstra-ctl/cmd-batch.sh +0 -59
  523. package/runtime/bin/lib/okstra-ctl/cmd-list.sh +0 -35
  524. package/runtime/bin/lib/okstra-ctl/cmd-open.sh +0 -36
  525. package/runtime/bin/lib/okstra-ctl/cmd-projects.sh +0 -26
  526. package/runtime/bin/lib/okstra-ctl/cmd-reconcile.sh +0 -29
  527. package/runtime/bin/lib/okstra-ctl/cmd-reindex.sh +0 -38
  528. package/runtime/bin/lib/okstra-ctl/cmd-rerun.sh +0 -345
  529. package/runtime/bin/lib/okstra-ctl/cmd-show.sh +0 -27
  530. package/runtime/bin/lib/okstra-ctl/cmd-tail.sh +0 -92
  531. package/runtime/bin/lib/okstra-ctl/main.sh +0 -41
  532. package/runtime/bin/lib/okstra-ctl/prepare.sh +0 -31
  533. package/runtime/bin/lib/okstra-ctl/usage.sh +0 -23
  534. package/runtime/bin/okstra-central.sh +0 -152
  535. package/runtime/bin/okstra-incremental-carry.py +0 -10
  536. package/runtime/bin/okstra-incremental-scope.py +0 -10
  537. package/runtime/bin/okstra-team-reconcile.sh +0 -36
  538. package/runtime/python/okstra_ctl/agent_prompt_cli.py +0 -1156
  539. package/runtime/python/okstra_ctl/batch.py +0 -60
  540. package/runtime/python/okstra_ctl/clarification_items.py +0 -1050
  541. package/runtime/python/okstra_ctl/container_registry.py +0 -72
  542. package/runtime/python/okstra_ctl/improvement_assignment.py +0 -61
  543. package/runtime/python/okstra_ctl/resolver.py +0 -54
  544. package/runtime/python/okstra_ctl/team_reconcile.py +0 -275
  545. package/runtime/python/okstra_ctl/tmux.py +0 -134
  546. package/runtime/python/okstra_ctl/worktree.py +0 -1099
@@ -1,6 +1,6 @@
1
1
  """Read-side state accessors over okstra's on-disk authority files.
2
2
 
3
- Skills, okstra.sh, and okstra-ctl all read the same files through this module
3
+ Skills and okstra.sh read the same files through this module
4
4
  so identity / discovery values are derived from disk on every call instead of
5
5
  being passed via process environment. This keeps concurrent claude-code skill
6
6
  invocations isolated — each call reads the authoritative state at the moment
@@ -34,6 +34,13 @@ from .dirs import (
34
34
  TASK_MANIFEST_FILENAME,
35
35
  TASKS_RELATIVE,
36
36
  )
37
+ # 포인터 승격은 순수 값 연산이라 하위 계층이 소유한다. 예전에는 함수 본문에서
38
+ # okstra_ctl.next_phase 를 지연 import 했다 — okstra_ctl 패키지 __init__ 이
39
+ # 이 모듈의 slugify 를 도로 끌어와 순환이 됐기 때문이다.
40
+ from .phase_pointer import promote as promote_phase_pointer
41
+ # slug 규칙은 leaf 가 소유한다 — okstra_ctl 이 이 모듈을 거치지 않고 규칙만
42
+ # 가져갈 수 있어야 패키지 __init__ 을 통한 순환이 생기지 않는다.
43
+ from .slug import slugify # noqa: F401 — 재노출: 기존 호출부가 state 에서 끌어온다
37
44
 
38
45
 
39
46
  class StateError(Exception):
@@ -53,31 +60,6 @@ def _load_json(path: Path) -> Optional[dict]:
53
60
  raise StateError(f"failed to parse {path}: {exc}") from exc
54
61
 
55
62
 
56
- def _next_phase():
57
- """`okstra_ctl.next_phase` 를 호출 시점에 가져온다.
58
-
59
- 모듈 최상단에서 import 하면 순환이 된다 — `okstra_ctl/__init__.py` 가
60
- `.ids` 를 거쳐 이 모듈의 `slugify` 를 도로 import 하기 때문에, 여기서
61
- okstra_ctl 을 먼저 끌어오면 아직 정의되지 않은 이름을 찾다가 ImportError 로
62
- 죽는다. 같은 파일의 `_reconcile_task_root_best_effort` 도 같은 이유로 지연
63
- import 를 쓴다.
64
- """
65
- from okstra_ctl import next_phase
66
-
67
- return next_phase
68
-
69
-
70
- def slugify(value: str) -> str:
71
- """task-group / task-id segment 를 디스크 경로용 slug 로 정규화한다.
72
-
73
- 소문자화 + 알파넘 외 문자 → '-' 로 collapse.
74
- okstra.sh 의 path-resolve.sh slug 규칙과 일치해야 한다.
75
- """
76
- value = (value or "").lower()
77
- value = re.sub(r"[^a-z0-9]+", "-", value).strip("-")
78
- return value
79
-
80
-
81
63
  def read_task_catalog(project_root: Path) -> list[dict]:
82
64
  """project-level task-catalog.json 을 list[dict] 로 돌려준다.
83
65
 
@@ -117,7 +99,7 @@ def read_task_manifest(task_root: Path) -> Optional[dict]:
117
99
  workflow = manifest.get("workflow")
118
100
  if not isinstance(workflow, dict):
119
101
  return manifest
120
- workflow["nextRecommendedPhase"] = _next_phase().promote(
102
+ workflow["nextRecommendedPhase"] = promote_phase_pointer(
121
103
  workflow.get("nextRecommendedPhase")
122
104
  )
123
105
  # routingStatus 는 포인터 status 로 흡수됐다 — 승격과 같은 자리에서 지운다.
@@ -143,11 +125,20 @@ def read_task_key(task_root: Path) -> str:
143
125
 
144
126
 
145
127
  def _reconcile_task_root_best_effort(project_root: Path, task_root: Path) -> None:
128
+ """카탈로그가 가리키는 task-root 를 정본 산출물로 치유한다(best-effort).
129
+
130
+ import 를 함수 본문에 두는 이유는 순환이 아니다 — 순환은 없다. 하위 계층인
131
+ okstra_project 가 상위 계층 okstra_ctl 을 import 시점에 끌어오지 않게 하려는
132
+ 것이다. 이 치유는 읽기측 해석의 부가 동작이므로, 실패해도 해석 자체는
133
+ 계속돼야 한다.
134
+ """
146
135
  try:
147
136
  from okstra_ctl.implementation_outcome import reconcile_implementation_outcome
148
137
 
149
138
  reconcile_implementation_outcome(project_root, task_root)
150
139
  except Exception:
140
+ # expected-miss: 치유는 부가 동작이다. 여기서 던지면 단순 조회가
141
+ # 실패한다. 무엇이 치유되지 않았는지는 다음 run 의 정합성 검사가 잡는다.
151
142
  return
152
143
 
153
144
 
@@ -195,7 +186,7 @@ def _entry_with_manifest_state(entry: dict, task_root: Path) -> dict:
195
186
  raw = workflow.get("nextRecommendedPhase")
196
187
  if raw is None:
197
188
  raw = entry.get("nextRecommendedPhase")
198
- out["nextRecommendedPhase"] = _next_phase().promote(raw)
189
+ out["nextRecommendedPhase"] = promote_phase_pointer(raw)
199
190
  out.update(derived_task_status(manifest))
200
191
  return out
201
192
 
@@ -350,7 +341,7 @@ def list_project_tasks(
350
341
  def resolve_task_identity(project_root: Path, task_key: str) -> dict:
351
342
  """task-key 한 줄로 manifest + 경로를 한 번에 반환.
352
343
 
353
- skill / okstra.sh / okstra-ctl 모두가 이 함수를 호출해 같은 dict 를 받는다.
344
+ skill 과 okstra.sh 모두가 이 함수를 호출해 같은 dict 를 받는다.
354
345
  StateError: task root 또는 manifest 없음.
355
346
  """
356
347
  task_root = find_task_root(project_root, task_key)
@@ -379,7 +370,7 @@ def resolve_task_identity(project_root: Path, task_key: str) -> dict:
379
370
  "taskType": manifest.get("taskType") or "",
380
371
  "currentPhase": workflow.get("currentPhase") or "",
381
372
  "currentPhaseState": workflow.get("currentPhaseState") or "",
382
- "nextRecommendedPhase": _next_phase().promote(
373
+ "nextRecommendedPhase": promote_phase_pointer(
383
374
  workflow.get("nextRecommendedPhase")
384
375
  ),
385
376
  "lastCompletedPhase": workflow.get("lastCompletedPhase") or "",
@@ -410,7 +401,7 @@ def task_read_side_snapshot(project_root: Path, task_key: str) -> dict:
410
401
  "currentPhase": workflow.get("currentPhase"),
411
402
  "currentPhaseState": workflow.get("currentPhaseState"),
412
403
  "lastCompletedPhase": workflow.get("lastCompletedPhase"),
413
- "nextRecommendedPhase": _next_phase().promote(
404
+ "nextRecommendedPhase": promote_phase_pointer(
414
405
  workflow.get("nextRecommendedPhase")
415
406
  ),
416
407
  "phaseStates": workflow.get("phaseStates"),
@@ -421,202 +412,3 @@ def task_read_side_snapshot(project_root: Path, task_key: str) -> dict:
421
412
  "modelAssignments": manifest.get("modelAssignments"),
422
413
  "latestRunPath": manifest.get("latestRunPath"),
423
414
  }
424
-
425
-
426
- def stage_map_read_side_snapshot(project_root: Path, task_key: str) -> dict:
427
- """stage-map inspect 용 read-side view: Stage Map + done 처리된 stage 번호.
428
-
429
- Stage Map 파싱과 planning run-root 위치를 caller 에게 노출하지 않는다 —
430
- Node inspect 가 okstra_ctl 의 private 심볼을 import 하거나 `runs/` 경로를
431
- 직접 조립하지 않도록 하는 어댑터다.
432
- """
433
- from okstra_ctl.consumers import read_stage_consumer_state
434
- from okstra_ctl.paths import RunRef
435
- from okstra_ctl.stage_map import (
436
- PlanningDetail,
437
- StageMapError,
438
- load_planning_detail,
439
- load_task_stage_map,
440
- merge_planning_detail,
441
- )
442
-
443
- identity = resolve_task_identity(project_root, task_key)
444
- task_root = Path(identity["taskRoot"])
445
- try:
446
- stage_snapshot = load_task_stage_map(task_root, identity["manifest"])
447
- detail = (
448
- load_planning_detail(Path(stage_snapshot.source_plan_path))
449
- if stage_snapshot.source_plan_path
450
- else PlanningDetail({}, {})
451
- )
452
- except StageMapError as exc:
453
- raise StateError(str(exc), stage=exc.code) from exc
454
- plan_run_root = RunRef.from_task_root(
455
- task_root, "implementation-planning"
456
- ).run_dir
457
- done: list[int] = []
458
- if plan_run_root.is_dir():
459
- done = sorted(
460
- read_stage_consumer_state(
461
- plan_run_root, recover_from_carry=True
462
- ).done_stages
463
- )
464
- return {
465
- "taskKey": identity["taskKey"],
466
- "taskRoot": identity["taskRoot"],
467
- "state": stage_snapshot.state,
468
- "sourcePlanPath": stage_snapshot.source_plan_path,
469
- "stages": merge_planning_detail(stage_snapshot.stages, detail),
470
- "doneStages": done,
471
- "planning": detail.task_narratives,
472
- }
473
-
474
-
475
- def code_review_target_snapshot(
476
- project_root: Path, task_key: str, stage: int
477
- ) -> dict:
478
- """stage 코드 리뷰가 무엇을 읽고 결과를 어디에 쓰는지 해소한다.
479
-
480
- stage_map_read_side_snapshot 과 같은 결: caller 는 registry 행도, run-root
481
- 레이아웃도, stage base 규칙도 보지 않는다. stage_targets 의
482
- StageTargetError 도 StateError 로 바꿔 던진다 — caller 가 그 예외를 잡으려고
483
- okstra_ctl 을 import 하지 않도록.
484
-
485
- base 는 stage worktree 를 만들 때 registry 행에 적힌 `base_ref` 다 — 그
486
- stage 가 실제로 갈라져 나온 커밋. 리뷰 시점에 규칙으로 다시 계산하면
487
- 표류한다: 다중의존 stage 는 오늘의 task-key worktree HEAD 를 받게 되어
488
- whole-task final-verification 이 stage 들을 병합한 뒤에는 base..head 구간이
489
- 비거나 뒤집히고, 단일의존 stage 는 선행 stage 가 재실행되면 어긋난다.
490
- """
491
- from okstra_ctl import code_review_paths, worktree_registry
492
- from okstra_ctl.stage_map import StageMapError, load_task_stage_map
493
-
494
- identity = resolve_task_identity(project_root, task_key)
495
- task_root = Path(identity["taskRoot"])
496
- try:
497
- stage_snapshot = load_task_stage_map(task_root, identity["manifest"])
498
- except StageMapError as exc:
499
- raise StateError(str(exc), stage=exc.code) from exc
500
- if stage_snapshot.state != "ready":
501
- raise StateError(
502
- "implementation-planning Stage Map is missing",
503
- stage="missing",
504
- )
505
- stages = stage_snapshot.stages
506
- selected = next((s for s in stages if s["stage_number"] == stage), None)
507
- if selected is None:
508
- raise StateError(
509
- f"stage {stage} is not in the Stage Map for {task_key}",
510
- stage="stage_missing",
511
- )
512
-
513
- coords = (identity["projectId"], identity["taskGroup"], identity["taskId"])
514
- stage_row = worktree_registry.get_stage_row(*coords, stage) or {}
515
- worktree_view = _stage_worktree_view(project_root, stage_row, stage)
516
- base_commit = stage_row.get("base_ref") or _legacy_stage_base_commit(
517
- identity, stages, selected
518
- )
519
- review_path, round_no = code_review_paths.next_stage_review(
520
- code_review_paths.stage_review_dir(
521
- project_root, identity["taskGroup"], identity["taskId"]
522
- ),
523
- stage,
524
- )
525
- return {
526
- "mode": "stage",
527
- "taskKey": identity["taskKey"],
528
- "taskRoot": identity["taskRoot"],
529
- "stage": stage,
530
- **worktree_view,
531
- "baseCommit": base_commit,
532
- "reviewPath": str(review_path),
533
- "round": round_no,
534
- }
535
-
536
-
537
- def _legacy_stage_base_commit(
538
- identity: dict, stages: list[dict], selected: dict
539
- ) -> str:
540
- """`base_ref` 를 남기지 않은 옛 registry 행의 base 를 규칙에서 되살린다.
541
-
542
- provision 이 base_ref 를 기록하기 전에 만들어진 stage 행에만 쓰인다. 규칙
543
- 자체는 stage_targets 가 소유하며 여기서 다시 유도하지 않는다.
544
- """
545
- from okstra_ctl import stage_targets, worktree_registry
546
- from okstra_ctl.paths import RunRef
547
-
548
- coords = (identity["projectId"], identity["taskGroup"], identity["taskId"])
549
- plan_run_root = RunRef.from_task_root(
550
- Path(identity["taskRoot"]), "implementation-planning"
551
- ).run_dir
552
- lifecycle = stage_targets.read_stage_lifecycle_snapshot(
553
- stages, plan_run_root, recover_from_carry=True
554
- )
555
- # The anchor and the multi-dep candidate base must come from the task-key
556
- # worktree HEAD, where stage work accumulates — not from the invocation
557
- # cwd, which may sit on an older or unrelated commit.
558
- task_entry = worktree_registry.lookup(*coords)
559
- task_worktree = Path(
560
- (task_entry.worktree_path if task_entry else "") or identity["projectRoot"]
561
- )
562
- anchor = worktree_registry.get_implementation_base(*coords) or ""
563
- try:
564
- return stage_targets.resolve_stage_base_commit(
565
- selected,
566
- lifecycle.done_rows,
567
- anchor_base_commit=anchor,
568
- candidate_base=_git_out(task_worktree, "rev-parse", "HEAD"),
569
- project_root=task_worktree,
570
- plan_run_root=plan_run_root,
571
- )
572
- except stage_targets.StageTargetError as exc:
573
- raise StateError(
574
- f"stage {selected['stage_number']} has no recorded base_ref and its "
575
- f"base could not be derived: {exc}",
576
- stage="stage_base_unresolved",
577
- ) from exc
578
-
579
-
580
- def _stage_worktree_view(project_root: Path, stage_row: dict, stage: int) -> dict:
581
- """한 stage 의 worktree 경로 / 브랜치 / head 커밋.
582
-
583
- 철거된 stage worktree 는 오류가 아니다: whole-task final-verification 이
584
- 디렉터리를 지워도 브랜치는 남고, 리뷰가 필요한 커밋은 그 브랜치에 그대로
585
- 있다.
586
- """
587
- branch = stage_row.get("branch") or ""
588
- if not branch:
589
- raise StateError(
590
- f"stage {stage} has no registry branch — review it in branch mode",
591
- stage="stage_branch_missing",
592
- )
593
- worktree_path = ""
594
- if stage_row.get("status") == "active" and stage_row.get("worktree_path"):
595
- candidate = Path(stage_row["worktree_path"])
596
- if candidate.is_dir():
597
- worktree_path = str(candidate)
598
- head_source = Path(worktree_path) if worktree_path else Path(project_root)
599
- head_ref = "HEAD" if worktree_path else branch
600
- head_commit = _git_out(head_source, "rev-parse", head_ref)
601
- if not head_commit:
602
- raise StateError(
603
- f"stage {stage} head could not be resolved: branch {branch!r} is "
604
- f"not readable from {head_source}",
605
- stage="stage_head_unresolved",
606
- )
607
- return {
608
- "worktreePath": worktree_path,
609
- "branch": branch,
610
- "headCommit": head_commit,
611
- }
612
-
613
-
614
- def _git_out(repo: Path, *args: str) -> str:
615
- """git 호출의 stdout. 실패는 빈 문자열 — 호출자가 부재를 판단한다."""
616
- result = subprocess.run(
617
- ["git", "-C", str(repo), *args],
618
- capture_output=True,
619
- text=True,
620
- check=False,
621
- )
622
- return result.stdout.strip() if result.returncode == 0 else ""
@@ -1,18 +1,64 @@
1
1
  """Antigravity (`agy`) CLI usage collector.
2
2
 
3
3
  공식 headless 문서는 ``--output-format json`` / ``stream-json`` 의 최종
4
- ``usage`` 객체에 토큰을 둔다. okstra 는 이미 ``stream-json`` 으로 호출하고
5
- 그 줄을 워커 로그에 남긴다. 정본은 마지막 ``result.usage`` 이다.
4
+ ``usage`` 객체에 토큰을 둔다. okstra 는 ``stream-json`` 으로 호출하고, 러너가
5
+ 스트림의 마지막 ``usage`` 스냅샷을 래퍼 status 사이드카의 ``usage`` 에 적는다
6
+ (`worker_runner`) — 그것이 정본이다. 워커 로그는 러너가 사람이 읽는 줄로 옮겨
7
+ 적은 것이라 stream-json 이 아니다. raw stream-json 로그를 읽는 경로는 러너
8
+ 이전의 로그를 위해 남긴다.
6
9
  """
7
10
  from __future__ import annotations
8
11
 
12
+ import json
9
13
  from pathlib import Path
14
+ from typing import Any, Mapping
10
15
 
11
16
  from .jsonl_io import iter_jsonl
12
17
 
13
18
 
19
+ def _usage_total(usage: Mapping[str, Any], model: str | None) -> dict:
20
+ return {
21
+ "totalTokens": usage.get("total_tokens", 0) or 0,
22
+ "inputTokens": usage.get("input_tokens", 0) or 0,
23
+ "outputTokens": usage.get("output_tokens", 0) or 0,
24
+ "thoughtsTokens": usage.get("thinking_tokens", 0) or 0,
25
+ "cacheReadTokens": usage.get("cache_read_tokens", 0) or 0,
26
+ "model": model,
27
+ "available": True,
28
+ }
29
+
30
+
31
+ def _read_status(status_path: Path) -> dict | None:
32
+ try:
33
+ data = json.loads(status_path.read_text(encoding="utf-8"))
34
+ except (OSError, ValueError):
35
+ return None
36
+ return data if isinstance(data, dict) else None
37
+
38
+
39
+ def status_carries_usage(path: Path) -> bool:
40
+ """이 경로가 ``usage`` 스냅샷을 실은 래퍼 status 사이드카인가."""
41
+ if not path.name.endswith(".status.json"):
42
+ return False
43
+ status = _read_status(path)
44
+ return isinstance((status or {}).get("usage"), dict) and bool(status["usage"])
45
+
46
+
47
+ def antigravity_status_total(status_path: Path) -> dict:
48
+ """래퍼 status 사이드카의 ``usage`` 스냅샷. 모델은 served-model 관측값이다."""
49
+ status = _read_status(status_path) or {}
50
+ usage = status.get("usage")
51
+ if not isinstance(usage, dict) or not usage:
52
+ return {"totalTokens": 0, "available": False}
53
+ attestation = status.get("servedModelAttestation")
54
+ model = (
55
+ attestation.get("observedModel") if isinstance(attestation, dict) else None
56
+ )
57
+ return _usage_total(usage, model if isinstance(model, str) and model else None)
58
+
59
+
14
60
  def antigravity_session_total(json_path: Path) -> dict:
15
- """stream-json 로그에서 마지막 result.usage 를 읽는다."""
61
+ """raw stream-json 로그에서 마지막 result.usage 를 읽는다."""
16
62
  result_usage: dict | None = None
17
63
  step_usage: dict | None = None
18
64
  model: str | None = None
@@ -35,15 +81,7 @@ def antigravity_session_total(json_path: Path) -> dict:
35
81
  usage = result_usage or step_usage
36
82
  if usage is None:
37
83
  return {"totalTokens": 0, "available": False}
38
- return {
39
- "totalTokens": usage.get("total_tokens", 0) or 0,
40
- "inputTokens": usage.get("input_tokens", 0) or 0,
41
- "outputTokens": usage.get("output_tokens", 0) or 0,
42
- "thoughtsTokens": usage.get("thinking_tokens", 0) or 0,
43
- "cacheReadTokens": usage.get("cache_read_tokens", 0) or 0,
44
- "model": model,
45
- "available": True,
46
- }
84
+ return _usage_total(usage, model)
47
85
 
48
86
 
49
87
  def find_antigravity_session(project_root: Path, started_at: str, ended_at: str) -> Path | None:
@@ -2,6 +2,7 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  import json
5
+ import sys
5
6
  import re
6
7
  from datetime import datetime
7
8
  from pathlib import Path
@@ -158,8 +159,15 @@ def _advance_usage_scan(jsonl_path: Path, usage_state: dict) -> dict:
158
159
  if ev:
159
160
  tail_events.append(ev)
160
161
  break
161
- except OSError:
162
+ except FileNotFoundError:
163
+ # expected-miss: 세션 jsonl 은 열거된 뒤 사라질 수 있고(정리·회전), 아직
164
+ # 한 줄도 안 쓴 세션은 파일 자체가 없다. 읽을 것이 없는 것이 정상이다.
162
165
  pass
166
+ except OSError as exc:
167
+ # 파일은 있는데 못 읽은 것은 다르다. 읽다 만 상태로 반환하면 토큰 집계가
168
+ # 실제보다 적게 나오는데 리포트에는 정상 수치처럼 찍힌다.
169
+ print(f"token-usage: partial read of {jsonl_path} ({exc})",
170
+ file=sys.stderr)
163
171
  usage_state.update(offset=offset, events=events,
164
172
  agentName=agent_name, model=model)
165
173
  return {"events": events + tail_events,
@@ -14,7 +14,9 @@ from .report import (
14
14
 
15
15
 
16
16
  def main() -> int:
17
- parser = argparse.ArgumentParser(description=__doc__)
17
+ parser = argparse.ArgumentParser(
18
+ prog="okstra token-usage",
19
+ description=__doc__)
18
20
  parser.add_argument(
19
21
  "team_state",
20
22
  type=Path,