okstra 0.206.0 → 0.206.1
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 +2 -2
- package/dist/commands/lifecycle/install.mjs +1 -1
- package/dist/commands/lifecycle/install.mjs.map +1 -1
- package/docs/architecture.md +12 -12
- package/docs/cli.md +4 -4
- package/docs/contributor-change-matrix.md +3 -2
- package/docs/performance-improvement-plan-v2.md +1 -1
- package/docs/project-structure-overview.md +39 -18
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/bin/okstra-spawn-followups.py +2 -2
- package/runtime/prompts/launch.template.md +1 -1
- package/runtime/prompts/lead/context-loader.md +1 -1
- package/runtime/prompts/lead/convergence.md +3 -3
- package/runtime/prompts/lead/okstra-lead-contract.md +13 -54
- package/runtime/prompts/lead/phase-routing.md +64 -0
- package/runtime/prompts/lead/report-writer.md +2 -2
- package/runtime/prompts/lead/team-contract.md +1 -1
- package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +1 -1
- package/runtime/prompts/profiles/_coverage-critic.md +1 -1
- package/runtime/prompts/profiles/forbidden-actions.json +0 -94
- package/runtime/python/okstra_ctl/agent/prompt_cli/corrections.py +1 -1
- 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/asset_roots.py +19 -0
- package/runtime/python/okstra_ctl/consumers.py +12 -0
- package/runtime/python/okstra_ctl/dispatch_state.py +22 -0
- package/runtime/python/okstra_ctl/doctor.py +2 -1
- package/runtime/python/okstra_ctl/execution_mutation_audit.py +27 -1
- 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 +8 -1
- 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 +1 -1
- 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 +4 -4
- 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} +2 -2
- 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} +1 -1
- 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/profile_show.py +3 -3
- package/runtime/python/okstra_ctl/render.py +9 -2
- package/runtime/python/okstra_ctl/report_assembly.py +11 -90
- 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 +67 -349
- package/runtime/python/okstra_ctl/stage_map.py +13 -0
- 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_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_prompt_contract.py +36 -0
- package/runtime/python/okstra_ctl/workflow.py +26 -143
- package/runtime/skills/okstra-brief-gen/SKILL.md +3 -3
- package/runtime/skills/okstra-run/SKILL.md +1 -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
|
@@ -174,7 +174,7 @@ The Module column below is where the command's behaviour lives — a `src/` modu
|
|
|
174
174
|
| `git-reconcile` | `scripts/okstra_ctl/git_reconcile.py` | Reconcile stale stage SHAs after external git history changes |
|
|
175
175
|
| `stage-close` | `scripts/okstra_ctl/stage_close.py` | Close an already-landed implementation stage as done (commit + conformance evidence required) |
|
|
176
176
|
| `option-votes` | `scripts/okstra_ctl/option_votes.py` | List the implementation candidates that only lack feasibility votes, and the analyser owing each one |
|
|
177
|
-
| `handoff` | `scripts/okstra_ctl/handoff.py` |
|
|
177
|
+
| `handoff` | `scripts/okstra_ctl/handoff.py` | CLI assembly and common verification recording; release policy is in `phases/release_handoff/operations.py` |
|
|
178
178
|
| `integrate-stages` | `scripts/okstra_ctl/stage_integrate.py` | Merge verified stages into the task worktree and clean stage worktrees |
|
|
179
179
|
| `task-list`, `task-show` | `scripts/okstra_ctl/task_list_cli.py`, `scripts/okstra_ctl/task_show_cli.py` | Task/run introspection for skills; `task-show` consumes the Python task read-side snapshot |
|
|
180
180
|
| `resolve-task-key` | `scripts/okstra_ctl/resolve_task_key.py` | Resolve a bare task-id to candidate task-keys from the project catalog |
|
|
@@ -243,11 +243,11 @@ Important modules:
|
|
|
243
243
|
| `run.py` | `prepare_task_bundle()` single authority and CLI parser; for final-verification it passes CLI values to `phases/final_verification/`, whose `entry.py` builds the target request, applies the acquired target to render context, and writes the `verification-target.md` snapshot and digest before manifests and prompts are rendered |
|
|
244
244
|
| `agent/activity.py` | Records activity rows against run-manifest identity, imports validated command evidence from worker audit sidecars, and deterministically projects the current run's `lead-events-*.jsonl` activity rows into `agentActivity[]`. Manifests without `activityContractVersion: 1` are left unchanged. |
|
|
245
245
|
| `exact_coverage.py` | Shared pure calculator for requirement coverage and scope precision in option selection and selected-direction planning |
|
|
246
|
-
| `
|
|
246
|
+
| `phases/implementation_option_selection/validation.py` | Option-selection criteria, weighting, candidate fingerprint convergence, ranking, and semantic validation |
|
|
247
247
|
| `implementation_direction.py` | Selected report/response validation, direction snapshot materialization, and selected-direction reference validation |
|
|
248
|
-
| `technical_verification.py` | Optional `technical-verification` phase backend — resolves and freezes the explicitly classified unresolved facts from the same task's implementation-option-selection report into `state/technical-verification-input-<seq>.json` (`write_technical_verification_input` / `resolve_technical_verification_input`, driven from `run.py`). No selected direction is required and unresolved user decisions still block entry; it links test inputs to observed results and never produces adoption approval or changes candidate feasibility |
|
|
248
|
+
| `phases/technical_verification/entry.py` | Optional `technical-verification` phase backend — resolves and freezes the explicitly classified unresolved facts from the same task's implementation-option-selection report into `state/technical-verification-input-<seq>.json` (`write_technical_verification_input` / `resolve_technical_verification_input`, driven from `run.py`). No selected direction is required and unresolved user decisions still block entry; it links test inputs to observed results and never produces adoption approval or changes candidate feasibility |
|
|
249
249
|
| `verification_target.py` | Shared reader for the prepared final-verification target snapshot (`verification-target.md`) written by `phases/final_verification/entry.py::write_verification_target_snapshot`. One implementation of the digest/scope rule serves both consumers — report assembly (records `verificationScope`) and `validators/validate-run.py` (re-checks the published report against the target) — so the two cannot drift |
|
|
250
|
-
| `
|
|
250
|
+
| `phases/implementation/entry.py` | `implementation` single-stage run orchestration — read the Stage Lifecycle Snapshot → pick an available Stage Map entry → provision an isolated stage worktree → publish the selected stage as run context (extracted from `run.py`) |
|
|
251
251
|
| `stage_targets.py` | Stage readiness/verification policy SSOT — from the Stage Lifecycle Snapshot (`consumers.jsonl` ledger + carry sidecar backfill + active registry reservation) it decides which stage is runnable, which commit it branches from, and the Git and ledger facts final-verification builds its target from: whole-task integration, nested stage worktree relocation, the stage that contains every other done stage, and teardown after the verdict. `order_stage_closure` topologically sorts (Kahn) the dependency closure of the wizard's multi-selected stage set to produce the unattended `chain-stages` chaining order |
|
|
252
252
|
| `stage_fix_carry.py` | fix-run carry derivation for a re-run on an `implementation` stage whose latest final-report data.json carries verifier `FAIL` verdicts — collects the previous report path, previous run HEAD, failed verifiers, carried blocking findings, and a routing recommendation, which `run.py` renders into the analysis profile through the `{{FIX_RUN_CONTEXT}}` token. A first run, or a re-run after `PASS`, yields no carry and renders the token empty |
|
|
253
253
|
| `stage_reconcile.py` | best-effort git reconciliation shared by the stage prepare flow (delegates to `git_reconcile.auto_reconcile`; advisory — failures are only reported to stderr, the dependency gate stays authoritative) |
|
|
@@ -270,7 +270,7 @@ Important modules:
|
|
|
270
270
|
| `timeline_runs.py` | read-side overlay of a `history/timeline.json` entry with its run-manifest's current facts (`current_run_facts`) — the entry is a prepare-time snapshot (`status`, `workflowSnapshot`, reserved `reportRecordPath`) and `validate-run` writes the end state to the run-manifest only; a run whose `validation.status` is `not-run` projects no report path. Shared by `recap.py` and the `history-input` / overview projections in `model_io/renderers.py` |
|
|
271
271
|
| `render.py` | task manifest, run manifest, timeline, task index, discovery, team-state, prompt/template render |
|
|
272
272
|
| `group_context.py` | task-group context document (`.okstra/briefs/<task-group>/group-context.md`): the skeleton writer behind `okstra group-context init` (template `templates/reports/group-context.template.md`), `validate_group_context` (four required sections, no template placeholder left, directory slug matches the frontmatter `task-group`) that `validators/validate-brief.py` dispatches to on frontmatter `type: group-context`, and the path helpers `run.py` uses to validate the file at preflight and copy it to `instruction-set/task-group-context.md` for the analysis packet's `## Task-Group Context` section |
|
|
273
|
-
| `workflow.py` |
|
|
273
|
+
| `workflow.py` | Common phase sequence (`PHASE_SEQUENCE`) and boundary rendering. Allowed outputs and forbidden actions are read from the selected phase's `boundary.json`; next-phase decisions remain in the lead routing instructions. |
|
|
274
274
|
| `next_phase.py` | `workflow.nextRecommendedPhase` SSOT — the pointer's shape (`make` / `is_pointer` over `{phase, status, rationale}`, `status` ∈ `ready`/`pending`/`blocked`/`terminal`), the promotion of a legacy string pointer (`promote`), the projection of one report's routing field into a pointer (`project`), and the `ready`-only read the shell and wizard autofill share (`autofill_task_type`). There is no static phase table and no sequence walk: the next phase comes from what the report authored, and nothing else may compute one |
|
|
275
275
|
| `workers.py`, `models.py` | Worker roster; `models.py` is the model catalog SSOT (`ModelSpec` per alias + `ROLE_DEFAULTS`) — add-a-model single reference point from which picker options, codex pricing, and role defaults all derive |
|
|
276
276
|
| `worktree/`, `worktree_registry.py` | One worktree per task-key, branch registry, sync dirs/files/snapshots. The package layers the job: `naming` (path/branch strings, no disk), `sync_config` (which paths follow the checkout across), `git_ops` (the git calls), then `cleanliness` (dirty by okstra's definition), `linking` (installs the symlinks), `decisions` (answers what provisioning would do, without doing it), and `provision` — the only layer with side effects |
|
|
@@ -322,7 +322,7 @@ Important modules:
|
|
|
322
322
|
| `code_review_target.py` | `okstra code-review target` backend — argument validation and JSON shaping only. Stage mode delegates whole to `okstra_project.state.code_review_target_snapshot`; branch mode is resolved here, defaulting the diff base to the merge-base with the default branch (`refs/remotes/origin/HEAD`, else `main`/`master`). Read-only: it never creates the review directory |
|
|
323
323
|
| `session.py`, `seeding.py`, `locks.py`, `invocation.py`, `sequence.py`, `ids.py`, `material.py` | Supporting lifecycle helpers |
|
|
324
324
|
| `pane_reclaim.py` | resolves which runs of the current project still hold a non-terminal dispatch, so the `SessionStart(compact)` hook can re-inject the pane-cleanup obligation for them. The signal is the newest `team-state` per run directory, not the central run index — an in-session run never appears there (ADR-0011). Imports the status split from the `dispatch_state.NON_TERMINAL_WORKER_STATUSES` SSOT |
|
|
325
|
-
| `
|
|
325
|
+
| `phases/improvement_discovery/lenses.py` | lens enum SSOT + cap constants for the improvement-discovery phase (DEFAULT 8, ABSOLUTE 12, MIN/MAX PRIORITY 1/4, SOURCE_WORKERS) |
|
|
326
326
|
| `container.py` | the `okstra container` convergence entrypoint of the okstra-container-build public skill — `provision_container_group` + `up`/`status`/`down` dispatch, env-override synthesis, compose argv assembly, and healthcheck polling |
|
|
327
327
|
| `plan_run_root.py` | shared helper deriving `approved_plan_path` → `plan_run_root` and back-tracing the task-key |
|
|
328
328
|
| `manager_cli.py` | `okstra manager` Python entrypoint — purpose-specific fixed text by default, machine JSON with `--json` |
|
|
@@ -341,7 +341,10 @@ Important modules:
|
|
|
341
341
|
| `cmux.py` | cmux-pane worker backend — a worker that gets a pane frees the lead process, and anything that stops a pane opening degrades quietly to the blocking wrapper. Detects a usable cmux session before selecting the backend (CLI resolves + ping answers PONG + the lead's workspace is resolvable), derives placement from the workspace geometry each dispatch, relays lead/worker events to the cmux sidebar, and records the run's terminal backend in the manifest so both phases of a run land on one backend. A sandbox that hides cmux (`PermissionError` on the socket) stops dispatch with the remedy instead of degrading into the same broken fallback; a quit app (`FileNotFoundError`) still degrades |
|
|
342
342
|
| `codex_dispatch.py` | Compatibility adapter delegating `okstra codex-dispatch` to the provider-neutral `worker_dispatch` path |
|
|
343
343
|
| `analysis_packet.py` | assembles the compact analysis-worker input packet for a task run from worker-owned profile sections; report/lead procedure stays outside the packet |
|
|
344
|
-
| `
|
|
344
|
+
| `analysis_scope.py` | Shared normalized project-relative path and scope-inclusion predicates for analysis evidence and project-map validation |
|
|
345
|
+
| `technical_verification_facts.py` | Shared unresolved technical-fact identities, candidate safety checks and user-decision gate consumed by option selection and technical verification |
|
|
346
|
+
| `handoff.py`, `handoff_verification.py`, `handoff_error.py` | Common verification recording, accepted-evidence reading and handoff error type; release-specific preparation and remote-operation policy live in `phases/release_handoff/` |
|
|
347
|
+
| `analysis_inputs.py` | shared input boundary for `project-analysis`, `feature-analysis`, and `change-impact-analysis` — validates evidence-report identity and review status, enforces the type-to-type relation allowlist, computes `exact`/`stale` freshness, and exposes report candidates to the phase-owned feature-target resolver |
|
|
345
348
|
| `user_response.py` | parses clarification/approval responses and the analysis-review sidecar; `parse_analysis_review` validates accepted, revision-requested, and rejected decisions plus their affected IDs and reason; `format_show_view` prints why-asked, linked plan items, and cited artifacts for the in-session picker |
|
|
346
349
|
| `context_cost.py` | read-side context-cost estimator for a prepared okstra task bundle (the `okstra context-cost` backend) |
|
|
347
350
|
| `schema_excerpt.py` | generates a task-type-scoped excerpt of the final-report schema — a schema reduction to inject into the worker/lead prompt |
|
|
@@ -366,7 +369,7 @@ Important modules:
|
|
|
366
369
|
| `plan_items.py`, `plan_items_cli.py` | deterministic extraction of the report-writer narrative `P-*` plan-item queue plus the `okstra plan-items extract` / `validate` / `seed` / `collect-verdicts` / `apply-verdicts` / `derivations` adapter; v2 data.json remains a read input |
|
|
367
370
|
| `claim_reproduction.py` | reproduces a plan-body single-vote `fact` claim before it can block on one vote — runs the declared probe (`path-exists` / `path-absent` / `literal-present` / `literal-absent` / `citations-differ`) inside the resolved project root and returns `reproduced` / `not-reproduced` / `not-runnable`, which `plan-items apply-verdicts --run-manifest` writes into `reproductionResult` (always overwriting the worker-sent value so a verifier cannot score its own claim). A `judgement` claim, or a `fact` that does not reproduce, takes the quorum route |
|
|
368
371
|
| `plan_derivations.py` | the supersession sweep `_common-contract.md` requires an author to do by hand — extracts the symbols, paths, and ids an answered clarification names and reports every plan string that mentions one. Advisory: it locates candidates and never judges which are now false |
|
|
369
|
-
| `scope_provenance.py` | single source of truth for the scope-provenance grammar every phase-emitted requirement must declare, shared by `validators/validate-run.py` and `
|
|
372
|
+
| `scope_provenance.py` | single source of truth for the scope-provenance grammar every phase-emitted requirement must declare, shared by `validators/validate-run.py` and `scripts/okstra_ctl/phases/requirements_discovery/validation.py` so the planning report and fan-out packets cannot drift |
|
|
370
373
|
| `worker_artifact_paths.py` | canonical worker artifact path derivation (e.g. `audit_sidecar_rel` inserts `-audit-` after the first `-worker-` token), so dispatch and validation agree on non-canonical-path rejection |
|
|
371
374
|
| `report_translation_dispatch.py` | Phase 7 `translate` step — for a non-English `reportLanguage` and no `*.i18n.<lang>.json` sidecar, reuses or materializes this run's translator reservation (`agent-prompt materialize --audience translator` in-process, instruction file under `state/`), runs the CLI-wrapper dispatch, and succeeds only when the sidecar exists afterwards. Replaces the manual lead sequence that was skipped in practice |
|
|
372
375
|
| `report_finalize.py` | Phase 7 post-report sequence **SSOT** — runs `translate` → `token-usage` → `render-views` → `spawn-followups` → `validate-run` → `record-group-memory` → `teardown-stages` in that load-bearing order. A non-zero exit still runs every later check through `validate-run` and names the earliest failure; `record-group-memory` (this run's conclusion into the task-group's `group-context.md`, plus `nextInGroup` for the closeout) and `teardown-stages` are skipped when any earlier step failed. Both lead paths converge here: the Codex adapter calls it in-process (`codex_dispatch`), a Claude-led run reaches it through `okstra report-finalize`. Neither reimplements the sequence |
|
|
@@ -382,7 +385,7 @@ Important modules:
|
|
|
382
385
|
| `contract_refreeze.py` | re-freezes a running run's frozen contracts in the installed format. A run freezes its duty/role/common contracts at start and pins their digest, so installing a release that changed the contract format leaves that run unable to produce another prompt (`run duty snapshot catalog digest does not match`). Backs `okstra agent-prompt refreeze-contracts`, rewrites the frozen copies and the manifest digest only, and never touches a prompt, result or ledger |
|
|
383
386
|
| `operation_invocation.py` | prepares an Okstra-owned LLM operation that runs outside `okstra-run` — the operation contract (`agents/operations/<id>.json`) owns the duty and the worker count, and the role is derived from that duty's `roleId`, so a skill passes the operation name instead of assembling role/provider/model itself (ADR-0017). Backs `okstra agent-prompt resolve-operation` |
|
|
384
387
|
| `phases/catalog.py` | Fixed map from the 12 public task types to their phase package names, whether each phase has moved into `phases/<package>/`, and its HTML view builder. Resolves a task type's profile Markdown/JSON and phase-owned report templates inside one asset root (repo checkout, `runtime/python`, or `~/.okstra/lib/python`) and resolves `{{INCLUDE:...}}` targets for a phase `profile.md`. Importing it loads no phase module |
|
|
385
|
-
| `phases/final_verification/` |
|
|
388
|
+
| `phases/final_verification/` | Final-verification policy and assets: `profile.md`/`profile.json` (recorded under the logical paths `prompts/profiles/final-verification.*`), `spec.md` (process note and guarantees), `entry.py` (verification-target request, snapshot writer, prepare-flag checks), `validation.py` (added-surface, verdict, and scope checks that `validate-run` calls before its routing check), `wizard.py` (whole-task pick condition), `target.py` (`acquire_final_verification_target()`: chooses single-stage, containing-stage, or integrated whole-task target behind one task-key mutex), `report.py` (HTML view builder and `verificationScope` reader), and `report_assets/` (report body templates). Its `tests/` directory is collected by pytest and left out of the runtime copy |
|
|
386
389
|
| `report_template_loader.py` | Jinja loader for report templates: a logical name owned by a migrated phase opens from that phase's `report_assets/`, and every other name opens from `templates/reports` |
|
|
387
390
|
| `contract_graph.py`, `contract_graph_cli.py` | runtime-contract graph loader + cross-reference/dependency-closure validator and its `okstra contract-check --root <dir> (--profile\|--operation)` CLI boundary. Loads the agent contract schemas (`common`/`role`/`duty`/`profile`/`operation`), validates known role capabilities, and reports the dependency closure with per-file `path`/`schemaVersion`/`sha256`; an invalid contract raises `ContractGraphError` |
|
|
388
391
|
| `json_boundary.py` | strict JSON persistence boundaries for okstra-owned artifacts — a sealed `ExternalJsonSource` (validated producer + path) is the only way owned JSON is read, and `JsonBoundaryError` names artifact / reason / path when a write cannot satisfy its contract; the SSOT that keeps the model out of internal JSON key/path authorship |
|
|
@@ -416,6 +419,27 @@ Important modules:
|
|
|
416
419
|
|
|
417
420
|
> `i18n.py` (the final-report i18n dictionary loader + Jinja2 lookup) is an intentionally undocumented internal helper — it is a render helper that users and contributors do not need to know about in the canonical docs, so it is excluded from the module map.
|
|
418
421
|
|
|
422
|
+
#### Phase packages
|
|
423
|
+
|
|
424
|
+
All 12 task types have a phase package. Each phase owns `profile.md`, `profile.json`, `boundary.json`, `spec.md`, `report.py`, dedicated `report_assets/` and its policy tests. The catalog resolves the existing logical profile and template names to these files. Pytest collects phase-local tests; the runtime copy excludes them. Common report shells, schemas, worker dispatch and evidence readers remain shared.
|
|
425
|
+
|
|
426
|
+
| Task type and specification | Phase-owned policy |
|
|
427
|
+
|---|---|
|
|
428
|
+
| [requirements-discovery](../scripts/okstra_ctl/phases/requirements_discovery/spec.md) | `fanout.py` orders decomposed units; `validation.py` checks their provenance, dependencies and index. |
|
|
429
|
+
| [improvement-discovery](../scripts/okstra_ctl/phases/improvement_discovery/spec.md) | `lenses.py` defines scan lenses and bounds; `validation.py` checks candidate scope, sources and report branches. [Input template](../scripts/okstra_ctl/phases/improvement_discovery/report_assets/improvement-discovery-input.template.md). |
|
|
430
|
+
| [project-analysis](../scripts/okstra_ctl/phases/project_analysis/spec.md) | `entry.py` rejects upstream inputs; `validation.py` checks entry-point scope and component references. [Input template](../scripts/okstra_ctl/phases/project_analysis/report_assets/project-analysis-input.template.md). |
|
|
431
|
+
| [feature-analysis](../scripts/okstra_ctl/phases/feature_analysis/spec.md) | `entry.py` resolves the feature target; `wizard.py` owns target questions; `validation.py` checks the report target against the resolved input. [Input template](../scripts/okstra_ctl/phases/feature_analysis/report_assets/feature-analysis-input.template.md). |
|
|
432
|
+
| [change-impact-analysis](../scripts/okstra_ctl/phases/change_impact_analysis/spec.md) | `entry.py` collects feature evidence; `validation.py` limits planning inputs to constraints and unknowns. [Input template](../scripts/okstra_ctl/phases/change_impact_analysis/report_assets/change-impact-analysis-input.template.md). |
|
|
433
|
+
| [error-analysis](../scripts/okstra_ctl/phases/error_analysis/spec.md) | `validation.py` checks reproduction evidence and cause relationships. [Input template](../scripts/okstra_ctl/phases/error_analysis/report_assets/error-analysis-input.template.md). |
|
|
434
|
+
| [technical-verification](../scripts/okstra_ctl/phases/technical_verification/spec.md) | `entry.py` freezes experiment inputs; `validation.py` checks observed evidence against those inputs. |
|
|
435
|
+
| [implementation-option-selection](../scripts/okstra_ctl/phases/implementation_option_selection/spec.md) | `entry.py`, `validation.py`, `votes.py` and `comparison.py` own direction comparison, feasibility and ranking; `authoring.py` supplies report instructions. |
|
|
436
|
+
| [implementation-planning](../scripts/okstra_ctl/phases/implementation_planning/spec.md) | `entry.py`, `wizard.py`, `validation.py`, `plan_body.py` and `authoring.py` own selected-direction preparation and plan verification; `instructions/` contains plan-body guidance. [Input template](../scripts/okstra_ctl/phases/implementation_planning/report_assets/implementation-planning-input.template.md). |
|
|
437
|
+
| [implementation](../scripts/okstra_ctl/phases/implementation/spec.md) | `entry.py` claims and publishes a stage run; `wizard.py` owns stage selection; `validation.py` checks verifier independence; `instructions/` contains executor and verifier guidance. [Input template](../scripts/okstra_ctl/phases/implementation/report_assets/implementation-input.template.md). |
|
|
438
|
+
| [final-verification](../scripts/okstra_ctl/phases/final_verification/spec.md) | `entry.py`, `target.py`, `wizard.py` and `validation.py` own the prepared verification target, scope and acceptance checks. [Input template](../scripts/okstra_ctl/phases/final_verification/report_assets/final-verification-input.template.md). |
|
|
439
|
+
| [release-handoff](../scripts/okstra_ctl/phases/release_handoff/spec.md) | `entry.py`, `operations.py` and `wizard.py` own handoff input, eligibility, selected remote operations and delivery choices. [Input template](../scripts/okstra_ctl/phases/release_handoff/report_assets/release-handoff-input.template.md). |
|
|
440
|
+
|
|
441
|
+
`prompts/lead/phase-routing.md` owns the lead's continuation decisions. Common `next_phase.py`, release gates, verification evidence, stage state and selected-direction readers consume recorded facts without importing another phase's execution policy. CLI modules such as `option_votes.py`, `option_comparison.py` and `handoff.py` remain assembly entrypoints.
|
|
442
|
+
|
|
419
443
|
### 4.4 `scripts/okstra_project/`
|
|
420
444
|
|
|
421
445
|
Project resolver and read-only state helpers:
|
|
@@ -442,9 +466,7 @@ Token/cost accounting:
|
|
|
442
466
|
| `launch.template.md` | Lead prompt template rendered for each run |
|
|
443
467
|
| `duties/<duty>.json` | Canonical functional duty contracts composed into every Okstra-owned LLM invocation, alongside the common contract at `agents/common.json` and the role contract at `agents/roles/<role>.json`; `direction-selection-worker` owns direction comparison/validation while `planning-worker` realizes the selected direction; provider/model identity does not select the duty |
|
|
444
468
|
| `profiles/_common-contract.md` | Shared phase contract |
|
|
445
|
-
| `profiles
|
|
446
|
-
| `implementation-option-selection.md` | Read-only lifecycle profile for candidate comparison or preselected-direction validation before detailed planning |
|
|
447
|
-
| `project-analysis.md`, `feature-analysis.md`, `change-impact-analysis.md` | Read-only sidetrack profiles for project mapping, one-feature behavior tracing, and proposed-change impact mapping |
|
|
469
|
+
| `profiles/_*.md` | Shared include fragments; task profiles are canonical under `scripts/okstra_ctl/phases/<package>/profile.md`, never a translated mirror |
|
|
448
470
|
| `wizard/prompts.ko.json` | Korean wizard prompt single source of truth |
|
|
449
471
|
|
|
450
472
|
### 4.7 `templates/`
|
|
@@ -453,11 +475,11 @@ Token/cost accounting:
|
|
|
453
475
|
|---|---|
|
|
454
476
|
| `templates/reports/final-report-v2.template.md` | Full reading copy Markdown spine |
|
|
455
477
|
| `templates/reports/final-report-v2.template.md` | Schema v2 full reading copy Markdown spine |
|
|
456
|
-
| `templates/reports/md/
|
|
457
|
-
| `templates/reports/html/base.template.html`, `html/
|
|
478
|
+
| `templates/reports/md/macros/sections.md` | Shared Markdown sections; dedicated task bodies live in each phase's `report_assets/` |
|
|
479
|
+
| `templates/reports/html/base.template.html`, `html/macros/` | Shared HTML shell and macros; dedicated task templates live in each phase's `report_assets/` |
|
|
458
480
|
| `templates/reports/report.css`, `report.js` | Inline assets for self-contained HTML report views |
|
|
459
481
|
| `templates/reports/*.template.md` | Inputs, schedule, user-response, settings templates |
|
|
460
|
-
|
|
|
482
|
+
| Phase `report_assets/*-input.template.md` | Dedicated brief input templates for task types that provide one; common inputs remain under `templates/reports/` |
|
|
461
483
|
| `user-response.template.md`, `report.js` | Analysis Review sidecar block and the browser control that exports accept/revision/reject without changing the source report |
|
|
462
484
|
| `templates/project-docs/task-index.template.md` | Project task index template |
|
|
463
485
|
| `templates/worker-prompt-preamble.md` | Initial analysis audience procedure and output contract |
|
|
@@ -488,7 +510,6 @@ Optional (v1.0 backward-compatible) top-level keys:
|
|
|
488
510
|
| `validate_analysis_report.py` | Cross-field validation for the three read-only analysis reports: frozen target/evidence snapshots, current-code evidence, review-source identity, and exact affected-ID resolution coverage on revision reruns |
|
|
489
511
|
| `validate-schedule.py` | Schedule section/order/code validation |
|
|
490
512
|
| `validate-implementation-plan-stages.py` | enforces the Stage Map structure — checks the S1–S8 rules (`## 5.5 Stage Map` + `## 5.5.<i> Stage <i>` sections, ≤ 8 steps per stage, etc.) |
|
|
491
|
-
| `validate_improvement_report.py` | enforces the 11-item contract of the improvement-discovery final-report. Automatically invoked by `validate-run.py` when `task_type == "improvement-discovery"` |
|
|
492
513
|
| `detect_self_mock.py` | self-mock detector — runs BOTH gates and writes the run's sidecar. Gate A (static) scans the changed TEST files for SUT-stub signals (patterns imported from the SSOT `scripts/okstra_ctl/self_mock_signals.py`, never redefined here), matching each file as one whole-file string so multi-line signals are caught. Python strings and comments are token-masked without changing line positions before those regexes run, so examples in docstrings and comments do not become findings while executable `patch.object(self, ...)` and `sut._private` accesses remain detectable. Writes a `qa/self-mock[-stage-<N>].json` sidecar and prints `QA-RESULT: PASS|FAIL` as its last line (exit 0 = no hits, exit 1 = at least one hit). The sidecar records `scannedFiles`/`skippedFiles` so the gate can prove every changed test file was actually scanned (a run that skips them cannot pass on empty input). An optional `--waivers <path>` moves hits matching `(file,line,signal)` from `staticDetect.hits` to `staticDetect.waived` (each carrying the user's `reason`/`acknowledgedBy`) and records the file as `waiverSource`. Gate B (mutation) runs in the same call: `--changed-file` takes the stage's WHOLE changed set (each adapter selects its own production sources out of it), `--diff` and `--worktree` scope it, and `scripts/okstra_ctl/mutation_probe.py` writes the result into the sidecar's `mutation` block; the received set is recorded as `changedFiles` so the gate can prove gate B was not handed an empty input. `overall` and the exit code follow BOTH gates — a mutation FAIL with a clean static scan still exits 1. The same `--waivers` file feeds both (gate A reads its `signal` entries, gate B its `mutant` ones). Its verdict feeds the fail-closed `_validate_selfmock` gate in `validate-run.py` (implementation / final-verification): a diff that touches test files with no readable PASS sidecar blocks the run; a `waived` entry missing `reason`/`acknowledgedBy`, or a `waiverSource` that is not the task's own `qa/self-mock-waivers.json`, also blocks |
|
|
493
514
|
| `validate-workflow.sh` | End-to-end fixture workflow validation |
|
|
494
515
|
| `lib/*.sh` | Shared shell validator helpers and fixtures |
|
|
@@ -610,7 +631,7 @@ Current report pipeline:
|
|
|
610
631
|
3. Report-writer worker writes `worker-results/report-writer-narrative-<task-type>-<seq>.md`, including `humanSummary` and one task-type deliverable; Phase 7 later assembles the schema v3 report record.
|
|
611
632
|
4. For implementation-planning, `okstra plan-items extract` creates the complete `P-*` queue, `validate` proves it still matches data.json, and the analyser instances run the separate plan-body verification round.
|
|
612
633
|
5. Token usage substitution fills usage/cost cells in the report record. The full reading copy is rendered on demand with `okstra render-final-report` from `templates/reports/final-report-v2.template.md`.
|
|
613
|
-
6. `scripts/okstra-render-report-views.py` independently selects one of
|
|
634
|
+
6. `scripts/okstra-render-report-views.py` independently selects one of twelve dedicated task templates and emits human-facing HTML directly from the same data.json; run validation checks the record and the human HTML. A quick Markdown input retains its legacy conditional path.
|
|
614
635
|
|
|
615
636
|
For the three analysis sidetracks, the HTML view also exports an immutable-source `## ANALYSIS REVIEW` sidecar. A revision rerun carries that sidecar, reanalyzes the whole confirmed scope, and records one `analysisReviewResolution` row for every affected ID before `validate_analysis_report.py` accepts the result.
|
|
616
637
|
|
|
@@ -721,7 +742,7 @@ When changing code, keep these docs in sync:
|
|
|
721
742
|
- New runtime source copied to users: update `tools/build.mjs`, install/uninstall manifests if applicable, and this file.
|
|
722
743
|
- New skill/agent: update `README.md`, this file, install/uninstall fallback lists, and `CHANGES.md`.
|
|
723
744
|
- New report field/section: update schema, template, report-writer worker, validator tests, this file's report model if user-visible.
|
|
724
|
-
- New phase/profile behavior: update the phase directory under `scripts/okstra_ctl/phases/`
|
|
745
|
+
- New phase/profile behavior: update the phase directory under `scripts/okstra_ctl/phases/` and its `spec.md`, plus `docs/architecture.md`, `docs/cli.md`, and `README.md` if user-facing.
|
|
725
746
|
|
|
726
747
|
Edit English canonical Markdown sources directly; nothing asks you to touch the Korean mirror in the same change. A maintainer session reconciles the mirrors on its own schedule with `$sync-korean-sources` or `/sync-korean-sources`, which begins by reading `node tools/korean-sources/cli.mjs status`. `.project-docs/ko-sources/**` is maintainer-local only: it is neither published nor committed.
|
|
727
748
|
|
package/package.json
CHANGED
package/runtime/BUILD.json
CHANGED
|
@@ -56,13 +56,13 @@ prefer_colocated_modules(__file__, "okstra_ctl/next_phase.py")
|
|
|
56
56
|
from okstra_ctl import next_phase # noqa: E402
|
|
57
57
|
from okstra_ctl.final_report_paths import final_report_markdown_path # noqa: E402
|
|
58
58
|
from okstra_ctl.paths import task_manifest_file # noqa: E402
|
|
59
|
-
from okstra_ctl.
|
|
59
|
+
from okstra_ctl.phases.catalog import task_types as phase_task_types # noqa: E402
|
|
60
60
|
from okstra_project.dirs import tasks_root # noqa: E402
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
SLUG_RE = re.compile(r"[^a-zA-Z0-9-]+")
|
|
64
64
|
|
|
65
|
-
ALLOWED_TASK_TYPES = set(
|
|
65
|
+
ALLOWED_TASK_TYPES = set(phase_task_types())
|
|
66
66
|
ALLOWED_ORIGINS = {
|
|
67
67
|
"phase-continuation",
|
|
68
68
|
"out-of-plan",
|
|
@@ -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
|
```
|
|
@@ -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
|
|
|
@@ -761,4 +761,4 @@ If `convergence.enabled: false`, this contract is skipped. Phase 6 operates usin
|
|
|
761
761
|
|
|
762
762
|
## Plan-body verification mode (implementation-planning only)
|
|
763
763
|
|
|
764
|
-
Moved to its own contract:
|
|
764
|
+
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.
|
|
@@ -205,7 +205,7 @@ User-utterance interpretation rule:
|
|
|
205
205
|
- 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
206
|
- 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
207
|
|
|
208
|
-
**Enforced:** the Forbidden actions column is declared in `
|
|
208
|
+
**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
209
|
|
|
210
210
|
## Progress reporting (BLOCKING)
|
|
211
211
|
|
|
@@ -247,7 +247,7 @@ Required checkpoints:
|
|
|
247
247
|
- `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
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 — read from the `okstra team reclaim --project-root <dir> --run-manifest <path> --dry-run` pass taken immediately before the closing pass, never estimated. 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.
|
|
249
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
|
|
250
|
+
- `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
251
|
- `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
252
|
- `PROGRESS: phase-7-persist updating manifests` — at the start of Phase 7.
|
|
253
253
|
- `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.
|
|
@@ -291,7 +291,7 @@ The sequence is fixed:
|
|
|
291
291
|
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
292
|
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
293
|
|
|
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. `
|
|
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. `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
295
|
|
|
296
296
|
The approval state transitions are fixed:
|
|
297
297
|
|
|
@@ -301,7 +301,7 @@ The approval state transitions are fixed:
|
|
|
301
301
|
|
|
302
302
|
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
303
|
|
|
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`, `
|
|
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`, `scripts/okstra_ctl/phases/implementation_planning/plan_body.py` `_user_accepted_plan_item_ids`.
|
|
305
305
|
|
|
306
306
|
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
307
|
|
|
@@ -378,7 +378,9 @@ After context-loader completes, read **only the compact intake files below** in
|
|
|
378
378
|
**Doctrine lazy reads (BLOCKING — read at the round, not at Phase 1):**
|
|
379
379
|
|
|
380
380
|
- [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
|
-
-
|
|
381
|
+
- `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.
|
|
382
|
+
|
|
383
|
+
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
384
|
|
|
383
385
|
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
386
|
|
|
@@ -406,7 +408,9 @@ checks the emitted common procedure. The same entry-guard read trace applies.
|
|
|
406
408
|
|
|
407
409
|
**Implementation profile lazy reading discipline (BLOCKING — applies only when `task_type == "implementation"`):**
|
|
408
410
|
|
|
409
|
-
The `implementation` profile's thin core (`
|
|
411
|
+
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.
|
|
412
|
+
|
|
413
|
+
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
414
|
|
|
411
415
|
**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
416
|
|
|
@@ -552,54 +556,9 @@ All categories must appear in the final synthesis. Do not omit contested or work
|
|
|
552
556
|
|
|
553
557
|
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
558
|
|
|
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.
|
|
559
|
+
### Phase 6 sub-step: Plan-body verification (implementation-planning only)
|
|
601
560
|
|
|
602
|
-
|
|
561
|
+
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
562
|
|
|
604
563
|
## Phase 7: Artifact persistence and validator handoff
|
|
605
564
|
|
|
@@ -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.
|
|
@@ -93,7 +93,7 @@ This section adds report-specific checks to [okstra-lead-contract](./okstra-lead
|
|
|
93
93
|
2. The ledger lives at `runs/<task-type>/state/report-writer-corrections-<task-type>-<seq>-a<N>.json` (schema `schemas/report-writer-corrections-v1.0.schema.json`) and holds one entry per defect: `replace` with the exact replacement value (add `current` when you want it checked), `remove` for an item or optional field, `rewrite` with a `rule` when the writer has to re-author prose. Paths use the validator's grammar (`implementationOptionSelection.rankedOptions[1].coverageSummary.coveragePercent`), so a report-assembly refusal can be copied into the ledger verbatim. Never write an indirect instruction such as `use the schema value`, `use the valid status`, or `fix the enum`: a `replacement` is the literal, and a `rule` names the required outcome. You do not copy allowed enum literals by hand — okstra attaches each `rewrite`'s schema constraint from the frozen schema.
|
|
94
94
|
3. Run `okstra agent-prompt check-corrections --project-root <root> --run-manifest <path> --corrections <ledger>` until it reports no defect. It applies the ledger to a scratch copy of the base narrative and validates the complete proposed narrative against the writer-owned value schema and the task's semantic validator, listing every defect at once. Validating only the edited field is insufficient because one replacement can select a different schema branch, which is why the check covers the whole narrative.
|
|
95
95
|
4. When the check reports `mechanical: true` and has corrections, run `okstra agent-prompt apply-corrections` with the same arguments: okstra writes the corrected narrative to `reportNarrativePath` and records a `lead-correction-applied` activity row naming the ledger and its correction ids. This includes validated `replace`, `remove`, `add`, `move`, and derived step counts. No writer dispatch, `record-dispatch`, or `link-result` follows; the roster row's result already exists.
|
|
96
|
-
5. Otherwise materialize the writer prompt with the same `--corrections <ledger>` under a new invocation id and prompt path (retire the first attempt's link with `reject-result` as
|
|
96
|
+
5. Otherwise materialize the writer prompt with the same `--corrections <ledger>` under a new invocation id and prompt path (retire the first attempt's link with `reject-result` as `plan-body-verification` (the absolute path in **Okstra Runtime Resources**) describes). okstra renders the correction-only field values, evidence, schema constraints, replacement-file contract, application command, and output paths. Put context in the ledger; the initial instruction body is not sent to the correction writer.
|
|
97
97
|
|
|
98
98
|
A report-writer materialization without `--corrections` whose narrative already exists and parses is refused before any prompt is written — free-form corrections cannot be checked before the writer runs, and four of six re-runs in the 2026-09-03 measurement were lead instructions that contradicted the authoring contract. Only a narrative whose structure does not parse (line grammar, an unknown top-level field) is re-authored, not corrected: that dispatch needs no ledger, and its body quotes the parser's message. Because re-authoring overwrites the live file in place, okstra copies the existing narrative to `worker-results/<narrative-name>.pre-<invocation-id>.md` at materialization and renders a `## Previous Attempt` section naming that copy (**Enforced:** `_preserve_reauthored_narrative` in `scripts/okstra_ctl/agent/prompt_cli/materialize.py`); the 2026-09-09 dev-10642 run lost a 579-line attempt to a failed in-place re-indent command with no copy to fall back on. A narrative that breaks the line grammar is not a produced artifact: the dispatcher settles that attempt as `required worker artifact is unusable: narrative does not parse: …` and retries it inside the same batch, so you see the parser's message at collection, not at Phase 7 assembly (**Enforced:** `okstra_ctl.dispatch_state.unusable_result_defect`, read by `missing_completion_paths` and the `team await` record path). The synthesis packet's Authoring Contract carries the line grammar itself (`report_narrative.NARRATIVE_GRAMMAR_INSTRUCTIONS`), so a writer that reads only the packet still sees it. Value defects — an id outside its pattern, a value outside its enum, a missing required field — leave the structure readable and are exactly what the ledger fixes; the a3 attempt of the 2026-09-03 run carried twenty `SC-` ids that assembly refused and was still a corrective base.
|
|
99
99
|
|
|
@@ -106,7 +106,7 @@ A report-writer materialization without `--corrections` whose narrative already
|
|
|
106
106
|
3. Run initial plan-body verification as round 1.
|
|
107
107
|
4. Apply at most one automatic planner self-fix to the narrative. Skip this step when `gating` is `false`.
|
|
108
108
|
5. Run targeted re-verification as round 2 when needed. Skip this step when `gating` is `false`.
|
|
109
|
-
6. Persist the completed `planBodyVerification` value in convergence state. Run `okstra plan-items next-dispatch`: after the single automatic self-fix, settle eligible judgements with `resolve-dissent`; ask the user immediately for decisions outside lead authority. Preserve dissent and do not restart the automatic loop. The exact procedure and enforced authority checks are in `
|
|
109
|
+
6. Persist the completed `planBodyVerification` value in convergence state. Run `okstra plan-items next-dispatch`: after the single automatic self-fix, settle eligible judgements with `resolve-dissent`; ask the user immediately for decisions outside lead authority. Preserve dissent and do not restart the automatic loop. The exact procedure and enforced authority checks are in `scripts/okstra_ctl/phases/implementation_planning/instructions/plan-body-verification.md` step 8.
|
|
110
110
|
7. Complete the design-surface detector snapshot: `okstra design-snapshot --narrative <reportNarrativePath> --output <designPreparationPath>`, taking both paths from the run manifest. Nothing else writes that snapshot, and step 8 fails without it — `report_inputs._PLANNING_INPUT_FIELDS` lists `designPreparationPath` as a required planning input.
|
|
111
111
|
8. Run Phase 7 report assembly.
|
|
112
112
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
- When verifying worker team composition and operational rules
|
|
6
6
|
- When applying model assignment rules
|
|
7
7
|
|
|
8
|
-
**Not applicable to `release-handoff`** — that profile is lead-only and intentionally has no `Required workers:` block (see `
|
|
8
|
+
**Not applicable to `release-handoff`** — that profile is lead-only and intentionally has no `Required workers:` block (see `scripts/okstra_ctl/phases/release_handoff/profile.md`). The worker-dispatch contract in this document does not engage during `release-handoff` runs.
|
|
9
9
|
|
|
10
10
|
## Team Structure
|
|
11
11
|
|
|
@@ -16,7 +16,7 @@ prompt through `prepare_agent_invocation()` before `worker-dispatch`.
|
|
|
16
16
|
Load the applicable coding conventions for every language the diff will touch, then state in ONE line which conventions apply (e.g. `Applying TS + hexagonal overlay; domain at src/domains/*/domain/`). Lint/test green is necessary but NOT sufficient — self-mocked tests, interaction-only assertions, and untruthful names all pass a green pipeline; this gate is what keeps them out of the diff.
|
|
17
17
|
|
|
18
18
|
- **Resource selection — read the routed pack, never inline it here.** Use this worker prompt's `**Coding preflight pack:**` anchor header as the absolute path to the installed routed pack. Detect each touched file's language and framework from its extension or project manifest (`package.json`, `Cargo.toml`, `pyproject.toml`, `pom.xml`, `build.gradle*`, `prisma/schema.prisma`), then read that pack's resources via the Read tool by absolute path. Always read `overview.md` (the router) + `clean-code.md`, then select per the router's three ordered stages — Stage 1 language → `languages/<lang>.md`, Stage 2 framework → `frameworks/<fw>.md` (e.g. `frameworks/node-server.md` for server-side Node), Stage 3 architecture → `architectures/<arch>.md` (e.g. `architectures/hexagonal.md` for ports-and-adapters / NestJS-hex). Each stage is a list of rules; include EVERY matching resource (a change set can touch multiple languages/frameworks/architectures) — do not stop at the first match. These files are runtime resources, not Skill-tool skills, so always read them by path.
|
|
19
|
-
- **Project policy projection:** before selecting resources, run `okstra model-io project-context --project-root <PROJECT_ROOT> --task-ref <
|
|
19
|
+
- **Project policy projection:** before selecting resources, run `okstra model-io project-context --project-root <PROJECT_ROOT> --task-ref <TASK_KEY>` (the full `Task key` your dispatch prompt names). Consume its `Architecture style`, `Project Review Rule Packs`, and `Project QA Commands` sections; do not open Okstra-owned JSON storage.
|
|
20
20
|
- **Declared architecture style — an authoritative Stage 3 input, and it binds.** A projected `hexagonal` selects `architectures/hexagonal.md` even when none of Stage 3's layout signals matched, so the declaration — not the directory shape — decides. A projected `layered` has no pack resource; its invariant applies from this line: dependencies run one direction only — an upper layer may import a lower one, never the reverse — and a variation point is extracted onto a layer boundary. A declared style makes this overlay binding rather than advisory, and which rule binds follows the style: under `hexagonal` the overlay's otherwise-advisory concrete-adapter item is blocking, so a service dependency you add or modify goes through a port instead of a concrete implementation and that placement violation is fixed before the write rather than recorded as a note; under `layered` what binds is the direction invariant just stated — your own judgement over the import list of every file the diff touches, plus extracting a variation point onto a layer boundary — while the concrete-adapter item stays advisory, since `layered` has no ports to route it through. An absent or `none` projected style leaves Stage 3 detection-driven and its overlay advisory. The verifier re-grades the same diff under the same declaration (`_implementation-verifier.md` → Static design & test-quality review), so a placement violation missed here returns as a verdict `FAIL`.
|
|
21
21
|
- **Project review rule packs:** a pack applies when either source names it — the task brief's `Source Material` / `Reporter Confirmations` cites its exact `SKILL.md` path, or the project-context projection lists it as a standing standard. The two sources are a union. Read only those files and the `references/*.md` files they directly name; a declared path that will not open is recorded as `project-review-rules: declared <path> unreadable`, never silently dropped. Do not search parent directories or host skill catalogs. Apply those rules during implementation as a prevention pass, not a PR-comment generation workflow: do not dispatch reviewer subagents from the executor. For Fonts Ninja-style PR review packs, the executor must avoid newly introduced duplicate helper stacks, tautological tests that merely re-call the delegated helper, self-mocking, domain rules in adapters/ports, domain objects outside `domain/`, dead APIs, weak public names, and functions that fail the plain-English read.
|
|
22
22
|
- **Language-agnostic principles that ALWAYS bind (the TDD loop MUST satisfy them):** (1) no self-mocking of the SUT — stub/spy only injected collaborators, never the subject's own methods; (2) behavioral assertions on outcomes (return value, state, persisted rows, events, boundary calls) — never `toHaveBeenCalled*` on an internal helper as the only/primary assertion; (3) truthful names — a `get*` / `find*` that writes/inserts, or a name encoding the caller's use-case (`*ForInit`) or hiding a domain rule (`findValid*`), is a defect; (4) single-purpose functions ≤50 effective lines, plain-English readability. Self-mocking (1) — Enforced by `validators/detect_self_mock.py` (static), which the implementation **verifier** runs; it is never delegated to the executor (`_implementation-verifier.md` §"Self-mock detection"). Naming the enforcement here says who will check your diff, not that you should run the check: the executor's half is satisfying principle (1) in the code it writes, and it MUST NOT invoke the detector or write `<task_root>/qa/self-mock-*.json`. **Enforced:** that sidecar is not among the paths an executor attempt's `writePolicy.artifactPolicy.allowedPaths` carries, so writing it closes an otherwise-passing stage as `error` with `artifact-root change exceeds batch policy union` (`scripts/okstra_ctl/execution_mutation_audit.py`). The sidecar's absence BLOCKS at `validate-run.py` on the verifier's report.
|