okstra 0.102.2 → 0.102.4

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 (167) hide show
  1. package/README.kr.md +5 -5
  2. package/README.md +5 -5
  3. package/docs/kr/architecture/storage-model.md +8 -3
  4. package/docs/kr/architecture.md +12 -13
  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/lib/okstra/interactive.sh +12 -0
  12. package/runtime/bin/okstra-antigravity-exec.sh +1 -2
  13. package/runtime/bin/okstra-codex-exec.sh +1 -2
  14. package/runtime/bin/okstra-render-final-report.py +2 -9
  15. package/runtime/bin/okstra-spawn-followups.py +4 -6
  16. package/runtime/bin/okstra-trace-cleanup.sh +24 -4
  17. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  18. package/runtime/prompts/lead/report-writer.md +1 -1
  19. package/runtime/prompts/profiles/_common-contract.md +9 -11
  20. package/runtime/python/okstra_ctl/codex_dispatch.py +6 -13
  21. package/runtime/python/okstra_ctl/consumers.py +35 -0
  22. package/runtime/python/okstra_ctl/container.py +4 -6
  23. package/runtime/python/okstra_ctl/dispatch_core.py +8 -13
  24. package/runtime/python/okstra_ctl/final_report_paths.py +24 -0
  25. package/runtime/python/okstra_ctl/handoff.py +2 -1
  26. package/runtime/python/okstra_ctl/implementation_outcome.py +271 -0
  27. package/runtime/python/okstra_ctl/implementation_stage.py +7 -11
  28. package/runtime/python/okstra_ctl/path_hints.py +665 -0
  29. package/runtime/python/okstra_ctl/render.py +4 -3
  30. package/runtime/python/okstra_ctl/report_view_artifacts.py +14 -0
  31. package/runtime/python/okstra_ctl/report_views.py +7 -4
  32. package/runtime/python/okstra_ctl/run.py +3 -10
  33. package/runtime/python/okstra_ctl/run_context.py +4 -2
  34. package/runtime/python/okstra_ctl/stage_targets.py +18 -0
  35. package/runtime/python/okstra_ctl/wizard.py +37 -26
  36. package/runtime/python/okstra_ctl/wizard_stage_intent.py +54 -0
  37. package/runtime/python/okstra_project/state.py +40 -2
  38. package/runtime/python/okstra_token_usage/report.py +2 -5
  39. package/runtime/validators/validate-report-views.py +2 -1
  40. package/runtime/validators/validate-run.py +1 -11
  41. package/src/commands/lifecycle/install.mjs +5 -5
  42. package/src/commands/lifecycle/uninstall.mjs +4 -4
  43. package/docs/superpowers/plans/2026-05-12-ticket-id-in-reports.md +0 -638
  44. package/docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md +0 -1568
  45. package/docs/superpowers/plans/2026-05-17-dual-format-final-report.md +0 -167
  46. package/docs/superpowers/plans/2026-05-20-final-report-language.md +0 -1501
  47. package/docs/superpowers/plans/2026-05-20-implementation-planning-multi-stage.md +0 -1267
  48. package/docs/superpowers/plans/2026-05-20-okstra-run-prompt-sot-b1.md +0 -1007
  49. package/docs/superpowers/plans/2026-05-20-wizard-messages-json-sot.md +0 -720
  50. package/docs/superpowers/plans/2026-05-20-wizard-prompt-json-sot-a1.md +0 -681
  51. package/docs/superpowers/plans/2026-05-21-improvement-discovery-task-type.md +0 -1691
  52. package/docs/superpowers/plans/2026-05-24-implementation-lead-context-slimming.md +0 -1700
  53. package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +0 -158
  54. package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +0 -860
  55. package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +0 -326
  56. package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +0 -337
  57. package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +0 -410
  58. package/docs/superpowers/plans/2026-06-02-requirements-discovery-fanout.md +0 -728
  59. package/docs/superpowers/plans/2026-06-04-adversarial-implementation-planning.md +0 -294
  60. package/docs/superpowers/plans/2026-06-04-adversarial-verification.md +0 -570
  61. package/docs/superpowers/plans/2026-06-04-coverage-critic.md +0 -516
  62. package/docs/superpowers/plans/2026-06-04-stage-cohesion-planner.md +0 -351
  63. package/docs/superpowers/plans/2026-06-04-stage-run-batching.md +0 -457
  64. package/docs/superpowers/plans/2026-06-05-acceptance-critic.md +0 -251
  65. package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +0 -323
  66. package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +0 -559
  67. package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +0 -993
  68. package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +0 -93
  69. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +0 -447
  70. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +0 -289
  71. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +0 -774
  72. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +0 -303
  73. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +0 -387
  74. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase2.md +0 -275
  75. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase3.md +0 -282
  76. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4a.md +0 -147
  77. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4b.md +0 -262
  78. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4c.md +0 -184
  79. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4d.md +0 -88
  80. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4e.md +0 -250
  81. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa.md +0 -409
  82. package/docs/superpowers/plans/2026-06-09-implementation-run-artifact-stage-isolation.md +0 -320
  83. package/docs/superpowers/plans/2026-06-10-concurrent-run-team-guard.md +0 -456
  84. package/docs/superpowers/plans/2026-06-10-git-reconcile-stale-sha-recovery.md +0 -1408
  85. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling-PROBE.md +0 -42
  86. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling.md +0 -337
  87. package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +0 -1029
  88. package/docs/superpowers/plans/2026-06-10-stage-group-handoff.md +0 -1572
  89. package/docs/superpowers/plans/2026-06-11-fix-cycle.md +0 -1290
  90. package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +0 -526
  91. package/docs/superpowers/plans/2026-06-12-html-plan-approval.md +0 -1000
  92. package/docs/superpowers/plans/2026-06-13-repo-risk-hardening.md +0 -493
  93. package/docs/superpowers/plans/2026-06-14-host-runtime-auto-execution.md +0 -1775
  94. package/docs/superpowers/plans/2026-06-15-coding-preflight-pack-dispatch-path.md +0 -504
  95. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-final-fixups.md +0 -342
  96. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-fixups.md +0 -258
  97. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-remaining-fixups.md +0 -387
  98. package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +0 -749
  99. package/docs/superpowers/plans/2026-06-15-worker-prompt-anchor-final-fixups.md +0 -828
  100. package/docs/superpowers/plans/2026-06-15-worker-prompt-header-error-contract.md +0 -490
  101. package/docs/superpowers/plans/2026-06-17-okstra-error-report.md +0 -724
  102. package/docs/superpowers/plans/2026-06-18-subagent-pane-reclaim.md +0 -483
  103. package/docs/superpowers/plans/2026-06-19-agent-operating-standard.md +0 -476
  104. package/docs/superpowers/plans/2026-06-19-okstra-inspect-recap-facet.md +0 -647
  105. package/docs/superpowers/plans/2026-06-20-error-feedback-loop.md +0 -1019
  106. package/docs/superpowers/plans/2026-06-20-run-index-row-normalization.md +0 -583
  107. package/docs/superpowers/plans/2026-06-20-stage-auto-integrate-teardown.md +0 -819
  108. package/docs/superpowers/plans/2026-06-21-okstra-container-local-user-test.md +0 -714
  109. package/docs/superpowers/plans/2026-06-21-release-handoff-local-checkout.md +0 -348
  110. package/docs/superpowers/plans/2026-06-23-implementation-stage-multiselect-chain.md +0 -630
  111. package/docs/superpowers/plans/2026-06-23-implementation-step-commit-granularity.md +0 -274
  112. package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +0 -409
  113. package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +0 -542
  114. package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +0 -568
  115. package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +0 -203
  116. package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +0 -525
  117. package/docs/superpowers/specs/2026-05-12-ticket-id-in-reports-design.md +0 -131
  118. package/docs/superpowers/specs/2026-05-15-implementation-plan-verification-design.md +0 -254
  119. package/docs/superpowers/specs/2026-05-20-final-report-language-design.md +0 -383
  120. package/docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md +0 -322
  121. package/docs/superpowers/specs/2026-05-20-okstra-run-prompt-sot-design.md +0 -299
  122. package/docs/superpowers/specs/2026-05-21-improvement-discovery-task-type-design.md +0 -335
  123. package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +0 -113
  124. package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +0 -173
  125. package/docs/superpowers/specs/2026-06-02-requirements-discovery-fanout-design.md +0 -154
  126. package/docs/superpowers/specs/2026-06-04-adversarial-implementation-planning-design.md +0 -90
  127. package/docs/superpowers/specs/2026-06-04-adversarial-verification-design.md +0 -176
  128. package/docs/superpowers/specs/2026-06-04-coverage-critic-design.md +0 -99
  129. package/docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md +0 -98
  130. package/docs/superpowers/specs/2026-06-05-acceptance-critic-design.md +0 -90
  131. package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +0 -87
  132. package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +0 -121
  133. package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +0 -126
  134. package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +0 -180
  135. package/docs/superpowers/specs/2026-06-06-vertical-slice-tdd-planning-design.md +0 -179
  136. package/docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md +0 -169
  137. package/docs/superpowers/specs/2026-06-09-executor-model-custom-id-cascade-design.md +0 -66
  138. package/docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md +0 -87
  139. package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +0 -168
  140. package/docs/superpowers/specs/2026-06-10-concurrent-run-team-guard-design.md +0 -107
  141. package/docs/superpowers/specs/2026-06-10-git-reconcile-stale-sha-recovery-design.md +0 -105
  142. package/docs/superpowers/specs/2026-06-10-lead-worker-completion-polling-design.md +0 -113
  143. package/docs/superpowers/specs/2026-06-10-stage-group-handoff-design.md +0 -156
  144. package/docs/superpowers/specs/2026-06-11-brief-entry-only-handoff-stage-entry-design.md +0 -158
  145. package/docs/superpowers/specs/2026-06-11-fix-cycle-design.md +0 -94
  146. package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +0 -89
  147. package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +0 -358
  148. package/docs/superpowers/specs/2026-06-12-html-plan-approval-design.md +0 -85
  149. package/docs/superpowers/specs/2026-06-12-stage-discipline-rule-design.md +0 -108
  150. package/docs/superpowers/specs/2026-06-13-forbidden-actions-ssot-design.md +0 -134
  151. package/docs/superpowers/specs/2026-06-13-neutral-tmux-lead-adapter-design.md +0 -284
  152. package/docs/superpowers/specs/2026-06-14-host-runtime-auto-execution-design.md +0 -404
  153. package/docs/superpowers/specs/2026-06-17-okstra-error-report-design.md +0 -123
  154. package/docs/superpowers/specs/2026-06-18-subagent-pane-reclaim-design.md +0 -150
  155. package/docs/superpowers/specs/2026-06-19-agent-operating-standard-design.md +0 -120
  156. package/docs/superpowers/specs/2026-06-19-okstra-inspect-recap-facet-design.md +0 -96
  157. package/docs/superpowers/specs/2026-06-20-error-feedback-loop-design.md +0 -171
  158. package/docs/superpowers/specs/2026-06-20-run-index-row-normalization-design.md +0 -112
  159. package/docs/superpowers/specs/2026-06-20-stage-auto-integrate-teardown-design.md +0 -145
  160. package/docs/superpowers/specs/2026-06-21-okstra-container-local-user-test-design.md +0 -125
  161. package/docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md +0 -113
  162. package/docs/superpowers/specs/2026-06-23-implementation-stage-multiselect-chain-design.md +0 -138
  163. package/docs/superpowers/specs/2026-06-23-implementation-step-commit-granularity-design.md +0 -120
  164. package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +0 -129
  165. package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +0 -185
  166. package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +0 -121
  167. package/docs/superpowers/specs/2026-06-24-okstra-container-build-rename-design.md +0 -110
@@ -1,326 +0,0 @@
1
- # final-verification 검증 프로토콜 강화 Implementation Plan
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:** final-verification 을 "리뷰 의견 수집"에서 **target 일치성 → 요구사항 커버리지 → read-only validation → 구조화된 verdict** 로 이어지는 검증 프로토콜로 강화한다.
6
-
7
- **Architecture:** lead 의 강한 entry gate 와 동일한 기준을 (1) 워커 dispatch contract, (2) 입력 템플릿, (3) report schema/template, (4) validator 에 구조화해 전달·강제한다. 변경은 저위험 prose/contract(PR1)와 고위험 schema/validator(PR2) 둘로 나눈다.
8
-
9
- **Tech Stack:** Markdown 프로파일/템플릿, JSON Schema, Python(validate-run.py + pytest), Jinja2 렌더 + i18n(en/ko json), okstra 빌드(`npm run build`).
10
-
11
- 근거: 본 계획은 두 출처를 병합한다 — (A) 검증 초점 분석(이 세션), (B) 다른 에이전트의 final-verification contract 분석. 아래 모든 항목은 소스 직접 확인으로 검증됨.
12
-
13
- ---
14
-
15
- ## 범위 결정 (먼저 확인)
16
-
17
- - **PR1 (저위험, schema 무변경):** 프로파일 prose 정정 + 검증 초점 재설계 + 워커 dispatch target snapshot + 입력 템플릿. 단독으로 가치 있음.
18
- - **PR2 (고위험, breaking — pre-1.0 라 compat 불필요):** report schema/template/i18n + validator 강제 + golden fixture. PR1 위에 쌓는다.
19
- - **범위 밖 (별도):** `analysis-material` 이 brief 전체를 복사하는 중복([material.py](../../../scripts/okstra_ctl/material.py)). **모든 task-type 에 영향을 주는 cross-cutting** 이라 이 PR 들에 섞지 않고 별도 후속 작업으로 분리.
20
-
21
- 브랜치: PR1/PR2 각각 `main` 기준 새 브랜치 (pane-cleanup PR 과 무관).
22
-
23
- ---
24
-
25
- ## File Structure
26
-
27
- **PR1**
28
- - Modify: `prompts/profiles/final-verification.md` — 검증 초점 재설계, no-mutation audit 범위 축소, routing vocab, section-name 호환, conditional-accept 참조, deliverable target-snapshot.
29
- - Modify: `templates/worker-prompt-preamble.md` — `implementation` 전용 Worktree 블록을 `final-verification` 까지 확장(+ base ref / head SHA / diff stat anchor).
30
- - Modify: `templates/reports/final-verification-input.template.md` — `## Requirement Coverage Source` 섹션 + target/requirement 질문.
31
-
32
- **PR2**
33
- - Modify: `schemas/final-report-v1.0.schema.json` — `sourceImplementationReport`(diffSummaryQuote/implementationBaseRef/gitDiffStat), `finalVerdict`(conditionalAcceptanceConditions), `ReadonlyCommandRow`(status/nullable exitCode/rejectionReason).
34
- - Modify: `templates/reports/final-report.template.md` — §4.8.1 새 필드 렌더, §4.8.x Conditional Acceptance Conditions, Read-only Command Log status 렌더.
35
- - Modify: `templates/reports/i18n/en.json` + `ko.json` — 신규 `evidenceMeta`/라벨 키.
36
- - Modify: `validators/validate-run.py` — verdict↔blocker/condition/routing 일관성 강제 + 섹션 목록.
37
- - Modify: `tests/test_validate_run.py`(또는 해당 파일) — 강제 로직 회귀 테스트.
38
- - Modify: `tests/fixtures/reports/golden-final-verification.md`, `tests/fixtures/final-report-data/final-verification-001.data.json` — 새 필드 반영.
39
- - Modify: `CHANGES.md` — 사용자 영향 엔트리(PR2 에서, 또는 양쪽).
40
-
41
- `runtime/` 는 gitignored build output — 커밋에 포함 안 함. profile/template/preamble/schema/i18n 변경 후 `npm run build` 로 동기화.
42
-
43
- ---
44
-
45
- # PR1 — 저위험 prose / contract
46
-
47
- ## Task 1: 검증 초점 재설계 + Expected output emphasis 제거
48
-
49
- **Files:** Modify `prompts/profiles/final-verification.md:11-21`
50
-
51
- - [ ] **Step 1:** `Primary focus areas` + `Expected output emphasis` 블록(11-21행)을 아래로 교체.
52
-
53
- ```markdown
54
- - Primary focus areas (each maps to a deliverable section below):
55
- - Acceptance-gating — a failure here pushes the verdict toward `blocked` / `conditional-accept`:
56
- - requirement & acceptance coverage — every must-pass point in the brief's `## Acceptance Criteria` (and the approved plan's requirements) is covered with a cited artifact or raised as an Acceptance Blocker; no silent omissions
57
- - delivered artifacts match recorded expected values in `reference-expectations` (config files, deployment manifests, other recorded expected states); when reference-expectations are absent, record it as missing information rather than assuming a match
58
- - test & validation suite pass status — independently re-run the read-only two-tier command set (Tier 1 = brief/approved-plan `validation`, Tier 2 = `project.json` `qaCommands`) and confirm each passes on the verified head, citing exact command + exit code
59
- - test correctness — delivered tests actually assert the intended behaviour: no gutted/weakened assertions, no tautological or always-passing tests, no tests exercising only mocks; new behaviour has matching coverage
60
- - no new defects introduced — the diff does not break previously-working behaviour and adds no new bug (logic/off-by-one, null/empty handling, resource leaks, broken error paths)
61
- - scope conformance — the delivered diff stays within the approved plan's scope; flag out-of-scope edits, unrelated file changes, leftover debug/commented-out code, and unintended deletions
62
- - Residual-tracked — note as Residual Risk unless severe enough to block:
63
- - unresolved edge cases
64
- - regression risk in adjacent code paths not directly changed
65
- - documentation or rollout gaps
66
- - production-specific failure modes not caught by tests (env/config drift across stages, secrets & permission/auth changes, migration ordering & rollback executability, observability gaps)
67
- ```
68
-
69
- - [ ] **Step 2:** `grep -n "Expected output emphasis" prompts/profiles/final-verification.md` → 0건(제거 확인). `grep -rn "Expected output emphasis" tests/ validators/` → 0건(참조 없음, 이미 확인됨).
70
- - [ ] **Step 3:** `npm run build && bash validators/validate-workflow.sh` → OK.
71
- - [ ] **Step 4:** commit `feat(profiles/final-verification): 검증 초점 재설계 — gating/residual 2계층 + 테스트정확성·범위·신규버그 추가`.
72
-
73
- ## Task 2: no-mutation audit 범위 축소 (자기모순 제거)
74
-
75
- **Files:** Modify `prompts/profiles/final-verification.md:43`
76
-
77
- - [ ] **Step 1:** self-review 5번 항목을 교체.
78
-
79
- old:
80
- ```
81
- 5. **No-mutation audit** — scan the run's session transcripts for any Edit / Write / mutating Bash command. Any occurrence means the run has crossed into implementation and MUST be re-routed; do NOT silently strip the evidence.
82
- ```
83
- new:
84
- ```
85
- 5. **No source-mutation audit** — scan the run's session transcripts for Edit / Write or state-mutating Bash commands that touch paths OUTSIDE `<PROJECT_ROOT>/.okstra/**` and outside the assigned run-artifact paths. Writes to worker prompts, audit sidecars, team-state, the final-report `data.json`, and rendered reports under the run directory are allowed okstra artifacts. Any source/schema/deployment mutation means the run has crossed into implementation and MUST be re-routed; do NOT silently strip the evidence.
86
- ```
87
-
88
- - [ ] **Step 2:** `npm run build` → OK. commit `fix(profiles/final-verification): no-mutation audit 를 source-mutation 으로 한정 (.okstra artifact 허용)`.
89
-
90
- ## Task 3: routing vocabulary + section-name 호환 + conditional-accept 참조
91
-
92
- **Files:** Modify `prompts/profiles/final-verification.md` (23, 29, 35행)
93
-
94
- - [ ] **Step 1 (routing, 35행):** `Routing recommendation` deliverable 줄 교체.
95
-
96
- old:
97
- ```
98
- - **Routing recommendation**: brief note on the next safe phase (`done`, `error-analysis`, `implementation-planning`) tied to the verdict and blocker list.
99
- ```
100
- new:
101
- ```
102
- - **Routing recommendation**: the next safe phase — one of `release-handoff`, `done`, `error-analysis`, `implementation-planning` — tied to the verdict and blocker list. `release-handoff` is allowed ONLY when the Verdict Token is `accepted`.
103
- ```
104
-
105
- - [ ] **Step 2 (section-name 호환, 23행):** entry-gate 줄에서 implementation report 필수 섹션 인용을 양쪽 표기 허용으로.
106
-
107
- old fragment: ``includes `Plan link & approval evidence`, `Commit list`, ``
108
- new fragment: ``includes the approved-plan reference (heading `Approved Plan Reference` or `Plan link & approval evidence`), `Commit list`, ``
109
-
110
- - [ ] **Step 3 (conditional-accept 참조, 29행):** `conditional-accept` 설명에 구조화 deliverable 참조 추가(현 문장 끝에 append).
111
-
112
- append: ` Each condition MUST be recorded as a row in the **Conditional Acceptance Conditions** deliverable (id, condition, evidence required, blocks-release-handoff).`
113
-
114
- > 주의: 이 줄은 PR2 의 §4.8 Conditional Acceptance Conditions 섹션·schema 와 짝이다. PR1 만 단독 머지할 경우 이 Step 3 는 PR2 와 함께 가도록 보류 가능 — 실행 시점에 결정.
115
-
116
- - [ ] **Step 4:** `npm run build && bash validators/validate-workflow.sh` → OK. commit `fix(profiles/final-verification): routing 에 release-handoff 추가 + approved-plan 섹션명 호환`.
117
-
118
- ## Task 4: 워커 dispatch 에 verification target snapshot 전달
119
-
120
- **Files:** Modify `templates/worker-prompt-preamble.md:84-88`, `prompts/profiles/final-verification.md`(deliverable)
121
-
122
- - [ ] **Step 1 (preamble):** `For the implementation phase specifically...` 블록(84-88)을 implementation + final-verification 둘 다 커버하도록 교체.
123
-
124
- old:
125
- ```
126
- For the **implementation phase** specifically, the dispatched prompt MUST also include:
127
-
128
- - `**Worktree:** <absolute-path>` — the task worktree path.
129
- - `cwd for every mutating command: <absolute-path>` — same as Worktree path; used by codex / gemini wrappers as `--add-dir` / `--include-directories`.
130
- ```
131
- new:
132
- ```
133
- For the **implementation phase** specifically, the dispatched prompt MUST also include:
134
-
135
- - `**Worktree:** <absolute-path>` — the task worktree path.
136
- - `cwd for every mutating command: <absolute-path>` — same as Worktree path; used by codex / gemini wrappers as `--add-dir` / `--include-directories`.
137
-
138
- For the **final-verification phase** specifically, the dispatched prompt MUST also include the verification target snapshot so every analyser verifies the SAME target the lead captured at the entry gate:
139
-
140
- - `**Worktree:** <absolute-path>` — the checkout under verification (read-only).
141
- - `**Verification base ref:** <base-ref>` — the implementation base for the diff.
142
- - `**Verification head SHA:** <sha>` — head SHA captured at run start.
143
- - `**Verification diff stat:** <git diff --stat output>` — the captured diff-stat that bounds the verification scope.
144
- ```
145
-
146
- - [ ] **Step 2 (profile deliverable, final-verification.md "Source Implementation Report" deliverable 28행 근처):** 워커가 이 snapshot 을 기준으로 검증하고 보고서가 cite 하도록, deliverable 의 Source Implementation Report 항목에 한 줄 추가:
147
-
148
- append: ` The lead injects this same target snapshot into every analyser prompt (`**Worktree:** / **Verification base ref:** / **Verification head SHA:** / **Verification diff stat:**`); a worker that cannot confirm its analysis ran against that exact head MUST record a `tool-failure` rather than verify an ambiguous target.`
149
-
150
- - [ ] **Step 3:** `npm run build && bash validators/validate-workflow.sh` → OK. commit `feat(worker-preamble,final-verification): 워커 dispatch 에 verification target snapshot 전달`.
151
-
152
- ## Task 5: 입력 템플릿에 Requirement Coverage Source 추가
153
-
154
- **Files:** Modify `templates/reports/final-verification-input.template.md` (`## Source Implementation Report` 다음)
155
-
156
- - [ ] **Step 1:** `## Source Implementation Report` 블록 종료(40행 인용구) 다음에 신규 섹션 삽입.
157
-
158
- ```markdown
159
-
160
- ## Requirement Coverage Source
161
-
162
- - Approved implementation-planning report path:
163
- - Requirement source used for coverage (plan section / brief Acceptance Criteria):
164
- - Requirement IDs / acceptance IDs to verify:
165
- - Requirements intentionally excluded from this verification:
166
-
167
- > final-verification 은 위 source 의 각 requirement / acceptance id 마다 Validation Evidence 에 artifact 를 cite 해야 한다. source 가 비면 brief 의 `## Acceptance Criteria` 를 기본 source 로 사용한다.
168
- ```
169
-
170
- - [ ] **Step 2:** 입력 템플릿의 analyser 질문 목록(85행 근처) 맨 앞에 target-integrity 질문 2개 추가:
171
-
172
- ```markdown
173
- 1. Does the verification target (head SHA / diff stat) match the implementation report's commit list and diff summary?
174
- 2. For each requirement / acceptance criterion, what exact artifact (commit SHA, test output, log line, config value) proves coverage?
175
- ```
176
- (기존 번호 질문들은 뒤로 밀린다.)
177
-
178
- - [ ] **Step 3:** `npm run build`. 렌더 검증: `python3 -m pytest tests/test_template_full_render_both_langs.py -q` → PASS. commit `feat(final-verification-input): Requirement Coverage Source + target-integrity 질문`.
179
-
180
- ## Task 6: PR1 검증 + PR
181
-
182
- - [ ] **Step 1:** `python3 -m pytest tests/ -q` → 전부 PASS(또는 tmux skip). `bash validators/validate-workflow.sh` → OK. `node bin/okstra --version`.
183
- - [ ] **Step 2:** diff critique — 새 토큰 grep(`grep -rn "Verification base ref\|Requirement Coverage Source\|No source-mutation audit" prompts/ templates/`), runtime parity.
184
- - [ ] **Step 3:** push + `gh pr create --base main` (제목 `feat(final-verification): 검증 프로토콜 강화 — 초점/target snapshot/입력 (PR1)`).
185
-
186
- ---
187
-
188
- # PR2 — report contract (schema / template / i18n / validator)
189
-
190
- > PR1 머지 후 `main` 기준 새 브랜치에서 진행. breaking schema 변경(pre-1.0, compat 불필요).
191
-
192
- ## Task 7: schema — sourceImplementationReport diff-stat 분리
193
-
194
- **Files:** Modify `schemas/final-report-v1.0.schema.json` (`sourceImplementationReport`, 현 ~547행)
195
-
196
- - [ ] **Step 1 (test first):** schema 검증 테스트 추가 — diff-stat/diffSummaryQuote 누락 시 invalid. (해당 schema 검증 테스트 파일은 `tests/test_validate_run*.py` 또는 schema 단위 테스트; 실행 시 위치 확인 후 케이스 추가.)
197
- - [ ] **Step 2:** `sourceImplementationReport` 를 교체:
198
-
199
- ```json
200
- "sourceImplementationReport": {
201
- "type": "object",
202
- "required": ["path", "commitListQuote", "diffSummaryQuote", "worktreePath", "implementationBaseRef", "capturedHeadSha", "gitStatusShort", "gitDiffStat"],
203
- "additionalProperties": false,
204
- "properties": {
205
- "path": { "type": "string" },
206
- "commitListQuote": { "type": "string" },
207
- "diffSummaryQuote": { "type": "string" },
208
- "worktreePath": { "type": "string" },
209
- "implementationBaseRef": { "type": "string" },
210
- "capturedHeadSha": { "type": "string" },
211
- "gitStatusShort": { "type": "string" },
212
- "gitDiffStat": { "type": "string" }
213
- }
214
- }
215
- ```
216
- (주의: 기존 `baseHeadSha` → `implementationBaseRef` + `capturedHeadSha` 분리. template/i18n/fixture 동반 수정 필요 — Task 10/11.)
217
-
218
- - [ ] **Step 3:** schema 테스트 PASS. commit.
219
-
220
- ## Task 8: schema — conditionalAcceptanceConditions
221
-
222
- **Files:** Modify `schemas/final-report-v1.0.schema.json` (`finalVerdict` + `$defs`)
223
-
224
- - [ ] **Step 1 (test first):** verdict=`conditional-accept` 인데 conditions 비면 invalid 케이스.
225
- - [ ] **Step 2:** `finalVerdict.properties` 에 추가 + `$defs` 에 row 정의:
226
-
227
- ```json
228
- "conditionalAcceptanceConditions": {
229
- "type": "array",
230
- "items": { "$ref": "#/$defs/ConditionalAcceptanceConditionRow" }
231
- }
232
- ```
233
- ```json
234
- "ConditionalAcceptanceConditionRow": {
235
- "type": "object",
236
- "required": ["id", "condition", "evidenceRequired", "blocksReleaseHandoff"],
237
- "additionalProperties": false,
238
- "properties": {
239
- "id": { "type": "string", "pattern": "^CA-\\d{3,}$" },
240
- "condition": { "type": "string", "minLength": 1 },
241
- "evidenceRequired": { "type": "string", "minLength": 1 },
242
- "blocksReleaseHandoff": { "type": "boolean" }
243
- }
244
- }
245
- ```
246
- (`finalVerdict.required` 에는 넣지 않음 — accepted/blocked 에선 빈 배열 허용; 강제는 validator 에서 verdict 조건부로.)
247
-
248
- - [ ] **Step 3:** 테스트 PASS. commit.
249
-
250
- ## Task 9: schema — ReadonlyCommandRow status / nullable exitCode
251
-
252
- **Files:** Modify `schemas/final-report-v1.0.schema.json` (`ReadonlyCommandRow`, 현 ~1306행)
253
-
254
- - [ ] **Step 1 (test first):** status=`rejected`, exitCode=null 인 row 가 valid 케이스 + status=`executed` 인데 exitCode=null 이면 invalid(아래 Step 2 의 조건).
255
- - [ ] **Step 2:** `ReadonlyCommandRow` 교체:
256
-
257
- ```json
258
- "ReadonlyCommandRow": {
259
- "type": "object",
260
- "required": ["number", "tier", "command", "status", "exitCode", "outputTail"],
261
- "additionalProperties": false,
262
- "properties": {
263
- "number": { "type": "integer", "minimum": 1 },
264
- "tier": { "enum": [1, 2] },
265
- "command": { "type": "string", "minLength": 1 },
266
- "status": { "enum": ["executed", "rejected", "not-configured"] },
267
- "exitCode": { "type": ["integer", "null"] },
268
- "rejectionReason": { "type": ["string", "null"] },
269
- "outputTail": { "type": "string" }
270
- },
271
- "allOf": [
272
- { "if": { "properties": { "status": { "const": "executed" } } },
273
- "then": { "properties": { "exitCode": { "type": "integer" } } } },
274
- { "if": { "properties": { "status": { "const": "rejected" } } },
275
- "then": { "required": ["rejectionReason"] } }
276
- ]
277
- }
278
- ```
279
-
280
- - [ ] **Step 3:** 테스트 PASS. commit.
281
-
282
- ## Task 10: template §4.8 — 새 필드 렌더
283
-
284
- **Files:** Modify `templates/reports/final-report.template.md` (§4.8.1, + 신규 conditions 섹션, Read-only Command Log)
285
-
286
- - [ ] **Step 1:** §4.8.1 Source Implementation Report 렌더에 diffSummaryQuote / implementationBaseRef / gitDiffStat 추가, baseHeadSha → capturedHeadSha 로 변경 (i18n 키는 Task 11).
287
- - [ ] **Step 2:** §4.8.x `Conditional Acceptance Conditions` 섹션 추가 — verdict=`conditional-accept` 일 때 행 렌더, 아니면 `- Not applicable (verdict is not conditional-accept).`.
288
- - [ ] **Step 3:** Read-only Command Log 렌더에 `status` 열 + rejected 행의 `rejectionReason`, exitCode null 처리.
289
- - [ ] **Step 4:** `npm run build`. `python3 -m pytest tests/test_template_full_render_both_langs.py tests/test_render_phase_blocks.py -q` → PASS(또는 fixture 갱신 후). commit.
290
-
291
- ## Task 11: i18n 키 + golden fixture
292
-
293
- **Files:** Modify `templates/reports/i18n/en.json`, `ko.json`, `tests/fixtures/reports/golden-final-verification.md`, `tests/fixtures/final-report-data/final-verification-001.data.json`
294
-
295
- - [ ] **Step 1:** `en.json` + `ko.json` 의 `evidenceMeta` 에 키 추가: `diffSummaryAtRunStart`, `implementationBaseRef`, `gitDiffStatAtRunStart` (+ conditions/command-status 라벨). 기존 `capturedHeadBaseSha` → `capturedHeadSha` 의미로 정리.
296
- - [ ] **Step 2:** golden data.json 에 새 필드 채우고, golden md 를 새 렌더 결과로 갱신 (`npm run build` 후 렌더러로 재생성하거나 수동 갱신).
297
- - [ ] **Step 3:** `python3 -m pytest tests/test_template_full_render_both_langs.py tests/test_report_views.py -q` → PASS. commit.
298
-
299
- ## Task 12: validator — verdict↔blocker/condition/routing 일관성 강제
300
-
301
- **Files:** Modify `validators/validate-run.py` (final-verification 블록 ~1172), `tests/test_validate_run*.py`
302
-
303
- - [ ] **Step 1 (test first):** 4개 회귀 테스트 추가:
304
- - verdict=`accepted` + acceptanceBlockers 비어있지 않음 → fail
305
- - verdict=`blocked` + acceptanceBlockers 0개 → fail
306
- - verdict=`conditional-accept` + conditions 0개 → fail
307
- - routingRecommendation 이 `release-handoff` 인데 verdict ≠ `accepted` → fail
308
- - [ ] **Step 2:** `if task_type == "final-verification":` 블록(1172)에 위 4개 검사 추가. 신규 §4.8 섹션 추가했으면 `FINAL_VERIFICATION_REQUIRED_SECTIONS`(876)에 `"Conditional Acceptance Conditions"` 등 반영.
309
- - [ ] **Step 3:** `python3 -m pytest tests/test_validate_run.py -q` → PASS. commit.
310
-
311
- ## Task 13: PR2 검증 + docs + PR
312
-
313
- - [ ] **Step 1:** `python3 -m pytest tests/ -q`, `bash validators/validate-workflow.sh`, golden 렌더 테스트 전부 PASS.
314
- - [ ] **Step 2:** `CHANGES.md` 에 사용자 영향 엔트리(verdict 일관성 강제 + diff-stat/conditions/command-status 구조화).
315
- - [ ] **Step 3:** diff critique(rule #5) — schema↔template↔i18n↔fixture↔validator 5자 정합, 새 식별자 grep.
316
- - [ ] **Step 4:** push + `gh pr create --base main` (`feat(final-verification): report contract 구조화 — diff-stat/conditions/command-status + verdict 강제 (PR2)`).
317
-
318
- ---
319
-
320
- ## Self-Review (작성자 체크)
321
-
322
- - **Spec coverage:** 다른 에이전트 8개 항목 매핑 — #1 target snapshot=Task4, #2 diff-stat=Task7/10/11, #3 requirement source=Task5, #4 no-mutation=Task2, #5 conditions=Task3/8/10/12, #6 command status=Task9/10/12, #7 routing=Task3, #8 section-name=Task3. + 검증 초점 재설계=Task1.
323
- - **범위 밖 명시:** material.py 중복(cross-cutting)은 별도 — spawn 권장.
324
- - **Placeholder:** schema/profile/preamble/input 은 완전한 텍스트 포함. template/i18n/fixture(Task10/11)는 정확한 위치·키를 지정하되, 렌더 결과 golden md 는 빌드로 재생성하는 절차로 둠(수작업 전체 전사 비현실적).
325
- - **enforcement 정직성:** 검증 초점(Task1)·no-mutation(Task2)·target snapshot(Task4)은 선언 레벨(런타임 강제 없음). verdict↔blocker/condition/routing(Task12)·schema 필드(Task7-9)는 validator/schema 가 런타임 강제.
326
- - **의존성:** Task3 Step3(conditional 참조)는 PR2 의 conditions 와 짝 — PR1 단독이면 보류.
@@ -1,337 +0,0 @@
1
- # okstra-run 브랜치 결정 확인 단계 구현 계획
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:** okstra-run wizard 의 최종 confirm 직전에 "새 worktree+브랜치 생성 vs 현재 worktree 재사용" 을 명시 확인하는 전용 `branch_confirm` 단계를 추가한다(동작 변경 없음, 확인 게이트만).
6
-
7
- **Architecture:** `worktree.py` 의 provisioning 결정 로직을 부수효과 없는 `preview_worktree_decision()` 으로 추출하고 `provision_task_worktree` 가 이를 호출하게 리팩터한다(미리보기=실제 보장). wizard 에 predicate-driven `branch_confirm` Step 을 추가해 그 헬퍼로 결정을 미리보고 picker 로 확인받는다. 강제는 state 전이 구조(`confirm` 도달 전 `branch_confirm` 필수).
8
-
9
- **Tech Stack:** Python 3 (pytest), wizard prompts JSON(`prompts/wizard/prompts.ko.json`).
10
-
11
- 설계 근거: [docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md](../specs/2026-06-02-okstra-run-branch-confirm-step-design.md)
12
-
13
- 핵심 사실(검증됨):
14
- - okstra-run 스킬은 `--work-category` 를 넘기지 않으므로 wizard 경로의 work_category 는 `""` → 실제 브랜치는 `task-<task-id>` (`_work_category_prefix("")=="task"`). 미리보기도 `work_category=""` 로 동일 계산.
15
- - wizard 는 predicate-driven: 각 `Step.applies(state)` 가 참인 첫 미답 Step 이 다음 단계. prompt 텍스트는 `prompts/wizard/prompts.ko.json` 의 `steps.<id>`.
16
- - provision 결정 4갈래: not-git(`skipped-not-git`) / in-worktree(`skipped-in-worktree`) / registry active(`reused`) / 신규(`created`).
17
-
18
- ---
19
-
20
- ## File Structure
21
-
22
- - `scripts/okstra_ctl/worktree.py` — `WorktreeDecision` dataclass + `preview_worktree_decision()` 추출, `provision_task_worktree` 가 이를 사용하도록 리팩터.
23
- - `scripts/okstra_ctl/wizard.py` — `S_BRANCH_CONFIRM` 상수, `WizardState.branch_confirmed`, `_build_branch_confirm`/`_submit_branch_confirm`, STEPS 항목, `_ready_for_confirm` 갱신.
24
- - `prompts/wizard/prompts.ko.json` — `steps.branch_confirm` 텍스트.
25
- - `docs/kr/architecture.md`, `CHANGES.md` — 새 단계 / 사용자 영향.
26
- - tests: `tests/test_okstra_worktree.py`, `tests/test_okstra_ctl_wizard.py`, `tests/test_wizard_prompts.py`.
27
-
28
- ---
29
-
30
- ## Task 1: preview_worktree_decision 추출 + provision 리팩터
31
-
32
- **Files:**
33
- - Modify: `scripts/okstra_ctl/worktree.py`
34
- - Test: `tests/test_okstra_worktree.py`
35
-
36
- - [ ] **Step 1: 실패 테스트 작성** (`tests/test_okstra_worktree.py` 에 추가)
37
-
38
- ```python
39
- def test_preview_decision_new_when_main_repo(tmp_path, monkeypatch):
40
- import subprocess
41
- from okstra_ctl.worktree import preview_worktree_decision
42
- repo = tmp_path / "repo"; repo.mkdir()
43
- subprocess.run(["git", "init", "-q"], cwd=repo, check=True)
44
- monkeypatch.setenv("OKSTRA_HOME", str(tmp_path / "home"))
45
- d = preview_worktree_decision(
46
- project_root=repo, project_id="proj", task_group_segment="grp",
47
- task_id_segment="dev-1", work_category="", base_ref="main",
48
- )
49
- assert d.status == "new"
50
- assert d.branch == "task-dev-1"
51
- assert d.base_ref == "main"
52
- assert d.worktree_path.endswith("/proj/grp/dev-1")
53
-
54
-
55
- def test_preview_decision_not_git(tmp_path):
56
- from okstra_ctl.worktree import preview_worktree_decision
57
- d = preview_worktree_decision(
58
- project_root=tmp_path, project_id="proj", task_group_segment="grp",
59
- task_id_segment="dev-1", work_category="", base_ref="main",
60
- )
61
- assert d.status == "skipped-not-git"
62
- ```
63
-
64
- - [ ] **Step 2: 실패 확인**
65
-
66
- Run: `python3 -m pytest tests/test_okstra_worktree.py -k preview -q`
67
- Expected: FAIL — `ImportError: cannot import name 'preview_worktree_decision'`
68
-
69
- - [ ] **Step 3: WorktreeDecision + preview_worktree_decision 구현**
70
-
71
- `worktree.py` 에 추가 (기존 `WorktreeProvision` dataclass 근처). decision 은 provision 의 4갈래를 부수효과 없이 계산한다. registry 재사용/in-worktree/not-git 분기는 기존 `provision_task_worktree` 의 가드(`_is_git_repo`, `_is_inside_non_main_worktree`, `worktree_registry.lookup`)를 그대로 호출(모두 read-only).
72
-
73
- ```python
74
- from dataclasses import dataclass
75
-
76
- @dataclass
77
- class WorktreeDecision:
78
- status: str # "new" | "reused" | "skipped-in-worktree" | "skipped-not-git"
79
- path: str # worktree path (new: prospective; reuse: existing; skip: project_root)
80
- branch: str = "" # new: prospective branch; reused: existing branch
81
- base_ref: str = "" # new: requested base_ref; reused: existing base
82
-
83
-
84
- def preview_worktree_decision(
85
- *, project_root, project_id, task_group_segment, task_id_segment,
86
- work_category, base_ref="",
87
- ) -> "WorktreeDecision":
88
- """Side-effect-free: what provision_task_worktree WOULD do, without touching disk.
89
-
90
- Mirrors provision's decision branches exactly; reuses the same read-only
91
- helpers so preview never diverges from the actual provisioning result.
92
- """
93
- project_root = Path(project_root)
94
- if not _is_git_repo(project_root):
95
- return WorktreeDecision(status="skipped-not-git", path=str(project_root))
96
- if _is_inside_non_main_worktree(project_root):
97
- return WorktreeDecision(status="skipped-in-worktree", path=str(project_root))
98
- safe_project = _safe_segment(project_id)
99
- safe_group = _safe_segment(task_group_segment)
100
- safe_task = _safe_segment(task_id_segment)
101
- existing = worktree_registry.lookup(safe_project, safe_group, safe_task)
102
- if existing is not None and existing.status == "active":
103
- return WorktreeDecision(
104
- status="reused", path=existing.worktree_path,
105
- branch=existing.branch, base_ref=existing.base_ref,
106
- )
107
- return WorktreeDecision(
108
- status="new",
109
- path=str(compute_worktree_path(
110
- project_id=safe_project, task_group_segment=safe_group,
111
- task_id_segment=safe_task)),
112
- branch=compute_branch_name(work_category=work_category, task_id_segment=safe_task),
113
- base_ref=base_ref,
114
- )
115
- ```
116
-
117
- - [ ] **Step 4: provision_task_worktree 가 헬퍼를 쓰도록 리팩터**
118
-
119
- `provision_task_worktree` 의 결정 분기(현재 not-git / in-worktree / registry-lookup 구간, 약 line 494-532)를 `decision = preview_worktree_decision(...)` 한 줄 호출로 교체하고, `decision.status` 로 분기:
120
- - `skipped-not-git` → 기존 note 로 `WorktreeProvision(status="skipped-not-git", ...)` 반환.
121
- - `skipped-in-worktree` → 기존 note 로 반환.
122
- - `reused` → `worktree_registry.touch_phase(...)` + `_seed_worktree_settings_symlink(Path(decision.path))` 후 기존 reused note 로 반환.
123
- - `new` → `decision.branch` / `decision.path` 를 사용해 기존 생성 로직(`git worktree add` + `worktree_registry.reserve` + seed) 그대로 수행, `status="created"` 반환.
124
-
125
- 핵심: 결정(분기 판정 + branch/path 계산)은 헬퍼가 단일 소스. provision 은 실행만.
126
-
127
- - [ ] **Step 5: 통과 + 회귀 확인**
128
-
129
- Run: `python3 -m pytest tests/test_okstra_worktree.py -q`
130
- Expected: 신규 preview 테스트 통과 + 기존 worktree 테스트 전부 통과(회귀 0).
131
-
132
- - [ ] **Step 6: 커밋**
133
-
134
- ```bash
135
- git add scripts/okstra_ctl/worktree.py tests/test_okstra_worktree.py
136
- git commit -m "refactor(worktree): preview_worktree_decision 추출 + provision 공유"
137
- ```
138
-
139
- ---
140
-
141
- ## Task 2: wizard branch_confirm 단계
142
-
143
- **Files:**
144
- - Modify: `scripts/okstra_ctl/wizard.py`
145
- - Modify: `prompts/wizard/prompts.ko.json`
146
- - Test: `tests/test_okstra_ctl_wizard.py`, `tests/test_wizard_prompts.py`
147
-
148
- - [ ] **Step 1: 프롬프트 텍스트 추가** (`prompts/wizard/prompts.ko.json` 의 `steps` 객체에)
149
-
150
- ```json
151
- "branch_confirm": {
152
- "label": "{summary}",
153
- "labels": {
154
- "new": "새 브랜치 `{branch}` 를 base-ref `{base_ref}` 에서 새 worktree(`{path}`)에 생성합니다 — 진행할까요?",
155
- "reuse": "현재 worktree(`{path}`, 브랜치 `{branch}`)를 재사용합니다 — 진행할까요?",
156
- "in_worktree": "현재 worktree(`{path}`)에서 그대로 진행합니다(이미 non-main worktree) — 진행할까요?",
157
- "not_git": "git 저장소가 아니므로 `{path}` 에서 직접 진행합니다 — 진행할까요?"
158
- },
159
- "options": { "proceed": "진행", "edit": "base-ref 다시 고르기" },
160
- "echo_template": "branch-confirm: {value}"
161
- }
162
- ```
163
-
164
- - [ ] **Step 2: 실패 테스트 작성** — 핸들러 직접 테스트 (전체 wizard 구동 없이; 기존 파일의 `WizardState(...)` 직접 구성 + 핸들러 직접 호출 패턴을 따름. `_seed_wizard_prompts` 헬퍼는 파일 상단에 이미 있음)
165
-
166
- ```python
167
- def test_build_branch_confirm_new_worktree(tmp_path, monkeypatch):
168
- import subprocess
169
- from okstra_ctl.wizard import WizardState, _build_branch_confirm, S_BRANCH_CONFIRM
170
- repo = tmp_path / "repo"; repo.mkdir()
171
- subprocess.run(["git", "init", "-q"], cwd=repo, check=True)
172
- _seed_wizard_prompts(repo)
173
- monkeypatch.setenv("OKSTRA_HOME", str(tmp_path / "home"))
174
- state = WizardState(
175
- workspace_root=str(repo), project_root=str(repo),
176
- project_id="proj", task_group="grp", task_id="dev-1", base_ref="main",
177
- )
178
- p = _build_branch_confirm(state)
179
- assert p.step == S_BRANCH_CONFIRM and p.kind == "pick"
180
- assert "task-dev-1" in p.label and "main" in p.label
181
- vals = [o.value for o in p.options]
182
- assert "proceed" in vals and "edit" in vals # new 모드 → edit 제공
183
-
184
-
185
- def test_submit_branch_confirm_proceed_and_edit(tmp_path):
186
- from okstra_ctl.wizard import WizardState, _submit_branch_confirm
187
- state = WizardState(
188
- workspace_root=str(tmp_path), project_root=str(tmp_path),
189
- project_id="proj", task_group="grp", task_id="dev-1", base_ref="main",
190
- )
191
- assert _submit_branch_confirm(state, "proceed") is not None
192
- assert state.branch_confirmed is True
193
- state.branch_confirmed = True
194
- _submit_branch_confirm(state, "edit")
195
- assert state.branch_confirmed is None # edit → 재확인 위해 리셋
196
- ```
197
-
198
- (전이 자체 — `branch_confirm → confirm` 순서 — 는 기존 confirm-도달 테스트를 갱신해 검증한다. Step 5 참조.)
199
-
200
- - [ ] **Step 3: 실패 확인**
201
-
202
- Run: `python3 -m pytest tests/test_okstra_ctl_wizard.py -k branch_confirm -q`
203
- Expected: FAIL (S_BRANCH_CONFIRM 미정의 / 전이 없음).
204
-
205
- - [ ] **Step 4: wizard 구현** (`scripts/okstra_ctl/wizard.py`)
206
-
207
- 1) 상수: `S_CONFIRM` 정의 부근에 `S_BRANCH_CONFIRM = "branch_confirm"`.
208
- 2) `WizardState` 에 필드 추가: `branch_confirmed: Optional[bool] = None`.
209
- 3) build/submit 핸들러 추가:
210
-
211
- ```python
212
- def _build_branch_confirm(state: WizardState) -> Prompt:
213
- from okstra_ctl.worktree import preview_worktree_decision
214
- decision = preview_worktree_decision(
215
- project_root=Path(state.project_root),
216
- project_id=state.project_id,
217
- task_group_segment=state.task_group,
218
- task_id_segment=state.task_id,
219
- work_category="", # okstra-run 경로는 --work-category 를 안 넘김
220
- base_ref=state.base_ref,
221
- )
222
- key = {
223
- "new": "new", "reused": "reuse",
224
- "skipped-in-worktree": "in_worktree", "skipped-not-git": "not_git",
225
- }[decision.status]
226
- t = _p(state.workspace_root, "branch_confirm")
227
- label = t["labels"][key].format(
228
- branch=decision.branch or "(none)",
229
- base_ref=decision.base_ref or "(HEAD)",
230
- path=decision.path,
231
- )
232
- # new 모드에서만 Edit 제공; 그 외에는 Proceed 만.
233
- opts = t["options"]
234
- options = [_opt("proceed", opts["proceed"])]
235
- if decision.status == "new":
236
- options.append(_opt("edit", opts["edit"]))
237
- return Prompt(step=S_BRANCH_CONFIRM, kind="pick", label=label,
238
- options=options, echo_template=t["echo_template"])
239
-
240
-
241
- def _submit_branch_confirm(state: WizardState, value: str) -> Optional[str]:
242
- if value == "edit":
243
- _reset_from(state, S_BASE_REF_PICK) # base-ref 재질문
244
- state.branch_confirmed = None
245
- return "branch-confirm: edit"
246
- if value != "proceed":
247
- raise WizardError(f"expected 'proceed' or 'edit', got: {value!r}")
248
- state.branch_confirmed = True
249
- return "branch-confirm: proceed"
250
- ```
251
-
252
- 4) STEPS 리스트에서 `Step(S_CONFIRM, ...)` **바로 앞**에 삽입:
253
-
254
- ```python
255
- Step(S_BRANCH_CONFIRM,
256
- applies=lambda s: _ready_for_confirm(s) and s.branch_confirmed is None,
257
- build=_build_branch_confirm, submit=_submit_branch_confirm,
258
- owns=("branch_confirmed",)),
259
- ```
260
-
261
- 5) `_ready_for_confirm` 가 confirm 전에 branch_confirm 을 강제하도록, `S_CONFIRM` 의 `applies` 를 `_ready_for_confirm(s) and s.branch_confirmed is True and s.confirmed is None` 로 변경.
262
-
263
- > 주의: `applies` 술어가 `_ready_for_confirm(s)` 를 공유하므로, STEPS 리스트에서 `S_BRANCH_CONFIRM` 이 `S_CONFIRM` 보다 **앞에** 와야 branch_confirm 이 먼저 매칭된다(첫 매칭 우선). `_reset_from` 가 `branch_confirmed` 도 리셋 범위에 포함하는지 확인 — base-ref edit 시 branch_confirmed 가 다시 None 이어야 재계산된다(위 submit 에서 명시적으로 None 처리했으니 OK).
264
-
265
- - [ ] **Step 5: 기존 confirm-도달 테스트 갱신 (필수 — 안 하면 회귀)**
266
-
267
- `tests/test_okstra_ctl_wizard.py` 에서 `next_prompt(state).step == S_CONFIRM` 를 단언하는 기존 테스트들(현재 약 line 478, 519, 664, 685, 899 — `grep -n "== S_CONFIRM" tests/test_okstra_ctl_wizard.py` 로 전수 확인)은 이제 confirm **직전에 `S_BRANCH_CONFIRM` 이 먼저 나온다.** 각 지점을 다음 패턴으로 갱신:
268
-
269
- ```python
270
- p = next_prompt(state)
271
- assert p.step == S_BRANCH_CONFIRM # 새 게이트가 먼저
272
- submit(state, "proceed")
273
- assert next_prompt(state).step == S_CONFIRM
274
- ```
275
-
276
- `S_BRANCH_CONFIRM` 을 테스트 상단 import 에 추가. 누락하면 해당 테스트들이 `S_BRANCH_CONFIRM != S_CONFIRM` 로 실패한다 — 전수 갱신할 것.
277
-
278
- - [ ] **Step 6: 통과 + 회귀**
279
-
280
- Run: `python3 -m pytest tests/test_okstra_ctl_wizard.py tests/test_wizard_prompts.py -q`
281
- Expected: 신규 + 갱신된 기존 전부 통과. 이어서 `python3 -m pytest tests/ -q` 전체 회귀 0.
282
-
283
- - [ ] **Step 7: 커밋**
284
-
285
- ```bash
286
- git add scripts/okstra_ctl/wizard.py prompts/wizard/prompts.ko.json tests/test_okstra_ctl_wizard.py tests/test_wizard_prompts.py
287
- git commit -m "feat(wizard): branch_confirm 단계 — 브랜치/worktree 결정 명시 확인"
288
- ```
289
-
290
- ---
291
-
292
- ## Task 3: okstra-run 스킬 안내 + 문서
293
-
294
- **Files:**
295
- - Modify: `skills/okstra-run/SKILL.md`
296
- - Modify: `docs/kr/architecture.md`, `CHANGES.md`
297
-
298
- - [ ] **Step 1: 스킬 1줄 안내** — `skills/okstra-run/SKILL.md` 의 pick 처리 설명 부근에, `branch_confirm` 도 일반 pick step 으로 그대로 렌더된다는 1줄 추가(별도 처리 불필요 명시). 기존 step 설명 형식을 따른다.
299
-
300
- - [ ] **Step 2: architecture.md** — requirements-discovery fan-out 절 부근(또는 wizard/worktree 설명부)에 추가:
301
-
302
- ```markdown
303
- #### branch_confirm (worktree 결정 확인)
304
-
305
- okstra-run wizard 는 최종 confirm 직전에 `branch_confirm` 단계로 "새 브랜치/worktree 생성 vs
306
- 현재 worktree 재사용"을 명시 확인한다. 결정은 `worktree.preview_worktree_decision()`(부수효과 없음)
307
- 으로 미리보고, 같은 헬퍼를 `provision_task_worktree` 가 실행에 쓰므로 미리보기와 실제가 일치한다.
308
- worktree 격리 동작 자체는 변경 없음(확인 게이트만).
309
- ```
310
-
311
- - [ ] **Step 3: CHANGES.md** — `## 2026-06-02` 섹션에 추가:
312
-
313
- ```markdown
314
- ### feat(wizard): okstra-run 에 브랜치/worktree 결정 확인 단계 추가
315
-
316
- - okstra-run wizard 가 최종 confirm 직전에 `branch_confirm` 단계를 띄워, 새 브랜치를 base-ref 에서
317
- 새 worktree 에 만드는지(또는 현재 worktree 재사용)를 명시 확인하게 함. auto mode 에서 base-ref 가
318
- 조용히 선택되어 의도치 않은 브랜치가 생기던 문제의 가시성을 높임. worktree 격리 동작은 변경 없음.
319
- - 사용자 영향: 다음 release + `npx -y okstra@latest install` 후 적용. okstra-run 진행 시 브랜치 생성
320
- 여부를 확인하는 단계가 한 번 더 추가된다(full-auto 가 아닌 경우 실제로 멈춰 확인).
321
- ```
322
-
323
- - [ ] **Step 4: 커밋**
324
-
325
- ```bash
326
- git add skills/okstra-run/SKILL.md docs/kr/architecture.md CHANGES.md
327
- git commit -m "docs(branch-confirm): 스킬 안내 + architecture + CHANGES"
328
- ```
329
-
330
- ---
331
-
332
- ## Task 4: 전체 회귀 + 빌드
333
-
334
- - [ ] **Step 1:** `python3 -m pytest tests/ -q` → 전부 통과(회귀 0).
335
- - [ ] **Step 2:** `npm run build` → 성공(runtime 동기화).
336
- - [ ] **Step 3:** `node bin/okstra --version` → 버전 출력.
337
- - [ ] **Step 4:** `git status --short` → clean 확인.