okstra 0.174.0 → 0.175.1

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 (374) hide show
  1. package/README.md +18 -9
  2. package/bin/okstra +8 -4
  3. package/dist/cli-registry.d.mts +16 -0
  4. package/dist/cli-registry.mjs +560 -0
  5. package/dist/cli-registry.mjs.map +1 -0
  6. package/dist/commands/execute/agent-prompt.d.mts +1 -0
  7. package/{src → dist}/commands/execute/agent-prompt.mjs +10 -11
  8. package/dist/commands/execute/agent-prompt.mjs.map +1 -0
  9. package/dist/commands/execute/codex-dispatch.d.mts +3 -0
  10. package/dist/commands/execute/codex-dispatch.mjs +6 -0
  11. package/dist/commands/execute/codex-dispatch.mjs.map +1 -0
  12. package/dist/commands/execute/codex-run.d.mts +3 -0
  13. package/{src → dist}/commands/execute/codex-run.mjs +30 -37
  14. package/dist/commands/execute/codex-run.mjs.map +1 -0
  15. package/dist/commands/execute/convergence.d.mts +1 -0
  16. package/{src → dist}/commands/execute/convergence.mjs +15 -16
  17. package/dist/commands/execute/convergence.mjs.map +1 -0
  18. package/dist/commands/execute/error-log.d.mts +1 -0
  19. package/{src → dist}/commands/execute/error-log.mjs +2 -3
  20. package/dist/commands/execute/error-log.mjs.map +1 -0
  21. package/dist/commands/execute/git-reconcile.d.mts +1 -0
  22. package/{src → dist}/commands/execute/git-reconcile.mjs +10 -11
  23. package/dist/commands/execute/git-reconcile.mjs.map +1 -0
  24. package/dist/commands/execute/handoff.d.mts +1 -0
  25. package/{src → dist}/commands/execute/handoff.mjs +10 -11
  26. package/dist/commands/execute/handoff.mjs.map +1 -0
  27. package/dist/commands/execute/incremental-carry.d.mts +1 -0
  28. package/{src → dist}/commands/execute/incremental-carry.mjs +2 -3
  29. package/dist/commands/execute/incremental-carry.mjs.map +1 -0
  30. package/dist/commands/execute/incremental-scope.d.mts +1 -0
  31. package/{src → dist}/commands/execute/incremental-scope.mjs +2 -3
  32. package/dist/commands/execute/incremental-scope.mjs.map +1 -0
  33. package/dist/commands/execute/integrate-stages.d.mts +1 -0
  34. package/{src → dist}/commands/execute/integrate-stages.mjs +10 -11
  35. package/dist/commands/execute/integrate-stages.mjs.map +1 -0
  36. package/dist/commands/execute/pane-title.d.mts +1 -0
  37. package/dist/commands/execute/pane-title.mjs +20 -0
  38. package/dist/commands/execute/pane-title.mjs.map +1 -0
  39. package/dist/commands/execute/plan-items.d.mts +1 -0
  40. package/dist/commands/execute/plan-items.mjs +9 -0
  41. package/dist/commands/execute/plan-items.mjs.map +1 -0
  42. package/dist/commands/execute/plan-validate.d.mts +1 -0
  43. package/dist/commands/execute/plan-validate.mjs +68 -0
  44. package/dist/commands/execute/plan-validate.mjs.map +1 -0
  45. package/dist/commands/execute/plan-verify.d.mts +1 -0
  46. package/{src → dist}/commands/execute/plan-verify.mjs +13 -16
  47. package/dist/commands/execute/plan-verify.mjs.map +1 -0
  48. package/dist/commands/execute/render-bundle.d.mts +3 -0
  49. package/{src → dist}/commands/execute/render-bundle.mjs +65 -61
  50. package/dist/commands/execute/render-bundle.mjs.map +1 -0
  51. package/dist/commands/execute/run.d.mts +24 -0
  52. package/dist/commands/execute/run.mjs +196 -0
  53. package/dist/commands/execute/run.mjs.map +1 -0
  54. package/dist/commands/execute/spawn-followups.d.mts +1 -0
  55. package/{src → dist}/commands/execute/spawn-followups.mjs +6 -7
  56. package/dist/commands/execute/spawn-followups.mjs.map +1 -0
  57. package/dist/commands/execute/team.d.mts +3 -0
  58. package/{src → dist}/commands/execute/team.mjs +29 -36
  59. package/dist/commands/execute/team.mjs.map +1 -0
  60. package/dist/commands/execute/token-usage.d.mts +1 -0
  61. package/{src → dist}/commands/execute/token-usage.mjs +2 -3
  62. package/dist/commands/execute/token-usage.mjs.map +1 -0
  63. package/dist/commands/execute/wizard.d.mts +8 -0
  64. package/dist/commands/execute/wizard.mjs +191 -0
  65. package/dist/commands/execute/wizard.mjs.map +1 -0
  66. package/dist/commands/execute/worker-audit-check.d.mts +1 -0
  67. package/{src → dist}/commands/execute/worker-audit-check.mjs +11 -12
  68. package/dist/commands/execute/worker-audit-check.mjs.map +1 -0
  69. package/dist/commands/execute/worker-dispatch.d.mts +7 -0
  70. package/{src → dist}/commands/execute/worker-dispatch.mjs +34 -46
  71. package/dist/commands/execute/worker-dispatch.mjs.map +1 -0
  72. package/dist/commands/execute/worker-state.d.mts +1 -0
  73. package/{src → dist}/commands/execute/worker-state.mjs +15 -16
  74. package/dist/commands/execute/worker-state.mjs.map +1 -0
  75. package/dist/commands/execute/worktree-lookup.d.mts +1 -0
  76. package/{src → dist}/commands/execute/worktree-lookup.mjs +38 -37
  77. package/dist/commands/execute/worktree-lookup.mjs.map +1 -0
  78. package/dist/commands/execute/worktree-status.d.mts +1 -0
  79. package/{src → dist}/commands/execute/worktree-status.mjs +52 -46
  80. package/dist/commands/execute/worktree-status.mjs.map +1 -0
  81. package/dist/commands/inspect/code-review.d.mts +1 -0
  82. package/{src → dist}/commands/inspect/code-review.mjs +16 -19
  83. package/dist/commands/inspect/code-review.mjs.map +1 -0
  84. package/dist/commands/inspect/container.d.mts +1 -0
  85. package/{src → dist}/commands/inspect/container.mjs +11 -13
  86. package/dist/commands/inspect/container.mjs.map +1 -0
  87. package/dist/commands/inspect/context-cost.d.mts +1 -0
  88. package/{src → dist}/commands/inspect/context-cost.mjs +11 -13
  89. package/dist/commands/inspect/context-cost.mjs.map +1 -0
  90. package/dist/commands/inspect/design-prep.d.mts +1 -0
  91. package/{src → dist}/commands/inspect/design-prep.mjs +10 -11
  92. package/dist/commands/inspect/design-prep.mjs.map +1 -0
  93. package/dist/commands/inspect/error-report.d.mts +1 -0
  94. package/{src → dist}/commands/inspect/error-report.mjs +11 -13
  95. package/dist/commands/inspect/error-report.mjs.map +1 -0
  96. package/dist/commands/inspect/error-zip.d.mts +1 -0
  97. package/{src → dist}/commands/inspect/error-zip.mjs +11 -12
  98. package/dist/commands/inspect/error-zip.mjs.map +1 -0
  99. package/dist/commands/inspect/log-report.d.mts +1 -0
  100. package/{src → dist}/commands/inspect/log-report.mjs +11 -13
  101. package/dist/commands/inspect/log-report.mjs.map +1 -0
  102. package/dist/commands/inspect/profile-show.d.mts +1 -0
  103. package/{src → dist}/commands/inspect/profile-show.mjs +10 -11
  104. package/dist/commands/inspect/profile-show.mjs.map +1 -0
  105. package/dist/commands/inspect/recap.d.mts +1 -0
  106. package/{src → dist}/commands/inspect/recap.mjs +11 -13
  107. package/dist/commands/inspect/recap.mjs.map +1 -0
  108. package/dist/commands/inspect/resolve-task-key.d.mts +1 -0
  109. package/{src → dist}/commands/inspect/resolve-task-key.mjs +11 -13
  110. package/dist/commands/inspect/resolve-task-key.mjs.map +1 -0
  111. package/dist/commands/inspect/rollup.d.mts +1 -0
  112. package/{src → dist}/commands/inspect/rollup.mjs +11 -13
  113. package/dist/commands/inspect/rollup.mjs.map +1 -0
  114. package/dist/commands/inspect/run-audit.d.mts +1 -0
  115. package/{src → dist}/commands/inspect/run-audit.mjs +11 -12
  116. package/dist/commands/inspect/run-audit.mjs.map +1 -0
  117. package/dist/commands/inspect/set-work-status.d.mts +1 -0
  118. package/{src → dist}/commands/inspect/set-work-status.mjs +11 -13
  119. package/dist/commands/inspect/set-work-status.mjs.map +1 -0
  120. package/dist/commands/inspect/stage-map.d.mts +1 -0
  121. package/dist/commands/inspect/stage-map.mjs +110 -0
  122. package/dist/commands/inspect/stage-map.mjs.map +1 -0
  123. package/dist/commands/inspect/task-list.d.mts +1 -0
  124. package/dist/commands/inspect/task-list.mjs +103 -0
  125. package/dist/commands/inspect/task-list.mjs.map +1 -0
  126. package/dist/commands/inspect/task-show.d.mts +1 -0
  127. package/dist/commands/inspect/task-show.mjs +108 -0
  128. package/dist/commands/inspect/task-show.mjs.map +1 -0
  129. package/dist/commands/inspect/time-report.d.mts +1 -0
  130. package/{src → dist}/commands/inspect/time-report.mjs +11 -13
  131. package/dist/commands/inspect/time-report.mjs.map +1 -0
  132. package/dist/commands/inspect/usage-report.d.mts +1 -0
  133. package/{src → dist}/commands/inspect/usage-report.mjs +11 -13
  134. package/dist/commands/inspect/usage-report.mjs.map +1 -0
  135. package/dist/commands/inspect/user-response.d.mts +1 -0
  136. package/{src → dist}/commands/inspect/user-response.mjs +10 -11
  137. package/dist/commands/inspect/user-response.mjs.map +1 -0
  138. package/dist/commands/inspect/worker-liveness.d.mts +1 -0
  139. package/{src → dist}/commands/inspect/worker-liveness.mjs +11 -13
  140. package/dist/commands/inspect/worker-liveness.mjs.map +1 -0
  141. package/dist/commands/lifecycle/check-project.d.mts +21 -0
  142. package/dist/commands/lifecycle/check-project.mjs +175 -0
  143. package/dist/commands/lifecycle/check-project.mjs.map +1 -0
  144. package/dist/commands/lifecycle/config.d.mts +1 -0
  145. package/dist/commands/lifecycle/config.mjs +369 -0
  146. package/dist/commands/lifecycle/config.mjs.map +1 -0
  147. package/dist/commands/lifecycle/doctor.d.mts +10 -0
  148. package/dist/commands/lifecycle/doctor.mjs +317 -0
  149. package/dist/commands/lifecycle/doctor.mjs.map +1 -0
  150. package/dist/commands/lifecycle/install.d.mts +17 -0
  151. package/dist/commands/lifecycle/install.mjs +1077 -0
  152. package/dist/commands/lifecycle/install.mjs.map +1 -0
  153. package/dist/commands/lifecycle/migrate.d.mts +1 -0
  154. package/{src → dist}/commands/lifecycle/migrate.mjs +10 -11
  155. package/dist/commands/lifecycle/migrate.mjs.map +1 -0
  156. package/dist/commands/lifecycle/model.d.mts +1 -0
  157. package/dist/commands/lifecycle/model.mjs +22 -0
  158. package/dist/commands/lifecycle/model.mjs.map +1 -0
  159. package/dist/commands/lifecycle/paths.d.mts +1 -0
  160. package/dist/commands/lifecycle/paths.mjs +102 -0
  161. package/dist/commands/lifecycle/paths.mjs.map +1 -0
  162. package/dist/commands/lifecycle/preflight.d.mts +1 -0
  163. package/dist/commands/lifecycle/preflight.mjs +124 -0
  164. package/dist/commands/lifecycle/preflight.mjs.map +1 -0
  165. package/dist/commands/lifecycle/setup.d.mts +1 -0
  166. package/dist/commands/lifecycle/setup.mjs +297 -0
  167. package/dist/commands/lifecycle/setup.mjs.map +1 -0
  168. package/dist/commands/lifecycle/uninstall.d.mts +4 -0
  169. package/dist/commands/lifecycle/uninstall.mjs +262 -0
  170. package/dist/commands/lifecycle/uninstall.mjs.map +1 -0
  171. package/dist/commands/manager.d.mts +3 -0
  172. package/{src → dist}/commands/manager.mjs +25 -32
  173. package/dist/commands/manager.mjs.map +1 -0
  174. package/dist/commands/memory/memory.d.mts +1 -0
  175. package/dist/commands/memory/memory.mjs +569 -0
  176. package/dist/commands/memory/memory.mjs.map +1 -0
  177. package/dist/commands/pr/pr.d.mts +33 -0
  178. package/dist/commands/pr/pr.mjs +296 -0
  179. package/dist/commands/pr/pr.mjs.map +1 -0
  180. package/dist/commands/report/agent-activity.d.mts +1 -0
  181. package/{src → dist}/commands/report/agent-activity.mjs +11 -12
  182. package/dist/commands/report/agent-activity.mjs.map +1 -0
  183. package/dist/commands/report/finalize.d.mts +4 -0
  184. package/{src → dist}/commands/report/finalize.mjs +25 -32
  185. package/dist/commands/report/finalize.mjs.map +1 -0
  186. package/dist/commands/report/inject-report-index.d.mts +1 -0
  187. package/{src → dist}/commands/report/inject-report-index.mjs +6 -7
  188. package/dist/commands/report/inject-report-index.mjs.map +1 -0
  189. package/dist/commands/report/render-final-report.d.mts +1 -0
  190. package/{src → dist}/commands/report/render-final-report.mjs +6 -7
  191. package/dist/commands/report/render-final-report.mjs.map +1 -0
  192. package/dist/commands/report/render-views.d.mts +1 -0
  193. package/{src → dist}/commands/report/render-views.mjs +6 -7
  194. package/dist/commands/report/render-views.mjs.map +1 -0
  195. package/dist/commands/report/translate.d.mts +1 -0
  196. package/{src → dist}/commands/report/translate.mjs +6 -7
  197. package/dist/commands/report/translate.mjs.map +1 -0
  198. package/dist/lib/helper-scripts.d.mts +3 -0
  199. package/{src → dist}/lib/helper-scripts.mjs +11 -14
  200. package/dist/lib/helper-scripts.mjs.map +1 -0
  201. package/dist/lib/host-registry-client.d.mts +25 -0
  202. package/dist/lib/host-registry-client.mjs +152 -0
  203. package/dist/lib/host-registry-client.mjs.map +1 -0
  204. package/dist/lib/install-assets.d.mts +8 -0
  205. package/{src → dist}/lib/install-assets.mjs +17 -20
  206. package/dist/lib/install-assets.mjs.map +1 -0
  207. package/dist/lib/okstra-dirs.d.mts +4 -0
  208. package/{src → dist}/lib/okstra-dirs.mjs +3 -6
  209. package/dist/lib/okstra-dirs.mjs.map +1 -0
  210. package/dist/lib/paths.d.mts +4 -0
  211. package/dist/lib/paths.mjs +78 -0
  212. package/dist/lib/paths.mjs.map +1 -0
  213. package/dist/lib/proc.d.mts +3 -0
  214. package/dist/lib/proc.mjs +31 -0
  215. package/dist/lib/proc.mjs.map +1 -0
  216. package/dist/lib/python-helper.d.mts +8 -0
  217. package/dist/lib/python-helper.mjs +123 -0
  218. package/dist/lib/python-helper.mjs.map +1 -0
  219. package/dist/lib/runtime-manifest.d.mts +7 -0
  220. package/dist/lib/runtime-manifest.mjs +73 -0
  221. package/dist/lib/runtime-manifest.mjs.map +1 -0
  222. package/dist/lib/skill-catalog.d.mts +4 -0
  223. package/dist/lib/skill-catalog.mjs +50 -0
  224. package/dist/lib/skill-catalog.mjs.map +1 -0
  225. package/dist/lib/types.d.mts +129 -0
  226. package/dist/lib/types.mjs +2 -0
  227. package/dist/lib/types.mjs.map +1 -0
  228. package/dist/lib/version.d.mts +2 -0
  229. package/dist/lib/version.mjs +27 -0
  230. package/dist/lib/version.mjs.map +1 -0
  231. package/docs/architecture/storage-model.md +4 -0
  232. package/docs/architecture.md +7 -1
  233. package/docs/cli.md +26 -6
  234. package/docs/contributor-change-matrix.md +2 -2
  235. package/docs/project-structure-overview.md +16 -7
  236. package/docs/task-process/README.md +2 -0
  237. package/docs/task-process/implementation-planning.md +1 -1
  238. package/docs/task-process/implementation.md +1 -1
  239. package/package.json +11 -5
  240. package/runtime/BUILD.json +2 -2
  241. package/runtime/agents/workers/claude-worker.md +2 -1
  242. package/runtime/agents/workers/report-writer-worker.md +3 -1
  243. package/runtime/agents/workers/translator-worker.md +3 -1
  244. package/runtime/bin/lib/okstra/cli.sh +12 -0
  245. package/runtime/bin/lib/okstra/globals.sh +3 -0
  246. package/runtime/bin/lib/okstra/usage.sh +4 -4
  247. package/runtime/bin/okstra-error-log.py +27 -0
  248. package/runtime/bin/okstra-provider-exec.py +217 -5
  249. package/runtime/bin/okstra.sh +10 -0
  250. package/runtime/prompts/lead/convergence.md +27 -18
  251. package/runtime/prompts/lead/okstra-lead-contract.md +3 -1
  252. package/runtime/prompts/lead/plan-body-verification.md +10 -3
  253. package/runtime/prompts/lead/team-contract.md +1 -1
  254. package/runtime/prompts/profiles/change-impact-analysis.md +16 -0
  255. package/runtime/prompts/profiles/error-analysis.md +20 -0
  256. package/runtime/prompts/profiles/feature-analysis.md +16 -0
  257. package/runtime/prompts/profiles/final-verification.md +16 -0
  258. package/runtime/prompts/profiles/implementation-option-selection.md +16 -0
  259. package/runtime/prompts/profiles/implementation-planning.md +20 -0
  260. package/runtime/prompts/profiles/implementation.md +15 -0
  261. package/runtime/prompts/profiles/improvement-discovery.md +16 -0
  262. package/runtime/prompts/profiles/project-analysis.md +16 -0
  263. package/runtime/prompts/profiles/release-handoff.md +4 -0
  264. package/runtime/prompts/profiles/requirements-discovery.md +20 -0
  265. package/runtime/prompts/wizard/prompts.ko.json +18 -0
  266. package/runtime/python/okstra_ctl/adapters/dispatch/cli_wrapper.py +8 -0
  267. package/runtime/python/okstra_ctl/adapters/dispatch/cmux.py +8 -0
  268. package/runtime/python/okstra_ctl/adapters/dispatch/native_team.py +13 -0
  269. package/runtime/python/okstra_ctl/adapters/hosts/antigravity/adapter.py +2 -2
  270. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +25 -5
  271. package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +2 -2
  272. package/runtime/python/okstra_ctl/adapters/hosts/external/adapter.py +4 -1
  273. package/runtime/python/okstra_ctl/adapters/hosts/grok/adapter.py +2 -2
  274. package/runtime/python/okstra_ctl/adapters/hosts/kimi/adapter.py +2 -2
  275. package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +79 -11
  276. package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +95 -25
  277. package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +59 -14
  278. package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +55 -9
  279. package/runtime/python/okstra_ctl/adapters/providers/kimi/adapter.py +51 -12
  280. package/runtime/python/okstra_ctl/agent_activity.py +5 -1
  281. package/runtime/python/okstra_ctl/agent_invocation.py +608 -14
  282. package/runtime/python/okstra_ctl/agent_prompt_cli.py +249 -50
  283. package/runtime/python/okstra_ctl/application/resolve_assignment.py +53 -12
  284. package/runtime/python/okstra_ctl/assignment_environment.py +102 -0
  285. package/runtime/python/okstra_ctl/assignment_resolver.py +790 -0
  286. package/runtime/python/okstra_ctl/attempt_evidence.py +342 -0
  287. package/runtime/python/okstra_ctl/convergence.py +409 -3
  288. package/runtime/python/okstra_ctl/convergence_engine.py +248 -15
  289. package/runtime/python/okstra_ctl/convergence_store.py +170 -1
  290. package/runtime/python/okstra_ctl/dispatch_core.py +1092 -63
  291. package/runtime/python/okstra_ctl/dispatch_state.py +696 -11
  292. package/runtime/python/okstra_ctl/doctor.py +14 -0
  293. package/runtime/python/okstra_ctl/domain/host.py +32 -1
  294. package/runtime/python/okstra_ctl/domain/provider.py +212 -6
  295. package/runtime/python/okstra_ctl/domain/role.py +125 -0
  296. package/runtime/python/okstra_ctl/domain/wizard/interaction.py +13 -0
  297. package/runtime/python/okstra_ctl/domain/worker_exec.py +34 -1
  298. package/runtime/python/okstra_ctl/domain/worker_role.py +13 -3
  299. package/runtime/python/okstra_ctl/domain/worker_stream.py +24 -0
  300. package/runtime/python/okstra_ctl/error_log_write.py +9 -0
  301. package/runtime/python/okstra_ctl/error_report.py +21 -1
  302. package/runtime/python/okstra_ctl/execution_identity.py +529 -0
  303. package/runtime/python/okstra_ctl/execution_manifest.py +1281 -0
  304. package/runtime/python/okstra_ctl/execution_mutation_audit.py +619 -0
  305. package/runtime/python/okstra_ctl/index.py +6 -2
  306. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +43 -3
  307. package/runtime/python/okstra_ctl/legacy_model_selection.py +490 -0
  308. package/runtime/python/okstra_ctl/model_cli.py +278 -0
  309. package/runtime/python/okstra_ctl/model_defaults.py +46 -0
  310. package/runtime/python/okstra_ctl/model_discovery.py +26 -7
  311. package/runtime/python/okstra_ctl/model_pool.py +501 -0
  312. package/runtime/python/okstra_ctl/models.py +47 -27
  313. package/runtime/python/okstra_ctl/mutation_recovery.py +293 -0
  314. package/runtime/python/okstra_ctl/pane_title.py +151 -0
  315. package/runtime/python/okstra_ctl/ports/host_model.py +48 -17
  316. package/runtime/python/okstra_ctl/ports/worker_dispatch.py +4 -0
  317. package/runtime/python/okstra_ctl/registry/provider_registry.py +8 -4
  318. package/runtime/python/okstra_ctl/render.py +78 -10
  319. package/runtime/python/okstra_ctl/render_final_report.py +19 -0
  320. package/runtime/python/okstra_ctl/report_contract.py +39 -0
  321. package/runtime/python/okstra_ctl/report_finalize.py +16 -0
  322. package/runtime/python/okstra_ctl/report_html/render.py +1 -0
  323. package/runtime/python/okstra_ctl/role_requirements.py +217 -0
  324. package/runtime/python/okstra_ctl/run.py +1207 -258
  325. package/runtime/python/okstra_ctl/run_index_row.py +7 -1
  326. package/runtime/python/okstra_ctl/time_report.py +38 -4
  327. package/runtime/python/okstra_ctl/usage_identity.py +86 -0
  328. package/runtime/python/okstra_ctl/usage_report.py +15 -3
  329. package/runtime/python/okstra_ctl/wizard.py +1253 -62
  330. package/runtime/python/okstra_ctl/worker_audit_ledger.py +68 -65
  331. package/runtime/python/okstra_ctl/worker_request.py +7 -1
  332. package/runtime/python/okstra_ctl/worker_runner.py +130 -5
  333. package/runtime/python/okstra_ctl/workers.py +7 -5
  334. package/runtime/python/okstra_ctl/write_policy.py +571 -0
  335. package/runtime/schemas/convergence-groups-v2.0.schema.json +128 -0
  336. package/runtime/schemas/execution-manifest-v2.schema.json +340 -0
  337. package/runtime/schemas/final-report-v2.0.schema.json +25 -0
  338. package/runtime/skills/okstra-run/SKILL.md +9 -9
  339. package/runtime/templates/report-writer-prompt-preamble.md +2 -0
  340. package/runtime/templates/reports/final-report-v2.template.md +7 -1
  341. package/runtime/templates/reports/html/base.template.html +21 -0
  342. package/runtime/templates/reports/html/i18n/en.json +4 -0
  343. package/runtime/templates/reports/html/i18n/ko.json +4 -0
  344. package/runtime/templates/worker-prompt-preamble.md +6 -2
  345. package/runtime/validators/lib/fixtures.sh +49 -16
  346. package/runtime/validators/validate-run.py +429 -35
  347. package/runtime/validators/validate_session_conformance.py +25 -7
  348. package/src/cli-registry.mjs +0 -539
  349. package/src/commands/execute/codex-dispatch.mjs +0 -10
  350. package/src/commands/execute/plan-items.mjs +0 -9
  351. package/src/commands/execute/plan-validate.mjs +0 -68
  352. package/src/commands/execute/run.mjs +0 -208
  353. package/src/commands/execute/wizard.mjs +0 -167
  354. package/src/commands/inspect/stage-map.mjs +0 -98
  355. package/src/commands/inspect/task-list.mjs +0 -97
  356. package/src/commands/inspect/task-show.mjs +0 -100
  357. package/src/commands/lifecycle/check-project.mjs +0 -187
  358. package/src/commands/lifecycle/config.mjs +0 -385
  359. package/src/commands/lifecycle/doctor.mjs +0 -308
  360. package/src/commands/lifecycle/install.mjs +0 -1170
  361. package/src/commands/lifecycle/paths.mjs +0 -104
  362. package/src/commands/lifecycle/preflight.mjs +0 -125
  363. package/src/commands/lifecycle/setup.mjs +0 -333
  364. package/src/commands/lifecycle/uninstall.mjs +0 -279
  365. package/src/commands/memory/memory.mjs +0 -524
  366. package/src/commands/pr/pr.mjs +0 -261
  367. package/src/lib/host-registry-client.mjs +0 -176
  368. package/src/lib/paths.mjs +0 -86
  369. package/src/lib/proc.mjs +0 -31
  370. package/src/lib/python-helper.mjs +0 -142
  371. package/src/lib/runtime-manifest.mjs +0 -70
  372. package/src/lib/skill-catalog.mjs +0 -53
  373. package/src/lib/version.mjs +0 -20
  374. /package/{src → dist}/commands/pr/default.md +0 -0
@@ -1,100 +0,0 @@
1
- import { runPythonSnippet, emitJsonError } from "../../lib/python-helper.mjs";
2
-
3
- const USAGE = `okstra task-show — summarize a task's manifest and workflow state
4
-
5
- Usage:
6
- okstra task-show <task-key> task-key is project-id:task-group:task-id
7
- okstra task-show <task-key> --cwd <dir> Resolve PROJECT_ROOT from <dir>
8
- okstra task-show <task-key> --project <dir> Use <dir> directly as PROJECT_ROOT
9
-
10
- Output: JSON with taskKey, taskType, taskRoot, brief path, workflow phases,
11
- artifacts, modelAssignments, latestRunPath. Replaces the
12
- \`cat task-manifest.json | python3 -c ...\` summarization pattern.
13
- `;
14
-
15
- function parseArgs(args) {
16
- const opts = { cwd: process.cwd(), projectRoot: "", taskKey: "" };
17
- const positional = [];
18
- for (let i = 0; i < args.length; i++) {
19
- const a = args[i];
20
- if (a === "--cwd") {
21
- opts.cwd = args[++i];
22
- if (!opts.cwd) throw new Error("--cwd requires a path");
23
- } else if (a === "--project") {
24
- opts.projectRoot = args[++i];
25
- if (!opts.projectRoot) throw new Error("--project requires a path");
26
- } else if (a.startsWith("--")) {
27
- throw new Error(`unknown argument '${a}'`);
28
- } else {
29
- positional.push(a);
30
- }
31
- }
32
- if (positional.length !== 1) {
33
- throw new Error("expected exactly one positional argument: <task-key>");
34
- }
35
- opts.taskKey = positional[0];
36
- return opts;
37
- }
38
-
39
- const SCRIPT = `
40
- import json, sys
41
- from pathlib import Path
42
- from okstra_project import (
43
- resolve_project_root, task_read_side_snapshot,
44
- ResolverError, StateError,
45
- )
46
-
47
- explicit = sys.argv[1]
48
- cwd = sys.argv[2]
49
- task_key = sys.argv[3]
50
-
51
- try:
52
- pr = resolve_project_root(explicit_root=explicit, cwd=cwd)
53
- except ResolverError as e:
54
- print(json.dumps({"ok": False, "stage": "resolve", "reason": str(e)}))
55
- sys.exit(2)
56
-
57
- pr_path = Path(pr)
58
- try:
59
- snapshot = task_read_side_snapshot(pr_path, task_key)
60
- except StateError as e:
61
- print(json.dumps({
62
- "ok": False,
63
- "stage": getattr(e, "stage", None) or "task_snapshot",
64
- "reason": str(e),
65
- }))
66
- sys.exit(1)
67
-
68
- out = {"ok": True, **snapshot}
69
- print(json.dumps(out, ensure_ascii=False, default=str, indent=2))
70
- `;
71
-
72
- export async function run(args) {
73
- if (args.includes("--help") || args.includes("-h")) {
74
- process.stdout.write(USAGE);
75
- return 0;
76
- }
77
- let opts;
78
- try {
79
- opts = parseArgs(args);
80
- } catch (err) {
81
- process.stderr.write(`error: ${err.message}\n\n${USAGE}`);
82
- return 2;
83
- }
84
-
85
- const result = await runPythonSnippet({
86
- script: SCRIPT,
87
- args: [opts.projectRoot, opts.cwd, opts.taskKey],
88
- });
89
-
90
- if (result.code !== 0 && !result.stdout.trim()) {
91
- emitJsonError({
92
- stage: "python",
93
- reason: `python invocation failed: ${result.stderr.trim() || "no output"}`,
94
- });
95
- return 1;
96
- }
97
-
98
- process.stdout.write(result.stdout);
99
- return result.code === 0 ? 0 : result.code;
100
- }
@@ -1,187 +0,0 @@
1
- import { promises as fs } from "node:fs";
2
- import { join } from "node:path";
3
- import { buildPythonpath, resolvePaths } from "../../lib/paths.mjs";
4
- import { fileExists, runProcess } from "../../lib/proc.mjs";
5
-
6
- const USAGE = `okstra check-project — verify that the current project has okstra setup
7
-
8
- Usage:
9
- okstra check-project Resolve PROJECT_ROOT from cwd, look for
10
- .okstra/project.json,
11
- print JSON status to stdout.
12
- okstra check-project --cwd <dir> Use <dir> as the search starting point
13
- instead of process cwd.
14
- okstra check-project --json Same as default (kept for symmetry with
15
- 'paths --json').
16
- okstra check-project --quiet Suppress stdout on success; exit code
17
- alone reports state.
18
-
19
- Exit codes:
20
- 0 project.json found, projectId present
21
- 1 project.json missing or unreadable (project setup not done)
22
- 2 PROJECT_ROOT could not be resolved from cwd (no project marker
23
- ancestor; user should pass --cwd or run from within a project)
24
-
25
- User-facing skills should call this after 'ensure-installed' and refuse
26
- to proceed if the exit code is non-zero, directing the user to
27
- '/okstra-setup' first.
28
- `;
29
-
30
- function parseArgs(args) {
31
- const opts = { cwd: process.cwd(), quiet: false, json: true };
32
- for (let i = 0; i < args.length; i++) {
33
- const a = args[i];
34
- if (a === "--quiet" || a === "-q") opts.quiet = true;
35
- else if (a === "--json") opts.json = true;
36
- else if (a === "--cwd") {
37
- const next = args[i + 1];
38
- if (!next || next.startsWith("--")) throw new Error("--cwd requires a path");
39
- opts.cwd = next;
40
- i++;
41
- } else {
42
- throw new Error(`unknown argument '${a}'`);
43
- }
44
- }
45
- return opts;
46
- }
47
-
48
- function emit(opts, payload) {
49
- if (opts.quiet) return;
50
- process.stdout.write(JSON.stringify(payload, null, 2) + "\n");
51
- }
52
-
53
- export async function run(args) {
54
- if (args.includes("--help") || args.includes("-h")) {
55
- process.stdout.write(USAGE);
56
- return 0;
57
- }
58
-
59
- let opts;
60
- try {
61
- opts = parseArgs(args);
62
- } catch (err) {
63
- process.stderr.write(`error: ${err.message}\n\n${USAGE}`);
64
- return 2;
65
- }
66
- const { code, payload } = await checkProject({ cwd: opts.cwd });
67
- emit(opts, payload);
68
- return code;
69
- }
70
-
71
- // Core check shared with 'okstra preflight' — resolves PROJECT_ROOT from cwd
72
- // and validates .okstra/project.json without writing to stdout.
73
- export async function checkProject({ cwd = process.cwd() } = {}) {
74
- const paths = await resolvePaths();
75
-
76
- const probe = await runProcess(
77
- "python3",
78
- [
79
- "-c",
80
- [
81
- "import json, sys",
82
- "from okstra_project import resolve_project_root, project_json_path, ResolverError",
83
- "try:",
84
- " pr = resolve_project_root(explicit_root='', cwd=sys.argv[1])",
85
- " print('PROJECT_ROOT', pr)",
86
- " print('PROJECT_JSON', project_json_path(pr))",
87
- "except ResolverError as e:",
88
- " print('RESOLVER_ERROR', e)",
89
- ].join("\n"),
90
- cwd,
91
- ],
92
- { PYTHONPATH: buildPythonpath(paths) },
93
- );
94
-
95
- if (probe.code !== 0) {
96
- const raw = probe.stderr.trim() || probe.stdout.trim();
97
- return {
98
- code: 1,
99
- payload: {
100
- ok: false,
101
- stage: "python",
102
- reason:
103
- `python invocation failed: ${raw}. ` +
104
- "This usually means the okstra runtime is stale or missing — " +
105
- "run 'okstra doctor' to diagnose, then 'okstra ensure-installed' " +
106
- "to repair.",
107
- },
108
- };
109
- }
110
-
111
- const lines = probe.stdout.trim().split("\n");
112
- const tagOf = (key) =>
113
- lines
114
- .find((l) => l.startsWith(key + " "))
115
- ?.slice(key.length + 1)
116
- .trim() ?? null;
117
-
118
- const resolverError = tagOf("RESOLVER_ERROR");
119
- if (resolverError) {
120
- return {
121
- code: 2,
122
- payload: { ok: false, stage: "resolve", reason: resolverError, cwd },
123
- };
124
- }
125
-
126
- const projectRoot = tagOf("PROJECT_ROOT");
127
- const projectJsonPath = tagOf("PROJECT_JSON");
128
- if (!projectRoot || !projectJsonPath) {
129
- return {
130
- code: 1,
131
- payload: {
132
- ok: false,
133
- stage: "parse",
134
- reason: "could not parse python output",
135
- raw: probe.stdout,
136
- },
137
- };
138
- }
139
-
140
- if (!(await fileExists(projectJsonPath))) {
141
- return {
142
- code: 1,
143
- payload: {
144
- ok: false,
145
- stage: "project_json_missing",
146
- reason: `${projectJsonPath} not found — run /okstra-setup in this project first`,
147
- projectRoot,
148
- projectJsonPath,
149
- },
150
- };
151
- }
152
-
153
- let projectId = null;
154
- try {
155
- const data = JSON.parse(await fs.readFile(projectJsonPath, "utf8"));
156
- projectId = typeof data?.projectId === "string" ? data.projectId : null;
157
- } catch (err) {
158
- return {
159
- code: 1,
160
- payload: {
161
- ok: false,
162
- stage: "project_json_invalid",
163
- reason: `failed to parse ${projectJsonPath}: ${err.message}`,
164
- projectRoot,
165
- projectJsonPath,
166
- },
167
- };
168
- }
169
-
170
- if (!projectId) {
171
- return {
172
- code: 1,
173
- payload: {
174
- ok: false,
175
- stage: "project_json_invalid",
176
- reason: `${projectJsonPath} missing projectId field`,
177
- projectRoot,
178
- projectJsonPath,
179
- },
180
- };
181
- }
182
-
183
- return {
184
- code: 0,
185
- payload: { ok: true, projectRoot, projectJsonPath, projectId },
186
- };
187
- }
@@ -1,385 +0,0 @@
1
- import { promises as fs } from "node:fs";
2
- import { dirname, join, resolve, isAbsolute } from "node:path";
3
- import { buildPythonpath, resolvePaths, resolveOkstraHome } from "../../lib/paths.mjs";
4
- import { OKSTRA_DIR, projectJsonPath } from "../../lib/okstra-dirs.mjs";
5
- import { fileExists, runProcess } from "../../lib/proc.mjs";
6
-
7
- const USAGE = `okstra config — read / write okstra settings (project + global scopes)
8
-
9
- Settings are persisted as JSON keys in one of two files:
10
- project: <project-root>/${OKSTRA_DIR}/project.json
11
- global: ~/.okstra/config.json
12
-
13
- Supported keys (CLI alias -> JSON field):
14
- pr-template-path -> prTemplatePath
15
- PR body template used by the release-handoff phase.
16
- Path may be absolute, ~/-prefixed, or (project scope
17
- only) relative to <project-root>.
18
-
19
- report-language -> reportLanguage
20
- Final-report language. One of: en, ko, auto.
21
- 'auto' is resolved by the report-writer lead from
22
- the task brief at run time.
23
-
24
- Usage:
25
- okstra config get <key> [--scope project|global|all]
26
- Print the value at the requested scope.
27
- 'all' prints every scope, plus the effective resolved value where
28
- available (for pr-template-path the resolver may fall back to the
29
- bundled skill default).
30
-
31
- okstra config set <key> <value> [--scope project|global]
32
- Write the value. Scope is required unless cwd is inside an okstra
33
- project (then defaults to 'project'). Global scope only accepts
34
- absolute or ~/-prefixed paths.
35
-
36
- okstra config unset <key> [--scope project|global]
37
- Remove the key from the chosen scope.
38
-
39
- okstra config show [--scope project|global|all]
40
- Dump every okstra-managed key from the chosen scope as JSON.
41
-
42
- Common options:
43
- --cwd <dir> Search starting point for project root (default: pwd)
44
- --json Force JSON output for get/show (default for show)
45
- --quiet Suppress informational stdout on set/unset; exit
46
- code alone reports success
47
- `;
48
-
49
- // CLI-key -> { jsonField, scopes, validate }
50
- // validate(value, ctx) returns null on success or an error string.
51
- const KEYS = {
52
- "pr-template-path": {
53
- jsonField: "prTemplatePath",
54
- scopes: ["project", "global"],
55
- validate(value, ctx) {
56
- if (typeof value !== "string" || value.trim() === "") {
57
- return "value must be a non-empty path";
58
- }
59
- const v = value.trim();
60
- if (ctx.scope === "global") {
61
- if (!v.startsWith("~/") && !v.startsWith("~\\") && !isAbsolute(v)) {
62
- return (
63
- "global scope requires an absolute path or '~/'-prefixed path " +
64
- `(got ${JSON.stringify(v)}). Use --scope project for project-root-relative paths.`
65
- );
66
- }
67
- }
68
- return null;
69
- },
70
- },
71
- "report-language": {
72
- jsonField: "reportLanguage",
73
- scopes: ["project", "global"],
74
- validate(value) {
75
- const allowed = new Set(["en", "ko", "auto"]);
76
- if (typeof value !== "string" || !allowed.has(value)) {
77
- return (
78
- `value must be one of: en, ko, auto (got ${JSON.stringify(value)})`
79
- );
80
- }
81
- return null;
82
- },
83
- },
84
- };
85
-
86
- function parseArgs(args) {
87
- const opts = {
88
- op: null,
89
- key: null,
90
- value: null,
91
- scope: null,
92
- cwd: process.cwd(),
93
- json: false,
94
- quiet: false,
95
- };
96
- const positional = [];
97
- for (let i = 0; i < args.length; i++) {
98
- const a = args[i];
99
- if (a === "--scope") {
100
- const next = args[i + 1];
101
- if (!next) throw new Error("--scope requires a value (project|global|all)");
102
- opts.scope = next;
103
- i++;
104
- } else if (a === "--cwd") {
105
- const next = args[i + 1];
106
- if (!next) throw new Error("--cwd requires a path");
107
- opts.cwd = next;
108
- i++;
109
- } else if (a === "--json") {
110
- opts.json = true;
111
- } else if (a === "--quiet" || a === "-q") {
112
- opts.quiet = true;
113
- } else if (a.startsWith("--")) {
114
- throw new Error(`unknown flag ${a}`);
115
- } else {
116
- positional.push(a);
117
- }
118
- }
119
- opts.op = positional[0] ?? null;
120
- opts.key = positional[1] ?? null;
121
- opts.value = positional[2] ?? null;
122
- return opts;
123
- }
124
-
125
- function okstraHome() {
126
- return resolveOkstraHome();
127
- }
128
-
129
- function globalConfigPath() {
130
- return join(okstraHome(), "config.json");
131
- }
132
-
133
- function projectConfigPath(projectRoot) {
134
- return projectJsonPath(projectRoot);
135
- }
136
-
137
- async function readJson(p) {
138
- if (!(await fileExists(p))) return null;
139
- const text = await fs.readFile(p, "utf8");
140
- try {
141
- const data = JSON.parse(text);
142
- return typeof data === "object" && data !== null ? data : {};
143
- } catch (err) {
144
- throw new Error(`failed to parse ${p}: ${err.message}`);
145
- }
146
- }
147
-
148
- async function writeJsonAtomic(p, data) {
149
- await fs.mkdir(dirname(p), { recursive: true });
150
- const tmp = `${p}.tmp.${process.pid}`;
151
- await fs.writeFile(tmp, JSON.stringify(data, null, 2) + "\n", "utf8");
152
- await fs.rename(tmp, p);
153
- }
154
-
155
- async function resolveProjectRoot(cwd) {
156
- const paths = await resolvePaths();
157
- const result = await runProcess(
158
- "python3",
159
- [
160
- "-c",
161
- [
162
- "import sys",
163
- "from okstra_project import resolve_project_root, ResolverError",
164
- "try:",
165
- " print(resolve_project_root(explicit_root='', cwd=sys.argv[1]))",
166
- "except ResolverError as e:",
167
- " sys.stderr.write(str(e)+'\\n'); sys.exit(2)",
168
- ].join("\n"),
169
- cwd,
170
- ],
171
- { PYTHONPATH: buildPythonpath(paths) },
172
- );
173
- if (result.code === 0) return result.stdout.trim();
174
- return null;
175
- }
176
-
177
- function emit(opts, payload) {
178
- if (opts.quiet) return;
179
- if (opts.json || typeof payload !== "string") {
180
- process.stdout.write(JSON.stringify(payload, null, 2) + "\n");
181
- } else {
182
- process.stdout.write(`${payload}\n`);
183
- }
184
- }
185
-
186
- async function effectivePrTemplatePath(projectRoot) {
187
- // Mirror the python resolver order without depending on it for the simple
188
- // case where we just want to surface the chain in 'config get --scope all'.
189
- // Python remains the source of truth at run time; this is informational.
190
- const paths = await resolvePaths();
191
- const result = await runProcess(
192
- "python3",
193
- [
194
- "-c",
195
- [
196
- "import json, sys",
197
- "from pathlib import Path",
198
- "from okstra_ctl.pr_template import resolve_pr_template_path, PrTemplateError",
199
- "try:",
200
- " r = resolve_pr_template_path(Path(sys.argv[1]))",
201
- " print(json.dumps({'ok': True, 'path': str(r.path), 'source': r.source}))",
202
- "except PrTemplateError as e:",
203
- " print(json.dumps({'ok': False, 'reason': str(e)}))",
204
- ].join("\n"),
205
- projectRoot ?? process.cwd(),
206
- ],
207
- { PYTHONPATH: buildPythonpath(paths) },
208
- );
209
- if (result.code !== 0) return null;
210
- try {
211
- return JSON.parse(result.stdout.trim());
212
- } catch {
213
- return null;
214
- }
215
- }
216
-
217
- async function opGet(opts) {
218
- const spec = KEYS[opts.key];
219
- const scope = opts.scope ?? "all";
220
- const projectRoot = await resolveProjectRoot(opts.cwd);
221
-
222
- const out = {};
223
- if (scope === "project" || scope === "all") {
224
- if (!projectRoot) {
225
- out.project = { available: false, reason: "cwd not inside an okstra project" };
226
- } else {
227
- const cfg = (await readJson(projectConfigPath(projectRoot))) ?? {};
228
- out.project = {
229
- available: true,
230
- path: projectConfigPath(projectRoot),
231
- value: cfg[spec.jsonField] ?? null,
232
- };
233
- }
234
- }
235
- if (scope === "global" || scope === "all") {
236
- const cfg = (await readJson(globalConfigPath())) ?? {};
237
- out.global = {
238
- available: true,
239
- path: globalConfigPath(),
240
- value: cfg[spec.jsonField] ?? null,
241
- };
242
- }
243
-
244
- if (scope === "all" && opts.key === "pr-template-path") {
245
- const effective = await effectivePrTemplatePath(projectRoot);
246
- if (effective) out.effective = effective;
247
- }
248
-
249
- if (scope !== "all" && !opts.json) {
250
- const entry = out[scope];
251
- if (entry?.available && entry.value !== null) {
252
- emit(opts, entry.value);
253
- } else {
254
- emit(opts, "");
255
- }
256
- return 0;
257
- }
258
- emit(opts, out);
259
- return 0;
260
- }
261
-
262
- async function opSet(opts) {
263
- const spec = KEYS[opts.key];
264
- if (opts.value === null) throw new Error(`'config set ${opts.key}' requires a value argument`);
265
- let scope = opts.scope;
266
- const projectRoot = await resolveProjectRoot(opts.cwd);
267
- if (!scope) {
268
- scope = projectRoot ? "project" : null;
269
- if (!scope) {
270
- throw new Error(
271
- "--scope is required when cwd is not inside an okstra project. " +
272
- "Pass --scope project or --scope global.",
273
- );
274
- }
275
- }
276
- if (!spec.scopes.includes(scope)) {
277
- throw new Error(`key '${opts.key}' does not support scope '${scope}'`);
278
- }
279
- const ctx = { scope, projectRoot };
280
- const err = spec.validate(opts.value, ctx);
281
- if (err) throw new Error(err);
282
-
283
- if (scope === "project" && !projectRoot) {
284
- throw new Error("cwd not inside an okstra project — cannot write project scope");
285
- }
286
- const targetPath =
287
- scope === "project" ? projectConfigPath(projectRoot) : globalConfigPath();
288
- const existing = (await readJson(targetPath)) ?? {};
289
- existing[spec.jsonField] = opts.value;
290
- await writeJsonAtomic(targetPath, existing);
291
- emit(opts, { ok: true, scope, path: targetPath, key: opts.key, value: opts.value });
292
- return 0;
293
- }
294
-
295
- async function opUnset(opts) {
296
- const spec = KEYS[opts.key];
297
- let scope = opts.scope;
298
- const projectRoot = await resolveProjectRoot(opts.cwd);
299
- if (!scope) {
300
- scope = projectRoot ? "project" : null;
301
- if (!scope) throw new Error("--scope is required (project|global)");
302
- }
303
- if (scope === "project" && !projectRoot) {
304
- throw new Error("cwd not inside an okstra project — cannot unset project scope");
305
- }
306
- const targetPath =
307
- scope === "project" ? projectConfigPath(projectRoot) : globalConfigPath();
308
- const existing = (await readJson(targetPath)) ?? {};
309
- if (!(spec.jsonField in existing)) {
310
- emit(opts, { ok: true, scope, path: targetPath, key: opts.key, removed: false });
311
- return 0;
312
- }
313
- delete existing[spec.jsonField];
314
- await writeJsonAtomic(targetPath, existing);
315
- emit(opts, { ok: true, scope, path: targetPath, key: opts.key, removed: true });
316
- return 0;
317
- }
318
-
319
- async function opShow(opts) {
320
- const scope = opts.scope ?? "all";
321
- const projectRoot = await resolveProjectRoot(opts.cwd);
322
- const out = {};
323
- if (scope === "project" || scope === "all") {
324
- out.project = projectRoot
325
- ? {
326
- path: projectConfigPath(projectRoot),
327
- data: (await readJson(projectConfigPath(projectRoot))) ?? {},
328
- }
329
- : { available: false, reason: "cwd not inside an okstra project" };
330
- }
331
- if (scope === "global" || scope === "all") {
332
- out.global = {
333
- path: globalConfigPath(),
334
- data: (await readJson(globalConfigPath())) ?? {},
335
- };
336
- }
337
- emit({ ...opts, json: true }, out);
338
- return 0;
339
- }
340
-
341
- export async function run(args) {
342
- if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
343
- process.stdout.write(USAGE);
344
- return args.length === 0 ? 2 : 0;
345
- }
346
- const opts = parseArgs(args);
347
- if (!opts.op) {
348
- process.stderr.write("missing subcommand (get|set|unset|show)\n");
349
- return 2;
350
- }
351
- if (opts.scope !== null && !["project", "global", "all"].includes(opts.scope)) {
352
- process.stderr.write(`invalid --scope: ${opts.scope}\n`);
353
- return 2;
354
- }
355
- if (["get", "set", "unset"].includes(opts.op)) {
356
- if (!opts.key) {
357
- process.stderr.write(`'config ${opts.op}' requires a key argument\n`);
358
- return 2;
359
- }
360
- if (!KEYS[opts.key]) {
361
- process.stderr.write(
362
- `unknown key '${opts.key}'. Supported: ${Object.keys(KEYS).join(", ")}\n`,
363
- );
364
- return 2;
365
- }
366
- }
367
- try {
368
- switch (opts.op) {
369
- case "get":
370
- return await opGet(opts);
371
- case "set":
372
- return await opSet(opts);
373
- case "unset":
374
- return await opUnset(opts);
375
- case "show":
376
- return await opShow(opts);
377
- default:
378
- process.stderr.write(`unknown subcommand '${opts.op}'\n`);
379
- return 2;
380
- }
381
- } catch (err) {
382
- process.stderr.write(`error: ${err.message}\n`);
383
- return 1;
384
- }
385
- }