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
@@ -0,0 +1,215 @@
1
+ """argparse 표면과 명령 분배.
2
+
3
+ 여기 있는 것은 인자 정의와 `main` 의 분기뿐이다. 각 명령의 실제 동작은
4
+ `materialize` 와 `results` 에 있다. `_CLI_EPILOG` 는 이 명령의 사용법 정본이다 —
5
+ TypeScript 포워더가 들고 있던 USAGE 문자열이 여기로 왔다.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import argparse
10
+ from pathlib import Path
11
+ import sys
12
+
13
+ from ..invocation import AgentInvocationError
14
+ from ...worker_prompt_headers import WorkerPromptHeaderError
15
+ from ...dispatch_state import BACKEND_CLI_WRAPPER, BACKEND_CMUX_PANE, DispatchError
16
+ from .emit import _emit, _prepared_payload
17
+ from .inputs import AgentPromptCliError
18
+ from .materialize import _materialize
19
+ from .results import (
20
+ _complete,
21
+ _link_result,
22
+ _materialize_result,
23
+ _record_dispatch,
24
+ _abandon_attempt,
25
+ _reject_result,
26
+ _verify,
27
+ _verify_completion,
28
+ )
29
+
30
+
31
+ _CLI_EPILOG = r"""Usage:
32
+ okstra agent-prompt materialize [options]
33
+ okstra agent-prompt verify [options]
34
+ okstra agent-prompt materialize-result [options]
35
+ okstra agent-prompt complete [options]
36
+ okstra agent-prompt verify-completion [options]
37
+ okstra agent-prompt record-dispatch [options]
38
+ okstra agent-prompt link-result [options]
39
+ """
40
+
41
+
42
+ _CLI_DESCRIPTION = "Materialize and verify auditable agent invocations."
43
+
44
+
45
+ def _parser() -> argparse.ArgumentParser:
46
+ parser = argparse.ArgumentParser(
47
+ description=_CLI_DESCRIPTION,
48
+ epilog=_CLI_EPILOG,
49
+ formatter_class=argparse.RawDescriptionHelpFormatter,
50
+ prog="okstra agent-prompt")
51
+ commands = parser.add_subparsers(dest="command", required=True)
52
+ _add_materialize_parser(commands)
53
+ _add_completion_parsers(commands)
54
+ _add_dispatch_parsers(commands)
55
+ return parser
56
+
57
+
58
+ def _add_materialize_parser(commands: argparse._SubParsersAction) -> None:
59
+ materialize = commands.add_parser("materialize")
60
+ _common_paths(materialize)
61
+ materialize.add_argument("--invocation-id", required=True)
62
+ materialize.add_argument("--audience", required=True)
63
+ materialize.add_argument("--instruction", required=True)
64
+ materialize.add_argument("--prompt", required=True)
65
+ materialize.add_argument("--run-manifest")
66
+ materialize.add_argument("--worker-id")
67
+ materialize.add_argument("--dispatch-kind")
68
+ materialize.add_argument("--assignment-ref")
69
+ materialize.add_argument("--source-role-execution-ref")
70
+ materialize.add_argument("--result")
71
+ materialize.add_argument("--audit-source")
72
+ materialize.add_argument("--host-runtime")
73
+ materialize.add_argument(
74
+ "--terminal-backend",
75
+ choices=(BACKEND_CLI_WRAPPER, BACKEND_CMUX_PANE),
76
+ )
77
+ materialize.add_argument("--provider")
78
+ materialize.add_argument("--model-role")
79
+ materialize.add_argument("--model", default="")
80
+ materialize.add_argument("--purpose")
81
+ materialize.add_argument(
82
+ "--replace-undispatched",
83
+ action="store_true",
84
+ help="rewrite a prompt this invocation id already wrote, allowed only "
85
+ "while no dispatch has referenced it — the exit for a prompt that "
86
+ "failed a pre-dispatch gate and never ran. Not available for v2 "
87
+ "reverify prompts (--assignment-ref reverify/…): their reservation "
88
+ "records the prompt's input digest in the run manifest and "
89
+ "reservations are append-only, so a rewrite needs a fresh "
90
+ "invocation id and prompt path",
91
+ )
92
+ materialize.add_argument("--json", action="store_true")
93
+
94
+ verify = commands.add_parser("verify")
95
+ _common_paths(verify)
96
+ verify.add_argument("--run-manifest")
97
+ verify.add_argument("--metadata", required=True)
98
+ verify.add_argument("--json", action="store_true")
99
+ verify.add_argument("--text", action="store_true")
100
+
101
+
102
+ def _add_completion_parsers(commands: argparse._SubParsersAction) -> None:
103
+ materialize_result = commands.add_parser("materialize-result")
104
+ _standalone_completion_args(materialize_result)
105
+ materialize_result.add_argument("--returned-body-file", required=True)
106
+
107
+ complete = commands.add_parser("complete")
108
+ _standalone_completion_args(complete)
109
+
110
+ verify_completion = commands.add_parser("verify-completion")
111
+ _common_paths(verify_completion)
112
+ verify_completion.add_argument("--purpose", required=True)
113
+ verify_completion.add_argument("--completion", required=True)
114
+ verify_completion.add_argument("--json", action="store_true")
115
+
116
+
117
+ def _add_dispatch_parsers(commands: argparse._SubParsersAction) -> None:
118
+ record_dispatch = commands.add_parser("record-dispatch")
119
+ _common_paths(record_dispatch)
120
+ record_dispatch.add_argument("--run-manifest", required=True)
121
+ record_dispatch.add_argument("--metadata", required=True)
122
+ record_dispatch.add_argument(
123
+ "--enforcement-mode",
124
+ required=True,
125
+ choices=("core-pre-dispatch", "host-native-spec-link-gate"),
126
+ )
127
+ record_dispatch.add_argument("--json", action="store_true")
128
+
129
+ reject_result = commands.add_parser(
130
+ "reject-result",
131
+ help="mark a linked result rejected so a corrective re-dispatch can "
132
+ "claim its path",
133
+ )
134
+ _common_paths(reject_result)
135
+ reject_result.add_argument("--run-manifest", required=True)
136
+ reject_result.add_argument("--dispatch-id", required=True)
137
+ reject_result.add_argument("--superseded-by", required=True)
138
+ reject_result.add_argument("--reason", required=True)
139
+ reject_result.add_argument("--json", action="store_true")
140
+
141
+ abandon = commands.add_parser(
142
+ "abandon-attempt",
143
+ help="close a started source-readonly attempt whose worker died "
144
+ "without a result, so a retry can follow it",
145
+ )
146
+ _common_paths(abandon)
147
+ abandon.add_argument("--run-manifest", required=True)
148
+ abandon.add_argument("--invocation-ref", required=True)
149
+ abandon.add_argument("--reason", required=True)
150
+ abandon.add_argument("--json", action="store_true")
151
+
152
+ link_result = commands.add_parser("link-result")
153
+ _common_paths(link_result)
154
+ link_result.add_argument("--run-manifest", required=True)
155
+ link_result.add_argument("--dispatch-id", required=True)
156
+ link_result.add_argument("--result", required=True)
157
+ link_result.add_argument("--json", action="store_true")
158
+
159
+
160
+ def _common_paths(parser: argparse.ArgumentParser) -> None:
161
+ parser.add_argument("--project-root", required=True)
162
+
163
+
164
+ def _standalone_completion_args(parser: argparse.ArgumentParser) -> None:
165
+ _common_paths(parser)
166
+ parser.add_argument("--purpose", required=True)
167
+ parser.add_argument("--metadata", required=True)
168
+ parser.add_argument("--json", action="store_true")
169
+
170
+
171
+ def main(argv: list[str] | None = None) -> int:
172
+ try:
173
+ args = _parser().parse_args(argv)
174
+ if args.command == "materialize":
175
+ prepared = _materialize(args)
176
+ _emit(_prepared_payload(prepared, args.audience), args.json)
177
+ return 0
178
+ if args.command == "verify":
179
+ _verify(args)
180
+ _emit(
181
+ {"ok": True, "metadataPath": str(Path(args.metadata).resolve())},
182
+ args.json,
183
+ args.text,
184
+ )
185
+ return 0
186
+ if args.command == "materialize-result":
187
+ _materialize_result(args)
188
+ return 0
189
+ if args.command == "complete":
190
+ _complete(args)
191
+ return 0
192
+ if args.command == "verify-completion":
193
+ _verify_completion(args)
194
+ return 0
195
+ if args.command == "record-dispatch":
196
+ _record_dispatch(args)
197
+ return 0
198
+ if args.command == "reject-result":
199
+ _reject_result(args)
200
+ return 0
201
+ if args.command == "abandon-attempt":
202
+ _abandon_attempt(args)
203
+ return 0
204
+ _link_result(args)
205
+ return 0
206
+ except (
207
+ AgentPromptCliError,
208
+ AgentInvocationError,
209
+ DispatchError,
210
+ WorkerPromptHeaderError,
211
+ OSError,
212
+ ValueError,
213
+ ) as exc:
214
+ print(f"error: {exc}", file=sys.stderr)
215
+ return 2
@@ -0,0 +1,155 @@
1
+ """동적 검증자 요청을 예약하고, 그 출처가 자격이 있는지 본다.
2
+
3
+ 재검증 라운드에서 리드가 추가 검증자를 요청할 수 있고, 그 요청은 예약(슬롯
4
+ 확보)과 자격 검사(요청한 role 이 이 run 에서 그럴 수 있는가)를 함께 통과해야
5
+ 한다. 두 가지가 한 파일에 있는 이유는 예약이 자격 검사를 통과한 뒤에만
6
+ 일어나야 하기 때문이다 — 순서가 곧 계약이다.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import argparse
11
+ from dataclasses import replace
12
+ import hashlib
13
+ from pathlib import Path
14
+ from typing import Any, Mapping
15
+
16
+ from ..invocation import (
17
+ AgentInvocationRequest,
18
+ AgentModelAssignment,
19
+ compose_agent_prompt,
20
+ compose_unbound_run_prompt,
21
+ v2_role_assignment_authority_errors,
22
+ )
23
+ from ...convergence_store import (
24
+ DYNAMIC_VERIFIER_SOURCE_ROLES,
25
+ reserve_dynamic_verifier,
26
+ )
27
+ from .inputs import AgentPromptCliError
28
+
29
+
30
+ def _reserve_dynamic_verifier_request(
31
+ request: AgentInvocationRequest,
32
+ *,
33
+ args: argparse.Namespace,
34
+ manifest: Mapping[str, Any],
35
+ manifest_path: Path,
36
+ source_role_execution_ref: str,
37
+ ) -> AgentInvocationRequest:
38
+ _validate_dynamic_source_assignment(
39
+ manifest,
40
+ source_role_execution_ref,
41
+ request.assignment,
42
+ )
43
+ prompt_bytes = compose_unbound_run_prompt(request)
44
+ verifier, invocation = reserve_dynamic_verifier(
45
+ manifest_path,
46
+ source_role_execution_ref=source_role_execution_ref,
47
+ duty_id=args.audience,
48
+ round_number=_reverify_round(args.dispatch_kind),
49
+ task_key=_required_manifest_string(manifest, "taskKey"),
50
+ input_digest="sha256:" + hashlib.sha256(prompt_bytes).hexdigest(),
51
+ invocation_ref=args.invocation_id,
52
+ )
53
+ bound = replace(
54
+ request,
55
+ worker_id=None,
56
+ participant_ref=verifier.participant_ref,
57
+ role_execution_ref=verifier.role_execution_ref,
58
+ duty_id=args.audience,
59
+ invocation_ref=invocation.invocation_ref,
60
+ )
61
+ if compose_agent_prompt(bound).encode("utf-8") != prompt_bytes:
62
+ raise AgentPromptCliError(
63
+ "dynamic verifier identity changed immutable prompt bytes"
64
+ )
65
+ return bound
66
+
67
+
68
+ def _dynamic_verifier_source(
69
+ args: argparse.Namespace,
70
+ manifest: Mapping[str, Any],
71
+ ) -> str | None:
72
+ is_v2 = (
73
+ manifest.get("schemaVersion") == "2.0"
74
+ and manifest.get("executionIdentityVersion") == 2
75
+ )
76
+ is_reverify = (
77
+ args.assignment_ref.startswith("reverify/")
78
+ and args.audience == "reverification-worker"
79
+ )
80
+ source = args.source_role_execution_ref
81
+ if is_v2 and is_reverify:
82
+ if args.replace_undispatched:
83
+ raise AgentPromptCliError(
84
+ "v2 dynamic verifier prompts are append-only: this "
85
+ "invocation's reservation already recorded this prompt's input "
86
+ "digest in the run manifest, and a reservation cannot be "
87
+ "rewritten. Use a fresh invocation ID and prompt path."
88
+ )
89
+ if not source:
90
+ raise AgentPromptCliError(
91
+ "v2 reverify materialization requires "
92
+ "--source-role-execution-ref"
93
+ )
94
+ return source
95
+ if source:
96
+ raise AgentPromptCliError(
97
+ "--source-role-execution-ref is allowed only for v2 reverify"
98
+ )
99
+ return None
100
+
101
+
102
+ def _reverify_round(dispatch_kind: str) -> int:
103
+ prefix = "reverify-r"
104
+ value = dispatch_kind.removeprefix(prefix)
105
+ if not dispatch_kind.startswith(prefix) or not value.isdigit() or int(value) < 1:
106
+ raise AgentPromptCliError(
107
+ "dynamic verifier dispatch kind must be reverify-r<N>"
108
+ )
109
+ return int(value)
110
+
111
+
112
+ def _validate_dynamic_source_assignment(
113
+ manifest: Mapping[str, Any],
114
+ source_role_execution_ref: str,
115
+ assignment: AgentModelAssignment,
116
+ ) -> None:
117
+ rows = manifest.get("roleExecutions")
118
+ source = next(
119
+ (
120
+ row
121
+ for row in rows
122
+ if isinstance(row, Mapping)
123
+ and row.get("roleExecutionRef") == source_role_execution_ref
124
+ ),
125
+ None,
126
+ ) if isinstance(rows, list) else None
127
+ if source is None:
128
+ raise AgentPromptCliError(
129
+ f"source role execution is unknown: {source_role_execution_ref}"
130
+ )
131
+ if source.get("role") not in DYNAMIC_VERIFIER_SOURCE_ROLES:
132
+ raise AgentPromptCliError(
133
+ "dynamic verifier source role is not eligible for re-verification"
134
+ )
135
+ errors = v2_role_assignment_authority_errors(
136
+ manifest,
137
+ role_execution_ref=source_role_execution_ref,
138
+ participant_ref=str(source.get("participantRef") or ""),
139
+ assignment=assignment,
140
+ )
141
+ if errors:
142
+ raise AgentPromptCliError(
143
+ "dynamic verifier source does not match the selected assignment: "
144
+ + "; ".join(errors)
145
+ )
146
+
147
+
148
+ def _required_manifest_string(
149
+ manifest: Mapping[str, Any],
150
+ key: str,
151
+ ) -> str:
152
+ value = manifest.get(key)
153
+ if not isinstance(value, str) or not value.strip():
154
+ raise AgentPromptCliError(f"run manifest has no {key}")
155
+ return value
@@ -0,0 +1,66 @@
1
+ """명령의 결과를 표준 출력으로 내보낸다.
2
+
3
+ `--json` 이면 JSON, 아니면 고정 Markdown 줄이다. 두 형태를 한자리에 둬서
4
+ 명령마다 출력 모양이 갈라지지 않게 한다. 파일을 읽지도 쓰지도 않는다.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import json
9
+ from typing import Mapping
10
+
11
+ from ..invocation import PreparedAgentInvocation
12
+ from ...fixed_text import line
13
+
14
+
15
+
16
+ def _prepared_payload(
17
+ prepared: PreparedAgentInvocation,
18
+ audience: str,
19
+ ) -> dict[str, object]:
20
+ assignment = prepared.assignment
21
+ return {
22
+ "ok": True,
23
+ "invocationId": prepared.invocation_id,
24
+ "workerId": prepared.worker_id,
25
+ "assignmentRef": prepared.assignment_ref,
26
+ "audience": audience,
27
+ "promptPath": str(prepared.prompt_path),
28
+ "metadataPath": str(prepared.metadata_path),
29
+ "modelAssignment": {
30
+ "provider": assignment.provider,
31
+ "model": assignment.model,
32
+ "modelExecutionValue": assignment.model_execution_value,
33
+ "runner": assignment.runner,
34
+ "hostRuntime": assignment.host_runtime,
35
+ "hostModelValue": assignment.host_model_value,
36
+ },
37
+ "digests": {
38
+ "catalogDigest": prepared.catalog_digest,
39
+ "assignmentDigest": prepared.assignment_digest,
40
+ "dutyDigest": prepared.duty_digest,
41
+ "instructionDigest": prepared.instruction_digest,
42
+ "promptDigest": prepared.prompt_digest,
43
+ },
44
+ }
45
+
46
+
47
+ def _emit(
48
+ payload: Mapping[str, object], as_json: bool, as_text: bool = False
49
+ ) -> None:
50
+ if as_json:
51
+ print(json.dumps(payload, ensure_ascii=False, indent=2))
52
+ elif as_text:
53
+ print(render_agent_prompt_text(payload), end="")
54
+ else:
55
+ print(payload.get("promptPath") or payload.get("metadataPath") or "ok")
56
+
57
+
58
+ def render_agent_prompt_text(payload: Mapping[str, object]) -> str:
59
+ """agent prompt 검증 결과의 승인된 경로만 투영한다."""
60
+ rows = ["Okstra agent prompt\n"]
61
+ rows.append(line("Status", "ready" if payload.get("ok", True) else "error"))
62
+ for label, key in (("Prompt path", "promptPath"), ("Metadata path", "metadataPath"),
63
+ ("Assignment ID", "assignmentId"), ("Worker role", "workerRole")):
64
+ if key in payload:
65
+ rows.append(line(label, payload.get(key)))
66
+ return "".join(rows)
@@ -0,0 +1,138 @@
1
+ """명령이 받은 경로를 해석하고, 허용된 것만 돌려준다.
2
+
3
+ 이 CLI 는 모델이 부르는 표면이라 경로 인자를 그대로 믿을 수 없다. 여기 있는
4
+ 함수들은 전부 같은 모양이다 — 받은 문자열을 절대 경로로 만들고, 프로젝트
5
+ 루트(또는 명시된 상위) 안에 있는지 확인하고, 벗어나면 거절한다. 어느 것도
6
+ okstra 의 phase 나 role 을 모른다.
7
+
8
+ `AgentPromptCliError` 도 여기 있다. 모든 층이 이 하나로 실패를 알린다.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ from pathlib import Path
13
+ from pathlib import PurePosixPath
14
+ from typing import Any, Mapping
15
+
16
+ from ...json_boundary import JsonBoundaryError, load_owned_object
17
+
18
+
19
+
20
+ class AgentPromptCliError(RuntimeError):
21
+ """Raised when CLI input cannot become a valid invocation request."""
22
+
23
+
24
+ def _authorized_path(
25
+ project_root: Path,
26
+ raw_path: str,
27
+ raw_roots: object,
28
+ label: str,
29
+ *,
30
+ must_exist: bool,
31
+ ) -> Path:
32
+ if not isinstance(raw_roots, list) or not raw_roots:
33
+ raise AgentPromptCliError(f"run manifest has no authorized {label} roots")
34
+ path = _candidate(project_root, raw_path, must_exist=must_exist, label=label)
35
+ roots = [
36
+ _project_manifest_path(project_root, value, f"{label} root", must_exist=True)
37
+ for value in raw_roots
38
+ ]
39
+ if not any(_is_relative_to(path, root) for root in roots):
40
+ raise AgentPromptCliError(f"{label} path is outside authorized roots: {path}")
41
+ return path
42
+
43
+
44
+ def _candidate(project_root: Path, raw: str, *, must_exist: bool, label: str) -> Path:
45
+ candidate = Path(raw)
46
+ if not candidate.is_absolute():
47
+ candidate = project_root / candidate
48
+ try:
49
+ if must_exist or candidate.exists() or candidate.is_symlink():
50
+ return candidate.resolve(strict=True)
51
+ return candidate.parent.resolve(strict=True) / candidate.name
52
+ except OSError as exc:
53
+ raise AgentPromptCliError(f"{label} path is invalid: {candidate}") from exc
54
+
55
+
56
+ def _project_input(project_root: Path, raw: str, label: str) -> Path:
57
+ path = _candidate(project_root, raw, must_exist=True, label=label)
58
+ if not _is_relative_to(path, project_root):
59
+ raise AgentPromptCliError(f"{label} path escapes project root: {path}")
60
+ return path
61
+
62
+
63
+ def _project_manifest_path(
64
+ project_root: Path,
65
+ value: object,
66
+ label: str,
67
+ *,
68
+ must_exist: bool,
69
+ ) -> Path:
70
+ if not isinstance(value, str) or not value:
71
+ raise AgentPromptCliError(f"{label} path is invalid")
72
+ pure = PurePosixPath(value)
73
+ if pure.is_absolute() or any(part in {"", ".", ".."} for part in pure.parts):
74
+ raise AgentPromptCliError(f"{label} path is invalid")
75
+ path = _candidate(project_root, value, must_exist=must_exist, label=label)
76
+ if not _is_relative_to(path, project_root):
77
+ raise AgentPromptCliError(f"{label} path escapes project root: {path}")
78
+ return path
79
+
80
+
81
+ def _exact_path(raw: str, expected: Path, must_exist: bool, label: str) -> Path:
82
+ actual = (
83
+ Path(raw).resolve(strict=True)
84
+ if must_exist
85
+ else Path(raw).parent.resolve(strict=True) / Path(raw).name
86
+ )
87
+ expected_actual = (
88
+ expected.resolve(strict=True)
89
+ if must_exist
90
+ else expected.parent.resolve(strict=True) / expected.name
91
+ )
92
+ if actual != expected_actual:
93
+ raise AgentPromptCliError(f"{label} does not use canonical standalone path")
94
+ return actual
95
+
96
+
97
+ def _project_root(value: str) -> Path:
98
+ try:
99
+ return Path(value).resolve(strict=True)
100
+ except OSError as exc:
101
+ raise AgentPromptCliError(f"project root not found: {value}") from exc
102
+
103
+
104
+ def _relative(project_root: Path, path: Path) -> str:
105
+ try:
106
+ return path.relative_to(project_root).as_posix()
107
+ except ValueError as exc:
108
+ raise AgentPromptCliError(f"path escapes project root: {path}") from exc
109
+
110
+
111
+ def _read_json_object(path: Path, label: str) -> dict[str, Any]:
112
+ try:
113
+ value = load_owned_object(path, artifact="agent prompt metadata")
114
+ except JsonBoundaryError as exc:
115
+ raise AgentPromptCliError(f"{label} is invalid: {path}") from exc
116
+ if not isinstance(value, dict):
117
+ raise AgentPromptCliError(f"{label} must be a JSON object: {path}")
118
+ return value
119
+
120
+
121
+ def _mapping(value: object, label: str) -> Mapping[str, Any]:
122
+ if not isinstance(value, Mapping):
123
+ raise AgentPromptCliError(f"{label} is missing or invalid")
124
+ return value
125
+
126
+
127
+ def _is_relative_to(path: Path, root: Path) -> bool:
128
+ try:
129
+ path.relative_to(root)
130
+ except ValueError:
131
+ return False
132
+ return True
133
+
134
+
135
+ def _is_slug(value: str) -> bool:
136
+ if not value or value.startswith("-") or value.endswith("-"):
137
+ return False
138
+ return all(part.isalnum() and part.lower() == part for part in value.split("-"))