okstra 0.174.0 → 0.176.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.
- package/README.md +18 -9
- package/bin/okstra +8 -4
- package/dist/cli-registry.d.mts +16 -0
- package/dist/cli-registry.mjs +560 -0
- package/dist/cli-registry.mjs.map +1 -0
- package/dist/commands/execute/agent-prompt.d.mts +1 -0
- package/{src → dist}/commands/execute/agent-prompt.mjs +10 -11
- package/dist/commands/execute/agent-prompt.mjs.map +1 -0
- package/dist/commands/execute/codex-dispatch.d.mts +3 -0
- package/dist/commands/execute/codex-dispatch.mjs +6 -0
- package/dist/commands/execute/codex-dispatch.mjs.map +1 -0
- package/dist/commands/execute/codex-run.d.mts +3 -0
- package/{src → dist}/commands/execute/codex-run.mjs +30 -37
- package/dist/commands/execute/codex-run.mjs.map +1 -0
- package/dist/commands/execute/convergence.d.mts +1 -0
- package/{src → dist}/commands/execute/convergence.mjs +15 -16
- package/dist/commands/execute/convergence.mjs.map +1 -0
- package/dist/commands/execute/error-log.d.mts +1 -0
- package/{src → dist}/commands/execute/error-log.mjs +2 -3
- package/dist/commands/execute/error-log.mjs.map +1 -0
- package/dist/commands/execute/git-reconcile.d.mts +1 -0
- package/{src → dist}/commands/execute/git-reconcile.mjs +10 -11
- package/dist/commands/execute/git-reconcile.mjs.map +1 -0
- package/dist/commands/execute/handoff.d.mts +1 -0
- package/{src → dist}/commands/execute/handoff.mjs +10 -11
- package/dist/commands/execute/handoff.mjs.map +1 -0
- package/dist/commands/execute/incremental-carry.d.mts +1 -0
- package/{src → dist}/commands/execute/incremental-carry.mjs +2 -3
- package/dist/commands/execute/incremental-carry.mjs.map +1 -0
- package/dist/commands/execute/incremental-scope.d.mts +1 -0
- package/{src → dist}/commands/execute/incremental-scope.mjs +2 -3
- package/dist/commands/execute/incremental-scope.mjs.map +1 -0
- package/dist/commands/execute/integrate-stages.d.mts +1 -0
- package/{src → dist}/commands/execute/integrate-stages.mjs +10 -11
- package/dist/commands/execute/integrate-stages.mjs.map +1 -0
- package/dist/commands/execute/pane-title.d.mts +1 -0
- package/dist/commands/execute/pane-title.mjs +20 -0
- package/dist/commands/execute/pane-title.mjs.map +1 -0
- package/dist/commands/execute/plan-items.d.mts +1 -0
- package/dist/commands/execute/plan-items.mjs +9 -0
- package/dist/commands/execute/plan-items.mjs.map +1 -0
- package/dist/commands/execute/plan-validate.d.mts +1 -0
- package/dist/commands/execute/plan-validate.mjs +68 -0
- package/dist/commands/execute/plan-validate.mjs.map +1 -0
- package/dist/commands/execute/plan-verify.d.mts +1 -0
- package/{src → dist}/commands/execute/plan-verify.mjs +13 -16
- package/dist/commands/execute/plan-verify.mjs.map +1 -0
- package/dist/commands/execute/render-bundle.d.mts +3 -0
- package/{src → dist}/commands/execute/render-bundle.mjs +65 -61
- package/dist/commands/execute/render-bundle.mjs.map +1 -0
- package/dist/commands/execute/run.d.mts +24 -0
- package/dist/commands/execute/run.mjs +196 -0
- package/dist/commands/execute/run.mjs.map +1 -0
- package/dist/commands/execute/spawn-followups.d.mts +1 -0
- package/{src → dist}/commands/execute/spawn-followups.mjs +6 -7
- package/dist/commands/execute/spawn-followups.mjs.map +1 -0
- package/dist/commands/execute/team.d.mts +3 -0
- package/{src → dist}/commands/execute/team.mjs +29 -36
- package/dist/commands/execute/team.mjs.map +1 -0
- package/dist/commands/execute/token-usage.d.mts +1 -0
- package/{src → dist}/commands/execute/token-usage.mjs +2 -3
- package/dist/commands/execute/token-usage.mjs.map +1 -0
- package/dist/commands/execute/wizard.d.mts +8 -0
- package/dist/commands/execute/wizard.mjs +191 -0
- package/dist/commands/execute/wizard.mjs.map +1 -0
- package/dist/commands/execute/worker-audit-check.d.mts +1 -0
- package/{src → dist}/commands/execute/worker-audit-check.mjs +11 -12
- package/dist/commands/execute/worker-audit-check.mjs.map +1 -0
- package/dist/commands/execute/worker-dispatch.d.mts +7 -0
- package/{src → dist}/commands/execute/worker-dispatch.mjs +34 -46
- package/dist/commands/execute/worker-dispatch.mjs.map +1 -0
- package/dist/commands/execute/worker-state.d.mts +1 -0
- package/{src → dist}/commands/execute/worker-state.mjs +15 -16
- package/dist/commands/execute/worker-state.mjs.map +1 -0
- package/dist/commands/execute/worktree-lookup.d.mts +1 -0
- package/{src → dist}/commands/execute/worktree-lookup.mjs +38 -37
- package/dist/commands/execute/worktree-lookup.mjs.map +1 -0
- package/dist/commands/execute/worktree-status.d.mts +1 -0
- package/{src → dist}/commands/execute/worktree-status.mjs +52 -46
- package/dist/commands/execute/worktree-status.mjs.map +1 -0
- package/dist/commands/inspect/code-review.d.mts +1 -0
- package/{src → dist}/commands/inspect/code-review.mjs +16 -19
- package/dist/commands/inspect/code-review.mjs.map +1 -0
- package/dist/commands/inspect/container.d.mts +1 -0
- package/{src → dist}/commands/inspect/container.mjs +11 -13
- package/dist/commands/inspect/container.mjs.map +1 -0
- package/dist/commands/inspect/context-cost.d.mts +1 -0
- package/{src → dist}/commands/inspect/context-cost.mjs +11 -13
- package/dist/commands/inspect/context-cost.mjs.map +1 -0
- package/dist/commands/inspect/design-prep.d.mts +1 -0
- package/{src → dist}/commands/inspect/design-prep.mjs +10 -11
- package/dist/commands/inspect/design-prep.mjs.map +1 -0
- package/dist/commands/inspect/error-report.d.mts +1 -0
- package/{src → dist}/commands/inspect/error-report.mjs +11 -13
- package/dist/commands/inspect/error-report.mjs.map +1 -0
- package/dist/commands/inspect/error-zip.d.mts +1 -0
- package/{src → dist}/commands/inspect/error-zip.mjs +11 -12
- package/dist/commands/inspect/error-zip.mjs.map +1 -0
- package/dist/commands/inspect/log-report.d.mts +1 -0
- package/{src → dist}/commands/inspect/log-report.mjs +11 -13
- package/dist/commands/inspect/log-report.mjs.map +1 -0
- package/dist/commands/inspect/profile-show.d.mts +1 -0
- package/{src → dist}/commands/inspect/profile-show.mjs +10 -11
- package/dist/commands/inspect/profile-show.mjs.map +1 -0
- package/dist/commands/inspect/recap.d.mts +1 -0
- package/{src → dist}/commands/inspect/recap.mjs +11 -13
- package/dist/commands/inspect/recap.mjs.map +1 -0
- package/dist/commands/inspect/resolve-task-key.d.mts +1 -0
- package/{src → dist}/commands/inspect/resolve-task-key.mjs +11 -13
- package/dist/commands/inspect/resolve-task-key.mjs.map +1 -0
- package/dist/commands/inspect/rollup.d.mts +1 -0
- package/{src → dist}/commands/inspect/rollup.mjs +11 -13
- package/dist/commands/inspect/rollup.mjs.map +1 -0
- package/dist/commands/inspect/run-audit.d.mts +1 -0
- package/{src → dist}/commands/inspect/run-audit.mjs +11 -12
- package/dist/commands/inspect/run-audit.mjs.map +1 -0
- package/dist/commands/inspect/set-work-status.d.mts +1 -0
- package/{src → dist}/commands/inspect/set-work-status.mjs +11 -13
- package/dist/commands/inspect/set-work-status.mjs.map +1 -0
- package/dist/commands/inspect/stage-map.d.mts +1 -0
- package/dist/commands/inspect/stage-map.mjs +110 -0
- package/dist/commands/inspect/stage-map.mjs.map +1 -0
- package/dist/commands/inspect/task-list.d.mts +1 -0
- package/dist/commands/inspect/task-list.mjs +103 -0
- package/dist/commands/inspect/task-list.mjs.map +1 -0
- package/dist/commands/inspect/task-show.d.mts +1 -0
- package/dist/commands/inspect/task-show.mjs +108 -0
- package/dist/commands/inspect/task-show.mjs.map +1 -0
- package/dist/commands/inspect/time-report.d.mts +1 -0
- package/{src → dist}/commands/inspect/time-report.mjs +11 -13
- package/dist/commands/inspect/time-report.mjs.map +1 -0
- package/dist/commands/inspect/usage-report.d.mts +1 -0
- package/{src → dist}/commands/inspect/usage-report.mjs +11 -13
- package/dist/commands/inspect/usage-report.mjs.map +1 -0
- package/dist/commands/inspect/user-response.d.mts +1 -0
- package/{src → dist}/commands/inspect/user-response.mjs +10 -11
- package/dist/commands/inspect/user-response.mjs.map +1 -0
- package/dist/commands/inspect/worker-liveness.d.mts +1 -0
- package/{src → dist}/commands/inspect/worker-liveness.mjs +11 -13
- package/dist/commands/inspect/worker-liveness.mjs.map +1 -0
- package/dist/commands/lifecycle/check-project.d.mts +21 -0
- package/dist/commands/lifecycle/check-project.mjs +175 -0
- package/dist/commands/lifecycle/check-project.mjs.map +1 -0
- package/dist/commands/lifecycle/config.d.mts +1 -0
- package/dist/commands/lifecycle/config.mjs +369 -0
- package/dist/commands/lifecycle/config.mjs.map +1 -0
- package/dist/commands/lifecycle/doctor.d.mts +10 -0
- package/dist/commands/lifecycle/doctor.mjs +317 -0
- package/dist/commands/lifecycle/doctor.mjs.map +1 -0
- package/dist/commands/lifecycle/install.d.mts +17 -0
- package/dist/commands/lifecycle/install.mjs +1077 -0
- package/dist/commands/lifecycle/install.mjs.map +1 -0
- package/dist/commands/lifecycle/migrate.d.mts +1 -0
- package/{src → dist}/commands/lifecycle/migrate.mjs +10 -11
- package/dist/commands/lifecycle/migrate.mjs.map +1 -0
- package/dist/commands/lifecycle/model.d.mts +1 -0
- package/dist/commands/lifecycle/model.mjs +22 -0
- package/dist/commands/lifecycle/model.mjs.map +1 -0
- package/dist/commands/lifecycle/paths.d.mts +1 -0
- package/dist/commands/lifecycle/paths.mjs +102 -0
- package/dist/commands/lifecycle/paths.mjs.map +1 -0
- package/dist/commands/lifecycle/preflight.d.mts +1 -0
- package/dist/commands/lifecycle/preflight.mjs +124 -0
- package/dist/commands/lifecycle/preflight.mjs.map +1 -0
- package/dist/commands/lifecycle/setup.d.mts +1 -0
- package/dist/commands/lifecycle/setup.mjs +297 -0
- package/dist/commands/lifecycle/setup.mjs.map +1 -0
- package/dist/commands/lifecycle/uninstall.d.mts +4 -0
- package/dist/commands/lifecycle/uninstall.mjs +262 -0
- package/dist/commands/lifecycle/uninstall.mjs.map +1 -0
- package/dist/commands/manager.d.mts +3 -0
- package/{src → dist}/commands/manager.mjs +25 -32
- package/dist/commands/manager.mjs.map +1 -0
- package/dist/commands/memory/memory.d.mts +1 -0
- package/dist/commands/memory/memory.mjs +569 -0
- package/dist/commands/memory/memory.mjs.map +1 -0
- package/dist/commands/pr/pr.d.mts +33 -0
- package/dist/commands/pr/pr.mjs +296 -0
- package/dist/commands/pr/pr.mjs.map +1 -0
- package/dist/commands/report/agent-activity.d.mts +1 -0
- package/{src → dist}/commands/report/agent-activity.mjs +11 -12
- package/dist/commands/report/agent-activity.mjs.map +1 -0
- package/dist/commands/report/finalize.d.mts +4 -0
- package/{src → dist}/commands/report/finalize.mjs +25 -32
- package/dist/commands/report/finalize.mjs.map +1 -0
- package/dist/commands/report/inject-report-index.d.mts +1 -0
- package/{src → dist}/commands/report/inject-report-index.mjs +6 -7
- package/dist/commands/report/inject-report-index.mjs.map +1 -0
- package/dist/commands/report/render-final-report.d.mts +1 -0
- package/{src → dist}/commands/report/render-final-report.mjs +6 -7
- package/dist/commands/report/render-final-report.mjs.map +1 -0
- package/dist/commands/report/render-views.d.mts +1 -0
- package/{src → dist}/commands/report/render-views.mjs +6 -7
- package/dist/commands/report/render-views.mjs.map +1 -0
- package/dist/commands/report/translate.d.mts +1 -0
- package/{src → dist}/commands/report/translate.mjs +6 -7
- package/dist/commands/report/translate.mjs.map +1 -0
- package/dist/lib/helper-scripts.d.mts +3 -0
- package/{src → dist}/lib/helper-scripts.mjs +11 -14
- package/dist/lib/helper-scripts.mjs.map +1 -0
- package/dist/lib/host-registry-client.d.mts +25 -0
- package/dist/lib/host-registry-client.mjs +152 -0
- package/dist/lib/host-registry-client.mjs.map +1 -0
- package/dist/lib/install-assets.d.mts +8 -0
- package/{src → dist}/lib/install-assets.mjs +17 -20
- package/dist/lib/install-assets.mjs.map +1 -0
- package/dist/lib/okstra-dirs.d.mts +4 -0
- package/{src → dist}/lib/okstra-dirs.mjs +3 -6
- package/dist/lib/okstra-dirs.mjs.map +1 -0
- package/dist/lib/paths.d.mts +4 -0
- package/dist/lib/paths.mjs +78 -0
- package/dist/lib/paths.mjs.map +1 -0
- package/dist/lib/proc.d.mts +3 -0
- package/dist/lib/proc.mjs +31 -0
- package/dist/lib/proc.mjs.map +1 -0
- package/dist/lib/python-helper.d.mts +8 -0
- package/dist/lib/python-helper.mjs +123 -0
- package/dist/lib/python-helper.mjs.map +1 -0
- package/dist/lib/runtime-manifest.d.mts +7 -0
- package/dist/lib/runtime-manifest.mjs +73 -0
- package/dist/lib/runtime-manifest.mjs.map +1 -0
- package/dist/lib/skill-catalog.d.mts +4 -0
- package/dist/lib/skill-catalog.mjs +50 -0
- package/dist/lib/skill-catalog.mjs.map +1 -0
- package/dist/lib/types.d.mts +129 -0
- package/dist/lib/types.mjs +2 -0
- package/dist/lib/types.mjs.map +1 -0
- package/dist/lib/version.d.mts +2 -0
- package/dist/lib/version.mjs +27 -0
- package/dist/lib/version.mjs.map +1 -0
- package/docs/architecture/storage-model.md +6 -2
- package/docs/architecture.md +29 -20
- package/docs/cli.md +40 -16
- package/docs/contributor-change-matrix.md +2 -2
- package/docs/for-ai/skills/okstra-inspect.md +2 -3
- package/docs/for-ai/skills/okstra-rollup.md +1 -0
- package/docs/project-structure-overview.md +72 -62
- package/docs/task-process/README.md +12 -8
- package/docs/task-process/common-flow.md +13 -16
- package/docs/task-process/error-analysis.md +9 -10
- package/docs/task-process/final-verification.md +7 -7
- package/docs/task-process/implementation-planning.md +9 -9
- package/docs/task-process/implementation.md +6 -6
- package/docs/task-process/release-handoff.md +8 -7
- package/docs/task-process/requirements-discovery.md +8 -8
- package/package.json +11 -5
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +2 -1
- package/runtime/agents/workers/report-writer-worker.md +3 -1
- package/runtime/agents/workers/translator-worker.md +3 -1
- package/runtime/bin/lib/okstra/cli.sh +12 -0
- package/runtime/bin/lib/okstra/globals.sh +3 -0
- package/runtime/bin/lib/okstra/interactive.sh +12 -6
- package/runtime/bin/lib/okstra/usage.sh +7 -6
- package/runtime/bin/okstra-error-log.py +27 -0
- package/runtime/bin/okstra-provider-exec.py +217 -5
- package/runtime/bin/okstra-spawn-followups.py +4 -2
- package/runtime/bin/okstra.sh +10 -0
- package/runtime/prompts/launch.template.md +2 -2
- package/runtime/prompts/lead/context-loader.md +1 -2
- package/runtime/prompts/lead/convergence.md +27 -18
- package/runtime/prompts/lead/okstra-lead-contract.md +6 -5
- package/runtime/prompts/lead/plan-body-verification.md +10 -3
- package/runtime/prompts/lead/report-writer.md +15 -1
- package/runtime/prompts/lead/team-contract.md +17 -13
- package/runtime/prompts/profiles/_implementation-deliverable.md +1 -1
- package/runtime/prompts/profiles/_implementation-executor.md +0 -3
- package/runtime/prompts/profiles/_implementation-verifier.md +3 -7
- package/runtime/prompts/profiles/change-impact-analysis.md +20 -0
- package/runtime/prompts/profiles/error-analysis.md +27 -1
- package/runtime/prompts/profiles/feature-analysis.md +20 -0
- package/runtime/prompts/profiles/final-verification.md +20 -1
- package/runtime/prompts/profiles/implementation-option-selection.md +20 -0
- package/runtime/prompts/profiles/implementation-planning.md +26 -0
- package/runtime/prompts/profiles/implementation.md +19 -0
- package/runtime/prompts/profiles/improvement-discovery.md +21 -1
- package/runtime/prompts/profiles/project-analysis.md +20 -0
- package/runtime/prompts/profiles/release-handoff.md +4 -0
- package/runtime/prompts/profiles/requirements-discovery.md +27 -1
- package/runtime/prompts/wizard/prompts.ko.json +35 -0
- package/runtime/python/okstra_ctl/adapters/dispatch/cli_wrapper.py +8 -0
- package/runtime/python/okstra_ctl/adapters/dispatch/cmux.py +8 -0
- package/runtime/python/okstra_ctl/adapters/dispatch/native_team.py +13 -0
- package/runtime/python/okstra_ctl/adapters/hosts/antigravity/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +25 -5
- package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/hosts/external/adapter.py +4 -1
- package/runtime/python/okstra_ctl/adapters/hosts/grok/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/hosts/kimi/adapter.py +2 -2
- package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +79 -11
- package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +95 -25
- package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +59 -14
- package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +55 -9
- package/runtime/python/okstra_ctl/adapters/providers/kimi/adapter.py +51 -12
- package/runtime/python/okstra_ctl/adapters/runtime/__init__.py +1 -0
- package/runtime/python/okstra_ctl/adapters/runtime/assembly.py +27 -0
- package/runtime/python/okstra_ctl/adapters/runtime/cli_wrapper.py +49 -0
- package/runtime/python/okstra_ctl/adapters/runtime/cmux.py +74 -0
- package/runtime/python/okstra_ctl/agent_activity.py +5 -1
- package/runtime/python/okstra_ctl/agent_invocation.py +608 -14
- package/runtime/python/okstra_ctl/agent_prompt_cli.py +249 -50
- package/runtime/python/okstra_ctl/application/open_worker.py +29 -0
- package/runtime/python/okstra_ctl/application/resolve_assignment.py +53 -12
- package/runtime/python/okstra_ctl/assignment_environment.py +102 -0
- package/runtime/python/okstra_ctl/assignment_resolver.py +790 -0
- package/runtime/python/okstra_ctl/attempt_evidence.py +342 -0
- package/runtime/python/okstra_ctl/convergence.py +409 -3
- package/runtime/python/okstra_ctl/convergence_engine.py +248 -15
- package/runtime/python/okstra_ctl/convergence_store.py +170 -1
- package/runtime/python/okstra_ctl/dispatch_core.py +1204 -155
- package/runtime/python/okstra_ctl/dispatch_state.py +696 -11
- package/runtime/python/okstra_ctl/doctor.py +14 -0
- package/runtime/python/okstra_ctl/domain/host.py +34 -1
- package/runtime/python/okstra_ctl/domain/provider.py +212 -6
- package/runtime/python/okstra_ctl/domain/role.py +125 -0
- package/runtime/python/okstra_ctl/domain/wizard/interaction.py +18 -0
- package/runtime/python/okstra_ctl/domain/worker_exec.py +34 -1
- package/runtime/python/okstra_ctl/domain/worker_role.py +13 -3
- package/runtime/python/okstra_ctl/domain/worker_runtime.py +44 -0
- package/runtime/python/okstra_ctl/domain/worker_stream.py +24 -0
- package/runtime/python/okstra_ctl/error_log_write.py +9 -0
- package/runtime/python/okstra_ctl/error_report.py +21 -1
- package/runtime/python/okstra_ctl/execution_identity.py +529 -0
- package/runtime/python/okstra_ctl/execution_manifest.py +1281 -0
- package/runtime/python/okstra_ctl/execution_mutation_audit.py +619 -0
- package/runtime/python/okstra_ctl/implementation_outcome.py +21 -5
- package/runtime/python/okstra_ctl/index.py +6 -2
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +43 -3
- package/runtime/python/okstra_ctl/legacy_model_selection.py +578 -0
- package/runtime/python/okstra_ctl/manager_sync.py +4 -1
- package/runtime/python/okstra_ctl/model_cli.py +278 -0
- package/runtime/python/okstra_ctl/model_defaults.py +46 -0
- package/runtime/python/okstra_ctl/model_discovery.py +26 -7
- package/runtime/python/okstra_ctl/model_pool.py +501 -0
- package/runtime/python/okstra_ctl/models.py +47 -27
- package/runtime/python/okstra_ctl/mutation_recovery.py +293 -0
- package/runtime/python/okstra_ctl/next_phase.py +236 -0
- package/runtime/python/okstra_ctl/pane_title.py +151 -0
- package/runtime/python/okstra_ctl/ports/host_model.py +48 -17
- package/runtime/python/okstra_ctl/ports/worker_dispatch.py +4 -0
- package/runtime/python/okstra_ctl/ports/worker_runtime.py +26 -0
- package/runtime/python/okstra_ctl/recap.py +4 -1
- package/runtime/python/okstra_ctl/registry/provider_registry.py +8 -4
- package/runtime/python/okstra_ctl/render.py +124 -57
- package/runtime/python/okstra_ctl/render_final_report.py +19 -0
- package/runtime/python/okstra_ctl/report_contract.py +39 -0
- package/runtime/python/okstra_ctl/report_finalize.py +16 -0
- package/runtime/python/okstra_ctl/report_html/render.py +1 -0
- package/runtime/python/okstra_ctl/role_requirements.py +210 -0
- package/runtime/python/okstra_ctl/rollup.py +4 -1
- package/runtime/python/okstra_ctl/run.py +1210 -258
- package/runtime/python/okstra_ctl/run_index_row.py +7 -1
- package/runtime/python/okstra_ctl/stage_fix_carry.py +17 -1
- package/runtime/python/okstra_ctl/team.py +14 -18
- package/runtime/python/okstra_ctl/time_report.py +38 -4
- package/runtime/python/okstra_ctl/usage_identity.py +86 -0
- package/runtime/python/okstra_ctl/usage_report.py +15 -3
- package/runtime/python/okstra_ctl/wizard.py +1449 -66
- package/runtime/python/okstra_ctl/worker_audit_ledger.py +68 -65
- package/runtime/python/okstra_ctl/worker_prompt_body.py +18 -2
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +40 -9
- package/runtime/python/okstra_ctl/worker_prompt_headers.py +16 -1
- package/runtime/python/okstra_ctl/worker_request.py +7 -1
- package/runtime/python/okstra_ctl/worker_runner.py +130 -5
- package/runtime/python/okstra_ctl/workers.py +7 -5
- package/runtime/python/okstra_ctl/workflow.py +18 -32
- package/runtime/python/okstra_ctl/worktree.py +3 -3
- package/runtime/python/okstra_ctl/worktree_registry.py +5 -4
- package/runtime/python/okstra_ctl/write_policy.py +571 -0
- package/runtime/python/okstra_project/state.py +54 -6
- package/runtime/schemas/convergence-groups-v2.0.schema.json +128 -0
- package/runtime/schemas/execution-manifest-v2.schema.json +340 -0
- package/runtime/schemas/final-report-v2.0.schema.json +68 -5
- package/runtime/skills/okstra-inspect/facets/recap.md +2 -0
- package/runtime/skills/okstra-inspect/facets/report.md +1 -1
- package/runtime/skills/okstra-inspect/facets/status.md +15 -13
- package/runtime/skills/okstra-rollup/SKILL.md +1 -0
- package/runtime/skills/okstra-run/SKILL.md +14 -14
- package/runtime/templates/implementation-worker-preamble.md +3 -18
- package/runtime/templates/project-docs/task-index.template.md +0 -1
- package/runtime/templates/report-writer-prompt-preamble.md +2 -0
- package/runtime/templates/reports/final-report-v2.template.md +7 -1
- package/runtime/templates/reports/html/base.template.html +21 -0
- package/runtime/templates/reports/html/i18n/en.json +4 -0
- package/runtime/templates/reports/html/i18n/ko.json +4 -0
- package/runtime/templates/reports/html/macros/forms.html +5 -4
- package/runtime/templates/reports/html/tasks/final-verification.template.html +1 -1
- package/runtime/templates/reports/html/tasks/implementation.template.html +1 -1
- package/runtime/templates/worker-prompt-preamble.md +6 -35
- package/runtime/validators/lib/fixtures.sh +49 -16
- package/runtime/validators/validate-run.py +486 -134
- package/runtime/validators/validate_session_conformance.py +25 -7
- package/src/cli-registry.mjs +0 -539
- package/src/commands/execute/codex-dispatch.mjs +0 -10
- package/src/commands/execute/plan-items.mjs +0 -9
- package/src/commands/execute/plan-validate.mjs +0 -68
- package/src/commands/execute/run.mjs +0 -208
- package/src/commands/execute/wizard.mjs +0 -167
- package/src/commands/inspect/stage-map.mjs +0 -98
- package/src/commands/inspect/task-list.mjs +0 -97
- package/src/commands/inspect/task-show.mjs +0 -100
- package/src/commands/lifecycle/check-project.mjs +0 -187
- package/src/commands/lifecycle/config.mjs +0 -385
- package/src/commands/lifecycle/doctor.mjs +0 -308
- package/src/commands/lifecycle/install.mjs +0 -1170
- package/src/commands/lifecycle/paths.mjs +0 -104
- package/src/commands/lifecycle/preflight.mjs +0 -125
- package/src/commands/lifecycle/setup.mjs +0 -333
- package/src/commands/lifecycle/uninstall.mjs +0 -279
- package/src/commands/memory/memory.mjs +0 -524
- package/src/commands/pr/pr.mjs +0 -261
- package/src/lib/host-registry-client.mjs +0 -176
- package/src/lib/paths.mjs +0 -86
- package/src/lib/proc.mjs +0 -31
- package/src/lib/python-helper.mjs +0 -142
- package/src/lib/runtime-manifest.mjs +0 -70
- package/src/lib/skill-catalog.mjs +0 -53
- package/src/lib/version.mjs +0 -20
- /package/{src → dist}/commands/pr/default.md +0 -0
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { resolvePaths } from "../../lib/paths.mjs";
|
|
2
|
-
|
|
3
|
-
const USAGE = `okstra paths — print runtime paths
|
|
4
|
-
|
|
5
|
-
Usage:
|
|
6
|
-
okstra paths Print all paths as JSON
|
|
7
|
-
okstra paths --json Same as the default
|
|
8
|
-
okstra paths --field <key> Print one field as a plain string
|
|
9
|
-
okstra paths --shell Print shell 'export' statements for the
|
|
10
|
-
standard OKSTRA_* env vars (sourced by skills)
|
|
11
|
-
|
|
12
|
-
Fields:
|
|
13
|
-
agents Absolute path to agents/. Default: <workspace>/agents.
|
|
14
|
-
workspace Directory containing prompts/, templates/, validators/,
|
|
15
|
-
agents/. Equals the package's runtime/ directory in copy
|
|
16
|
-
mode, or the dev-link repo path in dev mode.
|
|
17
|
-
pythonpath $HOME/.okstra/lib/python
|
|
18
|
-
bin $HOME/.okstra/bin
|
|
19
|
-
home $HOME/.okstra
|
|
20
|
-
version Installed okstra version (from ~/.okstra/version stamp)
|
|
21
|
-
package Currently invoked package version
|
|
22
|
-
dev-link Repo path recorded by 'okstra install --link <repo>'
|
|
23
|
-
(empty string when not in dev mode).
|
|
24
|
-
|
|
25
|
-
Shell mode exports (variable name -> field):
|
|
26
|
-
OKSTRA_WORKSPACE workspace
|
|
27
|
-
OKSTRA_AGENTS_DIR agents
|
|
28
|
-
OKSTRA_PYTHONPATH pythonpath
|
|
29
|
-
OKSTRA_BIN bin
|
|
30
|
-
OKSTRA_HOME home
|
|
31
|
-
`;
|
|
32
|
-
|
|
33
|
-
const VALID_FIELDS = new Set([
|
|
34
|
-
"agents",
|
|
35
|
-
"workspace",
|
|
36
|
-
"pythonpath",
|
|
37
|
-
"bin",
|
|
38
|
-
"home",
|
|
39
|
-
"version",
|
|
40
|
-
"package",
|
|
41
|
-
"dev-link",
|
|
42
|
-
]);
|
|
43
|
-
|
|
44
|
-
const SHELL_EXPORTS = [
|
|
45
|
-
["OKSTRA_WORKSPACE", "workspace"],
|
|
46
|
-
["OKSTRA_AGENTS_DIR", "agents"],
|
|
47
|
-
["OKSTRA_PYTHONPATH", "pythonpath"],
|
|
48
|
-
["OKSTRA_BIN", "bin"],
|
|
49
|
-
["OKSTRA_HOME", "home"],
|
|
50
|
-
];
|
|
51
|
-
|
|
52
|
-
export async function run(args) {
|
|
53
|
-
if (args.includes("--help") || args.includes("-h")) {
|
|
54
|
-
process.stdout.write(USAGE);
|
|
55
|
-
return 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
let field = null;
|
|
59
|
-
let mode = "json";
|
|
60
|
-
for (let i = 0; i < args.length; i++) {
|
|
61
|
-
const a = args[i];
|
|
62
|
-
if (a === "--json") {
|
|
63
|
-
mode = "json";
|
|
64
|
-
} else if (a === "--shell") {
|
|
65
|
-
mode = "shell";
|
|
66
|
-
} else if (a === "--field") {
|
|
67
|
-
field = args[i + 1];
|
|
68
|
-
i++;
|
|
69
|
-
if (!field) {
|
|
70
|
-
process.stderr.write("error: --field requires a name\n");
|
|
71
|
-
return 2;
|
|
72
|
-
}
|
|
73
|
-
if (!VALID_FIELDS.has(field)) {
|
|
74
|
-
process.stderr.write(`error: unknown field '${field}'. Valid: ${[...VALID_FIELDS].join(", ")}\n`);
|
|
75
|
-
return 2;
|
|
76
|
-
}
|
|
77
|
-
mode = "field";
|
|
78
|
-
} else {
|
|
79
|
-
process.stderr.write(`error: unknown argument '${a}'\n\n${USAGE}`);
|
|
80
|
-
return 2;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const paths = await resolvePaths();
|
|
85
|
-
|
|
86
|
-
if (mode === "field") {
|
|
87
|
-
process.stdout.write(`${paths[field]}\n`);
|
|
88
|
-
return 0;
|
|
89
|
-
}
|
|
90
|
-
if (mode === "shell") {
|
|
91
|
-
for (const [varName, key] of SHELL_EXPORTS) {
|
|
92
|
-
process.stdout.write(`export ${varName}=${shellQuote(paths[key])}\n`);
|
|
93
|
-
}
|
|
94
|
-
return 0;
|
|
95
|
-
}
|
|
96
|
-
process.stdout.write(`${JSON.stringify(paths, null, 2)}\n`);
|
|
97
|
-
return 0;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function shellQuote(value) {
|
|
101
|
-
if (value === "" || value == null) return "''";
|
|
102
|
-
if (/^[A-Za-z0-9_\/.\-+:@%=]+$/.test(value)) return value;
|
|
103
|
-
return `'${String(value).replace(/'/g, "'\\''")}'`;
|
|
104
|
-
}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { checkProject } from "./check-project.mjs";
|
|
2
|
-
import { runEnsureInstalled } from "./install.mjs";
|
|
3
|
-
import { missingHelperScripts } from "../../lib/helper-scripts.mjs";
|
|
4
|
-
import { resolveInstalledScript } from "../../lib/python-helper.mjs";
|
|
5
|
-
import { resolvePaths } from "../../lib/paths.mjs";
|
|
6
|
-
import { checkRuntimeReadiness } from "../../lib/host-registry-client.mjs";
|
|
7
|
-
|
|
8
|
-
const USAGE = `okstra preflight — one-call skill preflight (ensure-installed + check-project)
|
|
9
|
-
|
|
10
|
-
Usage:
|
|
11
|
-
okstra preflight [--runtime <name>] [--cwd <dir>] [--json]
|
|
12
|
-
|
|
13
|
-
Runs the runtime freshness check (quietly reinstalling when stale), then
|
|
14
|
-
verifies the target project has .okstra/project.json. Prints one JSON object:
|
|
15
|
-
|
|
16
|
-
ok: true {ok, projectRoot, projectJsonPath, projectId, runtimeReadiness}
|
|
17
|
-
ok: false {ok, stage, reason, ...}
|
|
18
|
-
stage: install | helper_scripts_missing | resolve |
|
|
19
|
-
project_json_missing | project_json_invalid |
|
|
20
|
-
runtime_readiness | python | parse
|
|
21
|
-
|
|
22
|
-
Options:
|
|
23
|
-
--runtime <name> Runtime whose assets must be present (e.g. claude-code);
|
|
24
|
-
forwarded to ensure-installed.
|
|
25
|
-
--cwd <dir> Resolve PROJECT_ROOT from <dir> instead of process cwd.
|
|
26
|
-
--json Default output format (kept for symmetry).
|
|
27
|
-
|
|
28
|
-
Exit codes:
|
|
29
|
-
0 runtime fresh, project registered, and current host ready
|
|
30
|
-
1 runtime install failed, project setup missing/invalid, or host not ready
|
|
31
|
-
2 PROJECT_ROOT could not be resolved from cwd (pass --cwd), or bad flags
|
|
32
|
-
`;
|
|
33
|
-
|
|
34
|
-
function parseArgs(args) {
|
|
35
|
-
const opts = { cwd: process.cwd(), runtime: null };
|
|
36
|
-
for (let i = 0; i < args.length; i++) {
|
|
37
|
-
const a = args[i];
|
|
38
|
-
if (a === "--json") continue;
|
|
39
|
-
if (a === "--cwd" || a === "--runtime") {
|
|
40
|
-
const next = args[i + 1];
|
|
41
|
-
if (!next || next.startsWith("--")) throw new Error(`${a} requires a value`);
|
|
42
|
-
if (a === "--cwd") opts.cwd = next;
|
|
43
|
-
else opts.runtime = next;
|
|
44
|
-
i++;
|
|
45
|
-
} else {
|
|
46
|
-
throw new Error(`unknown argument '${a}'`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return opts;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function emit(payload) {
|
|
53
|
-
process.stdout.write(JSON.stringify(payload, null, 2) + "\n");
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// A BLOCKING lead step calls these mid-run; resolving them here turns a stale
|
|
57
|
-
// install into an up-front failure instead of a dead end hours into a run.
|
|
58
|
-
async function findMissingHelperScripts() {
|
|
59
|
-
return missingHelperScripts(await resolvePaths(), resolveInstalledScript);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export async function run(args) {
|
|
63
|
-
if (args.includes("--help") || args.includes("-h")) {
|
|
64
|
-
process.stdout.write(USAGE);
|
|
65
|
-
return 0;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
let opts;
|
|
69
|
-
try {
|
|
70
|
-
opts = parseArgs(args);
|
|
71
|
-
} catch (err) {
|
|
72
|
-
process.stderr.write(`error: ${err.message}\n\n${USAGE}`);
|
|
73
|
-
return 2;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const ensureArgs = ["--quiet"];
|
|
77
|
-
if (opts.runtime) ensureArgs.push("--runtime", opts.runtime);
|
|
78
|
-
const installCode = await runEnsureInstalled(ensureArgs);
|
|
79
|
-
if (installCode !== 0) {
|
|
80
|
-
emit({
|
|
81
|
-
ok: false,
|
|
82
|
-
stage: "install",
|
|
83
|
-
reason:
|
|
84
|
-
"okstra runtime install failed — run 'okstra doctor' to diagnose, " +
|
|
85
|
-
"then 'okstra install' to repair.",
|
|
86
|
-
});
|
|
87
|
-
return installCode === 2 ? 2 : 1;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const missingHelpers = await findMissingHelperScripts();
|
|
91
|
-
if (missingHelpers.length > 0) {
|
|
92
|
-
emit({
|
|
93
|
-
ok: false,
|
|
94
|
-
stage: "helper_scripts_missing",
|
|
95
|
-
missingHelpers,
|
|
96
|
-
reason:
|
|
97
|
-
`${missingHelpers.length} helper script(s) a lead prompt can call are not ` +
|
|
98
|
-
"installed — run 'okstra install' to repair before starting a run.",
|
|
99
|
-
});
|
|
100
|
-
return 1;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const { code, payload } = await checkProject({ cwd: opts.cwd });
|
|
104
|
-
if (code !== 0) {
|
|
105
|
-
emit(payload);
|
|
106
|
-
return code;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const runtimeReadiness = await checkRuntimeReadiness({
|
|
110
|
-
runtime: opts.runtime,
|
|
111
|
-
projectRoot: payload.projectRoot,
|
|
112
|
-
});
|
|
113
|
-
if (["blocked", "unknown"].includes(runtimeReadiness.status)) {
|
|
114
|
-
emit({
|
|
115
|
-
...payload,
|
|
116
|
-
ok: false,
|
|
117
|
-
stage: "runtime_readiness",
|
|
118
|
-
reason: `current host readiness is ${runtimeReadiness.status}`,
|
|
119
|
-
runtimeReadiness,
|
|
120
|
-
});
|
|
121
|
-
return 1;
|
|
122
|
-
}
|
|
123
|
-
emit({ ...payload, runtimeReadiness });
|
|
124
|
-
return code;
|
|
125
|
-
}
|
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from "node:fs";
|
|
2
|
-
import { createInterface } from "node:readline";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { join, resolve as resolvePath } from "node:path";
|
|
5
|
-
import { buildPythonpath, resolvePaths } from "../../lib/paths.mjs";
|
|
6
|
-
import { fileExists, runProcess } from "../../lib/proc.mjs";
|
|
7
|
-
|
|
8
|
-
const USAGE = `okstra setup — register the current project with okstra
|
|
9
|
-
|
|
10
|
-
Writes <PROJECT_ROOT>/.okstra/project.json. This is the
|
|
11
|
-
project-level companion to 'okstra install' (which is machine-level).
|
|
12
|
-
Inside a Claude Code session this is also exposed as the /okstra-setup
|
|
13
|
-
slash command.
|
|
14
|
-
|
|
15
|
-
Usage:
|
|
16
|
-
okstra setup --project-id <id> Register with explicit projectId
|
|
17
|
-
okstra setup Use existing project.json or
|
|
18
|
-
prompt for projectId (TTY only)
|
|
19
|
-
okstra setup --project-root <path> Override PROJECT_ROOT resolution
|
|
20
|
-
okstra setup --yes Skip prompts; require all inputs
|
|
21
|
-
on the command line
|
|
22
|
-
|
|
23
|
-
Behavior:
|
|
24
|
-
- If project.json already exists, the projectId must match (okstra refuses
|
|
25
|
-
to silently rename a project). Delete the file manually if you really
|
|
26
|
-
want to change projectId.
|
|
27
|
-
- If --project-id is omitted and stdin is a TTY, you are prompted.
|
|
28
|
-
- If --project-id is omitted and stdin is not a TTY, the command exits
|
|
29
|
-
with an error (use --project-id for CI / scripts).
|
|
30
|
-
|
|
31
|
-
Exit codes:
|
|
32
|
-
0 project.json present and valid after the run
|
|
33
|
-
1 I/O / python failure or projectId mismatch
|
|
34
|
-
2 PROJECT_ROOT could not be resolved
|
|
35
|
-
`;
|
|
36
|
-
|
|
37
|
-
function parseArgs(args) {
|
|
38
|
-
const opts = {
|
|
39
|
-
projectId: null,
|
|
40
|
-
projectRoot: null,
|
|
41
|
-
yes: false,
|
|
42
|
-
};
|
|
43
|
-
for (let i = 0; i < args.length; i++) {
|
|
44
|
-
const a = args[i];
|
|
45
|
-
if (a === "--yes" || a === "-y") opts.yes = true;
|
|
46
|
-
else if (a === "--project-id") {
|
|
47
|
-
const next = args[i + 1];
|
|
48
|
-
if (!next || next.startsWith("--")) throw new Error("--project-id requires a value");
|
|
49
|
-
opts.projectId = next;
|
|
50
|
-
i++;
|
|
51
|
-
} else if (a === "--project-root") {
|
|
52
|
-
const next = args[i + 1];
|
|
53
|
-
if (!next || next.startsWith("--")) throw new Error("--project-root requires a path");
|
|
54
|
-
opts.projectRoot = next;
|
|
55
|
-
i++;
|
|
56
|
-
} else {
|
|
57
|
-
throw new Error(`unknown argument '${a}'`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return opts;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
function prompt(question) {
|
|
65
|
-
return new Promise((resolve) => {
|
|
66
|
-
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
67
|
-
rl.question(question, (answer) => {
|
|
68
|
-
rl.close();
|
|
69
|
-
resolve(answer.trim());
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function validateProjectId(id) {
|
|
75
|
-
if (!id) return "project-id is empty";
|
|
76
|
-
if (!/[A-Za-z0-9]/.test(id)) return "project-id must contain at least one alphanumeric character";
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async function resolveProjectRoot(paths, explicit) {
|
|
81
|
-
const probe = await runProcess(
|
|
82
|
-
"python3",
|
|
83
|
-
[
|
|
84
|
-
"-c",
|
|
85
|
-
[
|
|
86
|
-
"import sys",
|
|
87
|
-
"from okstra_project import resolve_project_root, project_json_path, ResolverError",
|
|
88
|
-
"try:",
|
|
89
|
-
" pr = resolve_project_root(explicit_root=sys.argv[1], cwd=sys.argv[2])",
|
|
90
|
-
" print('PROJECT_ROOT', pr)",
|
|
91
|
-
" print('PROJECT_JSON', project_json_path(pr))",
|
|
92
|
-
"except ResolverError as e:",
|
|
93
|
-
" print('RESOLVER_ERROR', e)",
|
|
94
|
-
].join("\n"),
|
|
95
|
-
explicit || "",
|
|
96
|
-
process.cwd(),
|
|
97
|
-
],
|
|
98
|
-
{ PYTHONPATH: buildPythonpath(paths) },
|
|
99
|
-
);
|
|
100
|
-
if (probe.code !== 0) {
|
|
101
|
-
throw new Error(`python invocation failed: ${probe.stderr.trim() || probe.stdout.trim()}`);
|
|
102
|
-
}
|
|
103
|
-
const lines = probe.stdout.trim().split("\n");
|
|
104
|
-
const tagOf = (key) =>
|
|
105
|
-
lines
|
|
106
|
-
.find((l) => l.startsWith(key + " "))
|
|
107
|
-
?.slice(key.length + 1)
|
|
108
|
-
.trim() ?? null;
|
|
109
|
-
const resolverError = tagOf("RESOLVER_ERROR");
|
|
110
|
-
if (resolverError) {
|
|
111
|
-
const err = new Error(resolverError);
|
|
112
|
-
err.code = "RESOLVER";
|
|
113
|
-
throw err;
|
|
114
|
-
}
|
|
115
|
-
return {
|
|
116
|
-
projectRoot: tagOf("PROJECT_ROOT"),
|
|
117
|
-
projectJsonPath: tagOf("PROJECT_JSON"),
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
async function upsert(paths, projectRoot, projectId) {
|
|
122
|
-
const probe = await runProcess(
|
|
123
|
-
"python3",
|
|
124
|
-
[
|
|
125
|
-
"-c",
|
|
126
|
-
[
|
|
127
|
-
"import json, sys",
|
|
128
|
-
"from pathlib import Path",
|
|
129
|
-
"from okstra_project import upsert_project_json, ResolverError",
|
|
130
|
-
"try:",
|
|
131
|
-
" result = upsert_project_json(Path(sys.argv[1]), sys.argv[2])",
|
|
132
|
-
" print('OK', json.dumps(result))",
|
|
133
|
-
"except ResolverError as e:",
|
|
134
|
-
" print('ERROR', e)",
|
|
135
|
-
].join("\n"),
|
|
136
|
-
projectRoot,
|
|
137
|
-
projectId,
|
|
138
|
-
],
|
|
139
|
-
{ PYTHONPATH: buildPythonpath(paths) },
|
|
140
|
-
);
|
|
141
|
-
if (probe.code !== 0) {
|
|
142
|
-
throw new Error(`python invocation failed: ${probe.stderr.trim() || probe.stdout.trim()}`);
|
|
143
|
-
}
|
|
144
|
-
const out = probe.stdout.trim();
|
|
145
|
-
if (out.startsWith("OK ")) {
|
|
146
|
-
return JSON.parse(out.slice(3));
|
|
147
|
-
}
|
|
148
|
-
if (out.startsWith("ERROR ")) {
|
|
149
|
-
throw new Error(out.slice(6));
|
|
150
|
-
}
|
|
151
|
-
throw new Error(`unexpected upsert output: ${out}`);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export async function run(args) {
|
|
155
|
-
if (args.includes("--help") || args.includes("-h")) {
|
|
156
|
-
process.stdout.write(USAGE);
|
|
157
|
-
return 0;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
let opts;
|
|
161
|
-
try {
|
|
162
|
-
opts = parseArgs(args);
|
|
163
|
-
} catch (err) {
|
|
164
|
-
process.stderr.write(`error: ${err.message}\n\n${USAGE}`);
|
|
165
|
-
return 1;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const paths = await resolvePaths();
|
|
169
|
-
|
|
170
|
-
let resolved;
|
|
171
|
-
try {
|
|
172
|
-
resolved = await resolveProjectRoot(paths, opts.projectRoot);
|
|
173
|
-
} catch (err) {
|
|
174
|
-
if (err.code === "RESOLVER") {
|
|
175
|
-
const cwd = resolvePath(process.cwd());
|
|
176
|
-
const home = resolvePath(homedir());
|
|
177
|
-
const inHome = cwd === home;
|
|
178
|
-
process.stderr.write(
|
|
179
|
-
"error: 'okstra setup' registers the CURRENT directory as an okstra project,\n" +
|
|
180
|
-
" but no project root could be resolved from here.\n" +
|
|
181
|
-
` cwd: ${cwd}\n` +
|
|
182
|
-
(inHome
|
|
183
|
-
? " (this looks like your home directory — setup is project-level, not machine-level;\n" +
|
|
184
|
-
" machine-level install is 'okstra install', which you've likely already done.)\n"
|
|
185
|
-
: "") +
|
|
186
|
-
"\nFix one of:\n" +
|
|
187
|
-
" 1. cd into the project you want to register, then re-run:\n" +
|
|
188
|
-
" cd <your project> && okstra setup --project-id <id>\n" +
|
|
189
|
-
" 2. pass an explicit path:\n" +
|
|
190
|
-
" okstra setup --project-root <abs-path> --project-id <id>\n" +
|
|
191
|
-
" 3. run from inside any git working tree (the toplevel becomes PROJECT_ROOT).\n" +
|
|
192
|
-
`\n(underlying error: ${err.message})\n`,
|
|
193
|
-
);
|
|
194
|
-
return 2;
|
|
195
|
-
}
|
|
196
|
-
// Non-RESOLVER path: typically python invocation failure (PYTHONPATH wrong,
|
|
197
|
-
// ~/.okstra missing, python3 not on PATH, okstra_project module missing).
|
|
198
|
-
// The user can't fix this by adjusting setup arguments — it's a runtime
|
|
199
|
-
// health issue, not a PROJECT_ROOT issue. Reword accordingly.
|
|
200
|
-
const looksLikePythonFailure = /python invocation failed|ModuleNotFoundError|No module named/.test(
|
|
201
|
-
err.message,
|
|
202
|
-
);
|
|
203
|
-
if (looksLikePythonFailure) {
|
|
204
|
-
process.stderr.write(
|
|
205
|
-
"error: 'okstra setup' could not start because the okstra runtime is not\n" +
|
|
206
|
-
" reachable from this process. This is almost always a stale or\n" +
|
|
207
|
-
" incomplete install, not a problem with your setup arguments.\n" +
|
|
208
|
-
"\nFix:\n" +
|
|
209
|
-
" 1. run 'okstra doctor' to see exactly what is missing\n" +
|
|
210
|
-
" 2. run 'okstra ensure-installed' (or 'npx -y okstra@latest install')\n" +
|
|
211
|
-
" to repair the runtime\n" +
|
|
212
|
-
" 3. retry: okstra setup --project-id <id>\n" +
|
|
213
|
-
`\n(underlying error: ${err.message})\n`,
|
|
214
|
-
);
|
|
215
|
-
return 1;
|
|
216
|
-
}
|
|
217
|
-
process.stderr.write(`error: could not resolve PROJECT_ROOT: ${err.message}\n`);
|
|
218
|
-
return 1;
|
|
219
|
-
}
|
|
220
|
-
const { projectRoot, projectJsonPath } = resolved;
|
|
221
|
-
|
|
222
|
-
let existing = null;
|
|
223
|
-
if (await fileExists(projectJsonPath)) {
|
|
224
|
-
try {
|
|
225
|
-
existing = JSON.parse(await fs.readFile(projectJsonPath, "utf8"));
|
|
226
|
-
} catch (err) {
|
|
227
|
-
process.stderr.write(`error: failed to parse ${projectJsonPath}: ${err.message}\n`);
|
|
228
|
-
return 1;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
let projectId = opts.projectId;
|
|
233
|
-
if (!projectId && existing?.projectId) {
|
|
234
|
-
projectId = existing.projectId;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (!projectId) {
|
|
238
|
-
if (opts.yes || !process.stdin.isTTY) {
|
|
239
|
-
process.stderr.write(
|
|
240
|
-
`error: --project-id is required (no existing project.json, not a TTY)\n`,
|
|
241
|
-
);
|
|
242
|
-
return 1;
|
|
243
|
-
}
|
|
244
|
-
process.stderr.write(`PROJECT_ROOT: ${projectRoot}\n`);
|
|
245
|
-
const answer = await prompt("project-id (e.g. INV-1234, my-app): ");
|
|
246
|
-
projectId = answer;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const invalid = validateProjectId(projectId);
|
|
250
|
-
if (invalid) {
|
|
251
|
-
process.stderr.write(`error: ${invalid}\n`);
|
|
252
|
-
return 1;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
let result;
|
|
256
|
-
try {
|
|
257
|
-
result = await upsert(paths, projectRoot, projectId);
|
|
258
|
-
} catch (err) {
|
|
259
|
-
process.stderr.write(`error: ${err.message}\n`);
|
|
260
|
-
return 1;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
let settingsSymlink = null;
|
|
264
|
-
try {
|
|
265
|
-
settingsSymlink = await ensureProjectSettingsSymlink(projectRoot);
|
|
266
|
-
} catch (err) {
|
|
267
|
-
process.stderr.write(
|
|
268
|
-
`warning: failed to provision .claude/settings.local.json symlink — ` +
|
|
269
|
-
`host Claude Code sessions in this project may need to add wrapper permissions manually. (${err.message})\n`,
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
process.stdout.write(
|
|
274
|
-
JSON.stringify(
|
|
275
|
-
{
|
|
276
|
-
ok: true,
|
|
277
|
-
...result,
|
|
278
|
-
projectJsonPath,
|
|
279
|
-
settingsLocalJson: settingsSymlink,
|
|
280
|
-
},
|
|
281
|
-
null,
|
|
282
|
-
2,
|
|
283
|
-
) + "\n",
|
|
284
|
-
);
|
|
285
|
-
return 0;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
async function ensureProjectSettingsSymlink(projectRoot) {
|
|
289
|
-
const template = join(homedir(), ".okstra", "templates", "settings.local.json");
|
|
290
|
-
try {
|
|
291
|
-
await fs.access(template);
|
|
292
|
-
} catch {
|
|
293
|
-
return null; // install hasn't provisioned the template yet (pre-0.14 install)
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
const claudeDir = join(projectRoot, ".claude");
|
|
297
|
-
const target = join(claudeDir, "settings.local.json");
|
|
298
|
-
await fs.mkdir(claudeDir, { recursive: true });
|
|
299
|
-
|
|
300
|
-
let existingStat;
|
|
301
|
-
try {
|
|
302
|
-
existingStat = await fs.lstat(target);
|
|
303
|
-
} catch {
|
|
304
|
-
existingStat = null;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
if (existingStat?.isSymbolicLink()) {
|
|
308
|
-
const current = await fs.readlink(target);
|
|
309
|
-
const resolved = current.startsWith("/") ? current : join(claudeDir, current);
|
|
310
|
-
if (resolved === template) return target;
|
|
311
|
-
await backupAndReplace(target, template);
|
|
312
|
-
return target;
|
|
313
|
-
}
|
|
314
|
-
if (existingStat) {
|
|
315
|
-
await backupAndReplace(target, template);
|
|
316
|
-
return target;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
await fs.symlink(template, target);
|
|
320
|
-
return target;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
async function backupAndReplace(target, template) {
|
|
324
|
-
const stamp = new Date()
|
|
325
|
-
.toISOString()
|
|
326
|
-
.replace(/[-:]/g, "")
|
|
327
|
-
.replace(/\..*/, "")
|
|
328
|
-
.replace("T", "-");
|
|
329
|
-
const backup = `${target}.bak.${stamp}`;
|
|
330
|
-
await fs.rename(target, backup);
|
|
331
|
-
await fs.symlink(template, target);
|
|
332
|
-
}
|
|
333
|
-
|