okstra 0.206.0 → 0.207.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 +3 -3
- package/dist/cli-registry.mjs +7 -1
- package/dist/cli-registry.mjs.map +1 -1
- package/dist/commands/lifecycle/install.mjs +1 -1
- package/dist/commands/lifecycle/install.mjs.map +1 -1
- package/docs/architecture/storage-model.md +1 -0
- package/docs/architecture.md +40 -16
- package/docs/cli.md +17 -15
- package/docs/contributor-change-matrix.md +3 -2
- package/docs/performance-improvement-plan-v2.md +1 -1
- package/docs/project-structure-overview.md +43 -20
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/operations/code-review.json +1 -1
- package/runtime/bin/lib/okstra/usage.sh +3 -3
- package/runtime/bin/okstra-compact-reminder.sh +1 -1
- package/runtime/bin/okstra-spawn-followups.py +2 -2
- package/runtime/prompts/duties/direction-selection-worker.json +1 -1
- package/runtime/prompts/launch.template.md +2 -2
- package/runtime/prompts/lead/adapters/cmux.md +4 -3
- package/runtime/prompts/lead/context-loader.md +1 -1
- package/runtime/prompts/lead/convergence.md +44 -12
- package/runtime/prompts/lead/okstra-lead-contract.md +44 -73
- package/runtime/prompts/lead/phase-routing.md +64 -0
- package/runtime/prompts/lead/report-writer.md +10 -8
- package/runtime/prompts/lead/team-contract.md +1 -1
- package/runtime/prompts/profiles/_clarification-recommendation.md +4 -4
- package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +2 -2
- package/runtime/prompts/profiles/_coverage-critic.md +1 -1
- package/runtime/prompts/profiles/forbidden-actions.json +0 -94
- package/runtime/prompts/wizard/prompts.ko.json +2 -1
- package/runtime/python/okstra_ctl/adapters/hosts/antigravity/relay.md +1 -1
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +5 -5
- package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +1 -1
- package/runtime/python/okstra_ctl/adapters/hosts/external/relay.md +3 -2
- package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +1 -1
- package/runtime/python/okstra_ctl/adapters/hosts/kimi/relay.md +1 -1
- package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +17 -26
- package/runtime/python/okstra_ctl/agent/prompt_cli/batch.py +183 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +60 -10
- package/runtime/python/okstra_ctl/agent/prompt_cli/corrections.py +1 -1
- package/runtime/python/okstra_ctl/agent/prompt_cli/jobs.py +21 -4
- package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +10 -1
- package/runtime/python/okstra_ctl/analysis_inputs.py +0 -39
- package/runtime/python/okstra_ctl/analysis_scope.py +31 -0
- package/runtime/python/okstra_ctl/approval_decisions.py +32 -2
- package/runtime/python/okstra_ctl/asset_roots.py +19 -0
- package/runtime/python/okstra_ctl/assignment_resolver.py +8 -0
- package/runtime/python/okstra_ctl/blocking_checks.py +7 -0
- package/runtime/python/okstra_ctl/code_review_target.py +92 -6
- package/runtime/python/okstra_ctl/consumers.py +12 -0
- package/runtime/python/okstra_ctl/dispatch_checkpoints.py +121 -0
- package/runtime/python/okstra_ctl/dispatch_core.py +54 -32
- package/runtime/python/okstra_ctl/dispatch_state.py +34 -5
- package/runtime/python/okstra_ctl/doctor.py +2 -1
- package/runtime/python/okstra_ctl/domain/provider.py +5 -0
- package/runtime/python/okstra_ctl/domain/worker_presentation.py +21 -2
- package/runtime/python/okstra_ctl/domain/write_policy.py +2 -1
- package/runtime/python/okstra_ctl/execution_mutation_audit.py +46 -9
- package/runtime/python/okstra_ctl/handoff.py +11 -466
- package/runtime/python/okstra_ctl/handoff_error.py +5 -0
- package/runtime/python/okstra_ctl/implementation_direction.py +0 -477
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +13 -1
- package/runtime/python/okstra_ctl/lead_progress.py +33 -1
- package/runtime/python/okstra_ctl/manager_view.py +26 -19
- package/runtime/python/okstra_ctl/model_io/lines.py +21 -4
- package/runtime/python/okstra_ctl/models.py +4 -1
- package/runtime/python/okstra_ctl/operation_invocation.py +11 -2
- package/runtime/python/okstra_ctl/option_comparison.py +3 -165
- package/runtime/python/okstra_ctl/option_votes.py +3 -191
- package/runtime/python/okstra_ctl/paths.py +8 -6
- package/runtime/python/okstra_ctl/phases/catalog.py +56 -12
- package/runtime/python/okstra_ctl/phases/change_impact_analysis/boundary.json +11 -0
- package/runtime/python/okstra_ctl/phases/change_impact_analysis/entry.py +39 -0
- package/runtime/python/okstra_ctl/{report_html/view_models/change_impact_analysis.py → phases/change_impact_analysis/report.py} +3 -3
- package/runtime/python/okstra_ctl/phases/change_impact_analysis/spec.md +26 -0
- package/runtime/python/okstra_ctl/phases/change_impact_analysis/validation.py +23 -0
- package/runtime/python/okstra_ctl/phases/error_analysis/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/error_analysis/boundary.json +9 -0
- package/runtime/{prompts/profiles/error-analysis.md → python/okstra_ctl/phases/error_analysis/profile.md} +2 -2
- package/runtime/python/okstra_ctl/{report_html/view_models/error_analysis.py → phases/error_analysis/report.py} +9 -8
- package/runtime/{templates/reports → python/okstra_ctl/phases/error_analysis/report_assets}/error-analysis-input.template.md +1 -1
- package/runtime/python/okstra_ctl/phases/error_analysis/spec.md +118 -0
- package/runtime/python/okstra_ctl/phases/error_analysis/validation.py +241 -0
- package/runtime/python/okstra_ctl/phases/feature_analysis/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/feature_analysis/boundary.json +8 -0
- package/runtime/python/okstra_ctl/phases/feature_analysis/entry.py +63 -0
- package/runtime/python/okstra_ctl/{report_html/view_models/feature_analysis.py → phases/feature_analysis/report.py} +12 -5
- package/runtime/python/okstra_ctl/phases/feature_analysis/spec.md +22 -0
- package/runtime/python/okstra_ctl/phases/feature_analysis/validation.py +27 -0
- package/runtime/python/okstra_ctl/phases/feature_analysis/wizard.py +95 -0
- package/runtime/python/okstra_ctl/phases/final_verification/boundary.json +8 -0
- package/runtime/python/okstra_ctl/phases/final_verification/profile.md +2 -2
- package/runtime/{templates/reports → python/okstra_ctl/phases/final_verification/report_assets}/final-verification-input.template.md +1 -1
- package/runtime/python/okstra_ctl/phases/final_verification/spec.md +1 -1
- package/runtime/python/okstra_ctl/phases/implementation/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/implementation/boundary.json +17 -0
- package/runtime/python/okstra_ctl/{implementation_stage.py → phases/implementation/entry.py} +22 -10
- package/runtime/{prompts/host-orchestration/implementation.md → python/okstra_ctl/phases/implementation/host-rules.md} +1 -1
- package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-deliverable.md +1 -1
- package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-executor.md +4 -3
- package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-verifier.md +18 -7
- package/runtime/{prompts/profiles/implementation.md → python/okstra_ctl/phases/implementation/profile.md} +5 -5
- package/runtime/python/okstra_ctl/{report_html/view_models/implementation.py → phases/implementation/report.py} +3 -3
- package/runtime/{templates/reports → python/okstra_ctl/phases/implementation/report_assets}/implementation-input.template.md +1 -1
- package/runtime/python/okstra_ctl/phases/implementation/spec.md +238 -0
- package/runtime/python/okstra_ctl/phases/implementation/validation.py +205 -0
- package/runtime/python/okstra_ctl/phases/implementation/wizard.py +39 -0
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/authoring.py +80 -0
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/boundary.json +10 -0
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/comparison.py +168 -0
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/entry.py +27 -0
- package/runtime/{prompts/profiles/implementation-option-selection.md → python/okstra_ctl/phases/implementation_option_selection/profile.md} +3 -3
- package/runtime/python/okstra_ctl/{report_html/view_models/implementation_option_selection.py → phases/implementation_option_selection/report.py} +2 -2
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/spec.md +83 -0
- package/runtime/python/okstra_ctl/{implementation_options.py → phases/implementation_option_selection/validation.py} +3 -3
- package/runtime/python/okstra_ctl/phases/implementation_option_selection/votes.py +194 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/authoring.py +2345 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/boundary.json +12 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/entry.py +161 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/guidance.py +178 -0
- package/runtime/{prompts/lead → python/okstra_ctl/phases/implementation_planning/instructions}/plan-body-verification.md +61 -51
- package/runtime/python/okstra_ctl/phases/implementation_planning/plan_body.py +3295 -0
- package/runtime/{prompts/profiles/implementation-planning.md → python/okstra_ctl/phases/implementation_planning/profile.md} +74 -25
- package/runtime/python/okstra_ctl/phases/implementation_planning/report.py +237 -0
- package/runtime/{templates/reports → python/okstra_ctl/phases/implementation_planning/report_assets}/implementation-planning-input.template.md +2 -2
- package/runtime/python/okstra_ctl/phases/implementation_planning/spec.md +204 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/validation.py +597 -0
- package/runtime/python/okstra_ctl/phases/implementation_planning/wizard.py +166 -0
- package/runtime/python/okstra_ctl/phases/improvement_discovery/boundary.json +12 -0
- package/runtime/python/okstra_ctl/{improvement_lenses.py → phases/improvement_discovery/lenses.py} +1 -6
- package/runtime/{prompts/profiles/improvement-discovery.md → python/okstra_ctl/phases/improvement_discovery/profile.md} +5 -5
- package/runtime/python/okstra_ctl/{report_html/view_models/improvement_discovery.py → phases/improvement_discovery/report.py} +3 -3
- package/runtime/{templates/reports → python/okstra_ctl/phases/improvement_discovery/report_assets}/improvement-discovery-input.template.md +1 -2
- package/runtime/python/okstra_ctl/phases/improvement_discovery/spec.md +29 -0
- package/runtime/{validators/validate_improvement_report.py → python/okstra_ctl/phases/improvement_discovery/validation.py} +5 -14
- package/runtime/python/okstra_ctl/phases/project_analysis/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/project_analysis/boundary.json +8 -0
- package/runtime/python/okstra_ctl/phases/project_analysis/entry.py +11 -0
- package/runtime/python/okstra_ctl/{report_html/view_models/project_analysis.py → phases/project_analysis/report.py} +3 -3
- package/runtime/python/okstra_ctl/phases/project_analysis/spec.md +33 -0
- package/runtime/python/okstra_ctl/phases/project_analysis/validation.py +55 -0
- package/runtime/python/okstra_ctl/phases/release_handoff/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/release_handoff/boundary.json +17 -0
- package/runtime/python/okstra_ctl/phases/release_handoff/entry.py +147 -0
- package/runtime/python/okstra_ctl/phases/release_handoff/operations.py +446 -0
- package/runtime/{prompts/profiles/release-handoff.md → python/okstra_ctl/phases/release_handoff/profile.md} +3 -3
- package/runtime/python/okstra_ctl/{report_html/view_models/release_handoff.py → phases/release_handoff/report.py} +3 -3
- package/runtime/{templates/reports → python/okstra_ctl/phases/release_handoff/report_assets}/release-handoff-input.template.md +1 -1
- package/runtime/python/okstra_ctl/phases/release_handoff/spec.md +233 -0
- package/runtime/python/okstra_ctl/phases/release_handoff/wizard.py +84 -0
- package/runtime/python/okstra_ctl/phases/requirements_discovery/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/requirements_discovery/boundary.json +9 -0
- package/runtime/{prompts/profiles/requirements-discovery.md → python/okstra_ctl/phases/requirements_discovery/profile.md} +2 -3
- package/runtime/python/okstra_ctl/{report_html/view_models/requirements_discovery.py → phases/requirements_discovery/report.py} +3 -3
- package/runtime/python/okstra_ctl/phases/requirements_discovery/spec.md +132 -0
- package/runtime/{validators/validate_fanout.py → python/okstra_ctl/phases/requirements_discovery/validation.py} +11 -12
- package/runtime/python/okstra_ctl/phases/technical_verification/__init__.py +1 -0
- package/runtime/python/okstra_ctl/phases/technical_verification/boundary.json +9 -0
- package/runtime/python/okstra_ctl/phases/technical_verification/entry.py +100 -0
- package/runtime/{prompts/profiles/technical-verification.md → python/okstra_ctl/phases/technical_verification/profile.md} +2 -2
- package/runtime/python/okstra_ctl/{report_html/view_models/technical_verification.py → phases/technical_verification/report.py} +2 -2
- package/runtime/python/okstra_ctl/phases/technical_verification/spec.md +37 -0
- package/runtime/python/okstra_ctl/phases/technical_verification/validation.py +90 -0
- package/runtime/python/okstra_ctl/plan_approval.py +70 -0
- package/runtime/python/okstra_ctl/plan_items_cli.py +2 -2130
- package/runtime/python/okstra_ctl/process_group.py +118 -0
- package/runtime/python/okstra_ctl/profile_show.py +3 -3
- package/runtime/python/okstra_ctl/render.py +15 -4
- package/runtime/python/okstra_ctl/report_assembly.py +28 -92
- package/runtime/python/okstra_ctl/report_finalize.py +106 -2
- package/runtime/python/okstra_ctl/report_html/context_links.py +1 -1
- package/runtime/python/okstra_ctl/report_projections.py +1 -36
- package/runtime/python/okstra_ctl/report_routing.py +23 -0
- package/runtime/python/okstra_ctl/report_synthesis_packet.py +4 -73
- package/runtime/python/okstra_ctl/report_validation_identity.py +38 -0
- package/runtime/python/okstra_ctl/report_views.py +1 -1
- package/runtime/python/okstra_ctl/run.py +68 -350
- package/runtime/python/okstra_ctl/run_artifact_prune.py +200 -0
- package/runtime/python/okstra_ctl/stage_map.py +13 -0
- package/runtime/python/okstra_ctl/team.py +108 -9
- package/runtime/python/okstra_ctl/technical_verification_facts.py +52 -0
- package/runtime/python/okstra_ctl/wizard/__init__.py +31 -31
- package/runtime/python/okstra_ctl/wizard/api.py +18 -0
- package/runtime/python/okstra_ctl/wizard/outcome.py +3 -12
- package/runtime/python/okstra_ctl/wizard/registry.py +20 -12
- package/runtime/python/okstra_ctl/wizard/steps_analysis.py +0 -97
- package/runtime/python/okstra_ctl/wizard/steps_options.py +8 -0
- package/runtime/python/okstra_ctl/wizard/steps_plan.py +10 -263
- package/runtime/python/okstra_ctl/wizard/steps_roles.py +2 -1
- package/runtime/python/okstra_ctl/work_categories.py +1 -1
- package/runtime/python/okstra_ctl/worker_dispatch.py +44 -3
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +36 -0
- package/runtime/python/okstra_ctl/worker_prompt_policy.py +19 -0
- package/runtime/python/okstra_ctl/worker_runner.py +21 -3
- package/runtime/python/okstra_ctl/workflow.py +26 -143
- package/runtime/python/okstra_ctl/write_policy.py +57 -7
- package/runtime/python/okstra_project/dirs.py +14 -0
- package/runtime/python/okstra_project/resolver.py +2 -1
- package/runtime/schemas/execution-manifest-v2.schema.json +2 -1
- package/runtime/skills/okstra-brief-gen/SKILL.md +3 -3
- package/runtime/skills/okstra-code-review/SKILL.md +70 -32
- package/runtime/skills/okstra-code-review/references/review-calibration.md +26 -6
- package/runtime/skills/okstra-run/SKILL.md +3 -3
- package/runtime/templates/manager/view.template.html +18 -1
- package/runtime/templates/reports/quick-input.template.md +1 -1
- package/runtime/templates/reports/task-brief.template.md +1 -1
- package/runtime/validators/validate-brief.py +2 -2
- package/runtime/validators/validate-run.py +299 -3940
- package/runtime/validators/validate_analysis_report.py +14 -126
- package/runtime/python/okstra_ctl/report_html/view_models/implementation_planning.py +0 -147
- package/runtime/python/okstra_ctl/technical_verification.py +0 -195
- /package/runtime/{prompts/profiles/change-impact-analysis.json → python/okstra_ctl/phases/change_impact_analysis/profile.json} +0 -0
- /package/runtime/{prompts/profiles/change-impact-analysis.md → python/okstra_ctl/phases/change_impact_analysis/profile.md} +0 -0
- /package/runtime/{templates/reports → python/okstra_ctl/phases/change_impact_analysis/report_assets}/change-impact-analysis-input.template.md +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/change_impact_analysis/report_assets}/change-impact-analysis.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/change_impact_analysis/report_assets}/change-impact-analysis.template.md +0 -0
- /package/runtime/{prompts/profiles/error-analysis.json → python/okstra_ctl/phases/error_analysis/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/error_analysis/report_assets}/error-analysis.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/error_analysis/report_assets}/error-analysis.template.md +0 -0
- /package/runtime/{prompts/profiles/feature-analysis.json → python/okstra_ctl/phases/feature_analysis/profile.json} +0 -0
- /package/runtime/{prompts/profiles/feature-analysis.md → python/okstra_ctl/phases/feature_analysis/profile.md} +0 -0
- /package/runtime/{templates/reports → python/okstra_ctl/phases/feature_analysis/report_assets}/feature-analysis-input.template.md +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/feature_analysis/report_assets}/feature-analysis.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/feature_analysis/report_assets}/feature-analysis.template.md +0 -0
- /package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-diff-review.md +0 -0
- /package/runtime/{prompts/profiles → python/okstra_ctl/phases/implementation/instructions}/_implementation-self-check.md +0 -0
- /package/runtime/{prompts/profiles/implementation.json → python/okstra_ctl/phases/implementation/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/implementation/report_assets}/implementation.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/implementation/report_assets}/implementation.template.md +0 -0
- /package/runtime/{prompts/profiles/implementation-option-selection.json → python/okstra_ctl/phases/implementation_option_selection/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/implementation_option_selection/report_assets}/implementation-option-selection.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/implementation_option_selection/report_assets}/implementation-option-selection.template.md +0 -0
- /package/runtime/{prompts/host-orchestration/implementation-planning.md → python/okstra_ctl/phases/implementation_planning/host-rules.md} +0 -0
- /package/runtime/{prompts/profiles/implementation-planning.json → python/okstra_ctl/phases/implementation_planning/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/implementation_planning/report_assets}/implementation-planning.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/implementation_planning/report_assets}/implementation-planning.template.md +0 -0
- /package/runtime/{prompts/profiles/improvement-discovery.json → python/okstra_ctl/phases/improvement_discovery/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/improvement_discovery/report_assets}/improvement-discovery.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/improvement_discovery/report_assets}/improvement-discovery.template.md +0 -0
- /package/runtime/{prompts/profiles/project-analysis.json → python/okstra_ctl/phases/project_analysis/profile.json} +0 -0
- /package/runtime/{prompts/profiles/project-analysis.md → python/okstra_ctl/phases/project_analysis/profile.md} +0 -0
- /package/runtime/{templates/reports → python/okstra_ctl/phases/project_analysis/report_assets}/project-analysis-input.template.md +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/project_analysis/report_assets}/project-analysis.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/project_analysis/report_assets}/project-analysis.template.md +0 -0
- /package/runtime/{prompts/profiles/release-handoff.json → python/okstra_ctl/phases/release_handoff/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/release_handoff/report_assets}/release-handoff.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/release_handoff/report_assets}/release-handoff.template.md +0 -0
- /package/runtime/python/okstra_ctl/{fanout.py → phases/requirements_discovery/fanout.py} +0 -0
- /package/runtime/{prompts/profiles/requirements-discovery.json → python/okstra_ctl/phases/requirements_discovery/profile.json} +0 -0
- /package/runtime/{templates/reports → python/okstra_ctl/phases/requirements_discovery/report_assets}/fan-out-unit.template.md +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/requirements_discovery/report_assets}/requirements-discovery.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/requirements_discovery/report_assets}/requirements-discovery.template.md +0 -0
- /package/runtime/{prompts/profiles/technical-verification.json → python/okstra_ctl/phases/technical_verification/profile.json} +0 -0
- /package/runtime/{templates/reports/html/tasks → python/okstra_ctl/phases/technical_verification/report_assets}/technical-verification.template.html +0 -0
- /package/runtime/{templates/reports/md/tasks → python/okstra_ctl/phases/technical_verification/report_assets}/technical-verification.template.md +0 -0
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
**Enforced:** `validators/validate_session_conformance.py` reads the selected adapter's evidence within the run window and reports a missing checkpoint. Missing lines are advisories, not failures — by the time the validator runs the session that would have emitted the line has ended, so the finding records that the run is hard to follow, not that its work is wrong.
|
|
9
9
|
|
|
10
|
-
Emit one `PROGRESS: <phase-id> <verb-phrase>` line as plain user-facing text at every checkpoint enumerated in the lifecycle core contract (`{{OKSTRA_LEAD_CONTRACT_PATH}}` "Progress reporting (BLOCKING)") — phase-1-intake start/complete, phase-2-prompts, phase-3-team-create, phase-4-dispatch (per worker), phase-5-collect (per worker), phase-5.5-convergence (per round), phase-6-synthesis, phase-7-persist, and final `complete`. One line per checkpoint, never batched, never replaced with prose. This is the only signal the user has during multi-minute silent windows. Record each one with `okstra lead-progress append --project-root <dir> --run-manifest <path> --phase <phase-id>` and emit the `progressLine` it prints — that call is what puts the checkpoint where the validator reads it.
|
|
10
|
+
Emit one `PROGRESS: <phase-id> <verb-phrase>` line as plain user-facing text at every checkpoint enumerated in the lifecycle core contract (`{{OKSTRA_LEAD_CONTRACT_PATH}}` "Progress reporting (BLOCKING)") — phase-1-intake start/complete, phase-2-prompts, phase-3-team-create, phase-4-dispatch (per worker), phase-5-collect (per worker), phase-5.5-convergence (per round), phase-6-synthesis, phase-7-persist, and final `complete`. One line per checkpoint, never batched, never replaced with prose. This is the only signal the user has during multi-minute silent windows. Record each one with `okstra lead-progress append --project-root <dir> --run-manifest <path> --phase <phase-id>` and emit the `progressLine` it prints — that call is what puts the checkpoint where the validator reads it. The exception is a checkpoint the command performing the step records itself (`team dispatch`, `team await`, `team reclaim`, `worker-dispatch`, `report-finalize`; the contract lists which): emit the `PROGRESS:` line that command prints and do not append it again.
|
|
11
11
|
|
|
12
12
|
When the run manifest declares `activityContractVersion: 1`, call `okstra agent-activity append` before each required activity boundary. Only after the structured append succeeds, emit the matching `PROGRESS:` line and the immediately following `ACTIVITY:` projection from the same fields. If the structured append fails, do not mark that boundary completed. Never reconstruct structured activity by parsing `ACTIVITY:` conversation text.
|
|
13
13
|
|
|
@@ -189,7 +189,7 @@ The **default is full re-verification**. Narrow this re-run to the impacted stag
|
|
|
189
189
|
```
|
|
190
190
|
The CLI reads the plan's dependency graph from the prior `implementationPlanning.stageMap`, which is authoritative for the impacted stage numbers. The CLI prints JSON `{mode, reverify_stages, carry_stages, reason}` **and writes the same decision** to the record this run's manifest names in `incrementalDecisionPath`. You do not transcribe it: the report writer receives it through its authoring contract, and `incremental-carry` reads the same record. An `unresolved` result is a question back to you and is deliberately not recorded.
|
|
191
191
|
4. **`mode == "full"`** → run the existing full re-verification path unchanged; ignore `reverify_stages` / `carry_stages`.
|
|
192
|
-
5. **`mode == "incremental"`** → scope every worker dispatch prompt to `reverify_stages` only (the downstream closure of the impacted stages). Do NOT re-analyze `carry_stages` — their prior plan-item verdicts are carried forward verbatim (see `
|
|
192
|
+
5. **`mode == "incremental"`** → scope every worker dispatch prompt to `reverify_stages` only (the downstream closure of the impacted stages). Do NOT re-analyze `carry_stages` — their prior plan-item verdicts are carried forward verbatim (see `scripts/okstra_ctl/phases/implementation_planning/profile.md` "Cross-verification mode" and `prompts/lead/convergence.md` "Convergence scope"). When the pin in step 0 was `auto`, this is the decision — do not upgrade it to full.
|
|
193
193
|
6. **`mode == "unresolved"`** → ask the user for stage numbers; re-enter step 3 with those numbers in `--impacted`. Do not fall back to full. Do not record `unresolved` as `incrementalDecision`. Then continue from the new `mode`.
|
|
194
194
|
7. **Merge carried-forward verdicts.** In `incremental` mode the report writer receives the carried stage rows as a packet source and is told, in its own authoring contract, to copy them unchanged — you do not repeat that instruction to it. After `okstra plan-items seed --narrative ... --state ...`, the lead runs:
|
|
195
195
|
```
|
|
@@ -33,7 +33,7 @@ Keep the selected host relay's dispatch permission guidance when calling `okstra
|
|
|
33
33
|
| `await_workers` | Run `okstra team await --project-root <root> --run-manifest <path>` through the host's asynchronous shell facility. |
|
|
34
34
|
| `redispatch_worker` | Create the core-specified fresh jobs file and dispatch it with a new `dispatchKind`; never reuse a live worker conversation. |
|
|
35
35
|
| `shutdown_workers` | Run `okstra team teardown --project-root <root> --run-manifest <path>` only after the user-approved cleanup gate. |
|
|
36
|
-
| `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --project-root <dir> --run-manifest <path> --phase <phase-id>` for a checkpoint and `okstra agent-activity append --project-root <dir> --run-manifest <path> --kind <kind> ...` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
|
|
36
|
+
| `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Use `okstra lead-progress append --project-root <dir> --run-manifest <path> --phase <phase-id>` for a checkpoint the command performing that step does not record itself (the lead contract "Progress reporting" lists the ones `team dispatch`, `team await`, `team reclaim`, `worker-dispatch` and `report-finalize` record; emit the `PROGRESS:` lines they print instead) and `okstra agent-activity append --project-root <dir> --run-manifest <path> --kind <kind> ...` for an activity record; both resolve the ledger path from the run manifest. Emit the matching `PROGRESS:` line — the command prints it as `progressLine` — and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
|
|
37
37
|
| `collect_usage` | Collect artifact/CLI-log-backed usage through the existing Okstra token-usage path; never substitute another runtime's session log. |
|
|
38
38
|
|
|
39
39
|
An `implementation` run calls `dispatch_worker` twice: once for the Executor, then — after `await_workers` settles it — once for the verifiers. That second call's `--workers` list must omit the Executor's worker ID: it is materialized as the Executor on every dispatch, so a batch still carrying it is refused again. A verifier started beside the Executor observes base HEAD instead of the stage diff, so a single batch holding both is refused by `scripts/okstra_ctl/dispatch_core.py` `_validate_implementation_phase_order`, `--dry-run` included.
|
|
@@ -61,7 +61,8 @@ Use the screen to tell "still working" from "stuck", and to see at a glance whic
|
|
|
61
61
|
- Worker completion is valid only from `workerDispatches[]`, terminal status sidecars, and required Result Paths. Pane creation alone is not completion.
|
|
62
62
|
- Reverify uses a fresh jobs file at `runs/<task-type>/state/reverify-jobs-r<N>-<task-type>-<seq>.json`, sets `dispatchKind: "reverify-r<N>"`, and dispatches with `okstra team dispatch --project-root <root> --run-manifest <path> --dispatch-kind reverify-r<N> --jobs-file <jobs-file>`.
|
|
63
63
|
- Report-writer uses a fresh one-job jobs file with `dispatchKind: "report-writer"` and the same schema, then dispatches through `okstra team dispatch --project-root <root> --run-manifest <path> --jobs-file <jobs-file>`.
|
|
64
|
-
-
|
|
64
|
+
- Build a batch's jobs file in the call that materializes it: one `materialize --batch <file> --jobs-out <jobs-file>` call for every worker of the batch (convergence "Invocation materialization gate"), or one `materialize … --jobs-out <jobs-file>` call for the report writer, chained with `&& okstra team dispatch … --jobs-file <jobs-file>` in the same shell command. One materialize, verify, or jobs call per worker adds one lead turn over the whole context per worker; `team dispatch` verifies every invocation of the jobs file, so no `agent-prompt verify` call precedes it.
|
|
65
|
+
- For metadata already materialized (a retry), generate v2 jobs files with `okstra agent-prompt jobs --project-root <root> --run-manifest <path> --dispatch-kind <kind> --metadata <prompt-meta.json> [--metadata <prompt-meta.json>] --out <jobs-file>`. Pass only the metadata paths for the core-planned batch. The command derives the `workers` array, canonical role execution, result headers, and five digests, and verifies them through the same consumer used at dispatch. Do not transcribe those fields. Identical output is reused; differing output is preserved and requires a new `--out` path. Existing v1 files remain readable by dispatch.
|
|
65
66
|
- `workerResultPath` is the path the prompt tells the worker to write: the prompt's `**Result Path:**`, or `**Worker Result Path:**` for the report writer. `okstra team dispatch` refuses an entry whose value differs from that anchor, because the collector waits on `workerResultPath` while the worker writes where the anchor says. A reverify result is named `<worker-id>-worker-reverify-r<N>-<task-type>-<seq>.md`: the `-worker-` token is what the audit sidecar name inserts `-audit-` after (a name without it is refused with `worker result path has no canonical -worker- token`), and the round label is what keeps one round's file apart from the next. The report writer's `workerResultPath` is the roster's `resultPath` for `report-writer` and its `**Result Path:**` is the run manifest's `reportNarrativePath` — the report-writer materialization ([report-writer](../report-writer.md)) refuses any other pair. **Enforced:** `_validate_jobs_file_prompt_anchors` in `scripts/okstra_ctl/dispatch_state.py`, `_validate_report_writer_paths` in `scripts/okstra_ctl/agent/prompt_cli/materialize.py`.
|
|
66
67
|
- `role` names the role execution's own role — `verifier` for reverify, `report-writer` for the report writer. It is not a per-round label: `dispatch_state.py` requires the entry's `role` to equal both the role execution's `role` and the duty's role, so a value like `worker-reverify-r<N>` is refused as `jobs file v2 identity does not match role execution authority`. The round lives in `dispatchKind` and in `invocationRef`. The report-writer completion paths include its narrative Markdown, worker-result pointer, and audit sidecar; they do not include the Phase 7 report record.
|
|
67
68
|
- After either dispatch, run `okstra team await --project-root <root> --run-manifest <path>` before evaluating terminal status or completion paths.
|
|
@@ -69,5 +70,5 @@ Use the screen to tell "still working" from "stuck", and to see at a glance whic
|
|
|
69
70
|
## Completion, cleanup, and resume
|
|
70
71
|
|
|
71
72
|
- Await through `okstra team await`; raw Result Path polling is forbidden for this backend.
|
|
72
|
-
- Reclaim terminal panes after each batch through `okstra team reclaim --project-root <root> --run-manifest <path>` before dispatching the next batch. Reserve `teardown` for run completion.
|
|
73
|
+
- Reclaim terminal panes after each batch through `okstra team reclaim --project-root <root> --run-manifest <path>` before dispatching the next batch; it records `phase-batch-cleanup` itself. Reserve `teardown` for run completion.
|
|
73
74
|
- Resume from run artifacts and lead-events checkpoints. After usage collection, persistence, and the core user-approval gate, run `okstra team teardown --project-root <root> --run-manifest <path>` and tear down only Okstra-owned panes recorded for the run.
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
Do not open, parse, or infer Okstra-owned task, run, discovery, or active-context JSON. This contract uses the fixed text views below before the lead contract is loaded, so it cannot bypass that boundary.
|
|
11
11
|
|
|
12
|
-
- `okstra model-io project-context --project-root <project-root> --task-ref <task-ref>` provides project identity and the pointer for one explicit task reference. `task-ref` accepts a bare task ID, full task key, or that task's manifest path.
|
|
12
|
+
- `okstra model-io project-context --project-root <project-root> --task-ref <task-ref>` provides project identity and the pointer for one explicit task reference. `task-ref` accepts a bare task ID, full task key, or that task's manifest path. A bare task ID matches the catalog `taskId` exactly, which is the whole task-id segment (`task-42-fix-login`), not a ticket-number prefix of it and not a `<group>/<task-id>` path.
|
|
13
13
|
- `okstra model-io run-input --run-manifest <run-manifest-path>` provides the current run identity, worker roster, model assignments, and permitted artifact paths.
|
|
14
14
|
|
|
15
15
|
## Step 1: Resolve the Task and Run Paths
|
|
@@ -52,7 +52,7 @@ Configure this in the `convergence` block of `task-manifest.json`. If the block
|
|
|
52
52
|
| `verificationMode` | `"lightweight"` | `"lightweight"` or `"full-reanalysis"` |
|
|
53
53
|
| `adversarial` | phase-aware: `true` for `requirements-discovery` / `error-analysis` / `implementation-option-selection` / `implementation-planning` / `project-analysis` / `feature-analysis` / `change-impact-analysis`, `false` otherwise | When `true`, Phase 5.5 runs in **adversarial mode** (see §"Adversarial Verification Mode"): verifiers actively try to refute each finding, the burden of proof sits on the claim, and `verificationMode` is forced to `"full-reanalysis"` scoped to the finding's cited evidence. Resolved by `scripts/okstra_ctl/render.py` `_build_convergence_block` and recorded in `config.adversarial` of the convergence state artifact. |
|
|
54
54
|
|
|
55
|
-
**Auto-disable rule (BLOCKING).** Convergence requires ≥2 analyser workers to produce a meaningful consensus tally. When the active profile's `Required workers:` block (see `prompts/profiles/*.md`) resolves to fewer than 2 analyser workers — e.g. `release-handoff` (zero analyser workers, lead-only) — the lead MUST treat `convergence.enabled` as `false` for that run regardless of manifest configuration, skip Phases 5.5 and the plan-body verification round (
|
|
55
|
+
**Auto-disable rule (BLOCKING).** Convergence requires ≥2 analyser workers to produce a meaningful consensus tally. When the active profile's `Required workers:` block (see `prompts/profiles/*.md`) resolves to fewer than 2 analyser workers — e.g. `release-handoff` (zero analyser workers, lead-only) — the lead MUST treat `convergence.enabled` as `false` for that run regardless of manifest configuration, skip Phases 5.5 and the plan-body verification round (`plan-body-verification` (the absolute path in **Okstra Runtime Resources**)), and record `finalState: "converged"` with `totalRounds: 0`, `round2SkippedReason: "auto-disabled"`, an empty `roundHistory`, and an explanatory note in `config` (e.g. `"autoDisabled": "fewer-than-two-analysers"`). The plan-body round inherits the same rule via its `gating=false` advisory path.
|
|
56
56
|
|
|
57
57
|
## Finding Category
|
|
58
58
|
|
|
@@ -66,7 +66,7 @@ Configure this in the `convergence` block of `task-manifest.json`. If the block
|
|
|
66
66
|
|
|
67
67
|
## Convergence Algorithm
|
|
68
68
|
|
|
69
|
-
**Majority definition (BLOCKING).** "Majority" means *strictly greater than half* of the non-error votes for that finding (`verification-error` votes are excluded from both numerator and denominator). Ties — including the 1-AGREE / 1-DISAGREE case in a two-analyser roster — are NOT a majority: in intermediate rounds the finding is **carried forward**; in the final executed round the finding is classified `contested`. In adversarial mode a tie whose DISAGREE carries `counter-evidence` does not carry forward — it is classified `contested` in that round (§"Adversarial Verification Mode"). This rule applies identically to the plan-body verification round (
|
|
69
|
+
**Majority definition (BLOCKING).** "Majority" means *strictly greater than half* of the non-error votes for that finding (`verification-error` votes are excluded from both numerator and denominator). Ties — including the 1-AGREE / 1-DISAGREE case in a two-analyser roster — are NOT a majority: in intermediate rounds the finding is **carried forward**; in the final executed round the finding is classified `contested`. In adversarial mode a tie whose DISAGREE carries `counter-evidence` does not carry forward — it is classified `contested` in that round (§"Adversarial Verification Mode"). This rule applies identically to the plan-body verification round (`plan-body-verification` (the absolute path in **Okstra Runtime Resources**)) where the same verdict tokens are reused.
|
|
70
70
|
|
|
71
71
|
**Enforced:** the engine owns the classifier and replays it — `scripts/okstra_ctl/convergence_engine.py` `validate_final_state` recomputes each finding's expected final classification from its recorded votes and rejects the state when the persisted value differs, and `finalize` runs that same check before it writes, so a tie scored as a consensus never reaches the artifact. `okstra convergence validate` is the same call on demand. Nothing re-derives the majority rule outside the engine; a second implementation would only drift from it.
|
|
72
72
|
|
|
@@ -258,6 +258,35 @@ keeps its legacy read-only identity resolution for that schema version. The
|
|
|
258
258
|
returned `promptPath` is the only body that may be dispatched; do not append
|
|
259
259
|
role prose or reconstruct model headers after materialization.
|
|
260
260
|
|
|
261
|
+
Materialize a whole dispatch batch — every row of one round plan, every
|
|
262
|
+
critic-gap verification row of one dispatch kind — in one `okstra agent-prompt
|
|
263
|
+
materialize --project-root <root> --run-manifest <run-manifest> --batch <file>
|
|
264
|
+
--jobs-out <jobs-file>` call, not one call per worker. The batch file holds
|
|
265
|
+
`{"invocations": [...]}`; each entry maps the per-invocation flags above,
|
|
266
|
+
without the leading `--`, to their values (`"invocation-id"`, `"audience"`,
|
|
267
|
+
`"assignment-ref"`, `"source-role-execution-ref"`, `"worker-id"`,
|
|
268
|
+
`"dispatch-kind"`, `"instruction"`, `"prompt"`, `"result"`, and `"replace-undispatched": true` for a legacy v1 correction). A batch refuses those flags at the top level, so a v1 correction re-run through a batch carries `"replace-undispatched": true` in its entry. Each entry is
|
|
269
|
+
materialized exactly as the single call would be and fails with the same error;
|
|
270
|
+
a failure names the entry and every invocation already materialized, and an
|
|
271
|
+
identical rerun after the fix reuses those unchanged. `--jobs-out` then writes
|
|
272
|
+
the verified jobs file as `okstra agent-prompt jobs` would, so for
|
|
273
|
+
`runner=cli-wrapper` rows one shell command covers the batch: render the
|
|
274
|
+
instruction files, create the batch file, run `materialize --batch …
|
|
275
|
+
--jobs-out <jobs-file> && <dispatcher> --project-root <root> --run-manifest
|
|
276
|
+
<run-manifest> --dispatch-kind <kind> --jobs-file <jobs-file>`, where
|
|
277
|
+
`<dispatcher>` is the one the planned execution surface selects below —
|
|
278
|
+
`okstra team dispatch` when `terminalBackend` is `cmux-pane`, otherwise
|
|
279
|
+
`okstra worker-dispatch`. `--jobs-out` needs a v2 run manifest
|
|
280
|
+
(`executionIdentityVersion: 2`) and a path under the run directory; both are
|
|
281
|
+
checked before any entry is materialized, so a legacy v1 run materializes the
|
|
282
|
+
batch without `--jobs-out` and dispatches as it did before. `runner=native-session`
|
|
283
|
+
rows are never chained into a jobs-file dispatcher: materialize them in the
|
|
284
|
+
batch without `--jobs-out`, then `verify`, `record-dispatch` and the host call
|
|
285
|
+
per row as below. Each worker in its own materialize call costs one lead turn
|
|
286
|
+
over the whole context per worker. The batch call is `materialize_batch` in
|
|
287
|
+
`scripts/okstra_ctl/agent/prompt_cli/batch.py`; the pre-materialization check is
|
|
288
|
+
`check_jobs_target` in `scripts/okstra_ctl/agent/prompt_cli/jobs.py`.
|
|
289
|
+
|
|
261
290
|
If the dispatch gate then rejects that prompt, preserve its prompt, metadata,
|
|
262
291
|
reservation, and append-only Invocation bytes. A v2 reverify correction uses a
|
|
263
292
|
fresh `--invocation-id` and fresh prompt/metadata path; the materializer rejects
|
|
@@ -267,8 +296,11 @@ may fix the task-instructions file and re-run the same `materialize` call with
|
|
|
267
296
|
row names the invocation, replacement is rejected even for v1 and the prompt is
|
|
268
297
|
history. Do not delete prompt, metadata, or reservation files by hand.
|
|
269
298
|
|
|
270
|
-
|
|
271
|
-
<
|
|
299
|
+
Before a native-session dispatch, run `okstra agent-prompt verify --project-root
|
|
300
|
+
<dir> --run-manifest <path> --metadata <metadataPath> --text`. A `--jobs-file`
|
|
301
|
+
dispatch needs no separate `verify` call: jobs generation and the dispatcher
|
|
302
|
+
both run the same verification (`validate_dispatch_prompts` in
|
|
303
|
+
`scripts/okstra_ctl/dispatch_state.py`). A failed verification is a
|
|
272
304
|
pre-dispatch contract failure. For `runner=native-session`, pass only the
|
|
273
305
|
returned `hostModelValue` to the host model argument. For
|
|
274
306
|
`runner=cli-wrapper`, follow the planned execution surface after
|
|
@@ -305,15 +337,15 @@ The generated `**Errors log path:**` and `**Errors sidecar path:**` headers use
|
|
|
305
337
|
|
|
306
338
|
An older instruction file may already contain the fixed boundary. Matching values are retained once; conflicting model, task type, or forbidden-actions values are reported with the expected value and a materialization remedy. Do not edit a dispatched prompt. Use a fresh invocation ID and prompt path for a dynamic reverify correction; undispatched initial prompts can be regenerated in place by the existing recovery path.
|
|
307
339
|
|
|
308
|
-
After materialization, generate the batch file from the returned metadata paths:
|
|
309
|
-
|
|
310
340
|
Name the reverify result `<role-slug>-worker-reverify-r<N>-<task-type>-<seq>.md` under the run's authorized worker-results directory. Its generated audit path is checked before dispatch.
|
|
311
341
|
|
|
342
|
+
Materialize the round's workers and generate their jobs file in the one batch call (§"Invocation materialization gate"):
|
|
343
|
+
|
|
312
344
|
```bash
|
|
313
|
-
okstra agent-prompt
|
|
345
|
+
okstra agent-prompt materialize --project-root <root> --run-manifest <manifest> --batch <run-state>/reverify-batch-r<N>.json --jobs-out <run-state>/reverify-jobs-r<N>.json
|
|
314
346
|
```
|
|
315
347
|
|
|
316
|
-
Pass only the current engine-planned batch. The generator reads the actual result headers and canonical role execution, verifies all inputs, then publishes the file. Dispatch the emitted file with the selected adapter's `--jobs-file`; do not copy identity, path, or digest fields by hand. Existing v1 jobs-file consumers remain available.
|
|
348
|
+
`okstra agent-prompt jobs --project-root <root> --run-manifest <manifest> --dispatch-kind reverify-r<N> --metadata <meta.json> --out <jobs-file>` builds the same file from metadata that is already materialized, such as a retry's. Pass only the current engine-planned batch. The generator reads the actual result headers and canonical role execution, verifies all inputs, then publishes the file. Dispatch the emitted file with the selected adapter's `--jobs-file`; do not copy identity, path, or digest fields by hand. Existing v1 jobs-file consumers remain available.
|
|
317
349
|
|
|
318
350
|
### Required reverify output contract (BLOCKING)
|
|
319
351
|
|
|
@@ -603,7 +635,7 @@ Render the critic-only task instructions with `okstra convergence critic-prompt
|
|
|
603
635
|
verbatim — the same pattern as `okstra plan-items prompt` at round 1. Then run
|
|
604
636
|
`okstra agent-prompt
|
|
605
637
|
materialize` with `--audience scope-critic`, `--assignment-ref critic/scope`,
|
|
606
|
-
the
|
|
638
|
+
`--worker-id scope` (the run-input Worker Roster line), and `--dispatch-kind critic`. Verify the returned
|
|
607
639
|
`metadataPath` before dispatch and use its `promptPath` without modification.
|
|
608
640
|
For `runner=native-session`, use only `hostModelValue`; for
|
|
609
641
|
`runner=cli-wrapper`, use `okstra team dispatch` when `terminalBackend` is
|
|
@@ -696,8 +728,8 @@ The `final-verification` phase uses the same fresh one-shot `redispatch_worker`
|
|
|
696
728
|
|
|
697
729
|
Before that call, write the acceptance-only task instructions and run `okstra
|
|
698
730
|
agent-prompt materialize` with `--audience acceptance-critic`,
|
|
699
|
-
`--assignment-ref critic/acceptance`,
|
|
700
|
-
`--dispatch-kind critic`. **The final-verification 96-nonblank-line prompt-body
|
|
731
|
+
`--assignment-ref critic/acceptance`, `--worker-id acceptance` (the run-input
|
|
732
|
+
Worker Roster line), and `--dispatch-kind critic`. **The final-verification 96-nonblank-line prompt-body
|
|
701
733
|
cap applies to this dispatch too** — `resolve_prompt_plan` exempts a critic from
|
|
702
734
|
the analysis equality group, not from the cap. The anchors and the duty contract
|
|
703
735
|
account for roughly 51 of those lines, so the instructions you write have a
|
|
@@ -761,4 +793,4 @@ If `convergence.enabled: false`, this contract is skipped. Phase 6 operates usin
|
|
|
761
793
|
|
|
762
794
|
## Plan-body verification mode (implementation-planning only)
|
|
763
795
|
|
|
764
|
-
Moved to its own contract:
|
|
796
|
+
Moved to its own contract: `plan-body-verification` (the absolute path in **Okstra Runtime Resources**). It fires only for `task-type = implementation-planning`, as a Phase 6 sub-step after the report-writer draft — read that file at that sub-step, NOT during the Phase 5.5 finding convergence this contract governs. The finding queue (`F-*`, this contract) and the plan-item queue (`P-*`, that contract) are disjoint — see its "MUTUAL EXCLUSION" section.
|
|
@@ -23,7 +23,7 @@ This document is the operating contract and phase index. Detailed procedures liv
|
|
|
23
23
|
| [context-loader](./context-loader.md) | Phase 1 task-bundle discovery, manifest fields, run-directory layout |
|
|
24
24
|
| [team-contract](./team-contract.md) | Phase 2–5 worker roster, model assignment rules, prompt composition (anchor headers, `[Required reading]`, `[Error reporting]`), worker output contract, terminal statuses, usage tracking |
|
|
25
25
|
| [convergence](./convergence.md) | Phase 5.5 finding convergence loop, finding categories, reverify dispatch, convergence state schema. Use the bounded common read under Doctrine lazy reads |
|
|
26
|
-
|
|
|
26
|
+
| `plan-body-verification` (the absolute path in **Okstra Runtime Resources**) | Phase 6 plan-body verification sub-step (implementation-planning only) — plan-item extraction, verdict semantics, gate resolution, state schema. Read only the common procedure at that sub-step, using the bounded read below |
|
|
27
27
|
| [report-writer](./report-writer.md) | Phase 6 final-report authorship, dispatch template, resume-safe dispatch, shared-graph integrity check, Phase 7 token-usage collector |
|
|
28
28
|
|
|
29
29
|
Read-side inspection (`/okstra-inspect`) and scheduling (`/okstra-schedule-gen`) are user-invoked skills, not lead support contracts — the lead does not consult them during a run.
|
|
@@ -65,10 +65,10 @@ Every `okstra` command the lead documents cite, grouped by phase, each spelled w
|
|
|
65
65
|
|
|
66
66
|
| Command | Use when | Procedure |
|
|
67
67
|
|---|---|---|
|
|
68
|
-
| `okstra lead-progress append --project-root <dir> --run-manifest <path> --phase <phase-id>` | Every `PROGRESS` checkpoint; print the `progressLine` it returns. `--phase` accepts only the listed phase ids; use `--worker`, `--field NAME=VALUE`, and `--detail <text>` for the rest | this contract "Progress reporting" |
|
|
68
|
+
| `okstra lead-progress append --project-root <dir> --run-manifest <path> --phase <phase-id>` | Every `PROGRESS` checkpoint the command performing that step does not record itself; print the `progressLine` it returns. `--phase` accepts only the listed phase ids; use `--worker`, `--field NAME=VALUE`, and `--detail <text>` for the rest | this contract "Progress reporting" |
|
|
69
69
|
| `okstra agent-activity append --project-root <dir> --run-manifest <path> --kind <kind> --agent <agent> --outcome <outcome> --summary <text>` | Before each activity boundary when the run manifest declares `activityContractVersion: 1` | launch prompt "Progress reporting" |
|
|
70
70
|
| `okstra error-log append-observed --out <errors-path> --task-key <key> --phase <phase> --agent <provider-worker> --agent-role <role> --model <model> --error-type <type> --command-kind <kind> --command <command> --message <text>` | Record an observed failure. `--agent` takes the provider worker id (`codex-worker`); an execution label goes in `--execution-label` | this contract "Errors log path wiring"; `team-contract` "Worker error-log command" |
|
|
71
|
-
| `okstra approval-decision open --ledger <path> --task-key <key> --task-type <type> --run-seq <seq> --clarification-id <C-NNN> --ticket-id <id> --statement <text> --expected-form <form> --classification <class> --origin <origin> --user-confirmation <text> --unblock-condition <text> --recommended-disposition <disposition
|
|
71
|
+
| `okstra approval-decision open --ledger <path> --task-key <key> --task-type <type> --run-seq <seq> --clarification-id <C-NNN> --ticket-id <id> --statement <text> --expected-form <form> --classification <class> --origin <origin> --user-confirmation <text> --unblock-condition <text> --recommended-disposition <disposition> [--supersedes <C-NNN>]` | Open an approval blocker after the user confirmed it | this contract "User confirmation before an approval blocker" |
|
|
72
72
|
| `okstra approval-decision carry --ledger <path> --clarification-id <C-NNN> --from-responses <path>` | Carry a decision answered in an earlier run | `report-writer` "Role-owned inputs" |
|
|
73
73
|
| `okstra approval-decision resolve --ledger <path> --clarification-id <C-NNN> --disposition <disposition> --user-text <text> --user-response-ref <ref>` | Record the user's disposition of an approval row; it touches no verdict | `plan-body-verification` "Round protocol" |
|
|
74
74
|
| `okstra user-response show --report <path>` | Not a lead step: the `okstra-user-response` skill reads approval rows through it, so an `origin` outside the schema enum breaks every later read | `plan-body-verification` "Round protocol" |
|
|
@@ -77,24 +77,25 @@ Every `okstra` command the lead documents cite, grouped by phase, each spelled w
|
|
|
77
77
|
|
|
78
78
|
| Command | Use when | Procedure |
|
|
79
79
|
|---|---|---|
|
|
80
|
-
| `okstra agent-prompt materialize --project-root <dir> --invocation-id <id> --audience <audience> --instruction <path> --prompt <path>` | Materialize
|
|
81
|
-
| `okstra agent-prompt
|
|
80
|
+
| `okstra agent-prompt materialize --project-root <dir> --invocation-id <id> --audience <audience> --instruction <path> --prompt <path>` | Materialize one worker prompt; the command owns the anchor headers and paths. Add `--jobs-out <jobs-file>` in run mode to also write its verified jobs file (report writer) | `convergence` "Invocation materialization gate"; `report-writer` "Report-writer dispatch" |
|
|
81
|
+
| `okstra agent-prompt materialize --project-root <dir> --run-manifest <path> --batch <file> --jobs-out <jobs-file>` | Materialize every worker of one dispatch batch and write its jobs file in one call — one call per batch, never one per worker. For `runner=cli-wrapper` rows chain the dispatcher the execution surface selects in the same shell command: `&& okstra team dispatch … --jobs-file <jobs-file>` on `terminalBackend: cmux-pane`, `&& okstra worker-dispatch … --jobs-file <jobs-file>` otherwise. `--jobs-out` needs a v2 run manifest; `runner=native-session` rows take the batch without `--jobs-out` and keep their per-row `verify` + `record-dispatch` + host call | `convergence` "Invocation materialization gate" |
|
|
82
|
+
| `okstra agent-prompt verify --project-root <dir> --metadata <path>` | Immediately before a native-session dispatch (`record-dispatch`). Not needed before a `--jobs-file` dispatch: jobs generation and the dispatcher verify every invocation | `convergence` "Invocation materialization gate" |
|
|
82
83
|
| `okstra agent-prompt record-dispatch --project-root <dir> --run-manifest <path> --metadata <path> --enforcement-mode <mode>` | Record a native-session dispatch | `convergence` "Invocation materialization gate" |
|
|
83
84
|
| `okstra agent-prompt jobs --project-root <dir> --run-manifest <path> --dispatch-kind <kind> --metadata <path> --out <jobs-file>` | Build a verified jobs file for `okstra team dispatch` | cmux adapter "cmux dispatch details" |
|
|
84
|
-
| `okstra team dispatch --project-root <dir> --run-manifest <path>` | Dispatch pane-backed workers (`terminalBackend` is `cmux-pane`) | cmux adapter "Semantic operation mapping" |
|
|
85
|
-
| `okstra worker-dispatch --project-root <dir> --run-manifest <path>` | Dispatch CLI-backed workers when `terminalBackend` is not `cmux-pane` | this contract "Model assignments" |
|
|
86
|
-
| `okstra codex-dispatch --project-root <dir> --run-manifest <path>` | CLI-backed dispatch for a prepared Codex run; never under the cmux adapter | cmux adapter "cmux dispatch details" |
|
|
85
|
+
| `okstra team dispatch --project-root <dir> --run-manifest <path>` | Dispatch pane-backed workers (`terminalBackend` is `cmux-pane`). Records `phase-3-team-create`, `phase-4-dispatch` and `phase-6-synthesis` as this contract "Progress reporting" describes; emit its `progressLines` | cmux adapter "Semantic operation mapping" |
|
|
86
|
+
| `okstra worker-dispatch --project-root <dir> --run-manifest <path>` | Dispatch CLI-backed workers when `terminalBackend` is not `cmux-pane`. Records `phase-3-team-create`, `phase-4-dispatch`, `phase-5-collect` and `phase-6-synthesis`; emit its `progressLines` | this contract "Model assignments" |
|
|
87
|
+
| `okstra codex-dispatch --project-root <dir> --run-manifest <path>` | CLI-backed dispatch for a prepared Codex run; never under the cmux adapter. Same command as `worker-dispatch`, and records the same checkpoints | cmux adapter "cmux dispatch details" |
|
|
87
88
|
|
|
88
89
|
### Phase 5 — await and collect
|
|
89
90
|
|
|
90
91
|
| Command | Use when | Procedure |
|
|
91
92
|
|---|---|---|
|
|
92
|
-
| `okstra team await --project-root <dir> --run-manifest <path>` | Wait for pane-backed workers | cmux adapter "Semantic operation mapping" |
|
|
93
|
+
| `okstra team await --project-root <dir> --run-manifest <path>` | Wait for pane-backed workers. Records `phase-5-poll` on entry and again when the counts changed, and `phase-5-collect` for each `initial` dispatch it settled; emit the `PROGRESS:` lines it prints | cmux adapter "Semantic operation mapping" |
|
|
93
94
|
| `okstra worker-liveness --team-state <path> --dispatch-id <id>` | Probe a pending worker; add `--wait` to block until result, death, or timeout | `team-contract` "Mid-run liveness probes" |
|
|
94
95
|
| `okstra agent-prompt link-result --project-root <dir> --run-manifest <path> --dispatch-id <id> --result <path>` | Link a returned result to its dispatch | `convergence` "Invocation materialization gate" |
|
|
95
96
|
| `okstra agent-prompt reject-result --project-root <dir> --run-manifest <path> --dispatch-id <id> --superseded-by <id> --reason <text>` | Retire a linked result before a corrective dispatch links its own | `plan-body-verification` "Round protocol" |
|
|
96
97
|
| `okstra worker-audit-check --run-dir <path> --task-type <type> --seq <seq>` | Check a live worker's audit sidecars and citations before accepting its result; add `--worker <id>` | `team-contract` "Lead Redispatch Policy on Result-Missing" |
|
|
97
|
-
| `okstra team reclaim --project-root <dir> --run-manifest <path>` | Close finished dispatches' panes at a batch boundary | this contract "Progress reporting" |
|
|
98
|
+
| `okstra team reclaim --project-root <dir> --run-manifest <path>` | Close finished dispatches' panes at a batch boundary and record `phase-batch-cleanup panes=<n>`; add `--gate` before a user gate, which prints `phase-gate-cleanup` and records nothing | this contract "Progress reporting" |
|
|
98
99
|
|
|
99
100
|
### Phase 5.5 / 5.6 — convergence and critic
|
|
100
101
|
|
|
@@ -138,9 +139,9 @@ Every `okstra` command the lead documents cite, grouped by phase, each spelled w
|
|
|
138
139
|
|
|
139
140
|
| Command | Use when | Procedure |
|
|
140
141
|
|---|---|---|
|
|
141
|
-
| `okstra report-finalize --project-root <dir> --run-manifest <path> --report <path>` | Run the whole Phase 7 sequence; do not run its steps separately | `report-writer` "Phase 6 → Phase 7 execution sequence" |
|
|
142
|
+
| `okstra report-finalize --project-root <dir> --run-manifest <path> --report <path>` | Run the whole Phase 7 sequence; do not run its steps separately. Without `--only` it records `phase-7-persist` first; emit its `progressLines` | `report-writer` "Phase 6 → Phase 7 execution sequence" |
|
|
142
143
|
| `okstra report-translate check-data --run-manifest <path>` | Check an existing translation after a narrative correction | `report-writer` "Phase 6 → Phase 7 execution sequence" |
|
|
143
|
-
| `okstra handoff record-verified --plan-run-root <dir> --stage <N> --report-path <path> --data-json <path>` | Record an accepted final-verification against its stage |
|
|
144
|
+
| `okstra handoff record-verified --plan-run-root <dir> --stage <N> --report-path <path> --data-json <path>` | Record an accepted final-verification against its stage. `report-finalize` runs it in its `record-verified` step; run it by hand only to repair a registry after that step failed | `report-writer` "Phase 6 → Phase 7 execution sequence" |
|
|
144
145
|
| `okstra team teardown --project-root <dir> --run-manifest <path>` | Close every recorded pane at the end of the run | cmux adapter "Semantic operation mapping" |
|
|
145
146
|
|
|
146
147
|
**Names that do not exist.** Lead sessions have called these; each fails with `unknown command`. Use the command on the right.
|
|
@@ -205,7 +206,7 @@ User-utterance interpretation rule:
|
|
|
205
206
|
- If the current phase's outputs are already complete and the user clearly wants to advance, reply with the phase-transition checklist above and the exact next-run command. Wait for explicit user confirmation before any action that belongs to the next phase.
|
|
206
207
|
- If the Next-Phase Pointer target (`nextRecommendedPhase.phase`) is `implementation-planning`, the next run produces a **plan**, not code. The next run after that is `implementation`.
|
|
207
208
|
|
|
208
|
-
**Enforced:** the Forbidden actions column is declared in `
|
|
209
|
+
**Enforced:** the Forbidden actions column is declared in each phase module’s `boundary.json` (`scripts/okstra_ctl/phases/<phase>/boundary.json`) and scanned post-hoc by `validators/forbidden_actions.py` `scan_forbidden_actions`, which matches this run's task type through `forbidden_patterns_for` against the commands the run actually executed.
|
|
209
210
|
|
|
210
211
|
## Progress reporting (BLOCKING)
|
|
211
212
|
|
|
@@ -219,12 +220,22 @@ A single okstra run frequently spans 30–120 minutes with multi-minute silent w
|
|
|
219
220
|
|
|
220
221
|
Record each checkpoint with `okstra lead-progress append --project-root <dir> --run-manifest <path> --phase <phase-id>`, then emit the `progressLine` it prints as the user-facing line. The command resolves `leadEventsPath` from the run manifest and writes the checkpoint there — on a host whose adapter declares `sessionAccounting: artifact-only` that ledger is the only place the post-hoc validator can read it, so a conversation line alone leaves no trace and the run is reported as missing the checkpoint. Pass `--worker <role>` on the per-worker checkpoints (it rewrites a phase-specific functional label into the roster role team-state records), `--field NAME=VALUE` for the remaining `key=value` tokens in the order the line carries them, and `--detail <text>` where the line ends in a verb phrase; the wording listed below is the default for the fixed-prose checkpoints.
|
|
221
222
|
|
|
223
|
+
Some checkpoints are recorded by the command that performs the step, because that command holds the fact the line states:
|
|
224
|
+
|
|
225
|
+
- `okstra team dispatch` (on a `terminalBackend: cmux-pane` run) and `okstra worker-dispatch` / `okstra codex-dispatch` record `phase-3-team-create using implicit team` when the dispatch is the one that writes the implicit-team marker into team-state (no `teamCreate` recorded yet), `phase-4-dispatch` for each `initial` job, and `phase-6-synthesis` on the run's first report-writer dispatch.
|
|
226
|
+
- On a `cmux-pane` run `okstra team await` records `phase-5-poll` on entry and again when the counts changed; `okstra team await` there and `okstra worker-dispatch` record `phase-5-collect worker=<role> status=<terminal-status>` for each `initial` dispatch they settled — the settlement is the result verification: the required artifact exists, the mutation audit passed and the result is linked to its dispatch, or the attempt closed as `error` / `timeout`. A retried attempt counts once its retry settles.
|
|
227
|
+
- On a `cmux-pane` run `okstra team reclaim` records `phase-batch-cleanup`.
|
|
228
|
+
- The team commands record nothing on any other `terminalBackend`: a run that dispatches with `okstra team dispatch` and waits with `okstra team await` there appends the team commands' checkpoints itself. `okstra worker-dispatch` still records its own, as listed above.
|
|
229
|
+
- `okstra report-finalize` without `--only` records `phase-7-persist` before its first step, so `validate-run` reads it.
|
|
230
|
+
|
|
231
|
+
Emit the `PROGRESS:` lines those commands print (the trailing text lines of `team await` and `team reclaim`, or `progressLines` in the JSON the others print) verbatim, and do not call `lead-progress append` for them — each extra call is one more lead turn over the whole context. Everything else still goes through `lead-progress append`: every other checkpoint; `phase-3-team-create` when the lead itself recorded the marker (the concurrent-run `skipped (concurrent-run)` variant); and `phase-4-dispatch`, `phase-5-collect` and `phase-6-synthesis` for a worker dispatched through a host-native primitive (`record-dispatch` / `link-result`). `phase-5-collect` from a command does not replace the lead's own acceptance check (`okstra worker-audit-check`), and on an activity-contract-v1 run each `worker-dispatched` / `worker-completed` activity is still the lead's to append. **Enforced:** `scripts/okstra_ctl/dispatch_checkpoints.py`, `record_checkpoint` in `scripts/okstra_ctl/lead_progress.py`, `tests/run/test_team_cmux_backend.py`, `tests/run/test_okstra_ctl_dispatcher.py`, `tests/report/test_report_finalize.py`.
|
|
232
|
+
|
|
222
233
|
For an `implementation-planning` run whose run manifest declares `activityContractVersion: 1`, record every required activity boundary with `okstra agent-activity append` against the manifest-provided `leadEventsPath`. Model-facing calls pass prose through `--summary-file <md>` and a command through `--command`, `--command-cwd`, `--command-exit-code`, and `--command-output-file <md>`; do not construct `--command-record` JSON. The ordering is fixed: the structured append succeeds first, the matching `PROGRESS:` line is emitted second, and the immediately following `ACTIVITY:` line projects the same structured fields into the conversation language. Do not reconstruct structured activity from conversation text. If the append fails, do not present that activity boundary as completed.
|
|
223
234
|
|
|
224
235
|
The live projection follows this shape:
|
|
225
236
|
|
|
226
237
|
```text
|
|
227
|
-
PROGRESS: phase-4-dispatch worker=codex-worker model=gpt-6-sol
|
|
238
|
+
PROGRESS: phase-4-dispatch worker=codex-worker model=gpt-6.1-sol
|
|
228
239
|
ACTIVITY: id=A-001 agent=codex-worker summary="Verify Stage Map paths and commands" items=P-Step-001,P-Step-002 result=runs/.../codex-worker-....md outcome=pending
|
|
229
240
|
```
|
|
230
241
|
|
|
@@ -237,19 +248,19 @@ Required checkpoints:
|
|
|
237
248
|
- `PROGRESS: phase-1-intake reading task bundle` — at the start of Phase 1, before issuing parallel Read calls.
|
|
238
249
|
- `PROGRESS: phase-1-intake complete` — after all intake reads return.
|
|
239
250
|
- `PROGRESS: phase-2-prompts preparing <N> worker prompts` — at the start of Phase 2, before any `Write` to the assigned prompt paths.
|
|
240
|
-
- `PROGRESS: phase-3-team-create <adapter-specific-status>` — after selected-adapter setup is recorded in team-state. The stable phase id is retained for artifact compatibility.
|
|
251
|
+
- `PROGRESS: phase-3-team-create <adapter-specific-status>` — after selected-adapter setup is recorded in team-state. The stable phase id is retained for artifact compatibility. When the first dispatch writes the implicit-team marker, that dispatch command records the line.
|
|
241
252
|
- `PROGRESS: phase-4-dispatch worker=<role> model=<model>` — once per worker, immediately before `dispatch_worker`. `<role>` is the **roster** role, exactly as team-state's `workers[].role` records it (`Claude worker`, `Codex worker`) — the checkpoint is matched against that entry, so a phase-specific functional label (`Claude verifier`, `Codex executor`) names no roster worker and fails the check. Only `claude-worker`-style hyphenation of the same roster role is also accepted.
|
|
242
253
|
- `PROGRESS: phase-5-poll pending=<n> done=<m>` — emitted when entering the wait and when the pending attempts or terminal outcomes change. A host wait returning without a worker state change does not create a new checkpoint.
|
|
243
|
-
- `PROGRESS: phase-5-collect worker=<role> status=<terminal-status>` — once per worker, immediately after the result file is verified. `<role>` is the roster role, same rule as `phase-4-dispatch` above.
|
|
254
|
+
- `PROGRESS: phase-5-collect worker=<role> status=<terminal-status>` — once per worker, immediately after the result file is verified. `<role>` is the roster role, same rule as `phase-4-dispatch` above. `team await` (cmux-pane run only) and `worker-dispatch` record it for the dispatches they settle.
|
|
244
255
|
- `PROGRESS: phase-5-stage stage=<N> title=<title> steps=<count>` — `implementation` only, immediately before the Executor's `phase-4-dispatch` line, after parsing the approved plan's Stage Map and this run's `**Stage for this implementation run:**` anchor. `<title>` is the stage's Stage Map title and `<count>` is its `stepwiseExecution` row count, both read from the approved plan — this is the line that tells the user WHICH plan stage this run executes. The numbering keeps the line sorted where the work happens — the stage runs in Phase 5.
|
|
245
256
|
- `PROGRESS: phase-5-stage-complete stage=<N> steps=<done>/<count>` — `implementation` only, immediately after the Executor result is verified and its `### Stage Carry Evidence` block is parsed, before the verifier dispatch. `<done>` counts the block's `stepResults[]` rows whose `status` is `done` — read from the emitted block, never recomputed from git. Omitted when the Executor ends without carry evidence (`FAIL` or a non-result); the user then learns the outcome from `phase-5-collect status=<terminal-status>`.
|
|
246
257
|
- `PROGRESS: phase-5.5-convergence round=<N> queue=<count>` — at the start of each convergence round (Phase 5.5).
|
|
247
258
|
- `PROGRESS: phase-5.6-critic provider=<provider> gaps=<n>` — after the critic result is collected (Phase 5.6, opt-in; the critic dispatch itself fires concurrently with the first 5.5 reverify round). Omitted when `convergence.critic.enabled == false`.
|
|
248
|
-
- `PROGRESS: phase-batch-cleanup panes=<n>` — immediately after cleaning up the previous batch's panes, at each batch boundary (① just before the first `phase-5.5-convergence` round ② just before the `phase-6-synthesis` report-writer dispatch). `<n>` is the number of panes closed at that boundary — the panes of dispatches this run recorded and that have since finished —
|
|
249
|
-
- `PROGRESS: phase-6-synthesis dispatching report-writer-worker` — at the start of Phase 6.
|
|
250
|
-
- `PROGRESS: phase-5.5.9-plan-verify round=<N> items=<count>` — immediately before dispatching each plan-body verification round (`implementation-planning` only; see
|
|
259
|
+
- `PROGRESS: phase-batch-cleanup panes=<n>` — immediately after cleaning up the previous batch's panes, at each batch boundary (① just before the first `phase-5.5-convergence` round ② just before the `phase-6-synthesis` report-writer dispatch). `<n>` is the number of panes closed at that boundary — the panes of dispatches this run recorded and that have since finished — counted by `okstra team reclaim --project-root <dir> --run-manifest <path>` as the panes that pass closed, never estimated; no `--dry-run` pass is needed to learn it. A pane the harness opened for its own teammate carries no recorded id, so it is not counted and not closed. Expose only the counts and NEVER expose a raw `paneId` or worker handle. Just before the first batch (analysis-worker dispatch) there is nothing to clean up, so it is a no-op and the marker is omitted.
|
|
260
|
+
- `PROGRESS: phase-6-synthesis dispatching report-writer-worker` — at the start of Phase 6. `team dispatch` (cmux-pane run only) and `worker-dispatch` record it on the first report-writer dispatch; on any other backend a `team dispatch` run appends it with `lead-progress append`.
|
|
261
|
+
- `PROGRESS: phase-5.5.9-plan-verify round=<N> items=<count>` — immediately before dispatching each plan-body verification round (`implementation-planning` only; see `plan-body-verification` (the absolute path in **Okstra Runtime Resources**) §"Round protocol"). Each round is a worker batch like any other, so round 2 and later MUST be preceded by a `phase-batch-cleanup` line reclaiming the previous round's verifiers. The numbering keeps this line sorted where the work happens — after Phase 6, because the round verifies the drafted plan body.
|
|
251
262
|
- `PROGRESS: user-confirm <C-NNN> <the question, one line>` — immediately before asking the user about anything that would otherwise become an open `Blocks=approval` row (see "User confirmation before an approval blocker" below). Not tied to a phase: it fires wherever the blocker surfaces. `<C-NNN>` is the id the row will carry, so the answer and the row can be matched afterwards.
|
|
252
|
-
- `PROGRESS: phase-7-persist updating manifests` — at the start of Phase 7.
|
|
263
|
+
- `PROGRESS: phase-7-persist updating manifests` — at the start of Phase 7. `okstra report-finalize` records it.
|
|
253
264
|
- `PROGRESS: phase-7-teardown shutting-down-workers` — only after usage collection and user approval, immediately before `shutdown_workers`; omitted when no cleanup resource exists or the user keeps it.
|
|
254
265
|
- `PROGRESS: complete final-report=<relative-path>` — final summary line, after all persistence.
|
|
255
266
|
|
|
@@ -291,7 +302,7 @@ The sequence is fixed:
|
|
|
291
302
|
4. On an answer — record the raw text in the row's `userInput`, set `status: answered` and `userConfirmation: asked-and-answered`, and apply the selected disposition in this run.
|
|
292
303
|
5. Only when asking fails does the row stay open: `asked-awaiting` when the user has not answered, `deferred-no-interactive-session` when this run has no user to ask.
|
|
293
304
|
|
|
294
|
-
For report contract v3 `implementation-planning`, record active approval decisions only through `okstra approval-decision`; report assembly derives each report row's status, resolution, and backtraces from that lead-owned ledger plus the activity ledger. Classify a user-owned selection as `user-decision`, a surviving non-correctness majority disagreement as `noncritical-dissent`, and a cited path/symbol mismatch, `P-Req-*` coverage mismatch, or independent Requirement Coverage blocker as `correctness-critical`. `select` is limited to `user-decision`. `accept-risk` is available to all three classifications: it ends the gate, keeps the DISAGREE votes and the clarification row as evidence, and later stages read that record. `request-revision` / `reject` are available to all three and still withhold the next phase. Contract v2 remains read-only compatible; do not create a new v2 report. **Enforced:** `scripts/okstra_ctl/approval_decisions.py` rejects an invalid option/disposition combination at the moment the decision is opened or resolved, so a classification that does not admit the disposition never reaches the ledger. The backtraces are not re-derived afterwards — they are produced by assembly (next paragraph), which is why the lead has no hand-written path to them. `
|
|
305
|
+
For report contract v3 `implementation-planning`, record active approval decisions only through `okstra approval-decision`; report assembly derives each report row's status, resolution, and backtraces from that lead-owned ledger plus the activity ledger. Classify a user-owned selection as `user-decision`, a surviving non-correctness majority disagreement as `noncritical-dissent`, and a cited path/symbol mismatch, `P-Req-*` coverage mismatch, or independent Requirement Coverage blocker as `correctness-critical`. `select` is limited to `user-decision`. `accept-risk` is available to all three classifications: it ends the gate, keeps the DISAGREE votes and the clarification row as evidence, and later stages read that record. `request-revision` / `reject` are available to all three and still withhold the next phase. Contract v2 remains read-only compatible; do not create a new v2 report. **Enforced:** `scripts/okstra_ctl/approval_decisions.py` rejects an invalid option/disposition combination at the moment the decision is opened or resolved, so a classification that does not admit the disposition never reaches the ledger. The backtraces are not re-derived afterwards — they are produced by assembly (next paragraph), which is why the lead has no hand-written path to them. `scripts/okstra_ctl/phases/implementation_planning/plan_body.py` `_validate_v3_approval_context` checks the one claim assembly cannot see: an `approved` frontmatter published against a row that still blocks progress.
|
|
295
306
|
|
|
296
307
|
The approval state transitions are fixed:
|
|
297
308
|
|
|
@@ -301,7 +312,7 @@ The approval state transitions are fixed:
|
|
|
301
312
|
|
|
302
313
|
Do not move `answered` back to `open` because a check failed. The user's choice stands. Record the failed check on the row; later stages still see the DISAGREE votes.
|
|
303
314
|
|
|
304
|
-
`open` blocks until the user judges. `answered` with `select` / `accept-risk` / `answer`, `resolved`, and `obsolete` do not block approval or the next phase. `request-revision` and `reject` still withhold the next phase until this report's `supersessionLedger` records that the answer was incorporated (`superseded` or `no-dependent-statement`). `accept-risk` does not require re-verification `AGREE`. The worker votes stay on the plan item so a later stage can still see the dissent. **Enforced:** `scripts/okstra_ctl/clarification_items.py` `row_blocks_progress`, `
|
|
315
|
+
`open` blocks until the user judges. `answered` with `select` / `accept-risk` / `answer`, `resolved`, and `obsolete` do not block approval or the next phase. `request-revision` and `reject` still withhold the next phase until this report's `supersessionLedger` records that the answer was incorporated (`superseded` or `no-dependent-statement`). `accept-risk` does not require re-verification `AGREE`. The worker votes stay on the plan item so a later stage can still see the dissent. **Enforced:** `scripts/okstra_ctl/clarification_items.py` `row_blocks_progress`, `scripts/okstra_ctl/phases/implementation_planning/plan_body.py` `_user_accepted_plan_item_ids`.
|
|
305
316
|
|
|
306
317
|
When a terminal row preserves a pre-correction dissent classification, keep superseded votes in `state/plan-body-verification-implementation-planning-<seq>.json`. Activities that implement or check the decision record the exact `C-NNN` in `clarificationRefs` and the affected `P-*` identifiers in `planItemIds`. Report assembly verifies that every resolution `checkRefs` value names an existing activity and derives each plan item's `clarificationRefs`; the lead never copies those references into `approvalContext`. A corrected coverage-only blocker keeps its `C-NNN` in the non-blocking Requirement Coverage row's `decisionRefs`. An `obsolete` row is invalid while its disagreement or coverage blocker remains active in the current plan. **Enforced at assembly, not after it:** `scripts/okstra_ctl/report_assembly.py` `_clarification_row` refuses a resolution whose `checkRefs` is empty, names an activity that does not exist, or names one whose `clarificationRefs` omits this `C-NNN`; `_attach_plan_backlinks` derives every plan item's `clarificationRefs` from the activity ledger, so a hand-copied reference has nowhere to enter. Nothing recomputes these links afterwards — assembly failing is the whole check.
|
|
307
318
|
|
|
@@ -326,7 +337,7 @@ The table below documents those prep-time seed values **for reference only** —
|
|
|
326
337
|
| Lead role | opus | -- | runtime-specific role label; orchestration + convergence supervision + final-report review/approval |
|
|
327
338
|
| Report writer worker | sonnet | report-writer-worker | common + role + duty contracts composed per invocation; `native-session` execution |
|
|
328
339
|
| Claude worker | opus | claude-worker | common + role + duty contracts composed per invocation; `native-session` execution |
|
|
329
|
-
| Codex worker | gpt-6-sol | codex-worker | duty + task instructions composed per invocation; deterministic `worker-dispatch` execution |
|
|
340
|
+
| Codex worker | gpt-6.1-sol | codex-worker | duty + task instructions composed per invocation; deterministic `worker-dispatch` execution |
|
|
330
341
|
| Antigravity worker | gemini-3.1-pro | antigravity-worker | duty + task instructions composed per invocation; deterministic `worker-dispatch` execution |
|
|
331
342
|
|
|
332
343
|
Each analysis assignment follows its recorded `runner`. `runner=native-session` uses the host's native subagent primitive after `host-native-spec-link-gate`. `runner=cli-wrapper` follows the planned execution surface after `core-pre-dispatch` verification: `okstra team dispatch` when `terminalBackend` is `cmux-pane`, otherwise the deterministic `okstra worker-dispatch` process boundary. No LLM transport wrapper sits in front of a provider CLI.
|
|
@@ -378,7 +389,9 @@ After context-loader completes, read **only the compact intake files below** in
|
|
|
378
389
|
**Doctrine lazy reads (BLOCKING — read at the round, not at Phase 1):**
|
|
379
390
|
|
|
380
391
|
- [convergence](./convergence.md) — read the common procedure with the bounded command below before the first `PROGRESS: phase-5.5-convergence` line of any run that runs a convergence round.
|
|
381
|
-
-
|
|
392
|
+
- `plan-body-verification` (the absolute path in **Okstra Runtime Resources**) — read the common procedure with the bounded command in the Phase 6 sub-step before the first `PROGRESS: phase-5.5.9-plan-verify` line.
|
|
393
|
+
|
|
394
|
+
For a run frozen before the phase-package migration, a missing `prompts/lead/plan-body-verification.md` pointer resolves within the asset root containing this lead contract. Identify its unique `okstra_ctl` package at `scripts/okstra_ctl`, `python/okstra_ctl`, or `lib/python/okstra_ctl` by `__init__.py`, then read `phases/implementation_planning/instructions/plan-body-verification.md` inside that package at the original Phase 6 sub-step. Preserve the bounded read and the `phase-5.5.9-plan-verify` checkpoint order below. If the package is ambiguous or the resource is missing, stop and report it; do not search another installation or rewrite frozen profiles, manifests, prompts or run context. The mapping is checked by `scripts/okstra_ctl/phases/implementation_planning/tests/test_instruction_assets.py`; the existing entry guard checks read timing by the unchanged basename.
|
|
382
395
|
|
|
383
396
|
Both stay out of the Phase 1 baseline for the token reason above, and neither is optional at its round: together they carry more than half of this contract family's MUST clauses, so a round dispatched without the read is a round run from memory. **Enforced:** `validators/validate_session_conformance.py` `_ENTRY_GUARD_READS` requires each read — a `Read` call or a shell command naming the file — inside this run's window and before that checkpoint. The requirement is conditioned on the checkpoint actually appearing, so a run that holds no such round is never asked for it.
|
|
384
397
|
|
|
@@ -406,7 +419,9 @@ checks the emitted common procedure. The same entry-guard read trace applies.
|
|
|
406
419
|
|
|
407
420
|
**Implementation profile lazy reading discipline (BLOCKING — applies only when `task_type == "implementation"`):**
|
|
408
421
|
|
|
409
|
-
The `implementation` profile's thin core (`
|
|
422
|
+
The `implementation` profile's thin core (`scripts/okstra_ctl/phases/implementation/profile.md`) is intentionally minimal so the Phase 1 baseline stays small. Three sidecar files carry the bulk of the rules and MUST be read at the listed phase — do NOT pre-load them at Phase 1. The sidecar list and each one's `Read at` phase live in that profile's "Lazy section pointers" table, which arrives in the Phase 1 intake via `analysis-profile.md`, so it is already in context whenever this discipline applies.
|
|
423
|
+
|
|
424
|
+
For a run frozen before the phase-package migration, resolve a missing `prompts/profiles/_implementation-*.md` pointer within the asset root containing this lead contract. That root has one `okstra_ctl` package at `scripts/okstra_ctl`, `python/okstra_ctl`, or `lib/python/okstra_ctl`, identified by its `__init__.py`. Read `phases/implementation/instructions/<same-basename>` inside that package at the original `Read at` phase. If no unique package or requested file exists, stop and report the missing resource. Keep the frozen `analysis-profile.md` unchanged and do not search another installation. New runs carry resolved instruction paths. The path mapping is checked by `scripts/okstra_ctl/phases/implementation/tests/test_assets.py`; the entry guard below checks the recorded read timing.
|
|
410
425
|
|
|
411
426
|
**Entry guard (BLOCKING).** Before transitioning into Phase 5 or Phase 6 for an `implementation` run, lead MUST load the sidecar(s) whose `Read at` (per that table) matches the entering phase — either a single `Read` tool call, or a shell command naming that file (`cat`, `sed -n`), since some hosts steer file reads to the shell. If lead enters the phase without that load recorded in the selected adapter's conformance evidence/event source, phase entry is refused — lead writes a `contract-violation` to the run-level errors log with `--message "implementation-sidecar-not-loaded"` and stops. Re-entry requires the sidecar Read first. **Enforcement:** the Phase 7 validator (`validate_session_conformance.py`) verifies post-hoc that all three sidecar loads exist in the selected adapter's declared source within this run's window, and that they precede the `phase-6-synthesis` / `phase-7-persist` checkpoints respectively.
|
|
412
427
|
|
|
@@ -446,7 +461,7 @@ For `improvement-discovery`, Lead records `## Primary Pass Assignments` in the P
|
|
|
446
461
|
2. Verify the run manifest's `leadRuntime`, `leadAdapter`, dispatch backend, concurrency metadata, and artifact paths.
|
|
447
462
|
3. Execute the adapter's pre-dispatch setup without substituting another adapter's primitive.
|
|
448
463
|
4. Persist the setup outcome in team-state using the existing fields required by that backend.
|
|
449
|
-
5. Emit the canonical `PROGRESS: phase-3-team-create <adapter-specific-status>` checkpoint. The phase id remains stable for artifact compatibility; only the adapter-owned verb phrase varies.
|
|
464
|
+
5. Emit the canonical `PROGRESS: phase-3-team-create <adapter-specific-status>` checkpoint. The phase id remains stable for artifact compatibility; only the adapter-owned verb phrase varies. When the implicit-team marker is written by the first `team dispatch` / `worker-dispatch`, that command records the line and prints it; emit it from there.
|
|
450
465
|
|
|
451
466
|
**Enforced:** `validators/validate_session_conformance.py` `_check_progress_checkpoints` requires the `phase-3-team-create` checkpoint once any worker was dispatched, and `validate-run.py` `validate_team_state` reads the setup outcome this phase persists.
|
|
452
467
|
|
|
@@ -552,54 +567,9 @@ All categories must appear in the final synthesis. Do not omit contested or work
|
|
|
552
567
|
|
|
553
568
|
If only one worker result is usable: reduced-confidence synthesis. If evidence is missing: say `I don't know`. If no meaningful worker differences: say so explicitly.
|
|
554
569
|
|
|
555
|
-
### Phase 6 sub-step: Plan-body verification (implementation-planning only
|
|
556
|
-
|
|
557
|
-
After the Report writer worker narrative is reviewed, **if** `task_type == "implementation-planning"` **and** `task-manifest.json` `convergence.planBodyVerification.enabled == true` (default), the lead MUST run the plan-body verification sequence on the consolidated plan body before declaring Phase 6 complete and entering Phase 7.
|
|
558
|
-
|
|
559
|
-
This is a Phase 6 sub-step — it does NOT introduce a new top-level lifecycle phase; the lead operating-phase model (Phase 1 Intake → Phase 7 Persist, labels in the "Quick Reference" table above as the single source of truth) is preserved. The round's outcome is read from the final report's `### 5.5.9 Plan Body Verification` section and `implementationPlanning.planBodyVerification` in its data.json — it is not a separate lifecycle phase identifier.
|
|
560
|
-
|
|
561
|
-
**REQUIRED RESOURCE:** Read the common procedure of [plan-body-verification](./plan-body-verification.md) for the round protocol, plan-item ID scheme (`P-Dir-1` for selected-direction; `P-Opt-*` for legacy candidate comparison; then `P-Step-*` / `P-Dep-*` / `P-Val-*` / `P-Rb-*` / `P-Req-*` / `P-Prep-*`), verdict semantics (`AGREE` / `DISAGREE(a-f)` / `SUPPLEMENT`), classification rules, gate-result resolution, and state-path authority. Read the state-file schema only when diagnosing state or projection validation. For `P-Dir-1`, compare `directionRealization` with `selectedDirectionRef` and its snapshot: verify the core mechanism, architecture boundaries, planning invariants, and any hidden direction change.
|
|
562
|
-
|
|
563
|
-
Read from the resolved runtime resource path, replacing `<plan-body-contract-path>`
|
|
564
|
-
with that resource's absolute path. This prints the complete common procedure and
|
|
565
|
-
its conditional reading table, stopping before reference examples:
|
|
566
|
-
|
|
567
|
-
```sh
|
|
568
|
-
awk '/^## Reference material$/ {exit} {print}' '<plan-body-contract-path>'
|
|
569
|
-
```
|
|
570
|
-
|
|
571
|
-
Follow the conditional reading table for later rounds and validation failures.
|
|
572
|
-
The command keeps the filename in the read trace used by
|
|
573
|
-
`validators/validate_session_conformance.py` `_ENTRY_GUARD_READS`.
|
|
574
|
-
The bounded output is checked by
|
|
575
|
-
`tests/contract/test_contract_examples_execute.py::test_plan_body_common_read_keeps_gate_rules`.
|
|
576
|
-
|
|
577
|
-
Distinct from Phase 5.5 finding convergence:
|
|
578
|
-
|
|
579
|
-
- Phase 5.5 reconciles worker **findings** (F-*) from independent analysis.
|
|
580
|
-
- This sub-step reconciles the **consolidated plan body** (P-*) authored by the Report writer worker.
|
|
581
|
-
- The two rounds use disjoint queues and separate state files — see [plan-body-verification](./plan-body-verification.md) "MUTUAL EXCLUSION (BLOCKING)".
|
|
582
|
-
|
|
583
|
-
Lead's responsibilities in this sub-step (in order):
|
|
584
|
-
|
|
585
|
-
For a new `implementation-planning` run, the fixed order is initial verification → one planner self-fix → targeted re-verification → lead decision or immediate user confirmation. The initial verification is round 1 and the targeted re-verification is round 2. A second automatic self-fix is a contract violation. When `okstra plan-items prepare` reports `"gating": false` (one-stage `no-design-inputs` plan), skip the self-fix loop and the sweep batch: extraction and round 1 still run, then go to the user gate. Two-or-more stages, a PREP item, or non-empty `designPreparation.items` keep `gating: true` and the full order.
|
|
586
|
-
|
|
587
|
-
1. Build the queue with `okstra plan-items prepare --narrative <report-writer-narrative.md> --run-manifest <run-manifest>`, place the output of `okstra plan-items prompt --run-manifest <run-manifest>` verbatim in every verifier prompt, then run `okstra plan-items validate-prepared --narrative <report-writer-narrative.md> --run-manifest <run-manifest>`. Python resolves the one convergence-owned state path from that run identity. The lead MUST NOT summarise, select, omit, reorder, or renumber the queue. Each prompt uses the compact subject plus the lossless payload, and asks every item:
|
|
588
|
-
|
|
589
|
-
```text
|
|
590
|
-
What concrete false-positive input, failure ordering, or omitted dependency
|
|
591
|
-
would make this plan item incorrect even if its happy path succeeds?
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
An `AGREE` response records the considered counterexample and exclusion reason in its note; unverified external material is `verification-error`, not `DISAGREE`.
|
|
595
|
-
2. Dispatch a single plan-body reverify round to every analyser worker in the roster (`claude`, `codex`, and `antigravity` when opted in). `Report writer worker` is NOT a participant in this round.
|
|
596
|
-
3. Record each verifier Markdown result through `okstra plan-items apply-verdicts --state <plan-body-verification.json> --result <worker-id>=<result.md> --round <N>`. Python validates every submitted `P-*` identifier against the current convergence state and overwrites only that round's verdicts. Then resolve the gate result to one of `passed` / `passed-with-dissent` / `blocked-by-disagreement` / `aborted-non-result`.
|
|
597
|
-
4. After `okstra plan-verify` succeeds, run `okstra plan-items complete-round --state <plan-body-verification.json> --run-manifest <current-run-manifest.json> --round <N>`. Python reads the current worker assignments, atomically appends the convergence-owned history, and updates its nested final projection. This state is the only plan-verification input report assembly reads.
|
|
598
|
-
5. Record every *in-scope execution* `majority-disagree` decision through `okstra approval-decision`; record its plan and clarification links only on activities. Do not promote `observed` / `deferred` / `record` items, and do not append `clarificationItems[]` directly.
|
|
599
|
-
6. Run report assembly after the final plan-body state, approval ledger, design snapshot, activity ledger, and team state are complete. Assembly writes `implementationPlanning.planBodyVerification` and derived clarification rows while publishing `data.json` once.
|
|
600
|
-
7. Publish the report record `frontmatter.approved` field as `false`. There is no in-body `- [ ] Approved` marker line — approval lives only in the record (see [plan-body-verification](./plan-body-verification.md) §"Round protocol" step 9). The user may set it to `true` (via `--approve` or the in-session wizard) when the gate is `passed` / `passed-with-dissent`, or under `blocked-by-disagreement` once every remaining `Blocks=approval` row is user-proceeded (`accept-risk` / `select` / `answer`); `aborted-non-result` still withholds approval. **Enforced:** run-prep (`scripts/okstra_ctl/run.py` `_validate_approved_plan` / `_blocking_gate_survives_user_decision`) fail-closes an `approved: true` plan whose blocking gate carries no user disposition, and `validators/validate-run.py` `_validate_plan_body_gate_recompute` fails a gate value upgraded past what the recorded votes support. Manually flipping a blocked gate to passing is a contract violation.
|
|
570
|
+
### Phase 6 sub-step: Plan-body verification (implementation-planning only)
|
|
601
571
|
|
|
602
|
-
|
|
572
|
+
For `implementation-planning`, follow the Phase 6 plan-body verification sub-step in the selected phase profile before entering Phase 7. The phase profile owns the enablement gate, round protocol, and approval publication rules.
|
|
603
573
|
|
|
604
574
|
## Phase 7: Artifact persistence and validator handoff
|
|
605
575
|
|
|
@@ -674,6 +644,7 @@ The run-level error log lives at `<runDir>/logs/errors-<task-type>-<seq>.jsonl`.
|
|
|
674
644
|
| Injecting `[Required reading]` into lightweight reverify prompts | Lightweight reverify forbids re-reading source materials — see [convergence](./convergence.md) "Reverify prompt: required-reading suppression" |
|
|
675
645
|
| Letting `convergence.maxRounds` default to 2 for `requirements-discovery` | Resolve effective default to `1` for discovery and put it in the grouped input |
|
|
676
646
|
| Issuing serial Read calls in Phase 1 | The intake files are independent — issue all Read calls in a single message (parallel) |
|
|
647
|
+
| Running `agent-prompt materialize`, `jobs`, or a jobs-file dispatcher once per `runner=cli-wrapper` worker of a batch | One `okstra agent-prompt materialize --project-root <dir> --run-manifest <path> --batch <file> --jobs-out <jobs-file>` call per batch, chained with the dispatcher the execution surface selects (`okstra team dispatch` on `cmux-pane`, `okstra worker-dispatch` otherwise) and `--jobs-file <jobs-file>`. Native-session rows still dispatch one host call per row — see [convergence](./convergence.md) "Invocation materialization gate" |
|
|
677
648
|
| Flagging an adapter-shortened dispatch prompt as "incomplete" because it omits host-loaded material | The Worker Preamble pointer and core inputs remain mandatory; the selected adapter may omit duplicate host-loaded definitions |
|
|
678
649
|
| Waiting silently after `dispatch_worker` returns without a completed worker artifact | A dispatch acknowledgement is not completion — call `await_workers` and enforce the selected adapter's liveness policy |
|
|
679
650
|
| Re-sending a finding absent from the persisted round plan | Dispatch exactly the engine-returned `findingIds`; see [convergence](./convergence.md) "Re-verification Dispatch" |
|
|
@@ -16,3 +16,67 @@ Allowed targets:
|
|
|
16
16
|
- `done`
|
|
17
17
|
|
|
18
18
|
`finalVerification.routingRecommendation` is an **object** with exactly two fields — `target`, one value from the Allowed targets list, and `rationale`, the sentence tying that choice to the verdict and the blocker list. Free routing prose is not the field; a target named only in the prose does not route the task, because Phase 7 projects `workflow.nextRecommendedPhase` from `target` alone. `final-verification` re-runs this phase on the same head and is for exactly one situation: every remaining blocker is an environment or configuration fault whose cause this report already names — a `qaCommands` entry pointing at a path that no longer exists, a missing credential, a stale fixture — so nothing in the code, the plan, or the selected direction is being re-decided. Name the repair in the `rationale`. When any blocker needs a code, plan, or direction change, route to the phase that owns that change instead; routing a defect you have not diagnosed back into this phase re-runs the verification that already failed. Both `release-handoff` forms are allowed ONLY when the verdict is release-ready — `accepted`, or `conditional-accept` with every condition declaring `blocksReleaseHandoff: false`. Either verification scope may route there: release-handoff opens one PR per stage, so a release-ready `single-stage` run is the evidence for that stage's PR, and `release-handoff(stage-group)` is only a scope qualifier that projects onto the same phase. `done` ends the lifecycle here. Enforcement: `schemas/final-report-v2.0.schema.json` rejects a `target` outside the enum, a missing `rationale`, and a string in place of the object; `validators/validate-run.py` rejects a missing `target` and a verdict that is not release-ready routed to either `release-handoff` form (naming the condition ids that block it).
|
|
19
|
+
|
|
20
|
+
## release-handoff
|
|
21
|
+
|
|
22
|
+
- if any cited verdict is `blocked`, a `conditional-accept` carrying a condition that blocks release, or any other token (including ambiguous phrasing like "looks good"), the run MUST end immediately with status `blocked` and a routing recommendation back to `error-analysis` or `implementation-planning`. Do NOT prompt the user; Do NOT run any git command.
|
|
23
|
+
|
|
24
|
+
- **Routing recommendation**: explicit `done` token, since release-handoff is the terminal lifecycle phase. If the run ended in `skip` or `cancel`, or delivered only some of the selected stages, the recommendation MUST state which stages still need a PR and that re-entry into release-handoff is appropriate.
|
|
25
|
+
|
|
26
|
+
1. **Entry-gate audit** — the report cites, for every stage it delivered, that stage's final-verification report path and the literal `Verdict Token` row with a release-ready value. If any is missing, or a `conditional-accept` stage's PR body omits its conditions, the run is invalid and MUST be re-routed to `final-verification`.
|
|
27
|
+
|
|
28
|
+
Enforcement boundary: `scripts/okstra_ctl/release_gate.py` `release_handoff_allowed` rejects non-release-ready verification evidence, and `scripts/okstra_ctl/phases/release_handoff/operations.py` `_require_eligible` blocks ineligible stages. The lead performs the routing and report-completeness judgement through the phase-transition checklist in [the lead contract](./okstra-lead-contract.md); these code checks do not choose its next destination.
|
|
29
|
+
|
|
30
|
+
## technical-verification
|
|
31
|
+
|
|
32
|
+
Route only to `implementation-option-selection`, with one matching phase-continuation follow-up. The next comparison consumes this report through `--clarification-response` and authors fresh feasibility votes.
|
|
33
|
+
|
|
34
|
+
Enforcement: `technicalVerification.routing.nextTaskType` and phase-continuation constraints in the report schema; `scripts/okstra_ctl/report_routing.py` checks the routing value during publication and run validation.
|
|
35
|
+
|
|
36
|
+
## implementation-option-selection
|
|
37
|
+
|
|
38
|
+
When no candidate is valid and explicit eligible technical facts remain, route to `technical-verification` to collect experimental evidence. Keep `rankedOptions` empty and `recommendedOptionId` null. `validate_blocked_answer_channel` rejects this route while user decisions remain unresolved or no safe, explicitly classified technical fact is available. Historical blocked reports can be supplied explicitly without rewriting their verdict.
|
|
39
|
+
|
|
40
|
+
With valid options set routing to `pending-direction-selection`; without a valid option use `blocked`.
|
|
41
|
+
|
|
42
|
+
In `candidate-comparison`, keep `preselectedDirection` null and do not route directly to `implementation-planning`. In `preselected-validation`, emit exactly one validated option, an empty `candidateAudit`, a cited `preselectedDirection`, and routing `implementation-planning`.
|
|
43
|
+
|
|
44
|
+
## requirements-discovery
|
|
45
|
+
|
|
46
|
+
determine whether `error-analysis` or `implementation-option-selection` is the next safe step. Direct `implementation-planning` or `implementation` handoff is never a valid routing target — implementation requires direction selection followed by an approved `implementation-planning` report
|
|
47
|
+
|
|
48
|
+
The lead owns the final routing decision and safe resume guidance. The phase supplies request classification, rejection criteria, missing evidence and dependency facts. The report schemas constrain `requirementsDiscovery.routing.nextTaskType`; common `report_routing.fanout_routing_errors` checks each packet destination.
|
|
49
|
+
|
|
50
|
+
## error-analysis
|
|
51
|
+
|
|
52
|
+
Allowed targets:
|
|
53
|
+
|
|
54
|
+
- `implementation-option-selection`
|
|
55
|
+
- `error-analysis`
|
|
56
|
+
|
|
57
|
+
If the cause is credible, recommend `implementation-option-selection` with the verified evidence; if the cause is still unclear, recommend another `error-analysis` run with the next diagnostic. The lead's Phase Routing settles the next phase.
|
|
58
|
+
|
|
59
|
+
A route to `implementation-option-selection` requires a credible leading cause referenced by `routing.leadingCauseId` and `begin-option-selection` as the direction. A route back to `error-analysis` requires the sharp next diagnostic and `continue-investigation` as the direction.
|
|
60
|
+
|
|
61
|
+
The selected target is recorded in `errorAnalysis.routing.nextTaskType`. `schemas/final-report-v2.0.schema.json` and `schemas/final-report-v3.0.schema.json` constrain the target values. `okstra_ctl.phases.error_analysis.validation` checks the cause reference, matching verdict directions, and the single phase-continuation row. Common `okstra_ctl.next_phase` projects that selected target without choosing a destination.
|
|
62
|
+
|
|
63
|
+
## improvement-discovery
|
|
64
|
+
|
|
65
|
+
Both branches: Direction `routing`; Next Step "ask the user to select K candidates (see the ## 5.9 table)".
|
|
66
|
+
|
|
67
|
+
- `## 3. Recommended Next Steps` first entry summarises per-candidate routing and proposes new task-key names of the form `<task-group>/imp-<Cand-ID>`
|
|
68
|
+
|
|
69
|
+
### Candidate conversion
|
|
70
|
+
|
|
71
|
+
- Each candidate the user picks becomes a new okstra task. Suggested task-key: `<task-group>/imp-<Cand-ID>`.
|
|
72
|
+
- The candidate row's Recommended next-phase determines which `--task-type` to launch with.
|
|
73
|
+
|
|
74
|
+
## implementation
|
|
75
|
+
|
|
76
|
+
Pick `final-verification` when this stage's plan items landed and validation passed; `error-analysis` when a failure's cause is not understood; `implementation-planning` when the approved plan itself no longer fits the evidence; `implementation` when work remains inside this stage and the next run is a fix run.
|
|
77
|
+
|
|
78
|
+
For the `selected-direction` plan branch: A direction change routes to `implementation-option-selection`; a detail-only plan correction routes to `implementation-planning`.
|
|
79
|
+
|
|
80
|
+
For the legacy candidate-comparison branch: Any deviation MUST be justified in the final report AND routed to a new `implementation-planning` run; never silently expand scope.
|
|
81
|
+
|
|
82
|
+
Enforcement boundary: the lead applies these semantic distinctions through the phase-transition checklist in [the lead contract](./okstra-lead-contract.md). `tests/contract/test_prompt_fragment_ownership.py` preserves the decision rules at this canonical location; it checks instruction ownership, not the correctness of an individual model judgement.
|