okstra 0.52.0 → 0.53.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 (40) hide show
  1. package/README.kr.md +1 -1
  2. package/README.md +1 -1
  3. package/docs/kr/architecture.md +1 -0
  4. package/docs/kr/cli.md +2 -1
  5. package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +993 -0
  6. package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +93 -0
  7. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +447 -0
  8. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +289 -0
  9. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +774 -0
  10. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +303 -0
  11. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +387 -0
  12. package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +126 -0
  13. package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +180 -0
  14. package/package.json +1 -1
  15. package/runtime/BUILD.json +2 -2
  16. package/runtime/agents/workers/report-writer-worker.md +1 -0
  17. package/runtime/bin/lib/okstra/cli.sh +5 -1
  18. package/runtime/bin/okstra.sh +1 -0
  19. package/runtime/prompts/launch.template.md +1 -0
  20. package/runtime/prompts/profiles/_implementation-deliverable.md +1 -1
  21. package/runtime/prompts/profiles/_implementation-executor.md +16 -9
  22. package/runtime/prompts/profiles/_implementation-verifier.md +4 -1
  23. package/runtime/prompts/profiles/final-verification.md +7 -7
  24. package/runtime/prompts/profiles/implementation-planning.md +8 -4
  25. package/runtime/prompts/wizard/prompts.ko.json +3 -2
  26. package/runtime/python/okstra_ctl/analysis_packet.py +14 -2
  27. package/runtime/python/okstra_ctl/render.py +3 -0
  28. package/runtime/python/okstra_ctl/run.py +541 -41
  29. package/runtime/python/okstra_ctl/wizard.py +25 -7
  30. package/runtime/python/okstra_ctl/worktree.py +126 -9
  31. package/runtime/python/okstra_ctl/worktree_registry.py +88 -17
  32. package/runtime/schemas/final-report-v1.0.schema.json +36 -0
  33. package/runtime/skills/okstra-convergence/SKILL.md +14 -3
  34. package/runtime/skills/okstra-run/SKILL.md +1 -1
  35. package/runtime/templates/reports/final-report.template.md +12 -0
  36. package/runtime/templates/reports/final-verification-input.template.md +8 -5
  37. package/runtime/templates/reports/i18n/en.json +3 -1
  38. package/runtime/templates/reports/i18n/ko.json +3 -1
  39. package/runtime/validators/validate-run.py +143 -1
  40. package/runtime/validators/validate-workflow.sh +6 -1
@@ -0,0 +1,303 @@
1
+ # Stage Worktree 격리 P4 — CLI 패스스루 + 프로파일/문서 정합 구현 계획
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:** 사용자-facing 표면을 stage 격리에 맞춘다 — (B2) `okstra.sh`/`cli.sh`에 `--stage` 패스스루, (프로파일) `_implementation-executor.md`의 batch 문구를 spec §2.3 "한 run = 한 stage"로, (B1) okstra-run SKILL.md sub-flow에 stage_pick 문서화.
6
+
7
+ **Architecture:** B2는 기존 `--base-ref` 등과 동일한 cli.sh case + okstra.sh PY_ARGS 패턴을 그대로 따른다(셸 변경, e2e로 검증). 프로파일/SKILL은 문서 정합 — P3가 `STAGE_BATCH_DIRECTIVE`를 단수("Stage for this implementation run")로 바꿨으므로 executor가 참조하는 backtick 토큰과 batch 가정 문장을 단일 stage로 맞춘다.
8
+
9
+ **Tech Stack:** Bash (`scripts/okstra.sh`, `scripts/lib/okstra/cli.sh`), Markdown (`prompts/profiles/_implementation-executor.md`, `skills/okstra-run/SKILL.md`), pytest (e2e via subprocess).
10
+
11
+ 설계 문서: [docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md](../specs/2026-06-06-stage-worktree-isolation-design.md) §2.3 / §5 (dispatch UX). **비범위:** release-handoff stage PR 목록 수집(§5) → P5 별도 plan.
12
+
13
+ ---
14
+
15
+ ## File Structure
16
+
17
+ - Modify: `scripts/lib/okstra/cli.sh` — `--stage` case ([cli.sh:94](../../../scripts/lib/okstra/cli.sh) 의 `--base-ref` 패턴) + valid-options 문자열([cli.sh:188](../../../scripts/lib/okstra/cli.sh))
18
+ - Modify: `scripts/okstra.sh` — PY_ARGS 패스스루 ([okstra.sh:124](../../../scripts/okstra.sh) 의 `--base-ref` 줄 옆)
19
+ - Modify: `prompts/profiles/_implementation-executor.md` — batch 문구 → 단일 stage ([lines 30–46](../../../prompts/profiles/_implementation-executor.md))
20
+ - Modify: `skills/okstra-run/SKILL.md` — sub-flow 에 stage pick ([SKILL.md:125](../../../skills/okstra-run/SKILL.md))
21
+ - Test: `tests/test_okstra_sh_stage_passthrough.py` (신규, e2e)
22
+
23
+ ---
24
+
25
+ ### Task 1: B2 — `okstra.sh`/`cli.sh` `--stage` 패스스루
26
+
27
+ **Files:**
28
+ - Modify: `scripts/lib/okstra/cli.sh`, `scripts/okstra.sh`
29
+ - Test: `tests/test_okstra_sh_stage_passthrough.py` (신규)
30
+
31
+ - [ ] **Step 1: Write the failing e2e test**
32
+
33
+ ```python
34
+ # tests/test_okstra_sh_stage_passthrough.py (신규)
35
+ """okstra.sh 가 --stage 를 받아 python -m okstra_ctl.run 까지 전달하는지 검증."""
36
+ from __future__ import annotations
37
+
38
+ import json
39
+ import os
40
+ import subprocess
41
+ from pathlib import Path
42
+
43
+ REPO = Path(__file__).resolve().parents[1]
44
+ SCRIPT = REPO / "scripts" / "okstra.sh"
45
+
46
+
47
+ def _git_init(repo: Path) -> None:
48
+ subprocess.run(["git", "init", "-q", str(repo)], check=True)
49
+ subprocess.run(["git", "-C", str(repo), "config", "user.email", "t@e"], check=True)
50
+ subprocess.run(["git", "-C", str(repo), "config", "user.name", "t"], check=True)
51
+ (repo / "README").write_text("seed\n")
52
+ subprocess.run(["git", "-C", str(repo), "add", "."], check=True)
53
+ subprocess.run(["git", "-C", str(repo), "commit", "-q", "-m", "init"], check=True)
54
+
55
+
56
+ def _approved_plan(repo: Path) -> Path:
57
+ src = REPO / "tests" / "fixtures" / "plans" / "valid_one_stage.md"
58
+ # plan 은 .okstra/tasks/<...>/runs/implementation-planning/reports/ 모양일 필요 없이
59
+ # --approved-plan 는 파일 경로만 검사하므로 repo 안 임의 위치로 둔다.
60
+ dst = repo / "plan.md"
61
+ dst.write_text(
62
+ "---\ntitle: t\napproved: true\n---\n\n" + src.read_text(encoding="utf-8"),
63
+ encoding="utf-8",
64
+ )
65
+ return dst
66
+
67
+
68
+ def test_okstra_sh_forwards_stage_to_run(tmp_path):
69
+ repo = tmp_path / "proj"
70
+ repo.mkdir()
71
+ _git_init(repo)
72
+ plan = _approved_plan(repo)
73
+ home = tmp_path / "okstra-home"
74
+ env = {**os.environ, "OKSTRA_HOME": str(home)}
75
+
76
+ result = subprocess.run(
77
+ [str(SCRIPT), "--render-only", "--yes",
78
+ "--task-type", "implementation",
79
+ "--project-id", "proj",
80
+ "--project-root", str(repo),
81
+ "--task-group", "demo", "--task-id", "demo-1",
82
+ "--task-brief", "README",
83
+ "--approved-plan", str(plan),
84
+ "--base-ref", "HEAD",
85
+ "--stage", "1"],
86
+ env=env, capture_output=True, text=True, check=False,
87
+ )
88
+ # cli.sh 가 --stage 를 모르면 "unknown option" / "valid options" 로 죽는다.
89
+ assert "unknown option" not in result.stderr.lower(), result.stderr
90
+ assert "--stage" not in result.stderr or "valid options" not in result.stderr, result.stderr
91
+ # python 까지 전달되면 run.py 가 stage 1 을 선택해 출력한다.
92
+ assert result.returncode == 0, f"stdout={result.stdout}\nstderr={result.stderr}"
93
+ assert "selected stages: 1" in result.stdout, result.stdout
94
+
95
+
96
+ def test_okstra_sh_unknown_flag_still_rejected(tmp_path):
97
+ """가드: 진짜 미지원 플래그는 여전히 거부되어야 한다 (--stage 추가가 파서를
98
+ 느슨하게 만들지 않았는지)."""
99
+ home = tmp_path / "okstra-home"
100
+ env = {**os.environ, "OKSTRA_HOME": str(home)}
101
+ result = subprocess.run(
102
+ [str(SCRIPT), "--render-only", "--yes",
103
+ "--task-type", "error-analysis",
104
+ "--project-id", "proj", "--project-root", str(tmp_path),
105
+ "--task-group", "demo", "--task-id", "demo-1",
106
+ "--task-brief", "x", "--bogus-flag", "v"],
107
+ env=env, capture_output=True, text=True, check=False,
108
+ )
109
+ assert result.returncode != 0
110
+ assert "bogus-flag" in result.stderr or "unknown" in result.stderr.lower()
111
+ ```
112
+
113
+ - [ ] **Step 2: Run test to verify it fails**
114
+
115
+ Run: `cd /Volumes/Workspaces/workspace/projects/Okstra && python3 -m pytest tests/test_okstra_sh_stage_passthrough.py -v`
116
+ Expected: `test_okstra_sh_forwards_stage_to_run` FAILS — cli.sh rejects `--stage` as an unknown option (returncode != 0, "valid options" in stderr). The guard test may already pass.
117
+
118
+ - [ ] **Step 3a: Add `--stage` case to cli.sh**
119
+
120
+ [cli.sh](../../../scripts/lib/okstra/cli.sh) 의 `--base-ref)` case 블록(약 line 94–96) 바로 아래에 추가:
121
+
122
+ ```bash
123
+ --stage)
124
+ STAGE="$(require_option_value --stage "${2-}")"
125
+ shift 2
126
+ ;;
127
+ ```
128
+
129
+ - [ ] **Step 3b: Add `--stage` to the valid-options help string in cli.sh**
130
+
131
+ [cli.sh:188](../../../scripts/lib/okstra/cli.sh) 의 `valid options:` 문자열에서 `--implementation-option` 뒤에 ` --stage` 를 삽입:
132
+
133
+ ```bash
134
+ printf ' valid options: --render-only --resume-clarification --yes --workers --lead-model --claude-model --codex-model --gemini-model --report-writer-model --related-tasks --task-type --project-id --project-root --task-group --task-id --task-brief --directive --clarification-response --approved-plan --approve --implementation-option --stage --no-plan-verification -h|--help\n' >&2
135
+ ```
136
+
137
+ - [ ] **Step 3c: Forward `--stage` in okstra.sh PY_ARGS**
138
+
139
+ [okstra.sh:124](../../../scripts/okstra.sh) 의 `--base-ref` 줄 바로 아래에 추가:
140
+
141
+ ```bash
142
+ [[ -n "${STAGE-}" ]] && PY_ARGS+=(--stage "$STAGE")
143
+ ```
144
+
145
+ - [ ] **Step 4: Run test to verify it passes**
146
+
147
+ Run: `cd /Volumes/Workspaces/workspace/projects/Okstra && python3 -m pytest tests/test_okstra_sh_stage_passthrough.py -v`
148
+ Expected: PASS (2개).
149
+
150
+ - [ ] **Step 5: Commit**
151
+
152
+ ```bash
153
+ cd /Volumes/Workspaces/workspace/projects/Okstra
154
+ git add scripts/lib/okstra/cli.sh scripts/okstra.sh tests/test_okstra_sh_stage_passthrough.py
155
+ git commit -m "feat(cli): forward --stage through okstra.sh to run.py (B2)"
156
+ ```
157
+
158
+ ---
159
+
160
+ ### Task 2: executor 프로파일 — batch 문구 → 단일 stage (spec §2.3)
161
+
162
+ **Files:**
163
+ - Modify: `prompts/profiles/_implementation-executor.md` (lines 30–46)
164
+
165
+ > 문서 변경. 검증은 grep 토큰 + 전체 회귀. P3가 `STAGE_BATCH_DIRECTIVE` 를 단수("Stage for this implementation run")로 바꿨으므로, executor 가 참조하는 backtick 토큰과 batch 가정 문장을 단일 stage 로 맞춘다.
166
+
167
+ - [ ] **Step 1: Replace line 30**
168
+
169
+ before:
170
+ ```
171
+ - re-read the approved plan end-to-end and parse the `## 5.5 Stage Map`. 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 this batch — do NOT recompute the start stage from `consumers.jsonl`.
172
+ ```
173
+ after:
174
+ ```
175
+ - re-read the approved plan end-to-end and parse the `## 5.5 Stage Map`. Read the **Stage** injected in the launch prompt (`Stage for this implementation run`): the single stage number this run owns. The runtime already selected and reserved this stage (one run = one stage) — do NOT recompute the start stage from `consumers.jsonl`.
176
+ ```
177
+
178
+ - [ ] **Step 2: Replace lines 31–32**
179
+
180
+ before:
181
+ ```
182
+ - for each stage in the batch, load every `runs/<plan-key>/carry/stage-<i>.json` for `i ∈ depends-on(stage)` and inject them into the executor's working context as "runtime carry-in". For `depends-on (none)` stages, no sidecar load — task-brief only.
183
+ - 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 commands, Stage Exit Contract, and rollback path are the authoritative scope for that stage.
184
+ ```
185
+ after:
186
+ ```
187
+ - load every `runs/<plan-key>/carry/stage-<i>.json` for `i ∈ depends-on(this stage)` and inject them into the executor's working context as "runtime carry-in". For a `depends-on (none)` stage, no sidecar load — task-brief only.
188
+ - this stage's `depends-on` are all already `status:done`. Its file list, step order, Stage Validation commands, Stage Exit Contract, and rollback path are the authoritative scope.
189
+ ```
190
+
191
+ - [ ] **Step 3: Replace line 40 (section heading)**
192
+
193
+ before:
194
+ ```
195
+ ## Stage execution contract (this run owns the injected stage batch)
196
+ ```
197
+ after:
198
+ ```
199
+ ## Stage execution contract (this run owns one stage)
200
+ ```
201
+
202
+ - [ ] **Step 4: Replace lines 42–43**
203
+
204
+ before:
205
+ ```
206
+ - **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 a JSON object matching the schema in `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 is refused — see `--force-stage` non-goal).
207
+ - **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.
208
+ ```
209
+ after:
210
+ ```
211
+ - **Sidecar evidence writer (BLOCKING).** When this stage's Stage Validation `post` commands all succeed, the Executor MUST emit a JSON object matching the schema in `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`. The file MUST NOT exist before the run starts (overwrite is refused — see `--force-stage` non-goal).
212
+ - **Reverse link (BLOCKING).** The runtime already appended a `status:"started"` row for this stage before the run began. On completion, append a `status:"done"` row with `carry_path` populated for this stage number.
213
+ ```
214
+
215
+ - [ ] **Step 5: Replace lines 44–46 (PR section)**
216
+
217
+ before:
218
+ ```
219
+ - **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:
220
+ - `## Stage <N>` — one section per batched stage: number, title (from Stage Map row), touched files, and validation result.
221
+ - `## Carry-In summary` — per stage, depends-on list + cited identifiers/SHAs from each loaded sidecar (omit when depends-on is empty).
222
+ ```
223
+ after:
224
+ ```
225
+ - **One-PR-per-run.** This run creates exactly one PR titled `Stage <N>: <title>`. The PR body MUST include:
226
+ - `## Stage <N>` — number, title (from Stage Map row), touched files, and validation result.
227
+ - `## Carry-In summary` — depends-on list + cited identifiers/SHAs from each loaded sidecar (omit when depends-on is empty).
228
+ ```
229
+
230
+ - [ ] **Step 6: Verify no stale batch tokens remain + run build/regression**
231
+
232
+ Run:
233
+ ```bash
234
+ cd /Volumes/Workspaces/workspace/projects/Okstra
235
+ grep -nE "Stage batch|batched stage|batch's stages|Stages <first>" prompts/profiles/_implementation-executor.md && echo "STALE TOKENS REMAIN — fix" || echo "clean"
236
+ npm run build >/dev/null 2>&1 && echo "build ok" || echo "build FAILED"
237
+ python3 -m pytest tests/ -q
238
+ ```
239
+ Expected: `clean`, `build ok`, full suite PASS (프로파일은 런타임 복사 대상이라 `npm run build` 가 `runtime/` 에 동기화한다 — build 실패 시 BLOCKED).
240
+
241
+ - [ ] **Step 7: Commit**
242
+
243
+ ```bash
244
+ cd /Volumes/Workspaces/workspace/projects/Okstra
245
+ git add prompts/profiles/_implementation-executor.md
246
+ git commit -m "docs(profiles): executor owns one stage, not a batch (spec §2.3)"
247
+ ```
248
+
249
+ ---
250
+
251
+ ### Task 3: B1 — okstra-run SKILL.md sub-flow 에 stage pick 문서화
252
+
253
+ **Files:**
254
+ - Modify: `skills/okstra-run/SKILL.md:125`
255
+
256
+ - [ ] **Step 1: Replace line 125**
257
+
258
+ before:
259
+ ```
260
+ - `implementation`-only sub-flow: approved-plan path (frontmatter `approved: true` check) + executor pick,
261
+ ```
262
+ after:
263
+ ```
264
+ - `implementation`-only sub-flow: approved-plan path (frontmatter `approved: true` check) + stage pick (`auto` = 의존성 충족된 가장 빠른 미완료 stage, 또는 특정 stage 번호) + executor pick,
265
+ ```
266
+
267
+ - [ ] **Step 2: Verify + commit**
268
+
269
+ ```bash
270
+ cd /Volumes/Workspaces/workspace/projects/Okstra
271
+ grep -n "stage pick" skills/okstra-run/SKILL.md && echo "documented"
272
+ npm run build >/dev/null 2>&1 && echo "build ok"
273
+ git add skills/okstra-run/SKILL.md
274
+ git commit -m "docs(okstra-run): document stage_pick step in implementation sub-flow (B1)"
275
+ ```
276
+
277
+ ---
278
+
279
+ ## Self-Review
280
+
281
+ **Spec coverage (P4 범위):**
282
+ - §5 dispatch B2 (`--stage` CLI 패스스루) → Task 1 ✓ (e2e + unknown-flag 가드)
283
+ - §2.3 한 run = 한 stage 프로파일 정합 → Task 2 ✓ (P3의 단수 DIRECTIVE 와 토큰 일치)
284
+ - §5 dispatch B1 (stage_pick 문서) → Task 3 ✓
285
+ - release-handoff stage PR 수집 → **P5 (비범위, 명시)**
286
+
287
+ **Placeholder scan:** 없음 — Task 1 완전 코드, Task 2/3 완전 before/after.
288
+
289
+ **Type/token consistency:** Task 2 의 after 토큰("Stage for this implementation run")이 P3 의 `STAGE_BATCH_DIRECTIVE` 문자열([run.py 의 `**Stage for this implementation run:**`])과 정확히 일치 — executor 가 launch prompt 에서 그 backtick 을 찾는다.
290
+
291
+ **위험 플래그(구현자 주의):**
292
+ - 프로파일/SKILL 은 `runtime/` 빌드 산출물로 복사된다(seed 규칙). Task 2/3 의 `npm run build` 가 동기화 단계 — 실패 시 BLOCKED.
293
+ - Task 1 e2e 는 implementation 경로라 git `project_root` + `--base-ref HEAD` + approved-plan fixture 가 필수다. `valid_one_stage.md` fixture 가 frontmatter 없이 시작하므로 테스트가 `approved: true` frontmatter 를 prepend 한다(기존 `test_run_stage_arg.py` 패턴과 동일).
294
+
295
+ ## 검증 (P4 완료 기준)
296
+
297
+ ```bash
298
+ cd /Volumes/Workspaces/workspace/projects/Okstra
299
+ python3 -m pytest tests/test_okstra_sh_stage_passthrough.py -v
300
+ grep -nE "Stage batch|batched stage" prompts/profiles/_implementation-executor.md || echo "profile clean"
301
+ grep -n "stage pick" skills/okstra-run/SKILL.md
302
+ npm run build && python3 -m pytest tests/ -q
303
+ ```