okstra 0.102.2 → 0.102.3

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 (161) hide show
  1. package/README.kr.md +5 -5
  2. package/README.md +5 -5
  3. package/docs/kr/architecture/storage-model.md +1 -1
  4. package/docs/kr/architecture.md +7 -11
  5. package/docs/kr/cli.md +4 -4
  6. package/docs/kr/container.md +1 -1
  7. package/docs/kr/performance-improvement-plan-v2.md +2 -2
  8. package/docs/project-structure-overview.md +2 -2
  9. package/package.json +7 -2
  10. package/runtime/BUILD.json +2 -2
  11. package/runtime/bin/okstra-antigravity-exec.sh +1 -2
  12. package/runtime/bin/okstra-codex-exec.sh +1 -2
  13. package/runtime/bin/okstra-render-final-report.py +2 -9
  14. package/runtime/bin/okstra-spawn-followups.py +4 -6
  15. package/runtime/bin/okstra-trace-cleanup.sh +24 -4
  16. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  17. package/runtime/prompts/lead/report-writer.md +1 -1
  18. package/runtime/prompts/profiles/_common-contract.md +9 -11
  19. package/runtime/python/okstra_ctl/codex_dispatch.py +4 -12
  20. package/runtime/python/okstra_ctl/consumers.py +35 -0
  21. package/runtime/python/okstra_ctl/container.py +4 -6
  22. package/runtime/python/okstra_ctl/dispatch_core.py +4 -12
  23. package/runtime/python/okstra_ctl/final_report_paths.py +24 -0
  24. package/runtime/python/okstra_ctl/handoff.py +2 -1
  25. package/runtime/python/okstra_ctl/implementation_stage.py +7 -11
  26. package/runtime/python/okstra_ctl/report_view_artifacts.py +14 -0
  27. package/runtime/python/okstra_ctl/report_views.py +7 -4
  28. package/runtime/python/okstra_ctl/run.py +3 -10
  29. package/runtime/python/okstra_ctl/stage_targets.py +18 -0
  30. package/runtime/python/okstra_ctl/wizard.py +24 -25
  31. package/runtime/python/okstra_ctl/wizard_stage_intent.py +54 -0
  32. package/runtime/python/okstra_token_usage/report.py +2 -5
  33. package/runtime/validators/validate-report-views.py +2 -1
  34. package/runtime/validators/validate-run.py +1 -11
  35. package/src/commands/lifecycle/install.mjs +5 -5
  36. package/src/commands/lifecycle/uninstall.mjs +4 -4
  37. package/docs/superpowers/plans/2026-05-12-ticket-id-in-reports.md +0 -638
  38. package/docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md +0 -1568
  39. package/docs/superpowers/plans/2026-05-17-dual-format-final-report.md +0 -167
  40. package/docs/superpowers/plans/2026-05-20-final-report-language.md +0 -1501
  41. package/docs/superpowers/plans/2026-05-20-implementation-planning-multi-stage.md +0 -1267
  42. package/docs/superpowers/plans/2026-05-20-okstra-run-prompt-sot-b1.md +0 -1007
  43. package/docs/superpowers/plans/2026-05-20-wizard-messages-json-sot.md +0 -720
  44. package/docs/superpowers/plans/2026-05-20-wizard-prompt-json-sot-a1.md +0 -681
  45. package/docs/superpowers/plans/2026-05-21-improvement-discovery-task-type.md +0 -1691
  46. package/docs/superpowers/plans/2026-05-24-implementation-lead-context-slimming.md +0 -1700
  47. package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +0 -158
  48. package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +0 -860
  49. package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +0 -326
  50. package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +0 -337
  51. package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +0 -410
  52. package/docs/superpowers/plans/2026-06-02-requirements-discovery-fanout.md +0 -728
  53. package/docs/superpowers/plans/2026-06-04-adversarial-implementation-planning.md +0 -294
  54. package/docs/superpowers/plans/2026-06-04-adversarial-verification.md +0 -570
  55. package/docs/superpowers/plans/2026-06-04-coverage-critic.md +0 -516
  56. package/docs/superpowers/plans/2026-06-04-stage-cohesion-planner.md +0 -351
  57. package/docs/superpowers/plans/2026-06-04-stage-run-batching.md +0 -457
  58. package/docs/superpowers/plans/2026-06-05-acceptance-critic.md +0 -251
  59. package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +0 -323
  60. package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +0 -559
  61. package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +0 -993
  62. package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +0 -93
  63. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +0 -447
  64. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +0 -289
  65. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +0 -774
  66. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +0 -303
  67. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +0 -387
  68. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase2.md +0 -275
  69. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase3.md +0 -282
  70. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4a.md +0 -147
  71. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4b.md +0 -262
  72. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4c.md +0 -184
  73. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4d.md +0 -88
  74. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4e.md +0 -250
  75. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa.md +0 -409
  76. package/docs/superpowers/plans/2026-06-09-implementation-run-artifact-stage-isolation.md +0 -320
  77. package/docs/superpowers/plans/2026-06-10-concurrent-run-team-guard.md +0 -456
  78. package/docs/superpowers/plans/2026-06-10-git-reconcile-stale-sha-recovery.md +0 -1408
  79. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling-PROBE.md +0 -42
  80. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling.md +0 -337
  81. package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +0 -1029
  82. package/docs/superpowers/plans/2026-06-10-stage-group-handoff.md +0 -1572
  83. package/docs/superpowers/plans/2026-06-11-fix-cycle.md +0 -1290
  84. package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +0 -526
  85. package/docs/superpowers/plans/2026-06-12-html-plan-approval.md +0 -1000
  86. package/docs/superpowers/plans/2026-06-13-repo-risk-hardening.md +0 -493
  87. package/docs/superpowers/plans/2026-06-14-host-runtime-auto-execution.md +0 -1775
  88. package/docs/superpowers/plans/2026-06-15-coding-preflight-pack-dispatch-path.md +0 -504
  89. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-final-fixups.md +0 -342
  90. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-fixups.md +0 -258
  91. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-remaining-fixups.md +0 -387
  92. package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +0 -749
  93. package/docs/superpowers/plans/2026-06-15-worker-prompt-anchor-final-fixups.md +0 -828
  94. package/docs/superpowers/plans/2026-06-15-worker-prompt-header-error-contract.md +0 -490
  95. package/docs/superpowers/plans/2026-06-17-okstra-error-report.md +0 -724
  96. package/docs/superpowers/plans/2026-06-18-subagent-pane-reclaim.md +0 -483
  97. package/docs/superpowers/plans/2026-06-19-agent-operating-standard.md +0 -476
  98. package/docs/superpowers/plans/2026-06-19-okstra-inspect-recap-facet.md +0 -647
  99. package/docs/superpowers/plans/2026-06-20-error-feedback-loop.md +0 -1019
  100. package/docs/superpowers/plans/2026-06-20-run-index-row-normalization.md +0 -583
  101. package/docs/superpowers/plans/2026-06-20-stage-auto-integrate-teardown.md +0 -819
  102. package/docs/superpowers/plans/2026-06-21-okstra-container-local-user-test.md +0 -714
  103. package/docs/superpowers/plans/2026-06-21-release-handoff-local-checkout.md +0 -348
  104. package/docs/superpowers/plans/2026-06-23-implementation-stage-multiselect-chain.md +0 -630
  105. package/docs/superpowers/plans/2026-06-23-implementation-step-commit-granularity.md +0 -274
  106. package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +0 -409
  107. package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +0 -542
  108. package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +0 -568
  109. package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +0 -203
  110. package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +0 -525
  111. package/docs/superpowers/specs/2026-05-12-ticket-id-in-reports-design.md +0 -131
  112. package/docs/superpowers/specs/2026-05-15-implementation-plan-verification-design.md +0 -254
  113. package/docs/superpowers/specs/2026-05-20-final-report-language-design.md +0 -383
  114. package/docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md +0 -322
  115. package/docs/superpowers/specs/2026-05-20-okstra-run-prompt-sot-design.md +0 -299
  116. package/docs/superpowers/specs/2026-05-21-improvement-discovery-task-type-design.md +0 -335
  117. package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +0 -113
  118. package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +0 -173
  119. package/docs/superpowers/specs/2026-06-02-requirements-discovery-fanout-design.md +0 -154
  120. package/docs/superpowers/specs/2026-06-04-adversarial-implementation-planning-design.md +0 -90
  121. package/docs/superpowers/specs/2026-06-04-adversarial-verification-design.md +0 -176
  122. package/docs/superpowers/specs/2026-06-04-coverage-critic-design.md +0 -99
  123. package/docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md +0 -98
  124. package/docs/superpowers/specs/2026-06-05-acceptance-critic-design.md +0 -90
  125. package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +0 -87
  126. package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +0 -121
  127. package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +0 -126
  128. package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +0 -180
  129. package/docs/superpowers/specs/2026-06-06-vertical-slice-tdd-planning-design.md +0 -179
  130. package/docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md +0 -169
  131. package/docs/superpowers/specs/2026-06-09-executor-model-custom-id-cascade-design.md +0 -66
  132. package/docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md +0 -87
  133. package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +0 -168
  134. package/docs/superpowers/specs/2026-06-10-concurrent-run-team-guard-design.md +0 -107
  135. package/docs/superpowers/specs/2026-06-10-git-reconcile-stale-sha-recovery-design.md +0 -105
  136. package/docs/superpowers/specs/2026-06-10-lead-worker-completion-polling-design.md +0 -113
  137. package/docs/superpowers/specs/2026-06-10-stage-group-handoff-design.md +0 -156
  138. package/docs/superpowers/specs/2026-06-11-brief-entry-only-handoff-stage-entry-design.md +0 -158
  139. package/docs/superpowers/specs/2026-06-11-fix-cycle-design.md +0 -94
  140. package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +0 -89
  141. package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +0 -358
  142. package/docs/superpowers/specs/2026-06-12-html-plan-approval-design.md +0 -85
  143. package/docs/superpowers/specs/2026-06-12-stage-discipline-rule-design.md +0 -108
  144. package/docs/superpowers/specs/2026-06-13-forbidden-actions-ssot-design.md +0 -134
  145. package/docs/superpowers/specs/2026-06-13-neutral-tmux-lead-adapter-design.md +0 -284
  146. package/docs/superpowers/specs/2026-06-14-host-runtime-auto-execution-design.md +0 -404
  147. package/docs/superpowers/specs/2026-06-17-okstra-error-report-design.md +0 -123
  148. package/docs/superpowers/specs/2026-06-18-subagent-pane-reclaim-design.md +0 -150
  149. package/docs/superpowers/specs/2026-06-19-agent-operating-standard-design.md +0 -120
  150. package/docs/superpowers/specs/2026-06-19-okstra-inspect-recap-facet-design.md +0 -96
  151. package/docs/superpowers/specs/2026-06-20-error-feedback-loop-design.md +0 -171
  152. package/docs/superpowers/specs/2026-06-20-run-index-row-normalization-design.md +0 -112
  153. package/docs/superpowers/specs/2026-06-20-stage-auto-integrate-teardown-design.md +0 -145
  154. package/docs/superpowers/specs/2026-06-21-okstra-container-local-user-test-design.md +0 -125
  155. package/docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md +0 -113
  156. package/docs/superpowers/specs/2026-06-23-implementation-stage-multiselect-chain-design.md +0 -138
  157. package/docs/superpowers/specs/2026-06-23-implementation-step-commit-granularity-design.md +0 -120
  158. package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +0 -129
  159. package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +0 -185
  160. package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +0 -121
  161. package/docs/superpowers/specs/2026-06-24-okstra-container-build-rename-design.md +0 -110
@@ -1,457 +0,0 @@
1
- # Plan B — 실행기 측 run batching (ready-set + 예산 8) 구현 계획
2
-
3
- > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
-
5
- **Goal:** 한 `implementation` run 이 정확히 1 stage 대신, `depends-on` 이 모두 done 인 ready stage 들을 합산 effective step 예산 8 까지 batch 로 실행하게 하여, 교차검증·report 고정비를 stage 수가 아닌 run 수에 비례하게 만든다(사용자가 체감한 비용 절감의 본체).
6
-
7
- **Architecture:** stage 선택 권한을 Python 으로 일원화한다(현재 `_resolve_effective_stage` 의 단일 int + 프롬프트의 lead 자가계산 이중 경로를 제거). `_resolve_effective_stages` 가 ready-set 배치 리스트를 반환하고, `prepare_task_bundle` 가 batch 의 각 stage 에 `started` consumer row 를 쓰고 `{{EFFECTIVE_STAGES}}` 를 launch 프롬프트에 주입한다. 프롬프트 계약은 "주입된 batch 의 stage 들을 오름차순으로 실행, 각 경계에서 stage 별 sidecar/consumers done row 방출, run 끝에 교차검증·report 1회, PR 1개" 로 바뀐다.
8
-
9
- **Tech Stack:** Python 3 (`scripts/okstra_ctl/run.py`, `consumers.py`), pytest + e2e bash, jinja2 launch 템플릿, markdown 프로파일 프롬프트, Node 빌드(`npm run build`).
10
-
11
- > **선행:** Plan A(응집 + S9 병렬-안전 불변식) 가 먼저 머지되어 있어야 batch 와 병렬 run 의 파일 충돌이 구조적으로 방지된다. 본 계획은 Plan A 브랜치(`feat/stage-cohesion-planner`) 위에서 이어 작업하거나 그것이 main 에 머지된 뒤 새 브랜치에서 시작한다.
12
-
13
- > **명시적 비범위:** parallel-run started-exclusion. 현재 `_resolve_effective_stage` 는 다른 run 이 `started` 한 stage 를 배제하지 않는다(두 병렬 run 이 같은 ready-set 을 잡을 수 있음 — `tests/test_e2e_multi_stage_q1_q9.py::test_q7` 가 이 기존 동작을 문서화). batch 도입이 이 gap 을 악화시키지 않으며, 사용자의 실제 사용(순차 phase-continuation)에는 영향 없다. started-exclusion 은 별도 작업으로 남긴다.
14
-
15
- ---
16
-
17
- ## 파일 구조
18
-
19
- | 파일 | 책임 | 작업 |
20
- |---|---|---|
21
- | `scripts/okstra_ctl/run.py` | bundle 준비, stage 선택, consumers started row, ctx 주입 | 수정 |
22
- | `tests/test_resolve_effective_stages.py` | 순수 선택 함수 유닛 커버리지 | 신규 |
23
- | `tests/test_auto_stage_selection.py` | 통합 선택 동작 | 수정(batch 의미) |
24
- | `tests/test_e2e_multi_stage_q1_q9.py` | e2e Q1–Q9 | 수정(batch 의미) |
25
- | `prompts/launch.template.md` | lead 런치 프롬프트(jinja) | 수정(`{{EFFECTIVE_STAGES}}` 주입) |
26
- | `prompts/profiles/_implementation-executor.md` | executor 역할 계약 | 수정(batch 소비, one-PR-per-run) |
27
- | `prompts/profiles/_implementation-deliverable.md` | Phase 6 산출 계약 | 수정(stage 별 done row, report 1회) |
28
- | `prompts/profiles/implementation.md` | implementation 프로파일 | 수정(run 단위 검증 명시) |
29
- | `docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md` | 신규 설계 스펙 | 수정(구현 결과 반영: started-exclusion 비범위 명시) |
30
-
31
- ---
32
-
33
- ## Task 1: `_resolve_effective_stages` 순수 함수 (TDD)
34
-
35
- **Files:**
36
- - Create: `tests/test_resolve_effective_stages.py`
37
- - Modify: `scripts/okstra_ctl/run.py`
38
-
39
- `_resolve_effective_stage`(단일 int) 를 `_resolve_effective_stages`(list) 로 교체. ready = `depends-on` 이 모두 done 이고 자신은 not-done. batch = ready 를 stage 번호 순으로 누적 step_count ≤ 예산까지 (단 최소 1개 보장). numeric 요청은 단일 stage 리스트.
40
-
41
- - [ ] **Step 1: 실패 테스트 작성**
42
-
43
- Create `tests/test_resolve_effective_stages.py`:
44
-
45
- ```python
46
- """Unit coverage for run._resolve_effective_stages (ready-set batch selection)."""
47
- import importlib.util
48
- from pathlib import Path
49
-
50
- REPO = Path(__file__).resolve().parents[1]
51
- spec = importlib.util.spec_from_file_location(
52
- "okstra_run", REPO / "scripts" / "okstra_ctl" / "run.py"
53
- )
54
- run = importlib.util.module_from_spec(spec)
55
- spec.loader.exec_module(run)
56
-
57
-
58
- def _stage(n, deps, steps):
59
- return {"stage_number": n, "depends_on": deps, "step_count": steps}
60
-
61
-
62
- def test_auto_batches_independent_ready_stages_within_budget():
63
- stages = [_stage(1, [], 2), _stage(2, [], 3), _stage(3, [1, 2], 2)]
64
- # stages 1+2 are ready (deps empty), 2+3=5 ≤ 8 → batch [1, 2]; 3 not ready.
65
- assert run._resolve_effective_stages(stages, set(), "auto", budget=8) == [1, 2]
66
-
67
-
68
- def test_auto_stops_at_budget():
69
- stages = [_stage(1, [], 5), _stage(2, [], 5)]
70
- # 5 + 5 = 10 > 8 → only stage 1 fits after the first.
71
- assert run._resolve_effective_stages(stages, set(), "auto", budget=8) == [1]
72
-
73
-
74
- def test_auto_guarantees_at_least_one_even_over_budget():
75
- stages = [_stage(1, [], 6)]
76
- # single ready stage at the cap; budget never drops it.
77
- assert run._resolve_effective_stages(stages, set(), "auto", budget=8) == [1]
78
-
79
-
80
- def test_auto_skips_done_and_unready():
81
- stages = [_stage(1, [], 2), _stage(2, [1], 2), _stage(3, [1], 2)]
82
- # stage 1 done → 2 and 3 become ready (deps satisfied), 2+2=4 ≤ 8 → [2, 3].
83
- assert run._resolve_effective_stages(stages, {1}, "auto", budget=8) == [2, 3]
84
-
85
-
86
- def test_auto_raises_when_nothing_ready():
87
- stages = [_stage(1, [], 2), _stage(2, [1], 2)]
88
- # stage 1 not done and stage 2 depends on it → with stage 1 done-set empty,
89
- # stage 1 IS ready; to force "nothing ready" mark 1 done but 2 depends on a
90
- # missing dep. Simulate by marking 1 done and 2 depending on un-done 3.
91
- stages = [_stage(2, [3], 2)]
92
- import pytest
93
- with pytest.raises(run.PrepareError):
94
- run._resolve_effective_stages(stages, set(), "auto", budget=8)
95
-
96
-
97
- def test_numeric_returns_single_stage():
98
- stages = [_stage(1, [], 2), _stage(2, [], 2)]
99
- assert run._resolve_effective_stages(stages, set(), "2", budget=8) == [2]
100
-
101
-
102
- def test_numeric_rejects_done_stage():
103
- stages = [_stage(1, [], 2)]
104
- import pytest
105
- with pytest.raises(run.PrepareError):
106
- run._resolve_effective_stages(stages, {1}, "1", budget=8)
107
-
108
-
109
- def test_numeric_rejects_unknown_stage():
110
- stages = [_stage(1, [], 2)]
111
- import pytest
112
- with pytest.raises(run.PrepareError):
113
- run._resolve_effective_stages(stages, set(), "9", budget=8)
114
- ```
115
-
116
- - [ ] **Step 2: 실행 → 실패 확인**
117
-
118
- Run: `python3 -m pytest tests/test_resolve_effective_stages.py -v`
119
- Expected: collection 또는 AttributeError 실패 — `_resolve_effective_stages` 가 아직 없음.
120
-
121
- - [ ] **Step 3: 함수 구현**
122
-
123
- `scripts/okstra_ctl/run.py` 에서 기존 `_resolve_effective_stage`(line 211–246) 전체를 다음으로 교체:
124
-
125
- ```python
126
- RUN_STEP_BUDGET = 8
127
-
128
-
129
- def _resolve_effective_stages(
130
- stages: list,
131
- done_stages: set,
132
- requested: str,
133
- budget: int = RUN_STEP_BUDGET,
134
- ) -> list:
135
- """Return the ordered list of stage numbers this run executes.
136
-
137
- `requested` is "auto" or a decimal string. For "auto" the run batches all
138
- ready stages (depends-on all done, itself not done) in stage-number order up
139
- to `budget` effective steps — but always at least one. A numeric request is a
140
- single forced stage. Raises PrepareError on rejection cases."""
141
- if requested != "auto":
142
- try:
143
- n = int(requested)
144
- except ValueError:
145
- raise PrepareError(
146
- f"--stage must be 'auto' or an integer, got {requested!r}"
147
- )
148
- target = next((s for s in stages if s["stage_number"] == n), None)
149
- if target is None:
150
- raise PrepareError(
151
- f"--stage {n} not in Stage Map "
152
- f"(have {[s['stage_number'] for s in stages]})"
153
- )
154
- if n in done_stages:
155
- raise PrepareError(
156
- f"--stage {n} already completed (consumers.jsonl status:done exists)"
157
- )
158
- return [n]
159
-
160
- ready = [
161
- s for s in stages
162
- if s["stage_number"] not in done_stages
163
- and all(d in done_stages for d in s["depends_on"])
164
- ]
165
- if not ready:
166
- raise PrepareError(
167
- "no stage is ready: every remaining stage has unsatisfied depends-on"
168
- )
169
- batch: list = []
170
- total = 0
171
- for s in ready:
172
- sc = s.get("step_count", 0) or 0
173
- if batch and total + sc > budget:
174
- break
175
- batch.append(s["stage_number"])
176
- total += sc
177
- return batch
178
- ```
179
-
180
- - [ ] **Step 4: 실행 → 통과 확인**
181
-
182
- Run: `python3 -m pytest tests/test_resolve_effective_stages.py -v`
183
- Expected: 8 passed.
184
-
185
- - [ ] **Step 5: 커밋**
186
-
187
- ```bash
188
- git add scripts/okstra_ctl/run.py tests/test_resolve_effective_stages.py
189
- git commit -m "feat(okstra_ctl/run): batch ready stages up to a run step budget"
190
- ```
191
-
192
- ---
193
-
194
- ## Task 2: `prepare_task_bundle` 배선 + 통합/e2e 테스트 batch 의미 반영
195
-
196
- **Files:**
197
- - Modify: `scripts/okstra_ctl/run.py:843–869` (callsite)
198
- - Modify: `tests/test_auto_stage_selection.py`
199
- - Modify: `tests/test_e2e_multi_stage_q1_q9.py`
200
-
201
- - [ ] **Step 1: callsite 교체**
202
-
203
- `scripts/okstra_ctl/run.py` 의 line 851–869 블록을 다음으로 교체:
204
-
205
- ```python
206
- effective = _resolve_effective_stages(
207
- ctx["parsed_stage_map"], done_stages, inp.stage
208
- )
209
- ctx["effective_stages"] = effective
210
- csv = ",".join(str(n) for n in effective)
211
- ctx["EFFECTIVE_STAGES"] = csv
212
- ctx["STAGE_BATCH_DIRECTIVE"] = (
213
- f"- **Stage batch for this implementation run:** `{csv}` "
214
- "(comma-separated stage numbers, ascending). Execute exactly these "
215
- "Stage Map stages in this order — this is the authoritative scope. "
216
- "Do NOT recompute the start stage from `consumers.jsonl`; the runtime "
217
- "already selected and reserved this batch."
218
- )
219
- inp.stage = csv
220
- print(f"selected stages: {csv}", file=sys.stdout)
221
- head_proc = _subprocess.run(
222
- ["git", "rev-parse", "HEAD"],
223
- cwd=inp.project_root, capture_output=True, text=True,
224
- )
225
- head_sha = head_proc.stdout.strip() if head_proc.returncode == 0 else ""
226
- now = _dt.datetime.now(_dt.timezone.utc).isoformat()
227
- for stage_n in effective:
228
- append_consumer(
229
- plan_run_root,
230
- impl_task_key=ctx["TASK_KEY"],
231
- stage=stage_n,
232
- status="started",
233
- started_at=now,
234
- head_commit=head_sha,
235
- )
236
- ```
237
-
238
- (Non-impl 경로에서 `EFFECTIVE_STAGES` 가 비도록, ctx 기본값을 보장한다. ctx 초기화부에 `ctx.setdefault("EFFECTIVE_STAGES", "")` 가 없으면, jinja 렌더 시 KeyError 방지를 위해 launch 렌더 직전 `ctx.setdefault("EFFECTIVE_STAGES", "")` 한 줄을 추가 — Step 1b.)
239
-
240
- - [ ] **Step 1b: 비-impl 기본값 보장**
241
-
242
- `prepare_task_bundle` 에서 ctx 가 launch 렌더에 넘어가기 전(즉 `if inp.task_type == "implementation":` 블록 밖, 그 위) 한 줄 추가:
243
-
244
- ```python
245
- ctx.setdefault("EFFECTIVE_STAGES", "")
246
- ctx.setdefault("STAGE_BATCH_DIRECTIVE", "")
247
- ```
248
-
249
- - [ ] **Step 2: `test_auto_stage_selection.py` 갱신**
250
-
251
- 기존 단일-stage assertion 을 batch 의미로 교체. 다음 두 곳을 수정한다.
252
-
253
- `test_auto_picks_stage_1_when_none_done` 의
254
- ```python
255
- assert "selected stage: 1" in r.stdout
256
- ```
257
-
258
- ```python
259
- assert "selected stages: 1" in r.stdout
260
- ```
261
- 로. (이 테스트의 fixture 가 stage 1·2 를 둘 다 ready 로 만들고 합산 ≤8 이면 출력이 `selected stages: 1,2` 가 된다. 픽스처를 읽어 stage 2 가 ready 인지·step 합을 확인하고, 그렇다면 `assert "selected stages: 1,2" in r.stdout` 로, stage 2 가 stage 1 에 depends-on 이면 `selected stages: 1` 로 맞춘다.)
262
-
263
- `test_consumers_started_row_appended_on_success` 의
264
- ```python
265
- started_rows = [row for row in rows if row.get("status") == "started"]
266
- assert len(started_rows) == 1
267
- assert started_rows[0]["stage"] == 1
268
- ```
269
- 를, 위에서 확인한 batch 크기에 맞춰: stage 1 단독 batch 면 그대로; stage 1+2 batch 면
270
- ```python
271
- started_rows = [row for row in rows if row.get("status") == "started"]
272
- assert [row["stage"] for row in started_rows] == [1, 2]
273
- ```
274
- 로.
275
-
276
- `test_auto_picks_stage_2_when_stage_1_done_and_stage_2_independent` 의
277
- ```python
278
- assert "selected stage: 2" in r.stdout
279
- ```
280
- 는 stage 1 done 후 ready 집합이 {2,3...} 이 되므로, fixture 의 stage 3 depends-on 을 보고 `selected stages: 2` 또는 `selected stages: 2,3` 로 맞춘다.
281
-
282
- > 구현자 주의: 이 파일의 fixture 정의(인라인 plan 텍스트 또는 `tests/fixtures/plans/`)를 먼저 읽고 각 stage 의 `depends-on`·`step-count` 를 확인한 뒤, 위 규칙대로 기대 batch 를 계산해 assertion 을 채운다. 추측 금지.
283
-
284
- - [ ] **Step 3: `test_e2e_multi_stage_q1_q9.py` 갱신**
285
-
286
- batch 의미로 깨지는 assertion (Explore 맵 기준):
287
- - `test_q1_one_stage_plan_happy_path` (1-stage plan): batch=[1] 이므로 `"selected stage: 1"` → `"selected stages: 1"`, `len(started)==1` 유지.
288
- - `test_q2_three_stage_first_run_picks_stage_1`: 3-stage plan 의 stage 1·2 가 depends-on(none)·합산 ≤8 이면 batch=[1,2]. `"selected stage: 1"` → 실제 batch 문자열로, `len(rows)==1` → batch 크기로, `rows[0]["stage"]==1` → `[r["stage"] for r in rows]==<batch>` 로. (fixture 확인 후 확정.)
289
- - `test_q3_after_stage_1_done_picks_stage_2_and_loads_sidecar`: stage 1 done 후 ready 집합 기준으로 `"selected stages: ..."` 갱신.
290
- - `test_q7_parallel_runs_pick_distinct_none_stages`: 이 테스트는 started-exclusion 부재(비범위)를 문서화한다. 두 run 이 같은 batch 를 잡는 동작은 유지되나 출력 문자열이 `selected stages:` 로 바뀐다 — `"selected stage: 1"` → `"selected stages: ..."`. `len(started)==2` 와 `all(row["stage"]==1 ...)` 는 batch 크기에 따라 갱신(두 run 이 각각 같은 batch 를 started 하므로 started row 수 = 2 × batch 크기). fixture 확인 후 확정.
291
- - `test_q8_partial_depends_on_blocks_higher_stage`: `"selected stage: 1"` → `"selected stages: 1"` (stage 2·3 이 미충족 depends-on 으로 ready 가 아니면 batch=[1]).
292
- - S4/S5/S6/S8 거부 테스트(q4,q5,q6,q9)는 prepare 이전 validator 단계라 영향 없음 — 변경 금지.
293
-
294
- > 구현자 주의: 각 Q 테스트가 사용하는 plan fixture 의 stage depends-on·step-count 를 읽고 batch 를 계산해 정확한 문자열·카운트로 채운다.
295
-
296
- - [ ] **Step 4: 실행 → 통과 확인**
297
-
298
- Run: `python3 -m pytest tests/test_auto_stage_selection.py tests/test_e2e_multi_stage_q1_q9.py -v`
299
- Expected: 전부 통과 (batch 의미 반영).
300
-
301
- - [ ] **Step 5: 커밋**
302
-
303
- ```bash
304
- git add scripts/okstra_ctl/run.py tests/test_auto_stage_selection.py tests/test_e2e_multi_stage_q1_q9.py
305
- git commit -m "feat(okstra_ctl/run): wire ready-set batch into bundle prep and consumers"
306
- ```
307
-
308
- ---
309
-
310
- ## Task 3: 프롬프트 계약 — batch 소비 + one-PR-per-run + run 단위 검증
311
-
312
- **Files:**
313
- - Modify: `prompts/launch.template.md` (EFFECTIVE_STAGES 주입)
314
- - Modify: `prompts/profiles/_implementation-executor.md:30–49`
315
- - Modify: `prompts/profiles/_implementation-deliverable.md:51–52`
316
- - Modify: `prompts/profiles/implementation.md`
317
-
318
- 프로즈 변경(유닛 테스트 없음) — 검증은 빌드 동기화 + 사람 읽기 + e2e.
319
-
320
- - [ ] **Step 1: launch 프롬프트에 batch 주입**
321
-
322
- `launch.template.md` 는 `{% %}` 제어구문을 쓰지 않고 `{{ }}` 치환만 쓴다(확인됨). 따라서 조건 분기 없이, Python 이 만든 완성 지시문 ctx 변수를 무조건 렌더한다 — 비-impl 에서는 `STAGE_BATCH_DIRECTIVE` 가 빈 문자열이라 빈 줄만 남는다.
323
-
324
- `prompts/launch.template.md` 의 `- This run executes \`{{WORKFLOW_CURRENT_PHASE}}\` only.` 줄(현재 line 17) 바로 아래에 추가:
325
-
326
- ```markdown
327
- {{STAGE_BATCH_DIRECTIVE}}
328
- ```
329
-
330
- - [ ] **Step 2: `_implementation-executor.md` batch 계약**
331
-
332
- line 30–33 의 "Determine **start stage**" 블록을 batch 소비로 교체:
333
-
334
- ```markdown
335
- - read the **Stage batch** injected in the launch prompt (`Stage batch for this implementation run`). It lists the stage numbers this run owns, ascending. The runtime already selected and reserved them — do NOT recompute from `consumers.jsonl`.
336
- - for each stage in the batch, load every `runs/<plan-key>/carry/stage-<i>.json` for `i ∈ depends-on(stage)` and inject them as runtime carry-in. `depends-on (none)` stages need no sidecar — task-brief only.
337
- - the batch's stages are mutually independent (each one's depends-on are all already `status:done`, never another batch member), so execute them in ascending order; each stage's file list, step order, Stage Validation, Stage Exit Contract, and rollback path are the authoritative scope for that stage.
338
- ```
339
-
340
- line 41 의 헤딩
341
- ```markdown
342
- ## Stage execution contract (this run owns exactly one stage of the plan)
343
- ```
344
-
345
- ```markdown
346
- ## Stage execution contract (this run owns the injected stage batch)
347
- ```
348
- 로.
349
-
350
- line 43–44 의 sidecar/reverse-link 규칙을 stage 별 반복으로:
351
-
352
- ```markdown
353
- - **Sidecar evidence writer (BLOCKING, per stage).** For each stage in the batch, when that stage's Stage Validation `post` commands all succeed, the Executor MUST emit the JSON object (schema: `docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md` §3.2) and the lead MUST persist it to `runs/<impl-task-key>/carry/stage-<N>.json`. Each file MUST NOT exist before the run starts (overwrite refused).
354
- - **Reverse link (BLOCKING, per stage).** The runtime already appended a `status:"started"` row per batch stage before this run began. On each stage's completion, append a `status:"done"` row with `carry_path` populated for that stage number.
355
- ```
356
-
357
- line 45–49 의 One-PR-per-stage 를 one-PR-per-run 으로:
358
-
359
- ```markdown
360
- - **One-PR-per-run.** This run creates exactly one PR titled `Stages <first>–<last>: <run summary>` (or `Stage <N>: <title>` when the batch is a single stage). The PR body MUST include one `## Stage <N>` section per batched stage (title, files, validation result), and `## Previous run` / `## Next run` links so a reviewer can navigate the run chain.
361
- ```
362
-
363
- - [ ] **Step 3: `_implementation-deliverable.md` done row + report 1회**
364
-
365
- line 51–52 의 sidecar/done-row 문구를 batch 인지로:
366
-
367
- ```markdown
368
- - For EACH stage in this run's batch: write the carry JSON verbatim to `runs/<impl-key>/carry/stage-<N>.json` (refuse to overwrite an existing file), then append a `status:"done"` row to `runs/<plan-task-key>/consumers.jsonl` with `completed_at`, `carry_path`, and the HEAD SHA for that stage.
369
- - The verifier round, Phase 5.5 convergence, and this Phase 6 report run **once per run** over the batch's combined diff — NOT per stage. The single final report covers every batched stage, with a per-stage subsection.
370
- ```
371
-
372
- - [ ] **Step 4: `implementation.md` run 단위 검증 명시**
373
-
374
- `prompts/profiles/implementation.md` 의 `- Required workers:` 블록 바로 위 또는 Purpose 줄(line 3) 아래에 한 줄 추가:
375
-
376
- ```markdown
377
- - **Run-level fixed cost:** the verifier set, Phase 5.5 convergence, and the Phase 6 report-writer run exactly once per run, over the combined diff of all stages in this run's batch — never once per stage.
378
- ```
379
-
380
- - [ ] **Step 5: 토큰 정합성 확인**
381
-
382
- Run: `grep -rn "owns exactly one stage\|One-PR-per-stage\|EFFECTIVE_STAGES" prompts/profiles/ prompts/launch.template.md`
383
- Expected: `owns exactly one stage` / `One-PR-per-stage` 잔재 없음, `EFFECTIVE_STAGES` 는 launch + executor 에서 의미 일치.
384
-
385
- - [ ] **Step 6: 커밋**
386
-
387
- ```bash
388
- git add prompts/launch.template.md prompts/profiles/_implementation-executor.md prompts/profiles/_implementation-deliverable.md prompts/profiles/implementation.md
389
- git commit -m "feat(prompts/implementation): consume injected stage batch, one PR and one verification per run"
390
- ```
391
-
392
- ---
393
-
394
- ## Task 4: 신규 설계 스펙 — started-exclusion 비범위 명시
395
-
396
- **Files:**
397
- - Modify: `docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md`
398
-
399
- 구현 중 확정된 사실(started-exclusion 비범위, drift 일원화)을 스펙에 반영해 문서-구현 정합을 맞춘다.
400
-
401
- - [ ] **Step 1: §4 비범위에 한 줄 추가**
402
-
403
- `## 4. 비범위 / 향후` 섹션의 마지막 bullet 아래에 추가:
404
-
405
- ```markdown
406
- - **parallel-run started-exclusion 은 비범위.** 현재 ready-set 선택은 다른 run 이 `started` 한 stage 를 배제하지 않는다(두 병렬 run 이 같은 batch 를 잡을 수 있음 — 기존 동작, `tests/test_e2e_multi_stage_q1_q9.py::test_q7` 가 문서화). 사용자의 순차 phase-continuation 사용에는 영향 없으며, 진짜 충돌 backstop 은 §2.2 의 파일-서로소 불변식 + worktree 직렬성이다. started-exclusion 도입은 별도 작업.
407
- - **stage 선택은 Python SOT.** `_resolve_effective_stages`(run.py) 가 batch 를 선택·예약하고 `{{EFFECTIVE_STAGES}}` 로 lead 에 주입한다. 기존의 "lead 가 consumers.jsonl 로 자가계산" 이중 경로(drift)는 제거됐다.
408
- ```
409
-
410
- - [ ] **Step 2: 커밋**
411
-
412
- ```bash
413
- git add docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md
414
- git commit -m "docs(specs): record started-exclusion non-goal and Python-SOT stage selection"
415
- ```
416
-
417
- ---
418
-
419
- ## Task 5: 빌드 동기화 + 전체 회귀 + e2e
420
-
421
- **Files:** (없음 — 빌드·검증만)
422
-
423
- - [ ] **Step 1: runtime 동기화**
424
-
425
- Run: `npm run build`
426
- Expected: 종료 코드 0, 22/22 동기화.
427
-
428
- - [ ] **Step 2: stage 관련 + 전체 테스트**
429
-
430
- Run: `python3 -m pytest tests/`
431
- Expected: 전부 통과. 특히 `test_resolve_effective_stages.py`, `test_auto_stage_selection.py`, `test_e2e_multi_stage_q1_q9.py`, `test_wizard_stage_pick.py`, `test_run_stage_arg.py` 통과.
432
-
433
- - [ ] **Step 3: e2e 시나리오(있다면)**
434
-
435
- Run: `ls tests-e2e/ | grep -i stage` — stage 관련 e2e 시나리오가 있으면 실행:
436
- `bash tests-e2e/<scenario>.sh`
437
- Expected: 종료 코드 0. (없으면 이 step 생략하고 그 사실을 기록.)
438
-
439
- - [ ] **Step 4: 워크플로 validator**
440
-
441
- Run: `bash validators/validate-workflow.sh`
442
- Expected: 종료 코드 0.
443
-
444
- - [ ] **Step 5: CLI 스모크**
445
-
446
- Run: `node bin/okstra --version && node bin/okstra doctor`
447
- Expected: 버전 출력 + doctor 진단 정상.
448
-
449
- ---
450
-
451
- ## Self-Review (작성자 체크 — 실행 전 1회)
452
-
453
- - **Spec coverage:** 신규 스펙 §2.1(stage/run 분리)→Task 1+3, §2.3(ready-set 예산 8)→Task 1, §2.4(run 단위 검증, stage 별 sidecar)→Task 3, started-exclusion 비범위→Task 4. Plan A 의 S9·응집은 본 계획 비범위(이미 완료).
454
- - **Placeholder scan:** Python·테스트·프롬프트 step 에 실제 코드/문자열/명령 포함. 단, Task 2 의 일부 테스트 assertion 은 fixture 의 depends-on·step-count 에 의존하므로 "구현자가 fixture 를 읽고 batch 를 계산해 채운다" 는 명시적 규칙으로 대체 — 이는 placeholder 가 아니라 데이터-의존 변환 규칙이며, 변환 규칙 자체는 완전 명세돼 있다.
455
- - **Type consistency:** `_resolve_effective_stages` → `list[int]` 반환. callsite 는 `effective`(list), `ctx["EFFECTIVE_STAGES"]`(CSV str), `inp.stage`(CSV str), started row 루프. 프롬프트는 `{{EFFECTIVE_STAGES}}`(CSV) 소비. 함수명 `_resolve_effective_stages`(복수형) 로 통일 — 옛 단수형 `_resolve_effective_stage` 호출 잔재가 없는지 Task 2 Step 1 에서 grep 으로 확인할 것.
456
- - **잔재 확인 권고:** Task 2 착수 전 `grep -rn "_resolve_effective_stage\b" scripts/ tests/` 로 단수형 호출처가 callsite(run.py:851) 외에 없음을 확인.
457
- - **검증 한계(실DB/IO 규칙):** 본 변경은 DB/IO 를 직접 건드리지 않으나, e2e(`tests-e2e/`)와 실제 `implementation` run 의 lead 동작(프롬프트 계약)은 pytest 로 완전 재현되지 않는다. 프롬프트 계약 변경의 "검증" 은 빌드 동기화 + e2e 시나리오까지이며, lead 의 실제 batch 실행은 다음 실 run 에서 관측해야 최종 확인된다 — 그 전까지는 "정적·e2e 상 통과, 실 run 미관측" 으로 보고한다.