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
|
@@ -14,7 +14,11 @@ from pathlib import Path
|
|
|
14
14
|
from typing import Any, Mapping
|
|
15
15
|
|
|
16
16
|
from .clarification_items import USER_INPUT_BLOCKS, progress_blocking_ids
|
|
17
|
-
from .final_report_paths import
|
|
17
|
+
from .final_report_paths import (
|
|
18
|
+
final_report_data_path,
|
|
19
|
+
final_report_markdown_path,
|
|
20
|
+
is_full_reading_copy_path,
|
|
21
|
+
)
|
|
18
22
|
from .exact_coverage import ExactCoverageError, calculate_plan_exact_coverage
|
|
19
23
|
from .final_report_schema import (
|
|
20
24
|
SchemaError,
|
|
@@ -32,8 +36,12 @@ from .user_response import UserResponseError, parse_direction_selection
|
|
|
32
36
|
|
|
33
37
|
|
|
34
38
|
_TASK_TYPE = "implementation-option-selection"
|
|
39
|
+
# 손잡이는 리포트 **기록**이다. 전체 열람본(`.md`)은 `2bcd575` 이후 완료 산출물이
|
|
40
|
+
# 아니라 요청 시 렌더라(`dispatch_state._required_worker_artifacts`) run 의 reports
|
|
41
|
+
# 디렉터리에 없다. `--approved-plan` 이 이미 같은 이유로 기록만 받는다
|
|
42
|
+
# (`final_report_paths.require_approved_plan_record`).
|
|
35
43
|
_REPORT_RE = re.compile(
|
|
36
|
-
r"^final-report-implementation-option-selection-(?P<seq>\d{3,})\.
|
|
44
|
+
r"^final-report-implementation-option-selection-(?P<seq>\d{3,})\.data\.json$"
|
|
37
45
|
)
|
|
38
46
|
_FRONTMATTER_RE = re.compile(
|
|
39
47
|
r"\A---[ \t]*\r?\n(?P<body>.*?)(?:\r?\n)---[ \t]*(?:\r?\n|\Z)",
|
|
@@ -138,13 +146,6 @@ def _selection_layout(report: Path) -> tuple[Path, str]:
|
|
|
138
146
|
return task_root, match.group("seq")
|
|
139
147
|
|
|
140
148
|
|
|
141
|
-
def _sibling_data_path(report: Path) -> Path:
|
|
142
|
-
data_path = _strict_regular_file(final_report_data_path(report), "data")
|
|
143
|
-
if data_path.parent != report.parent:
|
|
144
|
-
raise DirectionSelectionError("data file must be a sibling of the report")
|
|
145
|
-
return data_path
|
|
146
|
-
|
|
147
|
-
|
|
148
149
|
def _parse_data(data_path: Path) -> tuple[dict[str, Any], bytes]:
|
|
149
150
|
try:
|
|
150
151
|
snapshot = load_owned_object_snapshot(
|
|
@@ -215,7 +216,7 @@ def _comparison_selection(
|
|
|
215
216
|
task_root: Path,
|
|
216
217
|
seq: str,
|
|
217
218
|
expected_task_key: str,
|
|
218
|
-
) -> tuple[str, str, str,
|
|
219
|
+
) -> tuple[str, str, str, tuple[str, ...]]:
|
|
219
220
|
sidecar = _strict_regular_file(
|
|
220
221
|
report.parent.parent
|
|
221
222
|
/ "user-responses"
|
|
@@ -253,7 +254,6 @@ def _comparison_selection(
|
|
|
253
254
|
return (
|
|
254
255
|
_relative_source(sidecar, task_root, "selection evidence"),
|
|
255
256
|
parsed.option_id,
|
|
256
|
-
parsed.option_name,
|
|
257
257
|
parsed.selection_note,
|
|
258
258
|
constraints,
|
|
259
259
|
)
|
|
@@ -261,7 +261,7 @@ def _comparison_selection(
|
|
|
261
261
|
|
|
262
262
|
def _preselected_selection(
|
|
263
263
|
selection: Mapping[str, Any],
|
|
264
|
-
) -> tuple[str, str, str,
|
|
264
|
+
) -> tuple[str, str, str, tuple[str, ...]]:
|
|
265
265
|
if selection.get("routing") != "implementation-planning":
|
|
266
266
|
raise DirectionSelectionError(
|
|
267
267
|
"preselected direction routing must be implementation-planning"
|
|
@@ -276,12 +276,21 @@ def _preselected_selection(
|
|
|
276
276
|
raise DirectionSelectionError(
|
|
277
277
|
"preselected direction evidence and citation are required"
|
|
278
278
|
)
|
|
279
|
-
return f"{confirmation} ({citation})", option_id, "",
|
|
279
|
+
return f"{confirmation} ({citation})", option_id, "", ()
|
|
280
280
|
|
|
281
281
|
|
|
282
282
|
def _selected_option(
|
|
283
|
-
selection: Mapping[str, Any], option_id: str
|
|
283
|
+
selection: Mapping[str, Any], option_id: str
|
|
284
284
|
) -> tuple[Mapping[str, Any], str]:
|
|
285
|
+
"""선택된 후보를 **id 로만** 특정한다.
|
|
286
|
+
|
|
287
|
+
사이드카의 `Option-Name` 은 대조하지 않는다. HTML 열람본은 번역 오버레이를
|
|
288
|
+
적용한 사본으로 렌더되므로(`report_html/render.py` `_localize`) Export 가
|
|
289
|
+
적는 이름은 독자의 언어다 — `reportLanguage` 가 `en` 이 아닌 런에서 영어
|
|
290
|
+
정본과의 바이트 비교는 통과할 수 있는 값이 하나도 없었다. id 는 번역되지
|
|
291
|
+
않으므로 신원은 id 가 온전히 결정하고, 하류로 나가는 이름은 아래에서
|
|
292
|
+
리포트 값으로 정규화된다.
|
|
293
|
+
"""
|
|
285
294
|
options = selection.get("rankedOptions")
|
|
286
295
|
if not isinstance(options, list):
|
|
287
296
|
raise DirectionSelectionError("ranked candidate list is missing")
|
|
@@ -297,10 +306,8 @@ def _selected_option(
|
|
|
297
306
|
)
|
|
298
307
|
except ValueError as exc:
|
|
299
308
|
raise DirectionSelectionError(str(exc)) from exc
|
|
300
|
-
if report_option_id != option_id
|
|
301
|
-
|
|
302
|
-
):
|
|
303
|
-
raise DirectionSelectionError("selected candidate name does not match report")
|
|
309
|
+
if report_option_id != option_id:
|
|
310
|
+
raise DirectionSelectionError("selected candidate id does not match report")
|
|
304
311
|
coverage = option.get("coverageSummary")
|
|
305
312
|
if not isinstance(coverage, Mapping) or coverage.get("coverageVerdict") != "exact":
|
|
306
313
|
raise DirectionSelectionError("selected candidate must have exact coverage")
|
|
@@ -340,12 +347,26 @@ def resolve_selected_direction(
|
|
|
340
347
|
report_path: Path,
|
|
341
348
|
expected_task_key: str,
|
|
342
349
|
) -> SelectedDirection:
|
|
343
|
-
"""Validate a selection report in the documented fail-closed order.
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
350
|
+
"""Validate a selection report record in the documented fail-closed order.
|
|
351
|
+
|
|
352
|
+
손잡이는 `.data.json` 이다. 전체 열람본은 어디서도 열리지 않는다 — 사이드카의
|
|
353
|
+
`source-report` 와 대조할 이름으로만 쓰인다. 그 파일을 실물로 요구하는 동안
|
|
354
|
+
이 게이트는 통과할 수 있는 입력이 0개였고, 후보 비교가 끝나도 계획으로 넘어갈
|
|
355
|
+
길이 없었다. 실측: fontsninja-v3-site 의 선택 리포트 3쌍 전부 열람본이 없다.
|
|
356
|
+
"""
|
|
357
|
+
handle = lexical_absolute_path(Path(report_path))
|
|
358
|
+
if is_full_reading_copy_path(handle):
|
|
359
|
+
raise DirectionSelectionError(
|
|
360
|
+
"selected direction must be the report record (.data.json), not the "
|
|
361
|
+
f"full reading copy: {report_path}\n"
|
|
362
|
+
f" use: {final_report_data_path(handle)}"
|
|
363
|
+
)
|
|
364
|
+
data_path = _strict_regular_file(handle, "data")
|
|
365
|
+
task_root, seq = _selection_layout(data_path)
|
|
348
366
|
data_path = validate_task_artifact_path(data_path, task_root, "data")
|
|
367
|
+
# 사이드카의 `source-report` 는 열람본 이름을 적는다. 그 파일을 열지는 않는다 —
|
|
368
|
+
# 대조할 이름일 뿐이다.
|
|
369
|
+
report = final_report_markdown_path(data_path)
|
|
349
370
|
data, data_bytes = _parse_data(data_path)
|
|
350
371
|
_validate_report_identity(data, expected_task_key)
|
|
351
372
|
_validate_schema(data)
|
|
@@ -354,7 +375,7 @@ def resolve_selected_direction(
|
|
|
354
375
|
raise DirectionSelectionError("implementation option selection data is missing")
|
|
355
376
|
mode = str(selection.get("mode") or "")
|
|
356
377
|
if mode == "candidate-comparison":
|
|
357
|
-
evidence, option_id,
|
|
378
|
+
evidence, option_id, note, constraints = _comparison_selection(
|
|
358
379
|
report=report,
|
|
359
380
|
data_path=data_path,
|
|
360
381
|
data_bytes=data_bytes,
|
|
@@ -363,14 +384,10 @@ def resolve_selected_direction(
|
|
|
363
384
|
expected_task_key=expected_task_key,
|
|
364
385
|
)
|
|
365
386
|
elif mode == "preselected-validation":
|
|
366
|
-
evidence, option_id,
|
|
367
|
-
selection
|
|
368
|
-
)
|
|
387
|
+
evidence, option_id, note, constraints = _preselected_selection(selection)
|
|
369
388
|
else:
|
|
370
389
|
raise DirectionSelectionError(f"unsupported selection mode: {mode}")
|
|
371
|
-
option, normalized_option_name = _selected_option(
|
|
372
|
-
selection, option_id, option_name
|
|
373
|
-
)
|
|
390
|
+
option, normalized_option_name = _selected_option(selection, option_id)
|
|
374
391
|
_validate_no_blockers(data, option)
|
|
375
392
|
return SelectedDirection(
|
|
376
393
|
mode=mode,
|
|
@@ -439,7 +456,7 @@ _PLAN_EXECUTION_FIELDS = (
|
|
|
439
456
|
)
|
|
440
457
|
|
|
441
458
|
|
|
442
|
-
def
|
|
459
|
+
def load_selected_direction_snapshot(
|
|
443
460
|
snapshot_path: Path,
|
|
444
461
|
) -> tuple[SelectedDirectionSnapshot | None, list[str]]:
|
|
445
462
|
path = lexical_absolute_path(Path(snapshot_path))
|
|
@@ -484,9 +501,16 @@ def validate_selected_direction_ref(
|
|
|
484
501
|
"the selected-direction snapshot"
|
|
485
502
|
)
|
|
486
503
|
if ref.get("snapshotPath") != snapshot.relative_path:
|
|
504
|
+
# 기대값을 이름으로 댄다. `sourceReport` / `sourceDataSha256` / `optionId`
|
|
505
|
+
# 는 스냅샷 파일에 그대로 실려 있어 저자가 옮겨 적으면 되지만,
|
|
506
|
+
# `snapshotPath` 는 저자가 직접 만들어야 하고 그 기준점(태스크 루트)은
|
|
507
|
+
# 스키마에도 프롬프트에도 적혀 있지 않았다. 무엇과 다른지 말하지 않는
|
|
508
|
+
# 실패는 실행이 스스로 고칠 수 없다.
|
|
487
509
|
failures.append(
|
|
488
510
|
"selectedDirectionRef.snapshotPath is missing or does not match the "
|
|
489
|
-
"actual selected-direction snapshot path"
|
|
511
|
+
"actual selected-direction snapshot path; expected the task-root "
|
|
512
|
+
f"relative {snapshot.relative_path!r}, got "
|
|
513
|
+
f"{ref.get('snapshotPath')!r}"
|
|
490
514
|
)
|
|
491
515
|
if ref.get("snapshotSha256") != snapshot.sha256:
|
|
492
516
|
failures.append(
|
|
@@ -774,6 +798,89 @@ def _declared_coverage_summary_errors(
|
|
|
774
798
|
]
|
|
775
799
|
|
|
776
800
|
|
|
801
|
+
# stage 를 게이트하는 검증 행이 implementation run 안에서 실행 가능함을 강제하는
|
|
802
|
+
# 마커. 실측 실패값(dev-10341 VC-013/VC-014)에서 왔다: 수동 워크스루·배포 전제
|
|
803
|
+
# 문구가 stageRefs 를 단 채 실리면, implementation run 은 배포 금지·자격증명
|
|
804
|
+
# 부재라 그 행을 영원히 통과시킬 수 없고 코드 결함 0건인 stage 가 차단된다.
|
|
805
|
+
# 그런 검증은 브리프의 External Gates / final-verification 의 user-owned
|
|
806
|
+
# external QA 소속이다.
|
|
807
|
+
_MANUAL_VALIDATION_MARKERS = (
|
|
808
|
+
"by hand",
|
|
809
|
+
"manually",
|
|
810
|
+
"redeploy",
|
|
811
|
+
"deployment",
|
|
812
|
+
"preproduction",
|
|
813
|
+
"signed in",
|
|
814
|
+
)
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
def _stage_validation_executability_errors(
|
|
818
|
+
planning: Mapping[str, Any],
|
|
819
|
+
) -> list[str]:
|
|
820
|
+
failures: list[str] = []
|
|
821
|
+
for row in planning.get("validationChecklist") or ():
|
|
822
|
+
if not isinstance(row, Mapping) or not row.get("stageRefs"):
|
|
823
|
+
continue
|
|
824
|
+
lowered = str(row.get("commandOrObservation") or "").lower()
|
|
825
|
+
matched = [
|
|
826
|
+
marker for marker in _MANUAL_VALIDATION_MARKERS if marker in lowered
|
|
827
|
+
]
|
|
828
|
+
if matched:
|
|
829
|
+
failures.append(
|
|
830
|
+
f"validationChecklist {row.get('id')} gates stage(s) "
|
|
831
|
+
f"{list(row.get('stageRefs') or ())} but is not executable by the "
|
|
832
|
+
f"implementation run (marker(s): {matched}); move manual or "
|
|
833
|
+
"deployed-environment verification to the brief's External Gates "
|
|
834
|
+
"or final-verification's user-owned external QA"
|
|
835
|
+
)
|
|
836
|
+
return failures
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
def _is_config_only_path(path: str) -> bool:
|
|
840
|
+
name = posixpath.basename(posixpath.normpath(str(path).replace("\\", "/")))
|
|
841
|
+
if name == "Dockerfile" or name.startswith("Dockerfile."):
|
|
842
|
+
return True
|
|
843
|
+
if name.startswith("docker-compose") or name.startswith(".env"):
|
|
844
|
+
return True
|
|
845
|
+
return name.endswith((".yml", ".yaml"))
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
def _micro_stage_fold_errors(planning: Mapping[str, Any]) -> list[str]:
|
|
849
|
+
"""설정 파일 전용 종속 stage 는 독립 stage 가 아니다 — 커밋으로만 나눈다.
|
|
850
|
+
|
|
851
|
+
실측(dev-10341): 다른 stage 가 도입한 플래그를 Dockerfile/compose 2줄,
|
|
852
|
+
workflow 2줄로 전파하는 작업이 stage 2·3 을 각각 차지해 run 2회(회당
|
|
853
|
+
30분+)와 검증 차단 1회를 낳았다. 값 전파는 도입 stage 의 스텝이고,
|
|
854
|
+
분리가 필요하면 커밋을 나눈다. 첫 stage(의존 없음)는 예외다 — 설정만
|
|
855
|
+
바꾸는 태스크 자체는 정당하다.
|
|
856
|
+
"""
|
|
857
|
+
dependent: dict[int, bool] = {}
|
|
858
|
+
for row in planning.get("stageMap") or ():
|
|
859
|
+
if isinstance(row, Mapping) and isinstance(row.get("stage"), int):
|
|
860
|
+
raw = str(row.get("dependsOn") or "").strip().lower()
|
|
861
|
+
dependent[row["stage"]] = raw not in ("", "(none)", "none")
|
|
862
|
+
failures: list[str] = []
|
|
863
|
+
for stage in planning.get("stages") or ():
|
|
864
|
+
if not isinstance(stage, Mapping):
|
|
865
|
+
continue
|
|
866
|
+
number = stage.get("stage")
|
|
867
|
+
if not isinstance(number, int) or not dependent.get(number):
|
|
868
|
+
continue
|
|
869
|
+
paths = [
|
|
870
|
+
str(path)
|
|
871
|
+
for step in stage.get("stepwiseExecution") or ()
|
|
872
|
+
if isinstance(step, Mapping)
|
|
873
|
+
for path in step.get("plannedPaths") or ()
|
|
874
|
+
]
|
|
875
|
+
if paths and all(_is_config_only_path(path) for path in paths):
|
|
876
|
+
failures.append(
|
|
877
|
+
f"stage {number} is a config-only propagation stage "
|
|
878
|
+
f"({sorted(set(paths))}); fold it into the stage that introduces "
|
|
879
|
+
"the value and split the work by commits, not stages"
|
|
880
|
+
)
|
|
881
|
+
return failures
|
|
882
|
+
|
|
883
|
+
|
|
777
884
|
def _direction_invalidation_errors(planning: Mapping[str, Any]) -> list[str]:
|
|
778
885
|
failures: list[str] = []
|
|
779
886
|
invalidation = planning.get("directionInvalidation")
|
|
@@ -807,7 +914,7 @@ def validate_selected_direction_plan(
|
|
|
807
914
|
return ["implementationPlanning is missing"]
|
|
808
915
|
if planning.get("planningContract") != "selected-direction":
|
|
809
916
|
return ["implementationPlanning.planningContract must be selected-direction"]
|
|
810
|
-
snapshot, failures =
|
|
917
|
+
snapshot, failures = load_selected_direction_snapshot(snapshot_path)
|
|
811
918
|
if snapshot is None:
|
|
812
919
|
return failures
|
|
813
920
|
header = data.get("header")
|
|
@@ -840,4 +947,6 @@ def validate_selected_direction_plan(
|
|
|
840
947
|
planning, brief_end_state_id_sequence(Path(brief_path))
|
|
841
948
|
)
|
|
842
949
|
)
|
|
950
|
+
failures.extend(_stage_validation_executability_errors(planning))
|
|
951
|
+
failures.extend(_micro_stage_fold_errors(planning))
|
|
843
952
|
return failures
|
|
@@ -22,6 +22,12 @@ EVALUATION_CRITERIA = (
|
|
|
22
22
|
"verification-cost",
|
|
23
23
|
"rollout-cost",
|
|
24
24
|
)
|
|
25
|
+
MIN_CRITERION_VALUE = 1
|
|
26
|
+
MAX_CRITERION_VALUE = 5
|
|
27
|
+
MIN_FEASIBLE_VOTES = 2
|
|
28
|
+
MAX_RANKED_OPTIONS = 3
|
|
29
|
+
CANDIDATE_COMPARISON_ROUTING = "pending-direction-selection"
|
|
30
|
+
NO_VALID_OPTIONS_ROUTING = "blocked"
|
|
25
31
|
|
|
26
32
|
_FINGERPRINT_FIELDS = (
|
|
27
33
|
"goal",
|
|
@@ -115,7 +121,9 @@ def _validate_criteria(data: Mapping[str, object], errors: list[str]) -> dict[st
|
|
|
115
121
|
errors.append("evaluationCriteria must contain the fixed eight criteria in order")
|
|
116
122
|
weights = _criterion_values(rows, "weight")
|
|
117
123
|
if any(
|
|
118
|
-
not isinstance(weight, int)
|
|
124
|
+
not isinstance(weight, int)
|
|
125
|
+
or isinstance(weight, bool)
|
|
126
|
+
or not MIN_CRITERION_VALUE <= weight <= MAX_CRITERION_VALUE
|
|
119
127
|
for weight in weights.values()
|
|
120
128
|
):
|
|
121
129
|
errors.append("evaluationCriteria weights must be integers in 1..5")
|
|
@@ -177,14 +185,16 @@ def _validate_option_scores(
|
|
|
177
185
|
errors.append(f"{option_id} criterionScores must contain the fixed eight criteria")
|
|
178
186
|
scores = _criterion_values(score_rows, "score")
|
|
179
187
|
if any(
|
|
180
|
-
not isinstance(score, int)
|
|
188
|
+
not isinstance(score, int)
|
|
189
|
+
or isinstance(score, bool)
|
|
190
|
+
or not MIN_CRITERION_VALUE <= score <= MAX_CRITERION_VALUE
|
|
181
191
|
for score in scores.values()
|
|
182
192
|
):
|
|
183
193
|
errors.append(f"{option_id} criterion score values must be integers in 1..5")
|
|
184
194
|
values_valid = all(
|
|
185
195
|
isinstance(score, int)
|
|
186
196
|
and not isinstance(score, bool)
|
|
187
|
-
and
|
|
197
|
+
and MIN_CRITERION_VALUE <= score <= MAX_CRITERION_VALUE
|
|
188
198
|
for score in scores.values()
|
|
189
199
|
)
|
|
190
200
|
if (
|
|
@@ -223,7 +233,7 @@ def _validate_option_feasibility(
|
|
|
223
233
|
isinstance(vote, Mapping) and vote.get("verdict") == "feasible"
|
|
224
234
|
for vote in votes
|
|
225
235
|
)
|
|
226
|
-
if require_valid and feasible <
|
|
236
|
+
if require_valid and feasible < MIN_FEASIBLE_VOTES:
|
|
227
237
|
errors.append(f"{option_id} must have at least two feasible votes")
|
|
228
238
|
if require_valid and option.get("safetyBlockers"):
|
|
229
239
|
errors.append(f"{option_id} safetyBlockers must be empty")
|
|
@@ -231,7 +241,7 @@ def _validate_option_feasibility(
|
|
|
231
241
|
errors.append(f"{option_id} unresolvedFeasibilityFacts must be empty")
|
|
232
242
|
return (
|
|
233
243
|
all_participated
|
|
234
|
-
and feasible >=
|
|
244
|
+
and feasible >= MIN_FEASIBLE_VOTES
|
|
235
245
|
and not option.get("safetyBlockers")
|
|
236
246
|
and not option.get("unresolvedFeasibilityFacts")
|
|
237
247
|
)
|
|
@@ -270,8 +280,10 @@ def _validate_displayed_options(
|
|
|
270
280
|
options = [
|
|
271
281
|
option for option in (raw_options or ()) if isinstance(option, Mapping)
|
|
272
282
|
]
|
|
273
|
-
if len(options) >
|
|
274
|
-
errors.append(
|
|
283
|
+
if len(options) > MAX_RANKED_OPTIONS:
|
|
284
|
+
errors.append(
|
|
285
|
+
f"rankedOptions must display at most {MAX_RANKED_OPTIONS} valid options"
|
|
286
|
+
)
|
|
275
287
|
validity = {
|
|
276
288
|
str(option.get("id")): _validate_candidate(
|
|
277
289
|
option,
|
|
@@ -297,10 +309,10 @@ def _validate_option_count_and_routing(
|
|
|
297
309
|
if not valid_candidates:
|
|
298
310
|
if recommended is not None:
|
|
299
311
|
errors.append("recommendedOptionId must be null when no valid options exist")
|
|
300
|
-
if routing !=
|
|
312
|
+
if routing != NO_VALID_OPTIONS_ROUTING:
|
|
301
313
|
errors.append("routing must be blocked only when no valid options exist")
|
|
302
314
|
return
|
|
303
|
-
if routing ==
|
|
315
|
+
if routing == NO_VALID_OPTIONS_ROUTING:
|
|
304
316
|
errors.append("routing may be blocked only when no valid options exist")
|
|
305
317
|
if not options:
|
|
306
318
|
errors.append("recommendedOptionId must name the first ranked option")
|
|
@@ -409,7 +421,9 @@ def _validate_complete_ranking(
|
|
|
409
421
|
and audit_validity.get(str(row.get("id")))
|
|
410
422
|
and candidate_fingerprint(row) not in displayed_fingerprints
|
|
411
423
|
)
|
|
412
|
-
expected = rank_valid_options(
|
|
424
|
+
expected = rank_valid_options(
|
|
425
|
+
valid, data.get("evaluationCriteria") or ()
|
|
426
|
+
)[:MAX_RANKED_OPTIONS]
|
|
413
427
|
reported = tuple(str(option.get("id")) for option in options)
|
|
414
428
|
if reported != expected:
|
|
415
429
|
errors.append("rankedOptions must contain the top valid candidates in order")
|
|
@@ -427,7 +441,7 @@ def _validate_mode(
|
|
|
427
441
|
if mode == "candidate-comparison":
|
|
428
442
|
if direction is not None:
|
|
429
443
|
errors.append("candidate-comparison must not set preselectedDirection")
|
|
430
|
-
if options and data.get("routing") !=
|
|
444
|
+
if options and data.get("routing") != CANDIDATE_COMPARISON_ROUTING:
|
|
431
445
|
errors.append("candidate-comparison with options must await direction selection")
|
|
432
446
|
return
|
|
433
447
|
if len(options) != 1:
|
|
@@ -13,7 +13,7 @@ from .consumers import (
|
|
|
13
13
|
)
|
|
14
14
|
from . import next_phase
|
|
15
15
|
from .paths import RunRef, task_manifest_file
|
|
16
|
-
from .stage_map import StageMapError,
|
|
16
|
+
from .stage_map import StageMapError, load_latest_plan_stage_map
|
|
17
17
|
from .workflow import PHASE_SEQUENCE
|
|
18
18
|
from .json_boundary import JsonBoundaryError, load_owned_object, write_owned_object_atomic
|
|
19
19
|
|
|
@@ -38,8 +38,11 @@ def derive_implementation_outcome(task_root: Path) -> ImplementationOutcome:
|
|
|
38
38
|
if not plan_run_root.is_dir():
|
|
39
39
|
return ImplementationOutcome(completed=False, reason="implementation-planning run root missing")
|
|
40
40
|
|
|
41
|
+
# 어떤 stage 가 끝나야 구현이 끝났는지는 최신 계획이 답한다. carry 가
|
|
42
|
+
# 가리키는 계획으로 물으면, 계획 수정 뒤 덧붙은 stage 가 아직 남아 있는데도
|
|
43
|
+
# 옛 계획의 마지막 stage 에서 phase 를 완료로 승격한다 (ADR-0015/0016).
|
|
41
44
|
try:
|
|
42
|
-
stage_snapshot =
|
|
45
|
+
stage_snapshot = load_latest_plan_stage_map(task_root)
|
|
43
46
|
except StageMapError as exc:
|
|
44
47
|
return ImplementationOutcome(
|
|
45
48
|
completed=False, reason=f"{exc.code}: {exc.reason}"
|
|
@@ -30,17 +30,3 @@ SOURCE_WORKERS: tuple[str, ...] = ("claude", "codex", "antigravity")
|
|
|
30
30
|
def is_valid_lens(value: str) -> bool:
|
|
31
31
|
return value in LENSES
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
def is_valid_lens_subset(values: list[str]) -> bool:
|
|
35
|
-
if not (MIN_PRIORITY_LENSES <= len(values) <= MAX_PRIORITY_LENSES):
|
|
36
|
-
return False
|
|
37
|
-
if len(set(values)) != len(values):
|
|
38
|
-
return False
|
|
39
|
-
return all(v in LENSES for v in values)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def is_within_candidate_cap(count: int, *, brief_cap: int | None) -> bool:
|
|
43
|
-
cap = brief_cap if brief_cap is not None else DEFAULT_CANDIDATE_CAP
|
|
44
|
-
if cap < 1 or cap > ABSOLUTE_CANDIDATE_CAP:
|
|
45
|
-
return False
|
|
46
|
-
return 1 <= count <= cap
|
|
@@ -423,8 +423,12 @@ def merge_v3_plan_state(
|
|
|
423
423
|
reverify_stages: set[int],
|
|
424
424
|
) -> dict[str, Any]:
|
|
425
425
|
"""이전 판정 중 이월 스테이지 소유분과 본문이 같은 체크리스트를 복사한다."""
|
|
426
|
+
# 양쪽 다 작성자 소유 필드만 놓고 비교한다. 한쪽만 거르면 "작성자가
|
|
427
|
+
# 바꿨는가" 가 아니라 "assembly 소유 필드가 실렸는가" 를 재게 되고, 이월을
|
|
428
|
+
# **제대로** 복사한 narrative 일수록 반드시 걸린다 — 복사가 성공할수록
|
|
429
|
+
# 실패하는 검사가 된다.
|
|
426
430
|
prev_stages = _writer_stage_rows(prev, snapshot="prior")
|
|
427
|
-
cur_stages =
|
|
431
|
+
cur_stages = _writer_stage_rows(narrative, snapshot="current")
|
|
428
432
|
_validate_stage_sets(prev_stages, cur_stages, carry_stages, reverify_stages)
|
|
429
433
|
for stage in sorted(carry_stages):
|
|
430
434
|
current = cur_stages.get(stage)
|
|
@@ -481,12 +485,15 @@ def merge_v3_plan_state(
|
|
|
481
485
|
return state
|
|
482
486
|
|
|
483
487
|
|
|
484
|
-
def
|
|
488
|
+
def sync_prepared_dispatch_queue(state_path: Path, merged: Mapping[str, Any]) -> None:
|
|
485
489
|
"""이월 뒤 프롬프트 큐를 상태 파일과 맞춘다.
|
|
486
490
|
|
|
487
491
|
`plan-items prompt` 는 prepare 가 쓴 `plan-items-*.json` 을 읽는다. 시드가
|
|
488
492
|
그 파일을 먼저 쓰므로, 이월이 큐를 줄인 뒤에는 형제 파일을 같이 고쳐야
|
|
489
493
|
워커가 이미 통과한 P-Val 을 다시 보지 않는다.
|
|
494
|
+
|
|
495
|
+
직전 run 판정 이월(`plan_items_cli._carry_prior_run_verdicts`)도 같은 자리를
|
|
496
|
+
맞춰야 한다 — 이월이 두 곳에 있으므로 이 동기화도 공개 이름을 쓴다.
|
|
490
497
|
"""
|
|
491
498
|
name = state_path.name
|
|
492
499
|
prefix = "plan-body-verification-"
|
|
@@ -512,6 +519,27 @@ def _sync_prepared_dispatch_queue(state_path: Path, merged: Mapping[str, Any]) -
|
|
|
512
519
|
write_json_atomic(prepared, envelope)
|
|
513
520
|
|
|
514
521
|
|
|
522
|
+
def _decision_stages(path: str) -> tuple[set[int], set[int]]:
|
|
523
|
+
"""판정 레코드가 말하는 두 stage 집합.
|
|
524
|
+
|
|
525
|
+
리드가 stdout 을 보고 CSV 로 다시 적던 값이다. 그 재입력이 report writer 가
|
|
526
|
+
받은 지시와 이 병합이 검사하는 범위를 갈라놓을 수 있던 자리이고, 갈리면
|
|
527
|
+
이월 검사가 엉뚱한 stage 를 본다.
|
|
528
|
+
"""
|
|
529
|
+
record = _load_data(path, option="--decision")
|
|
530
|
+
if record.get("mode") != "incremental":
|
|
531
|
+
raise CarryError(
|
|
532
|
+
f"--decision records mode {record.get('mode')!r}; a carry merge only "
|
|
533
|
+
"applies to an incremental decision"
|
|
534
|
+
)
|
|
535
|
+
try:
|
|
536
|
+
carry = {int(stage) for stage in record["carryStages"]}
|
|
537
|
+
reverify = {int(stage) for stage in record["reverifyStages"]}
|
|
538
|
+
except (KeyError, TypeError, ValueError) as exc:
|
|
539
|
+
raise CarryError(f"--decision has no usable stage sets: {exc}") from exc
|
|
540
|
+
return carry, reverify
|
|
541
|
+
|
|
542
|
+
|
|
515
543
|
def _parse_stage_csv(value: str | None, *, option: str) -> set[int] | None:
|
|
516
544
|
if value is None:
|
|
517
545
|
return None
|
|
@@ -536,14 +564,39 @@ def _load_data(path: str, *, option: str) -> dict:
|
|
|
536
564
|
return data
|
|
537
565
|
|
|
538
566
|
|
|
567
|
+
_CLI_EPILOG = r"""Usage:
|
|
568
|
+
okstra incremental-carry --prev-data <path> --cur-narrative <path> \
|
|
569
|
+
--state <path> --prev-seq <str> --carry-stages <csv> \
|
|
570
|
+
--reverify-stages <csv> --out-state <path>
|
|
571
|
+
okstra incremental-carry --prev-data <path> --cur-data <path> \
|
|
572
|
+
--prev-seq <str> [--carry-stages <csv> --reverify-stages <csv>] --out <path>
|
|
573
|
+
|
|
574
|
+
Exits non-zero on ownership, scope, or schema drift so the caller can fall back
|
|
575
|
+
to a full re-run.
|
|
576
|
+
"""
|
|
577
|
+
_CLI_DESCRIPTION = "Merge carried-forward plan-item verdicts."
|
|
578
|
+
|
|
579
|
+
|
|
539
580
|
def main(argv: list[str]) -> int:
|
|
540
|
-
ap = argparse.ArgumentParser(
|
|
581
|
+
ap = argparse.ArgumentParser(
|
|
582
|
+
description=_CLI_DESCRIPTION,
|
|
583
|
+
epilog=_CLI_EPILOG,
|
|
584
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
585
|
+
prog="okstra incremental-carry")
|
|
541
586
|
ap.add_argument("--prev-data", required=True, help="prior run final-report data.json")
|
|
542
587
|
current = ap.add_mutually_exclusive_group(required=True)
|
|
543
588
|
current.add_argument("--cur-data", help="historical v2 current data.json")
|
|
544
589
|
current.add_argument("--cur-narrative", help="contract v3 current narrative Markdown")
|
|
545
590
|
ap.add_argument("--state", help="contract v3 convergence-owned plan state")
|
|
546
591
|
ap.add_argument("--prev-seq", required=True, help="prior run seq, tagged onto carried items")
|
|
592
|
+
ap.add_argument(
|
|
593
|
+
"--decision",
|
|
594
|
+
default=None,
|
|
595
|
+
help="the `okstra incremental-scope` decision record (the run manifest's "
|
|
596
|
+
"incrementalDecisionPath). Supplies both stage sets, so they are the "
|
|
597
|
+
"same values the report writer's authoring contract was built from. "
|
|
598
|
+
"Cannot be combined with --carry-stages / --reverify-stages",
|
|
599
|
+
)
|
|
547
600
|
ap.add_argument("--carry-stages", default=None, help="comma-separated carried stage numbers")
|
|
548
601
|
ap.add_argument("--reverify-stages", default=None, help="comma-separated reverified stage numbers")
|
|
549
602
|
ap.add_argument("--out", help="historical v2 merged data.json path")
|
|
@@ -552,10 +605,18 @@ def main(argv: list[str]) -> int:
|
|
|
552
605
|
|
|
553
606
|
try:
|
|
554
607
|
prev = _load_data(args.prev_data, option="--prev-data")
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
608
|
+
if args.decision is not None:
|
|
609
|
+
if args.carry_stages is not None or args.reverify_stages is not None:
|
|
610
|
+
raise CarryError(
|
|
611
|
+
"--decision already carries both stage sets; remove "
|
|
612
|
+
"--carry-stages / --reverify-stages"
|
|
613
|
+
)
|
|
614
|
+
carry_stages, reverify_stages = _decision_stages(args.decision)
|
|
615
|
+
else:
|
|
616
|
+
carry_stages = _parse_stage_csv(args.carry_stages, option="--carry-stages")
|
|
617
|
+
reverify_stages = _parse_stage_csv(
|
|
618
|
+
args.reverify_stages, option="--reverify-stages",
|
|
619
|
+
)
|
|
559
620
|
if args.cur_narrative:
|
|
560
621
|
if not args.state or not args.out_state or args.out:
|
|
561
622
|
raise CarryError(
|
|
@@ -600,7 +661,7 @@ def main(argv: list[str]) -> int:
|
|
|
600
661
|
|
|
601
662
|
try:
|
|
602
663
|
write_json_atomic(output, merged)
|
|
603
|
-
|
|
664
|
+
sync_prepared_dispatch_queue(output, merged)
|
|
604
665
|
except OSError as exc:
|
|
605
666
|
print(f"carry refused: --out could not be written: {exc}", file=sys.stderr)
|
|
606
667
|
return 1
|