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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Read-side state accessors over okstra's on-disk authority files.
|
|
2
2
|
|
|
3
|
-
Skills
|
|
3
|
+
Skills and okstra.sh read the same files through this module
|
|
4
4
|
so identity / discovery values are derived from disk on every call instead of
|
|
5
5
|
being passed via process environment. This keeps concurrent claude-code skill
|
|
6
6
|
invocations isolated — each call reads the authoritative state at the moment
|
|
@@ -34,6 +34,13 @@ from .dirs import (
|
|
|
34
34
|
TASK_MANIFEST_FILENAME,
|
|
35
35
|
TASKS_RELATIVE,
|
|
36
36
|
)
|
|
37
|
+
# 포인터 승격은 순수 값 연산이라 하위 계층이 소유한다. 예전에는 함수 본문에서
|
|
38
|
+
# okstra_ctl.next_phase 를 지연 import 했다 — okstra_ctl 패키지 __init__ 이
|
|
39
|
+
# 이 모듈의 slugify 를 도로 끌어와 순환이 됐기 때문이다.
|
|
40
|
+
from .phase_pointer import promote as promote_phase_pointer
|
|
41
|
+
# slug 규칙은 leaf 가 소유한다 — okstra_ctl 이 이 모듈을 거치지 않고 규칙만
|
|
42
|
+
# 가져갈 수 있어야 패키지 __init__ 을 통한 순환이 생기지 않는다.
|
|
43
|
+
from .slug import slugify # noqa: F401 — 재노출: 기존 호출부가 state 에서 끌어온다
|
|
37
44
|
|
|
38
45
|
|
|
39
46
|
class StateError(Exception):
|
|
@@ -53,31 +60,6 @@ def _load_json(path: Path) -> Optional[dict]:
|
|
|
53
60
|
raise StateError(f"failed to parse {path}: {exc}") from exc
|
|
54
61
|
|
|
55
62
|
|
|
56
|
-
def _next_phase():
|
|
57
|
-
"""`okstra_ctl.next_phase` 를 호출 시점에 가져온다.
|
|
58
|
-
|
|
59
|
-
모듈 최상단에서 import 하면 순환이 된다 — `okstra_ctl/__init__.py` 가
|
|
60
|
-
`.ids` 를 거쳐 이 모듈의 `slugify` 를 도로 import 하기 때문에, 여기서
|
|
61
|
-
okstra_ctl 을 먼저 끌어오면 아직 정의되지 않은 이름을 찾다가 ImportError 로
|
|
62
|
-
죽는다. 같은 파일의 `_reconcile_task_root_best_effort` 도 같은 이유로 지연
|
|
63
|
-
import 를 쓴다.
|
|
64
|
-
"""
|
|
65
|
-
from okstra_ctl import next_phase
|
|
66
|
-
|
|
67
|
-
return next_phase
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def slugify(value: str) -> str:
|
|
71
|
-
"""task-group / task-id segment 를 디스크 경로용 slug 로 정규화한다.
|
|
72
|
-
|
|
73
|
-
소문자화 + 알파넘 외 문자 → '-' 로 collapse.
|
|
74
|
-
okstra.sh 의 path-resolve.sh slug 규칙과 일치해야 한다.
|
|
75
|
-
"""
|
|
76
|
-
value = (value or "").lower()
|
|
77
|
-
value = re.sub(r"[^a-z0-9]+", "-", value).strip("-")
|
|
78
|
-
return value
|
|
79
|
-
|
|
80
|
-
|
|
81
63
|
def read_task_catalog(project_root: Path) -> list[dict]:
|
|
82
64
|
"""project-level task-catalog.json 을 list[dict] 로 돌려준다.
|
|
83
65
|
|
|
@@ -117,7 +99,7 @@ def read_task_manifest(task_root: Path) -> Optional[dict]:
|
|
|
117
99
|
workflow = manifest.get("workflow")
|
|
118
100
|
if not isinstance(workflow, dict):
|
|
119
101
|
return manifest
|
|
120
|
-
workflow["nextRecommendedPhase"] =
|
|
102
|
+
workflow["nextRecommendedPhase"] = promote_phase_pointer(
|
|
121
103
|
workflow.get("nextRecommendedPhase")
|
|
122
104
|
)
|
|
123
105
|
# routingStatus 는 포인터 status 로 흡수됐다 — 승격과 같은 자리에서 지운다.
|
|
@@ -143,11 +125,20 @@ def read_task_key(task_root: Path) -> str:
|
|
|
143
125
|
|
|
144
126
|
|
|
145
127
|
def _reconcile_task_root_best_effort(project_root: Path, task_root: Path) -> None:
|
|
128
|
+
"""카탈로그가 가리키는 task-root 를 정본 산출물로 치유한다(best-effort).
|
|
129
|
+
|
|
130
|
+
import 를 함수 본문에 두는 이유는 순환이 아니다 — 순환은 없다. 하위 계층인
|
|
131
|
+
okstra_project 가 상위 계층 okstra_ctl 을 import 시점에 끌어오지 않게 하려는
|
|
132
|
+
것이다. 이 치유는 읽기측 해석의 부가 동작이므로, 실패해도 해석 자체는
|
|
133
|
+
계속돼야 한다.
|
|
134
|
+
"""
|
|
146
135
|
try:
|
|
147
136
|
from okstra_ctl.implementation_outcome import reconcile_implementation_outcome
|
|
148
137
|
|
|
149
138
|
reconcile_implementation_outcome(project_root, task_root)
|
|
150
139
|
except Exception:
|
|
140
|
+
# expected-miss: 치유는 부가 동작이다. 여기서 던지면 단순 조회가
|
|
141
|
+
# 실패한다. 무엇이 치유되지 않았는지는 다음 run 의 정합성 검사가 잡는다.
|
|
151
142
|
return
|
|
152
143
|
|
|
153
144
|
|
|
@@ -195,7 +186,7 @@ def _entry_with_manifest_state(entry: dict, task_root: Path) -> dict:
|
|
|
195
186
|
raw = workflow.get("nextRecommendedPhase")
|
|
196
187
|
if raw is None:
|
|
197
188
|
raw = entry.get("nextRecommendedPhase")
|
|
198
|
-
out["nextRecommendedPhase"] =
|
|
189
|
+
out["nextRecommendedPhase"] = promote_phase_pointer(raw)
|
|
199
190
|
out.update(derived_task_status(manifest))
|
|
200
191
|
return out
|
|
201
192
|
|
|
@@ -350,7 +341,7 @@ def list_project_tasks(
|
|
|
350
341
|
def resolve_task_identity(project_root: Path, task_key: str) -> dict:
|
|
351
342
|
"""task-key 한 줄로 manifest + 경로를 한 번에 반환.
|
|
352
343
|
|
|
353
|
-
skill
|
|
344
|
+
skill 과 okstra.sh 모두가 이 함수를 호출해 같은 dict 를 받는다.
|
|
354
345
|
StateError: task root 또는 manifest 없음.
|
|
355
346
|
"""
|
|
356
347
|
task_root = find_task_root(project_root, task_key)
|
|
@@ -379,7 +370,7 @@ def resolve_task_identity(project_root: Path, task_key: str) -> dict:
|
|
|
379
370
|
"taskType": manifest.get("taskType") or "",
|
|
380
371
|
"currentPhase": workflow.get("currentPhase") or "",
|
|
381
372
|
"currentPhaseState": workflow.get("currentPhaseState") or "",
|
|
382
|
-
"nextRecommendedPhase":
|
|
373
|
+
"nextRecommendedPhase": promote_phase_pointer(
|
|
383
374
|
workflow.get("nextRecommendedPhase")
|
|
384
375
|
),
|
|
385
376
|
"lastCompletedPhase": workflow.get("lastCompletedPhase") or "",
|
|
@@ -410,7 +401,7 @@ def task_read_side_snapshot(project_root: Path, task_key: str) -> dict:
|
|
|
410
401
|
"currentPhase": workflow.get("currentPhase"),
|
|
411
402
|
"currentPhaseState": workflow.get("currentPhaseState"),
|
|
412
403
|
"lastCompletedPhase": workflow.get("lastCompletedPhase"),
|
|
413
|
-
"nextRecommendedPhase":
|
|
404
|
+
"nextRecommendedPhase": promote_phase_pointer(
|
|
414
405
|
workflow.get("nextRecommendedPhase")
|
|
415
406
|
),
|
|
416
407
|
"phaseStates": workflow.get("phaseStates"),
|
|
@@ -421,202 +412,3 @@ def task_read_side_snapshot(project_root: Path, task_key: str) -> dict:
|
|
|
421
412
|
"modelAssignments": manifest.get("modelAssignments"),
|
|
422
413
|
"latestRunPath": manifest.get("latestRunPath"),
|
|
423
414
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
def stage_map_read_side_snapshot(project_root: Path, task_key: str) -> dict:
|
|
427
|
-
"""stage-map inspect 용 read-side view: Stage Map + done 처리된 stage 번호.
|
|
428
|
-
|
|
429
|
-
Stage Map 파싱과 planning run-root 위치를 caller 에게 노출하지 않는다 —
|
|
430
|
-
Node inspect 가 okstra_ctl 의 private 심볼을 import 하거나 `runs/` 경로를
|
|
431
|
-
직접 조립하지 않도록 하는 어댑터다.
|
|
432
|
-
"""
|
|
433
|
-
from okstra_ctl.consumers import read_stage_consumer_state
|
|
434
|
-
from okstra_ctl.paths import RunRef
|
|
435
|
-
from okstra_ctl.stage_map import (
|
|
436
|
-
PlanningDetail,
|
|
437
|
-
StageMapError,
|
|
438
|
-
load_planning_detail,
|
|
439
|
-
load_task_stage_map,
|
|
440
|
-
merge_planning_detail,
|
|
441
|
-
)
|
|
442
|
-
|
|
443
|
-
identity = resolve_task_identity(project_root, task_key)
|
|
444
|
-
task_root = Path(identity["taskRoot"])
|
|
445
|
-
try:
|
|
446
|
-
stage_snapshot = load_task_stage_map(task_root, identity["manifest"])
|
|
447
|
-
detail = (
|
|
448
|
-
load_planning_detail(Path(stage_snapshot.source_plan_path))
|
|
449
|
-
if stage_snapshot.source_plan_path
|
|
450
|
-
else PlanningDetail({}, {})
|
|
451
|
-
)
|
|
452
|
-
except StageMapError as exc:
|
|
453
|
-
raise StateError(str(exc), stage=exc.code) from exc
|
|
454
|
-
plan_run_root = RunRef.from_task_root(
|
|
455
|
-
task_root, "implementation-planning"
|
|
456
|
-
).run_dir
|
|
457
|
-
done: list[int] = []
|
|
458
|
-
if plan_run_root.is_dir():
|
|
459
|
-
done = sorted(
|
|
460
|
-
read_stage_consumer_state(
|
|
461
|
-
plan_run_root, recover_from_carry=True
|
|
462
|
-
).done_stages
|
|
463
|
-
)
|
|
464
|
-
return {
|
|
465
|
-
"taskKey": identity["taskKey"],
|
|
466
|
-
"taskRoot": identity["taskRoot"],
|
|
467
|
-
"state": stage_snapshot.state,
|
|
468
|
-
"sourcePlanPath": stage_snapshot.source_plan_path,
|
|
469
|
-
"stages": merge_planning_detail(stage_snapshot.stages, detail),
|
|
470
|
-
"doneStages": done,
|
|
471
|
-
"planning": detail.task_narratives,
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
def code_review_target_snapshot(
|
|
476
|
-
project_root: Path, task_key: str, stage: int
|
|
477
|
-
) -> dict:
|
|
478
|
-
"""stage 코드 리뷰가 무엇을 읽고 결과를 어디에 쓰는지 해소한다.
|
|
479
|
-
|
|
480
|
-
stage_map_read_side_snapshot 과 같은 결: caller 는 registry 행도, run-root
|
|
481
|
-
레이아웃도, stage base 규칙도 보지 않는다. stage_targets 의
|
|
482
|
-
StageTargetError 도 StateError 로 바꿔 던진다 — caller 가 그 예외를 잡으려고
|
|
483
|
-
okstra_ctl 을 import 하지 않도록.
|
|
484
|
-
|
|
485
|
-
base 는 stage worktree 를 만들 때 registry 행에 적힌 `base_ref` 다 — 그
|
|
486
|
-
stage 가 실제로 갈라져 나온 커밋. 리뷰 시점에 규칙으로 다시 계산하면
|
|
487
|
-
표류한다: 다중의존 stage 는 오늘의 task-key worktree HEAD 를 받게 되어
|
|
488
|
-
whole-task final-verification 이 stage 들을 병합한 뒤에는 base..head 구간이
|
|
489
|
-
비거나 뒤집히고, 단일의존 stage 는 선행 stage 가 재실행되면 어긋난다.
|
|
490
|
-
"""
|
|
491
|
-
from okstra_ctl import code_review_paths, worktree_registry
|
|
492
|
-
from okstra_ctl.stage_map import StageMapError, load_task_stage_map
|
|
493
|
-
|
|
494
|
-
identity = resolve_task_identity(project_root, task_key)
|
|
495
|
-
task_root = Path(identity["taskRoot"])
|
|
496
|
-
try:
|
|
497
|
-
stage_snapshot = load_task_stage_map(task_root, identity["manifest"])
|
|
498
|
-
except StageMapError as exc:
|
|
499
|
-
raise StateError(str(exc), stage=exc.code) from exc
|
|
500
|
-
if stage_snapshot.state != "ready":
|
|
501
|
-
raise StateError(
|
|
502
|
-
"implementation-planning Stage Map is missing",
|
|
503
|
-
stage="missing",
|
|
504
|
-
)
|
|
505
|
-
stages = stage_snapshot.stages
|
|
506
|
-
selected = next((s for s in stages if s["stage_number"] == stage), None)
|
|
507
|
-
if selected is None:
|
|
508
|
-
raise StateError(
|
|
509
|
-
f"stage {stage} is not in the Stage Map for {task_key}",
|
|
510
|
-
stage="stage_missing",
|
|
511
|
-
)
|
|
512
|
-
|
|
513
|
-
coords = (identity["projectId"], identity["taskGroup"], identity["taskId"])
|
|
514
|
-
stage_row = worktree_registry.get_stage_row(*coords, stage) or {}
|
|
515
|
-
worktree_view = _stage_worktree_view(project_root, stage_row, stage)
|
|
516
|
-
base_commit = stage_row.get("base_ref") or _legacy_stage_base_commit(
|
|
517
|
-
identity, stages, selected
|
|
518
|
-
)
|
|
519
|
-
review_path, round_no = code_review_paths.next_stage_review(
|
|
520
|
-
code_review_paths.stage_review_dir(
|
|
521
|
-
project_root, identity["taskGroup"], identity["taskId"]
|
|
522
|
-
),
|
|
523
|
-
stage,
|
|
524
|
-
)
|
|
525
|
-
return {
|
|
526
|
-
"mode": "stage",
|
|
527
|
-
"taskKey": identity["taskKey"],
|
|
528
|
-
"taskRoot": identity["taskRoot"],
|
|
529
|
-
"stage": stage,
|
|
530
|
-
**worktree_view,
|
|
531
|
-
"baseCommit": base_commit,
|
|
532
|
-
"reviewPath": str(review_path),
|
|
533
|
-
"round": round_no,
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
def _legacy_stage_base_commit(
|
|
538
|
-
identity: dict, stages: list[dict], selected: dict
|
|
539
|
-
) -> str:
|
|
540
|
-
"""`base_ref` 를 남기지 않은 옛 registry 행의 base 를 규칙에서 되살린다.
|
|
541
|
-
|
|
542
|
-
provision 이 base_ref 를 기록하기 전에 만들어진 stage 행에만 쓰인다. 규칙
|
|
543
|
-
자체는 stage_targets 가 소유하며 여기서 다시 유도하지 않는다.
|
|
544
|
-
"""
|
|
545
|
-
from okstra_ctl import stage_targets, worktree_registry
|
|
546
|
-
from okstra_ctl.paths import RunRef
|
|
547
|
-
|
|
548
|
-
coords = (identity["projectId"], identity["taskGroup"], identity["taskId"])
|
|
549
|
-
plan_run_root = RunRef.from_task_root(
|
|
550
|
-
Path(identity["taskRoot"]), "implementation-planning"
|
|
551
|
-
).run_dir
|
|
552
|
-
lifecycle = stage_targets.read_stage_lifecycle_snapshot(
|
|
553
|
-
stages, plan_run_root, recover_from_carry=True
|
|
554
|
-
)
|
|
555
|
-
# The anchor and the multi-dep candidate base must come from the task-key
|
|
556
|
-
# worktree HEAD, where stage work accumulates — not from the invocation
|
|
557
|
-
# cwd, which may sit on an older or unrelated commit.
|
|
558
|
-
task_entry = worktree_registry.lookup(*coords)
|
|
559
|
-
task_worktree = Path(
|
|
560
|
-
(task_entry.worktree_path if task_entry else "") or identity["projectRoot"]
|
|
561
|
-
)
|
|
562
|
-
anchor = worktree_registry.get_implementation_base(*coords) or ""
|
|
563
|
-
try:
|
|
564
|
-
return stage_targets.resolve_stage_base_commit(
|
|
565
|
-
selected,
|
|
566
|
-
lifecycle.done_rows,
|
|
567
|
-
anchor_base_commit=anchor,
|
|
568
|
-
candidate_base=_git_out(task_worktree, "rev-parse", "HEAD"),
|
|
569
|
-
project_root=task_worktree,
|
|
570
|
-
plan_run_root=plan_run_root,
|
|
571
|
-
)
|
|
572
|
-
except stage_targets.StageTargetError as exc:
|
|
573
|
-
raise StateError(
|
|
574
|
-
f"stage {selected['stage_number']} has no recorded base_ref and its "
|
|
575
|
-
f"base could not be derived: {exc}",
|
|
576
|
-
stage="stage_base_unresolved",
|
|
577
|
-
) from exc
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
def _stage_worktree_view(project_root: Path, stage_row: dict, stage: int) -> dict:
|
|
581
|
-
"""한 stage 의 worktree 경로 / 브랜치 / head 커밋.
|
|
582
|
-
|
|
583
|
-
철거된 stage worktree 는 오류가 아니다: whole-task final-verification 이
|
|
584
|
-
디렉터리를 지워도 브랜치는 남고, 리뷰가 필요한 커밋은 그 브랜치에 그대로
|
|
585
|
-
있다.
|
|
586
|
-
"""
|
|
587
|
-
branch = stage_row.get("branch") or ""
|
|
588
|
-
if not branch:
|
|
589
|
-
raise StateError(
|
|
590
|
-
f"stage {stage} has no registry branch — review it in branch mode",
|
|
591
|
-
stage="stage_branch_missing",
|
|
592
|
-
)
|
|
593
|
-
worktree_path = ""
|
|
594
|
-
if stage_row.get("status") == "active" and stage_row.get("worktree_path"):
|
|
595
|
-
candidate = Path(stage_row["worktree_path"])
|
|
596
|
-
if candidate.is_dir():
|
|
597
|
-
worktree_path = str(candidate)
|
|
598
|
-
head_source = Path(worktree_path) if worktree_path else Path(project_root)
|
|
599
|
-
head_ref = "HEAD" if worktree_path else branch
|
|
600
|
-
head_commit = _git_out(head_source, "rev-parse", head_ref)
|
|
601
|
-
if not head_commit:
|
|
602
|
-
raise StateError(
|
|
603
|
-
f"stage {stage} head could not be resolved: branch {branch!r} is "
|
|
604
|
-
f"not readable from {head_source}",
|
|
605
|
-
stage="stage_head_unresolved",
|
|
606
|
-
)
|
|
607
|
-
return {
|
|
608
|
-
"worktreePath": worktree_path,
|
|
609
|
-
"branch": branch,
|
|
610
|
-
"headCommit": head_commit,
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
def _git_out(repo: Path, *args: str) -> str:
|
|
615
|
-
"""git 호출의 stdout. 실패는 빈 문자열 — 호출자가 부재를 판단한다."""
|
|
616
|
-
result = subprocess.run(
|
|
617
|
-
["git", "-C", str(repo), *args],
|
|
618
|
-
capture_output=True,
|
|
619
|
-
text=True,
|
|
620
|
-
check=False,
|
|
621
|
-
)
|
|
622
|
-
return result.stdout.strip() if result.returncode == 0 else ""
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
import json
|
|
5
|
+
import sys
|
|
5
6
|
import re
|
|
6
7
|
from datetime import datetime
|
|
7
8
|
from pathlib import Path
|
|
@@ -158,8 +159,15 @@ def _advance_usage_scan(jsonl_path: Path, usage_state: dict) -> dict:
|
|
|
158
159
|
if ev:
|
|
159
160
|
tail_events.append(ev)
|
|
160
161
|
break
|
|
161
|
-
except
|
|
162
|
+
except FileNotFoundError:
|
|
163
|
+
# expected-miss: 세션 jsonl 은 열거된 뒤 사라질 수 있고(정리·회전), 아직
|
|
164
|
+
# 한 줄도 안 쓴 세션은 파일 자체가 없다. 읽을 것이 없는 것이 정상이다.
|
|
162
165
|
pass
|
|
166
|
+
except OSError as exc:
|
|
167
|
+
# 파일은 있는데 못 읽은 것은 다르다. 읽다 만 상태로 반환하면 토큰 집계가
|
|
168
|
+
# 실제보다 적게 나오는데 리포트에는 정상 수치처럼 찍힌다.
|
|
169
|
+
print(f"token-usage: partial read of {jsonl_path} ({exc})",
|
|
170
|
+
file=sys.stderr)
|
|
163
171
|
usage_state.update(offset=offset, events=events,
|
|
164
172
|
agentName=agent_name, model=model)
|
|
165
173
|
return {"events": events + tail_events,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
import json
|
|
5
|
+
import sys
|
|
5
6
|
import os
|
|
6
7
|
from datetime import datetime, timezone
|
|
7
8
|
from pathlib import Path
|
|
@@ -113,22 +114,76 @@ def _aggregate_totals(items: list[dict]) -> dict:
|
|
|
113
114
|
def run_artifact_suffix(team_state_path: Path) -> str | None:
|
|
114
115
|
"""``team-state-<task-type>-<seq>.json`` → ``<task-type>-<seq>``.
|
|
115
116
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
task 디렉토리 한 곳에 여러 run(재시도·이전 phase·레거시 타임스탬프)의 산출물이
|
|
118
|
+
섞여 있어, glob 으로 아무거나 집으면 엉뚱한 run 의 시각을 쓰게 된다(관측: 가장
|
|
119
|
+
오래된 레거시 manifest 의 createdAt 을 집어 윈도우가 한 달로 벌어짐).
|
|
120
|
+
|
|
121
|
+
**접미사가 곧 매니페스트 이름은 아니다.** okstra 는 카테고리별로 seq 를 따로
|
|
122
|
+
매기므로 한 run 이 `manifests: 025` 와 `state: 023` 을 동시에 가질 수 있다.
|
|
123
|
+
run-manifest 는 `_run_manifest_for_team_state` 가 매니페스트의 `teamStatePath`
|
|
124
|
+
역참조로 짚는다. status 산출물은 team-state 와 같은 카테고리라 이 접미사로
|
|
125
|
+
계속 짚는다."""
|
|
120
126
|
name = team_state_path.name
|
|
121
127
|
if not (name.startswith("team-state-") and name.endswith(".json")):
|
|
122
128
|
return None
|
|
123
129
|
return name[len("team-state-"):-len(".json")]
|
|
124
130
|
|
|
125
131
|
|
|
126
|
-
def
|
|
127
|
-
p = run_dir / "manifests" / f"run-manifest-{suffix}.json"
|
|
132
|
+
def _read_json_or_none(path: Path) -> dict | None:
|
|
128
133
|
try:
|
|
129
|
-
|
|
134
|
+
data = json.loads(path.read_text())
|
|
130
135
|
except (OSError, json.JSONDecodeError):
|
|
131
136
|
return None
|
|
137
|
+
return data if isinstance(data, dict) else None
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _run_manifest_for_team_state(
|
|
141
|
+
run_dir: Path, suffix: str, team_state_path: Path
|
|
142
|
+
) -> dict | None:
|
|
143
|
+
"""이 team-state 가 속한 run 의 매니페스트.
|
|
144
|
+
|
|
145
|
+
접미사가 곧 매니페스트 이름이라는 전제는 카테고리별 seq 가 갈리는 순간
|
|
146
|
+
깨진다. 실측(2026-08-27, fontsninja-nlpvibe `nestjs-migration-…`): 한 run 의
|
|
147
|
+
`manifests` 가 025, `state`·`prompts`·`worker-results` 가 023, `reports` 가
|
|
148
|
+
017 이었다. team-state 이름에서 뽑은 `023` 으로 매니페스트를 집으면 **12시간
|
|
149
|
+
전 run** 의 `createdAt`(04:45:34Z) 이 창의 시작이 되고, 그 사이 같은 세션이
|
|
150
|
+
돈 이전 run 들이 통째로 창에 들어온다 — `relax_start=False` 가 막으려던 바로
|
|
151
|
+
그 오탐이다(그 run 에서 로스터에 없는 워커 5명이 이 run 의 위반으로 보고됐다).
|
|
152
|
+
|
|
153
|
+
매니페스트는 자기 team-state 를 `teamStatePath` 에 적으므로 그것으로 맞춘다.
|
|
154
|
+
맞는 것이 없으면 접미사 방식으로 돌아간다 — 그 필드가 없던 옛 매니페스트다.
|
|
155
|
+
"""
|
|
156
|
+
direct = run_dir / "manifests" / f"run-manifest-{suffix}.json"
|
|
157
|
+
# `Path.glob` 는 디렉터리가 없어도 빈 결과를 낸다 — 감쌀 예외가 없다.
|
|
158
|
+
candidates = [
|
|
159
|
+
direct,
|
|
160
|
+
*sorted((run_dir / "manifests").glob("run-manifest-*.json")),
|
|
161
|
+
]
|
|
162
|
+
for path in candidates:
|
|
163
|
+
data = _read_json_or_none(path)
|
|
164
|
+
if data is None:
|
|
165
|
+
continue
|
|
166
|
+
recorded = str(data.get("teamStatePath") or "")
|
|
167
|
+
if recorded and Path(recorded).name == team_state_path.name:
|
|
168
|
+
return data
|
|
169
|
+
return _read_json_or_none(direct)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def _created_at_by_suffix(run_dir: Path, suffix: str) -> str | None:
|
|
173
|
+
"""접미사가 곧 매니페스트 이름인 조회.
|
|
174
|
+
|
|
175
|
+
**다른** run 을 접미사로 지목할 때만 쓴다(`_previous_run_end`). 이번 run 은
|
|
176
|
+
team-state 로 맞춰야 한다 — 두 접미사가 갈리는 run 이 실재한다.
|
|
177
|
+
"""
|
|
178
|
+
data = _read_json_or_none(run_dir / "manifests" / f"run-manifest-{suffix}.json")
|
|
179
|
+
return None if data is None else data.get("createdAt")
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _run_manifest_created_at(
|
|
183
|
+
run_dir: Path, suffix: str, team_state_path: Path
|
|
184
|
+
) -> str | None:
|
|
185
|
+
data = _run_manifest_for_team_state(run_dir, suffix, team_state_path)
|
|
186
|
+
return None if data is None else data.get("createdAt")
|
|
132
187
|
|
|
133
188
|
|
|
134
189
|
def _run_end_estimate(run_dir: Path, suffix: str) -> str | None:
|
|
@@ -233,9 +288,15 @@ def _previous_run_end(run_dir: Path, suffix: str) -> str | None:
|
|
|
233
288
|
ended_at = prev_state.get("runEndedAt")
|
|
234
289
|
if ended_at:
|
|
235
290
|
return str(ended_at)
|
|
236
|
-
except
|
|
291
|
+
except OSError:
|
|
292
|
+
# expected-miss: 직전 run 이 team-state 를 남기지 않고 끝났으면 파일이
|
|
293
|
+
# 없다. 아래 두 추정 경로가 바로 그 경우를 위한 폴백이다.
|
|
237
294
|
pass
|
|
238
|
-
|
|
295
|
+
except json.JSONDecodeError as exc:
|
|
296
|
+
# 파일은 있는데 깨진 것은 폴백이 상정한 상황이 아니다.
|
|
297
|
+
print(f"token-usage: team-state for the previous run ({prev}) is not "
|
|
298
|
+
f"valid JSON, estimating instead ({exc})", file=sys.stderr)
|
|
299
|
+
return _run_end_estimate(run_dir, prev) or _created_at_by_suffix(run_dir, prev)
|
|
239
300
|
|
|
240
301
|
|
|
241
302
|
def resolve_run_window(
|
|
@@ -271,7 +332,7 @@ def resolve_run_window(
|
|
|
271
332
|
if not suffix:
|
|
272
333
|
return None, None
|
|
273
334
|
run_dir = team_state_path.parent.parent
|
|
274
|
-
since = _run_manifest_created_at(run_dir, suffix)
|
|
335
|
+
since = _run_manifest_created_at(run_dir, suffix, team_state_path)
|
|
275
336
|
if relax_start:
|
|
276
337
|
earliest = _earliest_lead_session_ts(state, team_state_path)
|
|
277
338
|
if earliest and (since is None or earliest < since):
|
|
@@ -92,4 +92,6 @@ def save_cache(jsonl_path: Path, cache: dict) -> None:
|
|
|
92
92
|
tmp.write_text(json.dumps(cache, ensure_ascii=False, separators=(",", ":")))
|
|
93
93
|
os.replace(tmp, p)
|
|
94
94
|
except OSError:
|
|
95
|
+
# expected-miss: 이 캐시는 jsonl 에서 언제든 다시 만들 수 있는 파생물이다.
|
|
96
|
+
# 저장에 실패해도 집계 결과가 달라지지 않으므로 없는 것이 정상 분기다.
|
|
95
97
|
pass
|
|
@@ -11,7 +11,7 @@ import os
|
|
|
11
11
|
from datetime import datetime, timezone
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Mapping
|
|
14
|
-
from urllib.parse import
|
|
14
|
+
from urllib.parse import unquote
|
|
15
15
|
|
|
16
16
|
from .jsonl_io import iter_jsonl
|
|
17
17
|
from .paths import ts_in_window
|
|
@@ -132,10 +132,6 @@ def find_grok_sessions(
|
|
|
132
132
|
return sorted(matches)
|
|
133
133
|
|
|
134
134
|
|
|
135
|
-
def grok_session_dir_name(cwd: Path) -> str:
|
|
136
|
-
return quote(str(cwd), safe="")
|
|
137
|
-
|
|
138
|
-
|
|
139
135
|
def grok_session_is_non_interactive(updates_path: Path) -> bool:
|
|
140
136
|
"""워커 래퍼 세션은 prompt_context.is_non_interactive 가 true 이다."""
|
|
141
137
|
context_path = updates_path.parent / "prompt_context.json"
|
|
@@ -72,3 +72,29 @@ def claude_project_dir(cwd: Path, projects_root: Path | None = None) -> Path:
|
|
|
72
72
|
# `projects_root` 는 테스트/진단용 주입 시드 — 기본은 실제 ~/.claude/projects.
|
|
73
73
|
encoded = "-" + str(cwd).strip("/").replace("/", "-")
|
|
74
74
|
return (projects_root or CLAUDE_PROJECTS) / encoded
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def find_session_jsonl(
|
|
78
|
+
session_id: str, cwd: Path, projects_root: Path | None = None
|
|
79
|
+
) -> Path | None:
|
|
80
|
+
"""세션 id 하나의 transcript 경로. 못 찾으면 None.
|
|
81
|
+
|
|
82
|
+
프로젝트로 인코딩된 디렉터리를 먼저 보고, 없으면 projects_root 아래의
|
|
83
|
+
모든 인코딩 디렉터리를 훑는다. 리드 세션의 cwd 가 대상 프로젝트 루트와
|
|
84
|
+
다를 수 있기 때문이다 — `okstra preflight --cwd <다른 프로젝트>` 는
|
|
85
|
+
지원되는 실행 방식이고, 그때 transcript 는 **리드 세션의 cwd** 로 인코딩된
|
|
86
|
+
디렉터리에 놓인다. 프로젝트 디렉터리만 보면 실재하는 세션을 없다고 답한다.
|
|
87
|
+
|
|
88
|
+
세션 id 는 전역 유일하므로 디렉터리를 넓혀도 다른 세션을 잘못 집지 않는다.
|
|
89
|
+
파일 내용을 읽지 않는 경로 조회다.
|
|
90
|
+
"""
|
|
91
|
+
if not session_id:
|
|
92
|
+
return None
|
|
93
|
+
direct = claude_project_dir(cwd, projects_root) / f"{session_id}.jsonl"
|
|
94
|
+
if direct.is_file():
|
|
95
|
+
return direct
|
|
96
|
+
root = projects_root or CLAUDE_PROJECTS
|
|
97
|
+
try:
|
|
98
|
+
return next(iter(sorted(root.glob(f"*/{session_id}.jsonl"))), None)
|
|
99
|
+
except OSError:
|
|
100
|
+
return None
|
|
@@ -8,14 +8,15 @@ provider:
|
|
|
8
8
|
`claude-haiku-4-5-*`, `claude-3-5-sonnet-*`, `claude-3-5-haiku-*`,
|
|
9
9
|
`claude-3-opus-*`, `claude-3-haiku-*`.
|
|
10
10
|
* OpenAI / Codex — `gpt-5*`, `gpt-4o*`, `gpt-4*`.
|
|
11
|
-
* Google / Gemini — `gemini-3.6-flash*`, `gemini-3.5-flash*`, `gemini-3.1-pro*`, `gemini-3-flash*`,
|
|
11
|
+
* Google / Gemini — `gemini-3.7-flash*`, `gemini-3.6-flash*`, `gemini-3.5-flash*`, `gemini-3.1-pro*`, `gemini-3-flash*`,
|
|
12
12
|
`gemini-2.5-pro*`, `gemini-2.5-flash*`, `gemini-2.0-flash*`.
|
|
13
13
|
|
|
14
14
|
Matching prefers the longest key that is a substring of the model id (most
|
|
15
15
|
specific wins), so table ordering does not affect the result. Update when
|
|
16
16
|
providers change list pricing.
|
|
17
17
|
|
|
18
|
-
Sources (last verified 2026-08-03
|
|
18
|
+
Sources (last verified 2026-08-03 — Google table re-verified 2026-08-26,
|
|
19
|
+
public list prices, USD per 1M tokens):
|
|
19
20
|
* Anthropic: https://www.anthropic.com/pricing
|
|
20
21
|
* OpenAI: https://openai.com/api/pricing
|
|
21
22
|
* Google: https://ai.google.dev/gemini-api/docs/pricing
|
|
@@ -74,9 +75,10 @@ CLAUDE_PRICING = {
|
|
|
74
75
|
# Anthropic 1h ephemeral cache_creation multiplier on the base input rate.
|
|
75
76
|
CLAUDE_CACHE_CREATE_1H_MULT = 2.0
|
|
76
77
|
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
# `catalog_pricing("codex")`. Substring match order is
|
|
78
|
+
# Codex prices for slugs the provider catalog no longer offers. Prices for
|
|
79
|
+
# registered models -- selectable or hidden -- live in the model catalog and are
|
|
80
|
+
# merged in below via `catalog_pricing("codex")`. Substring match order is
|
|
81
|
+
# longest-key-first
|
|
80
82
|
# (see `_match_pricing`), so this dict's ordering no longer affects matching.
|
|
81
83
|
# For models with no published cached-input rate (o1-pro, o3-pro), cached is set
|
|
82
84
|
# equal to input as a conservative no-discount default.
|
|
@@ -84,6 +86,10 @@ _LEGACY_CODEX_PRICING = {
|
|
|
84
86
|
# model substring -> (input USD/1M, cached_input USD/1M, output USD/1M).
|
|
85
87
|
|
|
86
88
|
# GPT-5 series.
|
|
89
|
+
# gpt-5.6 was dropped from the provider catalog; its rate stays so past runs
|
|
90
|
+
# keep pricing. Substring matching means sol / terra / luna resolve here too
|
|
91
|
+
# -- the 5.6 family rate, not a per-variant price we have a source for.
|
|
92
|
+
"gpt-5.6": (5.00, 0.50, 30.0),
|
|
87
93
|
"gpt-5.2-pro": (21.0, 2.10, 168.0),
|
|
88
94
|
"gpt-5.1": (1.25, 0.125, 10.0),
|
|
89
95
|
"gpt-5-mini": (0.25, 0.025, 2.00),
|
|
@@ -126,8 +132,14 @@ GEMINI_PRICING = {
|
|
|
126
132
|
# forms appear in the wild, so include both for the new 3.x families.
|
|
127
133
|
|
|
128
134
|
# Gemini 3 series.
|
|
129
|
-
|
|
130
|
-
|
|
135
|
+
# 3.7 Flash 와 3.6 Flash 는 2026-12-31 까지 도입 요율 $0.75/$3.75 이고
|
|
136
|
+
# 2027-01-01 에 표준 요율 $1.50/$7.50 으로 오른다(2026-08-26 확인). 이 표에는
|
|
137
|
+
# 시점 개념이 없으므로 지금 청구되는 값을 담는다 — 그날 이후 두 계열을
|
|
138
|
+
# (1.50, 7.50) 으로 갱신해야 한다.
|
|
139
|
+
"3.7-flash": (0.75, 3.75),
|
|
140
|
+
"3-7-flash": (0.75, 3.75),
|
|
141
|
+
"3.6-flash": (0.75, 3.75),
|
|
142
|
+
"3-6-flash": (0.75, 3.75),
|
|
131
143
|
"3.5-flash": (1.50, 9.00),
|
|
132
144
|
"3-5-flash": (1.50, 9.00),
|
|
133
145
|
"3.1-pro": (2.00, 12.0),
|
|
@@ -31,6 +31,11 @@
|
|
|
31
31
|
"items": { "type": "string", "pattern": "\\S" }
|
|
32
32
|
},
|
|
33
33
|
"originEvidence": { "type": "string", "pattern": "\\S" },
|
|
34
|
+
"duplicateOf": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"pattern": "\\S",
|
|
37
|
+
"description": "The existing finding id (`F-NNN`) this candidate overlaps. A declared duplicate is recorded and skips gap verification entirely; restating the finding instead costs one verification round to reject it. The shape stays free-form because `findingId` is free-form in convergence-groups-v2.0; `okstra convergence apply-critic-gaps` owns the check that the id names a finding the state actually carries."
|
|
38
|
+
},
|
|
34
39
|
"severity": { "enum": ["critical", "major", "minor"] },
|
|
35
40
|
"evidenceArtifacts": {
|
|
36
41
|
"type": "array",
|
|
@@ -236,10 +236,7 @@
|
|
|
236
236
|
"dutyId",
|
|
237
237
|
"dispatchKind",
|
|
238
238
|
"round",
|
|
239
|
-
"inputDigest"
|
|
240
|
-
"writePolicy",
|
|
241
|
-
"writePolicyDigest",
|
|
242
|
-
"writeEnforcement"
|
|
239
|
+
"inputDigest"
|
|
243
240
|
],
|
|
244
241
|
"properties": {
|
|
245
242
|
"invocationRef": {"type": "string", "pattern": "\\S"},
|
|
@@ -250,10 +247,7 @@
|
|
|
250
247
|
"dutyId": {"type": "string", "pattern": "\\S"},
|
|
251
248
|
"dispatchKind": {"type": "string", "pattern": "\\S"},
|
|
252
249
|
"round": {"type": "integer", "minimum": 1},
|
|
253
|
-
"inputDigest": {"$ref": "#/$defs/Digest"}
|
|
254
|
-
"writePolicy": {"$ref": "#/$defs/WritePolicy"},
|
|
255
|
-
"writePolicyDigest": {"$ref": "#/$defs/Digest"},
|
|
256
|
-
"writeEnforcement": {"$ref": "#/$defs/WriteEnforcement"}
|
|
250
|
+
"inputDigest": {"$ref": "#/$defs/Digest"}
|
|
257
251
|
},
|
|
258
252
|
"additionalProperties": false
|
|
259
253
|
},
|
|
@@ -268,7 +262,10 @@
|
|
|
268
262
|
"resultPath",
|
|
269
263
|
"errorPath",
|
|
270
264
|
"changeSummary",
|
|
271
|
-
"evidenceSealRef"
|
|
265
|
+
"evidenceSealRef",
|
|
266
|
+
"writePolicy",
|
|
267
|
+
"writePolicyDigest",
|
|
268
|
+
"writeEnforcement"
|
|
272
269
|
],
|
|
273
270
|
"properties": {
|
|
274
271
|
"invocationRef": {"type": "string", "pattern": "\\S"},
|
|
@@ -279,7 +276,10 @@
|
|
|
279
276
|
"resultPath": {"type": ["string", "null"]},
|
|
280
277
|
"errorPath": {"type": ["string", "null"]},
|
|
281
278
|
"changeSummary": {"type": "object"},
|
|
282
|
-
"evidenceSealRef": {"type": ["string", "null"]}
|
|
279
|
+
"evidenceSealRef": {"type": ["string", "null"]},
|
|
280
|
+
"writePolicy": {"$ref": "#/$defs/WritePolicy"},
|
|
281
|
+
"writePolicyDigest": {"$ref": "#/$defs/Digest"},
|
|
282
|
+
"writeEnforcement": {"$ref": "#/$defs/WriteEnforcement"}
|
|
283
283
|
},
|
|
284
284
|
"additionalProperties": false
|
|
285
285
|
},
|