okstra 0.102.1 → 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 (162) hide show
  1. package/README.kr.md +5 -6
  2. package/README.md +5 -6
  3. package/docs/kr/architecture/storage-model.md +1 -1
  4. package/docs/kr/architecture.md +8 -12
  5. package/docs/kr/cli.md +6 -6
  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/cli-registry.mjs +1 -1
  36. package/src/commands/lifecycle/install.mjs +10 -20
  37. package/src/commands/lifecycle/uninstall.mjs +7 -10
  38. package/docs/superpowers/plans/2026-05-12-ticket-id-in-reports.md +0 -638
  39. package/docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md +0 -1568
  40. package/docs/superpowers/plans/2026-05-17-dual-format-final-report.md +0 -167
  41. package/docs/superpowers/plans/2026-05-20-final-report-language.md +0 -1501
  42. package/docs/superpowers/plans/2026-05-20-implementation-planning-multi-stage.md +0 -1267
  43. package/docs/superpowers/plans/2026-05-20-okstra-run-prompt-sot-b1.md +0 -1007
  44. package/docs/superpowers/plans/2026-05-20-wizard-messages-json-sot.md +0 -720
  45. package/docs/superpowers/plans/2026-05-20-wizard-prompt-json-sot-a1.md +0 -681
  46. package/docs/superpowers/plans/2026-05-21-improvement-discovery-task-type.md +0 -1691
  47. package/docs/superpowers/plans/2026-05-24-implementation-lead-context-slimming.md +0 -1700
  48. package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +0 -158
  49. package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +0 -860
  50. package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +0 -326
  51. package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +0 -337
  52. package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +0 -410
  53. package/docs/superpowers/plans/2026-06-02-requirements-discovery-fanout.md +0 -728
  54. package/docs/superpowers/plans/2026-06-04-adversarial-implementation-planning.md +0 -294
  55. package/docs/superpowers/plans/2026-06-04-adversarial-verification.md +0 -570
  56. package/docs/superpowers/plans/2026-06-04-coverage-critic.md +0 -516
  57. package/docs/superpowers/plans/2026-06-04-stage-cohesion-planner.md +0 -351
  58. package/docs/superpowers/plans/2026-06-04-stage-run-batching.md +0 -457
  59. package/docs/superpowers/plans/2026-06-05-acceptance-critic.md +0 -251
  60. package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +0 -323
  61. package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +0 -559
  62. package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +0 -993
  63. package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +0 -93
  64. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +0 -447
  65. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +0 -289
  66. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +0 -774
  67. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +0 -303
  68. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +0 -387
  69. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase2.md +0 -275
  70. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase3.md +0 -282
  71. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4a.md +0 -147
  72. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4b.md +0 -262
  73. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4c.md +0 -184
  74. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4d.md +0 -88
  75. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4e.md +0 -250
  76. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa.md +0 -409
  77. package/docs/superpowers/plans/2026-06-09-implementation-run-artifact-stage-isolation.md +0 -320
  78. package/docs/superpowers/plans/2026-06-10-concurrent-run-team-guard.md +0 -456
  79. package/docs/superpowers/plans/2026-06-10-git-reconcile-stale-sha-recovery.md +0 -1408
  80. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling-PROBE.md +0 -42
  81. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling.md +0 -337
  82. package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +0 -1029
  83. package/docs/superpowers/plans/2026-06-10-stage-group-handoff.md +0 -1572
  84. package/docs/superpowers/plans/2026-06-11-fix-cycle.md +0 -1290
  85. package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +0 -526
  86. package/docs/superpowers/plans/2026-06-12-html-plan-approval.md +0 -1000
  87. package/docs/superpowers/plans/2026-06-13-repo-risk-hardening.md +0 -493
  88. package/docs/superpowers/plans/2026-06-14-host-runtime-auto-execution.md +0 -1775
  89. package/docs/superpowers/plans/2026-06-15-coding-preflight-pack-dispatch-path.md +0 -504
  90. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-final-fixups.md +0 -342
  91. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-fixups.md +0 -258
  92. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-remaining-fixups.md +0 -387
  93. package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +0 -749
  94. package/docs/superpowers/plans/2026-06-15-worker-prompt-anchor-final-fixups.md +0 -828
  95. package/docs/superpowers/plans/2026-06-15-worker-prompt-header-error-contract.md +0 -490
  96. package/docs/superpowers/plans/2026-06-17-okstra-error-report.md +0 -724
  97. package/docs/superpowers/plans/2026-06-18-subagent-pane-reclaim.md +0 -483
  98. package/docs/superpowers/plans/2026-06-19-agent-operating-standard.md +0 -476
  99. package/docs/superpowers/plans/2026-06-19-okstra-inspect-recap-facet.md +0 -647
  100. package/docs/superpowers/plans/2026-06-20-error-feedback-loop.md +0 -1019
  101. package/docs/superpowers/plans/2026-06-20-run-index-row-normalization.md +0 -583
  102. package/docs/superpowers/plans/2026-06-20-stage-auto-integrate-teardown.md +0 -819
  103. package/docs/superpowers/plans/2026-06-21-okstra-container-local-user-test.md +0 -714
  104. package/docs/superpowers/plans/2026-06-21-release-handoff-local-checkout.md +0 -348
  105. package/docs/superpowers/plans/2026-06-23-implementation-stage-multiselect-chain.md +0 -630
  106. package/docs/superpowers/plans/2026-06-23-implementation-step-commit-granularity.md +0 -274
  107. package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +0 -409
  108. package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +0 -542
  109. package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +0 -568
  110. package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +0 -203
  111. package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +0 -525
  112. package/docs/superpowers/specs/2026-05-12-ticket-id-in-reports-design.md +0 -131
  113. package/docs/superpowers/specs/2026-05-15-implementation-plan-verification-design.md +0 -254
  114. package/docs/superpowers/specs/2026-05-20-final-report-language-design.md +0 -383
  115. package/docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md +0 -322
  116. package/docs/superpowers/specs/2026-05-20-okstra-run-prompt-sot-design.md +0 -299
  117. package/docs/superpowers/specs/2026-05-21-improvement-discovery-task-type-design.md +0 -335
  118. package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +0 -113
  119. package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +0 -173
  120. package/docs/superpowers/specs/2026-06-02-requirements-discovery-fanout-design.md +0 -154
  121. package/docs/superpowers/specs/2026-06-04-adversarial-implementation-planning-design.md +0 -90
  122. package/docs/superpowers/specs/2026-06-04-adversarial-verification-design.md +0 -176
  123. package/docs/superpowers/specs/2026-06-04-coverage-critic-design.md +0 -99
  124. package/docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md +0 -98
  125. package/docs/superpowers/specs/2026-06-05-acceptance-critic-design.md +0 -90
  126. package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +0 -87
  127. package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +0 -121
  128. package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +0 -126
  129. package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +0 -180
  130. package/docs/superpowers/specs/2026-06-06-vertical-slice-tdd-planning-design.md +0 -179
  131. package/docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md +0 -169
  132. package/docs/superpowers/specs/2026-06-09-executor-model-custom-id-cascade-design.md +0 -66
  133. package/docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md +0 -87
  134. package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +0 -168
  135. package/docs/superpowers/specs/2026-06-10-concurrent-run-team-guard-design.md +0 -107
  136. package/docs/superpowers/specs/2026-06-10-git-reconcile-stale-sha-recovery-design.md +0 -105
  137. package/docs/superpowers/specs/2026-06-10-lead-worker-completion-polling-design.md +0 -113
  138. package/docs/superpowers/specs/2026-06-10-stage-group-handoff-design.md +0 -156
  139. package/docs/superpowers/specs/2026-06-11-brief-entry-only-handoff-stage-entry-design.md +0 -158
  140. package/docs/superpowers/specs/2026-06-11-fix-cycle-design.md +0 -94
  141. package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +0 -89
  142. package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +0 -358
  143. package/docs/superpowers/specs/2026-06-12-html-plan-approval-design.md +0 -85
  144. package/docs/superpowers/specs/2026-06-12-stage-discipline-rule-design.md +0 -108
  145. package/docs/superpowers/specs/2026-06-13-forbidden-actions-ssot-design.md +0 -134
  146. package/docs/superpowers/specs/2026-06-13-neutral-tmux-lead-adapter-design.md +0 -284
  147. package/docs/superpowers/specs/2026-06-14-host-runtime-auto-execution-design.md +0 -404
  148. package/docs/superpowers/specs/2026-06-17-okstra-error-report-design.md +0 -123
  149. package/docs/superpowers/specs/2026-06-18-subagent-pane-reclaim-design.md +0 -150
  150. package/docs/superpowers/specs/2026-06-19-agent-operating-standard-design.md +0 -120
  151. package/docs/superpowers/specs/2026-06-19-okstra-inspect-recap-facet-design.md +0 -96
  152. package/docs/superpowers/specs/2026-06-20-error-feedback-loop-design.md +0 -171
  153. package/docs/superpowers/specs/2026-06-20-run-index-row-normalization-design.md +0 -112
  154. package/docs/superpowers/specs/2026-06-20-stage-auto-integrate-teardown-design.md +0 -145
  155. package/docs/superpowers/specs/2026-06-21-okstra-container-local-user-test-design.md +0 -125
  156. package/docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md +0 -113
  157. package/docs/superpowers/specs/2026-06-23-implementation-stage-multiselect-chain-design.md +0 -138
  158. package/docs/superpowers/specs/2026-06-23-implementation-step-commit-granularity-design.md +0 -120
  159. package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +0 -129
  160. package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +0 -185
  161. package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +0 -121
  162. package/docs/superpowers/specs/2026-06-24-okstra-container-build-rename-design.md +0 -110
@@ -1,180 +0,0 @@
1
- # stage별 worktree 격리 + 동시 병렬 실행 — 설계
2
-
3
- - 작성일: 2026-06-06
4
- - 범위: `implementation` phase에서 stage를 **별도 git worktree로 격리**해, 사용자가 수동으로 동시에 띄운 여러 `implementation` run이 안전하게 서로 다른 stage를 진행하도록 한다. `started-exclusion`(A2)을 같은 설계에 통합한다.
5
- - 비범위
6
- - **자동 fan-out 없음** — okstra가 ready stage들을 여러 프로세스로 자동 분기하지 않는다. 병렬 트리거는 사용자가 stage별 run을 각각 기동하는 **수동 동시**만 지원한다.
7
- - **okstra 자동 머지 없음** — stage 브랜치 합류는 사용자 수동 머지(또는 release-handoff 수집)다. (2026-06-10 개정: release-handoff stage-group 모드의 수집 머지는 예외 — [2026-06-10-stage-group-handoff-design.md](2026-06-10-stage-group-handoff-design.md)) (2026-06-20 갱신: whole-task 통합 경로에 한해 [2026-06-20-stage-auto-integrate-teardown-design.md](2026-06-20-stage-auto-integrate-teardown-design.md) 가 자동 머지+teardown 으로 전환·해소.)
8
- - `implementation` 외 phase(`requirements-discovery` / `error-analysis` / `implementation-planning` / `final-verification` / `release-handoff`)의 worktree 모델은 불변 — 기존 task-key worktree 1개 유지.
9
- - ADR↔gitignore(C1)는 별도 plan. 다국어/i18n.
10
- - 관계: [`2026-05-20-implementation-planning-multi-stage-design.md`](2026-05-20-implementation-planning-multi-stage-design.md)의 stage 개념·carry-in 모델 위에 선다. [`2026-06-04-stage-run-batching.md`](../plans/2026-06-04-stage-run-batching.md)가 known gap으로 남긴 **started-exclusion 미구현**을 본 설계가 해소한다. [`2026-06-04-stage-splitting-cost-aware-design.md`](2026-06-04-stage-splitting-cost-aware-design.md)의 "병렬=부수효과, run batch=비용 단위" 원칙과 양립한다(본 설계는 부수효과인 병렬을 **안전하게** 만들 뿐, 분할 기준을 바꾸지 않는다).
11
-
12
- ## 1. 동기
13
-
14
- `fontradar-v2-api:dev-9184`에서 사용자가 stage2/stage3를 두 `implementation` run으로 동시에 띄웠고, 두 run이 **같은 task-key worktree·브랜치를 공유**해 커밋이 한 브랜치에 인터리브됐다. 근본 원인 두 가지:
15
-
16
- 1. **worktree가 task-key 단위 1개**다. [`compute_worktree_path`](../../../scripts/okstra_ctl/worktree.py:489)·[`compute_branch_name`](../../../scripts/okstra_ctl/worktree.py:511)에 run-seq도 stage도 없고, 모든 phase가 같은 worktree를 재사용한다([worktree.py:5-9](../../../scripts/okstra_ctl/worktree.py:5)). 같은 task의 두 stage run은 같은 디렉토리에서 파일을 편집하고 같은 브랜치에 커밋한다.
17
- 2. **started-exclusion 미구현**이다. [`_resolve_effective_stages`](../../../scripts/okstra_ctl/run.py:264)가 `consumers.jsonl`의 `done`만 보고 `started`를 무시해, stage가 `started`(미완)인데 다른 run이 또 `auto`로 같은 ready-set을 잡는다(known gap: [stage-run-batching.md:13](../plans/2026-06-04-stage-run-batching.md), `tests/test_e2e_multi_stage_q1_q9.py::test_q7`가 현 동작을 박제).
18
-
19
- 사용자 욕구는 "진짜 동시 병렬"이다. 본 설계는 stage를 worktree로 격리하고 점유를 원자화해 이를 안전하게 만든다.
20
-
21
- ## 2. 핵심 원칙
22
-
23
- ### 2.1 격리 모델 — `implementation`만 stage worktree
24
-
25
- stage 개념은 `implementation`에만 존재한다. 따라서 stage worktree 격리도 `implementation` phase에서만 일어난다.
26
-
27
- - `requirements-discovery`~`implementation-planning`: 기존 task-key worktree 1개 그대로(분기 없는 단일 흐름).
28
- - `implementation`: 각 run이 자신이 맡은 stage(또는 ready batch)를 **전용 stage worktree**에서 실행한다.
29
-
30
- **비-git / nested-worktree degradation:** 주변 흐름의 [`provision_task_worktree`](../../../scripts/okstra_ctl/worktree.py)가 `project_root`가 git repo가 아니거나(`skipped-not-git`) 이미 다른 worktree 안인 경우(`skipped-in-worktree`) 일반 phase는 graceful degrade한다(task worktree 미발급, `EXECUTOR_WORKTREE_PATH=project_root`). `implementation` stage 격리도 같은 신호를 따라 degrade한다 — stage worktree 발급을 건너뛰고 ctx의 `EXECUTOR_WORKTREE_*`를 그대로 두며, `consumers.jsonl`에 선택된 stage의 `started` 행만 기록한다. (이 경로는 render-only 테스트·non-git 프로젝트 fallback용. 실제 stage 격리·동시 병렬은 git project에서만 작동.)
31
-
32
- ### 2.2 base 결정 — carry-in의 git-native 구현
33
-
34
- | stage 종류 | worktree base | 동시성 |
35
- |---|---|---|
36
- | **독립** (`depends-on (none)`) | **공통 base** = `implementation` 첫 진입 시점의 task-key worktree HEAD(=planning 종료 상태) | 서로 **동시 가능** |
37
- | **단일 의존** (`depends-on X`) | 선행 stage X의 **done commit**(그 stage 브랜치 위에 적층) | X done 이후 시작 |
38
- | **다중 의존** (`depends-on X,Y…`) | task-key worktree HEAD(candidate). 선행들의 `done.head_commit`이 **모두 candidate의 ancestor**일 때만(=사용자가 선행을 머지함) — §9 #1 | 선행 모두 done + 머지 이후 |
39
-
40
- - 공통 base는 **첫 stage 진입 시 한 번 결정·고정**한다(아래 §3.2). dev-9184에서 stage들이 `8a18f99`(다른 task 머지가 반영된 main)에서 출발한 그 지점이다.
41
- - **단일 의존** stage Y의 base는 선행 stage X의 done commit이다. X의 done은 이미 `consumers.jsonl`에 `head_commit`으로 기록된다(dev-9184 consumers의 `stage:1 done head_commit:b3971782…`가 그 증거). Y는 X 브랜치 위에 적층되므로 Y 머지 시 X도 따라온다.
42
- - **다중 의존** stage는 선행들이 서로 다른 stage 브랜치에 흩어져 있어 단일 base commit이 자명하지 않다. 옵션 A 자동 감지(§9 #1): task-key worktree HEAD를 candidate로 두고, 선행 stage들의 `done.head_commit`이 모두 candidate의 ancestor면(`git merge-base --is-ancestor`) 사용자가 선행을 머지한 것으로 보고 candidate를 base로 발급한다. 하나라도 ancestor가 아니면 `PrepareError`로 "선행 stage 브랜치를 머지 후 재시도" 안내.
43
- - 결론: **진짜 동시 실행은 독립 stage끼리만** 성립하고, dev-9184의 "의존 stage가 선행 변경 없는 base에서 시작" 문제가 구조적으로 사라진다.
44
-
45
- ### 2.3 점유 / 동시성 — registry flock 예약이 SSOT (A2 통합)
46
-
47
- - worktree **registry를 stage-key 단위로 확장**하고 flock으로 **원자적 예약**한다([worktree_registry](../../../scripts/okstra_ctl/worktree.py:47) 경유).
48
- - **ready 집합** = `depends-on`이 모두 `done` **AND** 자신이 `consumers.jsonl`에 `started`/`done` 행이 없음 **AND** registry에 active 예약 없음.
49
- - 두 동시 run이 같은 stage를 잡으려 하면 **flock 예약이 직렬화**한다 — 한쪽만 예약에 성공하고, 다른쪽은 다음 ready stage를 잡거나 "잡을 stage 없음"으로 정상 종료.
50
- - **이것이 점유의 SSOT**다. `consumers.jsonl`의 `started`는 기록·관찰용이고, 실제 동시성 backstop은 registry flock 예약이다. A2(started-exclusion)는 ready 집합 계산에 `started`/예약 제외를 더하는 것으로 충족된다.
51
- - **한 run = 한 stage** (단일 stage 실행). [`cost-aware-design.md §2.3`](2026-06-04-stage-splitting-cost-aware-design.md)의 "ready-set batch"는 stage가 한 worktree·한 branch에서 순차 실행된다는 가정 위에 섰지만, 본 설계가 stage마다 격리 worktree·격리 branch를 요구하므로 batch는 의미를 잃는다(같은 branch에 두 stage-key를 reserve하려 하면 P1 registry의 branch-uniqueness 불변식 충돌). `_resolve_effective_stages`는 backward compat로 batch 리스트를 반환하지만, implementation 통합 경로는 **첫 ready stage 하나만** 실행한다. 사용자가 여러 stage를 동시에 진행하려면 별도 run을 띄우면 되고(이게 본 설계의 동시 병렬), 순차로 진행하려면 stage가 done 되는 대로 다음 run을 띄우면 된다 — 어느 쪽이든 cost 측면 등가다.
52
-
53
- > **declaration ↔ enforcement** (okstra `CLAUDE.md` rule 3): 점유 규칙의 강제 지점은 **런타임 registry 예약**이다. `prepare_task_bundle`이 이미 active 예약된 stage-key를 또 잡으려 하면 `PrepareError`로 중단한다. 프로파일 문구(MUST)만으로 끝내지 않는다.
54
-
55
- ## 3. 데이터 모델
56
-
57
- ### 3.1 worktree 키 / 브랜치
58
-
59
- ```
60
- 경로: ~/.okstra/worktrees/<project>/<group>/<task-id>/stage-<N>/
61
- 브랜치: <work-category-prefix>-<task-id>-s<N>
62
- ```
63
-
64
- - [`compute_worktree_path`](../../../scripts/okstra_ctl/worktree.py:489)에 optional `stage_number` 추가. None이면 기존 task-key 경로(다른 phase 호환).
65
- - [`compute_branch_name`](../../../scripts/okstra_ctl/worktree.py:511)에 optional `stage_number` 추가. None이면 기존 `<prefix>-<task-id>`.
66
-
67
- ### 3.2 registry 엔트리 — task-key + stage-key 공존
68
-
69
- 기존 task-key 엔트리(다른 phase가 사용)는 유지하고, `implementation` stage마다 stage-key 엔트리를 추가한다. task-key 엔트리에 **공통 base 고정값**을 1회 기록한다.
70
-
71
- ```jsonc
72
- "tasks": {
73
- "<proj>/<group>/<task-id>": { // 기존 (다른 phase)
74
- "branch": "<prefix>-<task-id>",
75
- "implementationBaseCommit": "8a18f99…", // 신규: 첫 stage 진입 시 1회 고정
76
- ...
77
- },
78
- "<proj>/<group>/<task-id>#stage-2": { // 신규 (implementation stage)
79
- "branch": "<prefix>-<task-id>-s2",
80
- "worktree_path": ".../stage-2",
81
- "base_ref": "8a18f99…", // 독립: 공통 base
82
- "stage": 2, "status": "active"
83
- },
84
- "<proj>/<group>/<task-id>#stage-3": {
85
- "branch": "<prefix>-<task-id>-s3",
86
- "base_ref": "b3971782…", // 의존: 선행 stage done commit
87
- "stage": 3, "status": "active"
88
- }
89
- }
90
- ```
91
-
92
- - `implementationBaseCommit`는 첫 stage 예약 시 flock 안에서 한 번 써진다. 동시 첫 진입이라도 직렬화되어 둘째 run은 기록된 값을 읽는다(race 없음).
93
-
94
- ### 3.3 ready 집합 계산 (A2)
95
-
96
- `_resolve_effective_stages`의 ready 판정을 확장한다(`requested == "auto"` 경로):
97
-
98
- ```
99
- ready = [s for s in stages
100
- if s.number not in done_stages
101
- and s.number not in started_stages # ← A2 신규
102
- and s.number not in reserved_stages # ← registry 예약 신규
103
- and all(d in done_stages for d in s.depends_on)]
104
- ```
105
-
106
- `--stage N` 명시 경로는 단일 stage를 직접 예약 시도하고, 이미 예약/done이면 `PrepareError`.
107
-
108
- ## 4. 흐름
109
-
110
- ```
111
- implementation-planning done (task-key worktree HEAD = 공통 base 후보)
112
-
113
- 사용자가 동시에 두 run 기동: okstra-run --stage 2 │ okstra-run --stage 3
114
- ▼ ▼
115
- prepare(stage 2) prepare(stage 3)
116
- flock: flock:
117
- - implementationBaseCommit 고정(1회) - (이미 고정됨, 읽기)
118
- - ready/예약 확인 → stage-2 예약 - ready/예약 확인 → stage-3 예약
119
- - base=공통(독립) - base=공통(독립; depends-on 동일 Stage1만)
120
- - worktree add stage-2 @ base - worktree add stage-3 @ base
121
- ▼ ▼
122
- executor(stage-2) → commit → consumers executor(stage-3) → commit → consumers
123
- stage-2 done + carry/stage-2.json stage-3 done + carry/stage-3.json
124
- ▼ ▼
125
- └──────── 사용자 수동 머지(의존성 순) ────────┘
126
- release-handoff가 stage PR 목록 수집
127
- ```
128
-
129
- 의존 stage(예: Stage 4 `depends-on 2,3`)는 2·3가 done될 때까지 ready 아님 → 자동으로 직렬.
130
-
131
- ## 5. 변경 대상 파일 (seed)
132
-
133
- | 파일 | 변경 |
134
- |---|---|
135
- | [`worktree.py`](../../../scripts/okstra_ctl/worktree.py:489) | `compute_worktree_path`/`compute_branch_name`에 optional `stage_number`; `provision_task_worktree`에 stage 인지 + base 계산(독립=공통 `implementationBaseCommit`, 의존=선행 done commit) |
136
- | [`worktree_registry.py`](../../../scripts/okstra_ctl/worktree.py:47) | stage-key(`<task-key>#stage-<N>`) 예약/lookup; `implementationBaseCommit` 1회 고정(flock 내) |
137
- | [`run.py`](../../../scripts/okstra_ctl/run.py:264) | `_resolve_effective_stages`에 `started`/예약 제외(A2); `_reserve_implementation_stages`([run.py:890](../../../scripts/okstra_ctl/run.py:890))를 stage worktree 발급에 연결; `--stage N` 중복 예약 시 `PrepareError` |
138
- | [`_implementation-executor.md`](../../../prompts/profiles/_implementation-executor.md:30) | "owns a ready-set batch"를 stage worktree 컨텍스트로 — executor가 자신의 stage worktree에서만 작업, 다른 stage worktree 접근 금지 |
139
- | [`okstra.sh`](../../../scripts/okstra.sh) · [`cli.sh`](../../../scripts/lib/okstra/cli.sh) | `--stage` 패스스루(B2) — 수동 동시 병렬의 CLI 진입점 |
140
- | [`release-handoff.md`](../../../prompts/profiles/release-handoff.md) | stage 브랜치(`-s<N>`) PR 목록을 `consumers.jsonl`에서 수집 |
141
- | `validators/` (`validate-run.py` 인접) | prepare 시 stage-key 중복 예약 거부(런타임 강제 지점 명시) |
142
-
143
- seed 규칙(`feedback_okstra_fixes_target_end_users`): `runtime/`·개인 `.claude/`가 아니라 위 source 파일에만 가한다.
144
-
145
- ## 6. teardown / 정리
146
-
147
- 모든 stage done + 머지 후 stage worktree들을 정리한다. 기존 수동 절차(`git worktree remove <path>` → `git branch -D <branch>` → registry 키 삭제)를 **stage-key N개로 확장**한다. 자동 teardown은 본 설계 비범위(사용자 수동 또는 후속 spec).
148
-
149
- ## 7. 호환성
150
-
151
- okstra는 pre-1.0(`feedback_pre_v1_no_compat`). 기존 단일-worktree `implementation` 흐름은 **stage worktree 흐름으로 대체**된다 — N=1(단일 stage) plan도 `stage-1` worktree를 발급받는다. compat shim 없음. 다른 phase는 영향 없음.
152
-
153
- ## 8. 검증 시나리오 (수동 QA)
154
-
155
- | # | 시나리오 | 기대 |
156
- |---|----------|------|
157
- | W1 | 1-stage plan `implementation` | `stage-1` worktree 발급, PR 1개 |
158
- | W2 | 독립 stage 2·3을 두 run 동시 `--stage 2` / `--stage 3` | 각자 stage worktree·브랜치, 공통 base, 충돌 없음, consumers 2줄 |
159
- | W3 | W2를 둘 다 `auto`로 동시 | flock 직렬화 → 한 run이 2, 다른 run이 3 (중복 점유 없음) |
160
- | W4 | 다중 의존 stage 4(`depends-on 2,3`)를 2·3 done 전에 `--stage 4` | ready 아님 → `PrepareError`(선행 done 대기) |
161
- | W5 | 단일 의존 stage(`depends-on 2`)를 2 done 후 실행 | base = stage2 done commit, 2 브랜치 위 적층, carry-in 주입 |
162
- | W6 | 다중 의존 stage 4를 2·3 done + 통합 후 실행 | base = §9 규칙(통합 commit), carry-in 주입 |
163
- | W7 | 이미 active 예약된 stage를 또 `--stage N` | `PrepareError`(중복 예약 거부) — 런타임 강제 확인 |
164
- | W8 | `implementation` 외 phase | 기존 task-key worktree 그대로(stage 분기 없음) |
165
-
166
- ## 9. 미해결 / writing-plans 전 확정
167
-
168
- 1. **다중 의존 stage base 전략** (§2.2):
169
- - **(옵션 A, 잠정)** 선행 stage들이 사용자 수동 머지로 한 라인에 통합된 뒤, 그 통합 commit을 base로. → 다중 의존 stage는 선행 머지 대기(자연 직렬화). 단순하고 §5의 "수동 머지" 결정과 일관. 단점: 사용자가 머지를 늦추면 다중 의존 stage가 블록됨.
170
- - **(옵션 B)** okstra가 선행 done commit들을 임시 octopus 머지한 base를 생성. → 사용자 머지 전에도 시작 가능하나, 머지 충돌 해소 책임이 okstra로 들어옴(자동 머지 비범위와 충돌).
171
- - **확정: 옵션 A** (2026-06-06 사용자 승인). 다중 의존 stage는 선행 stage들이 사용자 머지로 통합된 뒤 ready가 된다. 옵션 B는 후속 spec 후보로 보류.
172
- - **자동 감지 구현** (2026-06-06 P5): 다중 의존 stage(`len(depends_on) >= 2`)의 base 결정은:
173
- 1. candidate = task-key worktree HEAD(`git rev-parse HEAD` in `project_root` — 모든 phase 공유 worktree이며 사용자가 선행 stage 머지를 반영하는 곳).
174
- 2. 각 선행 stage의 `done.head_commit`(consumers.jsonl)을 수집. 하나라도 done 행/head_commit이 없으면 `PrepareError`(선행 미완).
175
- 3. 각 선행 done commit이 candidate의 **ancestor**인지 `git merge-base --is-ancestor <done> <candidate>`(returncode 0)로 검증.
176
- - 모두 ancestor → 사용자가 선행을 머지함 → candidate를 base로 반환.
177
- - 하나라도 아니면 → `PrepareError`로 "선행 stage 브랜치(`-s<X>`/`-s<Y>`)를 task worktree에 머지(또는 main 머지 후 worktree 갱신) 후 재시도" 안내.
178
- - 사용자 워크플로우: stage X·Y가 done → 각 stage 브랜치를 task-key worktree(또는 main)에 머지 → task worktree HEAD가 X·Y done을 ancestor로 가짐 → 다중 의존 stage가 그 위에서 자동으로 base를 잡고 시작.
179
- - 옵션 B(okstra octopus 임시 머지)는 여전히 보류.
180
- 2. **stage worktree 자동 teardown** — 현재 수동(§6). 후속 spec 후보. (2026-06-20 갱신: whole-task 통합 경로에 한해 [2026-06-20-stage-auto-integrate-teardown-design.md](2026-06-20-stage-auto-integrate-teardown-design.md) 가 자동 머지+teardown 으로 전환·해소.)
@@ -1,179 +0,0 @@
1
- # implementation-planning 수직 슬라이스 + RED→GREEN 강제 설계
2
-
3
- - 작성일: 2026-06-06
4
- - 상태: Proposed (사용자 검토 대기)
5
- - 대상 phase: `implementation-planning` (okstra-run Phase 5 계획 산출)
6
-
7
- ## 1. 배경 / 문제
8
-
9
- PR 사이즈가 비대해지는 것을 막기 위해, implementation-planning 이 작업 계획을
10
- 세울 때 **PR 작업 단위를 수직 슬라이스(기능 단위 end-to-end)로 끊고**, 각 슬라이스를
11
- **TDD RED→GREEN** 흐름으로 구성하도록 강제하고 싶다.
12
-
13
- 현재 상태(이미 존재하는 인프라):
14
-
15
- - 계획은 작업을 **Stage** 로 분할하며 Stage 당 effective step ≤ 6 캡이 걸려 있다.
16
- ([implementation-planning.md:69](../../../prompts/profiles/implementation-planning.md:69))
17
- - implementation 실행 시 **run 당 PR 1개**(`One-PR-per-run`)가 원칙이라
18
- Stage = PR 단위 구조가 이미 성립한다.
19
- ([_implementation-executor.md:44](../../../prompts/profiles/_implementation-executor.md:44))
20
- - executor 의 **Mandatory TDD loop** 는 이미 강제: 실패 테스트 → `test(...)` 커밋 →
21
- 최소 구현 → `feat|fix(...)` 커밋 → refactor.
22
- ([_implementation-executor.md:25](../../../prompts/profiles/_implementation-executor.md:25))
23
-
24
- 격차(gap) 세 가지:
25
-
26
- 1. Stage 분할 앵커가 **"함께 바뀌는 파일 근접도(cohesion / file proximity)"** 로
27
- 표현돼 있어 "독립 배포 가능한 사용자 가치 증분"이라는 수직 슬라이스 멘탈모델과
28
- 말이 다르다. ([implementation-planning.md:72](../../../prompts/profiles/implementation-planning.md:72))
29
- 2. 각 Stage 가 "이 Stage 가 전달하는 사용자 관찰 가능한 증분"을 선언하지 않아,
30
- 레이어 가로 절단(horizontal slice)인지 수직 슬라이스인지 구분이 불가능하다.
31
- 3. 계획 단계의 TDD 는 `prefer TDD ordering` 수준의 **권고**일 뿐 강제가 아니다.
32
- ([implementation-planning.md:69](../../../prompts/profiles/implementation-planning.md:69))
33
- 실행(executor)에서만 강제되어 계획-실행 간 정합이 비대칭이다.
34
-
35
- ## 2. 목표 / 비목표
36
-
37
- ### 목표
38
- - Stage 분할 1차 앵커를 **수직 슬라이스(vertical slice)** 로 재정의한다.
39
- - 각 Stage 가 `Slice value:` / `Acceptance:` 를 선언하게 한다.
40
- - 계획 단계 `Stepwise Execution Order` 를 **RED→GREEN mandatory** 로 격상한다.
41
- - 위 규칙을 **검증기(validator)로 강제**한다 — 선언과 강제를 일치시킨다(Rule #3).
42
-
43
- ### 비목표
44
- - Stage Map 계약 골격(`## 5.5 Stage Map` + `## 5.5.<i> Stage <i>:` 4-subsection)
45
- 전면 개편은 하지 않는다(접근 A 기각). 골격은 보존하고 문구 + 검증만 추가한다.
46
- - 리포트 템플릿의 평면 `### 5.5.4 Stepwise Execution Order` 렌더링 경로
47
- ([final-report.template.md:178](../../../templates/reports/final-report.template.md:178))는
48
- 이번 변경 대상이 아니다(멀티-Stage 본문은 report-writer 가 프로파일 가이던스로
49
- 직접 작성하며, `tests/fixtures/plans/valid_one_stage.md` 가 실제 산출 형태다).
50
- - executor 의 TDD loop 동작 변경은 하지 않는다 — 이미 강제되어 있고, 계획의
51
- RED/GREEN step 이 executor 의 `test(...)` / `feat|fix(...)` 커밋에 1:1 매핑된다.
52
- - `One-PR-per-run` / parallel-safety(S9) 모델 변경 없음.
53
-
54
- ## 3. 채택 접근 — C (외과적 변경)
55
-
56
- `Stage = PR = run` 모델을 그대로 두고, **프로파일 문구 3곳 + 검증기 S10 1개**만
57
- 바꾼다. 기존 아키텍처·검증기 골격을 보존하면서 두 의도(수직 슬라이스 + 명시적
58
- RED→GREEN)를 채운다.
59
-
60
- 접근 A(검증기 전면 개편)와 B(응집도 위 추가 차원)는 변경 규모/이중화 때문에 기각.
61
-
62
- ## 4. 상세 설계
63
-
64
- ### 4.1 Delta 1 — 분할 앵커 재정의
65
-
66
- [implementation-planning.md:72](../../../prompts/profiles/implementation-planning.md:72)
67
- "Cohesion-first partition rule" → **"Vertical-slice-first partition rule"**:
68
-
69
- - 1차 앵커 = **사용자 관찰 가능한 증분 1개를 end-to-end 로 전달하는 얇은 수직
70
- 슬라이스**. 한 Stage 는 레이어를 가로지르더라도 하나의 기능 증분을 완결한다.
71
- - 파일 응집도("shared file/module proximity")는 폐기하지 않고 **슬라이스 내부에서
72
- step 을 묶는 2차 기준**으로 강등한다.
73
- - **레이어 가로 절단(horizontal layering) 금지** 문구를 명시한다 — 예: "DB 레이어만
74
- 한 Stage, 서비스 레이어만 다음 Stage" 식 분할은 거부.
75
- - 기존 분할 트리거는 유지하되 (c)만 재문구화:
76
- - (a) 실제 `depends-on` 데이터/계약 의존성이 있을 때
77
- - (b) effective step 이 6을 초과할 때
78
- - (c) **별개의 수직 슬라이스(서로 다른 사용자 가치 증분)일 때**
79
- - "Maximising parallel stages is NOT a reason to split" 원칙은 유지.
80
-
81
- ### 4.2 Delta 2 — Stage 당 슬라이스 선언
82
-
83
- [implementation-planning.md:67-74](../../../prompts/profiles/implementation-planning.md:67)
84
- 각 `## 5.5.<i> Stage <i>:` 섹션에 **필수 두 줄**을 추가한다(Carry-In 직전, 헤딩 바로 아래):
85
-
86
- ```
87
- Slice value: <이 Stage 가 전달하는 사용자 관찰 가능한 증분 한 줄>
88
- Acceptance: <관찰 가능한 통과 조건 또는 정확한 커맨드>
89
- ```
90
-
91
- - `Slice value` 는 "무엇이 동작하게 되는가"를 사용자/소비자 관점으로 기술한다.
92
- 레이어 이름("repository 추가")이 아니라 증분("X 를 조회하면 Y 가 반환된다").
93
- - `Acceptance` 는 그 슬라이스가 끝났음을 증명하는 관찰 가능 신호 — 보통 4.3 의
94
- RED step 이 PASS 로 전환되는 테스트 커맨드와 동일하다.
95
-
96
- ### 4.3 Delta 3 — 계획 단계 RED→GREEN mandatory
97
-
98
- [implementation-planning.md:69](../../../prompts/profiles/implementation-planning.md:69)
99
- `### Stepwise Execution Order` 요구를 `prefer TDD ordering` → **MUST** 로 격상:
100
-
101
- - 각 비면제 Stage 의 **첫 effective step 의 `action` 셀은 리터럴 `RED:` 로 시작**하고,
102
- 그 슬라이스의 acceptance 를 포착하는 **실패 테스트**를 기술한다(`expected` = FAIL).
103
- - 이후 구현 step 중 최소 하나의 `action` 셀은 리터럴 `GREEN:` 로 시작하고 테스트를
104
- 통과시키는 최소 구현을 기술한다(`expected` = PASS).
105
- - refactor step 은 선택(있으면 `REFACTOR:` 접두).
106
- - **면제**: doc-only / config-only / 순수 rename 등 런타임 관찰 동작이 없는 Stage 는
107
- 섹션에 한 줄 `TDD exemption: <사유>` 를 두고 RED/GREEN 을 생략할 수 있다(executor
108
- 의 동일 면제 규칙 [_implementation-executor.md:27](../../../prompts/profiles/_implementation-executor.md:27)과 정합).
109
-
110
- 리터럴 토큰(`RED:` / `GREEN:` / `REFACTOR:` / `TDD exemption:`)을 쓰는 이유: 검증기가
111
- "실패 테스트인지 단어로 추론"하는 brittle 방식 대신 substring 으로 확정 검사하기
112
- 위함 — 기존 §"Section heading contract"의 리터럴-substring 철학과 일관
113
- ([implementation-planning.md:54](../../../prompts/profiles/implementation-planning.md:54)).
114
-
115
- ### 4.4 Delta 4 — 검증기 S10 (강제)
116
-
117
- [validators/validate-implementation-plan-stages.py](../../../validators/validate-implementation-plan-stages.py)
118
- 에 `_check_slice_tdd()` 를 추가하고 `collect_validation_errors()` 에 연결한다.
119
- 각 Stage 섹션(`_slice_stage_section` 으로 추출)마다:
120
-
121
- - **S10a**: `Slice value:` 라인이 있고 콜론 뒤 값이 비어있지 않음.
122
- - **S10b**: `Acceptance:` 라인이 있고 콜론 뒤 값이 비어있지 않음.
123
- - **S10c (TDD ordering)**: 다음 둘 중 하나를 만족.
124
- - (i) `Stepwise Execution Order` 의 **첫 effective row 의 action 셀이 `RED:` 로
125
- 시작** AND 같은 표의 어떤 row 의 action 셀이 `GREEN:` 로 시작, **또는**
126
- - (ii) 섹션에 `TDD exemption:` 라인이 존재.
127
-
128
- 구현 메모:
129
- - 첫 effective row 의 action 셀 추출은 기존 `_count_effective_steps` 의 셀 파싱 로직
130
- (header/divider skip, `strip("|").split("|")`)을 재사용해 새 헬퍼로 분리한다 — 표 컬럼
131
- 순서는 `step | action | files | command | expected` 이므로 action 은 index 1.
132
- - S10 은 S1(Stage Map 부재) 단락 시 실행되지 않으며, stage 파싱 성공 시
133
- `_check_each_stage_section` 과 같은 레벨에서 호출한다.
134
- - 에러 코드 `S10`, stage 번호 포함, 메시지는 누락 항목 명시.
135
-
136
- ### 4.5 정합성 — executor / convergence
137
-
138
- - executor 의 per-step TDD loop 은 계획의 RED/GREEN step 을 그대로 실행하면 되므로
139
- [_implementation-executor.md](../../../prompts/profiles/_implementation-executor.md) 본문 변경 없음.
140
- 단, 계획이 이미 RED/GREEN 을 명시하므로 executor 가 "계획의 RED step = 첫 실패
141
- 테스트"로 읽도록 한 줄 정합 코멘트만 선택적으로 추가 가능(필수 아님).
142
- - §5.5.9 Plan Body Verification / self-review pass 의 "Stage Map self-check"
143
- ([implementation-planning.md:102](../../../prompts/profiles/implementation-planning.md:102))에
144
- Slice value/Acceptance/RED-GREEN 확인 항목을 한 줄 추가해 사람-검토와 기계-검토를
145
- 이중화한다.
146
-
147
- ## 5. 영향 / 마이그레이션
148
-
149
- ### 5.1 테스트 픽스처 (BLOCKING)
150
- S10 추가로 기존 valid 픽스처가 새로 실패하므로 **반드시 갱신**한다:
151
- - [tests/fixtures/plans/valid_one_stage.md](../../../tests/fixtures/plans/valid_one_stage.md):
152
- `Slice value:` / `Acceptance:` 두 줄 추가, action 셀을 `RED: ...` / `GREEN: ...` 로 수정.
153
- - [tests/fixtures/plans/valid_three_stage_parallel.md](../../../tests/fixtures/plans/valid_three_stage_parallel.md):
154
- 동일 갱신(3 stage 모두).
155
- - 신규 invalid 픽스처 추가: `invalid_missing_slice_value.md`, `invalid_missing_red_step.md`.
156
-
157
- ### 5.2 테스트 코드
158
- - [tests/test_validate_implementation_plan_stages.py](../../../tests/test_validate_implementation_plan_stages.py)
159
- 에 S10a/S10b/S10c 통과·실패 케이스, `TDD exemption` 면제 통과 케이스 추가.
160
- - `tests/test_render_final_report.py` / 골든 리포트가 stage 본문을 포함한다면 동반 갱신.
161
-
162
- ### 5.3 빌드 / 동기화
163
- - 소스(`prompts/`, `validators/`) 수정 후 `npm run build` 로 `runtime/` 동기화.
164
- - `runtime/` 직접 수정 금지.
165
-
166
- ### 5.4 사전 확인 (가정 금지)
167
- - 구현 착수 시 `report-writer` 가 stage 본문을 실제로 어디서 emit 하는지 1회 실측
168
- 확인한다(프로파일 가이던스 vs 템플릿). `valid_one_stage.md` 픽스처가 멀티-Stage
169
- 구조를 보이므로 프로파일 가이던스 경로가 유력하나, 코드로 확인 후 진행한다.
170
-
171
- ## 6. 수용 기준 (이 설계의 done 조건)
172
-
173
- 1. 프로파일 분할 앵커가 vertical-slice-first 로 재정의되고 horizontal 금지 명시.
174
- 2. 각 Stage 가 `Slice value:` / `Acceptance:` 를 선언하도록 프로파일이 요구.
175
- 3. 계획 `Stepwise Execution Order` 가 `RED:` 첫 step + `GREEN:` 을 MUST 로 요구.
176
- 4. `validate-implementation-plan-stages.py` S10 이 위 1–3 의 산출물을 강제하고
177
- `python3 -m pytest tests/test_validate_implementation_plan_stages.py` 가 통과.
178
- 5. 기존 valid 픽스처 갱신으로 전체 stages 검증 스위트 green.
179
- 6. `npm run build` 후 `runtime/` 의 프로파일·검증기가 소스와 일치.
@@ -1,169 +0,0 @@
1
- # Stage 요구사항-부합 검증 (Tier 3 Conformance QA) 설계
2
-
3
- - 상태: 설계 승인됨 (구현 전)
4
- - 날짜: 2026-06-07
5
- - 관련 코드: [`scripts/okstra_ctl/qa_commands.py`](../../../scripts/okstra_ctl/qa_commands.py), [`prompts/profiles/_implementation-verifier.md`](../../../prompts/profiles/_implementation-verifier.md), [`prompts/profiles/implementation-planning.md`](../../../prompts/profiles/implementation-planning.md), [`prompts/profiles/final-verification.md`](../../../prompts/profiles/final-verification.md), [`scripts/okstra_ctl/run.py`](../../../scripts/okstra_ctl/run.py), [`validators/validate-run.py`](../../../validators/validate-run.py)
6
-
7
- ## 1. 배경과 문제
8
-
9
- implementation run 은 정적 분석 + 모킹 유닛테스트 게이트를 통과해도, **실DB·프로젝트 엔드포인트·외부 API 같은 통합 표면**은 검증하지 못한 채 "정적 분석상 OK, 미검증(실행 안 함)"으로 남는 구조적 공백이 있다.
10
-
11
- 근거 — DEV-9184 (`fontradar-v2-api`) Stage 3:
12
-
13
- - 1930 유닛테스트 green + tsc clean 으로 정적/모킹 게이트는 통과했으나 **종합 verdict 는 FAIL**.
14
- - 원인 ①: DB real-execution 게이트(G-2/V-5) — diff 가 DB/SQL 을 건드리는데 `db-test` 미선언 → `정적 분석상 OK, 미검증(실행 안 함)`.
15
- - 원인 ②: 모킹이 못 잡은 런타임 버그(Q-1, full-consensus). 실DB·실행 없이는 표면화 불가.
16
- - FU-002 의 처방이 정확히 이 기능의 형태였다: replica DB 에서 `SELECT COUNT(*) FROM LicenseVersionMinPrices WHERE idLicenseVersion=<DRAFT> > 0`, `GET /price/list` pre/post read↔publish parity 검증.
17
-
18
- 핵심 통찰: 이 공백은 "검증 명령 부재"가 *조용히* PASS 로 흐른 데서 비롯됐다(silent mock-green). 따라서 해법은 (a) stage 별 통합 검증 스크립트를 1급 산출물로 만들고, (b) 그 스크립트가 없거나 못 돌 때 **조용히 통과시키지 않는 것**이다.
19
-
20
- ## 2. 목표 / 비목표
21
-
22
- 목표:
23
-
24
- - implementation 의 각 stage(및 final-verification)에 대해, **상위 요구사항(task brief → requirements-discovery / error-analysis / improvement-discovery → plan stage Acceptance)에 부합하는지**를 검증하는 실행 스크립트를 산출·실행·판정한다.
25
- - 유닛/모킹이 닿지 못하는 표면(실DB·엔드포인트·외부 API)을 커버한다.
26
- - 검증 미실행을 **silent pass 가 아니라 BLOCKING** 으로 만든다. 단, **명시적으로 확인된 우회 경로**를 감사 흔적과 함께 제공한다.
27
-
28
- 비목표:
29
-
30
- - 유닛테스트 자체의 대체(executor 의 RED→GREEN TDD 루프는 그대로 유지). 이 기능은 그 위의 **통합/부합 게이트**다.
31
- - 사용자 repo 의 정식 테스트 스위트를 okstra 가 소유/관리하는 것(Approach C 기각). conformance 스크립트는 okstra artifact 로 `.okstra/` 하위에 둔다.
32
- - 정적·프로젝트 전역 `qaCommands` 베이스라인을 per-stage 데이터로 오염시키는 것(Approach B 기각).
33
-
34
- ## 3. 데이터 모델 (무엇을 · 어디에)
35
-
36
- artifact-home 규칙에 따라 모든 산출물은 `.okstra/` 하위에 둔다.
37
-
38
- - 스크립트: `.okstra/tasks/<task-key>/runs/implementation/qa/stage-<N>.<ext>` (stage 당 1개 이상).
39
- - conformance 매니페스트: `.okstra/tasks/<task-key>/runs/implementation/qa/conformance-manifest.json`
40
-
41
- ```json
42
- {
43
- "entries": [
44
- {
45
- "stageKey": "<task-id>-stage-<N>",
46
- "script": "qa/stage-3.ts",
47
- "runCommand": "npx ts-node .okstra/.../qa/stage-3.ts",
48
- "requirementIds": ["R-001", "GAP-1"],
49
- "requires": ["db", "http"],
50
- "passContract": "exit 0 = PASS, non-zero = FAIL",
51
- "exemption": null,
52
- "waiver": null
53
- }
54
- ]
55
- }
56
- ```
57
-
58
- - 요구사항 추적성: 각 entry 의 `requirementIds` 는 plan §5.5.8 Requirement Coverage 의 `R-NNN`, 그리고 brief / requirements-discovery / error-analysis / improvement-discovery 에서 이월된 ID 를 가리킨다. "이 스크립트가 어떤 요구사항의 부합을 증명하는가"를 명시한다.
59
- - `requires`: capability 태그 화이트리스트 `["db", "io", "http", "external"]`. diff 가 건드린 표면과 대조해 게이트 강도를 결정한다.
60
-
61
- ## 4. 표준 스크립트 계약 (`main → pass/fail`)
62
-
63
- - 진입점 `main()` 실행 → **exit code 0 = PASS / 비0 = FAIL**.
64
- - stdout 마지막 줄에 파싱용 마커: `QA-RESULT: PASS|FAIL`, 그리고 요구사항별 줄 `REQ <id>: PASS|FAIL: <근거>`.
65
- - 언어는 프로젝트 따라감(`qaCommands` 의 `language` 와 정합). 예: DEV-9184 는 TS 스크립트가 `GET /price/list` 호출 + replica DB 에 `SELECT COUNT(*) … WHERE idLicenseVersion=<DRAFT>` 실행 후 read↔publish parity 를 판정.
66
- - 스크립트는 기본적으로 black-box(HTTP/SQL 등 외부에서 관측)로 작성한다. 프로젝트 코드 import 가 필요한 경우는 예외로, 프로젝트 모듈 해석 경로에 맞춘 배치를 허용한다(엣지).
67
-
68
- ## 5. 생성 시점 · 주체
69
-
70
- - implementation-planning 이 stage 별로:
71
- 1. plan 에 `### 5.5.x Stage Conformance Tests` 블록을 산출한다. 블록은 스크립트 본문 + 헤더(`stageKey` / `requirementIds` / `requires`)를 담는다.
72
- 2. 그 스크립트를 `.okstra/.../qa/` 에 파일로 기록하고 `conformance-manifest.json` 을 생성한다.
73
- - 근거: `Acceptance:` 라인이 이미 plan 의 1급 요소이므로, conformance 스크립트는 "Acceptance 를 실행 가능하게 만든 것"으로서 plan deliverable 의 자연스러운 확장이다(planning=설계 원칙과 정합 — 테스트 코드는 구현이 아니라 수용 기준의 실행형).
74
-
75
- ## 6. 실행 · 판정 (verifier Tier 3 + final-verification)
76
-
77
- - verifier 의 명령 lookup 에 **Tier 3** 추가:
78
- - Tier 1 = plan validation (pre/mid/post),
79
- - Tier 2 = `project.json.qaCommands`,
80
- - **Tier 3 = conformance 스크립트** (해당 stage 의 매니페스트 entry).
81
- - verifier 는 stage 의 스크립트를 worktree / replica env 에서 실행하고, exact runCommand + exit code + `QA-RESULT` 파싱 결과를 Read-only command log 와 증거에 기록한다.
82
- - final-verification: 전 stage 의 스크립트 합집합을 통합 state 에 대해 실행한다.
83
- - **핵심 불변식 — 미실행 = BLOCKING**: diff 가 `requires`(db/io/http/external) 표면을 건드리는데 스크립트 부재 / env 부재 / 미실행이면, DEV-9184 처럼 passive note 가 아니라 **verdict FAIL** 로 격상한다(silent mock-green 금지).
84
-
85
- ## 7. 명시적 우회 경로
86
-
87
- "건너뛰려면 둘 중 하나가 반드시 있어야 하고, 둘 다 리포트에 감사 흔적으로 남는다." silent skip 은 불가.
88
-
89
- ### 7.1 Planning 선언형 면제
90
-
91
- - stage 에 `Conformance exemption: <사유>` 라인을 선언(기존 `TDD exemption:` 패턴과 동형).
92
- - 용도: 테스트가 정말 불필요한 stage(doc / config / pure-rename, 또는 db/io/external 을 안 건드리고 유닛으로 충분).
93
- - 안전장치: diff 가 실제로 db/io/external 을 건드리면 선언형 면제는 **거부(BLOCKING)** — 면제 사유와 실제 surface 가 일치할 때만 허용. (면제로 실DB 변경을 숨기는 것 방지)
94
- - 기록: 매니페스트 entry 의 `exemption: { reason, declaredAt }`.
95
-
96
- ### 7.2 Run-time 사용자 확인형 우회 (waiver)
97
-
98
- - conformance 가 필요한데(surface 건드림) 사용자가 의도적으로 건너뛰는 경우.
99
- - **사용자 명시 확인 필수**(lead / worker 자체 면제 불가):
100
- - interactive(`okstra-run`): 명시적 확인 프롬프트(추천 picker, 마지막 옵션 "직접 입력").
101
- - headless(`okstra.sh`): `--qa-waiver <stageKey>:"<사유>"` 명시 인자.
102
- - 기록: 매니페스트 / 리포트에 `waiver: { acknowledgedBy, reason, scope: ["db" | "http" | …], at }`. `reason` 은 **사용자 지시 원문 그대로**(artifact-home 규칙의 "사용자 지시 verbatim 인용"과 동형).
103
- - verdict 반영: waiver 가 적용된 run 은 clean PASS 가 아니라 **`conditional-accept` (conformance 미검증 — 사용자 확인)** 로 기록 → final-verification 에서 그 조건이 그대로 노출된다. `conditional-accept` 는 기존 final-verdict verdict token 을 재사용.
104
- - scope 단위: stage 전체 또는 capability 별(예: `db` 만 waive, `http` 는 그대로 실행) — allowlist 방식으로 좁게.
105
-
106
- ## 8. env · 안전 모델
107
-
108
- - `project.json` 에 정적 `qaEnv` 블록 추가(예: `replicaDbDsn`, `appBaseUrl`, `envFile` 참조). per-stage 스크립트는 번들에, env 포인터는 `project.json` 에(정적 / 민감정보 분리). `qaEnv` 는 resolver 의 user-managed 보존 필드로 둔다(identity/timestamp 필드만 runtime-owned).
109
- - 안전: 기본 **replica / test env 전용**. mutation 을 일으키는 스크립트는 capability 태그로 명시한다. 기존 `qaCommands` 의 mutation deny-list 정신을 conformance 스크립트 실행 환경 가드에도 적용한다.
110
- - env / secret 부재 시 → §6 의 BLOCKING(절대 silent pass 아님). 단 §7.2 사용자 확인형 waiver 로만 우회 가능.
111
-
112
- ## 9. 검증 · 강제 (이 기능 자체)
113
-
114
- - 매니페스트 스키마 validator: entry 필수 필드(`stageKey`, `script`, `runCommand`, `requirementIds`, `requires`, `passContract`), `requires` 화이트리스트, `exemption`/`waiver` 형태.
115
- - verifier Tier 3 lookup 단위테스트(스크립트 있음/없음/면제/waiver 분기).
116
- - 강제 케이스: "diff 가 `requires` 표면을 건드림 + 스크립트/결과/면제/waiver 모두 없음 → BLOCKING FAIL".
117
- - 선언형 면제 거부 케이스: "면제 선언했지만 diff 가 db/io/external 을 건드림 → BLOCKING".
118
- - `QA-RESULT` 파싱 테스트(PASS/FAIL/누락).
119
- - 우회 감사 흔적 테스트: waiver 시 리포트에 사용자 원문 인용 + `conditional-accept` 반영.
120
-
121
- ## 10. 리스크 / 열린 질문
122
-
123
- - replica DB / 실행 env 준비는 프로젝트별 운영 부담. `qaEnv` 미설정 시 게이트가 항상 BLOCKING → 도입 초기에는 §7 우회로 점진 적용.
124
- - planning 이 실행 컨텍스트 없이 작성한 스크립트가 틀릴 수 있음 → 스크립트는 구현 전 RED(실패), 구현 후 GREEN(통과)으로 동작해야 하며, verifier 가 실제 실행으로 검증한다(정적 작성 ≠ 검증).
125
- - 동시 병렬 stage run(stage worktree isolation)에서 conformance 스크립트가 공유 replica DB 를 건드릴 때의 격리/오염 — 초기엔 직렬 실행 가정, 추후 stage 별 env 분리 고려.
126
-
127
- ## 11. 롤아웃
128
-
129
- - pre-1.0 이므로 호환 shim 없음. `qaCommands` 부재 프로젝트는 기존처럼 Tier 2 미구성으로 동작하되, Tier 3 는 매니페스트가 있을 때만 활성.
130
- - 사용자 영향(`CHANGES.md`)에 `사용자 영향:` 라인으로 기록.
131
- - 산출물은 seed/template/runtime sync 경로를 통해 end user 에 전파(`npm run build`).
132
-
133
- ## 12. Phase 4 addendum (2026-06-07) — 위치·생성·실행·강제 wiring 확정
134
-
135
- Phase 1~3(계약·판정·validate-run 게이트) 구현 중 드러난 설계 갭을 brainstorm 으로 해소한 결정. Phase 4 구현의 SSOT.
136
-
137
- ### 12.1 산출물 위치 — task-level (확정)
138
- - conformance 매니페스트/스크립트/`result-<stageKey>.json` 은 **`<task_root>/qa/`** (task-level) 에 둔다. planning→implementation→final-verification 3개 task-type 이 공유해야 하므로 run-level(`runs/<task-type>/qa/`)로는 final-verification 이 implementation 산출물을 못 본다.
139
- - `scripts/okstra_ctl/paths.py` 에 `task_qa()` / `TASK_QA_PATH` 토큰을 추가해 단일 출처로 삼는다(run.py/prompt/validator 의 경로 재유도 drift 방지).
140
- - **Phase 3 게이트 경로 수정(잠복 결함)**: `validators/validate-run.py` 의 `_validate_conformance` 는 현재 `report_path.parent.parent/qa`(run-level)를 읽는다 — task-level 결정에 따라 `<task_root>/qa` 로 바꾼다. report_path 는 `task_root/runs/<task-type>/reports/final-report.md` 이므로 `run_dir = report_path.parent.parent` (=`runs/<task-type>`), `task_root = run_dir.parent.parent`, `qa_dir = task_root / "qa"`. (주의: `report_path.parent.parent.parent` 는 `runs/` 라 잘못됨 — 한 단계 더 올라가야 task_root.) Phase 3 테스트 fixture 도 task-level 로 갱신한다.
141
- - 병렬 stage run 안전성: stage 별 `result-<stageKey>.json` 파일명이 달라 동시 쓰기 충돌 없음. 매니페스트는 planning 이 1회 작성.
142
-
143
- ### 12.2 planning 생성 + 선언 강제
144
- - `prompts/profiles/implementation-planning.md`: stage 마다 conformance entry(스크립트 + `<task_root>/qa/conformance-manifest.json` 갱신) **또는** `Conformance exemption: <사유>` 라인을 산출한다(기존 `TDD exemption:` 패턴과 동형).
145
- - `validators/validate-implementation-plan-stages.py` 에 새 검사(S11): 모든 stage 가 conformance entry 또는 exemption 을 가질 것 — 미선언 시 planning boundary 에서 BLOCKING.
146
-
147
- ### 12.3 verifier 실행 (Tier 3)
148
- - `prompts/profiles/_implementation-verifier.md`: command lookup 을 Tier1(plan validation) → Tier2(`qaCommands`) → **Tier3(conformance)** 로 확장. 각 entry 의 `runCommand` 를 worktree cwd + `qaEnv` 로 실행 → `parse_qa_result` → `<task_root>/qa/result-<stageKey>.json` 작성(포맷 `{stageKey, overall, ranAt, requirements}` — 코드가 이미 고정).
149
-
150
- ### 12.4 diff-surface 교차검증 (DEV-9184 자동 차단)
151
- - `scripts/okstra_ctl/conformance.py` 에 순수 함수 `detect_surfaces(file_paths) -> set[str]` 추가. 기본 패턴(`*.sql`·`migrations/`·`*repository*`·`*.entity.*` → `db`; `*controller*`·`*.routes.*` → `http`; 등), `project.json.qaEnv.surfacePatterns` 로 override.
152
- - `validators/validate-run.py`: **한 run = 한 stage** 이므로 그 run 의 Diff Summary 파일 목록에서 surface 를 감지하고, 해당 stage 의 선언(`requires` + exemption)이 그 surface 를 커버하지 못하면 BLOCKING. (순수 함수 → TDD 가능; validate-run 은 report 의 §5.7.3 Diff Summary 파일 경로를 입력으로 사용)
153
-
154
- ### 12.5 env 모델
155
- - `project.json.qaEnv`: `replicaDbDsn` / `appBaseUrl` / `envFile`(+ 선택 `surfacePatterns`). `scripts/okstra_project/resolver.py` 는 비-identity 필드를 이미 자동 보존하므로 코드 변경 불필요 — 스키마/`skills/okstra-setup/SKILL.md`/verifier prompt 만 문서화.
156
- - 안전: replica/test 전용, mutation 스크립트는 capability 태그로 명시, 기존 `qaCommands` mutation deny-list 정신 유지.
157
-
158
- ### 12.6 final-verification
159
- - `prompts/profiles/final-verification.md`: task-level `<task_root>/qa/` 에서 전 stage 스크립트 합집합을 통합 state 에 대해 실행, command lookup 에 Tier3 추가.
160
-
161
- ### 12.7 우회 UX (spec §7.2 구체화)
162
- - `scripts/okstra.sh` / `scripts/lib/okstra/cli.sh` 에 `--qa-waiver <stageKey>:"<reason>"` 패스스루 → `scripts/okstra_ctl/run.py` 가 `<task_root>/qa/conformance-manifest.json` 의 해당 entry `waiver` 를 채움(`acknowledgedBy`/`reason`(원문)/`scope`/`at`). `okstra-run` wizard 는 사용자 확인 picker(추천 + "직접 입력").
163
-
164
- ### 12.8 Phase 4 sub-plan 분해(구현 단위)
165
- 1. **4a** — 위치 SSOT: `paths.py` TASK_QA 토큰 + Phase 3 게이트 경로/테스트 task-level 전환.
166
- 2. **4b** — `detect_surfaces` (순수) + validate-run diff-surface 교차검증.
167
- 3. **4c** — planning 생성 + S11 선언 강제(prompt + validator).
168
- 4. **4d** — verifier Tier3 실행(prompt) + final-verification Tier3(prompt).
169
- 5. **4e** — env(`qaEnv` 스키마/setup/문서) + 우회 UX(`--qa-waiver` CLI + wizard).
@@ -1,66 +0,0 @@
1
- # executor 세부모델 선택에 "기타(직접입력)" cascade — 설계
2
-
3
- ## 배경 / 문제
4
-
5
- okstra-run wizard 의 모델 선택은 세부모델(opus/sonnet/haiku 등)을 바로 보여 준다. 사용자는
6
- "provider 를 먼저 고르고 그다음 세부모델을 보여 주는 2단계 cascade" + 목록에 없는 모델을
7
- 직접 입력할 수단을 원한다.
8
-
9
- executor 는 **이미** 2단계다: executor pick(provider: claude/codex/gemini) →
10
- executor_model pick(provider 별 세부모델, [`_build_executor_model`](../../../scripts/okstra_ctl/wizard.py),
11
- [`_executor_model_options`](../../../scripts/okstra_ctl/wizard.py)). 빠진 것은 세부모델
12
- 단계의 **"기타(직접입력 = 사용자 정의 모델 ID)"** 옵션뿐이다.
13
-
14
- ## 결정 (사용자 확인 완료)
15
-
16
- | # | 결정 | 근거 |
17
- |---|------|------|
18
- | D1 | cascade 범위 = **executor 만** | lead 는 Claude Code 세션 자체라 provider 변경 불가; report-writer 는 in-process Claude 서브에이전트라 codex/gemini 불가 (아래 비목표) |
19
- | D2 | "기타" = **사용자 정의 모델 ID** (선택한 provider 기준) | provider 는 claude/codex/gemini 3개 그대로, 세부모델만 자유 입력 |
20
- | D3 | 기존 `pick → text` 패턴 재사용 | base-ref 의 `S_BASE_REF_PICK → S_BASE_REF_TEXT` 와 동일 구조 |
21
-
22
- ## 비목표
23
-
24
- - **report-writer / lead 를 provider 선택 대상으로 만들지 않는다.** report-writer 는
25
- `subagent_type: "report-writer-worker"` 인 in-process Claude 서브에이전트로, `Write` 툴로
26
- data.json 을 저작하고 renderer 를 실행한다 ([team-contract:40](../../../skills/okstra-team-contract/SKILL.md),
27
- [report-writer dispatch](../../../skills/okstra-report-writer/SKILL.md)). codex/gemini 실행경로가
28
- 없으므로 wizard 에만 옵션을 넣으면 "가짜 옵션"이 된다. codex/gemini report-writer 는 별도
29
- 백엔드 프로젝트로 분리.
30
-
31
- ## 구현 범위 (모두 `wizard.py` + `prompts.ko.json`)
32
-
33
- > ⚠️ 두 파일은 현재 다른 작업(approve-plan-confirm)으로 동시 편집 중. **그 작업이 커밋되어
34
- > 파일이 풀린 뒤** 적용한다. 적용 전 `git status` 로 두 파일이 clean 인지 확인.
35
-
36
- 1. **새 상태** `S_EXECUTOR_MODEL_TEXT`(상수) + state 필드는 기존 `executor_model` 재사용.
37
- 2. **세부모델 pick 에 기타 옵션 추가** — `_build_executor_model` 의 옵션 목록 끝에
38
- `_opt(PICK_CUSTOM, <기타 라벨>)` 추가 (기존 `PICK_TYPE_CUSTOM` / `PICK_OTHER` 패턴과 동일한
39
- sentinel 상수 신설: `PICK_MODEL_CUSTOM`).
40
- 3. **분기** — `_submit_executor_model`: 값이 `PICK_MODEL_CUSTOM` 이면 다음 step 으로
41
- `S_EXECUTOR_MODEL_TEXT` 반환; 아니면 기존대로 `_validate_model(executor, value)`.
42
- 4. **text step** `_build_executor_model_text`(label = prompts.ko.json) +
43
- `_submit_executor_model_text`: 입력값을 `state.<executor>_model` 에 그대로 저장(자유 모델 ID
44
- 이므로 화이트리스트 검증 면제 — 비어 있으면 재프롬프트).
45
- 5. **STEP 그래프 등록** — `_RESUME_FILLED_STEPS` 등 관련 목록에 신규 step 반영.
46
- 6. **i18n** `prompts.ko.json` 에 `executor_model.options` 기타 라벨 + `executor_model_text`
47
- label/echo_template 추가. (en 미러가 있으면 함께.)
48
-
49
- ## 테스트
50
-
51
- - `tests/test_okstra_ctl_wizard.py`: (a) 세부모델 단계에 기타 옵션이 노출, (b) 기타 선택 시
52
- `S_EXECUTOR_MODEL_TEXT` 로 전이, (c) 자유 입력 모델 ID 가 검증 통과 후 state 에 저장, (d) 빈
53
- 입력은 재프롬프트.
54
-
55
- ## enforcement / 한계
56
-
57
- - 자유 입력 모델 ID 는 화이트리스트 검증을 면제하므로 **존재하지 않는 모델명도 통과**한다.
58
- 이는 사용자가 신규/프리뷰 모델을 쓰기 위한 의도된 탈출구다. 잘못된 id 는 실행 시점에
59
- 해당 provider CLI/Agent 가 거른다.
60
-
61
- ## 영향 / 전파
62
-
63
- - seed/배포 소스(`scripts/`, `prompts/`)에 land → `npm run build` → `runtime/` →
64
- `okstra install`. 개인 `.claude/` 직접 수정 아님.
65
- - 사용자 영향(CHANGES.md): "executor 세부모델 선택에서 목록에 없는 모델을 '기타(직접입력)'으로
66
- 직접 지정할 수 있다."