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.
- package/README.kr.md +5 -6
- package/README.md +5 -6
- package/docs/kr/architecture/storage-model.md +1 -1
- package/docs/kr/architecture.md +8 -12
- package/docs/kr/cli.md +6 -6
- package/docs/kr/container.md +1 -1
- package/docs/kr/performance-improvement-plan-v2.md +2 -2
- package/docs/project-structure-overview.md +2 -2
- package/package.json +7 -2
- package/runtime/BUILD.json +2 -2
- package/runtime/bin/okstra-antigravity-exec.sh +1 -2
- package/runtime/bin/okstra-codex-exec.sh +1 -2
- package/runtime/bin/okstra-render-final-report.py +2 -9
- package/runtime/bin/okstra-spawn-followups.py +4 -6
- package/runtime/bin/okstra-trace-cleanup.sh +24 -4
- package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
- package/runtime/prompts/lead/report-writer.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +9 -11
- package/runtime/python/okstra_ctl/codex_dispatch.py +4 -12
- package/runtime/python/okstra_ctl/consumers.py +35 -0
- package/runtime/python/okstra_ctl/container.py +4 -6
- package/runtime/python/okstra_ctl/dispatch_core.py +4 -12
- package/runtime/python/okstra_ctl/final_report_paths.py +24 -0
- package/runtime/python/okstra_ctl/handoff.py +2 -1
- package/runtime/python/okstra_ctl/implementation_stage.py +7 -11
- package/runtime/python/okstra_ctl/report_view_artifacts.py +14 -0
- package/runtime/python/okstra_ctl/report_views.py +7 -4
- package/runtime/python/okstra_ctl/run.py +3 -10
- package/runtime/python/okstra_ctl/stage_targets.py +18 -0
- package/runtime/python/okstra_ctl/wizard.py +24 -25
- package/runtime/python/okstra_ctl/wizard_stage_intent.py +54 -0
- package/runtime/python/okstra_token_usage/report.py +2 -5
- package/runtime/validators/validate-report-views.py +2 -1
- package/runtime/validators/validate-run.py +1 -11
- package/src/cli-registry.mjs +1 -1
- package/src/commands/lifecycle/install.mjs +10 -20
- package/src/commands/lifecycle/uninstall.mjs +7 -10
- package/docs/superpowers/plans/2026-05-12-ticket-id-in-reports.md +0 -638
- package/docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md +0 -1568
- package/docs/superpowers/plans/2026-05-17-dual-format-final-report.md +0 -167
- package/docs/superpowers/plans/2026-05-20-final-report-language.md +0 -1501
- package/docs/superpowers/plans/2026-05-20-implementation-planning-multi-stage.md +0 -1267
- package/docs/superpowers/plans/2026-05-20-okstra-run-prompt-sot-b1.md +0 -1007
- package/docs/superpowers/plans/2026-05-20-wizard-messages-json-sot.md +0 -720
- package/docs/superpowers/plans/2026-05-20-wizard-prompt-json-sot-a1.md +0 -681
- package/docs/superpowers/plans/2026-05-21-improvement-discovery-task-type.md +0 -1691
- package/docs/superpowers/plans/2026-05-24-implementation-lead-context-slimming.md +0 -1700
- package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +0 -158
- package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +0 -860
- package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +0 -326
- package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +0 -337
- package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +0 -410
- package/docs/superpowers/plans/2026-06-02-requirements-discovery-fanout.md +0 -728
- package/docs/superpowers/plans/2026-06-04-adversarial-implementation-planning.md +0 -294
- package/docs/superpowers/plans/2026-06-04-adversarial-verification.md +0 -570
- package/docs/superpowers/plans/2026-06-04-coverage-critic.md +0 -516
- package/docs/superpowers/plans/2026-06-04-stage-cohesion-planner.md +0 -351
- package/docs/superpowers/plans/2026-06-04-stage-run-batching.md +0 -457
- package/docs/superpowers/plans/2026-06-05-acceptance-critic.md +0 -251
- package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +0 -323
- package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +0 -559
- package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +0 -993
- package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +0 -93
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +0 -447
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +0 -289
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +0 -774
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +0 -303
- package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +0 -387
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase2.md +0 -275
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase3.md +0 -282
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4a.md +0 -147
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4b.md +0 -262
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4c.md +0 -184
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4d.md +0 -88
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4e.md +0 -250
- package/docs/superpowers/plans/2026-06-07-stage-conformance-qa.md +0 -409
- package/docs/superpowers/plans/2026-06-09-implementation-run-artifact-stage-isolation.md +0 -320
- package/docs/superpowers/plans/2026-06-10-concurrent-run-team-guard.md +0 -456
- package/docs/superpowers/plans/2026-06-10-git-reconcile-stale-sha-recovery.md +0 -1408
- package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling-PROBE.md +0 -42
- package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling.md +0 -337
- package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +0 -1029
- package/docs/superpowers/plans/2026-06-10-stage-group-handoff.md +0 -1572
- package/docs/superpowers/plans/2026-06-11-fix-cycle.md +0 -1290
- package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +0 -526
- package/docs/superpowers/plans/2026-06-12-html-plan-approval.md +0 -1000
- package/docs/superpowers/plans/2026-06-13-repo-risk-hardening.md +0 -493
- package/docs/superpowers/plans/2026-06-14-host-runtime-auto-execution.md +0 -1775
- package/docs/superpowers/plans/2026-06-15-coding-preflight-pack-dispatch-path.md +0 -504
- package/docs/superpowers/plans/2026-06-15-internal-skill-migration-final-fixups.md +0 -342
- package/docs/superpowers/plans/2026-06-15-internal-skill-migration-fixups.md +0 -258
- package/docs/superpowers/plans/2026-06-15-internal-skill-migration-remaining-fixups.md +0 -387
- package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +0 -749
- package/docs/superpowers/plans/2026-06-15-worker-prompt-anchor-final-fixups.md +0 -828
- package/docs/superpowers/plans/2026-06-15-worker-prompt-header-error-contract.md +0 -490
- package/docs/superpowers/plans/2026-06-17-okstra-error-report.md +0 -724
- package/docs/superpowers/plans/2026-06-18-subagent-pane-reclaim.md +0 -483
- package/docs/superpowers/plans/2026-06-19-agent-operating-standard.md +0 -476
- package/docs/superpowers/plans/2026-06-19-okstra-inspect-recap-facet.md +0 -647
- package/docs/superpowers/plans/2026-06-20-error-feedback-loop.md +0 -1019
- package/docs/superpowers/plans/2026-06-20-run-index-row-normalization.md +0 -583
- package/docs/superpowers/plans/2026-06-20-stage-auto-integrate-teardown.md +0 -819
- package/docs/superpowers/plans/2026-06-21-okstra-container-local-user-test.md +0 -714
- package/docs/superpowers/plans/2026-06-21-release-handoff-local-checkout.md +0 -348
- package/docs/superpowers/plans/2026-06-23-implementation-stage-multiselect-chain.md +0 -630
- package/docs/superpowers/plans/2026-06-23-implementation-step-commit-granularity.md +0 -274
- package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +0 -409
- package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +0 -542
- package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +0 -568
- package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +0 -203
- package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +0 -525
- package/docs/superpowers/specs/2026-05-12-ticket-id-in-reports-design.md +0 -131
- package/docs/superpowers/specs/2026-05-15-implementation-plan-verification-design.md +0 -254
- package/docs/superpowers/specs/2026-05-20-final-report-language-design.md +0 -383
- package/docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md +0 -322
- package/docs/superpowers/specs/2026-05-20-okstra-run-prompt-sot-design.md +0 -299
- package/docs/superpowers/specs/2026-05-21-improvement-discovery-task-type-design.md +0 -335
- package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +0 -113
- package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +0 -173
- package/docs/superpowers/specs/2026-06-02-requirements-discovery-fanout-design.md +0 -154
- package/docs/superpowers/specs/2026-06-04-adversarial-implementation-planning-design.md +0 -90
- package/docs/superpowers/specs/2026-06-04-adversarial-verification-design.md +0 -176
- package/docs/superpowers/specs/2026-06-04-coverage-critic-design.md +0 -99
- package/docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md +0 -98
- package/docs/superpowers/specs/2026-06-05-acceptance-critic-design.md +0 -90
- package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +0 -87
- package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +0 -121
- package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +0 -126
- package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +0 -180
- package/docs/superpowers/specs/2026-06-06-vertical-slice-tdd-planning-design.md +0 -179
- package/docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md +0 -169
- package/docs/superpowers/specs/2026-06-09-executor-model-custom-id-cascade-design.md +0 -66
- package/docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md +0 -87
- package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +0 -168
- package/docs/superpowers/specs/2026-06-10-concurrent-run-team-guard-design.md +0 -107
- package/docs/superpowers/specs/2026-06-10-git-reconcile-stale-sha-recovery-design.md +0 -105
- package/docs/superpowers/specs/2026-06-10-lead-worker-completion-polling-design.md +0 -113
- package/docs/superpowers/specs/2026-06-10-stage-group-handoff-design.md +0 -156
- package/docs/superpowers/specs/2026-06-11-brief-entry-only-handoff-stage-entry-design.md +0 -158
- package/docs/superpowers/specs/2026-06-11-fix-cycle-design.md +0 -94
- package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +0 -89
- package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +0 -358
- package/docs/superpowers/specs/2026-06-12-html-plan-approval-design.md +0 -85
- package/docs/superpowers/specs/2026-06-12-stage-discipline-rule-design.md +0 -108
- package/docs/superpowers/specs/2026-06-13-forbidden-actions-ssot-design.md +0 -134
- package/docs/superpowers/specs/2026-06-13-neutral-tmux-lead-adapter-design.md +0 -284
- package/docs/superpowers/specs/2026-06-14-host-runtime-auto-execution-design.md +0 -404
- package/docs/superpowers/specs/2026-06-17-okstra-error-report-design.md +0 -123
- package/docs/superpowers/specs/2026-06-18-subagent-pane-reclaim-design.md +0 -150
- package/docs/superpowers/specs/2026-06-19-agent-operating-standard-design.md +0 -120
- package/docs/superpowers/specs/2026-06-19-okstra-inspect-recap-facet-design.md +0 -96
- package/docs/superpowers/specs/2026-06-20-error-feedback-loop-design.md +0 -171
- package/docs/superpowers/specs/2026-06-20-run-index-row-normalization-design.md +0 -112
- package/docs/superpowers/specs/2026-06-20-stage-auto-integrate-teardown-design.md +0 -145
- package/docs/superpowers/specs/2026-06-21-okstra-container-local-user-test-design.md +0 -125
- package/docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md +0 -113
- package/docs/superpowers/specs/2026-06-23-implementation-stage-multiselect-chain-design.md +0 -138
- package/docs/superpowers/specs/2026-06-23-implementation-step-commit-granularity-design.md +0 -120
- package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +0 -129
- package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +0 -185
- package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +0 -121
- package/docs/superpowers/specs/2026-06-24-okstra-container-build-rename-design.md +0 -110
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# implementation stage 다중선택 + 무인 연쇄 설계
|
|
2
|
-
|
|
3
|
-
## 1. 배경
|
|
4
|
-
|
|
5
|
-
`okstra-run` 으로 `implementation` 작업을 시작하면 wizard 의 `stage_pick` 단계에서 진행할 stage 를 고른다. 현재 이 picker 에는 두 가지 불편이 있다.
|
|
6
|
-
|
|
7
|
-
1. **stage 진행 상태가 보이지 않는다.** implementation picker 의 각 옵션은 `"{번호}: {제목} [depends-on: … | steps: …]"` 형식뿐이다([wizard.py:1824-1836](../../../scripts/okstra_ctl/wizard.py:1824)). 어느 stage 가 이미 완료(done)됐는지, 다른 run 이 점유(started/reserved)했는지, depends-on 이 충족돼 지금 실행 가능한지(ready)가 화면에 전혀 표시되지 않는다. 점유/완료된 stage 를 고르면 prepare 런타임까지 가서야 `StageTargetError` 로 거부된다 — 사전 표시가 아니라 **사후 거부**다.
|
|
8
|
-
|
|
9
|
-
2. **한 번에 한 stage 만 고를 수 있다.** `implementation` picker 는 단일선택이라([wizard.py:1837-1842](../../../scripts/okstra_ctl/wizard.py:1837)), 여러 stage 를 순서대로 진행하려면 사용자가 stage 마다 `okstra-run` 을 다시 돌려야 한다.
|
|
10
|
-
|
|
11
|
-
`[done]/[미완]` 상태 마커 인프라([wizard.py:1827-1831](../../../scripts/okstra_ctl/wizard.py:1827))와 `multi=True` 체크박스 picker([`_build_handoff_stage_pick`](../../../scripts/okstra_ctl/wizard.py:1919), [`_submit_handoff_stage_pick`](../../../scripts/okstra_ctl/wizard.py:1947))는 **이미 wizard 안에 검증된 형태로 존재**한다. 전자는 `final-verification` 경로에서만, 후자는 `release-handoff` 경로에서만 켜져 있을 뿐이다. 이 설계는 두 인프라를 `implementation` picker 로 확장하고, 그 위에 현재 세션이 오케스트레이터가 되는 무인 연쇄 루프를 얹는다.
|
|
12
|
-
|
|
13
|
-
## 2. 목표 / 비목표
|
|
14
|
-
|
|
15
|
-
### 목표
|
|
16
|
-
- (A) implementation stage picker 에 각 stage 의 진행 상태(완료/진행·예약중/준비됨/대기)를 표시한다.
|
|
17
|
-
- (B) stage 를 체크박스(다중선택)로 고를 수 있게 하고, "전체(남은 미완료 stage 모두)" 옵션을 제공한다.
|
|
18
|
-
- (B) 선택한 stage 들을 의존성 순서로 자동 진행한다 — 현재 `okstra-run` 세션이 오케스트레이터가 되어 stage 를 하나씩 prepare·실행·완료 확인 후 다음으로 넘어가는 **무인 연쇄**.
|
|
19
|
-
|
|
20
|
-
### 비목표
|
|
21
|
-
- "1 run = 1 stage" 격리 모델을 바꾸지 않는다. stage 별 worktree 격리, registry stage-key 예약, base commit 계산은 그대로 유지된다. 연쇄는 단일-stage run 을 N 회 순차 실행하는 것이지, 한 run 에 여러 stage 를 묶는 것이 아니다.
|
|
22
|
-
- `release-handoff` 의 `--stages`(여러 done stage 를 1 PR 로 묶는 머지)와는 무관하다. 이 설계의 "다중 stage" 는 **실행** 대상이지 머지 대상이 아니다.
|
|
23
|
-
- 비대화형 CLI 진입점(`okstra.sh`, `node bin/okstra`)의 `--stage <auto|N>` 단일-stage 의미는 보존한다. 다중선택은 대화형 wizard picker 에만 추가한다.
|
|
24
|
-
|
|
25
|
-
## 3. 브레인스토밍 결론 (확정된 결정)
|
|
26
|
-
|
|
27
|
-
| 결정 항목 | 선택 |
|
|
28
|
-
|---|---|
|
|
29
|
-
| 다중 stage 실행 모델 | 순차 자동 디스패치 (각 stage = 독립 run, stage 격리 유지) |
|
|
30
|
-
| stage 경계 사람 게이트 | 완전 무인 연쇄 (done 되면 즉시 다음 stage) |
|
|
31
|
-
| 연쇄 주체 | 현재 `okstra-run` 세션이 오케스트레이터 |
|
|
32
|
-
| 부분 선택 시 미완료 의존성 | 의존 stage 자동 포함 (closure) |
|
|
33
|
-
| 무인 연쇄 중 예외 게이트(동시-run 충돌 / git stale-SHA 재조정) | 연쇄 멈추고 사용자에게 인계 |
|
|
34
|
-
| picker 의 `auto` 옵션 | 대화형 picker 에서 제거 (CLI `--stage auto` 는 유지) |
|
|
35
|
-
|
|
36
|
-
## 4. 기능 A — stage 진행 상태 표시
|
|
37
|
-
|
|
38
|
-
### 4.1 동작
|
|
39
|
-
implementation picker 의 각 stage 옵션 뒤에 4-상태 마커를 붙인다.
|
|
40
|
-
|
|
41
|
-
| 마커 | 의미 | 판정 출처 |
|
|
42
|
-
|---|---|---|
|
|
43
|
-
| `[완료]` | done | `consumers.jsonl` status:done |
|
|
44
|
-
| `[진행중]` | 다른 run 점유 | `consumers.jsonl` status:started + registry `list_active_stage_numbers` |
|
|
45
|
-
| `[준비됨]` | depends-on 모두 done | ready 판정 |
|
|
46
|
-
| `[대기]` | depends-on 미충족 | ready 여집합 |
|
|
47
|
-
|
|
48
|
-
표시 예: `2: 결제 어댑터 [depends-on: 1 | steps: 5] [준비됨]`
|
|
49
|
-
|
|
50
|
-
### 4.2 변경 지점
|
|
51
|
-
- [`_build_stage_pick`](../../../scripts/okstra_ctl/wizard.py:1812) 가 현재 `is_fv` 일 때만 읽는 done 집합 외에, implementation 경로에서도 **done / started / reserved** 집합을 읽어 상태를 계산한다. 상태 판정은 wizard 가 직접 재구현하지 않고 prepare 측 SSOT 를 재사용한다 — done/started 는 [`read_consumers`](../../../scripts/okstra_ctl/consumers.py) 로, reserved 는 [`worktree_registry.list_active_stage_numbers`](../../../scripts/okstra_ctl/worktree_registry.py:278) 로, ready 는 [`stage_targets.resolve_effective_stages`](../../../scripts/okstra_ctl/stage_targets.py:40) 의 ready 계산식(`all(d in done_stages for d in depends_on)`)을 공유한다.
|
|
52
|
-
- 마커 문자열은 [`prompts/wizard/prompts.ko.json`](../../../prompts/wizard/prompts.ko.json) 의 `stage_pick.options` 에 `[완료]/[진행중]/[준비됨]/[대기]` 4종을 정의한다. 기존 `[done]/[미완]`(final-verification 용)은 그대로 두되, 이 4종과 의미가 겹치지 않게 분리 유지한다.
|
|
53
|
-
|
|
54
|
-
### 4.3 final-verification 영향
|
|
55
|
-
`final-verification` picker 의 기존 `[done]/[미완]` 표시는 변경하지 않는다. 기능 A 의 4-상태는 `state.task_type == "implementation"` 분기에서만 적용한다.
|
|
56
|
-
|
|
57
|
-
## 5. 기능 B — 다중선택 체크박스 + 무인 연쇄
|
|
58
|
-
|
|
59
|
-
### 5.1 picker 다중선택 (B1)
|
|
60
|
-
[`_build_stage_pick`](../../../scripts/okstra_ctl/wizard.py:1812) 의 implementation 분기를 `release-handoff` picker 패턴([wizard.py:1940-1944](../../../scripts/okstra_ctl/wizard.py:1940))과 동일하게 `Prompt(..., multi=True, ...)` 로 만든다.
|
|
61
|
-
|
|
62
|
-
- picker 에서 `auto` 옵션을 **제거**한다([wizard.py:1820-1821](../../../scripts/okstra_ctl/wizard.py:1820) 의 implementation 분기). 기능 A 로 `[준비됨]` 이 보이므로 사용자가 ready stage 를 직접 체크한다.
|
|
63
|
-
- 맨 위에 `전체 (남은 미완료 stage 모두)` 옵션을 추가한다.
|
|
64
|
-
- 이미 `[완료]` 또는 `[진행중]` 인 stage 는 **선택 대상에서 제외**한다(picker 옵션으로 내보내되 선택 시 submit 이 거부, 또는 옵션 자체를 비활성 표기). 선택 가능한 것은 `[준비됨]` 과 `[대기]` 다.
|
|
65
|
-
- 다중선택 입력/직렬화 프로토콜은 손대지 않는다. `Prompt.multi` 필드([wizard.py:436](../../../scripts/okstra_ctl/wizard.py:436))와 SKILL.md 의 `multi:true → AskUserQuestion(multiSelect:true) → CSV join` 규약([SKILL.md:47](../../../skills/okstra-run/SKILL.md:47), [:101](../../../skills/okstra-run/SKILL.md:101))이 이미 존재한다.
|
|
66
|
-
|
|
67
|
-
### 5.2 선택 정규화 — 의존성 closure + 위상정렬 (B2)
|
|
68
|
-
[`_submit_stage_pick`](../../../scripts/okstra_ctl/wizard.py:1845) 을 CSV 파싱으로 교체한다(현재 단수 정수/`auto`/whole-task 만 허용). 처리 순서:
|
|
69
|
-
|
|
70
|
-
1. **파싱**: `value.split(",")` 로 선택 집합 수집([`_submit_handoff_stage_pick`](../../../scripts/okstra_ctl/wizard.py:1949) 패턴 재사용). 빈 선택은 `WizardError` 로 재질문.
|
|
71
|
-
2. **전체 치환**: `전체` 가 포함되면 **선택 가능한 stage 전부**(done/started/reserved 가 아닌, 즉 `[준비됨]`+`[대기]`)로 확장하고 다른 개별 선택과 동시 선택은 거부(handoff 의 `whole_task_exclusive` 패턴). started/reserved 는 다른 run 이 점유 중이므로 `전체` 에 포함하지 않는다.
|
|
72
|
-
3. **선택 가능성 검증**: 각 선택이 done/started/reserved 가 아닌지 확인. 점유/완료 stage 선택은 거부.
|
|
73
|
-
4. **의존성 closure**: 선택한 stage 가 의존하는 **미완료** stage 를 선택에 자동 추가한다. (이미 done 인 의존성은 추가 불필요.) 추가된 stage 는 echo 로 사용자에게 알린다("3 이 함께 포함됩니다"). (started/reserved 인 의존성도 미완료라 closure 에 포함될 수 있으나, 그 stage 의 render-bundle 은 점유로 거부되어 SKILL.md Step 7 에서 연쇄가 정상 종료된다.)
|
|
74
|
-
5. **위상정렬**: closure 집합을 depends-on 그래프의 위상순서로 정렬해 `state.selected_stages`(정렬된 CSV)에 저장한다.
|
|
75
|
-
|
|
76
|
-
closure + 위상정렬은 **순수 의존성 그래프 연산**이므로 [`stage_targets.py`](../../../scripts/okstra_ctl/stage_targets.py)(이미 ready 판정·의존성 충족 계산을 보유한 SSOT)에 새 헬퍼로 둔다. 입력은 `(stage_number, depends_on)` 형태로 추상화해, wizard 의 `StageMeta` 리스트([`_parse_stage_objects`](../../../scripts/okstra_ctl/wizard.py:937))와 run.py 의 dict stage_map([`_parse_stage_map_into_ctx`](../../../scripts/okstra_ctl/run.py:585)) 양쪽이 같은 헬퍼를 쓰게 한다. wizard.py 가 그래프 연산을 자체 구현하지 않게 한다(단일 참조점).
|
|
77
|
-
|
|
78
|
-
`state.selected_stages: str = ""` 필드를 [`WizardState`](../../../scripts/okstra_ctl/wizard.py:367) 에 추가한다. 기존 단수 `selected_stage` 는 비대화형 CLI 경로·final-verification 이 계속 쓰므로 유지한다(둘의 역할이 다르다).
|
|
79
|
-
|
|
80
|
-
### 5.3 render-args 확장 (B3)
|
|
81
|
-
[`render_args`](../../../scripts/okstra_ctl/wizard.py:3398) 의 implementation 분기가 위상정렬된 `selected_stages` CSV 를 출력하게 한다. 현재 implementation 은 단수 `stage` 만 내보낸다([wizard.py:3412-3413](../../../scripts/okstra_ctl/wizard.py:3412)). handoff 가 쓰는 `stages` 키([wizard.py:3441](../../../scripts/okstra_ctl/wizard.py:3441))와 의미가 다르므로(handoff=머지 대상, implementation=순차 실행 대상), implementation 전용으로 명확히 구분되는 키 이름을 쓴다(예: `chain-stages`). 단일 stage 만 골랐으면 CSV 원소 1개 = 기존 단일 run 과 동일하게 동작한다.
|
|
82
|
-
|
|
83
|
-
### 5.4 SKILL.md 무인 연쇄 루프 (B4)
|
|
84
|
-
연쇄 책임은 오케스트레이터 계층인 [`skills/okstra-run/SKILL.md`](../../../skills/okstra-run/SKILL.md) 에만 둔다. wizard.py(입력 1회 수집 → render-args 1세트)·python prepare(render-only, 단일-stage 강제)는 단일 stage 단위를 그대로 유지한다.
|
|
85
|
-
|
|
86
|
-
현재 흐름은 Step 6([SKILL.md:247-254](../../../skills/okstra-run/SKILL.md:247))에서 lead 인계 후 단일 run 으로 종료된다([SKILL.md:293](../../../skills/okstra-run/SKILL.md:293)). 여기에 연쇄 루프를 추가한다:
|
|
87
|
-
|
|
88
|
-
1. render-args 의 `chain-stages` CSV(위상정렬됨)를 큐로 받는다.
|
|
89
|
-
2. 큐의 다음 stage `N` 에 대해 `render-bundle --stage N` 을 호출한다(나머지 render-args 인자는 첫 호출에서 고정; base commit 은 prepare 가 predecessor done commit 으로 자동 계산한다).
|
|
90
|
-
3. 현재 세션(lead)이 그 bundle 의 Phase 1~7 을 인라인 실행하고, Phase 6 에서 `done` 행을 append 한다([`append_consumer`](../../../scripts/okstra_ctl/consumers.py:53), 프로파일 사이드카 [`_implementation-deliverable.md:50-56`](../../../prompts/profiles/_implementation-deliverable.md:50)).
|
|
91
|
-
4. 다음 사이클의 prepare 가 직전 stage 의 done(또는 carry 사이드카 backfill, [`backfill_done_from_carry`](../../../scripts/okstra_ctl/consumers.py:160))을 읽어 의존성 게이트를 자동으로 연다.
|
|
92
|
-
5. 큐가 빌 때까지 2~4 를 반복한다. 매 stage 경계에서 컨텍스트를 정리한다(여러 stage 누적 방지).
|
|
93
|
-
|
|
94
|
-
stage 시작/완료마다 한 줄 진행 보고("stage N/M 시작", "stage N done → 다음 stage K")를 출력한다.
|
|
95
|
-
|
|
96
|
-
### 5.5 예외 게이트 처리 (B5)
|
|
97
|
-
매 `render-bundle` 마다 발생할 수 있는 **동시-run 충돌 감지**([SKILL.md:208-223](../../../skills/okstra-run/SKILL.md:208))와 **git stale-SHA 재조정**([SKILL.md:225-245](../../../skills/okstra-run/SKILL.md:225)) 게이트는 사람 판단이 필요하다. 무인 연쇄 중 이 게이트가 뜨면:
|
|
98
|
-
|
|
99
|
-
- 그 stage 에서 **연쇄를 멈추고** 게이트를 사용자에게 그대로 제시한다.
|
|
100
|
-
- 사용자가 게이트를 해소하면 그 자리에서 연쇄를 재개한다(남은 큐를 이어서 처리).
|
|
101
|
-
- 이것이 "완전 무인" 의 안전 경계다 — 데이터 손상·동시 점유 충돌은 사람이 확인한다.
|
|
102
|
-
|
|
103
|
-
## 6. 변경 지점 요약
|
|
104
|
-
|
|
105
|
-
| # | 파일 | 변경 |
|
|
106
|
-
|---|---|---|
|
|
107
|
-
| A1 | [`scripts/okstra_ctl/wizard.py:1812`](../../../scripts/okstra_ctl/wizard.py:1812) `_build_stage_pick` | implementation 경로에 4-상태 마커 + done/started/reserved 집합 읽기 |
|
|
108
|
-
| A2 | [`prompts/wizard/prompts.ko.json`](../../../prompts/wizard/prompts.ko.json) | `[완료]/[진행중]/[준비됨]/[대기]` 마커 문자열 추가 |
|
|
109
|
-
| B1 | [`scripts/okstra_ctl/wizard.py:1837`](../../../scripts/okstra_ctl/wizard.py:1837) `_build_stage_pick` | `multi=True`, `전체` 옵션, `auto` 제거, 점유/완료 stage 선택 제외 |
|
|
110
|
-
| B2 | [`scripts/okstra_ctl/wizard.py:1845`](../../../scripts/okstra_ctl/wizard.py:1845) `_submit_stage_pick` | CSV 파싱 → closure → 위상정렬 → `state.selected_stages` |
|
|
111
|
-
| B2 | [`scripts/okstra_ctl/wizard.py:367`](../../../scripts/okstra_ctl/wizard.py:367) `WizardState` | `selected_stages: str` 필드 추가 |
|
|
112
|
-
| B2 | [`scripts/okstra_ctl/stage_targets.py`](../../../scripts/okstra_ctl/stage_targets.py) | closure + 위상정렬 순수 헬퍼(SSOT) |
|
|
113
|
-
| B3 | [`scripts/okstra_ctl/wizard.py:3398`](../../../scripts/okstra_ctl/wizard.py:3398) `render_args` | implementation 이 위상정렬 `chain-stages` CSV 출력 |
|
|
114
|
-
| B4 | [`skills/okstra-run/SKILL.md:247`](../../../skills/okstra-run/SKILL.md:247) Step 6 이후 | 무인 연쇄 루프 + 진행 보고 |
|
|
115
|
-
| B5 | [`skills/okstra-run/SKILL.md`](../../../skills/okstra-run/SKILL.md) | 연쇄 중 예외 게이트 → 중단·인계·재개 정책 |
|
|
116
|
-
|
|
117
|
-
`runtime/` 은 빌드 산출물이므로 손대지 않는다. 위 소스 변경 후 `npm run build` 로 동기화한다.
|
|
118
|
-
|
|
119
|
-
## 7. 아키텍처 일관성
|
|
120
|
-
|
|
121
|
-
- **단일 참조점**: stage 상태/ready/의존성 판정은 prepare 측 SSOT([`stage_targets.py`](../../../scripts/okstra_ctl/stage_targets.py), [`consumers.py`](../../../scripts/okstra_ctl/consumers.py), [`worktree_registry.py`](../../../scripts/okstra_ctl/worktree_registry.py))를 wizard 가 재사용한다. wizard 가 상태 계산이나 의존성 그래프 연산을 자체 구현하지 않는다.
|
|
122
|
-
- **3 진입점 수렴 유지**: 다중선택은 대화형 wizard picker 에만 추가되고, 세 진입점은 여전히 [`prepare_task_bundle`](../../../scripts/okstra_ctl/run.py:1851) 로 수렴한다. 연쇄는 그 위 오케스트레이터(SKILL.md)에서 prepare 를 N 회 호출하는 것이지 prepare 를 우회하지 않는다.
|
|
123
|
-
- **격리 모델 불변**: render-bundle 한 번 = stage 하나 = worktree 하나 = registry 예약 하나. 이 불변식은 그대로다.
|
|
124
|
-
- **pre-1.0**: 호환 shim 없이 implementation picker 의 단일선택 동작을 다중선택으로 교체한다(단일 stage 1개 선택 = 기존 동작 동치).
|
|
125
|
-
|
|
126
|
-
## 8. 테스트 계획
|
|
127
|
-
|
|
128
|
-
- `tests/wizard/`: `_submit_stage_pick` 다중선택 파싱, `전체` 치환·배타성, 점유/완료 stage 거부, closure 자동 포함, 위상정렬 순서.
|
|
129
|
-
- `tests/wizard/`: `_build_stage_pick` 가 implementation 에서 4-상태 마커를 정확히 부여(각 상태별 픽스처).
|
|
130
|
-
- `stage_targets.py` 헬퍼: closure + 위상정렬 순수 함수 단위 테스트(순환 의존 입력은 검증 단계에서 이미 단조 stage 번호로 차단되지만, 헬퍼 자체의 결정성 확인).
|
|
131
|
-
- e2e(`tests-e2e/`): 2-stage 의존 체인을 다중선택 → 무인 연쇄로 진행해 stage 1 done 후 stage 2 가 자동 prepare 되는지. 무인 연쇄 루프 자체는 SKILL.md(프롬프트)라 의존성 게이트(done→다음 ready 해금)는 prepare 단위 테스트로 커버하고, 연쇄 오케스트레이션은 시나리오 스크립트로 확인.
|
|
132
|
-
|
|
133
|
-
## 9. 위험 / 주의
|
|
134
|
-
|
|
135
|
-
- **컨텍스트 누적**: 현재 세션이 여러 stage 를 연속 실행하면 컨텍스트가 커진다. stage 경계 컨텍스트 정리(5.4-5)를 명시 지시로 둔다.
|
|
136
|
-
- **done 누락 시 게이트 미해금**: lead 가 Phase 6 의 `done` append 를 빠뜨리면 다음 stage 의 depends-on 이 안 풀린다. carry 사이드카 backfill 이 안전망이지만([`backfill_done_from_carry`](../../../scripts/okstra_ctl/consumers.py:160)), 연쇄 루프는 각 사이클에서 직전 stage 의 done(또는 carry)을 확인한 뒤 다음으로 넘어가야 한다.
|
|
137
|
-
- **의존성이 타 run 점유**: 선택한 `[대기]` stage 의 미완료 의존성이 다른 run 에 started/reserved 상태면 closure 가 그것을 큐에 넣지 못한다(점유 제외). 이 경우 그 대기 stage 는 의존성이 done 될 때까지 실행 불가이며, 무인 연쇄는 "다음 ready stage 없음" 으로 자연 종료하고 남은 큐를 사용자에게 보고한다.
|
|
138
|
-
- **마커 문자열 충돌**: 기능 A 의 `[준비됨]` 등 새 토큰은 final-verification 의 `[done]/[미완]` 과 분리 유지한다. 새 토큰 추가 후 prompts.ko.json 전반을 grep 해 중복·오용이 없는지 확인한다.
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# implementation 커밋·step 입도 완화 설계
|
|
2
|
-
|
|
3
|
-
## 1. 배경과 문제
|
|
4
|
-
|
|
5
|
-
`implementation-planning` 이 산출하는 stage 의 step 단위와, `implementation` executor 의 커밋 단위가
|
|
6
|
-
지나치게 잘게 쪼개진다는 사용자 피드백에서 출발한다.
|
|
7
|
-
|
|
8
|
-
현행 동작을 코드 기준으로 정리하면:
|
|
9
|
-
|
|
10
|
-
- **step 정의**: [`prompts/profiles/implementation-planning.md:81`](../../../prompts/profiles/implementation-planning.md)
|
|
11
|
-
— `### Stepwise Execution Order` 의 step 은 "one action completable in 2–5 minutes",
|
|
12
|
-
effective row count `≤ 6`.
|
|
13
|
-
- **커밋 정의**: [`prompts/profiles/_implementation-executor.md:30-31`](../../../prompts/profiles/_implementation-executor.md)
|
|
14
|
-
— step 당 TDD 루프가 `(2) commit the failing test (test(...))` → `(4) commit the
|
|
15
|
-
implementation (feat|fix(...))` → `(5) refactor 별도 커밋` 으로 한 step 을 커밋 2~3 개로 분해.
|
|
16
|
-
[`:74`](../../../prompts/profiles/_implementation-executor.md) "One commit MUST correspond to one plan step".
|
|
17
|
-
|
|
18
|
-
즉 "파일 하나에 커밋 하나" 라는 체감의 실제 원인은 파일 단위 분할이 아니라
|
|
19
|
-
**TDD RED/GREEN 분리 커밋 강제 × 2–5분 micro-step × ≤6 캡** 조합이다.
|
|
20
|
-
|
|
21
|
-
이를 두 갈래로 완화한다.
|
|
22
|
-
|
|
23
|
-
- **A. 커밋 합치기** — test 커밋과 impl 커밋을 한 커밋으로 병합. refactor 는 별도 커밋 허용.
|
|
24
|
-
- **B. step 입도 상향** — step 정의를 "완결적·응집 변경 단위" 로 격상하고 캡을 `6 → 8` 로 상향.
|
|
25
|
-
|
|
26
|
-
## 2. 설계 원칙과 범위 결정
|
|
27
|
-
|
|
28
|
-
- **최소 변경 (사용자 결정)**: planning 의 `RED:` / `GREEN:` step 표기와 validator S10c/S10d 는
|
|
29
|
-
**유지**한다. TDD discipline(테스트 먼저) 자체도 유지한다. 바꾸는 것은 executor 의 커밋 병합 정책과
|
|
30
|
-
step 입도 정의/캡뿐이다.
|
|
31
|
-
- **파생 결정 (커밋 매핑 단위)**: planning step 표기를 유지하면 한 stage 안에 `RED:` step 과
|
|
32
|
-
`GREEN:` step 이 별도 행으로 남는다. 따라서 executor 의 커밋 매핑 단위를 "1 커밋 = 1 step" 에서
|
|
33
|
-
**"1 커밋 = 1 TDD 사이클(RED step + 그 GREEN step(들))"** 로 바꿔야 test+impl 이 한 커밋으로 묶인다.
|
|
34
|
-
이것이 A 의 본체다.
|
|
35
|
-
- **enforcement / declaration 분리**: 캡의 실제 강제 지점(enforcement SSOT)은 validator
|
|
36
|
-
[`validators/validate-implementation-plan-stages.py`](../../../validators/validate-implementation-plan-stages.py) 의
|
|
37
|
-
S5 검사 한 곳이다. 프로파일·문서의 `≤ 8` 문구는 LLM 이 읽는 자연어 declaration 으로,
|
|
38
|
-
validator 상수를 미러링한다. 캡 숫자를 validator 모듈 상수 `HARD_STEP_CAP = 8` 로 추출해
|
|
39
|
-
코드 측 단일 참조점을 만든다.
|
|
40
|
-
- **YAGNI**: TDD 폐기 ❌, 캡의 "권장/hard" 2단 구조 ❌ (단일 hard cap 8).
|
|
41
|
-
- **pre-1.0 호환성**: 별도 호환 셔임 없음. 단, 이번 변경은 기존 산출 plan 을 깨지 않는다(캡 완화는
|
|
42
|
-
단조 확장이고, 커밋 정책은 executor 미래 동작에만 영향).
|
|
43
|
-
|
|
44
|
-
## 3. 변경 상세 (A — 커밋 합치기)
|
|
45
|
-
|
|
46
|
-
### 3.1 `prompts/profiles/_implementation-executor.md`
|
|
47
|
-
|
|
48
|
-
- **`:30-31` Mandatory TDD loop 의 "Order of operations per plan step"**
|
|
49
|
-
- 현행: (1) 실패 테스트 작성·실패 확인 → (2) `test(<scope>): ...` 실패 커밋 → (3) 최소 구현 →
|
|
50
|
-
(4) `feat|fix(<scope>): ...` 구현 커밋 → (5) refactor 시 `refactor(<scope>): ...` 별도 커밋.
|
|
51
|
-
- 변경: (1) 실패 테스트 작성·실패 확인 → (2) 최소 구현으로 통과 →
|
|
52
|
-
(3) **테스트와 구현을 한 커밋**(`feat|fix(<scope>): ...`)으로 — "실패 테스트 별도 커밋" 단계 제거 →
|
|
53
|
-
(4) behavior-보존 refactor 가 있으면 `refactor(<scope>): ...` 별도 커밋 허용.
|
|
54
|
-
- "The failing-then-passing transition between steps (2) and (4) is the TDD evidence" 문장은
|
|
55
|
-
"실패→통과 전환은 final report 의 evidence 로 기록(병합 커밋 직전 failing 출력 + 직후 passing 출력)" 으로 대체.
|
|
56
|
-
- **`:74` "One commit MUST correspond to one plan step"**
|
|
57
|
-
- 변경: "One commit corresponds to one TDD cycle — the RED step plus its GREEN step(s) are
|
|
58
|
-
merged into a single `feat|fix` commit; an optional REFACTOR step MAY be a separate commit.
|
|
59
|
-
Never split a test and its implementation into separate commits." 다만 "서로 무관한 step 을 한
|
|
60
|
-
커밋에 묶지 말 것" 제약은 유지.
|
|
61
|
-
- **`:29` head-less 문구**: "RED → GREEN → refactor → per-step commits" → "… → per-cycle commit"
|
|
62
|
-
으로 정합성만 맞춤.
|
|
63
|
-
|
|
64
|
-
### 3.2 `prompts/profiles/_implementation-deliverable.md`
|
|
65
|
-
|
|
66
|
-
- **`:20` TDD evidence**: "show the failing-test output BEFORE the implementation commit and the
|
|
67
|
-
passing-test output AFTER, with commit SHAs framing the transition" →
|
|
68
|
-
test/impl 이 한 커밋이라 두 SHA framing 이 불가하므로
|
|
69
|
-
"병합 커밋 직전 캡처한 failing-test 출력과 직후 passing-test 출력을, 단일 `feat|fix` 커밋 SHA 를
|
|
70
|
-
인용해 제시" 로 변경.
|
|
71
|
-
- **`:14` Commit list**: "the plan step it satisfies" → "the plan step(s)/TDD cycle it satisfies"
|
|
72
|
-
로 표현만 정합.
|
|
73
|
-
- **`:38` Plan coverage**: "every step ... must point to a commit" 는 유지하되, RED step 과 그
|
|
74
|
-
GREEN step 이 **동일 병합 커밋**을 가리키는 것은 coverage 위반이 아님을 한 줄로 명시(같은 SHA 를
|
|
75
|
-
두 step 이 공유 가능).
|
|
76
|
-
|
|
77
|
-
## 4. 변경 상세 (B — step 입도)
|
|
78
|
-
|
|
79
|
-
### 4.1 캡 상수화 (enforcement SSOT)
|
|
80
|
-
|
|
81
|
-
- [`validators/validate-implementation-plan-stages.py`](../../../validators/validate-implementation-plan-stages.py)
|
|
82
|
-
`:169-171` (S5): 모듈 상단에 `HARD_STEP_CAP = 8` 상수를 도입하고 `if steps > HARD_STEP_CAP:`
|
|
83
|
-
로 교체, 메시지도 상수를 참조. `_check_slice_tdd` docstring 의 step 설명도 정합.
|
|
84
|
-
|
|
85
|
-
### 4.2 declaration 미러 (자연어)
|
|
86
|
-
|
|
87
|
-
- [`prompts/profiles/implementation-planning.md`](../../../prompts/profiles/implementation-planning.md):
|
|
88
|
-
- `:81`: `Effective row count ≤ 6` → `≤ 8`; "Each step is one action completable in 2–5 minutes" →
|
|
89
|
-
"Each step is one cohesive, self-contained change (시간 하한 없음; 함께 바뀌는 여러 파일 포함 가능)".
|
|
90
|
-
- `:60`, `:88`, `:89`, `:130`: 본문 중 `6` / `≤6-step` 언급을 `8` / `≤8-step` 으로 미러.
|
|
91
|
-
- [`docs/kr/architecture.md:341`](../../kr/architecture.md): "effective step ≤ 6" → "≤ 8".
|
|
92
|
-
- [`docs/project-structure-overview.md:276`](../../project-structure-overview.md): "step ≤ 6" → "≤ 8".
|
|
93
|
-
|
|
94
|
-
## 5. 테스트 영향
|
|
95
|
-
|
|
96
|
-
- [`tests/contract/test_validate_implementation_plan_stages.py`](../../../tests/contract/test_validate_implementation_plan_stages.py)
|
|
97
|
-
`test_step_overflow_rejected` 는 fixture
|
|
98
|
-
[`tests/fixtures/plans/invalid_step_overflow.md`](../../../tests/fixtures/plans/invalid_step_overflow.md)
|
|
99
|
-
의 7-step 으로 S5 를 발화시킨다. 캡이 8 이 되면 7-step 은 통과하므로 fixture 를 **9-step** 으로
|
|
100
|
-
확장하고 Stage Map 의 `step-count` 셀을 `7 → 9` 로 맞춘다(S7 mismatch 방지, S5 만 깨끗이 발화).
|
|
101
|
-
- `valid_three_stage_parallel.md`(10행, stage 당 분산)·`valid_one_stage.md`(3행) 는 stage 당 step 이
|
|
102
|
-
8 이하라 수정 불필요.
|
|
103
|
-
- A 변경(커밋 정책)은 프롬프트 자연어라 직접 강제하는 단위 테스트가 없다. deliverable evidence 문구
|
|
104
|
-
변경도 검증기 토큰 대상이 아니다 — grep 으로 잔여 "framing the transition" / "commit the failing"
|
|
105
|
-
문구가 남지 않았는지만 확인.
|
|
106
|
-
|
|
107
|
-
## 6. 사용자 영향 (CHANGES.md)
|
|
108
|
-
|
|
109
|
-
[`CHANGES.md`](../../../CHANGES.md) 에 항목 추가, `사용자 영향:` 줄 포함:
|
|
110
|
-
|
|
111
|
-
- 다음 release 후 `npx -y okstra@latest install` 1회로 전파.
|
|
112
|
-
- 신규 `implementation-planning` run 부터 step 이 굵어지고 stage 당 step 수가 줄며,
|
|
113
|
-
`implementation` run 의 커밋이 "기능 1커밋 + (선택) refactor 1커밋" 으로 묶인다.
|
|
114
|
-
- breaking 아님 — 기존 산출 plan(≤6 step)은 그대로 통과하고, 캡 완화는 단조 확장.
|
|
115
|
-
|
|
116
|
-
## 7. 비-목표
|
|
117
|
-
|
|
118
|
-
- TDD 폐기 — 테스트 먼저 규율, planning 의 `RED:`/`GREEN:` 토큰, S10c/S10d 는 유지.
|
|
119
|
-
- 캡의 "권장/hard" 2단 구조 — 단일 hard cap 8 만 둔다.
|
|
120
|
-
- planning step 모델을 "RED/GREEN 통합 단일 step" 으로 재설계 — 사용자 결정에 따라 최소 변경 유지.
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
# Cross-Project Dependencies — implementation-planning 선행 필수 격상 설계
|
|
2
|
-
|
|
3
|
-
- 작성일: 2026-06-24
|
|
4
|
-
- 대상 phase: `implementation-planning`
|
|
5
|
-
- 상태: 설계 승인 완료 (구현 계획 작성 대기)
|
|
6
|
-
|
|
7
|
-
## 1. 배경과 문제
|
|
8
|
-
|
|
9
|
-
`implementation-planning` 보고서는 `data.json`(SSOT) → Jinja 템플릿(`templates/reports/final-report.template.md`)으로 **결정론적 렌더**된다. report-writer 는 마크다운을 직접 쓰지 못한다([report-writer-worker.md:27](../../../agents/workers/report-writer-worker.md:27)).
|
|
10
|
-
|
|
11
|
-
이 run 이 **다른 프로젝트(다른 repo·published 패키지)** 의 작업에 의존할 때, 그 의존을 표현할 수 있는 채널이 현재 3개뿐이고 모두 부족하다:
|
|
12
|
-
|
|
13
|
-
1. **`§3 Recommended Next Steps`** (`recommendedNextSteps[]`, 자유 텍스트) — "추천"이라 강제력이 없다. 실제 사례(`dev-9795`)에서 "helpers·common-api cross-repo carry 를 별도 okstra run 으로 먼저 진행하라"가 여기에 soft 하게 들어가, 선행 필수임이 드러나지 않았다.
|
|
14
|
-
2. **`Dependency / Migration Risk`** DM 행 — `kind` enum 에 `flag-precondition`/`repo-sequencing` 이 있으나([schema:1369](../../../schemas/final-report-v1.0.schema.json)) "위험 서술"일 뿐 "선행 필수 + 구체 작업"을 강제하지 않는다. `repo-sequencing` 은 프로파일상 **repo-내부 순서**를 뜻한다([implementation-planning.md:100](../../../prompts/profiles/implementation-planning.md:100)) — cross-repo 마커가 아니다.
|
|
15
|
-
3. **프로파일이 요구하는 `## Cross-Repo Carry — <repo>` 부록**([implementation-planning.md:94](../../../prompts/profiles/implementation-planning.md:94)) — **스키마·템플릿에 렌더 슬롯이 없어 보고서에 출력되지 못하는 잠복 버그**. 게다가 방향이 "이 run 이 상위(upstream)이고 다른 repo 가 하위"로, 사용자 사례(이 run 이 **하위**, 외부 패키지가 **선행 상위**)와 반대다.
|
|
16
|
-
|
|
17
|
-
결과적으로 **"이 run 이 다른 프로젝트의 선행 작업에 의존한다"** 는 1급 개념이 없어 soft recommendation 으로 새어나가고, 거기서 필요한 **구체 작업**도 강제되지 않는다.
|
|
18
|
-
|
|
19
|
-
## 2. 목표 / 비목표
|
|
20
|
-
|
|
21
|
-
### 목표
|
|
22
|
-
- cross-project 의존을 **1급·렌더되는 구조 필드**로 승격한다.
|
|
23
|
-
- upstream(이 run 이 기다림 = 선행 필수)과 downstream(이 run 이 만들어 줌 = 기존 carry) **두 방향을 한 개념으로 통합**한다.
|
|
24
|
-
- 각 의존에 **구체적으로 필요한 작업**(`requiredWork`)을 빈말 못 하도록 스키마 레벨에서 강제한다.
|
|
25
|
-
- cross-project 의존이 선언되면 이 섹션이 비어있지 못하도록 **검증기 게이트**를 둔다.
|
|
26
|
-
- 기존 `## Cross-Repo Carry` 잠복 렌더 버그를 통합 과정에서 해소한다.
|
|
27
|
-
|
|
28
|
-
### 비목표
|
|
29
|
-
- **런타임 게이트 없음.** `implementation` run 진입 시 선행 신호를 자동 확인하거나 워커 fan-out 을 차단하지 않는다.
|
|
30
|
-
- **승인 차단 없음.** 계획 frontmatter `approved` 를 막지 않는다 — 선행 작업은 병렬 진행 가능하므로 계획 승인 자체는 막지 않는다.
|
|
31
|
-
- 다른 repo 의 트리·`.okstra/` 에 쓰지 않는다(기존 cross-repo 구조 한계 유지).
|
|
32
|
-
|
|
33
|
-
## 3. 설계
|
|
34
|
-
|
|
35
|
-
### 3.1 데이터 모델 (schema)
|
|
36
|
-
|
|
37
|
-
`schemas/final-report-v1.0.schema.json` 의 `implementationPlanning` 객체에 새 배열 `crossProjectDependencies` 를 추가한다(기본 `[]` 허용 — 단일 프로젝트 계획은 빈 배열).
|
|
38
|
-
|
|
39
|
-
새 `$defs/CrossProjectDependency`:
|
|
40
|
-
|
|
41
|
-
| 필드 | 타입/제약 | 의미 |
|
|
42
|
-
|---|---|---|
|
|
43
|
-
| `id` | `^XP-\d{3,}$` | cross-project 식별자 |
|
|
44
|
-
| `direction` | enum: `upstream-precondition` \| `downstream-carry` | upstream = 이 run 이 **기다림**(선행 필수); downstream = 이 run 이 **만들어 줌**(기존 carry) |
|
|
45
|
-
| `project` | string, minLength 1 | 상대 프로젝트/repo/패키지명 (예: `@fonts-ninja-org/common-api`) |
|
|
46
|
-
| `requiredWork` | string, minLength 1 | **구체적으로 필요한 작업**. upstream: 상대 프로젝트가 만들어야 할 것; downstream: 상대가 후속으로 구현할 B-portion |
|
|
47
|
-
| `verificationSignal` | string, minLength 1 | 충족을 증명하는 관측 신호 (예: "npm common-api ≥ 1.27.46 + Font.d.ts 에 isSlanted 존재") |
|
|
48
|
-
| `linkedWork` | string, minLength 1 | upstream: 신호 충족 전 **막히는 이 계획의 stage/step**; downstream: 이 run 산출물을 소비하는 상대 작업 |
|
|
49
|
-
| `howToStart` | string, minLength 1 | 정확한 핸드오프 (`okstra-brief …(이 보고서 절대경로 Source Material)` → `okstra-run`) |
|
|
50
|
-
|
|
51
|
-
- `additionalProperties: false`, 위 7개 전부 `required`.
|
|
52
|
-
- `direction` 으로 양방향을 한 구조에 담는다. 기존 Cross-Repo Carry 의 세 서브섹션은 `downstream-carry` 행으로 흡수: `Preconditions already covered by this run` → `verificationSignal`(상대가 확인할 신호), `Work for <repo> to implement` → `requiredWork`, `How to start <repo>'s run` → `howToStart`.
|
|
53
|
-
|
|
54
|
-
### 3.2 렌더 (template + i18n)
|
|
55
|
-
|
|
56
|
-
`templates/reports/final-report.template.md` 의 §5.4 블록에서 `### Dependency / Migration Risk`([template:208](../../../templates/reports/final-report.template.md:208)) **바로 뒤**에 새 서브섹션 `### Cross-Project Dependencies` 를 추가한다.
|
|
57
|
-
|
|
58
|
-
- **엔트리별 블록** 렌더(Option Candidates 방식). 7열 표는 가독성이 떨어지므로 표를 쓰지 않는다:
|
|
59
|
-
```
|
|
60
|
-
**XP-001 — [upstream-precondition] @fonts-ninja-org/common-api**
|
|
61
|
-
- Required work: Font.d.ts 에 isSlanted 컬럼 추가 후 publish (≥ 1.27.46)
|
|
62
|
-
- Verification signal: npm view … → ≥ 1.27.46 AND isSlanted present
|
|
63
|
-
- Gated work in this plan: Stage 2 yarn install / Stage 3 compile — 신호 충족 전 진행 불가
|
|
64
|
-
- How to start: common-api repo 에서 okstra-brief … → okstra-run
|
|
65
|
-
```
|
|
66
|
-
- `crossProjectDependencies` 가 비면 단일 empty-state 라인(`- 해당 없음.` / 영어 i18n) 을 렌더한다 — 단일 프로젝트 계획은 항상 이 줄이 보인다.
|
|
67
|
-
- i18n: `templates/reports/i18n/{ko,en}.json` 에 섹션 헤딩 aside, 라벨(Required work / Verification signal / Linked work / How to start), empty-state 문자열 추가.
|
|
68
|
-
- 방향 라벨(`[upstream-precondition]` / `[downstream-carry]`)은 reader 가 선행/후속을 한눈에 구분하도록 블록 제목에 박는다.
|
|
69
|
-
|
|
70
|
-
### 3.3 강제 (validator) — 두 겹
|
|
71
|
-
|
|
72
|
-
**(a) 모양 규칙 — watertight, JSON 스키마가 강제**
|
|
73
|
-
`crossProjectDependencies` 가 비어있지 않으면 모든 행의 7개 필드가 minLength 1 을 만족해야 한다. `requiredWork`/`verificationSignal`/`howToStart` 가 비면 스키마 검증 실패 → **"구체 작업 명시"가 빈말이 될 수 없다.** `validate-run.py` 의 data.json 스키마 검증 경로([validate-run.py:1440](../../../validators/validate-run.py:1440))에서 자동 적용.
|
|
74
|
-
|
|
75
|
-
**(b) 존재 규칙 — trigger, `validate-run.py` 교차 필드 검사**
|
|
76
|
-
- DM `kind` enum 에 새 값 **`cross-project`** 추가(pre-1.0, enum 확장 자유). 의미: 다른 프로젝트/repo/패키지에 대한 의존. 기존 `repo-sequencing`(repo-내부)·`flag-precondition`(repo-내 플래그)과 명확히 구분.
|
|
77
|
-
- `validate-run.py` 에 교차 필드 규칙 신설: **data.json 에 `dependencyMigrationRisk` 행 중 `kind == cross-project` 가 하나라도 있으면 `crossProjectDependencies` 는 비어있으면 안 되고, `direction == upstream-precondition` 행이 ≥ 1 이어야 한다.** 위반 시 `contract-violated`.
|
|
78
|
-
- 이 규칙이 **"추천 → 선행 필수" 격상의 강제 지점**이다. 프로파일이 "타 repo/패키지 의존은 반드시 DM `cross-project` 행 + 매칭 XP 행으로 기록"을 지시하고, 검증기가 1:1 을 강제한다(allowlist 방식).
|
|
79
|
-
|
|
80
|
-
**(c) 섹션 헤딩 contract**
|
|
81
|
-
`implementation-planning.md` 섹션 헤딩 contract([implementation-planning.md:57](../../../prompts/profiles/implementation-planning.md:57))의 필수 substring 목록에 `Cross-Project Dependencies` 를 추가. 템플릿이 이 헤딩을 무조건 렌더하므로(empty-state 포함) substring 검사를 통과한다.
|
|
82
|
-
|
|
83
|
-
### 3.4 프로파일 prose (`prompts/profiles/implementation-planning.md`)
|
|
84
|
-
|
|
85
|
-
- 기존 Cross-Repo Carry 부록 블록(94–98)을 **새 구조 필드 참조로 재작성**하고 **양방향**(upstream-precondition / downstream-carry)을 커버하도록 바꾼다. "Recognition caveat"(상대 run 의 독립성) 문구는 섹션 하단 고정 노트(i18n)로 유지.
|
|
86
|
-
- "Required deliverable shape" 에 `crossProjectDependencies` 항목 추가: 타 프로젝트 의존은 DM `cross-project` 행 + 매칭 XP 행(구체 `requiredWork`·`verificationSignal`·`howToStart`) 으로 기록할 것.
|
|
87
|
-
- self-review 패스([implementation-planning.md:122](../../../prompts/profiles/implementation-planning.md:122))에 점검 추가: "타 repo/패키지 의존을 빠뜨리지 않았는가; DM `cross-project` ↔ XP 행 1:1 이 맞는가; `requiredWork` 가 구체적인가".
|
|
88
|
-
- §5.5.9 Plan Body Verification 의 adversarial 라운드 대상에 cross-project precondition 누락 점검을 포함.
|
|
89
|
-
- `recommendedNextSteps` 의 cross-project 항목 정책: **substance 는 새 섹션에, §3 는 포인터만**(이중 기록 방지). report-writer 가이드(`prompts/lead/report-writer.md:284` 인근)도 동기화.
|
|
90
|
-
|
|
91
|
-
### 3.5 스키마 excerpt / 빌드 흐름
|
|
92
|
-
|
|
93
|
-
- per-task-type 스키마 excerpt 빌더(`scripts/okstra_ctl/schema_excerpt.py`, `final_report_schema.py`)가 `implementationPlanning` 블록과 그 `$defs` 를 자동 포함하는지 확인한다. 새 `$defs/CrossProjectDependency` 가 implementation-planning excerpt 에 반드시 들어가야 report-writer 가 올바른 shape 로 authoring 한다.
|
|
94
|
-
- `runtime/` 은 빌드 출력이므로 직접 수정 금지 — 소스(`schemas/`, `templates/`, `prompts/`, `validators/`, `agents/`) 수정 후 `npm run build` 로 동기화.
|
|
95
|
-
|
|
96
|
-
## 4. 변경 파일 목록
|
|
97
|
-
|
|
98
|
-
| 파일 | 변경 |
|
|
99
|
-
|---|---|
|
|
100
|
-
| `schemas/final-report-v1.0.schema.json` | `$defs/CrossProjectDependency` 신설; `implementationPlanning.crossProjectDependencies` 추가; DM `kind` enum 에 `cross-project` 추가 |
|
|
101
|
-
| `templates/reports/final-report.template.md` | §5.4 에 `### Cross-Project Dependencies` 엔트리별 블록 + empty-state |
|
|
102
|
-
| `templates/reports/i18n/ko.json`, `en.json` | 섹션 헤딩 aside·필드 라벨·empty-state·recognition-caveat 문자열 |
|
|
103
|
-
| `prompts/profiles/implementation-planning.md` | Cross-Repo Carry 재작성(양방향), deliverable shape·self-review·heading contract·recommendedNextSteps 정책 갱신 |
|
|
104
|
-
| `prompts/lead/report-writer.md` | recommendedNextSteps cross-project 포인터 정책 동기화 |
|
|
105
|
-
| `validators/validate-run.py` | DM `cross-project` ↔ `crossProjectDependencies` 교차 필드 규칙 |
|
|
106
|
-
| `agents/workers/report-writer-worker.md` | 필요 시 새 섹션 authoring 안내(스키마 excerpt 가 주도하므로 최소) |
|
|
107
|
-
| `tests/` | 아래 §6 검증 계획 |
|
|
108
|
-
|
|
109
|
-
## 5. 강제 지점 매핑 (MUST → 어디서 강제되나)
|
|
110
|
-
|
|
111
|
-
| 규칙 | 강제 지점 |
|
|
112
|
-
|---|---|
|
|
113
|
-
| XP 행의 7필드 비-빈 (구체 작업 명시) | JSON 스키마 `required` + minLength → `validate-run.py` 스키마 검증 |
|
|
114
|
-
| DM `cross-project` 있으면 XP `upstream-precondition` ≥ 1 | `validate-run.py` 신설 교차 필드 검사 |
|
|
115
|
-
| 섹션 헤딩 `Cross-Project Dependencies` 존재 | `validate-run.py` substring 검사 + 템플릿 무조건 렌더 |
|
|
116
|
-
| report-writer 가 올바른 shape authoring | implementation-planning 스키마 excerpt 에 포함 |
|
|
117
|
-
|
|
118
|
-
## 6. 검증 계획 (추가할 테스트)
|
|
119
|
-
|
|
120
|
-
- `tests/report/test_render_final_report.py`: `implementation-planning` 픽스처에 `crossProjectDependencies`(upstream·downstream 각 1행) 추가 → 렌더 결과에 블록·라벨·방향 태그가 나오는지; 빈 배열 → empty-state 라인이 나오는지.
|
|
121
|
-
- `tests/contract/` (또는 validate-run 테스트): DM `cross-project` 행이 있는데 `crossProjectDependencies` 가 비면 `contract-violated` 인지; XP 행에 `requiredWork` 빈 값이면 스키마 검증 실패인지.
|
|
122
|
-
- `tests/fixtures/final-report-data/implementation-planning-001.data.json`: 새 필드 반영(빈 배열로 최소 변경하거나 샘플 1행 추가).
|
|
123
|
-
- 완료 게이트: `npm run check` 가 그대로 exit 0.
|
|
124
|
-
|
|
125
|
-
## 7. 한계 / 미해결
|
|
126
|
-
|
|
127
|
-
- **존재 규칙의 trigger 는 planner 가 DM `cross-project` 를 찍어야 발동**한다. cross-project 의존을 DM 에 전혀 기록하지 않으면 검증기가 잡지 못한다(완전 watertight 불가). 이를 줄이기 위해 프로파일 self-review + §5.5.9 adversarial verification 이 누락을 잡도록 prose 로 보강한다(휴리스틱, 강제 아님 — 이 한계를 spec 에 명시).
|
|
128
|
-
- 자유 텍스트(`recommendedNextSteps`)에서 cross-project 신호를 토큰 매칭으로 자동 검출하지 않는다(오탐 위험). 구조 신호(DM `cross-project`)만을 강제 앵커로 쓴다.
|
|
129
|
-
- 런타임 자동 신호 확인(예: npm 버전 publish 여부)은 본 설계 범위 밖(비목표).
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
# Decision Drafts — implementation-planning 잠복 렌더 갭 해소 설계
|
|
2
|
-
|
|
3
|
-
- 작성일: 2026-06-24
|
|
4
|
-
- 대상 phase: `implementation-planning`
|
|
5
|
-
- 상태: 설계 승인 완료 (구현 계획 작성 대기)
|
|
6
|
-
- 선행 참조: [2026-06-24-cross-project-precondition-design.md](2026-06-24-cross-project-precondition-design.md) — 동일 종류 갭을 같은 패턴으로 해소한 직전 사례
|
|
7
|
-
|
|
8
|
-
## 1. 배경과 문제
|
|
9
|
-
|
|
10
|
-
`implementation-planning` 보고서는 `data.json`(SSOT) → Jinja 템플릿([final-report.template.md](../../../templates/reports/final-report.template.md))으로 **결정론적 렌더**된다. report-writer 는 마크다운을 직접 쓰지 못한다([report-writer-worker.md:27](../../../agents/workers/report-writer-worker.md:27)).
|
|
11
|
-
|
|
12
|
-
프로파일의 Decision-record evaluation 블록([implementation-planning.md:111-116](../../../prompts/profiles/implementation-planning.md:111))은 3기준(① 되돌리기 어려움 ② 맥락 없으면 의아함 ③ 실제 trade-off) 충족 시 보고서 부록 섹션 `Decision Drafts` 를 **의무화**한다:
|
|
13
|
-
|
|
14
|
-
- 각 draft 는 `## Context / ## Decision / ## Consequences / ## Alternatives Considered` 형태, `## Status: Proposed` 로 시작.
|
|
15
|
-
- 평가했으나 기준 미달인 후보는 `skipped adr-candidate: <topic> — reason: <criterion>` 한 줄로 같은 섹션 아래 기록.
|
|
16
|
-
|
|
17
|
-
그러나 이 부록은 **실제 보고서에 출력될 수 없다**:
|
|
18
|
-
|
|
19
|
-
1. 스키마([final-report-v1.0.schema.json](../../../schemas/final-report-v1.0.schema.json))에 `decisionDraft` 류 필드가 없다(`grep decisionDraft` → 0건).
|
|
20
|
-
2. 템플릿에 `Decision Drafts` 렌더 블록이 없다.
|
|
21
|
-
3. i18n·validator 어디에도 `Decision Drafts` 가 없다.
|
|
22
|
-
|
|
23
|
-
즉 cross-project(`## Cross-Repo Carry`)와 **동일 종류의 잠복 렌더 갭**이다.
|
|
24
|
-
|
|
25
|
-
### 부록이 load-bearing 인 이유
|
|
26
|
-
|
|
27
|
-
이 부록은 단순 장식이 아니다. [implementation-planning.md:116](../../../prompts/profiles/implementation-planning.md:116)은 승인된 계획의 stepwise execution 에 다음 step 을 의무화한다:
|
|
28
|
-
|
|
29
|
-
> `Create <PROJECT_ROOT>/.okstra/decisions/<NNNN>-<slug>.md from the decision draft in section X`
|
|
30
|
-
|
|
31
|
-
즉 `implementation` run 이 ADR 파일을 만들 때 **"보고서의 섹션 X 에 있는 드래프트"를 출처로 가리킨다**. 부록이 렌더되지 못하면 그 step 은 존재하지 않는 섹션을 가리키게 된다.
|
|
32
|
-
|
|
33
|
-
보고서가 staging 위치로 설계된 이유:
|
|
34
|
-
- planning 은 계획 문서만 산출하고 source edit 이 금지된다([:48](../../../prompts/profiles/implementation-planning.md:48)).
|
|
35
|
-
- ADR 은 계획이 승인(frontmatter `approved: true`)되기 전에 "Accepted" 로 커밋되면 안 된다. 보고서에 `Proposed` draft 로 staging 했다가 승인+implementation 시점에 파일로 materialize 하는 것이 **승인 게이트를 지키는 흐름**이다.
|
|
36
|
-
|
|
37
|
-
하류 소비처 확인: `.okstra/decisions/<NNNN>-<slug>.md` 경로는 [_common-contract.md:87](../../../prompts/profiles/_common-contract.md:87)·[requirements-discovery.md:60](../../../prompts/profiles/requirements-discovery.md:60)·okstra-brief 가 참조하나, "Decision Drafts **보고서 섹션**"을 소비하는 것은 오직 line 116 자기참조뿐이다.
|
|
38
|
-
|
|
39
|
-
## 2. 목표 / 비목표
|
|
40
|
-
|
|
41
|
-
### 목표
|
|
42
|
-
- Decision Drafts 를 **1급·렌더되는 구조 필드**로 승격해 잠복 렌더 갭을 해소한다.
|
|
43
|
-
- draft(생성 대상)와 skipped 후보(평가 후 의도적 드롭)를 **한 섹션 아래** 구조화한다.
|
|
44
|
-
- draft 필드를 빈말 못 하도록 스키마 레벨에서 강제한다.
|
|
45
|
-
- draft 가 선언되면 line 116 의 materialization step 이 실제 존재하도록 **검증기 게이트**를 둔다.
|
|
46
|
-
|
|
47
|
-
### 비목표
|
|
48
|
-
- **런타임 게이트 없음.** `implementation` run 진입 시 ADR 파일 존재를 자동 확인하지 않는다.
|
|
49
|
-
- **승인 차단 없음.** 계획 frontmatter `approved` 를 막지 않는다.
|
|
50
|
-
- planning phase 가 `.okstra/decisions/*.md` 파일을 직접 쓰지 않는다 — 기존 "drafts are NOT written by this phase" 규칙 유지(implementation 이 materialize).
|
|
51
|
-
- brief 의 모든 `adr-candidate:*` 평가 완료를 watertight 하게 강제하지 않는다(§7 한계 참조).
|
|
52
|
-
|
|
53
|
-
## 3. 설계
|
|
54
|
-
|
|
55
|
-
### 3.1 데이터 모델 (schema)
|
|
56
|
-
|
|
57
|
-
`implementationPlanning` 객체에 배열 두 개를 추가한다(둘 다 기본 `[]` 허용 — 평가 결과가 없는 계획은 빈 배열). 둘 다 `required` 에 넣어 report-writer 가 항상 emit 하게 한다.
|
|
58
|
-
|
|
59
|
-
새 `$defs/DecisionDraft` (cross-project 의 `CrossProjectDependency` 와 동수인 7 필드, 전부 `required`, `additionalProperties: false`):
|
|
60
|
-
|
|
61
|
-
| 필드 | 타입/제약 | 의미 |
|
|
62
|
-
|---|---|---|
|
|
63
|
-
| `number` | `^\d{4,}$` | 파일명 `<NNNN>-<slug>.md` 의 NNNN. `(max existing in .okstra/decisions/ + 1)` zero-pad ≥4 자리 |
|
|
64
|
-
| `slug` | `^[a-z0-9]+(?:-[a-z0-9]+)*$` | 파일명 slug. 보고서 서브섹션 헤딩 `#### <number>-<slug>` 에도 사용 |
|
|
65
|
-
| `status` | const `"Proposed"` | planning 시점은 항상 Proposed |
|
|
66
|
-
| `context` | string, minLength 1 | ADR Context |
|
|
67
|
-
| `decision` | string, minLength 1 | ADR Decision |
|
|
68
|
-
| `consequences` | string, minLength 1 | ADR Consequences |
|
|
69
|
-
| `alternativesConsidered` | string, minLength 1 | 기각된 대안과 사유 |
|
|
70
|
-
|
|
71
|
-
새 `$defs/SkippedAdrCandidate` (`additionalProperties: false`, 둘 다 `required`):
|
|
72
|
-
|
|
73
|
-
| 필드 | 타입/제약 | 의미 |
|
|
74
|
-
|---|---|---|
|
|
75
|
-
| `topic` | string, minLength 1 | 평가한 adr-candidate 주제 |
|
|
76
|
-
| `reason` | string, minLength 1 | 미달한 기준 (예: "되돌리기 어렵지 않음") |
|
|
77
|
-
|
|
78
|
-
`implementationPlanning.properties` 추가:
|
|
79
|
-
- `decisionDrafts`: `array of $defs/DecisionDraft`
|
|
80
|
-
- `skippedAdrCandidates`: `array of $defs/SkippedAdrCandidate`
|
|
81
|
-
|
|
82
|
-
### 3.2 렌더 (template + i18n)
|
|
83
|
-
|
|
84
|
-
`templates/reports/final-report.template.md` §5.4 에서 `### Requirement Coverage`([:252](../../../templates/reports/final-report.template.md:252)) **뒤**, `## 5.5 Stage Map`([:260](../../../templates/reports/final-report.template.md:260)) **앞**에 `### Decision Drafts` 서브섹션을 추가한다(cross-project 와 같은 §5.4 내 위치).
|
|
85
|
-
|
|
86
|
-
```
|
|
87
|
-
### Decision Drafts{aside}
|
|
88
|
-
|
|
89
|
-
{% if drafts empty and skipped empty %}
|
|
90
|
-
{{ t("emptyState.decisionDrafts") }}
|
|
91
|
-
{% else %}
|
|
92
|
-
{% for d in decisionDrafts %}
|
|
93
|
-
#### {{ d.number }}-{{ d.slug }}
|
|
94
|
-
|
|
95
|
-
- **{{ t("...status") }}:** {{ d.status }}
|
|
96
|
-
- **{{ t("...context") }}:** {{ d.context }}
|
|
97
|
-
- **{{ t("...decision") }}:** {{ d.decision }}
|
|
98
|
-
- **{{ t("...consequences") }}:** {{ d.consequences }}
|
|
99
|
-
- **{{ t("...alternativesConsidered") }}:** {{ d.alternativesConsidered }}
|
|
100
|
-
{% endfor %}
|
|
101
|
-
{% for s in skippedAdrCandidates %}
|
|
102
|
-
- skipped adr-candidate: {{ s.topic }} — reason: {{ s.reason }}
|
|
103
|
-
{% endfor %}
|
|
104
|
-
{% endif %}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
설계 결정:
|
|
108
|
-
- **헤딩 레벨**: §5.4 서브섹션은 `###` 이므로 `### Decision Drafts`, 각 draft 는 `#### <number>-<slug>`. 프로파일이 말하는 draft 의 `## Context/...`(H2)는 **파일(`.okstra/decisions/*.md`)의 형태**이고, 보고서에서는 구조 필드를 라벨 불릿으로 렌더한다. implementation step 이 이 필드를 읽어 파일을 `## Status/Context/Decision/Consequences/Alternatives Considered` 형태로 materialize 한다. 보고서에 H2 를 박으면 보고서 헤딩 계층·TOC 앵커가 깨지므로 구조-필드 렌더가 정합적이다.
|
|
109
|
-
- **skipped 라인은 고정 English 토큰** (`skipped adr-candidate:` / `reason:`) — `RED:`/`GREEN:`/`Slice value:` 처럼 greppable contract token 이고 프로파일 verbatim 이라 i18n 하지 않는다(`topic`/`reason` 값은 보고서 언어를 따른다).
|
|
110
|
-
- 무조건 렌더(empty-state 포함) → 헤딩 substring 이 항상 존재 → §3.3(c) 헤딩 contract 통과.
|
|
111
|
-
- empty-state 가 기본값: 대부분의 계획은 draft·skipped 둘 다 빈 배열이라 empty-state 한 줄만 보인다.
|
|
112
|
-
|
|
113
|
-
i18n: `templates/reports/i18n/{ko,en}.json` 에 추가
|
|
114
|
-
- `sectionAside.decisionDrafts`
|
|
115
|
-
- `emptyState.decisionDrafts`
|
|
116
|
-
- `implementationPlanning.decisionDraftFields.{status, context, decision, consequences, alternativesConsidered}`
|
|
117
|
-
|
|
118
|
-
### 3.3 강제 (validator) — 세 겹
|
|
119
|
-
|
|
120
|
-
**(a) 모양 규칙 — JSON 스키마가 강제**
|
|
121
|
-
`decisionDrafts` 가 비어있지 않으면 모든 draft 의 7 필드가 `required`+`minLength 1`+`status` const 를 만족해야 한다. `skippedAdrCandidates` 행도 `topic`/`reason` 비-빈. → "구체 내용"이 빈말이 될 수 없다. `validate-run.py` 의 data.json 스키마 검증 경로에서 자동 적용.
|
|
122
|
-
|
|
123
|
-
**(b) 자기완결 trigger — `validate-run.py` 교차 필드 검사 (신설)**
|
|
124
|
-
- 새 함수 `_validate_implementation_planning_decision_drafts(data, failures)`:
|
|
125
|
-
- `implementationPlanning.decisionDrafts` 가 비어있지 않으면, **어떤 stage 의 `stepwiseExecution` step 의 `files` 또는 `action` 이 `.okstra/decisions/` 를 참조**해야 한다.
|
|
126
|
-
- 위반 시 `failures.append(...)` → `contract-violated`.
|
|
127
|
-
- 이것이 line 116 의 "approved plan's stepwise execution MUST include `Create .okstra/decisions/<NNNN>-<slug>.md ...`" 를 **실제 강제 지점으로 승격**한다. cross-project 의 trigger(planner 가 DM `cross-project` 를 수동으로 찍어야 발동)와 달리, 이 검사는 draft 존재 자체가 trigger 이므로 **self-contained·watertight** 하다.
|
|
128
|
-
- CLAUDE.md 의 "MUST/BLOCKING 은 강제 지점을 명시해야 한다" 규칙을 충족한다.
|
|
129
|
-
|
|
130
|
-
**(c) 섹션 헤딩 contract**
|
|
131
|
-
`validate-run.py` 의 `PLANNING_REQUIRED_SECTIONS`([:1132](../../../validators/validate-run.py:1132))에 `"Decision Drafts"` 를 추가. 템플릿이 이 헤딩을 무조건 렌더하므로(empty-state 포함) substring 검사를 통과한다.
|
|
132
|
-
|
|
133
|
-
### 3.4 프로파일 prose (`prompts/profiles/implementation-planning.md`)
|
|
134
|
-
|
|
135
|
-
- Decision-record evaluation 블록(111–116)의 "attach a decision draft as a report appendix section titled `Decision Drafts`" 와 "record `skipped adr-candidate: ...` one line under `Decision Drafts`" 를 **구조 필드 참조로 재작성**한다:
|
|
136
|
-
- draft 는 `decisionDrafts` 배열(필드: number/slug/status/context/decision/consequences/alternativesConsidered)로 기록 → §5.4 `### Decision Drafts` 에 렌더.
|
|
137
|
-
- skipped 후보는 `skippedAdrCandidates` 배열(topic/reason)로 기록.
|
|
138
|
-
- line 116 의 materialization step 의무는 유지하되, "from the decision draft in section X" 가 §5.4 `### Decision Drafts` 의 `#### <number>-<slug>` 서브섹션을 가리킴을 명시. 파일은 그 구조 필드를 `## Status/Context/Decision/Consequences/Alternatives Considered` 형태로 materialize.
|
|
139
|
-
- 섹션 헤딩 contract(line 57) 필수 substring 목록에 `Decision Drafts` 추가.
|
|
140
|
-
- self-review 패스([:123](../../../prompts/profiles/implementation-planning.md:123))에 점검 추가: "`decisionDrafts` 가 비어있지 않으면 매칭 materialization step(`.okstra/decisions/` 생성)이 어느 stage 의 stepwise 에 있는가 — validator (b) 가 잡지만 reviewer 도 확인".
|
|
141
|
-
|
|
142
|
-
### 3.5 report-writer 정합 (`agents/workers/report-writer-worker.md`)
|
|
143
|
-
|
|
144
|
-
- `implementation-planning` authoring 안내에 한 줄: `decisionDrafts`/`skippedAdrCandidates` 를 populate(없으면 `[]`). shape 는 스키마 excerpt 가 주도하므로 최소 안내.
|
|
145
|
-
|
|
146
|
-
### 3.6 스키마 excerpt / 빌드 흐름
|
|
147
|
-
|
|
148
|
-
- per-task-type 스키마 excerpt 빌더(`scripts/okstra_ctl/schema_excerpt.py`, `final_report_schema.py`)가 `implementationPlanning` 블록과 그 `$defs` 를 자동 포함하는지 확인한다. 새 `$defs/DecisionDraft`·`SkippedAdrCandidate` 가 `$ref` 로 도달 가능하므로 excerpt 에 자동 포함되어야 한다(`tests/report/test_schema_excerpt.py` 로 회귀 확인).
|
|
149
|
-
- `runtime/` 은 빌드 출력이므로 직접 수정 금지 — 소스 수정 후 `npm run build` 로 동기화.
|
|
150
|
-
|
|
151
|
-
## 4. 변경 파일 목록
|
|
152
|
-
|
|
153
|
-
| 파일 | 변경 |
|
|
154
|
-
|---|---|
|
|
155
|
-
| `schemas/final-report-v1.0.schema.json` | `$defs/DecisionDraft`·`$defs/SkippedAdrCandidate` 신설; `implementationPlanning` 에 `decisionDrafts`·`skippedAdrCandidates` 추가(properties + required) |
|
|
156
|
-
| `templates/reports/final-report.template.md` | §5.4 에 `### Decision Drafts` 블록(draft 서브섹션 + skipped 라인 + empty-state) |
|
|
157
|
-
| `templates/reports/i18n/ko.json`, `en.json` | 섹션 aside·필드 라벨·empty-state 문자열 |
|
|
158
|
-
| `prompts/profiles/implementation-planning.md` | Decision-record evaluation 재작성(구조 필드 참조); heading contract·self-review 갱신 |
|
|
159
|
-
| `agents/workers/report-writer-worker.md` | decisionDrafts/skippedAdrCandidates populate 안내 1줄 |
|
|
160
|
-
| `validators/validate-run.py` | `PLANNING_REQUIRED_SECTIONS` 에 `Decision Drafts` 추가; `_validate_implementation_planning_decision_drafts` 신설 + 호출 배선 |
|
|
161
|
-
| `tests/` + `tests/fixtures/` | 아래 §6 검증 계획 |
|
|
162
|
-
|
|
163
|
-
## 5. 강제 지점 매핑 (MUST → 어디서 강제되나)
|
|
164
|
-
|
|
165
|
-
| 규칙 | 강제 지점 |
|
|
166
|
-
|---|---|
|
|
167
|
-
| draft 7 필드 비-빈 + status const | JSON 스키마 `required`+`minLength`+`const` → `validate-run.py` 스키마 검증 |
|
|
168
|
-
| skipped 행 topic/reason 비-빈 | JSON 스키마 `required`+`minLength` |
|
|
169
|
-
| draft 있으면 `.okstra/decisions/` materialization step 존재 | `validate-run.py` `_validate_implementation_planning_decision_drafts` (신설, self-contained) |
|
|
170
|
-
| 섹션 헤딩 `Decision Drafts` 존재 | `validate-run.py` `PLANNING_REQUIRED_SECTIONS` substring + 템플릿 무조건 렌더 |
|
|
171
|
-
| report-writer 가 올바른 shape authoring | implementation-planning 스키마 excerpt 에 포함 |
|
|
172
|
-
|
|
173
|
-
## 6. 검증 계획 (추가할 테스트)
|
|
174
|
-
|
|
175
|
-
- `tests/report/test_render_final_report.py`: `implementation-planning` 픽스처에 `decisionDrafts`(1행)·`skippedAdrCandidates`(1행) 추가 → 렌더 결과에 `#### <number>-<slug>` 서브섹션, Status/Context/Decision/Consequences/Alternatives Considered 라벨, `skipped adr-candidate: ... — reason: ...` 라인이 나오는지; 빈 배열 둘 → empty-state 라인이 나오는지.
|
|
176
|
-
- `tests/contract/` (또는 validate-run 테스트): `decisionDrafts` 가 비어있지 않은데 어느 stage 의 stepwise 도 `.okstra/decisions/` 를 참조하지 않으면 `contract-violated` 인지; draft 의 `context` 빈 값이면 스키마 검증 실패인지; materialization step 이 있으면 통과인지.
|
|
177
|
-
- `tests/report/test_schema_excerpt.py`: implementation-planning excerpt 에 새 `$defs` 가 포함되는지.
|
|
178
|
-
- **모든 implementation-planning 픽스처**(`tests/fixtures/final-report-data/implementation-planning-001.data.json` + 테스트 내 인라인 픽스처)에 `decisionDrafts`·`skippedAdrCandidates`(최소 `[]`) 추가 — `required` 승격으로 기존 테스트가 깨지지 않게.
|
|
179
|
-
- 완료 게이트: `npm run check` 가 그대로 exit 0.
|
|
180
|
-
|
|
181
|
-
## 7. 한계 / 미해결
|
|
182
|
-
|
|
183
|
-
- **완전성(모든 adr-candidate 평가) 강제 불가**: "brief 의 모든 `adr-candidate:*` 를 draft 또는 skipped 로 처리했는가"는 brief 외부 입력과의 대조가 필요해 data.json 자기완결 검사로 watertight 하게 잡을 수 없다. 프로파일 self-review + §5.5.9 adversarial verification 휴리스틱으로만 보강한다(강제 아님 — cross-project spec §7 과 동일 종류 한계).
|
|
184
|
-
- **materialization step 의 정확성은 검사 안 함**: validator (b) 는 `.okstra/decisions/` 참조 step 의 *존재*만 본다. 그 step 이 올바른 `<NNNN>-<slug>` 를 가리키는지·draft 개수와 step 개수가 1:1 인지까지는 강제하지 않는다(self-review 책임).
|
|
185
|
-
- **planning 이 파일을 직접 쓰지 않음 유지**: 승인 게이트 보존을 위해 draft 는 보고서 staging 에만 두고, 실제 `.okstra/decisions/*.md` 생성은 implementation run 이 한다.
|