okstra 0.172.0 → 0.174.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/docs/architecture/storage-model.md +24 -3
- package/docs/architecture.md +21 -35
- package/docs/cli.md +39 -7
- package/docs/container.md +1 -1
- package/docs/contributor-change-matrix.md +1 -1
- package/docs/performance-improvement-plan-v2.md +6 -5
- package/docs/project-structure-overview.md +33 -25
- package/docs/task-process/README.md +6 -4
- package/docs/task-process/error-analysis.md +2 -2
- package/docs/task-process/final-verification.md +2 -2
- package/docs/task-process/implementation-option-selection.md +70 -0
- package/docs/task-process/implementation-planning.md +24 -16
- package/docs/task-process/requirements-discovery.md +2 -2
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/claude-worker.md +1 -1
- package/runtime/agents/workers/report-writer-worker.md +30 -6
- package/runtime/bin/lib/okstra/cli.sh +5 -1
- package/runtime/bin/lib/okstra/globals.sh +2 -1
- package/runtime/bin/lib/okstra/usage.sh +3 -0
- package/runtime/bin/okstra-provider-exec.py +29 -12
- package/runtime/bin/okstra-trace-cleanup.sh +58 -129
- package/runtime/bin/okstra.sh +2 -0
- package/runtime/prompts/duties/direction-selection-worker.md +44 -0
- package/runtime/prompts/duties/planning-worker.md +12 -4
- package/runtime/prompts/lead/adapters/cmux.md +2 -0
- package/runtime/prompts/lead/context-loader.md +1 -1
- package/runtime/prompts/lead/convergence.md +5 -5
- package/runtime/prompts/lead/okstra-lead-contract.md +7 -6
- package/runtime/prompts/lead/plan-body-verification.md +23 -6
- package/runtime/prompts/lead/report-writer.md +33 -11
- package/runtime/prompts/profiles/_common-contract.md +3 -3
- package/runtime/prompts/profiles/_implementation-deliverable.md +2 -2
- package/runtime/prompts/profiles/_implementation-executor.md +2 -0
- package/runtime/prompts/profiles/_implementation-verifier.md +2 -2
- package/runtime/prompts/profiles/error-analysis.md +4 -4
- package/runtime/prompts/profiles/final-verification.md +3 -3
- package/runtime/prompts/profiles/forbidden-actions.json +7 -0
- package/runtime/prompts/profiles/implementation-option-selection.md +35 -0
- package/runtime/prompts/profiles/implementation-planning.md +61 -46
- package/runtime/prompts/profiles/implementation.md +4 -2
- package/runtime/prompts/profiles/improvement-discovery.md +1 -1
- package/runtime/prompts/profiles/release-handoff.md +1 -1
- package/runtime/prompts/profiles/requirements-discovery.md +3 -3
- package/runtime/prompts/wizard/prompts.ko.json +9 -1
- package/runtime/python/okstra_ctl/adapters/dispatch/__init__.py +1 -6
- package/runtime/python/okstra_ctl/adapters/hosts/external/relay.md +4 -4
- package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +5 -0
- package/runtime/python/okstra_ctl/agent_invocation.py +1 -0
- package/runtime/python/okstra_ctl/analysis_packet.py +6 -0
- package/runtime/python/okstra_ctl/conformance.py +68 -0
- package/runtime/python/okstra_ctl/dispatch_core.py +89 -39
- package/runtime/python/okstra_ctl/dispatch_state.py +142 -14
- package/runtime/python/okstra_ctl/doctor.py +2 -2
- package/runtime/python/okstra_ctl/domain/worker_exec.py +5 -0
- package/runtime/python/okstra_ctl/exact_coverage.py +128 -0
- package/runtime/python/okstra_ctl/final_report_schema.py +5 -4
- package/runtime/python/okstra_ctl/fix_cycles.py +3 -1
- package/runtime/python/okstra_ctl/implementation_direction.py +836 -0
- package/runtime/python/okstra_ctl/implementation_options.py +479 -0
- package/runtime/python/okstra_ctl/pane_reclaim.py +13 -22
- package/runtime/python/okstra_ctl/plan_items.py +51 -3
- package/runtime/python/okstra_ctl/render.py +1 -0
- package/runtime/python/okstra_ctl/render_final_report.py +16 -19
- package/runtime/python/okstra_ctl/report_contract.py +45 -14
- package/runtime/python/okstra_ctl/report_finalize.py +68 -9
- package/runtime/python/okstra_ctl/report_html/render.py +4 -2
- package/runtime/python/okstra_ctl/report_html/router.py +4 -0
- package/runtime/python/okstra_ctl/report_html/view_models/implementation_option_selection.py +32 -0
- package/runtime/python/okstra_ctl/report_html/view_models/implementation_planning.py +25 -10
- package/runtime/python/okstra_ctl/report_views.py +148 -12
- package/runtime/python/okstra_ctl/run.py +393 -4
- package/runtime/python/okstra_ctl/schema_excerpt.py +1 -1
- package/runtime/python/okstra_ctl/scope_provenance.py +16 -10
- package/runtime/python/okstra_ctl/session.py +69 -12
- package/runtime/python/okstra_ctl/team.py +51 -25
- package/runtime/python/okstra_ctl/tmux.py +19 -149
- package/runtime/python/okstra_ctl/user_response.py +75 -0
- package/runtime/python/okstra_ctl/wizard.py +144 -0
- package/runtime/python/okstra_ctl/worker_prompt_policy.py +2 -0
- package/runtime/python/okstra_ctl/worker_request.py +2 -0
- package/runtime/python/okstra_ctl/workflow.py +29 -7
- package/runtime/python/okstra_ctl/worktree.py +69 -3
- package/runtime/python/okstra_token_usage/cli.py +1 -1
- package/runtime/python/okstra_token_usage/collect.py +66 -6
- package/runtime/schemas/final-report-v2.0.schema.json +1428 -137
- package/runtime/skills/okstra-setup/references/project-config.md +11 -0
- package/runtime/templates/reports/final-report-v2.template.md +4 -0
- package/runtime/templates/reports/final-verification-input.template.md +1 -1
- package/runtime/templates/reports/html/base.template.html +3 -2
- package/runtime/templates/reports/html/i18n/en.json +21 -1
- package/runtime/templates/reports/html/i18n/ko.json +21 -1
- package/runtime/templates/reports/html/macros/forms.html +21 -2
- package/runtime/templates/reports/html/tasks/implementation-option-selection.template.html +49 -0
- package/runtime/templates/reports/html/tasks/implementation-planning.template.html +36 -2
- package/runtime/templates/reports/i18n/en.json +13 -0
- package/runtime/templates/reports/implementation-input.template.md +4 -2
- package/runtime/templates/reports/implementation-planning-input.template.md +18 -4
- package/runtime/templates/reports/improvement-discovery-input.template.md +1 -1
- package/runtime/templates/reports/md/tasks/implementation-option-selection.template.md +13 -0
- package/runtime/templates/reports/md/tasks/implementation-planning.template.md +17 -0
- package/runtime/templates/reports/report.js +111 -4
- package/runtime/templates/reports/settings.template.json +0 -24
- package/runtime/templates/reports/task-brief.template.md +9 -3
- package/runtime/templates/reports/user-response.template.md +25 -4
- package/runtime/templates/worker-prompt-preamble.md +8 -0
- package/runtime/validators/lib/fixtures.sh +49 -17
- package/runtime/validators/validate-implementation-plan-stages.py +169 -4
- package/runtime/validators/validate-report-views.py +2 -2
- package/runtime/validators/validate-run.py +149 -498
- package/runtime/validators/validate_improvement_report.py +5 -1
- package/runtime/validators/validate_session_conformance.py +1 -1
- package/src/cli-registry.mjs +8 -1
- package/src/commands/execute/codex-run.mjs +1 -0
- package/src/commands/execute/render-bundle.mjs +1 -0
- package/src/commands/execute/team.mjs +3 -3
- package/src/commands/execute/worktree-status.mjs +109 -0
- package/src/commands/lifecycle/install.mjs +0 -2
- package/src/commands/report/finalize.mjs +13 -6
- package/runtime/bin/okstra-subagent-reclaim.sh +0 -26
- package/runtime/schemas/final-report-v1.0.schema.json +0 -6366
- package/runtime/templates/reports/final-report.template.md +0 -1258
|
@@ -34,6 +34,8 @@ It overrides only the worker-dispatch portion of the selected host relay, not th
|
|
|
34
34
|
| `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Emit the matching `PROGRESS:` line and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
|
|
35
35
|
| `collect_usage` | Collect artifact/CLI-log-backed usage through the existing Okstra token-usage path; never substitute another runtime's session log. |
|
|
36
36
|
|
|
37
|
+
An `implementation` run calls `dispatch_worker` twice: once for the Executor, then — after `await_workers` settles it — once for the verifiers. That second call's `--workers` list must omit the Executor's worker ID: it is materialized as the Executor on every dispatch, so a batch still carrying it is refused again. A verifier started beside the Executor observes base HEAD instead of the stage diff, so a single batch holding both is refused by `scripts/okstra_ctl/dispatch_core.py` `_validate_implementation_phase_order`, `--dry-run` included.
|
|
38
|
+
|
|
37
39
|
## Pane placement is not yours to compute
|
|
38
40
|
|
|
39
41
|
Okstra creates, sizes, labels, and closes every worker pane. Do not issue terminal-multiplexer commands of any kind — not to place a worker, not to resize the lead, not to reclaim a finished round. Pane geometry depends on the display, and a lead that recomputes it per run gets it wrong differently on every host.
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
| `projectId` | Project ID |
|
|
38
38
|
| `taskGroup` | Task group |
|
|
39
39
|
| `taskId` | Task ID |
|
|
40
|
-
| `taskType` | Analysis type (requirements-discovery, error-analysis, implementation-planning, implementation, final-verification, release-handoff, plus the sidetrack improvement-discovery) |
|
|
40
|
+
| `taskType` | Analysis type (requirements-discovery, error-analysis, implementation-option-selection, implementation-planning, implementation, final-verification, release-handoff, plus the sidetrack improvement-discovery) |
|
|
41
41
|
| `workCategory` | bugfix / feature / improvement / refactor / ops / unknown |
|
|
42
42
|
| `recommendedWorkers` | List of selected workers |
|
|
43
43
|
| `currentStatus` | Current task status |
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
## Scope and Terminology (BLOCKING)
|
|
24
24
|
|
|
25
|
-
This contract governs **Phase 5.5 (Convergence loop)** — a *lead operating phase* inside a single okstra run, not a task-type lifecycle phase. It leaves the
|
|
25
|
+
This contract governs **Phase 5.5 (Convergence loop)** — a *lead operating phase* inside a single okstra run, not a task-type lifecycle phase. It leaves the 7 task-type lifecycle phases (`requirements-discovery` → `error-analysis` → `implementation-option-selection` → `implementation-planning` → `implementation` → `final-verification` → `release-handoff`, see [okstra-lead-contract](./okstra-lead-contract.md) "Lifecycle Phase Boundaries") unchanged; the lead operating phases (Phase 1 Intake → Phase 7 Persist, see [okstra-lead-contract](./okstra-lead-contract.md) "Quick Reference") drive a *single* task-type run.
|
|
26
26
|
|
|
27
27
|
**`contested` is a final classification only.** It is NEVER an intermediate queue label. The verification queue carries findings that are *unique to a single worker* (entered in Round 0) or *mixed/unresolved after a re-verification round* (carried forward). The `contested` label is assigned only when the **last executed round** completes and the queue is still non-empty.
|
|
28
28
|
|
|
@@ -48,7 +48,7 @@ Configure this in the `convergence` block of `task-manifest.json`. If the block
|
|
|
48
48
|
| `enabled` | `true` | If `false`, skip the convergence loop and use the existing consensus/divergence method |
|
|
49
49
|
| `maxRounds` | phase-aware: `1` for `requirements-discovery`, `2` otherwise (range 1–3) | Maximum number of re-verification rounds. Discovery's routing/missing-input outputs gain little from a second round; other phases (especially `error-analysis`) keep `2`. Lead resolves the effective value when the manifest omits the key and records it in `config.effectiveMaxRounds` of the convergence state artifact. |
|
|
50
50
|
| `verificationMode` | `"lightweight"` | `"lightweight"` or `"full-reanalysis"` |
|
|
51
|
-
| `adversarial` | phase-aware: `true` for `requirements-discovery` / `error-analysis` / `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. |
|
|
51
|
+
| `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. |
|
|
52
52
|
|
|
53
53
|
**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](./plan-body-verification.md)), 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.
|
|
54
54
|
|
|
@@ -160,7 +160,7 @@ Use each finding as a guide but reanalyze the original code/data yourself. High
|
|
|
160
160
|
|
|
161
161
|
## Adversarial Verification Mode
|
|
162
162
|
|
|
163
|
-
Active only when `config.adversarial == true` (default for `requirements-discovery`, `error-analysis`, `implementation-planning`, `project-analysis`, `feature-analysis`, and `change-impact-analysis`; see §"Configuration"); when `false`, every rule in this section is inert and the collaborative behaviour elsewhere in this contract applies unchanged. In adversarial mode the verifier's job inverts: instead of confirming a peer's finding, the verifier **tries to break it**, and the burden of proof sits on the claim — a finding survives only if refutation attempts fail.
|
|
163
|
+
Active only when `config.adversarial == true` (default for `requirements-discovery`, `error-analysis`, `implementation-option-selection`, `implementation-planning`, `project-analysis`, `feature-analysis`, and `change-impact-analysis`; see §"Configuration"); when `false`, every rule in this section is inert and the collaborative behaviour elsewhere in this contract applies unchanged. In adversarial mode the verifier's job inverts: instead of confirming a peer's finding, the verifier **tries to break it**, and the burden of proof sits on the claim — a finding survives only if refutation attempts fail.
|
|
164
164
|
|
|
165
165
|
### Read-only analysis task contract
|
|
166
166
|
|
|
@@ -361,7 +361,7 @@ Lightweight reverify does not require the original `analysis-packet.md`, `analys
|
|
|
361
361
|
- **Lightweight mode**: the clause directly contradicts the "Do NOT re-analyze the original source materials" instruction below. Including it forces workers to re-read the entire instruction-set per round per worker (3 workers × 2 rounds × 5+ files in the worst case) for no quality gain.
|
|
362
362
|
- **Full-reanalysis mode**: workers DO need to re-read source materials, but only the analysis-worker file list (no `final-report-template.md`). If lead chooses to inject a reading clause here, it MUST mirror the audience-scoped enumeration in [okstra-lead-contract](./okstra-lead-contract.md) Phase 2 (no template).
|
|
363
363
|
|
|
364
|
-
This is the single largest avoidable cost in `requirements-discovery`, `error-analysis`, and `implementation-planning` runs. Treat as mandatory.
|
|
364
|
+
This is the single largest avoidable cost in `requirements-discovery`, `error-analysis`, `implementation-option-selection`, and `implementation-planning` runs. Treat as mandatory.
|
|
365
365
|
|
|
366
366
|
### Lightweight Re-verification Prompt
|
|
367
367
|
|
|
@@ -565,7 +565,7 @@ Save it to `runs/<task-type>/state/convergence-<task-type>-<seq>.json`.
|
|
|
565
565
|
Schema rules:
|
|
566
566
|
|
|
567
567
|
- `schemaVersion`: literal string `"1.3"` for all new runs — both adversarial and collaborative. Historical readers accept `"1.0"` / `"1.1"` / `"1.2"` unchanged and never rewrite those artifacts during validation. v1.3 adds the strict coverage-critic ledger and rejects unknown top-level fields; work-state remains v1.0.
|
|
568
|
-
- `config.adversarial`: boolean. `true` when this run used adversarial verification (default for `requirements-discovery` / `error-analysis` / `implementation-planning` / `project-analysis` / `feature-analysis` / `change-impact-analysis`). When `true`, `config.verificationMode` is `"full-reanalysis"` (scoped) and every `disagree` vote carries a non-null `disagreeBasis`.
|
|
568
|
+
- `config.adversarial`: boolean. `true` when this run used adversarial verification (default for `requirements-discovery` / `error-analysis` / `implementation-option-selection` / `implementation-planning` / `project-analysis` / `feature-analysis` / `change-impact-analysis`). When `true`, `config.verificationMode` is `"full-reanalysis"` (scoped) and every `disagree` vote carries a non-null `disagreeBasis`.
|
|
569
569
|
- `config.effectiveMaxRounds`: the integer the lead actually used after resolving the phase-aware default (`1` for `requirements-discovery`, `2` otherwise). MUST equal `config.maxRounds` when the manifest explicitly set it.
|
|
570
570
|
- `findings[].ticketIds`: array of ticket keys from Phase 4 grouping (parsed per the Round 0 step 5 rule). It is empty when the phase does not require ticket tagging; `"unknown"` is not a ticket key and must not be synthesized.
|
|
571
571
|
- `findings[].rounds[].votes.<worker>.verdict`: enum, one of `agree | disagree | supplement | verification-error`. Lower-case tokens; map upper-case AGREE/DISAGREE/SUPPLEMENT verdicts emitted by workers to their lower-case form and map the input alias `unverifiable` to persisted `verification-error`. The latter represents either a terminal non-result dispatch or a completed dispatch that could not verify a particular finding (§"Worker failure handling in reverify"). Every vote has a non-empty `explanation`.
|
|
@@ -39,7 +39,7 @@ Read-side inspection (`/okstra-inspect`) and scheduling (`/okstra-schedule-gen`)
|
|
|
39
39
|
| 5. Completion wait | Call `await_workers` and verify terminal state plus required artifacts | selected runtime adapter + `team-contract` |
|
|
40
40
|
| 5.5 Convergence | Semantically group findings, then drive deterministic state transitions through `ConvergenceEngine` via `okstra convergence` | `convergence` |
|
|
41
41
|
| 5.6 Critic pass | (opt-in) fresh one-shot critic pass through `redispatch_worker`: coverage gaps (discovery/error-analysis/impl-planning) or acceptance devil's-advocate (final-verification). The critic dispatch fires concurrently with the first 5.5 reverify round (its input is fixed at Round 0); gap/blocker verification (one round) completes here | `convergence` "Coverage critic pass" / "Acceptance critic pass" |
|
|
42
|
-
| 6. Synthesis | Dispatch Report writer worker, review draft. **For `implementation-planning`: then run the Phase 6 plan-body verification sub-step (see Phase 6 section below)
|
|
42
|
+
| 6. Synthesis | Dispatch Report writer worker, review draft. **For `implementation-planning`: then run the Phase 6 plan-body verification sub-step (see Phase 6 section below). Selected-direction plans verify `P-Dir-1`; legacy plans retain `P-Opt-*`.** | `report-writer` + `plan-body-verification` (sub-step) |
|
|
43
43
|
| 7. Persist | Call `collect_usage`, update manifests, run the cleanup approval gate, then call `shutdown_workers` only on approval | selected runtime adapter + `report-writer` + this contract |
|
|
44
44
|
|
|
45
45
|
## Core operating contract
|
|
@@ -60,6 +60,7 @@ A single okstra run executes **exactly one** lifecycle phase. The phase is given
|
|
|
60
60
|
|-----------------|-----------------|-------------------|
|
|
61
61
|
| `requirements-discovery` | classification, routing decision, missing-input list, next-phase recommendation | code edits, plan documents, build/test execution that mutates state |
|
|
62
62
|
| `error-analysis` | evidence, root-cause hypotheses, reproduction gaps, validation paths | code edits, implementation design, build/migration/deploy execution |
|
|
63
|
+
| `implementation-option-selection` | candidate comparison, counterevidence, criterion scores, requirement mappings, rejected-candidate audit | code edits, tests/builds, detailed file lists, stage maps, execution commands, plan approval |
|
|
63
64
|
| `implementation-planning` | option matrix, trade-offs, dependencies, recommended order, validation/rollback strategy, Tier3 conformance scripts + manifest under the task-root `qa/` tree, **explicit user-approval request** | source code edits, file writes outside the run's `reports/`, `prompts/`, `state/`, `manifests/`, `worker-results/`, `status/`, `sessions/` directories and the task-root `qa/` tree, build/migration/deploy execution |
|
|
64
65
|
| `implementation` | code edits authorised by an approved plan, accompanying tests | starting work without an approved `implementation-planning` final report carried in via `--clarification-response` or referenced in the brief |
|
|
65
66
|
| `final-verification` | acceptance verdict, residual risk, regression notes; read-only execution of existing test/validation commands, run-artifact writes (qa result sidecars, `okstra handoff record-verified` on acceptance), and qaEnv-replica-only conformance runs are permitted | source code edits, refactors, scope expansion, mutations of the project or shared environments |
|
|
@@ -180,7 +181,7 @@ For `--task-type implementation` runs, the task bundle additionally pins one of
|
|
|
180
181
|
- `instruction-set/analysis-profile.md` — top "Executor binding" block (provider, display name, model, runner, and dispatch mode)
|
|
181
182
|
- `runs/implementation/manifests/run-manifest-*.json` — `teamContract.executor` object (the same binding plus `appliesTo: "implementation"`)
|
|
182
183
|
|
|
183
|
-
Lead MUST dispatch Edit/Write-bearing work only through that executor binding: use the host primitive with `hostModelValue` for `runner=native-session`, or `okstra worker-dispatch` with `modelExecutionValue` for `runner=cli-wrapper`. The other
|
|
184
|
+
Lead MUST dispatch Edit/Write-bearing work only through that executor binding: use the host primitive with `hostModelValue` for `runner=native-session`, or `okstra worker-dispatch` with `modelExecutionValue` for `runner=cli-wrapper`. The other providers in the roster still run as read-only verifiers in the same run; the executor's own provider does not, because its worker ID materializes as the executor on every dispatch — so the diff is reviewed context-isolated by the remaining verifiers. Session isolation is the primary self-review safeguard — a verifier reusing the executor's model variant is acceptable in a distinct session. A different model variant (e.g. executor=opus / Claude verifier=sonnet) is recommended but not mandatory.
|
|
184
185
|
|
|
185
186
|
Executor is chosen at run-prep time via `--executor <claude|codex|antigravity>` (or `OKSTRA_DEFAULT_EXECUTOR`, fallback `claude`); the model used by the executor is taken from the corresponding worker model flag (`--claude-model` / `--codex-model` / `--antigravity-model`). For CLI-backed executors, the underlying file mutation happens inside the executor CLI's own auto-edit mode (e.g. `codex exec --sandbox workspace-write`), not through the lead runtime's `write_artifact` operation.
|
|
186
187
|
|
|
@@ -188,7 +189,7 @@ Executor is chosen at run-prep time via `--executor <claude|codex|antigravity>`
|
|
|
188
189
|
|
|
189
190
|
`okstra-ctl` provisions dedicated `git worktree`s at run-prep time. Lead, the Executor, and every verifier MUST treat the provisioned worktree as the canonical working directory regardless of task-type.
|
|
190
191
|
|
|
191
|
-
- **Task-key worktree (non-`implementation` phases):** `requirements-discovery`, `error-analysis`, and `implementation-planning` share one worktree per task-key so phase N inherits the working-tree state phase N-1 left behind. Location: `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` (override `OKSTRA_HOME` only for tests). All segments are sanitised — `/`, `:`, and other special chars collapse to `-`.
|
|
192
|
+
- **Task-key worktree (non-`implementation` phases):** `requirements-discovery`, `error-analysis`, `implementation-option-selection`, and `implementation-planning` share one worktree per task-key so phase N inherits the working-tree state phase N-1 left behind. Location: `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` (override `OKSTRA_HOME` only for tests). All segments are sanitised — `/`, `:`, and other special chars collapse to `-`.
|
|
192
193
|
- **Stage worktree (`implementation`):** stage-isolated — one run = one stage, each in its own worktree at `.../<task-id-segment>/stage-<N>/` on its own branch. Single-stage `final-verification` (`--stage <N>`) reuses that stage worktree read-only; whole-task `final-verification` operates on the task-key worktree.
|
|
193
194
|
- Branch: `<work-category-namespace>/<task-id-segment>` (e.g. `feature/dev-9436`, `fix/dev-7311`); a stage worktree appends `-s<N>` (e.g. `feature/dev-9436-s2`). The task-key worktree is branched from the user-chosen `--base-ref` (default: `HEAD` of the repo's **main** worktree) at the first phase's prep time; a stage worktree's base is resolved from its `depends-on` anchors at prep time. The resolved base SHA is recorded in `EXECUTOR_WORKTREE_BASE_REF`.
|
|
194
195
|
- A global registry at `~/.okstra/worktrees/registry.json` (flock-guarded) reserves both task-keys and stage-keys (`<task-key>#stage-<N>`), mapping each to its path + branch, and prevents concurrent runs from colliding. Branch names are globally unique on this machine.
|
|
@@ -232,7 +233,7 @@ The `implementation` profile's thin core (`prompts/profiles/implementation.md`)
|
|
|
232
233
|
|
|
233
234
|
The guard is not satisfied by memory from a prior run — each implementation run re-reads the sidecar fresh, since `okstra install` may have updated it between runs.
|
|
234
235
|
|
|
235
|
-
This pattern is implementation-only. Other profiles (`requirements-discovery`, `error-analysis`, `implementation-planning`, `final-verification`, `release-handoff`) load their whole profile body at Phase 1 as before — they are short enough not to benefit from a split.
|
|
236
|
+
This pattern is implementation-only. Other profiles (`requirements-discovery`, `error-analysis`, `implementation-option-selection`, `implementation-planning`, `final-verification`, `release-handoff`) load their whole profile body at Phase 1 as before — they are short enough not to benefit from a split.
|
|
236
237
|
|
|
237
238
|
Extract from the compact intake files: task key, task type, work category, workflow lifecycle snapshot, selected worker roster, assigned models, worker result paths, worker prompt history paths, current run prompt directory, final report path, final status path, validator path, resume helper path, config-file references, deployment-manifest references, and their expected values or invariants.
|
|
238
239
|
|
|
@@ -330,7 +331,7 @@ Convergence is enabled by default. Configure via task-manifest.json:
|
|
|
330
331
|
- `convergence.enabled`: true/false (default: true)
|
|
331
332
|
- `convergence.maxRounds`: 1–3 — **phase-aware default**: `1` for `requirements-discovery`, `2` for all other task types
|
|
332
333
|
- `convergence.verificationMode`: `"lightweight"` | `"full-reanalysis"` (default: `"lightweight"`; the adversarial phases below force `"full-reanalysis"`)
|
|
333
|
-
- `convergence.adversarial`: true/false — **phase-aware default**: `true` for `requirements-discovery` / `error-analysis` / `implementation-planning` / `project-analysis` / `feature-analysis` / `change-impact-analysis`, `false` otherwise. When `true`, Phase 5.5 runs in adversarial mode (verifiers refute findings; burden of proof on the claim). See [convergence](./convergence.md) "Adversarial Verification Mode".
|
|
334
|
+
- `convergence.adversarial`: true/false — **phase-aware default**: `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 (verifiers refute findings; burden of proof on the claim). See [convergence](./convergence.md) "Adversarial Verification Mode".
|
|
334
335
|
|
|
335
336
|
When `task-manifest.json` does not set `convergence.maxRounds`, lead MUST resolve the effective value via the phase-aware default above before entering Phase 5.5 and put it in the grouped input at `config.effectiveMaxRounds`.
|
|
336
337
|
|
|
@@ -377,7 +378,7 @@ After the Report writer worker draft is reviewed (or after the lead-authored fal
|
|
|
377
378
|
|
|
378
379
|
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.
|
|
379
380
|
|
|
380
|
-
**REQUIRED RESOURCE:** Read [plan-body-verification](./plan-body-verification.md) for the round protocol, plan-item ID scheme (`P-Opt-*`
|
|
381
|
+
**REQUIRED RESOURCE:** Read [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 the state-file schema at `runs/<task-type>/state/plan-body-verification.json`. For `P-Dir-1`, compare `directionRealization` with `selectedDirectionRef` and its snapshot: verify the core mechanism, architecture boundaries, planning invariants, and any hidden direction change.
|
|
381
382
|
|
|
382
383
|
Distinct from Phase 5.5 finding convergence:
|
|
383
384
|
|
|
@@ -53,7 +53,7 @@ The shared Majority definition and the auto-disable rule (fewer than 2 analyser
|
|
|
53
53
|
|
|
54
54
|
## Plan-item extraction (Round 0 equivalent)
|
|
55
55
|
|
|
56
|
-
From the report-writer's draft of `## 5.4 Implementation Plan Deliverables`, the lead creates the verification queue only through this sequence (see also `templates/reports/final-report.template.md` §5.5.9):
|
|
56
|
+
From the report-writer's draft of `## 5.4 Implementation Plan Deliverables`, the lead creates the verification queue only through this sequence (see also `templates/reports/final-report-v2.template.md` §5.5.9):
|
|
57
57
|
|
|
58
58
|
```text
|
|
59
59
|
okstra plan-items extract --data <data.json> --output <state>/plan-items-....json
|
|
@@ -67,11 +67,26 @@ as its heading, but it MUST include the lossless `payload` for the item's eviden
|
|
|
67
67
|
judgement. The final `validate` command confirms that the persisted queue exactly matches
|
|
68
68
|
the current draft before verdict aggregation.
|
|
69
69
|
|
|
70
|
-
The deterministic extractor assigns the
|
|
70
|
+
The deterministic extractor assigns one contract-specific direction prefix, followed by the shared execution prefixes.
|
|
71
|
+
|
|
72
|
+
### Legacy candidate-comparison branch
|
|
73
|
+
|
|
74
|
+
| ID | Source | Payload |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| `P-Opt-<N>` | `4.5.1 Option Candidates` | one Option (its File Structure list + interfaces + blast radius); verify its trade-off claims and consistency with the recommended option |
|
|
77
|
+
|
|
78
|
+
### Selected-direction branch
|
|
79
|
+
|
|
80
|
+
| ID | Source | Payload |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| `P-Dir-1` | `implementationPlanning.directionRealization` | exactly one selected-direction realization; compare it with `selectedDirectionRef` and the byte-verified snapshot |
|
|
83
|
+
|
|
84
|
+
`P-Dir-1` verifies the core mechanism, architecture boundaries, planning invariants, and any hidden direction change. An AGREE verdict means `directionRealization` preserves those properties from the snapshot named by `selectedDirectionRef`; it does not re-score candidates or recommend another direction. A required direction change is a `direction-invalidated` result, not a planner rewrite.
|
|
85
|
+
|
|
86
|
+
### Shared execution items
|
|
71
87
|
|
|
72
88
|
| Prefix | Source sub-section | One row per |
|
|
73
89
|
|--------|--------------------|-------------|
|
|
74
|
-
| `P-Opt-<N>` | `4.5.1 Option Candidates` | one Option (its File Structure list + interfaces + blast radius) |
|
|
75
90
|
| `P-Step-<N>` | `4.5.4 Stepwise Execution Order` | one step (path + command + success signal) |
|
|
76
91
|
| `P-Dep-<N>` | `4.5.5 Dependency / Migration Risk` | one dependency row |
|
|
77
92
|
| `P-Val-<N>` | `4.5.6 Validation Checklist` | one checklist item |
|
|
@@ -80,7 +95,7 @@ The deterministic extractor assigns the following prefixes:
|
|
|
80
95
|
| `P-Prep-S<stage>-<kind>` | Stage `designSurfaceCoverage` + `5.5.10 Implementation Design Preparation` | exactly one detector-produced `(stage, kind)` |
|
|
81
96
|
| `P-Var-<N>` | `5.5.11 Variation-Point Analysis` | one variation point (its `behavior` + `extractionDecision`), or a lone `P-Var-0` when the plan declares no variation point |
|
|
82
97
|
|
|
83
|
-
`4.5.2 Trade-off Matrix` and `4.5.3 Recommended Option` are NOT extracted as standalone plan items — the trade-off matrix is evaluated implicitly through each option's `P-Opt-*` verification, and the recommended option is one of those `P-Opt-*` rows.
|
|
98
|
+
For legacy candidate-comparison plans, `4.5.2 Trade-off Matrix` and `4.5.3 Recommended Option` are NOT extracted as standalone plan items — the trade-off matrix is evaluated implicitly through each option's `P-Opt-*` verification, and the recommended option is one of those `P-Opt-*` rows. Selected-direction plans contain neither section and use only `P-Dir-1` for direction preservation.
|
|
84
99
|
|
|
85
100
|
Each plan item inherits the `[TICKETID: ...]` tag of its source section (per the standard ticket-tagging contract).
|
|
86
101
|
|
|
@@ -109,7 +124,7 @@ The verdict tokens `AGREE` / `DISAGREE` / `SUPPLEMENT` are reused, but their mea
|
|
|
109
124
|
`P-Prep-S<stage>-<kind>` applies the same verdict tokens and adds these disposition checks:
|
|
110
125
|
|
|
111
126
|
- `inline-contract`: AGREE only when the contract contains the kind-specific fields needed to implement the stage; a label or generic prose is insufficient.
|
|
112
|
-
- `prep-item`: AGREE only when every referenced PREP item has a concrete `aiProposal`, correct `stageRefs`/`kind`, and state-specific safeguards required by `schemas/final-report-
|
|
127
|
+
- `prep-item`: AGREE only when every referenced PREP item has a concrete `aiProposal`, correct `stageRefs`/`kind`, and state-specific safeguards required by `schemas/final-report-v2.0.schema.json`.
|
|
113
128
|
- `not-applicable`: AGREE only when the rationale is consistent with the stage action; otherwise DISAGREE with `fixability` (`planner-fixable` when the plan can supply the missing contract, `needs-user-input` only for genuinely external facts).
|
|
114
129
|
- A declared `blocked` item is not itself a plan-body failure. Missing or duplicate coverage, an empty proposal, a mismatched reference, or an unjustified disposition is a failure and receives `DISAGREE(<kind>)` with `fixability`.
|
|
115
130
|
|
|
@@ -123,6 +138,8 @@ DISAGREE on a `P-Var-*` item means one of:
|
|
|
123
138
|
|
|
124
139
|
The hexagonal rule that an extracted point must declare `interfaceKind: "port"` is already machine-checked by `validators/validate-run.py` `_validate_variation_point_analysis` (it fires only for a project whose `architecture.style` is `hexagonal`). Do not re-run that mechanical check as a verdict; spend the judgement on placement and semantics instead — a point extracted as a port whose domain rule leaked into the adapter passes the validator and is still wrong.
|
|
125
140
|
|
|
141
|
+
`P-Dir-1` carries the same YAGNI judgement as the legacy option item, but its comparison source is the selected-direction snapshot rather than a trade-off matrix. A new abstraction, configuration knob, widened interface, file, or stage with no original-requirement link is a hidden direction change and receives `DISAGREE(e)` on `P-Dir-1`.
|
|
142
|
+
|
|
126
143
|
`P-Opt-<N>` carries the **YAGNI judgement** and is majority-gated for the same reason as `P-Var-*`: whether an abstraction serves the stated requirement or only a forecast is a judgement about the design, not a contradiction between two spelled-out references. Raise it as `DISAGREE(e)` — an option that carries an abstraction, parameter, or configuration knob no Requirement Coverage row demands contradicts the trade-off matrix that scored it, because the complexity the matrix priced is not the complexity the option actually buys. DISAGREE on a `P-Opt-*` item under this rule means one of:
|
|
127
144
|
|
|
128
145
|
- **an abstraction nobody asked for** — a helper module, strategy / factory, indirection layer, or interface whose only justification in the plan is a caller no requirement names. A second implementation already on the table is `P-Var-*` territory and is the opposite defect: do not raise both on the same behavior;
|
|
@@ -237,7 +254,7 @@ round before any host or provider process starts.
|
|
|
237
254
|
|
|
238
255
|
**How the corrective round is recorded.** The first prompt was dispatched, so it is immutable — `--replace-undispatched` refuses it, correctly. Materialize the correction under a NEW `--invocation-id` and a new prompt path. Before linking its result, retire the first attempt's link: `okstra agent-prompt reject-result --run-manifest <path> --dispatch-id <first dispatch id> --superseded-by <corrective dispatch id> --reason "<what was wrong with the returned result>"`. Without that step the corrective `link-result` fails with `agent result is already linked to another dispatch`, which is how a worker that ran for twenty minutes and wrote a good result ends up unrecordable. Nothing is deleted: the rejected link stays in `agentResultLinks` carrying `supersededBy` and `rejectionReason`, so the ledger shows both attempts and why the second exists.
|
|
239
256
|
|
|
240
|
-
Then lead writes `runs/<task-type>/state/plan-body-verification-<task-type>-<seq>.json` (schema below), **appending this round** — one new `roundHistory[]` entry plus this round's votes on each verified item's `planItems[].rounds[]`. The file accumulates across rounds; it is never truncated to the latest one. After `okstra plan-verify` exits 0, lead sets that new round's `completedAt` to the current ISO 8601 UTC time exactly once; a prior round's `completedAt` is immutable. Lead then populates `### 5.5.9 Plan Body Verification` in the final report's data.json (`implementationPlanning.planBodyVerification`, schema `schemas/final-report-
|
|
257
|
+
Then lead writes `runs/<task-type>/state/plan-body-verification-<task-type>-<seq>.json` (schema below), **appending this round** — one new `roundHistory[]` entry plus this round's votes on each verified item's `planItems[].rounds[]`. The file accumulates across rounds; it is never truncated to the latest one. After `okstra plan-verify` exits 0, lead sets that new round's `completedAt` to the current ISO 8601 UTC time exactly once; a prior round's `completedAt` is immutable. Lead then populates `### 5.5.9 Plan Body Verification` in the final report's data.json (`implementationPlanning.planBodyVerification`, schema `schemas/final-report-v2.0.schema.json`; template at `templates/reports/final-report-v2.template.md`). The §5.5.9 body is **grouped by plan item**: `planItems[]`, each carrying its `id`, its plain-language `subject` (rendered as the item heading), an optional `sourceSection`, an optional `clarificationId` (the `C-<N>` this item blocks on when `majority-disagree`), and a `verdicts[]` list (`worker / verdict / breakageKind / note`) — one verdict row per worker under that item. The renderer prints three fixed legends (gate values, verdict tokens, breakage kinds a–f) so the reader can decode every cell without opening this spec. The older flat `#### Verdict details` table (`Plan item / Worker / …`, one row per plan-item × worker pair) is superseded by the grouped layout — it hid *what* each vote was about behind a bare `P-*` ID; the subject heading is the fix. The validator's `Plan Body Verification` + `Gate result:` substring checks still gate this section.
|
|
241
258
|
7. **Self-fix loop (one rewrite, targeting planner-fixable defects).** After round 1, lead may run one report-writer rewrite when at least one `majority-disagree` item has a majority of its `DISAGREE` verdicts at `fixability == planner-fixable`. The targeted re-verification after that rewrite is round 2. After round 2, stop automatic self-fix regardless of outcome. Classify every remaining item as `user-decision`, `noncritical-dissent`, or `correctness-critical`. A second automatic self-fix is a contract violation. The fixed order is initial verification → one planner self-fix → targeted re-verification → user gate.
|
|
242
259
|
- **Group the targets by cause before instructing (BLOCKING).** Blocked items are usually several derivatives of one defect — one constant declared twice, one responsibility given two owners — and the coverage rows that cite them fail as a consequence, not independently. Lead MUST partition this round's targets into cause groups and instruct each group as **"remove this cause"**, naming the derivatives it accounts for. **Handing report-writer a bare item list is forbidden**: patched one at a time, each correction leaves the sibling sections still asserting the old value, so the next round re-finds the same family and the budget drains without converging. Record the partition in `planBodyVerification.selfFixGroups[]` (`round`, `causeSummary`, `itemIds`). One group per item is a legitimate outcome only when the items genuinely share no cause — recorded that way, it is a visible diagnosis rather than a skipped one. **Enforced:** `validators/validate-run.py` `_validate_self_fix_grouping` requires the partition, ties `selfFixRoundsApplied` to the highest recorded round, and fails any corrected item that belongs to no group.
|
|
243
260
|
- lead instructs report-writer to rewrite the items in each cause group (NOT a full draft regeneration; procedure in [report-writer](./report-writer.md) §"Self-fix rewrite").
|
|
@@ -8,7 +8,15 @@ The JSON SSOT path is `runs/<task-type>/reports/final-report-<task-type>-<seq>.d
|
|
|
8
8
|
|
|
9
9
|
New bundles use `schemas/final-report-v2.0.schema.json`. The Markdown keeps verdict, routing, evidence, one structured task deliverable, and audit data for the next agent. The HTML uses `humanSummary`, task `userNarrative`, and structured facts for the user. Raw worker discussion, convergence mechanics, and usage belong to audit structures and never to the HTML human main body.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
### Implementation-planning frontmatter contract
|
|
12
|
+
|
|
13
|
+
#### Selected-direction
|
|
14
|
+
|
|
15
|
+
Emit `frontmatter.approved` as `false` and copy `implementationPlanning.selectedDirectionRef.snapshotPath` into `frontmatter.selectedDirectionRef`. You MUST omit `frontmatter.implementationOption`; the direction was selected upstream and cannot be selected again in planning. `schemas/final-report-v2.0.schema.json` enforces the required selected-direction reference and rejects an `implementationOption` property for this branch.
|
|
16
|
+
|
|
17
|
+
#### Legacy candidate-comparison
|
|
18
|
+
|
|
19
|
+
Emit `frontmatter.approved` as `false` and `frontmatter.implementationOption` as the empty string `""`. The user later flips `approved` to `true` and fills `implementationOption` with the chosen Option Candidate name to authorise and scope the next `implementation` run. Every other report type follows the same empty `implementationOption` default; the schema's non-selected-direction branch requires that field and rejects a selected-direction reference.
|
|
12
20
|
|
|
13
21
|
**As the report-writer worker:** YOU write the data.json and invoke the renderer; the files on disk are the canonical record, so do not return either artifact inline.
|
|
14
22
|
|
|
@@ -131,7 +139,7 @@ The steps it executes, in this contractual order, and the contract each one carr
|
|
|
131
139
|
|
|
132
140
|
Output (idempotent — re-running overwrites):
|
|
133
141
|
- `runs/<task-type>/reports/final-report-<task-type>-<seq>.html` — single-file self-contained human view, always generated for schema v2 from the dedicated template registered for that task type. Clarification rows with `Status` ∈ {`open`, `answered`} embed response controls and export a `user-response-<task-type>-<seq>.md` sidecar. The original data and Markdown artifacts are never mutated by user input.
|
|
134
|
-
- the implementation-planning report renders a **Plan Approval** section at the end of the body
|
|
142
|
+
- the implementation-planning report renders a **Plan Approval** section at the end of the body — an implementation-option `<select>` plus approval checkbox for legacy candidate-comparison, and an approval checkbox only for selected-direction plans. It stays disabled while any §1 `Blocks: approval` row is unresolved.
|
|
135
143
|
- Schema-v1 and quick compatibility reports retain the legacy conditional HTML path; this does not change the schema-v2 always-generated contract.
|
|
136
144
|
|
|
137
145
|
It runs after usage collection so token placeholders are substituted in any rendered html, and before routing persistence so the html artifact, when generated, exists for the validator step that checks it. It also overlays the translation sidecar, which is why a non-English run must dispatch the translator before this command — see the ordering rule above.
|
|
@@ -253,17 +261,17 @@ For those v1 reports, the final report must contain section headings whose **lin
|
|
|
253
261
|
| 7 | `Validation Checklist` | `### Validation Checklist (Korean gloss)` |
|
|
254
262
|
| 8 | `Rollback` | `### Rollback Strategy (Korean gloss)` |
|
|
255
263
|
| 9 | `Requirement Coverage` | `### Requirement Coverage (Korean gloss)` |
|
|
256
|
-
| 10 | `Plan Body Verification` + `Gate result:` | `### Plan Body Verification (Korean gloss)` containing a `Gate result:` line — copy `templates/reports/final-report.template.md §5.5.9` verbatim. Validator checks both substrings. |
|
|
264
|
+
| 10 | `Plan Body Verification` + `Gate result:` | `### Plan Body Verification (Korean gloss)` containing a `Gate result:` line — copy `templates/reports/final-report-v2.template.md §5.5.9` verbatim. Validator checks both substrings. |
|
|
257
265
|
| 11 | `Cross-Project Dependencies` | `### Cross-Project Dependencies (Korean gloss)` — `_(none)_` when the plan is single-project. |
|
|
258
266
|
| 12 | `Decision Drafts` | `### Decision Drafts (Korean gloss)` |
|
|
259
267
|
|
|
260
268
|
**Never author a `User Approval Request` section.** The approval gate moved to the YAML frontmatter `approved: true|false` field, and `validators/validate-run.py` fails any report containing a `## User Approval Request` block or a `### 5.5.8 User Approval Request` stub. This paragraph replaces an earlier row that listed the heading as required — following it produced a report the validator rejected.
|
|
261
269
|
|
|
262
|
-
`Implementation Design Preparation` is NOT in the substring list: `templates/reports/final-report.template.md` §5.5.10 renders that heading from `implementationPlanning.designPreparation`, so it is enforced by the schema + renderer rather than by a heading scan.
|
|
270
|
+
`Implementation Design Preparation` is NOT in the substring list: `templates/reports/final-report-v2.template.md` §5.5.10 renders that heading from `implementationPlanning.designPreparation`, so it is enforced by the schema + renderer rather than by a heading scan.
|
|
263
271
|
|
|
264
272
|
The English keyword is mandatory and the body of each section is written in English, like everything else you author — see "Writing Guidelines" below. For non-`implementation-planning` runs, omit this entire block — these headings are NOT validator-checked for other task-types.
|
|
265
273
|
|
|
266
|
-
The final-report template `templates/reports/final-report.template.md` Section 5.5 already encodes this contract — copy that block verbatim and fill in.
|
|
274
|
+
The final-report template `templates/reports/final-report-v2.template.md` Section 5.5 already encodes this contract — copy that block verbatim and fill in.
|
|
267
275
|
|
|
268
276
|
### Self-fix rewrite (plan-body self-fix round)
|
|
269
277
|
|
|
@@ -293,11 +301,11 @@ When the run's `task-type` is `final-verification`, the report's `## 7. Final Ve
|
|
|
293
301
|
|---|--------------------|---------|
|
|
294
302
|
| 1 | `accepted` | All acceptance criteria pass; `release-handoff` may proceed. |
|
|
295
303
|
| 2 | `conditional-accept` | Acceptance passes with caveats; user must resolve listed conditions before `release-handoff`. |
|
|
296
|
-
| 3 | `blocked` | Acceptance failed; routing returns to `error-analysis` or `implementation-planning
|
|
304
|
+
| 3 | `blocked` | Acceptance failed; routing returns to `error-analysis`, `implementation-option-selection`, or `implementation-planning` according to whether the cause, direction, or detailed plan failed. |
|
|
297
305
|
|
|
298
306
|
For every other task-type, set the `Verdict Token` cell to `not-applicable`. Do NOT omit the row — the template renders it for all task-types and downstream tooling expects the field to exist.
|
|
299
307
|
|
|
300
|
-
The final-report template `templates/reports/final-report.template.md` Section 7 already encodes this contract — copy that block verbatim and fill in.
|
|
308
|
+
The final-report template `templates/reports/final-report-v2.template.md` Section 7 already encodes this contract — copy that block verbatim and fill in.
|
|
301
309
|
|
|
302
310
|
### Release-handoff section contract (release-handoff runs only)
|
|
303
311
|
|
|
@@ -305,7 +313,7 @@ When the run's `task-type` is `release-handoff`, the final report MUST include S
|
|
|
305
313
|
|
|
306
314
|
**Single-lead authorship (release-handoff only):** release-handoff has no worker roster. The lead authors the final-report file directly — there is no `Report writer worker` dispatch to perform in Phase 6, no resume-safe dispatch concern, and no mandatory worker-results file for a report-writer role. The rest of this contract's dispatch / resume / fallback machinery applies ONLY when `Report writer worker` is in the roster (i.e. every task-type other than `release-handoff`).
|
|
307
315
|
|
|
308
|
-
The final-report template `templates/reports/final-report.template.md` Section 5.6 already encodes this contract — copy that block verbatim and fill in. For non-`release-handoff` runs, omit Section 5.6 entirely.
|
|
316
|
+
The final-report template `templates/reports/final-report-v2.template.md` Section 5.6 already encodes this contract — copy that block verbatim and fill in. For non-`release-handoff` runs, omit Section 5.6 entirely.
|
|
309
317
|
|
|
310
318
|
### Mandatory worker-result pointer and audit sidecar (BLOCKING)
|
|
311
319
|
|
|
@@ -329,7 +337,7 @@ The selected report-writer preamble defines that audit shape. **Enforced:** `val
|
|
|
329
337
|
|
|
330
338
|
### Main Body Section
|
|
331
339
|
|
|
332
|
-
Section numbering follows `templates/reports/final-report.template.md` exactly — that file is the documentation SSOT for section names and ordering. For full body structure at authoring time, consult your run's **phase-stripped** `final-report-template.md` (the per-task-type instruction-set copy defined in Phase 6 dispatch item 10); the "copy that block verbatim" references below mean the §-block as it appears in that stripped copy, not a re-read of the full source.
|
|
340
|
+
Section numbering follows `templates/reports/final-report-v2.template.md` exactly — that file is the documentation SSOT for section names and ordering. For full body structure at authoring time, consult your run's **phase-stripped** `final-report-template.md` (the per-task-type instruction-set copy defined in Phase 6 dispatch item 10); the "copy that block verbatim" references below mean the §-block as it appears in that stripped copy, not a re-read of the full source.
|
|
333
341
|
|
|
334
342
|
**Verdict Card (top-of-report, mandatory).** Render `## Verdict Card` between the report header and the (conditional) Approval block. Its `Verdict Token` and `Direction` cells MUST byte-match the corresponding cells in `## 7. Final Verdict`. Its `Next Step`, the final-verdict next step, and the first item of `## 3. Recommended Next Steps` MUST name the same route target, though the actionable command and prose need not be byte-identical. Divergence is `contract-violated`.
|
|
335
343
|
|
|
@@ -347,12 +355,26 @@ Every field MUST anchor its claim with at least one evidence reference — a `pa
|
|
|
347
355
|
1. **Clarification Items** — single unified `C-*` table; column schema (4 columns with the short fields stacked in one record-meta cell), ID convention, and rerun behaviour are owned by `_common-contract.md §Clarification request policy` (SSOT). The deprecated `5.5.9 Open Questions` / `1.1 Additional Material Request` / `1.2 User Confirmation Questions` sub-sections are removed; the validator fails reports that reintroduce them.
|
|
348
356
|
- **Open `Blocks=approval` rows carry `origin` and `userConfirmation`** (same SSOT). Lead's dispatch prompt MUST state, per intended blocker, which `origin` applies and what Lead did about it — the writer cannot observe either. When Lead instructed the writer to raise an item rather than decide it, that row's `origin` is `lead-directed` no matter how the workers subsequently voted on it: an instruction returning as a consensus is not a finding. Before writing such an instruction, run the confirmation sequence in [okstra-lead-contract](./okstra-lead-contract.md) "User confirmation before an approval blocker" — asking first is usually cheaper than the row.
|
|
349
357
|
2. **Evidence and Detailed Analysis** — primary evidence rows (file path, line, snippet); secondary evidence / alternate interpretations. If `reference-expectations.md` lists explicit expected values, record match/gap per row.
|
|
350
|
-
- **Error-analysis diagnosis and routing.** When `header.taskType` is `error-analysis`, populate the required `errorAnalysis` object. Copy `errorAnalysis.symptomVerbatim` byte-for-byte from the symptom stated in the brief's `Source Material`; do not paraphrase it. Every `causeCandidates[]` row includes the full `supportingEvidence`, `falsifyingEvidenceChecked`, `confidence`, and `disproveWith` fields. When a candidate is a step in a propagation chain rather than a competing explanation — the analysis calls it a downstream step, a second stage, or a consequence of another candidate — set its `downstreamOf` to the ids of the candidates immediately upstream of it; leave the field absent for a candidate that stands on its own. Every id listed MUST be another candidate in the same report, no row may name itself, and the links MUST NOT form a cycle; `validators/validate-run.py::_validate_cause_chain` rejects all three. This is the only place the chain is machine-readable — prose calling a candidate "the second step of the chain" while `downstreamOf` is absent leaves the report's figure claiming the candidates are alternatives. Route `errorAnalysis.routing.nextTaskType=implementation-
|
|
358
|
+
- **Error-analysis diagnosis and routing.** When `header.taskType` is `error-analysis`, populate the required `errorAnalysis` object. Copy `errorAnalysis.symptomVerbatim` byte-for-byte from the symptom stated in the brief's `Source Material`; do not paraphrase it. Every `causeCandidates[]` row includes the full `supportingEvidence`, `falsifyingEvidenceChecked`, `confidence`, and `disproveWith` fields. When a candidate is a step in a propagation chain rather than a competing explanation — the analysis calls it a downstream step, a second stage, or a consequence of another candidate — set its `downstreamOf` to the ids of the candidates immediately upstream of it; leave the field absent for a candidate that stands on its own. Every id listed MUST be another candidate in the same report, no row may name itself, and the links MUST NOT form a cycle; `validators/validate-run.py::_validate_cause_chain` rejects all three. This is the only place the chain is machine-readable — prose calling a candidate "the second step of the chain" while `downstreamOf` is absent leaves the report's figure claiming the candidates are alternatives. Route `errorAnalysis.routing.nextTaskType=implementation-option-selection` with `direction=begin-option-selection`, or route `errorAnalysis.routing.nextTaskType=error-analysis` with `direction=continue-investigation`; no other pairing is valid. `verdictCard.nextStep`, `finalVerdict.nextStep`, the first `recommendedNextSteps` action and command, and the unique `followUpTasks` row whose `origin` is `phase-continuation` MUST all point to the same `errorAnalysis.routing.nextTaskType` target. The schema enforces only the presence of a `phase-continuation` row; `validators/validate-run.py::_validate_error_analysis_consistency` enforces exact target agreement and uniqueness.
|
|
359
|
+
- **Implementation-option-selection comparison.** When `header.taskType` is `implementation-option-selection`, populate `implementationOptionSelection` from the converged direction-selection findings. Preserve every merged or rejected raw candidate in `candidateAudit`, and put at most three selectable candidates in `rankedOptions`. Each displayed candidate carries its requirement coverage, scope commitments, criterion scores, feasibility votes, safety blockers, unresolved feasibility facts, planning invariants, and exact coverage summary. In each displayed candidate, `expectedChangeAreas` names direction-level change surfaces, never exact file paths or an exact file list. `expectedVerification` names direction-level verification signals, never a stage list or executable test commands. `schemas/final-report-v2.0.schema.json` enforces the displayed-summary constants and the three-option cap; semantic recalculation belongs to `validators/validate-run.py`.
|
|
360
|
+
- **Implementation-planning direction branch.** When `implementationPlanning.planningContract == "selected-direction"`, read `selectedDirectionRef` and the snapshot before authoring. Materialize the snapshot into `directionRealization`, stages, validation, rollback, and bidirectional original-requirement links. Author exactly one `P-Dir-1`; its payload is the complete `directionRealization`. Its verification covers the core mechanism, architecture boundaries, planning invariants, and any hidden direction change against `selectedDirectionRef`. Do not author Option Candidates, candidate scores, a Recommended Option, or user candidate-selection fields. When current evidence requires changing the direction, author `outcome: "direction-invalidated"` and omit the execution plan. Legacy candidate-comparison reruns retain `P-Opt-*`, Option Candidates, trade-off, and Recommended Option semantics.
|
|
361
|
+
|
|
362
|
+
```json
|
|
363
|
+
{
|
|
364
|
+
"candidateDetailBoundary": {
|
|
365
|
+
"expectedChangeAreas": "direction-level-only",
|
|
366
|
+
"expectedVerification": "direction-level-signals-only",
|
|
367
|
+
"forbidden": ["exact-file-lists", "stage-lists", "test-commands"]
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
- **Implementation-option-selection is non-terminal.** Its `followUpTasks` includes a `phase-continuation` row with `autoSpawn: "no"` and `priority: "P0"`; the schema's non-terminal conditional enforces row presence.
|
|
351
373
|
3. **Recommended Next Steps** — prioritized actions. After Phase 7's follow-up spawner runs, append a row per newly created task-key (see "Phase 6 → Phase 7 execution sequence" above). **Approval-gate consistency:** when §1 carries any `Blocks: approval` row with `Status` ∈ {open, answered}, the Verdict Card `Next Step` and the first recommended step MUST point to the clarification rerun (`resume-clarification` of the SAME task-type) — never to "flip frontmatter `approved: true` → jump straight to `implementation`". Run-prep enforces this gate (`run.py _validate_approved_plan` fail-closes on those rows and on a blocking data.json `gateResult`), so a direct-implementation next-step is an instruction the reader cannot actually follow. **Cross-project pointer rule:** for cross-project dependencies (another repo / a different top-level deployment module / a published package), `crossProjectDependencies` (§5.4 Cross-Project Dependencies) is authoritative — do NOT duplicate that substance (prerequisite work / verification signals / handoff) into `recommendedNextSteps`; put only a one-line pointer to that section (no double-recording).
|
|
352
374
|
4. **Follow-up Tasks** — auto-spawn-eligible table. Each row drives `okstra-spawn-followups.py`; see template §4 for the row schema.
|
|
353
375
|
5. **Missing Information and Risks** — uncertain / "I don't know" items. `implementation-planning` adds §5.5 (see heading contract below); `release-handoff` adds §5.6.
|
|
354
376
|
6. **Cross Verification Results** — 4 categories (Full / Partial / Contested / Worker-Unique) when convergence is enabled, per `convergence`. Prepend the Round History sub-table (columns: `Round | inputQueueSize | resolvedCount | carriedForwardCount | dispatches | skippedWorkers`) plus a `round2SkippedReason: <value>` note, pulled verbatim from `convergence-<task-type>-<seq>.json`. Empty contested list renders as `- No items lacking consensus.`. Convergence-disabled runs use the legacy Consensus/Differences format and omit the round table.
|
|
355
|
-
7. **Final Verdict** — `Direction` ∈ `continue-investigation` / `begin-planning` / `begin-implementation` / `approve` / `reject` / `hold`. **Verdict Token** is `not-applicable` for every task-type except `final-verification` — see "Final-verification verdict token contract" below for that case.
|
|
377
|
+
7. **Final Verdict** — `Direction` ∈ `continue-investigation` / `begin-option-selection` / `begin-planning` / `begin-implementation` / `approve` / `reject` / `hold`. **Verdict Token** is `not-applicable` for every task-type except `final-verification` — see "Final-verification verdict token contract" below for that case.
|
|
356
378
|
|
|
357
379
|
**§5.10 Fix History (data-presence gated).** When the run-manifest carries a `fixCycleId`, fill the data.json `fixCycle` block (`cycle` / `targetReport` / `symptom` / `runs`). Read the values from the task root's `history/fix-cycles.jsonl`: `cycle` MUST equal `fixCycleId`, `targetReport` / `symptom` come from that cycle's `opened` row, and `runs` lists its attached `run` rows (`taskType` / `runSeq` / `runManifest`). The validator (`validators/validate-run.py` → `_validate_fix_cycle`) fails the run when the block is missing or `fixCycle.cycle` does not match `fixCycleId`. When the run-manifest has no `fixCycleId`, OMIT the `fixCycle` block entirely — the renderer omits §5.10.
|
|
358
380
|
|
|
@@ -9,10 +9,10 @@ profile document.
|
|
|
9
9
|
- Worker interaction model (shared — read before inferring behaviour from the roster):
|
|
10
10
|
- the per-profile `Required workers:` block is a **roster**, not a behaviour contract. Each role's interaction mode changes across operating phases of the same run.
|
|
11
11
|
- **Phase 4 / 5 (independent analysis)**: every analyser in the resolved provider assignment roster produces findings independently and has no access to another worker's output. `report-writer` does not analyse.
|
|
12
|
-
- **Phase 5.5 (convergence — peer review by workers)**: workers peer-review each other's findings across up to `effectiveMaxRounds` rounds; the lead mediates but does not vote. See `prompts/lead/convergence.md` for the round protocol (replay of findings, `AGREE` / `DISAGREE` / `SUPPLEMENT` verdicts), queue invariants, and final classification (`full-consensus` / `partial-consensus` / `contested` / `worker-unique`). For `requirements-discovery`, `error-analysis`, `implementation-planning`, `project-analysis`, `feature-analysis`, and `change-impact-analysis` this phase runs in **adversarial mode** (`convergence.adversarial=true`): verifiers try to refute each finding against its cited evidence and the burden of proof sits on the claim — see that skill's §"Adversarial Verification Mode".
|
|
12
|
+
- **Phase 5.5 (convergence — peer review by workers)**: workers peer-review each other's findings across up to `effectiveMaxRounds` rounds; the lead mediates but does not vote. See `prompts/lead/convergence.md` for the round protocol (replay of findings, `AGREE` / `DISAGREE` / `SUPPLEMENT` verdicts), queue invariants, and final classification (`full-consensus` / `partial-consensus` / `contested` / `worker-unique`). For `requirements-discovery`, `error-analysis`, `implementation-option-selection`, `implementation-planning`, `project-analysis`, `feature-analysis`, and `change-impact-analysis` this phase runs in **adversarial mode** (`convergence.adversarial=true`): verifiers try to refute each finding against its cited evidence and the burden of proof sits on the claim — see that skill's §"Adversarial Verification Mode".
|
|
13
13
|
- Do NOT conclude "no peer review happens" from the roster alone — every profile that lists ≥2 analyser workers runs convergence by default (`convergence.enabled=true` in `task-manifest.json`).
|
|
14
14
|
- For a new `implementation-planning` run, the plan-body sequence is initial verification → one planner self-fix → targeted re-verification → user gate. The initial verification is round 1, the targeted re-verification is round 2, and a second automatic self-fix is a contract violation. A user-directed correction does not consume the automatic self-fix limit, and a verification failure after that correction does not restart the automatic loop.
|
|
15
|
-
- **provider-unavailable fallback (tolerance).** A worker dispatch can fail to produce a result for two distinct reasons, and both take the same recovery path. (1) **Pane budget:** the dispatch is rejected with `no room for another tmux split` (or an equivalent teammate-pane creation failure). (2) **Sandbox CLI-start failure
|
|
15
|
+
- **provider-unavailable fallback (tolerance).** A worker dispatch can fail to produce a result for two distinct reasons, and both take the same recovery path. (1) **Pane budget:** the dispatch is rejected with `no room for another tmux split` (or an equivalent teammate-pane creation failure) — this is the harness running out of room for its own teammate panes, not okstra placing a worker. (2) **Sandbox CLI-start failure:** an external CLI worker wrapper exits non-zero within seconds with empty stdout and its live-log shows `operation not permitted`. In either case the lead spends the one shared retry budget through the assignment's recorded runner. If the provider is still unavailable, record that terminal status and continue only under the convergence quorum rules; never replace it silently with a fixed provider or count a substitute as the original provider's vote. Completed external-CLI workers hold no pane of their own; the harness teammate panes are reclaimed by the selected runtime adapter's resource lifecycle. (This is a prompt instruction, not a code-enforced gate.)
|
|
16
16
|
- Dual-audience final-report contract (shared):
|
|
17
17
|
- data.json is the sole authored report artifact. AI handoff Markdown and human HTML are independently derived from it; neither derived artifact is the other's source.
|
|
18
18
|
- User-facing information belongs in `humanSummary` and the selected task block's `userNarrative`; it must not exist only in Markdown. The HTML human main body explains the result with those fields plus task facts.
|
|
@@ -69,7 +69,7 @@ profile document.
|
|
|
69
69
|
- `origin` — who raised it. `worker-finding` (an analyser or verifier reached it on its own evidence), `material-gap` (neither the brief nor the codebase answers it), or `lead-directed` (the lead's own judgment, **including anything the lead instructed a worker to raise**). A lead that seeds its conclusion into a worker prompt and then reports the worker's agreement as an independent finding has mislabelled the row; that shape is what let one run block on a question its own lead had authored.
|
|
70
70
|
- `userConfirmation` — what happened before the row was written. `asked-and-answered`, `asked-awaiting` (asked, no answer yet), or `deferred-no-interactive-session` (this run had no user to ask). Record an answer in `userInput` and move `status` to `answered`.
|
|
71
71
|
- Neither field is required once `status` is `answered` / `resolved` — the record lives in `userInput` by then.
|
|
72
|
-
- **Legacy canonical column schema (must match `templates/reports/final-report.template.md` §1 exactly):** every `## 1. Clarification Items` table has exactly these 4 columns, in this order:
|
|
72
|
+
- **Legacy canonical column schema (must match `templates/reports/final-report-v2.template.md` §1 exactly):** every `## 1. Clarification Items` table has exactly these 4 columns, in this order:
|
|
73
73
|
`| <record-meta> | Statement | Expected form | User input |` (the first header is the i18n `columns.recordMeta` label — `Record`).
|
|
74
74
|
The five short fields (ID, Ticket ID, Kind, Blocks, Status) are stacked inside the single record-meta cell, one per line separated by `<br>`, in this fixed order (mirrors the §2.1 Primary-Evidence meta column):
|
|
75
75
|
|
|
@@ -10,7 +10,7 @@ are collected and convergence finished. Phase 1-5 do not need it.
|
|
|
10
10
|
|
|
11
11
|
## Required deliverable shape (final report, in addition to the standard sections)
|
|
12
12
|
|
|
13
|
-
- **Plan link & approval evidence**: path to the approved `final-report.md`, the exact quoted approval marker, AND the executed stage number / title quoted from the Stage Map row.
|
|
13
|
+
- **Plan link & approval evidence**: path to the approved `final-report.md`, the exact quoted approval marker, AND the executed stage number / title quoted from the Stage Map row. For a selected-direction plan, also quote `selectedDirectionRef.optionId`, `snapshotPath`, and the validated snapshot digest; for a legacy plan, quote the effective `implementation-option` or the Recommended Option fallback.
|
|
14
14
|
- **Commit list**: each commit's SHA (or short SHA), message, and the plan step(s) / TDD cycle it satisfies
|
|
15
15
|
- **Diff summary**: `git diff --stat <base>..HEAD` output, plus a per-file one-line summary of changes
|
|
16
16
|
- **Out-of-plan edits block**: every file edited that was not in the approved plan's file list, with rationale (empty block is acceptable and preferred)
|
|
@@ -42,7 +42,7 @@ are collected and convergence finished. Phase 1-5 do not need it.
|
|
|
42
42
|
|
|
43
43
|
## Self-review pass before finalising the report (the Okstra lead runs this; do not delegate it)
|
|
44
44
|
|
|
45
|
-
1. **Plan coverage** — every step in the approved plan
|
|
45
|
+
1. **Plan coverage** — for a selected-direction plan, every step in the approved `plan-ready` stage must point to a commit (or an explicit `Skipped: <reason>` entry), and the diff must preserve the selected snapshot's mechanism and invariants. For a legacy plan, every step in the effective implementation option (explicit frontmatter value or Recommended Option fallback) must point to a commit or an explicit skip. List gaps. A `RED:` step and its `GREEN:` step pointing to the same merged commit SHA is NOT a coverage gap — one SHA may be shared by both.
|
|
46
46
|
2. **Evidence completeness** — every `Validation evidence` and `TDD evidence` claim has the actual command line and exit code? No paraphrased "tests pass" without output?
|
|
47
47
|
3. **Out-of-plan honesty** — files in the diff that are NOT in the plan list must appear in the `Out-of-plan edits` block. Cross-check with `git diff --name-only`.
|
|
48
48
|
4. **Verifier dissent preserved** — if the verifiers in the resolved roster disagree, the disagreement is visible in the report? Synthesis hides nothing?
|
|
@@ -94,6 +94,8 @@ persisted prompt lacks the heading `Coding-conventions preflight`
|
|
|
94
94
|
- **local git operations only**: `git add`, `git commit`. Prefer small commits keyed to plan steps.
|
|
95
95
|
- **Explicit-path staging only (BLOCKING).** Stage exactly the files a plan step touches by naming each path — `git add <path1> <path2>`. Never use the bulk forms `git add .`, `git add -A`, `git add -u`, or `git add --all`: they sweep in unrelated edits, stray build output, and editor scratch files. Never use `git add -f` (force) under any circumstance — `-f` is the *only* way a `.gitignore`d path reaches a commit, and a forced ignored file is always a defect. If `git add <path>` reports the path is ignored, that file does not belong in the commit; do not override it — leave it untracked.
|
|
96
96
|
- **No ignored / okstra files in commits (BLOCKING).** Before every `git commit`, run `git diff --cached --name-only` and pipe the staged paths through `git check-ignore --stdin --no-index`; abort the commit if it reports **any** match — a staged path that `.gitignore` excludes means a bulk-add or `-f` leaked it in. The check explicitly covers `.okstra/` (and `.project-docs/` when the legacy symlink is present): `.okstra/**` is gitignored, and force-staging it onto the stage branch is the one way these verification artifacts reach the upstream PR. Conformance/qa evidence belongs in the carry sidecar and verifier result — committing it is never correct, even when a step's instructions seem to ask for it.
|
|
97
|
+
- **Clean-tree checks use `okstra worktree-status --check-clean` (BLOCKING).** The worktree you execute in carries okstra's own provisioning — `.okstra`, the synced entries (`.project-docs`, `.claude`, …), and the nested `stage-<N>/` worktree — so `git status --porcelain` is never empty here and its emptiness proves nothing about your stage. Use `okstra worktree-status --check-clean`: it asks the same question over source paths only and exits 1 when dirty, so it chains as an assertion. This applies to a check you write yourself AND to one you inherit: when a plan step's `command` cell asserts cleanliness with a bare `git status`, run the okstra command in its place and record the substitution in `Out-of-plan edits` — the step's intent was a clean stage, not a literal empty status.
|
|
98
|
+
- **Never read an `.okstra/` artifact from a git object (BLOCKING).** `.okstra/**` is gitignored and never committed (see the staging rules above), so `git cat-file -e <tag>:.okstra/…`, `git show <tag>:.okstra/…`, and every variant of that read fail by construction — the answer is never "commit it after all". When a plan step's command depends on such a read, the step is unsatisfiable as written: read the artifact from the working tree instead, record the deviation, and carry the artifact forward through the stage carry sidecar.
|
|
97
99
|
- **Commit message format (mandatory)**: every commit message MUST follow Conventional Commits — `<type>(<scope>): <subject>` for the first line, optional body separated by a blank line, optional footer. Constraints:
|
|
98
100
|
- `<type>` MUST be one of: `feat` / `fix` / `perf` / `revert` / `deps` / `docs` / `refactor` / `build` / `ci` / `chore` / `test`. When the repo is `release-please`-managed, this aligns the commit with a configured changelog section.
|
|
99
101
|
- `<scope>` SHOULD be the plan step identifier or the primary module touched (e.g. `feat(report-writer): ...`). Omit the parentheses only when no meaningful scope applies.
|
|
@@ -10,8 +10,8 @@ at Phase 5, BEFORE constructing the verifier worker dispatch prompts.
|
|
|
10
10
|
## Verifier roles (resolved at run-prep time)
|
|
11
11
|
|
|
12
12
|
- **Verifier dispatch labelling.** The core functional role label is `<provider>-verifier` (here, and identically in `final-verification`). Provider, role, and model identity are owned by `prompts/lead/okstra-lead-contract.md` "Model assignments"; the selected runtime adapter owns provider-native dispatch-label mapping (including any `name` / `**Pane role:**` fields) and token-attribution wiring under its "Semantic operation mapping". This functional label is NOT what the run's PROGRESS checkpoints carry: `phase-4-dispatch` / `phase-5-collect` name the roster role team-state records (`Claude worker`, `Codex worker`), because that is the entry the Phase 7 conformance check matches them against.
|
|
13
|
-
- The verifier slots are `Claude verifier` and `Codex verifier`, plus `Antigravity verifier` **only when `antigravity` is in the resolved `--workers` roster**. Every verifier in the resolved roster is dispatched
|
|
14
|
-
- Session isolation — not model-variant divergence — is the primary self-review safeguard: each verifier is a separate CLI invocation with its own context window, so reusing the
|
|
13
|
+
- The verifier slots are `Claude verifier` and `Codex verifier`, plus `Antigravity verifier` **only when `antigravity` is in the resolved `--workers` roster**. Every verifier in the resolved roster is dispatched except the one whose worker ID holds the executor role this run: that ID materializes as the executor on every dispatch (`scripts/okstra_ctl/worker_prompt_policy.py`), so the executor's own provider has no separate verifier session in the current plumbing — a follow-up design item. Independence still holds where it counts: every verdict comes from a fresh CLI session with no shared context, never from the session that wrote the diff. Verifiers MUST NOT call Edit, Write, or any Bash command that mutates files outside the run's artifact directories. If a verifier wants a fix, it records the recommendation in its worker result; it does not apply the fix itself.
|
|
14
|
+
- Session isolation — not model-variant divergence — is the primary self-review safeguard: each verifier is a separate CLI invocation with its own context window, so a verifier reusing the executor's model variant is acceptable. Different model variants (e.g. executor=opus / Claude verifier=sonnet) remain recommended when available.
|
|
15
15
|
- Phase-specific model defaults override the shared defaults: `Claude verifier`=`opus`, `Codex verifier`=`gpt-5.6-sol`, `Antigravity verifier`=`gemini-3.1-pro` (only when present in the roster). The `Executor`'s model is taken from the provider-specific worker model corresponding to `--executor`: claude→`--claude-model` (default `opus`), codex→`--codex-model` (default `gpt-5.6-sol`), antigravity→`--antigravity-model` (default `gemini-3.1-pro`).
|
|
16
16
|
- Verifiers read from the SAME working tree path the Executor used so they observe the exact diff the Executor produced. Verifiers remain strictly read-only there.
|
|
17
17
|
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
- **Falsifiable cause candidates:** every root-cause candidate must include supporting evidence, the strongest falsifying evidence checked, confidence, and the next diagnostic action that would disprove it. A candidate that cannot be falsified is too vague for this phase.
|
|
24
24
|
- **Graph-aware scope:** a graph edge can explain ordering or duplication, but it is not proof of cause by itself. Cite code/log evidence before claiming an upstream related task caused the current symptom.
|
|
25
25
|
- **Sharp next diagnostic:** end with the single highest-value diagnostic command, log capture, or file inspection that should happen next, plus the expected signal that would confirm or reject the leading cause.
|
|
26
|
-
- **Fix-design boundary:** do not design the implementation fix beyond what is necessary to validate the cause. If the cause is credible, route to `implementation-
|
|
26
|
+
- **Fix-design boundary:** do not design the implementation fix beyond what is necessary to validate the cause. If the cause is credible, route to `implementation-option-selection` with the verified evidence; if the cause is still unclear, route to another `error-analysis` run with the next diagnostic.
|
|
27
27
|
- Structured diagnosis and routing contract:
|
|
28
28
|
- `errorAnalysis` is the source of truth for reproduction status, `EA-NNN` cause candidates, the sharp next diagnostic, and the next route.
|
|
29
|
-
- A route to `implementation-
|
|
30
|
-
- Structure is enforced by `schemas/final-report-
|
|
29
|
+
- 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.
|
|
30
|
+
- Structure is enforced by `schemas/final-report-v2.0.schema.json` `$defs.ErrorAnalysis`. Cross-field diagnosis and route semantics are enforced by `validators/validate-run.py::_validate_error_analysis_consistency`.
|
|
31
31
|
- Primary focus areas:
|
|
32
32
|
- symptom and trigger clarification
|
|
33
33
|
- root-cause candidates
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
{{INCLUDE:_coverage-critic.md}}
|
|
51
51
|
- Non-goals:
|
|
52
52
|
- implementation details unless they are necessary to validate the cause
|
|
53
|
-
- **source code edits, builds, migrations, or deployments** — this run produces evidence and cause analysis only; the fix belongs to a later `implementation-planning
|
|
53
|
+
- **source code edits, builds, migrations, or deployments** — this run produces evidence and cause analysis only; the fix belongs to a later `implementation-option-selection`, `implementation-planning`, and `implementation` sequence
|
|
54
54
|
- this run stays in `error-analysis` regardless of user phrasing — the shared anti-escalation rule applies
|
|
@@ -58,12 +58,12 @@
|
|
|
58
58
|
- Required deliverable shape (final report, in addition to the standard sections):
|
|
59
59
|
- **Source Implementation Report(s)** (**Enforced:** `validators/validate-run.py` `_validate_verification_target_match` compares `verificationScope`, `worktreePath`, `implementationBaseRef`, `capturedHeadSha`, and the `stageReports` stage set against the digest-verified `instruction-set/verification-target.md`; a snapshot whose digest no longer checks out is ignored rather than trusted. `verificationScope` in particular gates both stage-group eligibility and release-handoff routing, so it is not the report's to restate): the `VERIFICATION_TARGET` snapshot verbatim — verification scope, worktree path, base/head refs, the list of stages under verification, and one row per stage citing its originating implementation final-report (`report_path` from `consumers.jsonl`; render `(report_path unrecorded)` when absent). Every analyser prompt carries the same compact target identity (`**Verification scope:** / **Worktree:** / **Verification base ref:** / **Verification head ref:** / **Verification target path:** / **Verification target digest:**`) and reads the sidecar on demand for the complete diff stat. A worker that cannot confirm its analysis ran against that worktree's delivered diff MUST record a `tool-failure`.
|
|
60
60
|
- **Verdict vocabulary**: Section 7 (`Final Verdict`) MUST include a `Verdict Token` field whose value is exactly one of `accepted`, `conditional-accept`, or `blocked`. `conditional-accept` requires an explicit, exhaustive list of conditions; ambiguous verdicts ("looks good", "mostly ready") are not allowed. Each condition MUST be recorded as a row in the **Conditional Acceptance Conditions** deliverable (`id` `CA-NNN`, `condition`, `evidenceRequired`, `blocksReleaseHandoff`). The validator enforces verdict↔deliverable consistency: `accepted` ⇒ zero acceptance blockers, `blocked` ⇒ at least one, `conditional-accept` ⇒ at least one condition, and a `release-handoff` routing recommendation is allowed only when the verdict is `accepted`. **Any Acceptance Blocker therefore forces the verdict off `accepted` (to `conditional-accept` or `blocked`); the gates below cite this rule instead of restating the arithmetic.**
|
|
61
|
-
- **Acceptance Blockers block** (under section 4): one row per blocker with `id`, `severity` (`critical` / `major` / `minor`), evidence (file path, log excerpt, or test output), and the recommended follow-up phase
|
|
61
|
+
- **Acceptance Blockers block** (under section 4): one row per blocker with `id`, `severity` (`critical` / `major` / `minor`), evidence (file path, log excerpt, or test output), and the recommended follow-up phase: `error-analysis` for a cause problem, `implementation-option-selection` for a direction problem, or `implementation-planning` for a detailed-plan problem. Empty block is acceptable and preferred — render the single line `- No acceptance blockers found.`
|
|
62
62
|
- **Residual Risk block** (under section 4): risks that are not blockers but should be tracked, each with mitigation owner and a trigger that would escalate them to a blocker.
|
|
63
63
|
- **Validation Evidence**: for every requirement in the originating plan or task brief, cite the artifact (commit SHA, test output, log line, MCP SELECT result) that demonstrates coverage. Paraphrased "verified" claims without an artifact are rejected.
|
|
64
64
|
- **Read-only command log**: any pre-existing test/validation command touched during this run MUST be listed with its exact command line and one honest status — `executed` (ran; carries its exit code) / `advisory` (external Tier 3 did not PASS; carries observed/expected results and remains user-owned) / `env-unavailable` (should run but cannot in this environment — missing replica DB, container, or service; carries the reason, never a faked pass) / `not-configured` (no such qa-command tier) / `rejected` (a mutating/denied token — skipped, carries the denied token). A check that could not run locally is recorded as `env-unavailable` or `advisory` according to the external QA policy — never silently dropped and never reported as `executed` with an invented exit code. Mutating-command prohibition is the shared read-only boundary (see Non-goals); it is not restated per row.
|
|
65
65
|
- **Could-not-verify roll-up (§5.8.9)**: the template mechanically aggregates every not-confirmed check into one scannable list — `gap` requirement-coverage rows, `advisory` / `not-configured` / `env-unavailable` / `rejected` command rows, and `blocked` manual tests. You do not hand-author it, but you MUST give those rows their honest status so nothing unverified hides across sections: a check silently recorded as `executed`/`covered` will not surface in the roll-up. This is okstra's answer to "say what could not be verified this run."
|
|
66
|
-
- **Routing recommendation**: the next safe phase — one of `release-handoff`, `done`, `error-analysis`, `implementation-planning` — tied to the verdict and blocker list. `release-handoff` is allowed ONLY when the Verdict Token is `accepted`. `release-handoff` is additionally allowed ONLY when the verification scope (the `Verification scope:` line of the injected `VERIFICATION_TARGET` block, recorded as the report's `verificationScope` field) is `whole-task`; a `single-stage` accepted run routes to `release-handoff(stage-group)` (or `implementation` / `done`); plain `release-handoff` remains whole-task-only. Enforcement: `validators/validate-run.py` rejects a `single-stage` report whose routing cites plain `release-handoff`.
|
|
66
|
+
- **Routing recommendation**: the next safe phase — one of `release-handoff`, `done`, `error-analysis`, `implementation-option-selection`, `implementation-planning` — tied to the verdict and blocker list. `release-handoff` is allowed ONLY when the Verdict Token is `accepted`. `release-handoff` is additionally allowed ONLY when the verification scope (the `Verification scope:` line of the injected `VERIFICATION_TARGET` block, recorded as the report's `verificationScope` field) is `whole-task`; a `single-stage` accepted run routes to `release-handoff(stage-group)` (or `implementation` / `done`); plain `release-handoff` remains whole-task-only. Enforcement: `validators/validate-run.py` rejects a `single-stage` report whose routing cites plain `release-handoff`.
|
|
67
67
|
- **Verified-row recording** (single-stage scope only): when the Verdict Token is `accepted`, the lead MUST run `okstra handoff record-verified --plan-run-root <plan-run-root> --stage <N> --report-path <final-report.md path> --data-json <final-report data.json path>` and quote the command + exit code in the report. The helper re-validates taskType/scope/verdict from data.json, so a non-accepted or whole-task report is rejected at the tool layer. **Enforced:** `validators/validate-run.py` `_validate_verified_row_recorded` requires a `verified` row in `runs/implementation-planning/consumers.jsonl` for every accepted stage — the helper validated its own inputs but nothing checked it had ever run, leaving reports that said `accepted` while the registry said unverified, so the stage was never offered for a stage-group PR.
|
|
68
68
|
- Clarification request policy (phase-specific addendum — shared policy is in `_common-contract.md`):
|
|
69
69
|
- populate `## 1. Clarification Items` only when a blocker hinges on information only the user can supply (deployment intent, intended target environment, business-rule interpretation); use `Blocks=next-phase` for items that gate continuing to release-handoff
|
|
@@ -77,6 +77,6 @@
|
|
|
77
77
|
- **Acceptance critic (opt-in)**: when `convergence.critic.enabled=true` (chosen via the okstra-run picker or `--critic`), a reused-worker **acceptance devil's-advocate** pass is dispatched concurrently with the first convergence reverify round to surface candidate acceptance blockers the verifiers may have missed; candidates are verified only after convergence completes. Each candidate is verified **confirm-or-downgrade**: confirmed → an `Acceptance Blockers` row; unconfirmed → a `Residual Risk` row (never dropped). See `prompts/lead/convergence.md` "Acceptance critic pass (final-verification)".
|
|
78
78
|
- Non-goals:
|
|
79
79
|
- proposing unrelated refactors beyond the delivered scope
|
|
80
|
-
- **source code edits, follow-up bug fixes, or scope expansion** — this run renders a verdict only; defects detected here become inputs to a new `error-analysis` or `implementation-planning` run
|
|
80
|
+
- **source code edits, follow-up bug fixes, or scope expansion** — this run renders a verdict only; defects detected here become inputs to a new `error-analysis`, `implementation-option-selection`, or `implementation-planning` run according to whether the cause, direction, or detailed plan is invalid
|
|
81
81
|
- read-only execution of pre-existing test or validation commands is permitted, but any command that mutates source, schema, or deployment state is forbidden
|
|
82
82
|
- this run records detected issues and ends — the shared anti-escalation rule forbids in-run fixes regardless of user phrasing
|
|
@@ -38,6 +38,13 @@
|
|
|
38
38
|
"executing builds, migrations, deployments, or any state-mutating command",
|
|
39
39
|
"starting `implementation-planning` or `implementation` inside this run (each must be a separate run, and `implementation` additionally requires an approved `implementation-planning` deliverable)"
|
|
40
40
|
],
|
|
41
|
+
"implementation-option-selection": [
|
|
42
|
+
"source or configuration edits, refactors, or fix attempts",
|
|
43
|
+
"tests, builds, migrations, deployments, or any state-mutating command",
|
|
44
|
+
"detailed file lists, stage maps, execution commands, or plan approval",
|
|
45
|
+
"starting `implementation-planning` or `implementation` inside this run",
|
|
46
|
+
"displaying more than three merged candidates or omitting rejected-candidate audit records"
|
|
47
|
+
],
|
|
41
48
|
"implementation-planning": [
|
|
42
49
|
"source code edits of any kind (Edit/Write on project source files is forbidden)",
|
|
43
50
|
"file writes outside the run`s artifact directories (`reports/`, `prompts/`, `state/`, `manifests/`, `worker-results/`, `status/`, `sessions/`) and the task-root qa tree (`<task_root>/qa/` — the Tier3 conformance scripts, manifest, and tsconfig this phase MUST write per the Stage Map conformance contract); in particular, do not write to `docs/superpowers/specs/` or `docs/superpowers/plans/`",
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Implementation Option Selection Profile
|
|
2
|
+
|
|
3
|
+
- Purpose: compare feasible implementation directions before planning, preserving a read-only record of the evidence and trade-offs that selects the direction to plan
|
|
4
|
+
- Required workers:
|
|
5
|
+
- claude
|
|
6
|
+
- codex
|
|
7
|
+
- antigravity
|
|
8
|
+
- report-writer
|
|
9
|
+
- Optional workers (opt-in via `--workers`):
|
|
10
|
+
- grok
|
|
11
|
+
- kimi
|
|
12
|
+
{{INCLUDE:_common-contract.md}}
|
|
13
|
+
- Brief consumption:
|
|
14
|
+
- Apply the shared reporter-confirmation precondition exactly as written. Unresolved `intent-check:` and `conversion-block:` rows use `Blocks=next-phase`.
|
|
15
|
+
- Treat each stable brief end-state ID as a required evaluation target. A missing ID is a preparation failure; do not invent a replacement requirement.
|
|
16
|
+
- Worker direction-selection procedure:
|
|
17
|
+
- In `candidate-comparison` mode, produce candidate, supporting and contradicting evidence, criterion scores, and requirement mappings.
|
|
18
|
+
- In `candidate-comparison` mode only, submit at most three candidates. A candidate must be feasible from inspected evidence, not from an assumed future change.
|
|
19
|
+
- In `preselected-validation` mode, receive one preselected direction from the lead and validate its evidence, counterevidence, criterion scores, and requirement mappings. The worker must not generate new candidates.
|
|
20
|
+
- Do not produce detailed file lists, stage maps, execution commands, or a plan approval request.
|
|
21
|
+
- Pre-selection context exploration:
|
|
22
|
+
- In `candidate-comparison` mode, inspect the code paths, interfaces, tests, and constraints needed to distinguish candidates before assigning scores.
|
|
23
|
+
- In `preselected-validation` mode, inspect the code paths, interfaces, tests, and constraints needed to validate the one preselected direction.
|
|
24
|
+
- Record uncertainty and contradictory evidence instead of turning it into a candidate preference.
|
|
25
|
+
- Option evaluation rules:
|
|
26
|
+
- `candidate-comparison` generates alternatives. `preselected-validation` validates one preselected direction and does not rank or replace it with an alternative.
|
|
27
|
+
- In `candidate-comparison` mode, the lead merges overlapping candidates, then re-evaluates every merged candidate against the same criteria before ranking it.
|
|
28
|
+
- In `candidate-comparison` mode, display at most three merged candidates and record every rejected candidate with its rejection reason and cited evidence for audit.
|
|
29
|
+
- Map every displayed candidate or preselected direction to the stable brief end-state IDs it satisfies, preserves, or leaves unresolved.
|
|
30
|
+
- Cross-verification mode:
|
|
31
|
+
- Phase 5.5 convergence runs in adversarial mode (`convergence.adversarial=true`).
|
|
32
|
+
- Non-goals:
|
|
33
|
+
- source or configuration edits, tests, builds, migrations, deployments, or other state-mutating commands
|
|
34
|
+
- detailed implementation planning, file-change specifications, stage maps, execution commands, or user approval
|
|
35
|
+
- starting `implementation-planning` or any other lifecycle phase inside this run
|