okstra 0.173.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.
- 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/dist/commands/execute/team.mjs +56 -0
- 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/dist/commands/execute/worktree-status.mjs +115 -0
- 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/dist/commands/report/finalize.mjs +64 -0
- 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 +17 -3
- package/docs/architecture.md +12 -22
- package/docs/cli.md +29 -8
- package/docs/container.md +1 -1
- package/docs/contributor-change-matrix.md +3 -3
- package/docs/project-structure-overview.md +29 -20
- package/docs/task-process/README.md +3 -1
- package/docs/task-process/implementation-planning.md +2 -2
- package/docs/task-process/implementation.md +1 -1
- package/package.json +11 -5
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +3 -2
- 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 +4 -1
- package/runtime/bin/lib/okstra/usage.sh +4 -4
- package/runtime/bin/okstra-error-log.py +27 -0
- package/runtime/bin/okstra-provider-exec.py +245 -16
- package/runtime/bin/okstra-trace-cleanup.sh +58 -129
- package/runtime/bin/okstra.sh +10 -0
- package/runtime/prompts/lead/adapters/cmux.md +2 -0
- package/runtime/prompts/lead/convergence.md +27 -18
- package/runtime/prompts/lead/okstra-lead-contract.md +4 -2
- package/runtime/prompts/lead/plan-body-verification.md +13 -6
- package/runtime/prompts/lead/report-writer.md +6 -6
- package/runtime/prompts/lead/team-contract.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +2 -2
- package/runtime/prompts/profiles/_implementation-executor.md +2 -0
- package/runtime/prompts/profiles/_implementation-verifier.md +2 -2
- package/runtime/prompts/profiles/change-impact-analysis.md +16 -0
- package/runtime/prompts/profiles/error-analysis.md +21 -1
- package/runtime/prompts/profiles/feature-analysis.md +16 -0
- package/runtime/prompts/profiles/final-verification.md +16 -0
- package/runtime/prompts/profiles/implementation-option-selection.md +16 -0
- package/runtime/prompts/profiles/implementation-planning.md +32 -9
- package/runtime/prompts/profiles/implementation.md +17 -1
- package/runtime/prompts/profiles/improvement-discovery.md +16 -0
- package/runtime/prompts/profiles/project-analysis.md +16 -0
- package/runtime/prompts/profiles/release-handoff.md +5 -1
- package/runtime/prompts/profiles/requirements-discovery.md +20 -0
- package/runtime/prompts/wizard/prompts.ko.json +18 -0
- package/runtime/python/okstra_ctl/adapters/dispatch/__init__.py +1 -6
- 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/external/relay.md +4 -4
- 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 +100 -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/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/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/conformance.py +68 -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 +1181 -102
- package/runtime/python/okstra_ctl/dispatch_state.py +835 -22
- package/runtime/python/okstra_ctl/doctor.py +16 -2
- package/runtime/python/okstra_ctl/domain/host.py +32 -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 +13 -0
- package/runtime/python/okstra_ctl/domain/worker_exec.py +39 -1
- package/runtime/python/okstra_ctl/domain/worker_role.py +13 -3
- 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/final_report_schema.py +5 -4
- 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 +490 -0
- 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/pane_reclaim.py +13 -22
- 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/registry/provider_registry.py +8 -4
- package/runtime/python/okstra_ctl/render.py +78 -10
- package/runtime/python/okstra_ctl/render_final_report.py +34 -19
- package/runtime/python/okstra_ctl/report_contract.py +39 -1
- package/runtime/python/okstra_ctl/report_finalize.py +84 -9
- package/runtime/python/okstra_ctl/report_html/render.py +1 -0
- package/runtime/python/okstra_ctl/role_requirements.py +217 -0
- package/runtime/python/okstra_ctl/run.py +1250 -260
- package/runtime/python/okstra_ctl/run_index_row.py +7 -1
- package/runtime/python/okstra_ctl/schema_excerpt.py +1 -1
- package/runtime/python/okstra_ctl/scope_provenance.py +1 -1
- package/runtime/python/okstra_ctl/session.py +69 -12
- package/runtime/python/okstra_ctl/team.py +51 -25
- package/runtime/python/okstra_ctl/time_report.py +38 -4
- package/runtime/python/okstra_ctl/tmux.py +19 -149
- 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 +1253 -62
- package/runtime/python/okstra_ctl/worker_audit_ledger.py +68 -65
- package/runtime/python/okstra_ctl/worker_request.py +9 -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/worktree.py +69 -3
- package/runtime/python/okstra_ctl/write_policy.py +571 -0
- package/runtime/python/okstra_token_usage/cli.py +1 -1
- package/runtime/python/okstra_token_usage/collect.py +66 -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 +25 -0
- package/runtime/skills/okstra-run/SKILL.md +9 -9
- package/runtime/skills/okstra-setup/references/project-config.md +11 -0
- 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/settings.template.json +0 -24
- package/runtime/templates/worker-prompt-preamble.md +6 -2
- package/runtime/validators/lib/fixtures.sh +98 -33
- package/runtime/validators/validate-implementation-plan-stages.py +63 -3
- package/runtime/validators/validate-run.py +443 -508
- package/runtime/validators/validate_session_conformance.py +26 -8
- package/runtime/bin/okstra-subagent-reclaim.sh +0 -26
- package/runtime/schemas/final-report-v1.0.schema.json +0 -6366
- package/runtime/templates/reports/final-report.template.md +0 -1258
- package/src/cli-registry.mjs +0 -532
- 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/team.mjs +0 -63
- 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 -1172
- 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/commands/report/finalize.mjs +0 -64
- 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
package/src/commands/pr/pr.mjs
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from "node:fs";
|
|
2
|
-
import { execFileSync } from "node:child_process";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { dirname, join, resolve } from "node:path";
|
|
5
|
-
import { createInterface } from "node:readline/promises";
|
|
6
|
-
import { stdin as input, stdout as output } from "node:process";
|
|
7
|
-
import { resolveOkstraHome } from "../../lib/paths.mjs";
|
|
8
|
-
|
|
9
|
-
const NAME_RE = /^[A-Za-z0-9._-]+$/;
|
|
10
|
-
const DEFAULT_TEMPLATE_PATH = join(
|
|
11
|
-
dirname(fileURLToPath(import.meta.url)),
|
|
12
|
-
"default.md",
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
const USAGE = `okstra pr — PR body templates and PR generation
|
|
16
|
-
|
|
17
|
-
Usage:
|
|
18
|
-
okstra pr template list [--json]
|
|
19
|
-
okstra pr template show <name|default> [--json]
|
|
20
|
-
okstra pr template add --name <name> (--content <text> | --file <path>) [--yes]
|
|
21
|
-
okstra pr template path
|
|
22
|
-
okstra pr branches [--json]
|
|
23
|
-
okstra pr gen --base <ref> [--template <name|default>] [--json]
|
|
24
|
-
`;
|
|
25
|
-
|
|
26
|
-
export function isValidTemplateName(name) {
|
|
27
|
-
return (
|
|
28
|
-
typeof name === "string" &&
|
|
29
|
-
NAME_RE.test(name) &&
|
|
30
|
-
name !== "." &&
|
|
31
|
-
name !== ".."
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function templateDir(home) {
|
|
36
|
-
return join(home, "template", "pr");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function listTemplates(home) {
|
|
40
|
-
let entries;
|
|
41
|
-
try {
|
|
42
|
-
entries = await fs.readdir(templateDir(home));
|
|
43
|
-
} catch (err) {
|
|
44
|
-
if (err.code === "ENOENT") return [];
|
|
45
|
-
throw err;
|
|
46
|
-
}
|
|
47
|
-
return entries
|
|
48
|
-
.filter((f) => f.endsWith(".md"))
|
|
49
|
-
.map((f) => f.slice(0, -3))
|
|
50
|
-
.sort();
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async function readBundledDefault() {
|
|
54
|
-
return fs.readFile(DEFAULT_TEMPLATE_PATH, "utf8");
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export async function readTemplate(home, name) {
|
|
58
|
-
if (!name || name === "default") return readBundledDefault();
|
|
59
|
-
if (!isValidTemplateName(name)) throw new Error(`invalid template name: ${name}`);
|
|
60
|
-
try {
|
|
61
|
-
return await fs.readFile(join(templateDir(home), `${name}.md`), "utf8");
|
|
62
|
-
} catch (err) {
|
|
63
|
-
if (err.code === "ENOENT") return readBundledDefault();
|
|
64
|
-
throw err;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export async function addTemplate(home, name, content, opts = {}) {
|
|
69
|
-
if (!isValidTemplateName(name)) throw new Error(`invalid template name: ${name}`);
|
|
70
|
-
const dir = templateDir(home);
|
|
71
|
-
await fs.mkdir(dir, { recursive: true });
|
|
72
|
-
const target = join(dir, `${name}.md`);
|
|
73
|
-
if (!opts.force) {
|
|
74
|
-
try {
|
|
75
|
-
await fs.access(target);
|
|
76
|
-
throw new Error(`template exists: ${name} (use --yes to overwrite)`);
|
|
77
|
-
} catch (err) {
|
|
78
|
-
if (err.code !== "ENOENT") throw err;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
await fs.writeFile(target, content, "utf8");
|
|
82
|
-
return target;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function takeValue(args, i, flag) {
|
|
86
|
-
const v = args[i + 1];
|
|
87
|
-
if (!v || v.startsWith("--")) throw new Error(`${flag} requires a value`);
|
|
88
|
-
return v;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async function readAddContent(opts) {
|
|
92
|
-
if (opts.content !== null) return opts.content;
|
|
93
|
-
if (opts.file !== null) return fs.readFile(resolve(opts.file), "utf8");
|
|
94
|
-
throw new Error("template add requires --content or --file");
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
async function confirm(question) {
|
|
98
|
-
const rl = createInterface({ input, output });
|
|
99
|
-
try {
|
|
100
|
-
const answer = (await rl.question(`${question} [y/N] `)).trim().toLowerCase();
|
|
101
|
-
return answer === "y" || answer === "yes";
|
|
102
|
-
} finally {
|
|
103
|
-
rl.close();
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async function cmdTemplate(args, home) {
|
|
108
|
-
const sub = args[0];
|
|
109
|
-
const rest = args.slice(1);
|
|
110
|
-
const json = rest.includes("--json");
|
|
111
|
-
if (sub === "list") {
|
|
112
|
-
const names = await listTemplates(home);
|
|
113
|
-
if (json) output.write(JSON.stringify({ templates: names }) + "\n");
|
|
114
|
-
else output.write(names.length ? names.join("\n") + "\n" : "(no templates)\n");
|
|
115
|
-
return 0;
|
|
116
|
-
}
|
|
117
|
-
if (sub === "show") {
|
|
118
|
-
const name = rest.find((a) => !a.startsWith("--"));
|
|
119
|
-
if (!name) throw new Error("template show requires a name");
|
|
120
|
-
const body = await readTemplate(home, name);
|
|
121
|
-
output.write(json ? JSON.stringify({ name, body }) + "\n" : body);
|
|
122
|
-
return 0;
|
|
123
|
-
}
|
|
124
|
-
if (sub === "path") {
|
|
125
|
-
output.write(templateDir(home) + "\n");
|
|
126
|
-
return 0;
|
|
127
|
-
}
|
|
128
|
-
if (sub === "add") {
|
|
129
|
-
const opts = { name: null, content: null, file: null, yes: false };
|
|
130
|
-
for (let i = 0; i < rest.length; i++) {
|
|
131
|
-
const flag = rest[i];
|
|
132
|
-
if (flag === "--name") opts.name = takeValue(rest, i++, flag);
|
|
133
|
-
else if (flag === "--content") opts.content = takeValue(rest, i++, flag);
|
|
134
|
-
else if (flag === "--file") opts.file = takeValue(rest, i++, flag);
|
|
135
|
-
else if (flag === "--yes") opts.yes = true;
|
|
136
|
-
else throw new Error(`unknown flag ${flag}`);
|
|
137
|
-
}
|
|
138
|
-
if (!opts.name) throw new Error("template add requires --name");
|
|
139
|
-
const content = await readAddContent(opts);
|
|
140
|
-
const dir = templateDir(home);
|
|
141
|
-
const target = join(dir, `${opts.name}.md`);
|
|
142
|
-
let force = opts.yes;
|
|
143
|
-
if (!force && isValidTemplateName(opts.name)) {
|
|
144
|
-
let exists = false;
|
|
145
|
-
try {
|
|
146
|
-
await fs.access(target);
|
|
147
|
-
exists = true;
|
|
148
|
-
} catch (err) {
|
|
149
|
-
if (err.code !== "ENOENT") throw err;
|
|
150
|
-
}
|
|
151
|
-
if (exists) {
|
|
152
|
-
if (!process.stdin.isTTY) {
|
|
153
|
-
throw new Error(`template exists: ${opts.name} (use --yes to overwrite)`);
|
|
154
|
-
}
|
|
155
|
-
force = await confirm(`Overwrite existing template ${opts.name}?`);
|
|
156
|
-
if (!force) { output.write("aborted\n"); return 1; }
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
const saved = await addTemplate(home, opts.name, content, { force: true });
|
|
160
|
-
output.write(`saved: ${saved}\n`);
|
|
161
|
-
return 0;
|
|
162
|
-
}
|
|
163
|
-
throw new Error(`unknown template subcommand: ${sub ?? "(none)"}`);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function tryGit(cwd, args) {
|
|
167
|
-
try {
|
|
168
|
-
return execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
169
|
-
} catch {
|
|
170
|
-
return null;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export function recommendBranches(cwd) {
|
|
175
|
-
const currentBranch = tryGit(cwd, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
176
|
-
if (currentBranch === null) return { currentBranch: null, recommended: [] };
|
|
177
|
-
const ordered = [];
|
|
178
|
-
const remoteDefault = tryGit(cwd, ["symbolic-ref", "--short", "refs/remotes/origin/HEAD"]);
|
|
179
|
-
if (remoteDefault) {
|
|
180
|
-
const bare = remoteDefault.replace(/^origin\//, "");
|
|
181
|
-
if (tryGit(cwd, ["rev-parse", "--verify", "--quiet", `${bare}^{commit}`]) !== null) ordered.push(bare);
|
|
182
|
-
else if (tryGit(cwd, ["rev-parse", "--verify", "--quiet", `${remoteDefault}^{commit}`]) !== null) ordered.push(remoteDefault);
|
|
183
|
-
}
|
|
184
|
-
for (const b of ["main", "master", "develop"]) {
|
|
185
|
-
const local = tryGit(cwd, ["show-ref", "--verify", "--quiet", `refs/heads/${b}`]);
|
|
186
|
-
if (local !== null) ordered.push(b);
|
|
187
|
-
}
|
|
188
|
-
const recent = tryGit(cwd, [
|
|
189
|
-
"for-each-ref", "--sort=-committerdate", "--format=%(refname:short)", "refs/heads",
|
|
190
|
-
]);
|
|
191
|
-
if (recent) ordered.push(...recent.split("\n").filter(Boolean));
|
|
192
|
-
const recommended = [];
|
|
193
|
-
for (const b of ordered) {
|
|
194
|
-
if (b && b !== currentBranch && !recommended.includes(b)) recommended.push(b);
|
|
195
|
-
}
|
|
196
|
-
return { currentBranch, recommended };
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function cmdBranches(args, cwd) {
|
|
200
|
-
const json = args.includes("--json");
|
|
201
|
-
const r = recommendBranches(cwd);
|
|
202
|
-
if (json) output.write(JSON.stringify(r) + "\n");
|
|
203
|
-
else output.write((r.recommended.join("\n") || "(no branches)") + "\n");
|
|
204
|
-
return 0;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export async function buildGenBundle({ cwd, home, base, templateName }) {
|
|
208
|
-
if (!base) throw new Error("gen requires --base");
|
|
209
|
-
const verified = tryGit(cwd, ["rev-parse", "--verify", "--quiet", `${base}^{commit}`]);
|
|
210
|
-
if (verified === null) throw new Error(`base ref not found: ${base}`);
|
|
211
|
-
const currentBranch = tryGit(cwd, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
212
|
-
const logRaw = tryGit(cwd, [
|
|
213
|
-
"log", "--reverse", "--format=%h%x09%s", `${base}..HEAD`,
|
|
214
|
-
]) || "";
|
|
215
|
-
const commits = logRaw
|
|
216
|
-
.split("\n")
|
|
217
|
-
.filter(Boolean)
|
|
218
|
-
.map((line) => {
|
|
219
|
-
const tab = line.indexOf("\t");
|
|
220
|
-
return { hash: line.slice(0, tab), subject: line.slice(tab + 1) };
|
|
221
|
-
});
|
|
222
|
-
const diffStat = tryGit(cwd, ["diff", "--stat", `${base}...HEAD`]) || "";
|
|
223
|
-
const template = await readTemplate(home, templateName);
|
|
224
|
-
const resolvedName = templateName && templateName !== "default"
|
|
225
|
-
? templateName
|
|
226
|
-
: "default";
|
|
227
|
-
return { base, currentBranch, templateName: resolvedName, template, commits, diffStat };
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
async function cmdGen(args, cwd, home) {
|
|
231
|
-
const opts = { base: null, template: "default" };
|
|
232
|
-
for (let i = 0; i < args.length; i++) {
|
|
233
|
-
const flag = args[i];
|
|
234
|
-
if (flag === "--base") opts.base = takeValue(args, i++, flag);
|
|
235
|
-
else if (flag === "--template") opts.template = takeValue(args, i++, flag);
|
|
236
|
-
else if (flag === "--json") continue;
|
|
237
|
-
else throw new Error(`unknown flag ${flag}`);
|
|
238
|
-
}
|
|
239
|
-
const bundle = await buildGenBundle({ cwd, home, base: opts.base, templateName: opts.template });
|
|
240
|
-
output.write(JSON.stringify(bundle) + "\n");
|
|
241
|
-
return 0;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export async function run(args) {
|
|
245
|
-
if (args.length === 0 || args.includes("--help")) {
|
|
246
|
-
output.write(USAGE);
|
|
247
|
-
return 0;
|
|
248
|
-
}
|
|
249
|
-
const home = resolveOkstraHome();
|
|
250
|
-
const sub = args[0];
|
|
251
|
-
const rest = args.slice(1);
|
|
252
|
-
try {
|
|
253
|
-
if (sub === "template") return await cmdTemplate(rest, home);
|
|
254
|
-
if (sub === "branches") return cmdBranches(rest, process.cwd());
|
|
255
|
-
if (sub === "gen") return await cmdGen(rest, process.cwd(), home);
|
|
256
|
-
throw new Error(`unknown pr subcommand: ${sub}`);
|
|
257
|
-
} catch (err) {
|
|
258
|
-
process.stderr.write(`error: ${err.message}\n`);
|
|
259
|
-
return 1;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { runPythonModule } from "../../lib/python-helper.mjs";
|
|
2
|
-
import { resolvePaths } from "../../lib/paths.mjs";
|
|
3
|
-
|
|
4
|
-
const USAGE = `okstra report-finalize — run the Phase 7 post-report sequence
|
|
5
|
-
|
|
6
|
-
Usage:
|
|
7
|
-
okstra report-finalize --project-root <dir> --run-manifest <path> \\
|
|
8
|
-
--report <final-report-<task-type>-<seq>.md> [--team-state <path>]
|
|
9
|
-
|
|
10
|
-
Runs the four Phase 7 steps in their contractual order against one final-report:
|
|
11
|
-
|
|
12
|
-
1. token-usage substitute real token/cost numbers into the data.json
|
|
13
|
-
2. render-views write the schema-v2 task-specific *.html sibling; v1
|
|
14
|
-
keeps the legacy conditional interactive view
|
|
15
|
-
3. spawn-followups turn section 4 rows into task stubs
|
|
16
|
-
4. validate-run validate the finished run artifacts
|
|
17
|
-
|
|
18
|
-
Every step is idempotent, so re-running after a fixed failure is safe. The
|
|
19
|
-
sequence stops at the first non-zero exit and reports which step failed.
|
|
20
|
-
|
|
21
|
-
This is the same code path the Codex lead adapter runs automatically after its
|
|
22
|
-
report-writer completes, so a Claude-led and a Codex-led run finalize
|
|
23
|
-
identically.
|
|
24
|
-
|
|
25
|
-
--workspace-root is owned by this command.
|
|
26
|
-
`;
|
|
27
|
-
|
|
28
|
-
const OWNED_FLAGS = new Set(["--workspace-root"]);
|
|
29
|
-
|
|
30
|
-
function isOwnedFlag(arg) {
|
|
31
|
-
if (OWNED_FLAGS.has(arg)) return true;
|
|
32
|
-
return [...OWNED_FLAGS].some((flag) => arg.startsWith(`${flag}=`));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function buildReportFinalizeArgs(args, paths) {
|
|
36
|
-
return ["--workspace-root", paths.workspace, ...args];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function run(args) {
|
|
40
|
-
if (args.includes("--help") || args.includes("-h")) {
|
|
41
|
-
process.stdout.write(USAGE);
|
|
42
|
-
return 0;
|
|
43
|
-
}
|
|
44
|
-
if (args.length === 0) {
|
|
45
|
-
process.stdout.write(USAGE);
|
|
46
|
-
return 2;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const forbidden = args.find(isOwnedFlag);
|
|
50
|
-
if (forbidden) {
|
|
51
|
-
process.stderr.write(
|
|
52
|
-
`error: ${forbidden} is set by 'okstra report-finalize' itself — remove it from your args\n`,
|
|
53
|
-
);
|
|
54
|
-
return 2;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const paths = await resolvePaths();
|
|
58
|
-
const result = await runPythonModule({
|
|
59
|
-
module: "okstra_ctl.report_finalize",
|
|
60
|
-
args: buildReportFinalizeArgs(args, paths),
|
|
61
|
-
stdio: "inherit-stdout",
|
|
62
|
-
});
|
|
63
|
-
return result.code;
|
|
64
|
-
}
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import { homedir } from "node:os";
|
|
2
|
-
|
|
3
|
-
import { runPythonModule } from "./python-helper.mjs";
|
|
4
|
-
|
|
5
|
-
export const RUNTIME_AUTO = "auto";
|
|
6
|
-
|
|
7
|
-
const HOST_REQUEST_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
8
|
-
const PLAIN_TEXT_INPUT = "plain_text_input";
|
|
9
|
-
|
|
10
|
-
export class HostRegistryClientError extends Error {
|
|
11
|
-
constructor(message) {
|
|
12
|
-
super(message);
|
|
13
|
-
this.name = "HostRegistryClientError";
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async function callHosts(runPython, args) {
|
|
18
|
-
const result = await runPython({
|
|
19
|
-
module: "okstra_ctl.entrypoints.hosts",
|
|
20
|
-
args,
|
|
21
|
-
stdio: "capture",
|
|
22
|
-
});
|
|
23
|
-
if (result.code !== 0) {
|
|
24
|
-
const detail = String(result.stderr || "").trim() || `Python exited ${result.code}`;
|
|
25
|
-
throw new HostRegistryClientError(detail);
|
|
26
|
-
}
|
|
27
|
-
const stdout = String(result.stdout || "").trim();
|
|
28
|
-
if (!stdout) throw new HostRegistryClientError("host registry returned empty stdout");
|
|
29
|
-
try {
|
|
30
|
-
return JSON.parse(stdout);
|
|
31
|
-
} catch (error) {
|
|
32
|
-
throw new HostRegistryClientError(`host registry returned invalid JSON: ${error.message}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function resolutionContext(env = {}, capabilities = {}) {
|
|
37
|
-
return {
|
|
38
|
-
env: { OKSTRA_RUNTIME_HOST: String(env?.OKSTRA_RUNTIME_HOST ?? "") },
|
|
39
|
-
capabilities: {
|
|
40
|
-
claudeSkillHandoff: capabilities?.claudeSkillHandoff === true,
|
|
41
|
-
tmuxAvailable: capabilities?.tmuxAvailable === true,
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function createHostRegistryClient({ runPython = runPythonModule } = {}) {
|
|
47
|
-
return {
|
|
48
|
-
async catalog() {
|
|
49
|
-
return await callHosts(runPython, ["catalog", "--json"]);
|
|
50
|
-
},
|
|
51
|
-
async resolveHostRuntime({ requestedRuntime, command, env, capabilities }) {
|
|
52
|
-
return await callHosts(runPython, [
|
|
53
|
-
"resolve",
|
|
54
|
-
"--requested", requestedRuntime,
|
|
55
|
-
"--command", command,
|
|
56
|
-
"--context-json", JSON.stringify(resolutionContext(env, capabilities)),
|
|
57
|
-
]);
|
|
58
|
-
},
|
|
59
|
-
async probeHost({
|
|
60
|
-
hostRuntime,
|
|
61
|
-
entryMode,
|
|
62
|
-
projectRoot,
|
|
63
|
-
homeDir,
|
|
64
|
-
availableFunctions = [],
|
|
65
|
-
}) {
|
|
66
|
-
const args = [
|
|
67
|
-
"probe",
|
|
68
|
-
"--host", hostRuntime,
|
|
69
|
-
"--entry-mode", entryMode,
|
|
70
|
-
"--project-root", projectRoot,
|
|
71
|
-
"--home-dir", homeDir,
|
|
72
|
-
];
|
|
73
|
-
for (const availableFunction of availableFunctions) {
|
|
74
|
-
args.push("--available-function", availableFunction);
|
|
75
|
-
}
|
|
76
|
-
return await callHosts(runPython, args);
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const hostRegistryClient = createHostRegistryClient();
|
|
82
|
-
|
|
83
|
-
export function normalizeHostRequest(value) {
|
|
84
|
-
const runtime = String(value ?? "").trim() || RUNTIME_AUTO;
|
|
85
|
-
if (!HOST_REQUEST_PATTERN.test(runtime)) {
|
|
86
|
-
throw new Error(
|
|
87
|
-
`invalid runtime '${runtime}' (expected auto, all, or a lowercase host ID)`,
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
return runtime;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function failedResolution(requestedRuntime, error) {
|
|
94
|
-
return {
|
|
95
|
-
ok: false,
|
|
96
|
-
requestedRuntime,
|
|
97
|
-
resolvedRuntime: null,
|
|
98
|
-
launchMode: null,
|
|
99
|
-
installTargets: [],
|
|
100
|
-
host: "unknown",
|
|
101
|
-
confidence: "low",
|
|
102
|
-
reason: error.message,
|
|
103
|
-
fallbackFrom: null,
|
|
104
|
-
warnings: [],
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function catalogResolution(catalog) {
|
|
109
|
-
const hosts = Array.isArray(catalog?.hosts) ? catalog.hosts : [];
|
|
110
|
-
const catalogHostIds = hosts.map((host) => host.id);
|
|
111
|
-
const installTargets = Array.from(new Set(
|
|
112
|
-
hosts.flatMap((host) => host.install_targets ?? host.installTargets ?? []),
|
|
113
|
-
)).sort();
|
|
114
|
-
return {
|
|
115
|
-
ok: true,
|
|
116
|
-
requestedRuntime: "all",
|
|
117
|
-
resolvedRuntime: "all",
|
|
118
|
-
launchMode: "catalog",
|
|
119
|
-
installTargets,
|
|
120
|
-
catalogHostIds,
|
|
121
|
-
host: "explicit",
|
|
122
|
-
confidence: "high",
|
|
123
|
-
reason: "All registered host runtimes requested.",
|
|
124
|
-
fallbackFrom: null,
|
|
125
|
-
warnings: [],
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export async function loadHostCatalog() {
|
|
130
|
-
return await hostRegistryClient.catalog();
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export async function resolveHostRuntime(options) {
|
|
134
|
-
return await hostRegistryClient.resolveHostRuntime(options);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export async function probeHost(options) {
|
|
138
|
-
return await hostRegistryClient.probeHost(options);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export async function resolveRuntime({
|
|
142
|
-
requestedRuntime = RUNTIME_AUTO,
|
|
143
|
-
command = "run",
|
|
144
|
-
env = {},
|
|
145
|
-
capabilities = {},
|
|
146
|
-
} = {}) {
|
|
147
|
-
const request = normalizeHostRequest(requestedRuntime);
|
|
148
|
-
try {
|
|
149
|
-
if (request === "all") return catalogResolution(await loadHostCatalog());
|
|
150
|
-
return await resolveHostRuntime({
|
|
151
|
-
requestedRuntime: request,
|
|
152
|
-
command,
|
|
153
|
-
env,
|
|
154
|
-
capabilities,
|
|
155
|
-
});
|
|
156
|
-
} catch (error) {
|
|
157
|
-
if (!(error instanceof HostRegistryClientError)) throw error;
|
|
158
|
-
return failedResolution(request, error);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export async function checkRuntimeReadiness({
|
|
163
|
-
runtime,
|
|
164
|
-
projectRoot,
|
|
165
|
-
homeDir = homedir(),
|
|
166
|
-
hostRegistryClient = { probeHost },
|
|
167
|
-
}) {
|
|
168
|
-
if (!runtime) return { runtime: "auto", status: "ready", checks: [] };
|
|
169
|
-
return await hostRegistryClient.probeHost({
|
|
170
|
-
hostRuntime: runtime,
|
|
171
|
-
entryMode: "current-session",
|
|
172
|
-
projectRoot,
|
|
173
|
-
homeDir,
|
|
174
|
-
availableFunctions: [PLAIN_TEXT_INPUT],
|
|
175
|
-
});
|
|
176
|
-
}
|
package/src/lib/paths.mjs
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { homedir, tmpdir } from "node:os";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
4
|
-
import { getPackageRoot, getPackageVersion } from "./version.mjs";
|
|
5
|
-
|
|
6
|
-
function isStaleTmpHome(p) {
|
|
7
|
-
// tests/conftest.py creates the isolated home as `<tmp_path>/.okstra-isolated`
|
|
8
|
-
// under the system temp dir. Only a deleted one (env leaked, dir gone) heals;
|
|
9
|
-
// a soon-to-be-created `.okstra` temp home or a custom home is left untouched.
|
|
10
|
-
if (!p.endsWith("/.okstra-isolated")) return false;
|
|
11
|
-
const roots = [tmpdir(), "/tmp", "/private/tmp", "/var/folders", "/private/var/folders"];
|
|
12
|
-
return roots.some(
|
|
13
|
-
(r) => r && (p === r || p.startsWith(r.replace(/\/+$/, "") + "/")),
|
|
14
|
-
);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Resolve OKSTRA_HOME, healing a leaked value: when it points at a missing
|
|
18
|
-
// system-temp path (e.g. a deleted pytest-isolated home), warn and fall back
|
|
19
|
-
// to ~/.okstra instead of operating on the dead directory.
|
|
20
|
-
export function resolveOkstraHome() {
|
|
21
|
-
const raw = process.env.OKSTRA_HOME?.trim();
|
|
22
|
-
if (!raw) return join(homedir(), ".okstra");
|
|
23
|
-
if (!existsSync(raw) && isStaleTmpHome(raw)) {
|
|
24
|
-
process.stderr.write(
|
|
25
|
-
`⚠ OKSTRA_HOME=${raw} points to a missing temp dir (leaked test value); falling back to ~/.okstra\n`,
|
|
26
|
-
);
|
|
27
|
-
return join(homedir(), ".okstra");
|
|
28
|
-
}
|
|
29
|
-
return raw;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export async function resolvePaths() {
|
|
33
|
-
const home = resolveOkstraHome();
|
|
34
|
-
const pkgRoot = getPackageRoot();
|
|
35
|
-
const devLink = await readSimpleFile(join(home, "dev-link"));
|
|
36
|
-
const runtimeRoot = devLink || join(pkgRoot, "runtime");
|
|
37
|
-
return {
|
|
38
|
-
agents: join(runtimeRoot, "agents"),
|
|
39
|
-
workspace: runtimeRoot,
|
|
40
|
-
pythonpath: join(home, "lib", "python"),
|
|
41
|
-
bin: join(home, "bin"),
|
|
42
|
-
home,
|
|
43
|
-
package: await getPackageVersion(),
|
|
44
|
-
version: await readSimpleFile(join(home, "version")),
|
|
45
|
-
"dev-link": devLink || "",
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function workspacePythonpath(paths) {
|
|
50
|
-
const candidates = [
|
|
51
|
-
join(paths.workspace, "python"),
|
|
52
|
-
join(paths.workspace, "scripts"),
|
|
53
|
-
];
|
|
54
|
-
return candidates.find((candidate) => existsSync(candidate)) || "";
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Compose the PYTHONPATH spawned python3 subprocesses should see.
|
|
58
|
-
//
|
|
59
|
-
// Precedence (first wins):
|
|
60
|
-
// 1. process.env.PYTHONPATH (user override — e.g. in-repo `PYTHONPATH=scripts`
|
|
61
|
-
// for dev work without re-running `okstra install`).
|
|
62
|
-
// 2. The package/dev-link workspace runtime selected by `okstra paths`.
|
|
63
|
-
// 3. The installed user-runtime path (~/.okstra/lib/python).
|
|
64
|
-
//
|
|
65
|
-
// This is a colon-joined string suitable for direct assignment into the child
|
|
66
|
-
// process env. Empty segments are dropped so a missing env var does not produce
|
|
67
|
-
// a leading ':' (which Python treats as 'current directory').
|
|
68
|
-
export function buildPythonpath(paths) {
|
|
69
|
-
const fragments = [
|
|
70
|
-
process.env.PYTHONPATH,
|
|
71
|
-
workspacePythonpath(paths),
|
|
72
|
-
paths.pythonpath,
|
|
73
|
-
].filter(
|
|
74
|
-
(s) => typeof s === "string" && s.length > 0,
|
|
75
|
-
);
|
|
76
|
-
return fragments.join(":");
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async function readSimpleFile(path) {
|
|
80
|
-
try {
|
|
81
|
-
const { readFile } = await import("node:fs/promises");
|
|
82
|
-
return (await readFile(path, "utf8")).trim();
|
|
83
|
-
} catch {
|
|
84
|
-
return "";
|
|
85
|
-
}
|
|
86
|
-
}
|
package/src/lib/proc.mjs
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
// Shared filesystem / subprocess helpers used by the Node command modules.
|
|
2
|
-
// Extracted to one place so a fix lands once instead of in each command file.
|
|
3
|
-
import { spawn } from "node:child_process";
|
|
4
|
-
import { promises as fs } from "node:fs";
|
|
5
|
-
|
|
6
|
-
export async function fileExists(p) {
|
|
7
|
-
try {
|
|
8
|
-
await fs.access(p);
|
|
9
|
-
return true;
|
|
10
|
-
} catch {
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Run `cmd args`, capturing stdout/stderr. `env` holds *additional* vars that
|
|
16
|
-
// are merged over the inherited process.env. Never rejects — failures resolve
|
|
17
|
-
// with { code: -1, stderr: <message> }.
|
|
18
|
-
export function runProcess(cmd, args, env = {}) {
|
|
19
|
-
return new Promise((resolve) => {
|
|
20
|
-
const child = spawn(cmd, args, {
|
|
21
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
22
|
-
env: { ...process.env, ...env },
|
|
23
|
-
});
|
|
24
|
-
let stdout = "";
|
|
25
|
-
let stderr = "";
|
|
26
|
-
child.stdout.on("data", (b) => (stdout += b.toString()));
|
|
27
|
-
child.stderr.on("data", (b) => (stderr += b.toString()));
|
|
28
|
-
child.on("error", (err) => resolve({ code: -1, stdout, stderr: err.message }));
|
|
29
|
-
child.on("close", (code) => resolve({ code, stdout, stderr }));
|
|
30
|
-
});
|
|
31
|
-
}
|