okstra 0.171.0 → 0.173.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.
Files changed (106) hide show
  1. package/README.md +8 -6
  2. package/docs/architecture/storage-model.md +11 -0
  3. package/docs/architecture.md +29 -14
  4. package/docs/cli.md +40 -7
  5. package/docs/for-ai/skills/okstra-user-response.md +2 -2
  6. package/docs/performance-improvement-plan-v2.md +6 -5
  7. package/docs/project-structure-overview.md +24 -14
  8. package/docs/task-process/README.md +5 -3
  9. package/docs/task-process/error-analysis.md +2 -2
  10. package/docs/task-process/final-verification.md +2 -2
  11. package/docs/task-process/implementation-option-selection.md +70 -0
  12. package/docs/task-process/implementation-planning.md +23 -15
  13. package/docs/task-process/requirements-discovery.md +2 -2
  14. package/package.json +1 -1
  15. package/runtime/BUILD.json +2 -2
  16. package/runtime/agents/workers/report-writer-worker.md +30 -6
  17. package/runtime/bin/lib/okstra/cli.sh +5 -1
  18. package/runtime/bin/lib/okstra/globals.sh +1 -0
  19. package/runtime/bin/lib/okstra/usage.sh +3 -0
  20. package/runtime/bin/okstra.sh +2 -0
  21. package/runtime/prompts/duties/direction-selection-worker.md +44 -0
  22. package/runtime/prompts/duties/planning-worker.md +12 -4
  23. package/runtime/prompts/launch.template.md +4 -0
  24. package/runtime/prompts/lead/adapters/cmux.md +1 -1
  25. package/runtime/prompts/lead/context-loader.md +1 -1
  26. package/runtime/prompts/lead/convergence.md +5 -5
  27. package/runtime/prompts/lead/okstra-lead-contract.md +42 -17
  28. package/runtime/prompts/lead/plan-body-verification.md +42 -14
  29. package/runtime/prompts/lead/report-writer.md +38 -15
  30. package/runtime/prompts/lead/team-contract.md +2 -0
  31. package/runtime/prompts/profiles/_clarification-recommendation.md +3 -1
  32. package/runtime/prompts/profiles/_common-contract.md +3 -2
  33. package/runtime/prompts/profiles/_implementation-deliverable.md +2 -2
  34. package/runtime/prompts/profiles/error-analysis.md +3 -3
  35. package/runtime/prompts/profiles/final-verification.md +3 -3
  36. package/runtime/prompts/profiles/forbidden-actions.json +7 -0
  37. package/runtime/prompts/profiles/implementation-option-selection.md +35 -0
  38. package/runtime/prompts/profiles/implementation-planning.md +56 -37
  39. package/runtime/prompts/profiles/implementation.md +2 -1
  40. package/runtime/prompts/profiles/improvement-discovery.md +1 -1
  41. package/runtime/prompts/profiles/requirements-discovery.md +3 -3
  42. package/runtime/prompts/wizard/prompts.ko.json +9 -1
  43. package/runtime/python/okstra_ctl/adapters/hosts/antigravity/relay.md +1 -1
  44. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +1 -1
  45. package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +1 -1
  46. package/runtime/python/okstra_ctl/adapters/hosts/external/relay.md +1 -1
  47. package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +1 -1
  48. package/runtime/python/okstra_ctl/adapters/hosts/kimi/relay.md +1 -1
  49. package/runtime/python/okstra_ctl/agent_activity.py +306 -0
  50. package/runtime/python/okstra_ctl/agent_invocation.py +1 -0
  51. package/runtime/python/okstra_ctl/analysis_packet.py +6 -0
  52. package/runtime/python/okstra_ctl/clarification_items.py +37 -20
  53. package/runtime/python/okstra_ctl/exact_coverage.py +128 -0
  54. package/runtime/python/okstra_ctl/fix_cycles.py +3 -1
  55. package/runtime/python/okstra_ctl/implementation_direction.py +836 -0
  56. package/runtime/python/okstra_ctl/implementation_options.py +479 -0
  57. package/runtime/python/okstra_ctl/lead_events.py +47 -4
  58. package/runtime/python/okstra_ctl/plan_items.py +51 -3
  59. package/runtime/python/okstra_ctl/render.py +12 -3
  60. package/runtime/python/okstra_ctl/render_final_report.py +1 -0
  61. package/runtime/python/okstra_ctl/report_contract.py +45 -13
  62. package/runtime/python/okstra_ctl/report_finalize.py +51 -14
  63. package/runtime/python/okstra_ctl/report_html/common.py +5 -3
  64. package/runtime/python/okstra_ctl/report_html/render.py +4 -2
  65. package/runtime/python/okstra_ctl/report_html/router.py +4 -0
  66. package/runtime/python/okstra_ctl/report_html/view_models/implementation_option_selection.py +32 -0
  67. package/runtime/python/okstra_ctl/report_html/view_models/implementation_planning.py +42 -11
  68. package/runtime/python/okstra_ctl/report_translation.py +14 -0
  69. package/runtime/python/okstra_ctl/report_views.py +148 -12
  70. package/runtime/python/okstra_ctl/run.py +350 -2
  71. package/runtime/python/okstra_ctl/scope_provenance.py +15 -9
  72. package/runtime/python/okstra_ctl/user_response.py +75 -0
  73. package/runtime/python/okstra_ctl/wizard.py +144 -0
  74. package/runtime/python/okstra_ctl/worker_audit_ledger.py +150 -0
  75. package/runtime/python/okstra_ctl/worker_prompt_policy.py +2 -0
  76. package/runtime/python/okstra_ctl/workflow.py +29 -7
  77. package/runtime/schemas/final-report-v2.0.schema.json +1623 -143
  78. package/runtime/skills/okstra-user-response/SKILL.md +2 -2
  79. package/runtime/templates/reports/final-report-v2.template.md +12 -0
  80. package/runtime/templates/reports/final-verification-input.template.md +1 -1
  81. package/runtime/templates/reports/html/assets/base.css +7 -0
  82. package/runtime/templates/reports/html/base.template.html +3 -2
  83. package/runtime/templates/reports/html/i18n/en.json +27 -2
  84. package/runtime/templates/reports/html/i18n/ko.json +27 -2
  85. package/runtime/templates/reports/html/macros/forms.html +42 -4
  86. package/runtime/templates/reports/html/tasks/implementation-option-selection.template.html +49 -0
  87. package/runtime/templates/reports/html/tasks/implementation-planning.template.html +61 -2
  88. package/runtime/templates/reports/i18n/en.json +17 -0
  89. package/runtime/templates/reports/implementation-input.template.md +4 -2
  90. package/runtime/templates/reports/implementation-planning-input.template.md +18 -4
  91. package/runtime/templates/reports/improvement-discovery-input.template.md +1 -1
  92. package/runtime/templates/reports/md/tasks/implementation-option-selection.template.md +13 -0
  93. package/runtime/templates/reports/md/tasks/implementation-planning.template.md +17 -0
  94. package/runtime/templates/reports/report.js +137 -21
  95. package/runtime/templates/reports/task-brief.template.md +9 -3
  96. package/runtime/templates/reports/user-response.template.md +28 -5
  97. package/runtime/templates/worker-prompt-preamble.md +16 -0
  98. package/runtime/validators/validate-implementation-plan-stages.py +106 -1
  99. package/runtime/validators/validate-report-views.py +2 -2
  100. package/runtime/validators/validate-run.py +1124 -54
  101. package/runtime/validators/validate_improvement_report.py +5 -1
  102. package/runtime/validators/validate_session_conformance.py +523 -35
  103. package/src/cli-registry.mjs +7 -0
  104. package/src/commands/execute/codex-run.mjs +1 -0
  105. package/src/commands/execute/render-bundle.mjs +1 -0
  106. package/src/commands/report/agent-activity.mjs +21 -0
@@ -27,7 +27,7 @@ Current baseline:
27
27
  - package version: see `package.json`
28
28
  - Node CLI entrypoint: `bin/okstra`
29
29
  - Python orchestration authority: `scripts/okstra_ctl/run.py::prepare_task_bundle`
30
- - lifecycle: `requirements-discovery → error-analysis → implementation-planning → implementation → final-verification → release-handoff`
30
+ - lifecycle: `requirements-discovery → error-analysis → implementation-option-selection → implementation-planning → implementation → final-verification → release-handoff`
31
31
  - installed skills: 13
32
32
  - provider workers: `claude`, `codex`, `antigravity`, `grok`, `kimi`; functional report writer: `report-writer`
33
33
  - final report SSOT: current `schemas/final-report-v2.0.schema.json` + `*.data.json`; schema v1 remains a compatibility contract
@@ -189,6 +189,7 @@ Runtime/install asset changes follow this checklist:
189
189
  | `team` | `src/commands/execute/team.mjs` | External lead tmux-pane worker dispatch / await / teardown |
190
190
  | `convergence` | `src/commands/execute/convergence.mjs` | Internal admin CLI for the deterministic Phase 5.5 convergence engine (`seed`/`plan-round`/`apply-round`/`apply-critic-gaps`/`finalize`/`validate`/`example`; Python: `okstra_ctl.convergence`) |
191
191
  | `plan-items` | `src/commands/execute/plan-items.mjs` | Internal admin CLI for deterministic plan-body item extraction and exact-match validation (`extract`/`validate`; Python: `okstra_ctl.plan_items_cli`) |
192
+ | `agent-activity` | `src/commands/report/agent-activity.mjs` | Thin Node shim for `okstra_ctl.agent_activity`; `append` records one run-bound activity and `project` writes the validated event projection into final-report data |
192
193
  | `report-finalize` | `src/commands/report/finalize.mjs` | Run the whole Phase 7 post-report sequence in contractual order (Python: `okstra_ctl.report_finalize`) — the single reference point shared with the Codex lead adapter |
193
194
  | `render-views` | `src/commands/report/render-views.mjs` | Render schema v2 data with its task-specific human template, or use the schema v1 / quick-report compatibility view |
194
195
  | `render-final-report`, `inject-report-index` | `src/commands/report/*.mjs` | Render version-selected AI handoff Markdown from data.json; v1 index injection remains compatibility-only |
@@ -237,6 +238,10 @@ Important modules:
237
238
  | Module | Role |
238
239
  |---|---|
239
240
  | `run.py` | `prepare_task_bundle()` single authority and CLI parser; for final-verification it adapts CLI stage input into `FinalVerificationTargetRequest`, maps the acquired target into render context, and owns `verification-target.md` snapshot/digest materialization before manifests and prompts are rendered |
241
+ | `agent_activity.py` | Records activity rows against run-manifest identity, imports validated command evidence from worker audit sidecars, and deterministically projects the current run's `lead-events-*.jsonl` activity rows into `agentActivity[]`. Manifests without `activityContractVersion: 1` are left unchanged. |
242
+ | `exact_coverage.py` | Shared pure calculator for requirement coverage and scope precision in option selection and selected-direction planning |
243
+ | `implementation_options.py` | Option-selection criteria, weighting, candidate fingerprint convergence, ranking, and semantic validation |
244
+ | `implementation_direction.py` | Selected report/response validation, direction snapshot materialization, and selected-direction reference validation |
240
245
  | `implementation_stage.py` | `implementation` single-stage run orchestration — read the Stage Lifecycle Snapshot → pick an available Stage Map entry → provision an isolated stage worktree → publish the selected stage as run context (extracted from `run.py`) |
241
246
  | `stage_targets.py` | Stage readiness/verification policy SSOT — from the Stage Lifecycle Snapshot (`consumers.jsonl` ledger + carry sidecar backfill + active registry reservation) it decides which stage is runnable, which commit it branches from, and what final-verification checks. `acquire_final_verification_target()` acquires the ledger, registry, worktree, Git, and optional whole-task integration facts behind one task-key mutex and returns a typed target without render-context coupling. `order_stage_closure` topologically sorts (Kahn) the dependency closure of the wizard's multi-selected stage set to produce the unattended `chain-stages` chaining order |
242
247
  | `stage_fix_carry.py` | fix-run carry derivation for a re-run on an `implementation` stage whose latest final-report data.json carries verifier `FAIL` verdicts — collects the previous report path, previous run HEAD, failed verifiers, carried blocking findings, and a routing recommendation, which `run.py` renders into the analysis profile through the `{{FIX_RUN_CONTEXT}}` token. A first run, or a re-run after `PASS`, yields no carry and renders the token empty |
@@ -313,7 +318,7 @@ Important modules:
313
318
  | `domain/`, `application/`, `ports/` | Host-neutral values and errors, wizard/run use cases, and the interaction/session/dispatch/accounting port contracts |
314
319
  | `registry/host_registry.py`, `registry/provider_registry.py` | Discover bundled adapters plus explicit user installs under `~/.okstra/adapters/{hosts,providers}/<id>/`; project-local adapter code is outside the discovery roots |
315
320
  | `adapters/hosts/`, `adapters/providers/` | Six bundled host strategies and the independent provider catalogs; host manifests select a native provider without merging the two axes |
316
- | `lead_events.py` | structured JSONL events emitted by artifact-accounted lead runtimes |
321
+ | `lead_events.py` | Structured JSONL events emitted by artifact-accounted lead runtimes. Its locked append path assigns monotonic `A-NNN` identifiers to activity events in the same canonical event file. |
317
322
  | `team_reconcile.py` | stale team-member reconciliation at run-end teardown |
318
323
  | `worker_prompt_headers.py` | shared rendering of phase-aware worker prompt anchors (`worker_prompt_headers`): coding-preflight only for implementation and compact target identity for final-verification |
319
324
  | `worker_prompt_body.py` | provider-neutral initial analysis body/input renderer shared by Codex and external/team dispatch paths |
@@ -363,9 +368,10 @@ Token/cost accounting:
363
368
  | Path | Role |
364
369
  |---|---|
365
370
  | `launch.template.md` | Lead prompt template rendered for each run |
366
- | `duties/common.md`, `duties/<audience>.md` | Canonical common and functional duty contracts composed into every Okstra-owned LLM invocation; provider/model identity does not select the duty |
371
+ | `duties/common.md`, `duties/<audience>.md` | Canonical common and functional duty contracts composed into every Okstra-owned LLM invocation; `direction-selection-worker` owns direction comparison/validation while `planning-worker` realizes the selected direction; provider/model identity does not select the duty |
367
372
  | `profiles/_common-contract.md` | Shared phase contract |
368
373
  | `profiles/<task-type>.md` | Phase profiles (single language — runtime always loads from `profiles/`, never a translated mirror) |
374
+ | `implementation-option-selection.md` | Read-only lifecycle profile for candidate comparison or preselected-direction validation before detailed planning |
369
375
  | `project-analysis.md`, `feature-analysis.md`, `change-impact-analysis.md` | Read-only sidetrack profiles for project mapping, one-feature behavior tracing, and proposed-change impact mapping |
370
376
  | `wizard/prompts.ko.json` | Korean wizard prompt single source of truth |
371
377
 
@@ -375,8 +381,8 @@ Token/cost accounting:
375
381
  |---|---|
376
382
  | `templates/reports/final-report.template.md` | Schema v1 compatibility Markdown template |
377
383
  | `templates/reports/final-report-v2.template.md` | Schema v2 AI handoff Markdown spine |
378
- | `templates/reports/md/tasks/*.template.md`, `md/macros/sections.md` | Ten dedicated task bodies for the AI handoff Markdown, sibling of `html/tasks/`; shared section macro |
379
- | `templates/reports/html/base.template.html`, `html/tasks/*.template.html` | Shared HTML shell plus ten dedicated task templates for human reports; task bodies are not shared |
384
+ | `templates/reports/md/tasks/*.template.md`, `md/macros/sections.md` | Eleven dedicated task bodies for the AI handoff Markdown, sibling of `html/tasks/`; shared section macro |
385
+ | `templates/reports/html/base.template.html`, `html/tasks/*.template.html` | Shared HTML shell plus eleven dedicated task templates for human reports; task bodies are not shared |
380
386
  | `templates/reports/report.css`, `report.js` | Inline assets for self-contained HTML report views |
381
387
  | `templates/reports/*.template.md` | Inputs, schedule, user-response, settings templates |
382
388
  | `project-analysis-input.template.md`, `feature-analysis-input.template.md`, `change-impact-analysis-input.template.md` | Brief input templates for the three analysis sidetracks |
@@ -490,10 +496,11 @@ they are not published user skills.
490
496
  3. Resolve task identity segments, work category, and the run sequence input needed for path allocation.
491
497
  4. Provision or reuse the task-key worktree, or the selected implementation stage worktree for stage-isolated runs.
492
498
  5. For an analysis sidetrack, resolve the immutable source commit from the provisioned worktree's `HEAD`, then resolve evidence reports, freshness, and the feature target through `analysis_inputs.py`.
493
- 6. Compute task/run paths and persist run context under `runs/<task-type>/manifests/`.
494
- 7. Materialize `instruction-set/` files and lead prompt snapshot.
495
- 8. Persist run inputs, team state, task manifest, task index, run manifest, timeline, discovery pointers.
496
- 9. Record the run in `~/.okstra/{active,recent}.jsonl` and project index.
499
+ 6. For a new `implementation-planning` run, validate `--selected-direction` and materialize `instruction-set/selected-direction.json`; a same-task planning rerun validates its prior planning report instead.
500
+ 7. Compute task/run paths and persist run context under `runs/<task-type>/manifests/`.
501
+ 8. Materialize `instruction-set/` files and lead prompt snapshot.
502
+ 9. Persist run inputs, team state, task manifest, task index, run manifest, timeline, discovery pointers.
503
+ 10. Record the run in `~/.okstra/{active,recent}.jsonl` and project index.
497
504
 
498
505
  ### 5.2 Worktree model
499
506
 
@@ -530,7 +537,7 @@ Current report pipeline:
530
537
  4. For implementation-planning, `okstra plan-items extract` creates the complete `P-*` queue, `validate` proves it still matches data.json, and the analyser instances run the separate plan-body verification round.
531
538
  5. `scripts/okstra-render-final-report.py` renders compact AI handoff Markdown with `templates/reports/final-report-v2.template.md`.
532
539
  6. Token usage substitution fills usage/cost cells.
533
- 7. `scripts/okstra-render-report-views.py` independently selects one of ten dedicated task templates and emits human-facing HTML directly from the same data.json; run validation checks both derived artifacts. Schema v1 and quick Markdown inputs retain their legacy conditional path.
540
+ 7. `scripts/okstra-render-report-views.py` independently selects one of eleven dedicated task templates and emits human-facing HTML directly from the same data.json; run validation checks both derived artifacts. Schema v1 and quick Markdown inputs retain their legacy conditional path.
534
541
 
535
542
  For the three analysis sidetracks, the HTML view also exports an immutable-source `## ANALYSIS REVIEW` sidecar. A revision rerun carries that sidecar, reanalyzes the whole confirmed scope, and records one `analysisReviewResolution` row for every affected ID before `validate_analysis_report.py` accepts the result.
536
543
 
@@ -610,9 +617,10 @@ Project-local `<PROJECT_ROOT>/.claude/settings.local.json` is provisioned as a s
610
617
 
611
618
  | Phase | Purpose | Typical next step |
612
619
  |---|---|---|
613
- | `requirements-discovery` | Classify and route work | `error-analysis` or `implementation-planning` |
614
- | `error-analysis` | Reproduce and explain failure | `implementation-planning` |
615
- | `implementation-planning` | Compare options, produce approval-ready plan; the output is always the `## 5.5 Stage Map` + N `## 5.5.<i> Stage <i>` section structure. `implementation` can be split and run per stage | `implementation` after approval |
620
+ | `requirements-discovery` | Classify and route work | `error-analysis` or `implementation-option-selection` |
621
+ | `error-analysis` | Reproduce and explain failure | `implementation-option-selection` |
622
+ | `implementation-option-selection` | Compare or validate directions; display at most three exact-coverage candidates | `implementation-planning` after direction confirmation |
623
+ | `implementation-planning` | Realize one selected direction as an approval-ready Stage Map and exact-coverage plan | `implementation` after separate plan approval, or `implementation-option-selection` if invalidated |
616
624
  | `implementation` | Executor changes code, verifiers check independently | `final-verification` |
617
625
  | `final-verification` | Read-only acceptance verification | `release-handoff` if accepted |
618
626
  | `release-handoff` | User-selected commit/PR handoff | done or follow-up |
@@ -650,6 +658,8 @@ Edit English canonical Markdown sources directly. After changing a path register
650
658
  | `S-NNN` | Secondary evidence or alternate interpretation |
651
659
  | `R-NNN` | Missing information / risk |
652
660
  | `RR-NNN` | Residual risk |
661
+ | `IO-NNN` | Ranked or audited implementation direction in option selection |
662
+ | `P-Dir-1` | Selected direction realization item used by plan-body verification |
653
663
  | `P-Opt-*` | Plan option item used by plan-body verification |
654
664
  | `P-Step-*` | Plan execution step item |
655
665
  | `P-Dep-*` | Plan dependency / migration item |
@@ -658,7 +668,7 @@ Edit English canonical Markdown sources directly. After changing a path register
658
668
  | `FU-NNN` | Follow-up task |
659
669
  | `worker:item` | Source item pointer preserved from worker result into final report |
660
670
  | `Verdict Token` | `accepted`, `conditional-accept`, `blocked`, `not-applicable` |
661
- | `Direction` | `continue-investigation`, `begin-implementation`, `approve`, `reject`, `hold` |
671
+ | `Direction` | `continue-investigation`, `begin-option-selection`, `begin-implementation`, `approve`, `reject`, `hold` |
662
672
 
663
673
  Clarifications now live in the unified `## 1. Clarification Items` table. Deprecated `5.1` / `5.2` split sections are no longer part of the schema.
664
674
 
@@ -40,7 +40,8 @@ flowchart TD
40
40
  |---|---|---|
41
41
  | `requirements-discovery` | [requirements-discovery.md](requirements-discovery.md) | Classify the request and choose the next safe phase. |
42
42
  | `error-analysis` | [error-analysis.md](error-analysis.md) | Find cause candidates and validation paths from symptoms and evidence. |
43
- | `implementation-planning` | [implementation-planning.md](implementation-planning.md) | Produce a plan with implementation options, verification, rollback, and an approval gate. |
43
+ | `implementation-option-selection` | [implementation-option-selection.md](implementation-option-selection.md) | Compare or validate exact-coverage directions before detailed planning. |
44
+ | `implementation-planning` | [implementation-planning.md](implementation-planning.md) | Realize one selected direction as an exact-coverage plan with a separate approval gate. |
44
45
  | `implementation` | [implementation.md](implementation.md) | The executor implements the approved plan and the verifier verifies it independently. |
45
46
  | `final-verification` | [final-verification.md](final-verification.md) | Judge whole-task or single-stage acceptance of the implementation result. |
46
47
  | `release-handoff` | [release-handoff.md](release-handoff.md) | Perform the push/PR handoff lead-only after an accepted verdict. |
@@ -69,8 +70,9 @@ flowchart TD
69
70
  | task-type | wizard special question | runtime prepare gate | lead/worker mode | next phase default |
70
71
  |---|---|---|---|---|
71
72
  | `requirements-discovery` | common questions only | profile/brief/base-ref exist | multi-worker analysis, convergence 1 round default | `pending-routing-decision` |
72
- | `error-analysis` | common questions only | profile/brief/base-ref exist | multi-worker analysis, convergence 2 rounds default | `implementation-planning` |
73
- | `implementation-planning` | common questions only | profile/brief/base-ref exist | multi-worker analysis + Phase 6 plan-body verification | `implementation` |
73
+ | `error-analysis` | common questions only | profile/brief/base-ref exist | multi-worker analysis, convergence 2 rounds default | `implementation-option-selection` |
74
+ | `implementation-option-selection` | comparison or preselected-validation context | stable brief IDs and at least three analysers | read-only candidate validation, exact coverage, separate direction confirmation | `implementation-planning` or `blocked` |
75
+ | `implementation-planning` | selected-direction report for a new plan | selection report/sidecar/digest or same-task planning rerun | one-direction realization + Phase 6 plan-body verification | `implementation` after plan approval |
74
76
  | `implementation` | approved plan, stage multi-pick, executor | approved marker, Stage Lifecycle Snapshot, stage-key reservation, QA command deny-list | one run = one stage; executor writes in isolated stage worktree, verifiers read-only | `final-verification` |
75
77
  | `final-verification` | approved plan, stage pick (whole-task or single-stage) | `VERIFICATION_TARGET` resolved; whole-task auto integration/teardown or single-stage worktree reuse | whole-task may integrate stages first; analyser verification itself is read-only | `pending-release-handoff` |
76
78
  | `release-handoff` | handoff scope (stage-group or whole-task), PR template override/scope | Stage Lifecycle Snapshot eligibility, generated `release-handoff-input.md`, empty worker roster | single-lead; whole-task PR or stage-group collector branch/PR | `done-or-follow-up` |
@@ -57,7 +57,7 @@ sequenceDiagram
57
57
 
58
58
  For canonical briefs, preflight runs before worker resolution, worktree provisioning, or report creation. A brief whose `reporter-confirmations` status is `pending` stops at this point; legacy briefs keep the compatibility path.
59
59
 
60
- The final report records its next phase in `errorAnalysis.routing.nextTaskType`. After report validation passes, workflow metadata persists that route as `nextRecommendedPhase`. The static `error-analysis` → `implementation-planning` mapping is a fallback only when report data is missing, legacy, or not an error-analysis report.
60
+ The final report records its next phase in `errorAnalysis.routing.nextTaskType`. After report validation passes, workflow metadata persists that route as `nextRecommendedPhase`. A credible cause uses `implementation-option-selection`; continued investigation uses `error-analysis`. The static fallback also routes a missing or legacy error-analysis report to option selection.
61
61
 
62
62
  ## 4. lead execution flow
63
63
 
@@ -92,7 +92,7 @@ The expected final-report content is:
92
92
  - practical next diagnostic steps
93
93
  - if there is blocking uncertainty, `## 1. Clarification Items`, usually `Blocks=next-phase`
94
94
 
95
- For `error-analysis`, the structured `errorAnalysis` object is the source of truth for the verbatim symptom, reproduction status, `EA-NNN` cause candidates and their counter-evidence, the next diagnostic, and routing. Its shape is enforced by `schemas/final-report-v1.0.schema.json` `$defs.ErrorAnalysis`; `validators/validate-run.py::_validate_error_analysis_consistency` enforces the cross-field semantics. A route to `implementation-planning` needs a credible referenced leading cause and `begin-planning`. A route back to `error-analysis` needs the sharp next diagnostic and `continue-investigation`.
95
+ For `error-analysis`, the structured `errorAnalysis` object is the source of truth for the verbatim symptom, reproduction status, `EA-NNN` cause candidates and their counter-evidence, the next diagnostic, and routing. Its shape is enforced by the final-report schema; `validators/validate-run.py::_validate_error_analysis_consistency` enforces the cross-field semantics. A route to `implementation-option-selection` needs a credible referenced leading cause and `begin-option-selection`. A route back to `error-analysis` needs the sharp next diagnostic and `continue-investigation`.
96
96
 
97
97
  What is prohibited is source edit, refactor, fix attempt, implementation design artifact, and running build/migration/deploy. Deferring ambiguity that could be answered from code or logs to a user question is also a defect per the profile.
98
98
 
@@ -112,7 +112,7 @@ flowchart TD
112
112
  Verdict{Verdict Token}
113
113
  Verdict -->|accepted| Release[route to release-handoff or done]
114
114
  Verdict -->|conditional-accept| Conditions[conditions listed exhaustively]
115
- Conditions --> Followup[route to error-analysis or implementation-planning]
115
+ Conditions --> Followup[route by cause, direction, or detailed-plan defect]
116
116
  Verdict -->|blocked| Blockers[acceptance blockers with evidence]
117
117
  Blockers --> Followup
118
118
  ```
@@ -165,7 +165,7 @@ flowchart TD
165
165
  FV -. forbidden .-> Hide[hide verifier dissent]
166
166
  ```
167
167
 
168
- The stage merge/teardown of whole-task mode is a runtime-owned integration step that prepare performs. After that, lead verification is read-only. Source edit, follow-up fix, and scope expansion are all forbidden. When a defect is found, it is not fixed within the current run; instead it is recorded as a blocker in the final report and handed off as new `error-analysis` or `implementation-planning` input.
168
+ The stage merge/teardown of whole-task mode is a runtime-owned integration step that prepare performs. After that, lead verification is read-only. Source edit, follow-up fix, and scope expansion are all forbidden. When a defect is found, it is not fixed within the current run. Cause defects route to `error-analysis`, selected-direction defects route to `implementation-option-selection`, and detailed-plan defects route to `implementation-planning`.
169
169
 
170
170
  ## 8. Verified code
171
171
 
@@ -0,0 +1,70 @@
1
+ # implementation-option-selection process
2
+
3
+ ## Index
4
+
5
+ - [1. Purpose](#1-purpose)
6
+ - [2. Execution modes](#2-execution-modes)
7
+ - [3. Prepare gates](#3-prepare-gates)
8
+ - [4. Candidate validation and ranking](#4-candidate-validation-and-ranking)
9
+ - [5. Direction confirmation and planning handoff](#5-direction-confirmation-and-planning-handoff)
10
+ - [6. Forbidden actions](#6-forbidden-actions)
11
+ - [7. Verified code](#7-verified-code)
12
+
13
+ ## 1. Purpose
14
+
15
+ `implementation-option-selection` is the read-only lifecycle phase between cause analysis and detailed planning. It decides which implementation mechanism and architecture boundary planning may realize. It does not name the exact file list, split stages, or prescribe test commands.
16
+
17
+ Direction confirmation and detailed plan approval are independent user decisions. Confirming a direction permits planning to begin. It does not approve the plan or permit implementation.
18
+
19
+ ## 2. Execution modes
20
+
21
+ | Mode | Input | Output |
22
+ |---|---|---|
23
+ | `candidate-comparison` | Requirement ledger, cause evidence, code evidence, independently proposed raw candidates | At most three ranked valid directions and a separate user selection |
24
+ | `preselected-validation` | A direction already fixed by upstream evidence or an explicit user instruction | One normalized and validated direction, or `blocked`; no alternative is generated |
25
+
26
+ The normal analyser roster contains at least three analyser workers plus the report writer. Each analyser may propose at most three raw candidates. All analysers reassess the merged candidate set before ranking.
27
+
28
+ ## 3. Prepare gates
29
+
30
+ Prepare rejects the phase when the brief has no stable `EB-NNN`, `PB-NNN`, or `EO-NNN` requirement IDs. External Gates are not part of that denominator. Prepare also rejects a roster with fewer than three analysers.
31
+
32
+ The phase reuses the task-key worktree and may inspect the code and prior task artifacts. It does not obtain a writable implementation-stage worktree.
33
+
34
+ ## 4. Candidate validation and ranking
35
+
36
+ Every displayed candidate has all of the following properties:
37
+
38
+ - `coveragePercent == 100`
39
+ - `scopePrecisionPercent == 100`
40
+ - `coverageVerdict == exact`
41
+ - no `unmappedCommitments`
42
+ - no `contradictedRequirements`
43
+ - supporting code or upstream evidence
44
+ - at least two feasibility votes
45
+ - no safety blocker or unresolved implementation-critical external fact
46
+
47
+ The final report can display one, two, or three valid candidates. Rejected candidates remain in `candidateAudit` with their rejection reasons and cannot be selected. If no candidate is valid, the report uses `blocked` and planning cannot start.
48
+
49
+ Ranking uses eight fixed criteria with per-run weights: requirement fit, architecture fit, change locality, implementation complexity, correctness risk, reversibility, verification cost, and rollout cost. Safety and exact-coverage failures override the weighted score.
50
+
51
+ ## 5. Direction confirmation and planning handoff
52
+
53
+ Comparison mode exports a `DIRECTION SELECTION` block in the user-response sidecar. Prepare validates the selected ID against the displayed candidates and binds the response to the report's sibling data JSON through its SHA-256 digest.
54
+
55
+ A new planning run receives the selection report through `--selected-direction`. Prepare normalizes the validated choice into `instruction-set/selected-direction.json`. Planning cites that snapshot through `selectedDirectionRef` and writes `approved: false` until the user separately approves the detailed plan.
56
+
57
+ If planning proves that the mechanism or architecture boundary cannot satisfy exact coverage, it emits `direction-invalidated` and routes back to `implementation-option-selection`. It never picks the next ranked direction automatically.
58
+
59
+ ## 6. Forbidden actions
60
+
61
+ This phase does not edit source code, run builds or tests, execute migrations, deploy, or call a write API. Candidate details do not contain exact file lists, stage maps, or test commands. Those details belong to `implementation-planning` after direction confirmation.
62
+
63
+ ## 7. Verified code
64
+
65
+ - [`prompts/profiles/implementation-option-selection.md`](../../prompts/profiles/implementation-option-selection.md)
66
+ - [`prompts/duties/direction-selection-worker.md`](../../prompts/duties/direction-selection-worker.md)
67
+ - [`scripts/okstra_ctl/implementation_options.py`](../../scripts/okstra_ctl/implementation_options.py)
68
+ - [`scripts/okstra_ctl/implementation_direction.py`](../../scripts/okstra_ctl/implementation_direction.py)
69
+ - [`scripts/okstra_ctl/exact_coverage.py`](../../scripts/okstra_ctl/exact_coverage.py)
70
+ - [`validators/validate-run.py`](../../validators/validate-run.py)
@@ -12,7 +12,9 @@
12
12
 
13
13
  ## 1. Purpose
14
14
 
15
- `implementation-planning` is the phase that decides the implementation direction before coding. It produces at least two implementation options, trade-offs, a recommended option, a stepwise execution order, a validation checklist, and a rollback strategy, and it places a user approval gate.
15
+ `implementation-planning` realizes one direction that was already confirmed by `implementation-option-selection`. It turns that mechanism and architecture boundary into a file-level Stage Map, validation checklist, rollback strategy, and exact requirement-coverage map. The resulting detailed plan has its own approval gate; direction confirmation does not approve it.
16
+
17
+ An existing plan without `planningContract: selected-direction` remains on the legacy candidate-plan contract for compatibility. A new planning run uses the selected-direction contract and does not generate or rank alternatives.
16
18
 
17
19
  ## 2. okstra-run wizard flow
18
20
 
@@ -20,7 +22,11 @@
20
22
  flowchart TD
21
23
  Start[/okstra-run/] --> Common[common task identity flow]
22
24
  Common --> Type[task-type = implementation-planning]
23
- Type --> Worktree{active task worktree?}
25
+ Type --> Input{new plan or planning rerun?}
26
+ Input -->|new| Direction[selected-direction report pick]
27
+ Input -->|rerun| Prior[prior planning report via clarification-response]
28
+ Direction --> Worktree{active task worktree?}
29
+ Prior --> Worktree
24
30
  Worktree -->|yes| Defaults[Use defaults / Customize]
25
31
  Worktree -->|no| BaseRef[base-ref pick/text]
26
32
  BaseRef --> Defaults
@@ -33,7 +39,7 @@ flowchart TD
33
39
  Confirm --> Render[render-bundle]
34
40
  ```
35
41
 
36
- The wizard currently does not ask about `--no-plan-verification`. On the okstra-run path, plan-body verification is prepared as enabled by default. The shell/CLI path has a `--no-plan-verification` flag.
42
+ For a new plan, the wizard asks for a validated option-selection report and passes it as `--selected-direction`. A planning clarification rerun passes its own prior report through `--clarification-response`. The wizard currently does not ask about `--no-plan-verification`; on the okstra-run path, plan-body verification is prepared as enabled by default.
37
43
 
38
44
  ## 3. prepare_task_bundle handling
39
45
 
@@ -44,8 +50,10 @@ sequenceDiagram
44
50
  participant R as render.py
45
51
  participant M as manifests
46
52
 
47
- W->>P: task-type=implementation-planning
53
+ W->>P: task-type=implementation-planning + selected-direction or prior planning report
48
54
  P->>P: validate profile/brief/base-ref
55
+ P->>P: validate selection report, data digest, response, and selected option
56
+ P->>M: write instruction-set/selected-direction.json
49
57
  P->>P: resolve profile workers + optional override
50
58
  P->>P: resolve model metadata
51
59
  P->>P: provision/reuse task worktree
@@ -55,7 +63,7 @@ sequenceDiagram
55
63
  P-->>W: prepared lead prompt
56
64
  ```
57
65
 
58
- The runtime prepare stage does not block source edits itself; instead it "bakes the current phase boundary into the lead prompt and manifest." The actual no-edit/no-build rules must be honored by the lead and workers reading the profile.
66
+ Prepare rejects a new plan without a selected-direction report. Comparison mode requires a valid `DIRECTION SELECTION` sidecar, while preselected-validation mode uses the confirmed upstream direction without one. The normalized snapshot binds the source report, source-data digest, option ID, direction body, requirements, and invariants.
59
67
 
60
68
  ## 4. lead execution flow
61
69
 
@@ -72,8 +80,8 @@ flowchart TD
72
80
  RW --> Extract[Deterministic plan-item extraction]
73
81
  Extract --> PBV[Phase 6 sub-step<br/>Plan-body verifier round]
74
82
  PBV --> Gate{gate result}
75
- Gate -->|passed / passed-with-dissent| Approval[render top Approval checkbox]
76
- Gate -->|blocked-by-disagreement / aborted-non-result| NoApproval[render block without checkbox]
83
+ Gate -->|passed / passed-with-dissent| Approval[render plan decision approval control]
84
+ Gate -->|blocked-by-disagreement / aborted-non-result| NoApproval[render blocked plan decision]
77
85
  Approval --> P7[Phase 7 persistence/finalization<br/>canonical Markdown render<br/>HTML render + validate-run<br/>via okstra report-finalize]
78
86
  NoApproval --> P7
79
87
  ```
@@ -118,9 +126,8 @@ Plan approval and design-preparation status are independent gates. If plan-body
118
126
 
119
127
  ```mermaid
120
128
  flowchart LR
121
- Options[Option Candidates] --> Matrix[Trade-off Matrix]
122
- Matrix --> Rec[Recommended Option]
123
- Rec --> Stages[Stage Map + Stage Exit/Validation]
129
+ Direction[Selected Direction Snapshot] --> Realize[Direction Realization]
130
+ Realize --> Stages[Stage Map + Stage Exit/Validation]
124
131
  Stages --> Prep[Implementation Design Preparation]
125
132
  Prep --> Dep[Dependency / Migration Risk]
126
133
  Dep --> Val[Validation Checklist]
@@ -130,11 +137,10 @@ flowchart LR
130
137
  Approval --> Impl[Next run: implementation]
131
138
  ```
132
139
 
133
- Because the validator searches for the English substring of the section heading, the following strings must remain verbatim on the heading line.
140
+ The selected-direction branch verifies `P-Dir-1` before its stage, dependency, validation, rollback, requirement, preparation, and variation items. `P-Dir-1` proves that the plan preserves the selected mechanism, architecture boundary, invariants, and user constraints. The legacy branch continues to extract `P-Opt-*` from its option candidates.
141
+
142
+ The detailed selected-direction plan retains these deliverable surfaces:
134
143
 
135
- - `Option Candidates`
136
- - `Trade-off`
137
- - `Recommended Option`
138
144
  - `Stage Map`
139
145
  - `Stage Exit Contract`
140
146
  - `Stage Validation`
@@ -146,7 +152,9 @@ Because the validator searches for the English substring of the section heading,
146
152
  - `Requirement Coverage`
147
153
  - `Implementation Design Preparation`
148
154
 
149
- Approval is recorded with `approved: true` in the YAML frontmatter and the chosen `implementation-option`. If a `Blocks=approval` clarification row is unresolved, the implementation prepare rejects it even when the frontmatter is in an approved state. The `blocked` status of design-preparation is not the same as `Blocks=approval`, and it operates only at that stage's implementation preflight.
155
+ Approval is recorded with `approved: true` in YAML frontmatter. A selected-direction plan has no `implementation-option:` field and rejects `--implementation-option` before any approval-file mutation. If a `Blocks=approval` clarification row is unresolved, implementation prepare rejects the plan even when frontmatter is approved. Existing candidate plans keep their legacy option field and execution behavior.
156
+
157
+ `plan-ready` requires 100% requirement coverage, 100% scope precision, and no unmapped stage or file change. If the selected mechanism or boundary cannot meet those conditions, planning emits `direction-invalidated` without an executable Stage Map and routes back to `implementation-option-selection`. It does not choose another direction automatically.
150
158
 
151
159
  ## 6. Forbidden actions
152
160
 
@@ -11,7 +11,7 @@
11
11
 
12
12
  ## 1. Purpose
13
13
 
14
- `requirements-discovery` classifies the request before implementation. It determines which of bugfix, feature, improvement, refactor, or ops it is, and chooses whether the next safe phase is `error-analysis` or `implementation-planning`. Going directly to `implementation` is not valid per the profile. Implementation can only start once an approved `implementation-planning` report exists.
14
+ `requirements-discovery` classifies the request before implementation. It determines which of bugfix, feature, improvement, refactor, or ops it is, and chooses whether the next safe phase is `error-analysis` or `implementation-option-selection`. Going directly to planning or implementation is not valid for a new direction. Implementation can only start once a selected direction has been expanded into a separately approved `implementation-planning` report.
15
15
 
16
16
  ## 2. okstra-run wizard flow
17
17
 
@@ -90,7 +90,7 @@ flowchart LR
90
90
  RD --> Domain[Domain Alignment<br/>terminology resolution]
91
91
  RD --> Route{next safe phase}
92
92
  Route --> EA[error-analysis]
93
- Route --> IP[implementation-planning]
93
+ Route --> IOS[implementation-option-selection]
94
94
  Route -. invalid .-> Impl[implementation<br/>not allowed directly]
95
95
  ```
96
96
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okstra",
3
- "version": "0.171.0",
3
+ "version": "0.173.0",
4
4
  "description": "Host-aware multi-provider cross-verification orchestrator runtime and agent skills.",
5
5
  "license": "MIT",
6
6
  "author": "devonshin",
@@ -1,5 +1,5 @@
1
1
  {
2
- "package": "0.171.0",
3
- "builtAt": "2026-08-15T08:20:00.683Z",
2
+ "package": "0.173.0",
3
+ "builtAt": "2026-08-16T04:09:59.317Z",
4
4
  "repoRoot": "/home/runner/work/okstra/okstra"
5
5
  }
@@ -102,12 +102,36 @@ You author the final-report data.json (the JSON SSOT). You author it against the
102
102
 
103
103
  The AI handoff Markdown is an agent-facing ledger: verdict, routing, clarification decisions, evidence, one structured task deliverable, and execution audits. The human HTML is the reader-facing explanation: `humanSummary` plus the selected task block's `userNarrative` and structured facts. Populate both human fields in data.json even though the Markdown intentionally omits their full prose. Worker discussion, convergence mechanics, and token usage belong to audit data and must not be copied into the HTML human main body.
104
104
 
105
+ ### Implementation-planning frontmatter contract
106
+
107
+ #### Selected-direction
108
+
109
+ 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.
110
+
111
+ #### Legacy candidate-comparison
112
+
113
+ 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.
114
+
115
+ ### General authoring rules
116
+
105
117
  Rules (the schema enforces most of these — they are listed here so you know *what* to populate, not *how* to validate):
106
118
 
107
119
  - Read the exact permitted header values from the task bundle schema excerpt. In the current v2 contract, `header.reportOwner` is `"Okstra lead"` and `header.reportAuthor` is `"Report writer worker"`. Set author to `"Okstra lead"` only for `release-handoff` runs (single-lead by design) or a recorded report-writer dispatch failure fallback. A legacy v1 excerpt may retain its historical compatibility values; follow that excerpt rather than inferring ownership from the provider.
108
120
  - **Source items (worker:item) preservation.** Every `consensus[].sourceItems`, `differences[].workersPosition[].itemId`, and `evidence.primary[].sourceItems` entry MUST carry the worker:item-id pair (e.g. `claude:F-001`, `codex:1.1`, `antigravity:F-3`, or `lead:mcp-1` for lead-only evidence). The schema enforces this via the `SourceItem` regex; bare worker-name lists no longer parse.
109
121
  - **Verdict Card consistency.** `verdictCard.verdictToken` and `verdictCard.direction` MUST byte-match `finalVerdict.verdictToken` / `.direction`; `validators/validate-run.py` diffs both and fails the run on divergence. `verdictCard.nextStep` names the same action as `finalVerdict.nextStep` and `recommendedNextSteps[0].text` but is written as the actionable command the reader runs (e.g. `/okstra-run task-key=… task-type=release-handoff`) where the other two are prose — it is deliberately not a byte copy. Duplicating the compared values across `verdictCard` and `finalVerdict` is intentional so the validator can diff them.
110
- - **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-planning` with `direction=begin-planning`, 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. Phase validation MUST enforce exact target agreement and uniqueness through `validators/validate-run.py::_validate_error_analysis_consistency`; until that check is implemented and executed, those semantics are contract requirements rather than enforced guarantees.
122
+ - **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.
123
+ - **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`.
124
+ - **Implementation-planning direction branch.** For `planningContract: selected-direction`, read `selectedDirectionRef` and its snapshot, then preserve their core mechanism, architecture boundaries, and planning invariants in `directionRealization`. Materialize files, interfaces, stages, validation, rollback, and bidirectional original-requirement links without candidate generation, scoring, recommendation, or user candidate selection. Author exactly one `P-Dir-1` whose payload is the complete `directionRealization`; its verifier checks those preserved properties and any hidden direction change. If the direction must change, author `direction-invalidated` and no execution queue. Legacy candidate-comparison reruns retain Option Candidates, trade-offs, Recommended Option, and `P-Opt-*` semantics.
125
+
126
+ ```json
127
+ {
128
+ "candidateDetailBoundary": {
129
+ "expectedChangeAreas": "direction-level-only",
130
+ "expectedVerification": "direction-level-signals-only",
131
+ "forbidden": ["exact-file-lists", "stage-lists", "test-commands"]
132
+ }
133
+ }
134
+ ```
111
135
  - **Human narrative.** Populate required `humanSummary` and the selected task block's `userNarrative`. Human-visible analysis facts must not exist only in Markdown; HTML is derived independently and can use only data.json. Keep worker discussion and audit details in `crossVerification`, `executionStatus`, and `tokenUsage`, outside the human narrative fields.
112
136
  - **External QA advisory.** A Tier 3 entry requiring `db`, `http`, or
113
137
  `external` may be non-PASS without changing approval or final verdict. Render
@@ -116,7 +140,7 @@ Rules (the schema enforces most of these — they are listed here so you know *w
116
140
  and add the exact rerun command to `recommendedNextSteps`. Never turn this
117
141
  advisory alone into a clarification, Acceptance Blocker, conditional
118
142
  acceptance condition, or blocked routing.
119
- - **§7 phase-continuation row (mandatory for non-terminal task-types).** When `header.taskType` is one of `requirements-discovery` / `implementation-planning` / `error-analysis` / `implementation` / `final-verification`, `followUpTasks` MUST contain at least one row whose `origin` is `phase-continuation`, `newTaskId` reuses the current task-id, `autoSpawn` is `"no"`, and `priority` is `"P0"`. For `release-handoff` runs, omit the phase-continuation row. The schema `allOf` / `contains` clause enforces row presence, not exact route-target agreement or uniqueness; phase validation must enforce those error-analysis semantics as specified above.
143
+ - **§7 phase-continuation row (mandatory for non-terminal task-types).** When `header.taskType` is one of `requirements-discovery` / `implementation-option-selection` / `implementation-planning` / `error-analysis` / `implementation` / `final-verification`, `followUpTasks` MUST contain at least one row whose `origin` is `phase-continuation`, `newTaskId` reuses the current task-id, `autoSpawn` is `"no"`, and `priority` is `"P0"`. For `release-handoff` runs, omit the phase-continuation row. The schema `allOf` / `contains` clause enforces row presence, not exact route-target agreement or uniqueness; phase validation must enforce those error-analysis semantics as specified above.
120
144
  - **No deprecated sections.** The schema has no `4.5.8 User Approval Request` body field, no `4.5.9 Open Questions`, no `5.1 Additional Material Request`, no `5.2 User Confirmation Questions` — clarifications go under the unified `clarificationItems[]` array.
121
145
  - **Optional Section 0.** Include `clarificationCarryIn` ONLY when the lead's prompt provides a non-empty carry-in path. Omit the key entirely otherwise (do NOT set it to `null` or an empty object).
122
146
  - **Reading Confirmation** goes at `**Audit sidecar path:**` per the selected report-writer preamble's `Required reading` section — never in the data.json or the main worker-results file.
@@ -129,10 +153,10 @@ Rules (the schema enforces most of these — they are listed here so you know *w
129
153
  - Cite file paths and line numbers in every `evidence.primary[].source` / `consensus[].evidence` cell.
130
154
  - Preserve every analysis worker's ticket tagging — every row's `ticketId` field carries the ticket key or the task-fallback. For single-ticket runs, set `ticketCoverage` to `{"singleTicket": "<ticket>"}`. For runs that do not require ticket tagging (`release-handoff`, `final-verification`), set `ticketCoverage` to `{"omit": true}`.
131
155
  - For `requirements-discovery`, `error-analysis`, and `implementation-planning`, populate the top-level `endStateCoverage` with exactly one row per end-state id the brief declares — no more, no fewer. `disposition` is one of `addressed` / `deferred` / `not-applicable` / `blocked`. `addressed` requires a `coveredBy` anchor in THIS phase's own deliverable (requirements-discovery: the routing decision, the fan-out unit id, or the `C-NNN` clarification; error-analysis: the root-cause candidate or the next diagnostic; implementation-planning: the `R-NNN` row); every other disposition requires a `rationale`. Do not author a goal of your own here and do not restate the brief — this table records only how this phase accounted for what the reporter already pinned. When the brief declares no end-state ids (a brief authored before those sections existed), omit the field entirely. **Enforced:** `validators/validate-run.py` `_validate_end_state_coverage`.
132
- - For `implementation-planning`, populate `implementationPlanning.requirementCoverage` with one row per concrete requirement from the brief / packet, using IDs `R-001`, `R-002`, ... in source order. A `covered` row's `coveredBy` MUST name the specific Option Candidate plus Stage/Step that satisfies the requirement. Use `status: "covered"` only when the report's plan actually covers it; use `documented-deviation` only when `coveredBy` states the concrete alternative and the row records non-empty unique `decisionRefs` plus `approvalDisposition`. Each `C-NNN` ref must name a clarification in this report; each `D-NNNN` ref must name a `decisionDrafts[].number`. `approvalDisposition: "accepted"` requires a referenced clarification with `status: answered|resolved` and non-empty `userInput`; `approvalDisposition: "blocked C-NNN"` requires that same-report clarification to be `status: open, blocks: approval`. Otherwise use `gap` or `blocked C-NNN` and ensure the corresponding `Clarification Items` row blocks approval. Do not collapse this into `ticketCoverage`; ticket coverage is not requirement coverage. **Enforced:** `schemas/final-report-v2.0.schema.json` `$defs.ImplementationRequirementCoverageRow` and `validators/validate-run.py` `_validate_requirement_deviations`.
133
- - For `implementation-planning`, each `requirementCoverage` row's `source` is a graded cell, not prose — free text like `"carry-in from requirements-discovery C-001"` is rejected. Write exactly one of: `brief:EB-001` / `brief:PB-001` / `brief:EO-001`, an end-state id the brief declares — when the brief pins ids, citing a heading instead is rejected, because every brief carries the same generic headings and a heading cannot say WHICH reporter line the requirement came from (only a brief authored before the end-state sections existed still takes the older `brief:<heading>` form, and there the heading must literally exist in it); `derived:R-NNN — <one-line reason>`, whose chain must terminate at a `brief:` or `contract:` row of the same table without cycling; or `contract:<rule>`, for artifacts okstra's own phase contract mandates, whose allowlist is exactly the two tokens `decision-record-step` (the §5.4 Decision Drafts materialization step) and `glossary-step` (the glossary proposal step) — any other rule name is rejected, so never invent one. (Maintainer SSOT for that allowlist: `scripts/okstra_ctl/scope_provenance.py` in the okstra repo.) A requirement you cannot source this way does not belong in the table: put it in `clarificationItems[]` with `Blocks=approval`. **Enforced:** `validators/validate-run.py` `_validate_requirement_provenance`. In the same table, anchor every stage number in `coveredBy` to a `Stage` / `Stages` word (`Stage 2`, `Stages 1-3`) — `_validate_stage_has_requirement` reads that cell as prose and fails the plan when a Stage Map stage is cited by no row.
134
- - For `implementation-planning`, also populate `implementationPlanning.decisionDrafts` (one row per decision meeting all three decision-record criteria; `[]` otherwise) and `implementationPlanning.skippedAdrCandidates` (evaluated-but-dropped adr-candidates; `[]` otherwise). The schema excerpt enumerates the row shape; the renderer emits §5.4 `### Decision Drafts`. When `decisionDrafts` is non-empty, the plan's stages MUST carry a stepwise step that creates `.okstra/decisions/<NNNN>-<slug>.md` (validate-run gates this).
135
- - For `implementation-planning`, populate `implementationPlanning.variationPointAnalysis` — a `hasMultipleImplementations` judgement synthesized from the analysis workers' output, not a field filled in last. When it is `true`, write one `points[]` row per varying behavior carrying `behavior`, the two or more `implementations` that serve it, `evidence` (a `path:line`, or the sibling task / stage that already implements that behavior), and an `extractionDecision` of `extract` / `interfaceKind` / `coveredBy` (the Stage Map stage that builds the interface) / `rationale`; when it is `false`, write a non-empty `noVariationRationale` and leave `points` empty (the two branches are mutually exclusive). Do NOT pass a boilerplate rationale — `false` is the cheaper field to fill, and a `false` declaration the brief or the sibling code in the workers' evidence contradicts is a `P-Var` DISAGREE, not a saving. Also populate `implementationPlanning.recommendedOption.testSeams`: one row per boundary a test injects at and replaces, each carrying `boundary` / `injectedAs` / `replacedInTest`. An empty list is a conscious "no seam needed" claim, never a default for a field nobody filled. The schema excerpt enumerates both row shapes — author against it. (Maintainer SSOT for these two rules: the `Required deliverable shape` bullet in `prompts/profiles/implementation-planning.md` in the okstra repo; that path is not resolvable here, so it is provenance, not a file to open.) **Enforced:** `schemas/final-report-v2.0.schema.json` `$defs.VariationPointAnalysis` / `$defs.VariationPoint` (the block is in `implementationPlanning.required`) plus `testSeams` in `$defs.RecommendedOption`'s `required`; `validators/validate-run.py` `_validate_variation_point_analysis` rejects a rationale-less `false`, a `false` carrying points, a `true` with no point, an `extract: true` decision leaving `interfaceKind` or `coveredBy` empty, and a hexagonal project extracting as anything but a port; and every point becomes a `P-Var-*` plan item judged in §5.5.9.
156
+ - For selected-direction `implementation-planning`, preserve each original requirement ID and populate its `stageRefs`, `stepRefs`, `validationRefs`, and `fileRefs`; `validate_selected_direction_plan` enforces forward and reverse exact coverage. For legacy candidate-comparison `implementation-planning`, populate `implementationPlanning.requirementCoverage` with one row per concrete requirement from the brief / packet, using IDs `R-001`, `R-002`, ... in source order. A `covered` row's `coveredBy` MUST name the specific Option Candidate plus Stage/Step that satisfies the requirement. Use `status: "covered"` only when the report's plan actually covers it; use `documented-deviation` only when `coveredBy` states the concrete alternative and the row records non-empty unique `decisionRefs` plus `approvalDisposition`. Each `C-NNN` ref must name a clarification in this report; each `D-NNNN` ref must name a `decisionDrafts[].number`. `approvalDisposition: "accepted"` requires a referenced clarification with `status: answered|resolved` and non-empty `userInput`; `approvalDisposition: "blocked C-NNN"` requires that same-report clarification to be `status: open, blocks: approval`. Otherwise use `gap` or `blocked C-NNN` and ensure the corresponding `Clarification Items` row blocks approval. Do not collapse this into `ticketCoverage`; ticket coverage is not requirement coverage. **Enforced:** `schemas/final-report-v2.0.schema.json` `$defs.ImplementationRequirementCoverageRow` and `validators/validate-run.py` `_validate_requirement_deviations`.
157
+ - For legacy candidate-comparison `implementation-planning`, each `requirementCoverage` row's `source` is a graded cell, not prose — free text like `"carry-in from requirements-discovery C-001"` is rejected. Write exactly one of: `brief:EB-001` / `brief:PB-001` / `brief:EO-001`, an end-state id the brief declares — when the brief pins ids, citing a heading instead is rejected, because every brief carries the same generic headings and a heading cannot say WHICH reporter line the requirement came from (only a brief authored before the end-state sections existed still takes the older `brief:<heading>` form, and there the heading must literally exist in it); `derived:R-NNN — <one-line reason>`, whose chain must terminate at a `brief:` or `contract:` row of the same table without cycling; or `contract:<rule>`, for artifacts okstra's own phase contract mandates, whose allowlist is exactly the two tokens `decision-record-step` (the §5.4 Decision Drafts materialization step) and `glossary-step` (the glossary proposal step) — any other rule name is rejected, so never invent one. (Maintainer SSOT for that allowlist: `scripts/okstra_ctl/scope_provenance.py` in the okstra repo.) A requirement you cannot source this way does not belong in the table: put it in `clarificationItems[]` with `Blocks=approval`. **Enforced:** `validators/validate-run.py` `_validate_requirement_provenance`. In the same table, anchor every stage number in `coveredBy` to a `Stage` / `Stages` word (`Stage 2`, `Stages 1-3`) — `_validate_stage_has_requirement` reads that cell as prose and fails the plan when a Stage Map stage is cited by no row.
158
+ - For legacy candidate-comparison `implementation-planning`, also populate `implementationPlanning.decisionDrafts` (one row per decision meeting all three decision-record criteria; `[]` otherwise) and `implementationPlanning.skippedAdrCandidates` (evaluated-but-dropped adr-candidates; `[]` otherwise). The schema excerpt enumerates the row shape; the renderer emits §5.4 `### Decision Drafts`. When `decisionDrafts` is non-empty, the plan's stages MUST carry a stepwise step that creates `.okstra/decisions/<NNNN>-<slug>.md` (validate-run gates this).
159
+ - For `implementation-planning`, populate `implementationPlanning.variationPointAnalysis` — a `hasMultipleImplementations` judgement synthesized from the analysis workers' output, not a field filled in last. When it is `true`, write one `points[]` row per varying behavior carrying `behavior`, the two or more `implementations` that serve it, `evidence` (a `path:line`, or the sibling task / stage that already implements that behavior), and an `extractionDecision` of `extract` / `interfaceKind` / `coveredBy` (the Stage Map stage that builds the interface) / `rationale`; when it is `false`, write a non-empty `noVariationRationale` and leave `points` empty (the two branches are mutually exclusive). Do NOT pass a boilerplate rationale. Populate test seams under `implementationPlanning.directionRealization.testSeams` for selected-direction plans and under `implementationPlanning.recommendedOption.testSeams` for legacy candidate-comparison plans. An empty list is a conscious "no seam needed" claim, never a default for a field nobody filled. Every point becomes a `P-Var-*` plan item judged in §5.5.9.
136
160
  - When the `Task Type` is `improvement-discovery`, populate `improvementDiscovery.candidates[]`, `improvementDiscovery.lensCoverage[]`, `improvementDiscovery.selectionLimit`, and `improvementDiscovery.userNarrative`. Each candidate carries the 11 logical fields enforced by `validators/validate_improvement_report.py`; each lens-coverage row records candidate IDs or an evidence-backed no-candidate rationale. Source IDs, lens names, and worker prefixes from `scripts/okstra_ctl/improvement_lenses.py`. The standard renderer derives the AI handoff Markdown; never author a free-form improvement report.
137
161
 
138
162
  Write the three completion artifacts and the separate audit sidecar with your `Write` tool — that is the canonical authoring path, and okstra ships no hook that blocks `.md` writes (its seeded settings carry no `PreToolUse` entry at all — only the session/subagent lifecycle hooks `SessionStart` compact-reminder, `SessionEnd` trace-cleanup, and `SubagentStop` / `TaskCompleted` pane reclaim, none of which can intercept a tool call). A Bash heredoc is acceptable ONLY when a specific `Write` call is genuinely rejected by the host environment, and it MUST produce byte-identical content — do not reach for it pre-emptively. After writing data.json, invoke the renderer (`Bash`): `okstra render-final-report <data.json path>`, then write the Worker Result Path pointer. Confirm data.json, rendered Markdown, the pointer, and the audit sidecar exist before responding with a short status line prefixed by your model identity, per the preamble §"Return message to the lead". **Enforced:** dispatch `completionPaths` requires the first three files and `validators/validate_session_conformance.py` validates the audit sidecar.
@@ -175,6 +175,10 @@ while [[ $# -gt 0 ]]; do
175
175
  CLARIFICATION_RESPONSE_PATH="$(require_option_value --clarification-response "${2-}")"
176
176
  shift 2
177
177
  ;;
178
+ --selected-direction)
179
+ SELECTED_DIRECTION_PATH="$(require_option_value --selected-direction "${2-}")"
180
+ shift 2
181
+ ;;
178
182
  --task-key)
179
183
  TASK_KEY_INPUT="$(require_option_value --task-key "${2-}")"
180
184
  shift 2
@@ -233,7 +237,7 @@ while [[ $# -gt 0 ]]; do
233
237
  printf ' hint: did you mean --task-id?\n' >&2
234
238
  ;;
235
239
  esac
236
- printf ' valid options: --render-only --resume-clarification --yes --workers --lead-provider --lead-model --claude-model --codex-model --antigravity-model --worker-model --report-writer-provider --report-writer-model --lead-runtime --executor --critic --related-tasks --work-category --task-type --project-id --project-root --task-group --task-id --task-brief --directive --base-ref --fix-cycle --clarification-response --task-key --approved-plan --approve --implementation-option --stage --stages --qa-waiver --no-plan-verification -h|--help\n' >&2
240
+ printf ' valid options: --render-only --resume-clarification --yes --workers --lead-provider --lead-model --claude-model --codex-model --antigravity-model --worker-model --report-writer-provider --report-writer-model --lead-runtime --executor --critic --related-tasks --work-category --task-type --project-id --project-root --task-group --task-id --task-brief --directive --base-ref --fix-cycle --clarification-response --selected-direction --task-key --approved-plan --approve --implementation-option --stage --stages --qa-waiver --no-plan-verification -h|--help\n' >&2
237
241
  usage
238
242
  exit 1
239
243
  ;;
@@ -44,6 +44,7 @@ ANALYSIS_PROFILE=""
44
44
  DIRECTIVE=""
45
45
  FIX_CYCLE=""
46
46
  CLARIFICATION_RESPONSE_PATH=""
47
+ SELECTED_DIRECTION_PATH=""
47
48
  APPROVED_PLAN_PATH=""
48
49
  APPROVE_PLAN_ACK="false"
49
50
  # implementation 전용: 유저가 고른 Option Candidate 이름. 빈 값이면 implementation
@@ -43,6 +43,9 @@ optional arguments:
43
43
  input so the lead can reconcile each prior Q*. Use this for scripted or
44
44
  CI runs where the answer file is already prepared. Interactive users
45
45
  should prefer --resume-clarification, which wraps this flag.
46
+ --selected-direction Path to a validated implementation-option-selection final report.
47
+ Required for a new implementation-planning run. Existing planning
48
+ reruns continue to use --clarification-response with their prior report.
46
49
  --approved-plan Path to the approved final-report.md from a prior implementation-planning run.
47
50
  Required when --task-type=implementation; the file MUST contain a recorded user approval marker.
48
51
  --approve Treat the user's CLI invocation itself as the plan-approval signal. Only meaningful
@@ -187,6 +187,7 @@ okstra execution summary:
187
187
  task brief: ${BRIEF_PATH}
188
188
  directive: ${DIRECTIVE:-None}
189
189
  clarification response: ${CLARIFICATION_RESPONSE_PATH:-None}
190
+ selected direction: ${SELECTED_DIRECTION_PATH:-None}
190
191
  workers override: ${WORKERS_OVERRIDE:-None}
191
192
  executor (implementation only): ${EXECUTOR_OVERRIDE:-default(claude)}
192
193
  approved plan: ${APPROVED_PLAN_PATH:-None}
@@ -237,6 +238,7 @@ PY_ARGS=(
237
238
  [[ "$APPROVE_PLAN_ACK" == "true" ]] && PY_ARGS+=(--approve)
238
239
  [[ -n "${IMPLEMENTATION_OPTION-}" ]] && PY_ARGS+=(--implementation-option "$IMPLEMENTATION_OPTION")
239
240
  [[ -n "${CLARIFICATION_RESPONSE_PATH-}" ]] && PY_ARGS+=(--clarification-response "$CLARIFICATION_RESPONSE_PATH")
241
+ [[ -n "${SELECTED_DIRECTION_PATH-}" ]] && PY_ARGS+=(--selected-direction "$SELECTED_DIRECTION_PATH")
240
242
  [[ -n "${WORK_CATEGORY-}" ]] && PY_ARGS+=(--work-category "$WORK_CATEGORY")
241
243
  [[ -n "${BASE_REF-}" ]] && PY_ARGS+=(--base-ref "$BASE_REF")
242
244
  [[ -n "${STAGE-}" ]] && PY_ARGS+=(--stage "$STAGE")