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
@@ -1,5 +1,10 @@
1
1
  # shellcheck shell=bash
2
2
 
3
+ # 이 lib 은 단독으로 source 될 수 있다(계약 테스트가 그렇게 부른다). checks
4
+ # 경로 계산은 common.sh 한 곳에만 두고, 없으면 여기서 채운다.
5
+ # shellcheck source=common.sh
6
+ [ -n "${OKSTRA_VALIDATOR_CHECKS:-}" ] || . "$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common.sh"
7
+
3
8
  run_okstra() {
4
9
  local task_group="$1"
5
10
  local task_id="$2"
@@ -41,108 +46,5 @@ run_validator_expectation() {
41
46
 
42
47
  expected_task_manifest_relative_path="$(task_manifest_relative_path "$task_group" "$task_id")"
43
48
 
44
- python3 - "$PROJECT_ROOT" "$expected_task_manifest_relative_path" "$RUN_VALIDATOR_PATH" "$expected_status" "$expected_failure_substring" <<'PY'
45
- from pathlib import Path
46
- import json
47
- import subprocess
48
- import sys
49
-
50
- project_root = Path(sys.argv[1])
51
- task_manifest_path = project_root / sys.argv[2]
52
- validator_script = Path(sys.argv[3])
53
- expected_status = sys.argv[4]
54
- expected_failure_substring = sys.argv[5]
55
-
56
- task_manifest = json.loads(task_manifest_path.read_text())
57
- timeline_path = project_root / task_manifest["historyTimelinePath"]
58
- timeline = json.loads(timeline_path.read_text())
59
- runs = timeline.get("runs", [])
60
- latest_run = None
61
- if isinstance(runs, list):
62
- for item in reversed(runs):
63
- if isinstance(item, dict):
64
- latest_run = item
65
- break
66
-
67
- if latest_run is None:
68
- raise SystemExit("timeline does not contain a latest run entry")
69
-
70
- run_manifest_path = project_root / latest_run["runManifestPath"]
71
- run_manifest = json.loads(run_manifest_path.read_text())
72
- team_state_path = project_root / run_manifest["teamStatePath"]
73
- report_path = project_root / run_manifest["expectedReportRecordPath"]
74
- final_status_path = project_root / run_manifest["expectedStatusPath"]
75
-
76
- process = subprocess.run(
77
- [
78
- sys.executable,
79
- str(validator_script),
80
- "--team-state",
81
- str(team_state_path),
82
- "--report",
83
- str(report_path),
84
- "--run-manifest",
85
- str(run_manifest_path),
86
- "--task-manifest",
87
- str(task_manifest_path),
88
- "--final-status",
89
- str(final_status_path),
90
- # session-conformance 주입 시드 — prepare_run_validator_fixture 가
91
- # 만든 합성 lead jsonl 디렉터리 (실제 ~/.claude/projects 미오염).
92
- "--claude-projects-dir",
93
- str(project_root / ".claude-projects-fixture"),
94
- ],
95
- capture_output=True,
96
- text=True,
97
- )
98
-
99
- if not process.stdout.strip():
100
- raise SystemExit("validator did not produce JSON output")
101
-
102
- payload = json.loads(process.stdout)
103
- actual_status = payload.get("validationStatus")
104
- if actual_status != expected_status:
105
- extra = ""
106
- if expected_status == "passed":
107
- listed = payload.get("failures") or []
108
- extra = "\n" + "\n".join(str(item) for item in listed)
109
- raise SystemExit(
110
- f"validator status mismatch: expected {expected_status}, got {actual_status}{extra}"
111
- )
112
-
113
- if expected_status == "passed" and process.returncode != 0:
114
- raise SystemExit(f"validator returned non-zero on success: {process.stderr}")
115
- if expected_status == "failed" and process.returncode == 0:
116
- raise SystemExit("validator unexpectedly succeeded")
117
-
118
- if expected_failure_substring:
119
- failures = payload.get("failures", [])
120
- if not isinstance(failures, list) or not any(
121
- expected_failure_substring in str(item) for item in failures
122
- ):
123
- raise SystemExit(
124
- f"validator failure output did not include expected text: {expected_failure_substring}"
125
- )
126
-
127
- if not final_status_path.is_file():
128
- raise SystemExit(f"validator did not write final status file: {final_status_path}")
129
-
130
- final_status = final_status_path.read_text().strip()
131
- expected_final_status = "completed" if expected_status == "passed" else "contract-violated"
132
- if final_status != expected_final_status:
133
- raise SystemExit(
134
- f"final status file mismatch: expected {expected_final_status}, got {final_status}"
135
- )
136
-
137
- updated_run_manifest = json.loads(run_manifest_path.read_text())
138
- updated_task_manifest = json.loads(task_manifest_path.read_text())
139
- updated_team_state = json.loads(team_state_path.read_text())
140
-
141
- if updated_run_manifest.get("validation", {}).get("status") != expected_status:
142
- raise SystemExit("run manifest validation status was not updated correctly")
143
- if updated_task_manifest.get("contractValidation", {}).get("status") != expected_status:
144
- raise SystemExit("task manifest validation status was not updated correctly")
145
- if updated_team_state.get("validator", {}).get("status") != expected_status:
146
- raise SystemExit("team-state validator status was not updated correctly")
147
- PY
49
+ python3 "$OKSTRA_VALIDATOR_CHECKS/runners-01.py" "$PROJECT_ROOT" "$expected_task_manifest_relative_path" "$RUN_VALIDATOR_PATH" "$expected_status" "$expected_failure_substring"
148
50
  }
@@ -10,6 +10,6 @@ Validation completed successfully.
10
10
  - Primary task root: $(task_root "$PRIMARY_TASK_GROUP" "$PRIMARY_TASK_ID")
11
11
  - Secondary task root: $(task_root "$SECONDARY_TASK_GROUP" "$SECONDARY_TASK_ID")
12
12
 
13
- You can inspect the generated artifacts directly under the validation root.
13
+ The default validation root is removed on success; set OKSTRA_VALIDATION_PROJECT_ROOT to keep the artifacts for inspection.
14
14
  EOF
15
15
  }
@@ -1,5 +1,10 @@
1
1
  # shellcheck shell=bash
2
2
 
3
+ # 이 lib 은 단독으로 source 될 수 있다(계약 테스트가 그렇게 부른다). checks
4
+ # 경로 계산은 common.sh 한 곳에만 두고, 없으면 여기서 채운다.
5
+ # shellcheck source=common.sh
6
+ [ -n "${OKSTRA_VALIDATOR_CHECKS:-}" ] || . "$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common.sh"
7
+
3
8
  # Verify that the npm build output under `runtime/` is fresh and matches the
4
9
  # source files that `okstra install` (src/install.mjs) copies into the user's
5
10
  # `~/.claude/skills/`, `~/.claude/agents/`, and `~/.okstra/` directories.
@@ -20,60 +25,5 @@ validate_seeded_assets() {
20
25
  return 1
21
26
  fi
22
27
 
23
- python3 - "$SOURCE_ASSET_ROOT" "$WORKSPACE_ROOT/skills" "$runtime_root" "$validation_mode" <<'PY'
24
- from pathlib import Path
25
- import sys
26
-
27
- agents_source_root = Path(sys.argv[1]) # <repo>/agents
28
- skills_source_root = Path(sys.argv[2]) # <repo>/skills
29
- runtime_root = Path(sys.argv[3]) # <repo>/runtime
30
- validation_mode = sys.argv[4]
31
- errors = []
32
-
33
-
34
- def check(source_path: Path, target_path: Path) -> None:
35
- if not target_path.is_file():
36
- errors.append(f"missing build-output asset: {target_path}")
37
- return
38
- if validation_mode == "match" and target_path.read_bytes() != source_path.read_bytes():
39
- errors.append(f"build-output asset does not match source: {target_path}")
40
-
41
-
42
- # 1. Worker agent files: agents/workers/*-worker.md -> runtime/agents/workers/*-worker.md
43
- #
44
- workers_source = agents_source_root / "workers"
45
- workers_target = runtime_root / "agents" / "workers"
46
- if not workers_source.is_dir():
47
- errors.append(f"missing agents/workers source directory: {workers_source}")
48
- else:
49
- for source_path in sorted(workers_source.glob("*.md")):
50
- check(source_path, workers_target / source_path.name)
51
-
52
- # 2. Lead contract + internal lead resources: prompts/lead/* + prompts/coding-preflight/*
53
- # -> runtime/prompts/*. These ship as runtime resources (okstra install copies
54
- # runtime/prompts -> ~/.okstra/prompts), no longer as agent skills.
55
- prompts_source_root = agents_source_root.parent / "prompts"
56
- for sub in ("lead", "coding-preflight"):
57
- sub_root = prompts_source_root / sub
58
- if not sub_root.is_dir():
59
- errors.append(f"missing prompts source directory: {sub_root}")
60
- continue
61
- for source_path in sorted(sub_root.rglob("*.md")):
62
- relative = source_path.relative_to(prompts_source_root)
63
- check(source_path, runtime_root / "prompts" / relative)
64
-
65
- # 3. Skill packages: skills/<name>/SKILL.md -> runtime/skills/<name>/SKILL.md
66
- if not skills_source_root.is_dir():
67
- errors.append(f"missing skills source directory: {skills_source_root}")
68
- else:
69
- for skill_dir in sorted(p for p in skills_source_root.iterdir() if p.is_dir()):
70
- for source_path in sorted(skill_dir.rglob("*.md")):
71
- relative = source_path.relative_to(skills_source_root)
72
- check(source_path, runtime_root / "skills" / relative)
73
-
74
- if errors:
75
- for error in errors:
76
- print(error, file=sys.stderr)
77
- sys.exit(1)
78
- PY
28
+ python3 "$OKSTRA_VALIDATOR_CHECKS/validate-assets-01.py" "$SOURCE_ASSET_ROOT" "$WORKSPACE_ROOT/skills" "$runtime_root" "$validation_mode"
79
29
  }
@@ -1,5 +1,10 @@
1
1
  # shellcheck shell=bash
2
2
 
3
+ # 이 lib 은 단독으로 source 될 수 있다(계약 테스트가 그렇게 부른다). checks
4
+ # 경로 계산은 common.sh 한 곳에만 두고, 없으면 여기서 채운다.
5
+ # shellcheck source=common.sh
6
+ [ -n "${OKSTRA_VALIDATOR_CHECKS:-}" ] || . "$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common.sh"
7
+
3
8
  validate_worker_prompt_metadata() {
4
9
  local task_group="$1"
5
10
  local task_id="$2"
@@ -7,261 +12,5 @@ validate_worker_prompt_metadata() {
7
12
 
8
13
  expected_task_manifest_relative_path="$(task_manifest_relative_path "$task_group" "$task_id")"
9
14
 
10
- python3 - "$PROJECT_ROOT" "$expected_task_manifest_relative_path" <<'PY'
11
- from pathlib import Path
12
- import json
13
- import sys
14
-
15
- project_root = Path(sys.argv[1])
16
- task_manifest_path = project_root / sys.argv[2]
17
- errors = []
18
-
19
-
20
- def load_json(path: Path) -> dict:
21
- return json.loads(path.read_text())
22
-
23
-
24
- def validate_prompt_contract(
25
- prefix: str,
26
- worker_ids: list[str],
27
- prompt_dir: str,
28
- prompt_map: object,
29
- required_worker_roles: object,
30
- ) -> None:
31
- if not prompt_dir:
32
- errors.append(f"{prefix} is missing worker prompt directory metadata")
33
- if not isinstance(prompt_map, dict):
34
- errors.append(f"{prefix} worker prompt map is missing or invalid")
35
- prompt_map = {}
36
- if not isinstance(required_worker_roles, list):
37
- errors.append(f"{prefix} requiredWorkerRoles is missing or invalid")
38
- required_worker_roles = []
39
-
40
- expected_dir_prefix = prompt_dir.rstrip("/") + "/" if prompt_dir else ""
41
- for worker_id in worker_ids:
42
- if worker_id not in prompt_map:
43
- errors.append(f"{prefix} worker prompt map is missing selected worker: {worker_id}")
44
-
45
- for worker in required_worker_roles:
46
- if not isinstance(worker, dict):
47
- errors.append(f"{prefix} requiredWorkerRoles contains a non-object entry")
48
- continue
49
- worker_id = str(worker.get("workerId", "")).strip()
50
- prompt_relative = str(worker.get("promptPath", "")).strip()
51
- if not worker_id:
52
- errors.append(f"{prefix} requiredWorkerRoles contains an entry without workerId")
53
- continue
54
- if not prompt_relative:
55
- errors.append(
56
- f"{prefix} required worker is missing promptPath: {worker_id}"
57
- )
58
- continue
59
- if prompt_map.get(worker_id) != prompt_relative:
60
- errors.append(
61
- f"{prefix} worker prompt map does not match requiredWorkerRoles for {worker_id}"
62
- )
63
- if expected_dir_prefix and not prompt_relative.startswith(expected_dir_prefix):
64
- errors.append(
65
- f"{prefix} worker prompt path is outside the prompt directory: {prompt_relative}"
66
- )
67
-
68
-
69
- if not task_manifest_path.is_file():
70
- errors.append(f"task manifest is missing: {task_manifest_path}")
71
- else:
72
- task_manifest = load_json(task_manifest_path)
73
- selected_workers = task_manifest.get("recommendedWorkers", [])
74
- if not isinstance(selected_workers, list):
75
- errors.append("task manifest recommendedWorkers is missing or invalid")
76
- selected_workers = []
77
-
78
- task_prompt_dir = str(task_manifest.get("latestRunPromptsPath", "")).strip()
79
- if not task_prompt_dir:
80
- errors.append("task manifest is missing latestRunPromptsPath")
81
-
82
- task_artifacts = task_manifest.get("artifacts", {})
83
- if not isinstance(task_artifacts, dict):
84
- errors.append("task manifest artifacts is missing or invalid")
85
- task_artifacts = {}
86
-
87
- validate_prompt_contract(
88
- "task manifest",
89
- selected_workers,
90
- str(task_artifacts.get("workerPromptsDirectoryPath", "")).strip(),
91
- task_artifacts.get("workerPromptPathByWorkerId"),
92
- task_manifest.get("resultContract", {}).get("requiredWorkerRoles"),
93
- )
94
-
95
- if (
96
- task_prompt_dir
97
- and str(task_artifacts.get("workerPromptsDirectoryPath", "")).strip()
98
- and task_prompt_dir
99
- != str(task_artifacts.get("workerPromptsDirectoryPath", "")).strip()
100
- ):
101
- errors.append(
102
- "task manifest latestRunPromptsPath does not match artifacts.workerPromptsDirectoryPath"
103
- )
104
-
105
- timeline_relative_path = str(
106
- task_manifest.get("historyTimelinePath", "")
107
- ).strip()
108
- if not timeline_relative_path:
109
- errors.append("task manifest is missing historyTimelinePath")
110
- else:
111
- timeline_path = project_root / timeline_relative_path
112
- if not timeline_path.is_file():
113
- errors.append(f"timeline file is missing: {timeline_path}")
114
- else:
115
- timeline = load_json(timeline_path)
116
- runs = timeline.get("runs", [])
117
- latest_run = None
118
- if isinstance(runs, list):
119
- for item in reversed(runs):
120
- if isinstance(item, dict):
121
- latest_run = item
122
- break
123
- if latest_run is None:
124
- errors.append("timeline does not contain a latest run entry")
125
- else:
126
- latest_run_prompt_dir = str(
127
- latest_run.get("workerPromptDirectoryPath", "")
128
- ).strip()
129
- if not latest_run_prompt_dir:
130
- errors.append(
131
- "latest timeline entry is missing workerPromptDirectoryPath"
132
- )
133
- if task_prompt_dir and latest_run_prompt_dir and task_prompt_dir != latest_run_prompt_dir:
134
- errors.append(
135
- "timeline latest run prompt directory does not match task manifest latestRunPromptsPath"
136
- )
137
- prompt_map = latest_run.get("workerPromptPathByWorkerId")
138
- if not isinstance(prompt_map, dict):
139
- errors.append(
140
- "latest timeline entry is missing workerPromptPathByWorkerId"
141
- )
142
- else:
143
- for worker_id in selected_workers:
144
- if worker_id not in prompt_map:
145
- errors.append(
146
- f"latest timeline entry is missing worker prompt path for {worker_id}"
147
- )
148
-
149
- run_manifest_relative_path = str(
150
- latest_run.get("runManifestPath", "")
151
- ).strip()
152
- if not run_manifest_relative_path:
153
- errors.append(
154
- "latest timeline entry is missing runManifestPath"
155
- )
156
- else:
157
- run_manifest_path = project_root / run_manifest_relative_path
158
- if not run_manifest_path.is_file():
159
- errors.append(f"latest run manifest is missing: {run_manifest_path}")
160
- else:
161
- run_manifest = load_json(run_manifest_path)
162
- run_prompt_dir = str(
163
- run_manifest.get("workerPromptsDirectoryPath", "")
164
- ).strip()
165
- if task_prompt_dir and run_prompt_dir and task_prompt_dir != run_prompt_dir:
166
- errors.append(
167
- "run manifest workerPromptsDirectoryPath does not match task manifest latestRunPromptsPath"
168
- )
169
- validate_prompt_contract(
170
- "run manifest",
171
- selected_workers,
172
- run_prompt_dir,
173
- run_manifest.get("workerPromptPathByWorkerId"),
174
- run_manifest.get("teamContract", {}).get("requiredWorkerRoles"),
175
- )
176
-
177
- team_state_relative_path = str(
178
- run_manifest.get("teamStatePath")
179
- or task_manifest.get("teamStatePath", "")
180
- ).strip()
181
- if not team_state_relative_path:
182
- errors.append(
183
- "team state relative path is missing from run/task manifest"
184
- )
185
- else:
186
- team_state_path = project_root / team_state_relative_path
187
- if not team_state_path.is_file():
188
- errors.append(f"team-state file is missing: {team_state_path}")
189
- else:
190
- team_state = load_json(team_state_path)
191
- team_artifacts = team_state.get("artifacts", {})
192
- if not isinstance(team_artifacts, dict):
193
- errors.append(
194
- "team-state artifacts is missing or invalid"
195
- )
196
- team_artifacts = {}
197
- team_prompt_dir = str(
198
- team_artifacts.get(
199
- "workerPromptsDirectoryPath", ""
200
- )
201
- ).strip()
202
- if run_prompt_dir and team_prompt_dir and run_prompt_dir != team_prompt_dir:
203
- errors.append(
204
- "team-state worker prompt directory does not match run manifest"
205
- )
206
- workers = team_state.get("workers", [])
207
- if not isinstance(workers, list):
208
- errors.append("team-state workers is missing or invalid")
209
- else:
210
- team_workers = {}
211
- for worker in workers:
212
- if not isinstance(worker, dict):
213
- errors.append(
214
- "team-state workers contains a non-object entry"
215
- )
216
- continue
217
- worker_id = str(worker.get("workerId", "")).strip()
218
- if not worker_id:
219
- errors.append(
220
- "team-state workers contains an entry without workerId"
221
- )
222
- continue
223
- team_workers[worker_id] = worker
224
-
225
- run_prompt_map = run_manifest.get(
226
- "workerPromptPathByWorkerId", {}
227
- )
228
- if not isinstance(run_prompt_map, dict):
229
- run_prompt_map = {}
230
-
231
- for worker_id in selected_workers:
232
- worker = team_workers.get(worker_id)
233
- if worker is None:
234
- errors.append(
235
- f"team-state is missing selected worker entry: {worker_id}"
236
- )
237
- continue
238
- prompt_relative = str(
239
- worker.get("promptPath", "")
240
- ).strip()
241
- if not prompt_relative:
242
- errors.append(
243
- f"team-state worker is missing promptPath: {worker_id}"
244
- )
245
- continue
246
- if run_prompt_map.get(worker_id) != prompt_relative:
247
- errors.append(
248
- f"team-state worker prompt path does not match run manifest for {worker_id}"
249
- )
250
- expected_dir_prefix = (
251
- run_prompt_dir.rstrip("/") + "/"
252
- if run_prompt_dir
253
- else ""
254
- )
255
- if expected_dir_prefix and not prompt_relative.startswith(
256
- expected_dir_prefix
257
- ):
258
- errors.append(
259
- f"team-state worker prompt path is outside the run prompt directory: {prompt_relative}"
260
- )
261
-
262
- if errors:
263
- for error in errors:
264
- print(error, file=sys.stderr)
265
- sys.exit(1)
266
- PY
15
+ python3 "$OKSTRA_VALIDATOR_CHECKS/validate-prompt-metadata-01.py" "$PROJECT_ROOT" "$expected_task_manifest_relative_path"
267
16
  }