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
|
@@ -15,8 +15,15 @@ from .contract_graph import (
|
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
_CLI_EPILOG = r"""Usage:
|
|
19
|
+
okstra contract-check --root <repo-or-staging-root> [--profile <id> | --operation <id>]
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
|
|
18
23
|
def _parser() -> argparse.ArgumentParser:
|
|
19
24
|
parser = argparse.ArgumentParser(
|
|
25
|
+
epilog=_CLI_EPILOG,
|
|
26
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
20
27
|
prog="okstra contract-check",
|
|
21
28
|
description="Validate runtime contract documents and dependencies.",
|
|
22
29
|
)
|
|
@@ -9,7 +9,8 @@ from pathlib import Path, PurePosixPath
|
|
|
9
9
|
import sys
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
-
from okstra_project.
|
|
12
|
+
from okstra_project.slug import slugify
|
|
13
|
+
from okstra_project.state import StateError, parse_task_key
|
|
13
14
|
|
|
14
15
|
from .convergence_engine import (
|
|
15
16
|
ConvergenceContractError,
|
|
@@ -21,6 +22,11 @@ from .convergence_engine import (
|
|
|
21
22
|
validate_final_state,
|
|
22
23
|
validate_working_state,
|
|
23
24
|
)
|
|
25
|
+
from .convergence_critic_prompt import (
|
|
26
|
+
analyser_results,
|
|
27
|
+
covered_index,
|
|
28
|
+
critic_prompt_body,
|
|
29
|
+
)
|
|
24
30
|
from .convergence_migration import (
|
|
25
31
|
SeedDecision,
|
|
26
32
|
archive_state_bytes,
|
|
@@ -206,7 +212,18 @@ _EXAMPLES: dict[str, dict[str, Any]] = {
|
|
|
206
212
|
"ticketIds": ["TASK-001"],
|
|
207
213
|
"originEvidence": "No rollback query result is present",
|
|
208
214
|
"evidenceArtifacts": [_EVIDENCE_ARTIFACT],
|
|
209
|
-
}
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
# 이미 있는 finding 과 겹치면 다시 쓰지 않고 그 id 를 댄다.
|
|
218
|
+
# 다시 쓴 finding 은 기각에 검증 라운드 하나를 쓰고, 선언된
|
|
219
|
+
# 중복은 하나도 쓰지 않는다.
|
|
220
|
+
"candidateId": "CG-002",
|
|
221
|
+
"summary": "The migration assumption needs a live row",
|
|
222
|
+
"category": "missing",
|
|
223
|
+
"ticketIds": ["TASK-001"],
|
|
224
|
+
"originEvidence": "The same live row F-001 already cites",
|
|
225
|
+
"duplicateOf": "F-001",
|
|
226
|
+
},
|
|
210
227
|
],
|
|
211
228
|
},
|
|
212
229
|
"coverage-batch": {
|
|
@@ -215,11 +232,14 @@ _EXAMPLES: dict[str, dict[str, Any]] = {
|
|
|
215
232
|
"mode": "coverage",
|
|
216
233
|
# The critic's own provider never votes on its gaps, so `provider` here
|
|
217
234
|
# is deliberately absent from `dispatches[]`.
|
|
235
|
+
#
|
|
236
|
+
# 검증 대상 gap 이 하나이므로 배정도 한 명이다 — 로스터 순서 위
|
|
237
|
+
# round-robin 이 G-001 을 claude-worker 에게 준다. codex-worker 는 이
|
|
238
|
+
# 라운드에서 열리지 않는다.
|
|
218
239
|
"provider": "antigravity",
|
|
219
240
|
"modelExecutionValue": "gemini-3.1-pro",
|
|
220
241
|
"dispatches": [
|
|
221
242
|
{"worker": "claude-worker", "status": "completed", "durationMs": 1250},
|
|
222
|
-
{"worker": "codex-worker", "status": "completed", "durationMs": 980},
|
|
223
243
|
],
|
|
224
244
|
"gaps": [
|
|
225
245
|
{
|
|
@@ -235,28 +255,50 @@ _EXAMPLES: dict[str, dict[str, Any]] = {
|
|
|
235
255
|
"disagreeBasis": None,
|
|
236
256
|
"explanation": "The plan cites no rollback verification step",
|
|
237
257
|
},
|
|
238
|
-
"codex-worker": {
|
|
239
|
-
"verdict": "agree",
|
|
240
|
-
"disagreeBasis": None,
|
|
241
|
-
"explanation": "No rollback assertion appears in the stage map",
|
|
242
|
-
},
|
|
243
258
|
},
|
|
244
|
-
}
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
# 선언된 중복은 검증 라운드에 들어가지 않으므로 표가 없다.
|
|
262
|
+
"gapId": "G-002",
|
|
263
|
+
"summary": "The migration assumption needs a live row",
|
|
264
|
+
"category": "missing",
|
|
265
|
+
"ticketIds": ["TASK-001"],
|
|
266
|
+
"originEvidence": "The same live row F-001 already cites",
|
|
267
|
+
"duplicateOf": "F-001",
|
|
268
|
+
"votes": {},
|
|
269
|
+
},
|
|
245
270
|
],
|
|
246
271
|
},
|
|
247
272
|
}
|
|
248
273
|
|
|
249
274
|
|
|
275
|
+
_CLI_EPILOG = r"""Usage:
|
|
276
|
+
okstra convergence seed --groups <path> --work-state <path> \
|
|
277
|
+
--final-state <path> --migration-dir <path> [--restart-from-round0]
|
|
278
|
+
okstra convergence plan-round --work-state <path> --plan <path>
|
|
279
|
+
okstra convergence apply-round --work-state <path> --plan <path> \
|
|
280
|
+
--results <path>
|
|
281
|
+
okstra convergence critic-prompt --run-manifest <path>
|
|
282
|
+
okstra convergence apply-critic-gaps --work-state <path> --results <path>
|
|
283
|
+
okstra convergence finalize --work-state <path> --output <path>
|
|
284
|
+
okstra convergence validate --state <path> --kind <working|final>
|
|
285
|
+
okstra convergence example --kind <groups|round-results|critic-results>
|
|
286
|
+
|
|
287
|
+
Working lifecycle:
|
|
288
|
+
groups v1.0/v2.0 → work v1.0/v2.0 → round-plan/results v1.0 → final v1.3
|
|
289
|
+
historical final readers: v1.0, v1.1, v1.2
|
|
290
|
+
|
|
291
|
+
This internal admin command is consumed by the Phase 5.5 lead contract. It
|
|
292
|
+
does not install or revive the obsolete okstra-convergence skill.
|
|
293
|
+
"""
|
|
294
|
+
|
|
295
|
+
|
|
250
296
|
def _parser() -> argparse.ArgumentParser:
|
|
251
297
|
parser = argparse.ArgumentParser(
|
|
298
|
+
epilog=_CLI_EPILOG,
|
|
299
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
252
300
|
prog="okstra convergence",
|
|
253
301
|
description="Advance and validate deterministic re-verification state.",
|
|
254
|
-
epilog=(
|
|
255
|
-
"Working lifecycle: groups v1.0/v2.0 → work v1.0/v2.0 → "
|
|
256
|
-
"round-plan/results v1.0 → final v1.3\n"
|
|
257
|
-
"historical final readers: v1.0, v1.1, v1.2"
|
|
258
|
-
),
|
|
259
|
-
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
260
302
|
)
|
|
261
303
|
subparsers = parser.add_subparsers(dest="operation", required=True)
|
|
262
304
|
|
|
@@ -323,6 +365,21 @@ def _parser() -> argparse.ArgumentParser:
|
|
|
323
365
|
apply.add_argument("--plan", type=Path, required=True)
|
|
324
366
|
apply.add_argument("--results", type=Path, required=True)
|
|
325
367
|
|
|
368
|
+
critic_prompt = subparsers.add_parser(
|
|
369
|
+
"critic-prompt",
|
|
370
|
+
help="render the coverage-critic task instructions to stdout",
|
|
371
|
+
description=(
|
|
372
|
+
"Print the coverage-critic seed body. The lead writes it verbatim "
|
|
373
|
+
"to the task-instructions file the prompt materializer's "
|
|
374
|
+
"`--instruction` takes — it carries the Round 0 finding list, one "
|
|
375
|
+
"line per Phase 4 analyser result, the prior plan's already-covered "
|
|
376
|
+
"id index when this task has one, and the two mandates. Nothing "
|
|
377
|
+
"here is hand-written."
|
|
378
|
+
),
|
|
379
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
380
|
+
)
|
|
381
|
+
critic_prompt.add_argument("--run-manifest", type=Path, required=True)
|
|
382
|
+
|
|
326
383
|
apply_critic = subparsers.add_parser(
|
|
327
384
|
"apply-critic-gaps",
|
|
328
385
|
help="apply one coverage-critic verification batch",
|
|
@@ -1189,6 +1246,32 @@ def _convergence_config(authority: RunArtifactAuthority) -> Mapping[str, Any]:
|
|
|
1189
1246
|
return config
|
|
1190
1247
|
|
|
1191
1248
|
|
|
1249
|
+
def _critic_prompt(args: argparse.Namespace) -> str:
|
|
1250
|
+
"""coverage-critic 지시문 본문. 입력은 이 run 의 매니페스트 하나뿐이다."""
|
|
1251
|
+
authority = validated_run_authority(args.run_manifest)
|
|
1252
|
+
groups_path = authority.run_dir / "state" / _canonical_run_artifact_name(
|
|
1253
|
+
"convergence-groups", authority.task_type, authority.state_sequence
|
|
1254
|
+
)
|
|
1255
|
+
if not groups_path.is_file():
|
|
1256
|
+
raise ConvergenceContractError(
|
|
1257
|
+
"the critic seed needs the Round 0 grouping; run "
|
|
1258
|
+
f"`okstra convergence prepare-groups` first: {groups_path}"
|
|
1259
|
+
)
|
|
1260
|
+
groups = load_owned_json_object(groups_path)
|
|
1261
|
+
return critic_prompt_body(
|
|
1262
|
+
groups,
|
|
1263
|
+
analysis_packet_path=_manifest_authority_string(
|
|
1264
|
+
authority.payload, "analysisPacketPath"
|
|
1265
|
+
),
|
|
1266
|
+
results=analyser_results(
|
|
1267
|
+
groups,
|
|
1268
|
+
project_root=authority.project_root,
|
|
1269
|
+
run_dir=authority.run_dir,
|
|
1270
|
+
),
|
|
1271
|
+
covered=covered_index(authority.project_root, authority.run_dir),
|
|
1272
|
+
)
|
|
1273
|
+
|
|
1274
|
+
|
|
1192
1275
|
def _prepare_groups(args: argparse.Namespace) -> tuple[str, Path]:
|
|
1193
1276
|
authority = validated_run_authority(args.run_manifest)
|
|
1194
1277
|
manifest = authority.payload
|
|
@@ -1253,6 +1336,9 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1253
1336
|
)
|
|
1254
1337
|
return 0
|
|
1255
1338
|
try:
|
|
1339
|
+
if args.operation == "critic-prompt":
|
|
1340
|
+
print(_critic_prompt(args), end="")
|
|
1341
|
+
return 0
|
|
1256
1342
|
action, path = _execute(args)
|
|
1257
1343
|
except (ConvergenceContractError, VerdictBlockError,
|
|
1258
1344
|
json.JSONDecodeError, ValueError) as exc:
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"""Coverage-critic 시드 프롬프트를 디스크의 사실에서 결정적으로 렌더한다.
|
|
2
|
+
|
|
3
|
+
Phase 5.5 의 critic 은 리드가 손으로 쓴 지시문을 받아 왔다. 시드가 Round 0
|
|
4
|
+
finding 목록뿐이라 critic 은 "이미 다뤄진 것"을 알 방법이 없었고, 직전 리포트가
|
|
5
|
+
이미 덮은 항목을 갭으로 다시 제안했다. 그 재제안 한 건의 값은 gap 검증 라운드
|
|
6
|
+
하나이고, 그 라운드는 직렬 경로 위에 있다.
|
|
7
|
+
|
|
8
|
+
이 모듈은 그 시드를 코드로 만든다. 네 덩어리를 싣는다.
|
|
9
|
+
|
|
10
|
+
- Round 0 통합 finding 목록 (리드가 붙여 넣던 것과 같은 내용).
|
|
11
|
+
- Phase 4 분석자별 결과 파일 경로와 그 워커가 낸 finding id — "이름을 댄 결과를
|
|
12
|
+
열어라"는 지시가 실제 파일을 가리키게 한다.
|
|
13
|
+
- 직전 implementation-planning 리포트가 있으면(재실행) 그 리포트의 커버리지 행
|
|
14
|
+
id, clarification 행 id, stage 제목만 뽑은 "이미 다뤄진 것" 색인. **본문은
|
|
15
|
+
절대 싣지 않는다** — 283K 리포트를 통째로 실었다가 report-writer 가 timeout
|
|
16
|
+
난 적이 있다.
|
|
17
|
+
- 두 갈래 지시문(누락 / `unrequested-scope`)과 중복 선언 규칙.
|
|
18
|
+
|
|
19
|
+
산출물은 프롬프트 materializer 의 `--instruction` 이 받는 task 지시문 파일
|
|
20
|
+
본문이다(`prompts/lead/convergence.md` §"Dispatch (fresh one-shot)"). 그래서 그
|
|
21
|
+
계약이 BLOCKING 으로 요구하는 두 줄(`**Prompt Delivery Mode:**`, `## Inputs`
|
|
22
|
+
아래의 Primary analysis packet)도 이 본문이 직접 낸다 — 리드가 손으로 덧붙이던
|
|
23
|
+
자리다.
|
|
24
|
+
"""
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from dataclasses import dataclass
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Any, Mapping, Sequence
|
|
30
|
+
|
|
31
|
+
from .convergence_provenance import worker_result_suffix
|
|
32
|
+
from .fixed_text import line
|
|
33
|
+
from .json_boundary import JsonBoundaryError, load_owned_object
|
|
34
|
+
from .paths import RunRef
|
|
35
|
+
from .plan_run_root import list_implementation_planning_reports
|
|
36
|
+
from .stage_map import StageMapError, parse_stage_map_file
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
PROMPT_DELIVERY_MODE = "eager-include"
|
|
40
|
+
PLANNING_TASK_TYPE = "implementation-planning"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class CriticPromptError(ValueError):
|
|
44
|
+
"""시드를 결정적으로 만들 수 없다."""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class AnalyserResult:
|
|
49
|
+
"""한 Phase 4 분석자가 남긴 결과 파일과 그 워커가 낸 finding id."""
|
|
50
|
+
|
|
51
|
+
worker_id: str
|
|
52
|
+
result_path: str
|
|
53
|
+
finding_ids: tuple[str, ...]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass(frozen=True)
|
|
57
|
+
class CoveredIndex:
|
|
58
|
+
"""직전 계획이 이미 덮은 것의 id 색인. 본문은 담지 않는다.
|
|
59
|
+
|
|
60
|
+
``stage_titles`` 의 ``None`` 은 "Stage Map 을 못 읽었다" 이고 빈 튜플과 다르다
|
|
61
|
+
— 계획의 stage 번호는 `1..N` 이라 0 개인 계획은 없으므로, 못 읽은 것을 0 으로
|
|
62
|
+
쓰면 critic 에게 거짓을 말하게 된다(`stage_ledger.build_stage_ledger` 가 같은
|
|
63
|
+
이유로 세 결과를 구분한다).
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
plan_path: str
|
|
67
|
+
requirement_ids: tuple[str, ...]
|
|
68
|
+
clarification_ids: tuple[str, ...]
|
|
69
|
+
stage_titles: tuple[tuple[int, str], ...] | None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _nonempty_string(value: Any) -> str:
|
|
73
|
+
return value if isinstance(value, str) and value.strip() else ""
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _project_relative(project_root: Path, path: Path) -> str:
|
|
77
|
+
try:
|
|
78
|
+
return path.resolve().relative_to(Path(project_root).resolve()).as_posix()
|
|
79
|
+
except ValueError:
|
|
80
|
+
# expected-miss: 프로젝트 루트 밖의 경로 = 상대화 대상이 아니다. run 트리
|
|
81
|
+
# 밖을 가리키는 것은 정상 분기이며, 그때는 있는 그대로 적는다.
|
|
82
|
+
return path.as_posix()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _analysis_roster(groups: Mapping[str, Any]) -> list[str]:
|
|
86
|
+
workers = groups.get("workers")
|
|
87
|
+
if not isinstance(workers, list):
|
|
88
|
+
return []
|
|
89
|
+
return [
|
|
90
|
+
worker["workerId"]
|
|
91
|
+
for worker in workers
|
|
92
|
+
if isinstance(worker, Mapping)
|
|
93
|
+
and worker.get("audience") == "analysis"
|
|
94
|
+
and _nonempty_string(worker.get("workerId"))
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _findings_by_worker(groups: Mapping[str, Any]) -> dict[str, list[str]]:
|
|
99
|
+
"""워커 → 그 워커가 출처인 finding id. 그룹 순서를 유지한다.
|
|
100
|
+
|
|
101
|
+
`sourceItems` 와 `discoveredBy` 를 합집합으로 본다 — 그룹 파서
|
|
102
|
+
(`convergence_engine._parse_group`)가 출처 워커를 그렇게 센다. 한쪽만 보면
|
|
103
|
+
다른 쪽에만 적힌 워커의 결과 파일이 "낸 것 없음"으로 보인다.
|
|
104
|
+
"""
|
|
105
|
+
by_worker: dict[str, list[str]] = {}
|
|
106
|
+
|
|
107
|
+
def _record(worker: Any, finding_id: str) -> None:
|
|
108
|
+
name = _nonempty_string(worker)
|
|
109
|
+
if name and finding_id not in by_worker.setdefault(name, []):
|
|
110
|
+
by_worker[name].append(finding_id)
|
|
111
|
+
|
|
112
|
+
for group in groups.get("groups") or []:
|
|
113
|
+
if not isinstance(group, Mapping):
|
|
114
|
+
continue
|
|
115
|
+
finding_id = _nonempty_string(group.get("findingId"))
|
|
116
|
+
if not finding_id:
|
|
117
|
+
continue
|
|
118
|
+
for item in group.get("sourceItems") or []:
|
|
119
|
+
source = item.get("worker") if isinstance(item, Mapping) else None
|
|
120
|
+
_record(source, finding_id)
|
|
121
|
+
discovered = group.get("discoveredBy")
|
|
122
|
+
for worker in discovered if isinstance(discovered, Mapping) else {}:
|
|
123
|
+
_record(worker, finding_id)
|
|
124
|
+
return by_worker
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def analyser_results(
|
|
128
|
+
groups: Mapping[str, Any],
|
|
129
|
+
*,
|
|
130
|
+
project_root: Path,
|
|
131
|
+
run_dir: Path,
|
|
132
|
+
) -> list[AnalyserResult]:
|
|
133
|
+
"""분석 audience 워커마다 결과 파일 경로와 finding id 를 짝지어 돌려준다.
|
|
134
|
+
|
|
135
|
+
결과 파일명은 `convergence_provenance` 가 이미 소유한 규칙을 그대로 쓴다 —
|
|
136
|
+
`<worker>-worker-<task-type>-<workerResults seq>.md`. state 시퀀스와 다른
|
|
137
|
+
카운터라 그룹 파일명에서 접미사를 빌려 오면 빗나간다.
|
|
138
|
+
"""
|
|
139
|
+
suffix = worker_result_suffix(Path(run_dir), groups)
|
|
140
|
+
if suffix is None:
|
|
141
|
+
raise CriticPromptError(
|
|
142
|
+
"cannot resolve the worker-result suffix from the grouping's "
|
|
143
|
+
"runManifestPath"
|
|
144
|
+
)
|
|
145
|
+
results_dir = Path(run_dir) / "worker-results"
|
|
146
|
+
by_worker = _findings_by_worker(groups)
|
|
147
|
+
return [
|
|
148
|
+
AnalyserResult(
|
|
149
|
+
worker_id=worker,
|
|
150
|
+
result_path=_project_relative(
|
|
151
|
+
project_root, results_dir / f"{worker}-worker-{suffix}.md"
|
|
152
|
+
),
|
|
153
|
+
finding_ids=tuple(by_worker.get(worker, ())),
|
|
154
|
+
)
|
|
155
|
+
for worker in _analysis_roster(groups)
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def covered_index(project_root: Path, run_dir: Path) -> CoveredIndex | None:
|
|
160
|
+
"""직전 implementation-planning 리포트의 id 색인. 없으면 ``None``.
|
|
161
|
+
|
|
162
|
+
Phase 5.5 는 Phase 6 보다 앞이라 이 run 의 리포트는 아직 없다. 그래서
|
|
163
|
+
reports 디렉터리의 최신 리포트는 언제나 **직전** run 의 것이다.
|
|
164
|
+
|
|
165
|
+
계획 run 에서만 싣는다. 다른 phase 의 finding 은 계획의 커버리지 행이 덮는
|
|
166
|
+
대상이 아니라서, 같은 목록을 "이미 다뤄진 것"으로 보여 주면 critic 이 실재하는
|
|
167
|
+
갭을 중복으로 접는다.
|
|
168
|
+
"""
|
|
169
|
+
try:
|
|
170
|
+
ref = RunRef.from_run_dir(Path(run_dir))
|
|
171
|
+
except ValueError:
|
|
172
|
+
# expected-miss: `runs/` 앵커가 없는 경로 = okstra run 트리가 아니다.
|
|
173
|
+
# 그런 곳에는 직전 계획도 없다.
|
|
174
|
+
return None
|
|
175
|
+
if ref.task_type != PLANNING_TASK_TYPE:
|
|
176
|
+
return None
|
|
177
|
+
reports_dir = RunRef.from_task_root(
|
|
178
|
+
ref.task_root, PLANNING_TASK_TYPE
|
|
179
|
+
).reports_dir
|
|
180
|
+
if not reports_dir.is_dir():
|
|
181
|
+
return None
|
|
182
|
+
reports = list_implementation_planning_reports(reports_dir)
|
|
183
|
+
if not reports:
|
|
184
|
+
return None
|
|
185
|
+
report = reports[0]
|
|
186
|
+
try:
|
|
187
|
+
data = load_owned_object(report, artifact="planning final report")
|
|
188
|
+
except (OSError, UnicodeError, JsonBoundaryError) as exc:
|
|
189
|
+
raise CriticPromptError(
|
|
190
|
+
f"prior planning report is unreadable: {report} ({exc})"
|
|
191
|
+
) from exc
|
|
192
|
+
if not isinstance(data, Mapping):
|
|
193
|
+
raise CriticPromptError(f"prior planning report is not an object: {report}")
|
|
194
|
+
planning = data.get("implementationPlanning")
|
|
195
|
+
planning = planning if isinstance(planning, Mapping) else {}
|
|
196
|
+
try:
|
|
197
|
+
stages: list[Any] | None = parse_stage_map_file(report)
|
|
198
|
+
except StageMapError:
|
|
199
|
+
# expected-miss: schema v1 마크다운 계획이거나 Stage Map 이 깨졌다. 둘 다
|
|
200
|
+
# 나머지 색인(요구사항·clarification id)은 그대로 쓸 수 있는 분기이므로,
|
|
201
|
+
# 여기서 멈추는 대신 "못 읽었다"를 그대로 실어 보낸다.
|
|
202
|
+
stages = None
|
|
203
|
+
return CoveredIndex(
|
|
204
|
+
plan_path=_project_relative(project_root, report),
|
|
205
|
+
requirement_ids=tuple(
|
|
206
|
+
_nonempty_string(row.get("id"))
|
|
207
|
+
for row in planning.get("requirementCoverage") or []
|
|
208
|
+
if isinstance(row, Mapping) and _nonempty_string(row.get("id"))
|
|
209
|
+
),
|
|
210
|
+
clarification_ids=tuple(
|
|
211
|
+
_nonempty_string(row.get("id"))
|
|
212
|
+
for row in data.get("clarificationItems") or []
|
|
213
|
+
if isinstance(row, Mapping) and _nonempty_string(row.get("id"))
|
|
214
|
+
),
|
|
215
|
+
stage_titles=None if stages is None else tuple(
|
|
216
|
+
(stage.stage_number, stage.title) for stage in stages
|
|
217
|
+
),
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
_MANDATES = """
|
|
222
|
+
Your job has exactly two halves. Answer both.
|
|
223
|
+
|
|
224
|
+
(1) MISSING — name what nobody covered:
|
|
225
|
+
- files / directories / execution paths nobody inspected,
|
|
226
|
+
- requirements or acceptance points with zero findings,
|
|
227
|
+
- claims raised but never verified.
|
|
228
|
+
For each, emit a NEW finding with evidence (file:line or the requirement quote).
|
|
229
|
+
|
|
230
|
+
(2) UNREQUESTED — name work these findings propose that no requirement asked for:
|
|
231
|
+
- a finding whose proposed change serves no requirement, scope item, or
|
|
232
|
+
acceptance point you can QUOTE from the analysis packet,
|
|
233
|
+
- an abstraction, configuration knob, or generalization proposed for a caller or
|
|
234
|
+
a case nobody has stated,
|
|
235
|
+
- a rewrite, migration, or cleanup of code the requirements never mention.
|
|
236
|
+
For each, emit a candidate with `category: "unrequested-scope"`, quote the
|
|
237
|
+
proposed work verbatim, and state which requirement you searched for and did not
|
|
238
|
+
find.
|
|
239
|
+
|
|
240
|
+
Do NOT restate an existing finding. An overlap with an existing finding is
|
|
241
|
+
declared as `duplicateOf` naming that finding id, not restated as a new
|
|
242
|
+
candidate — a restated finding costs a whole verification round to reject, while
|
|
243
|
+
a declared duplicate costs none. Judge (2) against the analysis packet's
|
|
244
|
+
requirements and scope, never against your own preference for how the code
|
|
245
|
+
should look — "I would have done it differently" is not unrequested work, and
|
|
246
|
+
neither is work the packet authorizes but you consider unnecessary. If a half
|
|
247
|
+
has nothing, say so explicitly for that half; silence on one half is an
|
|
248
|
+
incomplete result.
|
|
249
|
+
|
|
250
|
+
Read before proposing anything: the analysis packet named above for requirements
|
|
251
|
+
and phase scope, the Round 0 findings below, and the named result file of any
|
|
252
|
+
analyser whose coverage you intend to call incomplete. Do NOT infer missing
|
|
253
|
+
verification from a one-line summary.
|
|
254
|
+
""".strip()
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def critic_prompt_body(
|
|
258
|
+
groups: Mapping[str, Any],
|
|
259
|
+
*,
|
|
260
|
+
analysis_packet_path: str,
|
|
261
|
+
results: Sequence[AnalyserResult],
|
|
262
|
+
covered: CoveredIndex | None,
|
|
263
|
+
) -> str:
|
|
264
|
+
"""critic 지시문 파일 본문. 같은 입력이면 같은 바이트를 낸다."""
|
|
265
|
+
task_key = _nonempty_string(groups.get("taskKey"))
|
|
266
|
+
if not task_key:
|
|
267
|
+
raise CriticPromptError("convergence groups carry no taskKey")
|
|
268
|
+
packet = _nonempty_string(analysis_packet_path)
|
|
269
|
+
if not packet.endswith("analysis-packet.md"):
|
|
270
|
+
raise CriticPromptError(
|
|
271
|
+
"run manifest analysisPacketPath must name analysis-packet.md; "
|
|
272
|
+
f"found `{analysis_packet_path}`"
|
|
273
|
+
)
|
|
274
|
+
rows: list[str] = [
|
|
275
|
+
f"**Prompt Delivery Mode:** {PROMPT_DELIVERY_MODE}\n",
|
|
276
|
+
"\n",
|
|
277
|
+
f"# Coverage critic — {task_key}\n",
|
|
278
|
+
"\n",
|
|
279
|
+
"## Inputs\n",
|
|
280
|
+
f"- Primary analysis packet: `{packet}`\n",
|
|
281
|
+
"\n",
|
|
282
|
+
"## Mandate\n",
|
|
283
|
+
"\n",
|
|
284
|
+
_MANDATES,
|
|
285
|
+
"\n\n",
|
|
286
|
+
]
|
|
287
|
+
rows.extend(_round0_rows(groups))
|
|
288
|
+
rows.extend(_analyser_rows(results))
|
|
289
|
+
rows.extend(_covered_rows(covered))
|
|
290
|
+
return "".join(rows)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def _round0_rows(groups: Mapping[str, Any]) -> list[str]:
|
|
294
|
+
findings = [
|
|
295
|
+
group for group in groups.get("groups") or [] if isinstance(group, Mapping)
|
|
296
|
+
]
|
|
297
|
+
rows = ["## Round 0 consolidated findings\n", line("Finding count", len(findings))]
|
|
298
|
+
for group in findings:
|
|
299
|
+
rows.append(f"\n### {_nonempty_string(group.get('findingId')) or '-'}\n")
|
|
300
|
+
rows.append(line("Summary", group.get("summary")))
|
|
301
|
+
rows.append(line("Category", group.get("category")))
|
|
302
|
+
rows.append(line("Ticket ids", ", ".join(group.get("ticketIds") or [])))
|
|
303
|
+
rows.append(line("Origin worker", group.get("originWorker")))
|
|
304
|
+
rows.append(line("Origin evidence", group.get("originEvidence")))
|
|
305
|
+
rows.append("\n")
|
|
306
|
+
return rows
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def _analyser_rows(results: Sequence[AnalyserResult]) -> list[str]:
|
|
310
|
+
rows = [
|
|
311
|
+
"## Phase 4 analyser results\n",
|
|
312
|
+
line("Analyser count", len(results)),
|
|
313
|
+
]
|
|
314
|
+
for index, result in enumerate(results, 1):
|
|
315
|
+
rows.append(line(f"Analyser {index} worker id", result.worker_id))
|
|
316
|
+
rows.append(line(f"Analyser {index} result path", result.result_path))
|
|
317
|
+
rows.append(
|
|
318
|
+
line(f"Analyser {index} finding ids", ", ".join(result.finding_ids))
|
|
319
|
+
)
|
|
320
|
+
rows.append("\n")
|
|
321
|
+
return rows
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def _covered_rows(covered: CoveredIndex | None) -> list[str]:
|
|
325
|
+
if covered is None:
|
|
326
|
+
return []
|
|
327
|
+
rows = [
|
|
328
|
+
"## Already covered by the prior plan\n",
|
|
329
|
+
"\n",
|
|
330
|
+
"Ids and titles only. A candidate that repeats one of these is a "
|
|
331
|
+
"duplicate: declare it with `duplicateOf`, or do not raise it.\n",
|
|
332
|
+
"\n",
|
|
333
|
+
line("Prior plan path", covered.plan_path),
|
|
334
|
+
line("Requirement coverage row ids", ", ".join(covered.requirement_ids)),
|
|
335
|
+
line("Clarification row ids", ", ".join(covered.clarification_ids)),
|
|
336
|
+
]
|
|
337
|
+
if covered.stage_titles is None:
|
|
338
|
+
rows.append(line("Stage map", "unreadable"))
|
|
339
|
+
rows.append("\n")
|
|
340
|
+
return rows
|
|
341
|
+
rows.append(line("Stage count", len(covered.stage_titles)))
|
|
342
|
+
for number, title in covered.stage_titles:
|
|
343
|
+
rows.append(line(f"Stage {number} title", title))
|
|
344
|
+
rows.append("\n")
|
|
345
|
+
return rows
|