okstra 0.186.7 → 0.187.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli-registry.d.mts +88 -1
- package/dist/cli-registry.mjs +68 -111
- package/dist/cli-registry.mjs.map +1 -1
- package/dist/commands/execute/render-bundle.mjs +0 -1
- package/dist/commands/execute/render-bundle.mjs.map +1 -1
- package/dist/commands/execute/run.mjs +8 -3
- package/dist/commands/execute/run.mjs.map +1 -1
- package/dist/commands/lifecycle/check-project.mjs +1 -14
- package/dist/commands/lifecycle/check-project.mjs.map +1 -1
- package/dist/commands/lifecycle/config.mjs +38 -40
- package/dist/commands/lifecycle/config.mjs.map +1 -1
- package/dist/commands/lifecycle/doctor.d.mts +22 -7
- package/dist/commands/lifecycle/doctor.mjs +77 -49
- package/dist/commands/lifecycle/doctor.mjs.map +1 -1
- package/dist/commands/lifecycle/install.d.mts +12 -10
- package/dist/commands/lifecycle/install.mjs +104 -39
- package/dist/commands/lifecycle/install.mjs.map +1 -1
- package/dist/commands/lifecycle/paths.mjs +8 -3
- package/dist/commands/lifecycle/paths.mjs.map +1 -1
- package/dist/commands/lifecycle/preflight.mjs +2 -1
- package/dist/commands/lifecycle/preflight.mjs.map +1 -1
- package/dist/commands/lifecycle/setup.mjs +22 -36
- package/dist/commands/lifecycle/setup.mjs.map +1 -1
- package/dist/commands/lifecycle/uninstall.d.mts +4 -2
- package/dist/commands/lifecycle/uninstall.mjs +59 -15
- package/dist/commands/lifecycle/uninstall.mjs.map +1 -1
- package/dist/commands/memory/memory.mjs +7 -1
- package/dist/commands/memory/memory.mjs.map +1 -1
- package/dist/lib/helper-scripts.d.mts +1 -1
- package/dist/lib/helper-scripts.mjs +10 -18
- package/dist/lib/helper-scripts.mjs.map +1 -1
- package/dist/lib/host-config.d.mts +72 -0
- package/dist/lib/host-config.mjs +404 -0
- package/dist/lib/host-config.mjs.map +1 -0
- package/dist/lib/host-registry-client.d.mts +2 -2
- package/dist/lib/host-registry-client.mjs +0 -3
- package/dist/lib/host-registry-client.mjs.map +1 -1
- package/dist/lib/install-assets.d.mts +1 -0
- package/dist/lib/install-assets.mjs +4 -0
- package/dist/lib/install-assets.mjs.map +1 -1
- package/dist/lib/proc.d.mts +2 -0
- package/dist/lib/proc.mjs +12 -0
- package/dist/lib/proc.mjs.map +1 -1
- package/dist/lib/python-command.d.mts +2 -0
- package/dist/lib/python-command.mjs +52 -0
- package/dist/lib/python-command.mjs.map +1 -0
- package/dist/lib/python-helper.d.mts +2 -5
- package/dist/lib/python-helper.mjs +3 -52
- package/dist/lib/python-helper.mjs.map +1 -1
- package/dist/lib/runtime-payload.d.mts +23 -0
- package/dist/lib/runtime-payload.mjs +57 -0
- package/dist/lib/runtime-payload.mjs.map +1 -0
- package/dist/lib/types.d.mts +24 -13
- package/docs/architecture/storage-model.md +21 -5
- package/docs/architecture.md +37 -36
- package/docs/cli.md +55 -76
- package/docs/coding-rules.md +295 -0
- package/docs/container.md +10 -36
- package/docs/contributor-change-matrix.md +1 -1
- package/docs/for-ai/skills/okstra-code-review.md +0 -1
- package/docs/for-ai/skills/okstra-container-build.md +8 -41
- package/docs/for-ai/skills/okstra-inspect.md +4 -4
- package/docs/for-ai/skills/okstra-manager.md +2 -2
- package/docs/for-ai/skills/okstra-rollup.md +0 -1
- package/docs/for-ai/skills/okstra-run.md +3 -3
- package/docs/for-ai/skills/okstra-user-response.md +0 -1
- package/docs/performance-improvement-plan-v2.md +1 -1
- package/docs/project-structure-overview.md +62 -62
- package/docs/task-process/README.md +3 -3
- package/docs/task-process/common-flow.md +1 -1
- package/docs/task-process/error-analysis.md +3 -3
- package/docs/task-process/implementation-planning.md +3 -1
- package/docs/task-process/release-handoff.md +1 -1
- package/package.json +3 -2
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +6 -11
- package/runtime/agents/workers/report-writer-worker.md +1 -1
- package/runtime/bin/lib/okstra/cli.sh +4 -0
- package/runtime/bin/lib/okstra/globals.sh +2 -0
- package/runtime/bin/lib/okstra/interactive.sh +26 -173
- package/runtime/bin/lib/okstra/project-resolver.sh +23 -61
- package/runtime/bin/lib/okstra/usage.sh +3 -3
- package/runtime/bin/okstra-compact-reminder.sh +1 -5
- package/runtime/bin/okstra-error-log.py +19 -2
- package/runtime/bin/okstra-import-check.py +26 -0
- package/runtime/bin/okstra-inject-report-index.py +5 -4
- package/runtime/bin/okstra-provider-exec.py +22 -17
- package/runtime/bin/okstra-render-final-report.py +16 -6
- package/runtime/bin/okstra-render-report-views.py +25 -18
- package/runtime/bin/okstra-report-translate.py +30 -18
- package/runtime/bin/okstra-spawn-followups.py +4 -0
- package/runtime/bin/okstra-token-usage.py +3 -0
- package/runtime/bin/okstra.sh +4 -2
- package/runtime/bin/okstra_bootstrap.py +58 -0
- package/runtime/prompts/coding-preflight/overview.md +1 -1
- package/runtime/prompts/duties/planning-worker.md +1 -1
- package/runtime/prompts/launch.template.md +35 -9
- package/runtime/prompts/lead/convergence.md +96 -87
- package/runtime/prompts/lead/okstra-lead-contract.md +63 -12
- package/runtime/prompts/lead/plan-body-verification.md +65 -46
- package/runtime/prompts/lead/report-writer.md +34 -4
- package/runtime/prompts/lead/team-contract.md +4 -1
- package/runtime/prompts/profiles/_clarification-recommendation.md +2 -1
- package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +3 -3
- package/runtime/prompts/profiles/_coverage-critic.md +1 -1
- package/runtime/prompts/profiles/_implementation-deliverable.md +2 -2
- package/runtime/prompts/profiles/_implementation-executor.md +3 -1
- package/runtime/prompts/profiles/_implementation-verifier.md +16 -2
- package/runtime/prompts/profiles/error-analysis.md +4 -3
- package/runtime/prompts/profiles/final-verification.md +2 -2
- package/runtime/prompts/profiles/implementation-planning.md +22 -17
- package/runtime/prompts/profiles/implementation.md +3 -2
- package/runtime/prompts/profiles/requirements-discovery.md +2 -1
- package/runtime/prompts/wizard/prompts.ko.json +29 -8
- package/runtime/python/okstra_ctl/__init__.py +6 -27
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -5
- package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +21 -2
- package/runtime/python/okstra_ctl/adapters/hosts/external/adapter.py +3 -12
- package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +40 -22
- package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +14 -21
- package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +37 -20
- package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +86 -14
- package/runtime/python/okstra_ctl/adapters/providers/kimi/adapter.py +12 -12
- package/runtime/python/okstra_ctl/adapters/runtime/cmux.py +4 -7
- package/runtime/python/okstra_ctl/agent/__init__.py +1 -0
- package/runtime/python/okstra_ctl/{agent_activity.py → agent/activity.py} +12 -1
- package/runtime/python/okstra_ctl/{agent_invocation.py → agent/invocation.py} +34 -5
- package/runtime/python/okstra_ctl/agent/prompt_cli/__init__.py +19 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/__main__.py +11 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +215 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/dynamic_verifier.py +155 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/emit.py +66 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/inputs.py +138 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +408 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/results.py +197 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/run_identity.py +107 -0
- package/runtime/python/okstra_ctl/analysis_packet.py +47 -4
- package/runtime/python/okstra_ctl/approval_decisions.py +260 -8
- package/runtime/python/okstra_ctl/assignment_resolver.py +0 -12
- package/runtime/python/okstra_ctl/attempt_evidence.py +12 -24
- package/runtime/python/okstra_ctl/blocking_checks.py +251 -0
- package/runtime/python/okstra_ctl/brief_frontmatter.py +0 -7
- package/runtime/python/okstra_ctl/clarification_items/__init__.py +102 -0
- package/runtime/python/okstra_ctl/clarification_items/carry.py +224 -0
- package/runtime/python/okstra_ctl/clarification_items/dispositions.py +135 -0
- package/runtime/python/okstra_ctl/clarification_items/parsing.py +253 -0
- package/runtime/python/okstra_ctl/clarification_items/rows.py +115 -0
- package/runtime/python/okstra_ctl/clarification_items/scan.py +215 -0
- package/runtime/python/okstra_ctl/clarification_items/sidecars.py +211 -0
- package/runtime/python/okstra_ctl/cmux.py +38 -31
- package/runtime/python/okstra_ctl/code_review_target.py +163 -1
- package/runtime/python/okstra_ctl/conformance.py +23 -0
- package/runtime/python/okstra_ctl/container.py +38 -421
- package/runtime/python/okstra_ctl/context_cost.py +16 -2
- package/runtime/python/okstra_ctl/contract_graph_cli.py +7 -0
- package/runtime/python/okstra_ctl/convergence.py +101 -15
- package/runtime/python/okstra_ctl/convergence_critic_prompt.py +345 -0
- package/runtime/python/okstra_ctl/convergence_engine.py +382 -70
- package/runtime/python/okstra_ctl/convergence_store.py +5 -29
- package/runtime/python/okstra_ctl/design_prep.py +108 -12
- package/runtime/python/okstra_ctl/design_snapshot.py +11 -1
- package/runtime/python/okstra_ctl/design_surfaces.py +29 -2
- package/runtime/python/okstra_ctl/dispatch_core.py +102 -25
- package/runtime/python/okstra_ctl/dispatch_state.py +268 -39
- package/runtime/python/okstra_ctl/doctor_cli.py +48 -0
- package/runtime/python/okstra_ctl/domain/worker_exec.py +10 -5
- package/runtime/python/okstra_ctl/domain/worker_presentation.py +21 -1
- package/runtime/python/okstra_ctl/domain/worker_stream.py +52 -21
- package/runtime/python/okstra_ctl/domain/write_policy.py +219 -0
- package/runtime/python/okstra_ctl/entrypoints/hosts.py +9 -2
- package/runtime/python/okstra_ctl/error_log_core.py +1 -1
- package/runtime/python/okstra_ctl/error_report.py +14 -0
- package/runtime/python/okstra_ctl/error_zip.py +18 -2
- package/runtime/python/okstra_ctl/execution_identity.py +100 -7
- package/runtime/python/okstra_ctl/execution_manifest.py +67 -20
- package/runtime/python/okstra_ctl/execution_mutation_audit.py +90 -8
- package/runtime/python/okstra_ctl/final_report_paths.py +17 -0
- package/runtime/python/okstra_ctl/final_report_schema.py +90 -16
- package/runtime/python/okstra_ctl/git_reconcile.py +22 -2
- package/runtime/python/okstra_ctl/handoff.py +24 -1
- package/runtime/python/okstra_ctl/ids.py +6 -16
- package/runtime/python/okstra_ctl/implementation_direction.py +142 -33
- package/runtime/python/okstra_ctl/implementation_options.py +25 -11
- package/runtime/python/okstra_ctl/implementation_outcome.py +5 -2
- package/runtime/python/okstra_ctl/improvement_lenses.py +0 -14
- package/runtime/python/okstra_ctl/incremental_carry.py +69 -8
- package/runtime/python/okstra_ctl/incremental_scope.py +173 -12
- package/runtime/python/okstra_ctl/index.py +2 -2
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +48 -8
- package/runtime/python/okstra_ctl/interactive_cli.py +223 -0
- package/runtime/python/okstra_ctl/json_boundary.py +10 -0
- package/runtime/python/okstra_ctl/listing.py +0 -91
- package/runtime/python/okstra_ctl/locks.py +5 -19
- package/runtime/python/okstra_ctl/log_report.py +14 -0
- package/runtime/python/okstra_ctl/manager_cli.py +22 -3
- package/runtime/python/okstra_ctl/manager_launch.py +4 -8
- package/runtime/python/okstra_ctl/material.py +2 -2
- package/runtime/python/okstra_ctl/migrate.py +23 -1
- package/runtime/python/okstra_ctl/model_cli.py +19 -5
- package/runtime/python/okstra_ctl/model_discovery.py +46 -47
- package/runtime/python/okstra_ctl/model_io/__init__.py +1 -0
- package/runtime/python/okstra_ctl/model_io/lines.py +163 -0
- package/runtime/python/okstra_ctl/model_io/references.py +370 -0
- package/runtime/python/okstra_ctl/model_io/renderers.py +498 -0
- package/runtime/python/okstra_ctl/model_io_cli.py +30 -945
- package/runtime/python/okstra_ctl/model_pool.py +10 -6
- package/runtime/python/okstra_ctl/models.py +8 -8
- package/runtime/python/okstra_ctl/mutation_recovery.py +5 -63
- package/runtime/python/okstra_ctl/next_phase.py +121 -69
- package/runtime/python/okstra_ctl/pane_reclaim.py +23 -0
- package/runtime/python/okstra_ctl/pane_title.py +11 -8
- package/runtime/python/okstra_ctl/path_hints.py +36 -11
- package/runtime/python/okstra_ctl/paths.py +76 -8
- package/runtime/python/okstra_ctl/plan_items.py +132 -16
- package/runtime/python/okstra_ctl/plan_items_cli.py +486 -36
- package/runtime/python/okstra_ctl/plan_run_root.py +1 -1
- package/runtime/python/okstra_ctl/plan_validate_cli.py +51 -0
- package/runtime/python/okstra_ctl/plan_verify_cli.py +80 -0
- package/runtime/python/okstra_ctl/prepare_error.py +20 -0
- package/runtime/python/okstra_ctl/prior_planning.py +157 -0
- package/runtime/python/okstra_ctl/profile_show.py +18 -1
- package/runtime/python/okstra_ctl/project_setup_cli.py +140 -0
- package/runtime/python/okstra_ctl/recap.py +22 -1
- package/runtime/python/okstra_ctl/reconcile.py +84 -0
- package/runtime/python/okstra_ctl/registry/host_registry.py +18 -1
- package/runtime/python/okstra_ctl/render.py +98 -32
- package/runtime/python/okstra_ctl/render_final_report.py +3 -7
- package/runtime/python/okstra_ctl/report_assembly.py +297 -7
- package/runtime/python/okstra_ctl/report_contract.py +30 -7
- package/runtime/python/okstra_ctl/report_finalize.py +206 -15
- package/runtime/python/okstra_ctl/report_html/common.py +2 -2
- package/runtime/python/okstra_ctl/report_html/render.py +8 -12
- package/runtime/python/okstra_ctl/report_language.py +8 -4
- package/runtime/python/okstra_ctl/report_narrative.py +90 -3
- package/runtime/python/okstra_ctl/report_projections.py +8 -2
- package/runtime/python/okstra_ctl/report_synthesis_packet.py +258 -1
- package/runtime/python/okstra_ctl/report_translation.py +2 -35
- package/runtime/python/okstra_ctl/report_views.py +4 -22
- package/runtime/python/okstra_ctl/resolve_task_key.py +13 -0
- package/runtime/python/okstra_ctl/rollup.py +13 -0
- package/runtime/python/okstra_ctl/run.py +639 -138
- package/runtime/python/okstra_ctl/run_audit.py +13 -0
- package/runtime/python/okstra_ctl/run_index_row.py +0 -12
- package/runtime/python/okstra_ctl/seeding.py +21 -11
- package/runtime/python/okstra_ctl/sequence.py +1 -1
- package/runtime/python/okstra_ctl/session.py +64 -14
- package/runtime/python/okstra_ctl/set_work_status.py +18 -0
- package/runtime/python/okstra_ctl/stage_integrate.py +15 -1
- package/runtime/python/okstra_ctl/stage_ledger.py +1 -1
- package/runtime/python/okstra_ctl/stage_map.py +57 -11
- package/runtime/python/okstra_ctl/stage_map_cli.py +83 -0
- package/runtime/python/okstra_ctl/stage_map_view.py +65 -0
- package/runtime/python/okstra_ctl/stage_targets.py +3 -12
- package/runtime/python/okstra_ctl/task_list_cli.py +138 -0
- package/runtime/python/okstra_ctl/task_show_cli.py +66 -0
- package/runtime/python/okstra_ctl/task_target.py +4 -16
- package/runtime/python/okstra_ctl/team.py +49 -2
- package/runtime/python/okstra_ctl/time_report.py +17 -2
- package/runtime/python/okstra_ctl/usage_report.py +11 -0
- package/runtime/python/okstra_ctl/user_response.py +55 -218
- package/runtime/python/okstra_ctl/user_response_values.py +242 -0
- package/runtime/python/okstra_ctl/validation_contract.py +3 -0
- package/runtime/python/okstra_ctl/verification_target.py +68 -0
- package/runtime/python/okstra_ctl/wizard.py +457 -92
- package/runtime/python/okstra_ctl/worker_artifacts.py +75 -16
- package/runtime/python/okstra_ctl/worker_audit_check.py +22 -0
- package/runtime/python/okstra_ctl/worker_dispatch.py +21 -0
- package/runtime/python/okstra_ctl/worker_liveness.py +33 -0
- package/runtime/python/okstra_ctl/worker_prompt_body.py +15 -2
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +98 -7
- package/runtime/python/okstra_ctl/worker_prompt_headers.py +24 -2
- package/runtime/python/okstra_ctl/worker_prompt_policy.py +18 -3
- package/runtime/python/okstra_ctl/worker_request.py +2 -1
- package/runtime/python/okstra_ctl/worker_runner.py +16 -9
- package/runtime/python/okstra_ctl/worker_state.py +16 -1
- package/runtime/python/okstra_ctl/workflow.py +18 -1
- package/runtime/python/okstra_ctl/worktree/__init__.py +92 -0
- package/runtime/python/okstra_ctl/worktree/cleanliness.py +89 -0
- package/runtime/python/okstra_ctl/worktree/decisions.py +127 -0
- package/runtime/python/okstra_ctl/worktree/git_ops.py +165 -0
- package/runtime/python/okstra_ctl/worktree/linking.py +249 -0
- package/runtime/python/okstra_ctl/worktree/naming.py +91 -0
- package/runtime/python/okstra_ctl/worktree/provision.py +385 -0
- package/runtime/python/okstra_ctl/worktree/sync_config.py +181 -0
- package/runtime/python/okstra_ctl/worktree_cli.py +75 -0
- package/runtime/python/okstra_ctl/worktree_lookup_cli.py +39 -0
- package/runtime/python/okstra_ctl/worktree_registry.py +7 -0
- package/runtime/python/okstra_ctl/worktree_status_cli.py +53 -0
- package/runtime/python/okstra_ctl/write_policy.py +90 -213
- package/runtime/python/okstra_project/__init__.py +0 -4
- package/runtime/python/okstra_project/dirs.py +2 -2
- package/runtime/python/okstra_project/phase_pointer.py +84 -0
- package/runtime/python/okstra_project/slug.py +24 -0
- package/runtime/python/okstra_project/state.py +22 -230
- package/runtime/python/okstra_token_usage/claude.py +9 -1
- package/runtime/python/okstra_token_usage/cli.py +3 -1
- package/runtime/python/okstra_token_usage/collect.py +71 -10
- package/runtime/python/okstra_token_usage/cursor.py +2 -0
- package/runtime/python/okstra_token_usage/grok.py +1 -5
- package/runtime/python/okstra_token_usage/paths.py +26 -0
- package/runtime/python/okstra_token_usage/pricing.py +19 -7
- package/runtime/schemas/convergence-critic-results-v1.0.schema.json +5 -0
- package/runtime/schemas/execution-manifest-v2.schema.json +10 -10
- package/runtime/schemas/final-report-v2.0.schema.json +9 -26
- package/runtime/schemas/final-report-v3.0.schema.json +173 -41
- package/runtime/schemas/report-narrative-v3.0.schema.json +3 -2
- package/runtime/skills/okstra-brief-gen/SKILL.md +35 -2
- package/runtime/skills/okstra-container-build/SKILL.md +16 -47
- package/runtime/skills/okstra-inspect/facets/history.md +1 -1
- package/runtime/skills/okstra-inspect/facets/status.md +7 -6
- package/runtime/skills/okstra-pr-gen/SKILL.md +1 -1
- package/runtime/skills/okstra-run/SKILL.md +7 -5
- package/runtime/templates/report-writer-prompt-preamble.md +1 -1
- package/runtime/templates/reports/brief.template.md +6 -2
- package/runtime/templates/reports/error-analysis-input.template.md +2 -0
- package/runtime/templates/reports/final-verification-input.template.md +2 -0
- package/runtime/templates/reports/implementation-input.template.md +7 -1
- package/runtime/templates/reports/implementation-planning-input.template.md +4 -0
- package/runtime/templates/reports/quick-input.template.md +2 -0
- package/runtime/templates/reports/release-handoff-input.template.md +6 -1
- package/runtime/templates/reports/report.js +20 -3
- package/runtime/templates/reports/schedule.template.md +2 -0
- package/runtime/templates/reports/settings.template.json +0 -10
- package/runtime/templates/reports/task-brief.template.md +3 -0
- package/runtime/templates/reports/user-response.template.md +7 -3
- package/runtime/validators/checks/fixtures-01.py +57 -0
- package/runtime/validators/checks/fixtures-02.py +565 -0
- package/runtime/validators/checks/runners-01.py +108 -0
- package/runtime/validators/checks/validate-assets-01.py +60 -0
- package/runtime/validators/checks/validate-prompt-metadata-01.py +261 -0
- package/runtime/validators/checks/validate-tasks-01.py +46 -0
- package/runtime/validators/checks/validate-tasks-02.py +85 -0
- package/runtime/validators/checks/validate-tasks-03.py +61 -0
- package/runtime/validators/checks/validate-tasks-04.py +118 -0
- package/runtime/validators/forbidden_actions.py +73 -3
- package/runtime/validators/lib/common.sh +5 -0
- package/runtime/validators/lib/fixtures.sh +7 -591
- package/runtime/validators/lib/paths.sh +13 -0
- package/runtime/validators/lib/runners.sh +6 -104
- package/runtime/validators/lib/summary.sh +1 -1
- package/runtime/validators/lib/validate-assets.sh +6 -56
- package/runtime/validators/lib/validate-prompt-metadata.sh +6 -257
- package/runtime/validators/lib/validate-tasks.sh +9 -294
- package/runtime/validators/validate-implementation-plan-stages.py +4 -4
- package/runtime/validators/validate-run.py +1369 -2654
- package/runtime/validators/validate-workflow.sh +56 -16
- package/runtime/validators/validate_improvement_report.py +2 -1
- package/runtime/validators/validate_session_conformance.py +295 -49
- package/dist/commands/execute/agent-prompt.d.mts +0 -1
- package/dist/commands/execute/agent-prompt.mjs +0 -24
- package/dist/commands/execute/agent-prompt.mjs.map +0 -1
- package/dist/commands/execute/codex-dispatch.d.mts +0 -3
- package/dist/commands/execute/codex-dispatch.mjs +0 -6
- package/dist/commands/execute/codex-dispatch.mjs.map +0 -1
- package/dist/commands/execute/codex-run.d.mts +0 -3
- package/dist/commands/execute/codex-run.mjs +0 -62
- package/dist/commands/execute/codex-run.mjs.map +0 -1
- package/dist/commands/execute/convergence.d.mts +0 -1
- package/dist/commands/execute/convergence.mjs +0 -38
- package/dist/commands/execute/convergence.mjs.map +0 -1
- package/dist/commands/execute/error-log.d.mts +0 -1
- package/dist/commands/execute/error-log.mjs +0 -18
- package/dist/commands/execute/error-log.mjs.map +0 -1
- package/dist/commands/execute/git-reconcile.d.mts +0 -1
- package/dist/commands/execute/git-reconcile.mjs +0 -30
- package/dist/commands/execute/git-reconcile.mjs.map +0 -1
- package/dist/commands/execute/handoff.d.mts +0 -1
- package/dist/commands/execute/handoff.mjs +0 -31
- package/dist/commands/execute/handoff.mjs.map +0 -1
- package/dist/commands/execute/incremental-carry.d.mts +0 -1
- package/dist/commands/execute/incremental-carry.mjs +0 -20
- package/dist/commands/execute/incremental-carry.mjs.map +0 -1
- package/dist/commands/execute/incremental-scope.d.mts +0 -1
- package/dist/commands/execute/incremental-scope.mjs +0 -29
- package/dist/commands/execute/incremental-scope.mjs.map +0 -1
- package/dist/commands/execute/integrate-stages.d.mts +0 -1
- package/dist/commands/execute/integrate-stages.mjs +0 -24
- package/dist/commands/execute/integrate-stages.mjs.map +0 -1
- package/dist/commands/execute/pane-title.d.mts +0 -1
- package/dist/commands/execute/pane-title.mjs +0 -20
- package/dist/commands/execute/pane-title.mjs.map +0 -1
- package/dist/commands/execute/plan-items.d.mts +0 -1
- package/dist/commands/execute/plan-items.mjs +0 -9
- package/dist/commands/execute/plan-items.mjs.map +0 -1
- package/dist/commands/execute/plan-validate.d.mts +0 -1
- package/dist/commands/execute/plan-validate.mjs +0 -68
- package/dist/commands/execute/plan-validate.mjs.map +0 -1
- package/dist/commands/execute/plan-verify.d.mts +0 -1
- package/dist/commands/execute/plan-verify.mjs +0 -43
- package/dist/commands/execute/plan-verify.mjs.map +0 -1
- package/dist/commands/execute/spawn-followups.d.mts +0 -1
- package/dist/commands/execute/spawn-followups.mjs +0 -22
- package/dist/commands/execute/spawn-followups.mjs.map +0 -1
- package/dist/commands/execute/team.d.mts +0 -3
- package/dist/commands/execute/team.mjs +0 -66
- package/dist/commands/execute/team.mjs.map +0 -1
- package/dist/commands/execute/token-usage.d.mts +0 -1
- package/dist/commands/execute/token-usage.mjs +0 -19
- package/dist/commands/execute/token-usage.mjs.map +0 -1
- package/dist/commands/execute/worker-audit-check.d.mts +0 -1
- package/dist/commands/execute/worker-audit-check.mjs +0 -34
- package/dist/commands/execute/worker-audit-check.mjs.map +0 -1
- package/dist/commands/execute/worker-dispatch.d.mts +0 -7
- package/dist/commands/execute/worker-dispatch.mjs +0 -64
- package/dist/commands/execute/worker-dispatch.mjs.map +0 -1
- package/dist/commands/execute/worker-state.d.mts +0 -1
- package/dist/commands/execute/worker-state.mjs +0 -28
- package/dist/commands/execute/worker-state.mjs.map +0 -1
- package/dist/commands/execute/worktree-lookup.d.mts +0 -1
- package/dist/commands/execute/worktree-lookup.mjs +0 -92
- package/dist/commands/execute/worktree-lookup.mjs.map +0 -1
- package/dist/commands/execute/worktree-status.d.mts +0 -1
- package/dist/commands/execute/worktree-status.mjs +0 -121
- package/dist/commands/execute/worktree-status.mjs.map +0 -1
- package/dist/commands/inspect/code-review.d.mts +0 -1
- package/dist/commands/inspect/code-review.mjs +0 -32
- package/dist/commands/inspect/code-review.mjs.map +0 -1
- package/dist/commands/inspect/container.d.mts +0 -1
- package/dist/commands/inspect/container.mjs +0 -25
- package/dist/commands/inspect/container.mjs.map +0 -1
- package/dist/commands/inspect/context-cost.d.mts +0 -1
- package/dist/commands/inspect/context-cost.mjs +0 -25
- package/dist/commands/inspect/context-cost.mjs.map +0 -1
- package/dist/commands/inspect/design-prep.d.mts +0 -1
- package/dist/commands/inspect/design-prep.mjs +0 -22
- package/dist/commands/inspect/design-prep.mjs.map +0 -1
- package/dist/commands/inspect/error-report.d.mts +0 -1
- package/dist/commands/inspect/error-report.mjs +0 -25
- package/dist/commands/inspect/error-report.mjs.map +0 -1
- package/dist/commands/inspect/error-zip.d.mts +0 -1
- package/dist/commands/inspect/error-zip.mjs +0 -24
- package/dist/commands/inspect/error-zip.mjs.map +0 -1
- package/dist/commands/inspect/log-report.d.mts +0 -1
- package/dist/commands/inspect/log-report.mjs +0 -26
- package/dist/commands/inspect/log-report.mjs.map +0 -1
- package/dist/commands/inspect/model-io.d.mts +0 -1
- package/dist/commands/inspect/model-io.mjs +0 -25
- package/dist/commands/inspect/model-io.mjs.map +0 -1
- package/dist/commands/inspect/profile-show.d.mts +0 -1
- package/dist/commands/inspect/profile-show.mjs +0 -28
- package/dist/commands/inspect/profile-show.mjs.map +0 -1
- package/dist/commands/inspect/recap.d.mts +0 -1
- package/dist/commands/inspect/recap.mjs +0 -30
- package/dist/commands/inspect/recap.mjs.map +0 -1
- package/dist/commands/inspect/resolve-task-key.d.mts +0 -1
- package/dist/commands/inspect/resolve-task-key.mjs +0 -24
- package/dist/commands/inspect/resolve-task-key.mjs.map +0 -1
- package/dist/commands/inspect/rollup.d.mts +0 -1
- package/dist/commands/inspect/rollup.mjs +0 -25
- package/dist/commands/inspect/rollup.mjs.map +0 -1
- package/dist/commands/inspect/run-audit.d.mts +0 -1
- package/dist/commands/inspect/run-audit.mjs +0 -25
- package/dist/commands/inspect/run-audit.mjs.map +0 -1
- package/dist/commands/inspect/set-work-status.d.mts +0 -1
- package/dist/commands/inspect/set-work-status.mjs +0 -29
- package/dist/commands/inspect/set-work-status.mjs.map +0 -1
- package/dist/commands/inspect/stage-map.d.mts +0 -1
- package/dist/commands/inspect/stage-map.mjs +0 -131
- package/dist/commands/inspect/stage-map.mjs.map +0 -1
- package/dist/commands/inspect/task-list.d.mts +0 -1
- package/dist/commands/inspect/task-list.mjs +0 -149
- package/dist/commands/inspect/task-list.mjs.map +0 -1
- package/dist/commands/inspect/task-show.d.mts +0 -1
- package/dist/commands/inspect/task-show.mjs +0 -108
- package/dist/commands/inspect/task-show.mjs.map +0 -1
- package/dist/commands/inspect/time-report.d.mts +0 -1
- package/dist/commands/inspect/time-report.mjs +0 -24
- package/dist/commands/inspect/time-report.mjs.map +0 -1
- package/dist/commands/inspect/usage-report.d.mts +0 -1
- package/dist/commands/inspect/usage-report.mjs +0 -23
- package/dist/commands/inspect/usage-report.mjs.map +0 -1
- package/dist/commands/inspect/user-response.d.mts +0 -1
- package/dist/commands/inspect/user-response.mjs +0 -35
- package/dist/commands/inspect/user-response.mjs.map +0 -1
- package/dist/commands/inspect/worker-liveness.d.mts +0 -1
- package/dist/commands/inspect/worker-liveness.mjs +0 -45
- package/dist/commands/inspect/worker-liveness.mjs.map +0 -1
- package/dist/commands/lifecycle/contract-check.d.mts +0 -1
- package/dist/commands/lifecycle/contract-check.mjs +0 -18
- package/dist/commands/lifecycle/contract-check.mjs.map +0 -1
- package/dist/commands/lifecycle/migrate.d.mts +0 -1
- package/dist/commands/lifecycle/migrate.mjs +0 -30
- package/dist/commands/lifecycle/migrate.mjs.map +0 -1
- package/dist/commands/lifecycle/model.d.mts +0 -1
- package/dist/commands/lifecycle/model.mjs +0 -22
- package/dist/commands/lifecycle/model.mjs.map +0 -1
- package/dist/commands/manager.d.mts +0 -3
- package/dist/commands/manager.mjs +0 -50
- package/dist/commands/manager.mjs.map +0 -1
- package/dist/commands/report/agent-activity.d.mts +0 -1
- package/dist/commands/report/agent-activity.mjs +0 -20
- package/dist/commands/report/agent-activity.mjs.map +0 -1
- package/dist/commands/report/approval-decision.d.mts +0 -1
- package/dist/commands/report/approval-decision.mjs +0 -21
- package/dist/commands/report/approval-decision.mjs.map +0 -1
- package/dist/commands/report/design-snapshot.d.mts +0 -1
- package/dist/commands/report/design-snapshot.mjs +0 -19
- package/dist/commands/report/design-snapshot.mjs.map +0 -1
- package/dist/commands/report/finalize.d.mts +0 -4
- package/dist/commands/report/finalize.mjs +0 -64
- package/dist/commands/report/finalize.mjs.map +0 -1
- package/dist/commands/report/inject-report-index.d.mts +0 -1
- package/dist/commands/report/inject-report-index.mjs +0 -21
- package/dist/commands/report/inject-report-index.mjs.map +0 -1
- package/dist/commands/report/render-final-report.d.mts +0 -1
- package/dist/commands/report/render-final-report.mjs +0 -23
- package/dist/commands/report/render-final-report.mjs.map +0 -1
- package/dist/commands/report/render-views.d.mts +0 -1
- package/dist/commands/report/render-views.mjs +0 -27
- package/dist/commands/report/render-views.mjs.map +0 -1
- package/dist/commands/report/translate.d.mts +0 -1
- package/dist/commands/report/translate.mjs +0 -33
- package/dist/commands/report/translate.mjs.map +0 -1
- package/runtime/bin/lib/okstra/tmux-pane.sh +0 -40
- package/runtime/bin/lib/okstra-ctl/cmd-batch.sh +0 -59
- package/runtime/bin/lib/okstra-ctl/cmd-list.sh +0 -35
- package/runtime/bin/lib/okstra-ctl/cmd-open.sh +0 -36
- package/runtime/bin/lib/okstra-ctl/cmd-projects.sh +0 -26
- package/runtime/bin/lib/okstra-ctl/cmd-reconcile.sh +0 -29
- package/runtime/bin/lib/okstra-ctl/cmd-reindex.sh +0 -38
- package/runtime/bin/lib/okstra-ctl/cmd-rerun.sh +0 -345
- package/runtime/bin/lib/okstra-ctl/cmd-show.sh +0 -27
- package/runtime/bin/lib/okstra-ctl/cmd-tail.sh +0 -92
- package/runtime/bin/lib/okstra-ctl/main.sh +0 -41
- package/runtime/bin/lib/okstra-ctl/prepare.sh +0 -31
- package/runtime/bin/lib/okstra-ctl/usage.sh +0 -23
- package/runtime/bin/okstra-central.sh +0 -152
- package/runtime/bin/okstra-incremental-carry.py +0 -10
- package/runtime/bin/okstra-incremental-scope.py +0 -10
- package/runtime/bin/okstra-team-reconcile.sh +0 -36
- package/runtime/python/okstra_ctl/agent_prompt_cli.py +0 -1156
- package/runtime/python/okstra_ctl/batch.py +0 -60
- package/runtime/python/okstra_ctl/clarification_items.py +0 -1050
- package/runtime/python/okstra_ctl/container_registry.py +0 -72
- package/runtime/python/okstra_ctl/improvement_assignment.py +0 -61
- package/runtime/python/okstra_ctl/resolver.py +0 -54
- package/runtime/python/okstra_ctl/team_reconcile.py +0 -275
- package/runtime/python/okstra_ctl/tmux.py +0 -134
- package/runtime/python/okstra_ctl/worktree.py +0 -1099
|
@@ -52,6 +52,14 @@ split_task_key() {
|
|
|
52
52
|
TASK_ID="$key_id"
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
# okstra_ctl.interactive_cli 호출 공용 래퍼. 조회 로직은 전부 그 모듈에 있다 —
|
|
56
|
+
# 예전에는 이 파일이 파이썬 heredoc 6개(153줄)로 같은 일을 했고, 셸 문자열 안이라
|
|
57
|
+
# import 도 테스트도 닿지 않았다(docs/coding-rules.md R1).
|
|
58
|
+
_okstra_interactive_cli() {
|
|
59
|
+
PYTHONPATH="${OKSTRA_PYTHONPATH}${PYTHONPATH:+:$PYTHONPATH}" \
|
|
60
|
+
python3 -m okstra_ctl.interactive_cli "$@"
|
|
61
|
+
}
|
|
62
|
+
|
|
55
63
|
resolve_task_root_for_shortcut() {
|
|
56
64
|
local project_root="$1"
|
|
57
65
|
local project_id="$2"
|
|
@@ -59,75 +67,9 @@ resolve_task_root_for_shortcut() {
|
|
|
59
67
|
local task_id="$4"
|
|
60
68
|
|
|
61
69
|
local resolved=""
|
|
62
|
-
resolved="$(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
# task root 의 slug 경로 구성은 okstra_ctl.paths.task_dir(SSOT) 에 위임한다.
|
|
67
|
-
# 과거 이 heredoc 은 slugify 와 `.okstra/tasks/<slug>/<slug>` 구조를 자체
|
|
68
|
-
# 재구현해 규칙 변경 시 silent drift 위험이 있었다. project-resolver.sh 와
|
|
69
|
-
# 동일하게 $OKSTRA_PYTHONPATH 를 sys.path 에 올려 패키지를 import 한다.
|
|
70
|
-
sys.path.insert(0, sys.argv[1])
|
|
71
|
-
from okstra_ctl.paths import task_dir
|
|
72
|
-
|
|
73
|
-
project_root = Path(sys.argv[2])
|
|
74
|
-
project_id = sys.argv[3]
|
|
75
|
-
task_group = sys.argv[4]
|
|
76
|
-
task_id = sys.argv[5]
|
|
77
|
-
|
|
78
|
-
requested_key = f"{project_id}:{task_group}:{task_id}"
|
|
79
|
-
requested_key_ci = requested_key.lower()
|
|
80
|
-
|
|
81
|
-
candidates = []
|
|
82
|
-
|
|
83
|
-
catalog_path = project_root / ".okstra" / "discovery" / "task-catalog.json"
|
|
84
|
-
catalog_keys = []
|
|
85
|
-
if catalog_path.is_file():
|
|
86
|
-
try:
|
|
87
|
-
catalog = json.loads(catalog_path.read_text(encoding="utf-8"))
|
|
88
|
-
except Exception as exc:
|
|
89
|
-
sys.stderr.write(f"resolve_task_root: failed to parse {catalog_path}: {exc}\n")
|
|
90
|
-
catalog = None
|
|
91
|
-
if isinstance(catalog, dict):
|
|
92
|
-
catalog_project_id = catalog.get("projectId")
|
|
93
|
-
tasks = catalog.get("tasks") or []
|
|
94
|
-
for entry in tasks:
|
|
95
|
-
if not isinstance(entry, dict):
|
|
96
|
-
continue
|
|
97
|
-
entry_key = entry.get("taskKey") or ""
|
|
98
|
-
if not isinstance(entry_key, str) or not entry_key:
|
|
99
|
-
continue
|
|
100
|
-
entry_belongs_to_project = (
|
|
101
|
-
catalog_project_id == project_id
|
|
102
|
-
or entry.get("projectId") == project_id
|
|
103
|
-
or entry_key.startswith(f"{project_id}:")
|
|
104
|
-
)
|
|
105
|
-
if entry_belongs_to_project:
|
|
106
|
-
catalog_keys.append(entry_key)
|
|
107
|
-
if entry_key.lower() == requested_key_ci:
|
|
108
|
-
rel = entry.get("taskRootPath") or entry.get("taskRoot")
|
|
109
|
-
if isinstance(rel, str) and rel:
|
|
110
|
-
abs_path = (project_root / rel).resolve() if not os.path.isabs(rel) else Path(rel)
|
|
111
|
-
if abs_path.is_dir():
|
|
112
|
-
print(f"OK\t{abs_path}")
|
|
113
|
-
sys.exit(0)
|
|
114
|
-
candidates.append(str(abs_path))
|
|
115
|
-
|
|
116
|
-
slug_path = task_dir(project_root, task_group, task_id)
|
|
117
|
-
if slug_path.is_dir():
|
|
118
|
-
print(f"OK\t{slug_path}")
|
|
119
|
-
sys.exit(0)
|
|
120
|
-
candidates.append(str(slug_path))
|
|
121
|
-
|
|
122
|
-
# Failure path: emit diagnostics so the wrapper can show them.
|
|
123
|
-
print("MISSING")
|
|
124
|
-
print(f"REQUESTED\t{requested_key}")
|
|
125
|
-
for cand in candidates:
|
|
126
|
-
print(f"TRIED\t{cand}")
|
|
127
|
-
for key in sorted(set(catalog_keys)):
|
|
128
|
-
print(f"AVAILABLE\t{key}")
|
|
129
|
-
PY
|
|
130
|
-
)"
|
|
70
|
+
resolved="$(_okstra_interactive_cli resolve-task-root \
|
|
71
|
+
--project-root "$project_root" --project-id "$project_id" \
|
|
72
|
+
--task-group "$task_group" --task-id "$task_id")"
|
|
131
73
|
|
|
132
74
|
local status=""
|
|
133
75
|
status="$(printf '%s' "$resolved" | head -n 1 | awk -F '\t' '{print $1}')"
|
|
@@ -176,53 +118,17 @@ autofill_from_manifest() {
|
|
|
176
118
|
return 0
|
|
177
119
|
fi
|
|
178
120
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
from pathlib import Path
|
|
182
|
-
|
|
183
|
-
from okstra_ctl.implementation_outcome import reconcile_implementation_outcome
|
|
184
|
-
|
|
185
|
-
try:
|
|
186
|
-
reconcile_implementation_outcome(Path(sys.argv[1]), Path(sys.argv[2]))
|
|
187
|
-
except Exception:
|
|
188
|
-
pass
|
|
189
|
-
PY
|
|
121
|
+
_okstra_interactive_cli reconcile-outcome \
|
|
122
|
+
--project-root "$manifest_project_root" --task-root "$manifest_task_root" || true
|
|
190
123
|
|
|
191
|
-
local need_brief_val need_type_val
|
|
192
|
-
need_brief_val="$([[ -z "$BRIEF_PATH" ]] && printf '1' || printf '0')"
|
|
193
|
-
need_type_val="$([[ -z "$TASK_TYPE" ]] && printf '1' || printf '0')"
|
|
194
124
|
local autofill_output=""
|
|
195
|
-
# autofill 은 편의 기능이라 실패해도 run 을 끊으면 안 된다.
|
|
196
|
-
#
|
|
197
|
-
#
|
|
198
|
-
#
|
|
199
|
-
autofill_output="$(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
from okstra_ctl import next_phase
|
|
203
|
-
|
|
204
|
-
path = sys.argv[1]
|
|
205
|
-
need_brief = sys.argv[2] == "1"
|
|
206
|
-
need_type = sys.argv[3] == "1"
|
|
207
|
-
try:
|
|
208
|
-
data = json.loads(open(path, "r", encoding="utf-8").read())
|
|
209
|
-
except Exception as exc:
|
|
210
|
-
sys.stderr.write(f"autofill_from_manifest: failed to parse {path}: {exc}\n")
|
|
211
|
-
sys.exit(0)
|
|
212
|
-
|
|
213
|
-
brief = ""
|
|
214
|
-
task_type = ""
|
|
215
|
-
if need_brief:
|
|
216
|
-
brief = (data.get("taskBriefPath") or "").strip()
|
|
217
|
-
if need_type:
|
|
218
|
-
# 포인터 판정은 Python SSOT 가 갖는다 — `ready` 가 아니면 빈 문자열이라
|
|
219
|
-
# 셸이 센티널 목록을 따로 들고 있을 이유가 없다.
|
|
220
|
-
task_type = next_phase.autofill_task_type(data)
|
|
221
|
-
|
|
222
|
-
print(f"BRIEF={brief}")
|
|
223
|
-
print(f"TYPE={task_type}")
|
|
224
|
-
PY
|
|
225
|
-
)" || true
|
|
125
|
+
# autofill 은 편의 기능이라 실패해도 run 을 끊으면 안 된다. 모듈이 okstra_ctl 을
|
|
126
|
+
# import 하므로 설치가 깨지면 비-0 으로 끝나는데, okstra.sh 는 `set -euo pipefail`
|
|
127
|
+
# 이라 이 평범한 대입 하나가 run 을 통째로 중단시킨다. 위 reconcile 호출이 같은
|
|
128
|
+
# 이유로 `|| true` 를 달고 있다.
|
|
129
|
+
autofill_output="$(_okstra_interactive_cli autofill --manifest "$manifest_path" \
|
|
130
|
+
$( [[ -z "$BRIEF_PATH" ]] && printf -- "--need-brief" ) \
|
|
131
|
+
$( [[ -z "$TASK_TYPE" ]] && printf -- "--need-type" ))" || true
|
|
226
132
|
|
|
227
133
|
local manifest_brief=""
|
|
228
134
|
local manifest_type=""
|
|
@@ -304,19 +210,8 @@ find_latest_final_report() {
|
|
|
304
210
|
}
|
|
305
211
|
|
|
306
212
|
local found=""
|
|
307
|
-
found="$(
|
|
308
|
-
|
|
309
|
-
import sys
|
|
310
|
-
from okstra_ctl.paths import RunRef
|
|
311
|
-
|
|
312
|
-
task_root, task_type_filter = sys.argv[1:3]
|
|
313
|
-
types = ((task_type_filter,) if task_type_filter
|
|
314
|
-
else ("error-analysis", "requirements-discovery"))
|
|
315
|
-
ref = RunRef.latest_under(task_root, types)
|
|
316
|
-
if ref is not None:
|
|
317
|
-
sys.stdout.write(f"{ref.report}\t{ref.task_type}")
|
|
318
|
-
PY
|
|
319
|
-
)" || return 1
|
|
213
|
+
found="$(_okstra_interactive_cli latest-report \
|
|
214
|
+
--task-root "$task_root" --task-type "$task_type_filter")" || return 1
|
|
320
215
|
|
|
321
216
|
if [[ -z "$found" ]]; then
|
|
322
217
|
printf 'resume-clarification: no final-report found for task %s:%s under %s/runs\n' \
|
|
@@ -386,12 +281,7 @@ run_resume_clarification() {
|
|
|
386
281
|
exit 1
|
|
387
282
|
fi
|
|
388
283
|
local resume_brief_rel=""
|
|
389
|
-
resume_brief_rel="$(
|
|
390
|
-
import json, sys
|
|
391
|
-
data = json.loads(open(sys.argv[1], "r", encoding="utf-8").read())
|
|
392
|
-
print((data.get("taskBriefPath") or "").strip())
|
|
393
|
-
PY
|
|
394
|
-
)"
|
|
284
|
+
resume_brief_rel="$(_okstra_interactive_cli manifest-brief --manifest "$manifest_file")"
|
|
395
285
|
if [[ -z "$resume_brief_rel" ]]; then
|
|
396
286
|
printf 'resume-clarification: manifest missing taskBriefPath: %s\n' "$manifest_file" >&2
|
|
397
287
|
exit 1
|
|
@@ -403,46 +293,9 @@ PY
|
|
|
403
293
|
local resume_extra_args=()
|
|
404
294
|
while IFS= read -r -d '' _arg; do
|
|
405
295
|
resume_extra_args+=("$_arg")
|
|
406
|
-
done < <(
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
from okstra_ctl.run_context import latest_run_inputs
|
|
410
|
-
from okstra_ctl.ids import slugify_task_segment
|
|
411
|
-
|
|
412
|
-
project_root, task_group, task_id, task_type = sys.argv[1:5]
|
|
413
|
-
inputs = latest_run_inputs(
|
|
414
|
-
project_root, task_group, task_id,
|
|
415
|
-
phase_segment=slugify_task_segment(task_type))
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
def emit(flag, value):
|
|
419
|
-
if value:
|
|
420
|
-
sys.stdout.write(flag + "\0" + value + "\0")
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
def model(value):
|
|
424
|
-
# 직전 run 의 모델 display 값. "default"/빈 값은 phase 기본값을 뜻하므로 넘기지
|
|
425
|
-
# 않는다(명시 플래그로 고정하면 안 됨).
|
|
426
|
-
return value if isinstance(value, str) and value not in ("", "default") else ""
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
workers = inputs.get("workers")
|
|
430
|
-
if isinstance(workers, list):
|
|
431
|
-
workers = ",".join(w for w in workers if isinstance(w, str))
|
|
432
|
-
elif not isinstance(workers, str):
|
|
433
|
-
workers = ""
|
|
434
|
-
emit("--workers", workers)
|
|
435
|
-
emit("--lead-model", model(inputs.get("leadModel")))
|
|
436
|
-
emit("--claude-model", model(inputs.get("claudeModel")))
|
|
437
|
-
emit("--codex-model", model(inputs.get("codexModel")))
|
|
438
|
-
emit("--antigravity-model", model(inputs.get("antigravityModel")))
|
|
439
|
-
emit("--report-writer-model", model(inputs.get("reportWriterModel")))
|
|
440
|
-
directive = inputs.get("directive")
|
|
441
|
-
emit("--directive", directive if isinstance(directive, str) else "")
|
|
442
|
-
related = inputs.get("relatedTasks")
|
|
443
|
-
emit("--related-tasks", related if isinstance(related, str) else "")
|
|
444
|
-
PY
|
|
445
|
-
)
|
|
296
|
+
done < <(_okstra_interactive_cli resume-args \
|
|
297
|
+
--project-root "$PROJECT_ROOT" --task-group "$TASK_GROUP" \
|
|
298
|
+
--task-id "$TASK_ID" --task-type "$resolved_type")
|
|
446
299
|
|
|
447
300
|
if [[ "${OKSTRA_RESUME_CLARIFICATION_DRY_RUN:-false}" == "true" ]]; then
|
|
448
301
|
printf 'resume-clarification (dry-run):\n' >&2
|
|
@@ -1,59 +1,36 @@
|
|
|
1
1
|
# shellcheck shell=bash
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
3
|
+
# scripts/okstra_project 리졸버의 bash 래퍼. okstra.sh 가 시작 시 PROJECT_ROOT 를
|
|
4
|
+
# 확정하고 <PROJECT_ROOT>/.okstra/project.json 을 upsert 한다. 과거 conf 파일
|
|
5
|
+
# 모델은 폐기되었다.
|
|
6
|
+
#
|
|
7
|
+
# 해석 자체는 `okstra_ctl.project_setup_cli` 한 곳에만 있다. 예전에는 이 파일이
|
|
8
|
+
# 파이썬 heredoc 4개로 같은 해석을 다시 적었고, TS 쪽(config/setup/check-project)
|
|
9
|
+
# 도 각자 한 벌씩 더 갖고 있었다 — 갈라져도 아무도 몰랐다.
|
|
6
10
|
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
# PYTHONPATH 는 호출 시점의 $OKSTRA_PYTHONPATH 를 앞에 둔다(설치본/레포 양쪽).
|
|
12
|
+
_okstra_project_cli() {
|
|
13
|
+
PYTHONPATH="${OKSTRA_PYTHONPATH}${PYTHONPATH:+:$PYTHONPATH}" \
|
|
14
|
+
python3 -m okstra_ctl.project_setup_cli "$@"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
# 절대경로를 stdout 으로. 실패 시 stderr 에 메시지를 남기고 비-0 종료.
|
|
10
18
|
resolve_project_root_strict() {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
sys.path.insert(0, sys.argv[1])
|
|
15
|
-
from okstra_project import resolve_project_root, ResolverError
|
|
16
|
-
explicit = sys.argv[2] if len(sys.argv) > 2 else ""
|
|
17
|
-
try:
|
|
18
|
-
p = resolve_project_root(explicit_root=explicit, cwd=os.getcwd())
|
|
19
|
-
except ResolverError as exc:
|
|
20
|
-
sys.stderr.write(f"resolve_project_root: {exc}\n")
|
|
21
|
-
sys.exit(1)
|
|
22
|
-
print(p)
|
|
23
|
-
PY
|
|
19
|
+
_okstra_project_cli resolve-root \
|
|
20
|
+
--explicit-root "${1-}" --cwd "$PWD" \
|
|
21
|
+
--on-error fail --error-prefix "resolve_project_root: " --error-code 1
|
|
24
22
|
}
|
|
25
23
|
|
|
26
24
|
# 실패해도 0 으로 종료하고 stdout 은 빈 문자열(autofill 등 best-effort 경로용).
|
|
27
25
|
resolve_project_root_safe() {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
import os, sys
|
|
31
|
-
sys.path.insert(0, sys.argv[1])
|
|
32
|
-
from okstra_project import resolve_project_root, ResolverError
|
|
33
|
-
explicit = sys.argv[2] if len(sys.argv) > 2 else ""
|
|
34
|
-
try:
|
|
35
|
-
p = resolve_project_root(explicit_root=explicit, cwd=os.getcwd())
|
|
36
|
-
except ResolverError:
|
|
37
|
-
sys.exit(0)
|
|
38
|
-
print(p)
|
|
39
|
-
PY
|
|
26
|
+
_okstra_project_cli resolve-root \
|
|
27
|
+
--explicit-root "${1-}" --cwd "$PWD" --on-error empty
|
|
40
28
|
}
|
|
41
29
|
|
|
42
30
|
# project.json upsert. 충돌(projectId 불일치) 시 비-0 종료 + stderr 메시지.
|
|
43
31
|
upsert_project_json() {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
python3 - "$OKSTRA_PYTHONPATH" "$project_root" "$project_id" <<'PY'
|
|
47
|
-
import sys
|
|
48
|
-
sys.path.insert(0, sys.argv[1])
|
|
49
|
-
from pathlib import Path
|
|
50
|
-
from okstra_project import upsert_project_json, ResolverError
|
|
51
|
-
try:
|
|
52
|
-
upsert_project_json(Path(sys.argv[2]), sys.argv[3])
|
|
53
|
-
except ResolverError as exc:
|
|
54
|
-
sys.stderr.write(f"project.json upsert failed: {exc}\n")
|
|
55
|
-
sys.exit(1)
|
|
56
|
-
PY
|
|
32
|
+
_okstra_project_cli upsert \
|
|
33
|
+
--project-root "$1" --project-id "$2" --format strict
|
|
57
34
|
}
|
|
58
35
|
|
|
59
36
|
# `okstra setup` 이 이미 기록한 값을 다시 묻지 않기 위한 자동 채움. 프로젝트
|
|
@@ -61,23 +38,8 @@ PY
|
|
|
61
38
|
autofill_from_project_json() {
|
|
62
39
|
[[ -n "$PROJECT_ID" && -n "$PROJECT_ROOT" ]] && return 0
|
|
63
40
|
local resolved
|
|
64
|
-
resolved="$(
|
|
65
|
-
|
|
66
|
-
from pathlib import Path
|
|
67
|
-
sys.path.insert(0, sys.argv[1])
|
|
68
|
-
from okstra_project import project_json_path
|
|
69
|
-
from okstra_project.resolver import resolve_project_root
|
|
70
|
-
try:
|
|
71
|
-
root = resolve_project_root(explicit_root=sys.argv[2] or "")
|
|
72
|
-
except Exception:
|
|
73
|
-
sys.exit(0)
|
|
74
|
-
path = project_json_path(Path(root))
|
|
75
|
-
if not path.is_file():
|
|
76
|
-
sys.exit(0)
|
|
77
|
-
data = json.loads(path.read_text(encoding="utf-8"))
|
|
78
|
-
print(f"{data.get('projectId', '')}\t{root}")
|
|
79
|
-
PY
|
|
80
|
-
)"
|
|
41
|
+
resolved="$(_okstra_project_cli project-json \
|
|
42
|
+
--explicit-root "$PROJECT_ROOT_OVERRIDE" || true)"
|
|
81
43
|
[[ -z "$resolved" ]] && return 0
|
|
82
44
|
[[ -z "$PROJECT_ID" ]] && PROJECT_ID="${resolved%%$'\t'*}"
|
|
83
45
|
[[ -z "$PROJECT_ROOT" ]] && PROJECT_ROOT="${resolved##*$'\t'}"
|
|
@@ -11,7 +11,7 @@ summary:
|
|
|
11
11
|
|
|
12
12
|
Skills, worker agents, and the codex wrapper are installed once per user under
|
|
13
13
|
~/.claude and ~/.okstra by scripts/okstra-install.sh. The user's settings.json
|
|
14
|
-
is never modified; okstra
|
|
14
|
+
is never modified; `okstra setup` and the prepare path provision the project's
|
|
15
15
|
.claude/settings.local.json as a symlink to ~/.okstra/templates/settings.local.json,
|
|
16
16
|
which Claude Code auto-loads.
|
|
17
17
|
|
|
@@ -99,7 +99,7 @@ options:
|
|
|
99
99
|
--claude-model Model for Claude worker. Default: OKSTRA_DEFAULT_CLAUDE_MODEL or opus
|
|
100
100
|
--codex-model Model for Codex worker. Default: OKSTRA_DEFAULT_CODEX_MODEL or gpt-5.6-sol
|
|
101
101
|
--antigravity-model Model for Antigravity worker. Default: OKSTRA_DEFAULT_ANTIGRAVITY_MODEL or gemini-3.1-pro
|
|
102
|
-
--worker-model Provider-qualified worker override CSV, e.g. grok=grok-4.
|
|
102
|
+
--worker-model Provider-qualified worker override CSV, e.g. grok=grok-4.6,kimi=kimi-k3.
|
|
103
103
|
--report-writer-provider
|
|
104
104
|
Provider for report writer. Supported: claude, codex. Default: claude.
|
|
105
105
|
--report-writer-model
|
|
@@ -136,7 +136,7 @@ model defaults:
|
|
|
136
136
|
Codex worker: OKSTRA_DEFAULT_CODEX_MODEL or gpt-5.6-sol
|
|
137
137
|
Antigravity worker: OKSTRA_DEFAULT_ANTIGRAVITY_MODEL or gemini-3.1-pro
|
|
138
138
|
Grok worker: grok-4.6
|
|
139
|
-
Kimi worker: kimi-
|
|
139
|
+
Kimi worker: kimi-k3
|
|
140
140
|
Implementation executor: OKSTRA_DEFAULT_EXECUTOR or claude (one of: claude | codex | antigravity | grok | kimi)
|
|
141
141
|
|
|
142
142
|
output:
|
|
@@ -16,11 +16,7 @@ home="${OKSTRA_HOME:-$HOME/.okstra}"
|
|
|
16
16
|
export PYTHONPATH="${_dir}:${home}/lib/python${PYTHONPATH:+:$PYTHONPATH}"
|
|
17
17
|
|
|
18
18
|
_stdin="$(cat 2>/dev/null || true)"
|
|
19
|
-
cwd="$(printf '%s' "$_stdin" | python3 -
|
|
20
|
-
try:
|
|
21
|
-
print(json.load(sys.stdin).get("cwd","") or "")
|
|
22
|
-
except Exception:
|
|
23
|
-
pass' 2>/dev/null || true)"
|
|
19
|
+
cwd="$(printf '%s' "$_stdin" | python3 -m okstra_ctl.pane_reclaim --cwd-from-hook-stdin 2>/dev/null || true)"
|
|
24
20
|
[ -n "$cwd" ] || cwd="$PWD"
|
|
25
21
|
|
|
26
22
|
while IFS= read -r run_dir; do
|
|
@@ -8,9 +8,15 @@ re-exports the writer's names so the contract tests keep reading one module.
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import argparse
|
|
11
|
+
import sys
|
|
11
12
|
from pathlib import Path
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
15
|
+
from okstra_bootstrap import prefer_colocated_modules # noqa: E402
|
|
16
|
+
|
|
17
|
+
prefer_colocated_modules(__file__, "okstra_ctl/error_log_write.py")
|
|
18
|
+
|
|
19
|
+
from okstra_ctl.error_log_write import ( # noqa: E402
|
|
14
20
|
ALLOWED_AGENT_ROLES,
|
|
15
21
|
ALLOWED_AGENTS,
|
|
16
22
|
ALLOWED_CAUSES,
|
|
@@ -48,8 +54,19 @@ __all__ = [
|
|
|
48
54
|
]
|
|
49
55
|
|
|
50
56
|
|
|
57
|
+
_CLI_EPILOG = r"""Usage:
|
|
58
|
+
okstra error-log <subcommand> [...] # e.g. append-observed / append-from-worker
|
|
59
|
+
|
|
60
|
+
See `okstra error-log append-observed --help` for that subcommand's options.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
|
|
51
64
|
def _build_parser():
|
|
52
|
-
p = argparse.ArgumentParser(
|
|
65
|
+
p = argparse.ArgumentParser(
|
|
66
|
+
prog="okstra error-log",
|
|
67
|
+
epilog=_CLI_EPILOG,
|
|
68
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
69
|
+
description="OKSTRA error log helper")
|
|
53
70
|
sub = p.add_subparsers(dest="cmd", required=True)
|
|
54
71
|
|
|
55
72
|
obs = sub.add_parser("append-observed",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""한 모듈이 현재 PYTHONPATH 로 import 되는지 확인한다 — `okstra doctor` 전용.
|
|
3
|
+
|
|
4
|
+
별도 파일인 이유: 이 프로브는 `okstra_ctl` 자체의 import 가능성도 검사한다.
|
|
5
|
+
`python3 -m okstra_ctl.<x>` 로 부르면 검사 대상이 못 뜰 때 프로브도 같이 죽어
|
|
6
|
+
"모듈이 없다"와 "프로브가 없다"를 구분할 수 없다. 그래서 okstra 를 import 하지
|
|
7
|
+
않는 독립 파일로 두고 경로로 호출한다.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import importlib
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def main(argv: list[str]) -> int:
|
|
16
|
+
if len(argv) != 1:
|
|
17
|
+
sys.stderr.write("usage: okstra-import-check.py <module>\n")
|
|
18
|
+
return 2
|
|
19
|
+
name = argv[0]
|
|
20
|
+
module = importlib.import_module(name)
|
|
21
|
+
print(getattr(module, "__name__", name))
|
|
22
|
+
return 0
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
@@ -21,10 +21,10 @@ import argparse
|
|
|
21
21
|
import sys
|
|
22
22
|
from pathlib import Path
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
25
|
+
from okstra_bootstrap import prefer_colocated_modules # noqa: E402
|
|
26
|
+
|
|
27
|
+
prefer_colocated_modules(__file__, "okstra_ctl/render_final_report.py")
|
|
28
28
|
|
|
29
29
|
from okstra_ctl.i18n import SUPPORTED_LANGS # noqa: E402
|
|
30
30
|
from okstra_ctl.render_final_report import ( # noqa: E402
|
|
@@ -35,6 +35,7 @@ from okstra_ctl.render_final_report import ( # noqa: E402
|
|
|
35
35
|
|
|
36
36
|
def main(argv: list[str]) -> int:
|
|
37
37
|
parser = argparse.ArgumentParser(
|
|
38
|
+
prog="okstra inject-report-index",
|
|
38
39
|
description="Inject the top-of-report index + scroll anchors into a free-form markdown report.",
|
|
39
40
|
)
|
|
40
41
|
parser.add_argument(
|
|
@@ -9,23 +9,16 @@ write scope in the order the CLIs are told it, and the role's idle budget.
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
11
|
import json
|
|
12
|
-
import os
|
|
13
12
|
import shutil
|
|
14
13
|
import sys
|
|
15
14
|
from dataclasses import dataclass
|
|
16
15
|
from pathlib import Path
|
|
17
16
|
from typing import Any, Callable, Mapping
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
_HOME_LIB = (
|
|
24
|
-
Path(os.environ.get("OKSTRA_HOME", str(Path.home() / ".okstra"))) / "lib" / "python"
|
|
25
|
-
)
|
|
26
|
-
sys.path.insert(0, str(_HERE))
|
|
27
|
-
if _HOME_LIB.is_dir() and str(_HOME_LIB) not in sys.path:
|
|
28
|
-
sys.path.append(str(_HOME_LIB))
|
|
18
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
19
|
+
from okstra_bootstrap import prefer_colocated_modules # noqa: E402
|
|
20
|
+
|
|
21
|
+
prefer_colocated_modules(__file__, "okstra_ctl/domain/provider.py")
|
|
29
22
|
|
|
30
23
|
from okstra_ctl.domain.provider import ( # noqa: E402
|
|
31
24
|
ProviderSpec,
|
|
@@ -54,7 +47,7 @@ from okstra_ctl.write_policy import ( # noqa: E402
|
|
|
54
47
|
write_policy_from_payload,
|
|
55
48
|
)
|
|
56
49
|
from okstra_ctl.model_pool import ModelPool # noqa: E402
|
|
57
|
-
from okstra_ctl.
|
|
50
|
+
from okstra_ctl.agent.invocation import ( # noqa: E402
|
|
58
51
|
AgentInvocationError,
|
|
59
52
|
agent_model_assignment_from_payload,
|
|
60
53
|
invocation_metadata_identity,
|
|
@@ -259,11 +252,12 @@ def _v2_status_extra(
|
|
|
259
252
|
recorded = project_root / recorded
|
|
260
253
|
if recorded.resolve(strict=False) != prompt_path.resolve(strict=True):
|
|
261
254
|
raise PreflightError(64, "invocation metadata prompt does not match wrapper")
|
|
262
|
-
role_execution,
|
|
255
|
+
role_execution, attempt_row, pool = _execution_authority(
|
|
263
256
|
metadata=metadata,
|
|
264
257
|
project_root=project_root,
|
|
265
258
|
role_execution_ref=identity.role_execution_ref,
|
|
266
259
|
invocation_ref=identity.invocation_ref,
|
|
260
|
+
attempt=identity.attempt,
|
|
267
261
|
)
|
|
268
262
|
binding = role_execution.binding
|
|
269
263
|
if (
|
|
@@ -290,9 +284,9 @@ def _v2_status_extra(
|
|
|
290
284
|
return ""
|
|
291
285
|
|
|
292
286
|
try:
|
|
293
|
-
write_policy = write_policy_from_payload(
|
|
287
|
+
write_policy = write_policy_from_payload(attempt_row.write_policy)
|
|
294
288
|
write_enforcement = write_enforcement_from_payload(
|
|
295
|
-
|
|
289
|
+
attempt_row.write_enforcement
|
|
296
290
|
)
|
|
297
291
|
except ValueError as exc:
|
|
298
292
|
raise PreflightError(64, f"invocation write contract is invalid: {exc}") from exc
|
|
@@ -312,7 +306,7 @@ def _v2_status_extra(
|
|
|
312
306
|
"level": "unknown",
|
|
313
307
|
"source": "unavailable",
|
|
314
308
|
},
|
|
315
|
-
"writePolicyDigest":
|
|
309
|
+
"writePolicyDigest": attempt_row.write_policy_digest,
|
|
316
310
|
"writeEnforcement": write_enforcement.to_payload(),
|
|
317
311
|
}, verify_attestation, write_policy, write_enforcement)
|
|
318
312
|
|
|
@@ -323,6 +317,7 @@ def _execution_authority(
|
|
|
323
317
|
project_root: Path,
|
|
324
318
|
role_execution_ref: str,
|
|
325
319
|
invocation_ref: str,
|
|
320
|
+
attempt: int,
|
|
326
321
|
):
|
|
327
322
|
source = metadata.get("contractSource")
|
|
328
323
|
manifest_raw = source.get("runManifestPath") if isinstance(source, Mapping) else None
|
|
@@ -353,9 +348,19 @@ def _execution_authority(
|
|
|
353
348
|
raise PreflightError(
|
|
354
349
|
64, "invocation metadata invocation does not match run manifest"
|
|
355
350
|
)
|
|
351
|
+
# 쓰기 계약은 이 시도의 행에 있다. invocation 으로 찾으면 재시도가 1회차의
|
|
352
|
+
# 허용 경로를 물고 자기 로그·상태 사이드카를 못 쓴다.
|
|
353
|
+
attempt_row = next((
|
|
354
|
+
row for row in manifest.attempts
|
|
355
|
+
if row.invocation_ref == invocation_ref and row.attempt == attempt
|
|
356
|
+
), None)
|
|
357
|
+
if attempt_row is None:
|
|
358
|
+
raise PreflightError(
|
|
359
|
+
64, "invocation metadata attempt does not match run manifest"
|
|
360
|
+
)
|
|
356
361
|
return (
|
|
357
362
|
role_execution,
|
|
358
|
-
|
|
363
|
+
attempt_row,
|
|
359
364
|
ModelPool.from_registry(default_provider_registry()),
|
|
360
365
|
)
|
|
361
366
|
|
|
@@ -19,12 +19,10 @@ import argparse
|
|
|
19
19
|
import sys
|
|
20
20
|
from pathlib import Path
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# scripts; for in-repo invocation we add ``scripts/`` explicitly.
|
|
27
|
-
sys.path.insert(0, str(_HERE))
|
|
22
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
23
|
+
from okstra_bootstrap import prefer_colocated_modules # noqa: E402
|
|
24
|
+
|
|
25
|
+
prefer_colocated_modules(__file__, "okstra_ctl/render_final_report.py")
|
|
28
26
|
|
|
29
27
|
from okstra_ctl.final_report_paths import final_report_markdown_path # noqa: E402
|
|
30
28
|
from okstra_ctl.render_final_report import ( # noqa: E402
|
|
@@ -34,8 +32,20 @@ from okstra_ctl.render_final_report import ( # noqa: E402
|
|
|
34
32
|
)
|
|
35
33
|
|
|
36
34
|
|
|
35
|
+
_CLI_EPILOG = r"""Usage:
|
|
36
|
+
okstra render-final-report <path-to-final-report.data.json>
|
|
37
|
+
|
|
38
|
+
schemaVersion 1.0
|
|
39
|
+
keeps the legacy Markdown template; schemaVersion 2.0 selects the full reading
|
|
40
|
+
copy template. Human HTML is rendered separately from the same data.json.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
|
|
37
44
|
def main(argv: list[str]) -> int:
|
|
38
45
|
parser = argparse.ArgumentParser(
|
|
46
|
+
prog="okstra render-final-report",
|
|
47
|
+
epilog=_CLI_EPILOG,
|
|
48
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
39
49
|
description="Render a final-report markdown from its JSON SSOT.",
|
|
40
50
|
)
|
|
41
51
|
parser.add_argument(
|