okstra 0.102.2 → 0.102.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/README.kr.md +5 -5
  2. package/README.md +5 -5
  3. package/docs/kr/architecture/storage-model.md +1 -1
  4. package/docs/kr/architecture.md +7 -11
  5. package/docs/kr/cli.md +4 -4
  6. package/docs/kr/container.md +1 -1
  7. package/docs/kr/performance-improvement-plan-v2.md +2 -2
  8. package/docs/project-structure-overview.md +2 -2
  9. package/package.json +7 -2
  10. package/runtime/BUILD.json +2 -2
  11. package/runtime/bin/okstra-antigravity-exec.sh +1 -2
  12. package/runtime/bin/okstra-codex-exec.sh +1 -2
  13. package/runtime/bin/okstra-render-final-report.py +2 -9
  14. package/runtime/bin/okstra-spawn-followups.py +4 -6
  15. package/runtime/bin/okstra-trace-cleanup.sh +24 -4
  16. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  17. package/runtime/prompts/lead/report-writer.md +1 -1
  18. package/runtime/prompts/profiles/_common-contract.md +9 -11
  19. package/runtime/python/okstra_ctl/codex_dispatch.py +4 -12
  20. package/runtime/python/okstra_ctl/consumers.py +35 -0
  21. package/runtime/python/okstra_ctl/container.py +4 -6
  22. package/runtime/python/okstra_ctl/dispatch_core.py +4 -12
  23. package/runtime/python/okstra_ctl/final_report_paths.py +24 -0
  24. package/runtime/python/okstra_ctl/handoff.py +2 -1
  25. package/runtime/python/okstra_ctl/implementation_stage.py +7 -11
  26. package/runtime/python/okstra_ctl/report_view_artifacts.py +14 -0
  27. package/runtime/python/okstra_ctl/report_views.py +7 -4
  28. package/runtime/python/okstra_ctl/run.py +3 -10
  29. package/runtime/python/okstra_ctl/stage_targets.py +18 -0
  30. package/runtime/python/okstra_ctl/wizard.py +24 -25
  31. package/runtime/python/okstra_ctl/wizard_stage_intent.py +54 -0
  32. package/runtime/python/okstra_token_usage/report.py +2 -5
  33. package/runtime/validators/validate-report-views.py +2 -1
  34. package/runtime/validators/validate-run.py +1 -11
  35. package/src/commands/lifecycle/install.mjs +5 -5
  36. package/src/commands/lifecycle/uninstall.mjs +4 -4
  37. package/docs/superpowers/plans/2026-05-12-ticket-id-in-reports.md +0 -638
  38. package/docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md +0 -1568
  39. package/docs/superpowers/plans/2026-05-17-dual-format-final-report.md +0 -167
  40. package/docs/superpowers/plans/2026-05-20-final-report-language.md +0 -1501
  41. package/docs/superpowers/plans/2026-05-20-implementation-planning-multi-stage.md +0 -1267
  42. package/docs/superpowers/plans/2026-05-20-okstra-run-prompt-sot-b1.md +0 -1007
  43. package/docs/superpowers/plans/2026-05-20-wizard-messages-json-sot.md +0 -720
  44. package/docs/superpowers/plans/2026-05-20-wizard-prompt-json-sot-a1.md +0 -681
  45. package/docs/superpowers/plans/2026-05-21-improvement-discovery-task-type.md +0 -1691
  46. package/docs/superpowers/plans/2026-05-24-implementation-lead-context-slimming.md +0 -1700
  47. package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +0 -158
  48. package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +0 -860
  49. package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +0 -326
  50. package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +0 -337
  51. package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +0 -410
  52. package/docs/superpowers/plans/2026-06-02-requirements-discovery-fanout.md +0 -728
  53. package/docs/superpowers/plans/2026-06-04-adversarial-implementation-planning.md +0 -294
  54. package/docs/superpowers/plans/2026-06-04-adversarial-verification.md +0 -570
  55. package/docs/superpowers/plans/2026-06-04-coverage-critic.md +0 -516
  56. package/docs/superpowers/plans/2026-06-04-stage-cohesion-planner.md +0 -351
  57. package/docs/superpowers/plans/2026-06-04-stage-run-batching.md +0 -457
  58. package/docs/superpowers/plans/2026-06-05-acceptance-critic.md +0 -251
  59. package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +0 -323
  60. package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +0 -559
  61. package/docs/superpowers/plans/2026-06-06-final-verification-whole-task-gate.md +0 -993
  62. package/docs/superpowers/plans/2026-06-06-stage-parallel-and-pending-fixes.md +0 -93
  63. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p1.md +0 -447
  64. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p2.md +0 -289
  65. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p3.md +0 -774
  66. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p4.md +0 -303
  67. package/docs/superpowers/plans/2026-06-06-stage-worktree-isolation-p5-multidep-base.md +0 -387
  68. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase2.md +0 -275
  69. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase3.md +0 -282
  70. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4a.md +0 -147
  71. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4b.md +0 -262
  72. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4c.md +0 -184
  73. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4d.md +0 -88
  74. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa-phase4e.md +0 -250
  75. package/docs/superpowers/plans/2026-06-07-stage-conformance-qa.md +0 -409
  76. package/docs/superpowers/plans/2026-06-09-implementation-run-artifact-stage-isolation.md +0 -320
  77. package/docs/superpowers/plans/2026-06-10-concurrent-run-team-guard.md +0 -456
  78. package/docs/superpowers/plans/2026-06-10-git-reconcile-stale-sha-recovery.md +0 -1408
  79. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling-PROBE.md +0 -42
  80. package/docs/superpowers/plans/2026-06-10-lead-worker-completion-polling.md +0 -337
  81. package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +0 -1029
  82. package/docs/superpowers/plans/2026-06-10-stage-group-handoff.md +0 -1572
  83. package/docs/superpowers/plans/2026-06-11-fix-cycle.md +0 -1290
  84. package/docs/superpowers/plans/2026-06-11-wizard-whole-task-final-verification.md +0 -526
  85. package/docs/superpowers/plans/2026-06-12-html-plan-approval.md +0 -1000
  86. package/docs/superpowers/plans/2026-06-13-repo-risk-hardening.md +0 -493
  87. package/docs/superpowers/plans/2026-06-14-host-runtime-auto-execution.md +0 -1775
  88. package/docs/superpowers/plans/2026-06-15-coding-preflight-pack-dispatch-path.md +0 -504
  89. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-final-fixups.md +0 -342
  90. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-fixups.md +0 -258
  91. package/docs/superpowers/plans/2026-06-15-internal-skill-migration-remaining-fixups.md +0 -387
  92. package/docs/superpowers/plans/2026-06-15-internal-skill-resource-migration.md +0 -749
  93. package/docs/superpowers/plans/2026-06-15-worker-prompt-anchor-final-fixups.md +0 -828
  94. package/docs/superpowers/plans/2026-06-15-worker-prompt-header-error-contract.md +0 -490
  95. package/docs/superpowers/plans/2026-06-17-okstra-error-report.md +0 -724
  96. package/docs/superpowers/plans/2026-06-18-subagent-pane-reclaim.md +0 -483
  97. package/docs/superpowers/plans/2026-06-19-agent-operating-standard.md +0 -476
  98. package/docs/superpowers/plans/2026-06-19-okstra-inspect-recap-facet.md +0 -647
  99. package/docs/superpowers/plans/2026-06-20-error-feedback-loop.md +0 -1019
  100. package/docs/superpowers/plans/2026-06-20-run-index-row-normalization.md +0 -583
  101. package/docs/superpowers/plans/2026-06-20-stage-auto-integrate-teardown.md +0 -819
  102. package/docs/superpowers/plans/2026-06-21-okstra-container-local-user-test.md +0 -714
  103. package/docs/superpowers/plans/2026-06-21-release-handoff-local-checkout.md +0 -348
  104. package/docs/superpowers/plans/2026-06-23-implementation-stage-multiselect-chain.md +0 -630
  105. package/docs/superpowers/plans/2026-06-23-implementation-step-commit-granularity.md +0 -274
  106. package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +0 -409
  107. package/docs/superpowers/plans/2026-06-24-cross-project-precondition.md +0 -542
  108. package/docs/superpowers/plans/2026-06-24-decision-drafts-render-gap.md +0 -568
  109. package/docs/superpowers/plans/2026-06-24-manual-user-test-section.md +0 -203
  110. package/docs/superpowers/plans/2026-06-24-okstra-container-build-rename.md +0 -525
  111. package/docs/superpowers/specs/2026-05-12-ticket-id-in-reports-design.md +0 -131
  112. package/docs/superpowers/specs/2026-05-15-implementation-plan-verification-design.md +0 -254
  113. package/docs/superpowers/specs/2026-05-20-final-report-language-design.md +0 -383
  114. package/docs/superpowers/specs/2026-05-20-implementation-planning-multi-stage-design.md +0 -322
  115. package/docs/superpowers/specs/2026-05-20-okstra-run-prompt-sot-design.md +0 -299
  116. package/docs/superpowers/specs/2026-05-21-improvement-discovery-task-type-design.md +0 -335
  117. package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +0 -113
  118. package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +0 -173
  119. package/docs/superpowers/specs/2026-06-02-requirements-discovery-fanout-design.md +0 -154
  120. package/docs/superpowers/specs/2026-06-04-adversarial-implementation-planning-design.md +0 -90
  121. package/docs/superpowers/specs/2026-06-04-adversarial-verification-design.md +0 -176
  122. package/docs/superpowers/specs/2026-06-04-coverage-critic-design.md +0 -99
  123. package/docs/superpowers/specs/2026-06-04-stage-splitting-cost-aware-design.md +0 -98
  124. package/docs/superpowers/specs/2026-06-05-acceptance-critic-design.md +0 -90
  125. package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +0 -87
  126. package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +0 -121
  127. package/docs/superpowers/specs/2026-06-06-final-verification-whole-task-gate-design.md +0 -126
  128. package/docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md +0 -180
  129. package/docs/superpowers/specs/2026-06-06-vertical-slice-tdd-planning-design.md +0 -179
  130. package/docs/superpowers/specs/2026-06-07-stage-conformance-qa-design.md +0 -169
  131. package/docs/superpowers/specs/2026-06-09-executor-model-custom-id-cascade-design.md +0 -66
  132. package/docs/superpowers/specs/2026-06-09-implementation-run-artifact-stage-isolation-design.md +0 -87
  133. package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +0 -168
  134. package/docs/superpowers/specs/2026-06-10-concurrent-run-team-guard-design.md +0 -107
  135. package/docs/superpowers/specs/2026-06-10-git-reconcile-stale-sha-recovery-design.md +0 -105
  136. package/docs/superpowers/specs/2026-06-10-lead-worker-completion-polling-design.md +0 -113
  137. package/docs/superpowers/specs/2026-06-10-stage-group-handoff-design.md +0 -156
  138. package/docs/superpowers/specs/2026-06-11-brief-entry-only-handoff-stage-entry-design.md +0 -158
  139. package/docs/superpowers/specs/2026-06-11-fix-cycle-design.md +0 -94
  140. package/docs/superpowers/specs/2026-06-11-wizard-whole-task-final-verification-design.md +0 -89
  141. package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +0 -358
  142. package/docs/superpowers/specs/2026-06-12-html-plan-approval-design.md +0 -85
  143. package/docs/superpowers/specs/2026-06-12-stage-discipline-rule-design.md +0 -108
  144. package/docs/superpowers/specs/2026-06-13-forbidden-actions-ssot-design.md +0 -134
  145. package/docs/superpowers/specs/2026-06-13-neutral-tmux-lead-adapter-design.md +0 -284
  146. package/docs/superpowers/specs/2026-06-14-host-runtime-auto-execution-design.md +0 -404
  147. package/docs/superpowers/specs/2026-06-17-okstra-error-report-design.md +0 -123
  148. package/docs/superpowers/specs/2026-06-18-subagent-pane-reclaim-design.md +0 -150
  149. package/docs/superpowers/specs/2026-06-19-agent-operating-standard-design.md +0 -120
  150. package/docs/superpowers/specs/2026-06-19-okstra-inspect-recap-facet-design.md +0 -96
  151. package/docs/superpowers/specs/2026-06-20-error-feedback-loop-design.md +0 -171
  152. package/docs/superpowers/specs/2026-06-20-run-index-row-normalization-design.md +0 -112
  153. package/docs/superpowers/specs/2026-06-20-stage-auto-integrate-teardown-design.md +0 -145
  154. package/docs/superpowers/specs/2026-06-21-okstra-container-local-user-test-design.md +0 -125
  155. package/docs/superpowers/specs/2026-06-21-release-handoff-local-checkout-design.md +0 -113
  156. package/docs/superpowers/specs/2026-06-23-implementation-stage-multiselect-chain-design.md +0 -138
  157. package/docs/superpowers/specs/2026-06-23-implementation-step-commit-granularity-design.md +0 -120
  158. package/docs/superpowers/specs/2026-06-24-cross-project-precondition-design.md +0 -129
  159. package/docs/superpowers/specs/2026-06-24-decision-drafts-render-gap-design.md +0 -185
  160. package/docs/superpowers/specs/2026-06-24-manual-user-test-section-design.md +0 -121
  161. package/docs/superpowers/specs/2026-06-24-okstra-container-build-rename-design.md +0 -110
@@ -1,154 +0,0 @@
1
- # requirements-discovery 도메인 fan-out 설계
2
-
3
- > 작성: 2026-06-02 · 갱신: 2026-06-02 (packet 모델로 교정) · 상태: 설계 승인됨
4
-
5
- ## 1. 배경 / 문제
6
-
7
- 현재 `requirements-discovery` 는 **단일 작업 요청 → 단일 분류 → 단일 라우팅** 모델이다
8
- ([prompts/profiles/requirements-discovery.md](../../../prompts/profiles/requirements-discovery.md)).
9
- 하나의 요청 안에 버그 수정·개선·신규 구현이 **혼합**돼 있어도 한 덩어리로 흘러가므로,
10
- 다운스트림(error-analysis / implementation-planning / implementation)에서 성격이 다른
11
- 일이 섞인 채 진행된다.
12
-
13
- 목표: 혼합 요청을 **도메인별로 분리해 독립적인 작업 단위로 fan-out** 한다. 그래야
14
- ① 할 일이 도메인별로 분명히 구분되고 ② 착수 순서를 쉽게 정할 수 있으며 ③ 단위별로
15
- 독립 실행·추적이 된다.
16
-
17
- ## 2. 용어 / 경계 (중요 — 이전 초안의 혼동 교정)
18
-
19
- - **packet = run 의 입력 파일.** `okstra-run` 은 `--task-brief <path>` 로 입력 파일을
20
- 받아 `instruction-set/task-brief.md` 로 복사해 phase 에 전달한다
21
- ([scripts/okstra_ctl/run.py:1143](../../../scripts/okstra_ctl/run.py),
22
- [run.py:912](../../../scripts/okstra_ctl/run.py)). 이 파일은 **임의의 markdown** 이면
23
- 되고, `okstra-brief` 가 만들든 손으로 만들든 okstra-run 은 상관하지 않는다.
24
- - **okstra-brief 는 이 설계와 무관하다.** 외부 소스 → packet 을 만들어 주는 *선택적·별개*
25
- 준비 도구일 뿐이다. fan-out 은 okstra-brief 를 **호출하지 않는다**.
26
- - **fan-out 은 okstra-run 내부에서 완결되는 루프**다: requirements-discovery 가 packet 을
27
- 만들고, 그 packet 을 다시 okstra-run 이 `--task-brief` 로 먹는다.
28
-
29
- > 이전 초안이 산출물을 `.okstra/briefs/` 의 "child brief" 로 둔 것은 okstra-brief 와
30
- > 산출물·소유권이 겹치는 오류였다. 이번 설계의 산출물은 brief 가 아니라 **packet** 이고,
31
- > 별도 템플릿·별도 저장 위치를 쓴다.
32
-
33
- ## 3. 핵심 결정 (brainstorming 합의)
34
-
35
- | # | 결정 | 값 |
36
- |---|---|---|
37
- | 분할 지점 | lifecycle 어디서 | **requirements-discovery** (okstra-run 안에서 실행) |
38
- | 도메인 축 | 무엇으로 나누나 | **기존 work-category 5-enum** (`bugfix / feature / refactor / ops / improvement`) |
39
- | 산출물 | 각 단위가 내놓는 것 | **작업 항목당 packet 파일** (도메인 태그) → 새 task-key 로 fan-out |
40
- | 입도 | packet 끊는 단위 | **작업 항목당 packet 1개** |
41
- | 트리거 | 실행 주체 | **packet + 추천순서만 생성, 실행은 별도** (사람이 게이트, forbidden 규칙 준수) |
42
- | 묶음/순서 | 의존·순서 표현 | **run 산출 영역의 fan-out 디렉토리 + index** |
43
- | 다운스트림 다리 | packet → run | **`okstra-run --task-brief <packet 경로>`** (okstra-brief 미개입) |
44
-
45
- ## 4. 동작
46
-
47
- ### 4.1 트리거 & 분해 (requirements-discovery 내부)
48
-
49
- 분류 후 작업이 **다항목/다도메인인지** 판정한다.
50
-
51
- - **단일 항목 / 단일 도메인** → 현행 그대로 (단일 라우팅, fan-out 없음). 기존 동작 100% 보존.
52
- - **다항목 또는 도메인 혼합** → fan-out 분기.
53
-
54
- 판정 기준(휴리스틱, 고정 규칙 아님): 분류가 2개 이상 도메인에 걸치거나, 입력에서 독립 착수
55
- 가능한 작업 항목이 2개 이상 식별될 때. 경계 케이스는 "한 단위로 묶어도 무방한가?" 로
56
- 판단하고 근거를 리포트에 1줄 기록.
57
-
58
- 분해 산출: 각 작업 항목을 `domain`(5-enum) + scope + evidence(path:line) + `depends-on`
59
- 으로 정규화. **소스 편집·해법 설계·plan 작성은 여전히 non-goal** — 분해는 "무엇을 별도
60
- 단위로 볼지" 까지만. 각 단위의 해법은 다운스트림 몫.
61
-
62
- ### 4.2 산출물 (run 산출 영역)
63
-
64
- run 산출물은 `.okstra/tasks/<task-group>/<task-id>/runs/<task-type>/` 아래 task-type 전용
65
- 서브디렉토리에 쌓인다 (선례: implementation 의 `carry/`, implementation-planning 의
66
- `consumers.jsonl`).
67
-
68
- ```
69
- .okstra/tasks/<task-group>/<task-id>/runs/requirements-discovery/
70
- └── fan-out/
71
- ├── unit-001.md ← packet (별도 템플릿, domain 태그 + depends-on)
72
- ├── unit-002.md
73
- └── index.md ← 단위 목록 + 추천 위상순서 (생성 뷰)
74
- ```
75
-
76
- packet 템플릿 — **신설** `templates/reports/fan-out-unit.template.md`. `brief.template.md`
77
- 와 **무관** (다른 템플릿·다른 홈·다른 소유자 → 중복/drift 없음). frontmatter 최소 필드:
78
-
79
- - `domain: <bugfix|feature|refactor|ops|improvement>`
80
- - `depends-on: []` — 같은 fan-out 내 다른 unit id 목록
81
- - `recommended-next-phase: <error-analysis|implementation-planning>`
82
- - packet 본문은 해당 작업 항목을 okstra-run 입력으로 쓸 수 있는 자족적 서술.
83
-
84
- **SSOT 규칙 (drift 방지):**
85
-
86
- - 각 packet 의 `domain` + `depends-on` 이 **권위 소스**.
87
- - `index.md` 는 그로부터 만든 **생성 뷰** (단위를 추천 위상순서로 나열 + 1줄 요약).
88
- "직접 편집 금지, packet 으로부터 재생성" 명시 → 두 번째 SSOT 아님.
89
- - requirements-discovery 최종 리포트는 분해 결과를 본문에 중복하지 않고
90
- "fan-out: N개 packet 생성 → `fan-out/index.md` 참조" **1줄 포인터**만 둔다.
91
-
92
- ### 4.3 순서 & 다운스트림
93
-
94
- **fan-out 시점 (task 아직 없음):**
95
-
96
- - `depends-on` 그래프로부터 **추천 착수 순서(위상정렬)** 를 계산해 `index.md` 에 기록.
97
- - **순환(cycle) 검출**: `depends-on` 이 DAG 가 아니면 위상정렬 불가 → 인덱스 생성 시
98
- 순환을 감지해 리포트에 경고 + 해당 의존을 끊도록 표시.
99
-
100
- **실행 (사람이 게이트, forbidden 규칙 준수):**
101
-
102
- - 사용자가 각 packet 을 `okstra-run --task-brief <packet 경로>` 로 시작 → 각자 같은
103
- task-group 아래 **새 task-key**.
104
- - requirements-discovery 는 다운스트림 phase 를 자기 run 에서 시작하지 않는다.
105
- - 추천 순서 준수는 사용자 재량 (인덱스는 권고).
106
-
107
- **okstra-schedule 의 역할 (제약):**
108
-
109
- - schedule 은 `task-manifest.json` 을 읽으므로 **단위가 task 로 시작된 *이후*** 에만 동작.
110
- 갓 만든 packet 은 task 가 아니라 schedule 이 직접 정렬하지 못한다.
111
- - 역할 분담: fan-out 직후~착수 전엔 `index.md` 가 순서 가이드; 여러 단위가 task 가 된 뒤엔
112
- okstra-schedule 이 task-manifest 기반 통합 일정 합성.
113
- - **schedule 을 packet(pre-task)까지 읽도록 확장하는 것은 범위 제외 (YAGNI).**
114
-
115
- ## 5. 변경 표면 & enforcement
116
-
117
- | 영역 | 파일 | 변경 |
118
- |---|---|---|
119
- | 계약 선언 | `prompts/profiles/requirements-discovery.md` | fan-out 분해 책임 추가(트리거/packet 발행/index). Non-goals 갱신: "작업 단위 분해" in-scope, 소스 편집·해법 설계·plan 작성은 여전히 non-goal |
120
- | packet 템플릿 | `templates/reports/fan-out-unit.template.md` (신설) | `domain` + `depends-on` + `recommended-next-phase` frontmatter + 본문 가이드 |
121
- | 5-enum SSOT | `scripts/okstra_ctl/work_categories.py` (신설) | 5-enum 상수 단일 정의(`improvement_lenses.py` 와 동일 위치 규약). validator 가 import. **기존 free-string `workCategory` 리팩터는 범위 제외** |
122
- | enforcement | `validators/validate_fanout.py` (신설) + `validators/validate-run.py` 훅 | `validate-run.py` 가 `task_type == "requirements-discovery"` 이고 `fan-out/` 존재 시 자동 호출 (improvement-discovery 의 `validate_improvement_report.py` 패턴 그대로). 검사: packet `domain` ∈ 5-enum, `depends-on` 이 같은 fan-out 내 resolve, DAG 순환 없음, `index.md` 의 단위 목록 == 실제 packet, 추천순서가 유효 위상순서 |
123
- | 순환검출 헬퍼 | `scripts/okstra_ctl/fanout.py` (신설) | DAG 위상정렬 + 순환검출. unit test 대상 |
124
- | 문서 | `docs/kr/architecture.md`, `CHANGES.md` | 새 흐름 / 사용자 영향(`사용자 영향:` 1줄) |
125
-
126
- > **스키마 변경 없음**: requirements-discovery 는 final-report 스키마에 전용 deliverable
127
- > 블록이 없다(`followUpTasks` 의 phase-continuation 행만 요구). fan-out 포인터를 위해 새
128
- > 스키마 구조를 만드는 건 과하다 — enforcement 는 `validate_fanout.py` 로 충분(YAGNI).
129
- > 리포트의 1줄 포인터는 프로필이 지시하는 markdown 일 뿐 스키마 필드가 아니다.
130
-
131
- **Rule 3 (선언 ≠ 강제) 매핑** — 프로필의 각 MUST 에 검증 1줄:
132
-
133
- | 프로필 선언 | 강제 위치 |
134
- |---|---|
135
- | packet 은 `domain`(5-enum)·`depends-on`·`recommended-next-phase` 를 가진다 | validate_fanout.py frontmatter 검사 |
136
- | `depends-on` 은 같은 fan-out 내 unit id 만 참조 | validate_fanout.py resolve 검사 |
137
- | 의존 그래프는 DAG | validate_fanout.py 순환검출 헬퍼 |
138
- | `index.md` 의 단위 목록 == 실제 packet | validate_fanout.py 정합성 검사 |
139
- | 단일 요청은 fan-out 하지 않음 | (음성 케이스) e2e 시나리오로 회귀 확인 |
140
-
141
- ## 6. 테스트 전략
142
-
143
- - **unit**: 순환검출/위상정렬 공유 헬퍼 · packet `domain`/`depends-on` 검증 · index 정합성.
144
- - **e2e**: `tests-e2e/scenario-<id>-requirements-discovery-fanout.sh` — 혼합 입력 →
145
- requirements-discovery → N packet + index 생성 → validate. 단일 입력 시 fan-out 하지
146
- 않음(회귀)도 같은 패밀리에서 확인.
147
-
148
- ## 7. 비목표 (이번 범위 아님)
149
-
150
- - error-analysis 등 다른 phase 의 출력 분할 (필요 시 후속).
151
- - 기존 free-string `workCategory` 사용처 전체를 5-enum SSOT 로 리팩터.
152
- - okstra-schedule 을 packet(pre-task)까지 읽도록 확장.
153
- - fan-out packet 의 자동 spawn (사람 게이트 유지).
154
- - okstra-brief 변경 (이 설계와 무관).
@@ -1,90 +0,0 @@
1
- # 적대적 검증을 implementation-planning 으로 확장 — 설계 (sub-project A)
2
-
3
- - 작성일: 2026-06-04
4
- - 범위: `implementation-planning` phase 의 두 교차검증 라운드를 적대적으로 전환한다 — (1) Phase 5.5 **finding convergence** 는 `requirements-discovery` / `error-analysis` 에 이미 적용된 적대적 기계를 *그대로 재사용*하고, (2) **plan-body verification** 은 검증 *자세*(입증 책임을 계획 쪽으로, 인용 경로 적극 추적)를 적대적으로 바꾸되 게이트 임계값은 **과반 유지**한다.
5
- - 비범위
6
- - plan-body 게이트 임계값 변경 없음 — `majority-disagree` 차단 규칙·gate-result 4값 enum·`validators/validate-run.py` 의 `validate_phase_boundary` 모두 불변. (단일-DISAGREE 차단은 사용자가 명시적으로 기각함.)
7
- - finding convergence 의 적대적 알고리즘 자체는 재정의하지 않는다 — 이미 [`skills/okstra-convergence/SKILL.md`](../../../skills/okstra-convergence/SKILL.md) §"Adversarial Verification Mode" 에 정의돼 있고, implementation-planning 은 플래그만 켜서 상속한다.
8
- - `final-verification` 적대화 / coverage critic 워커는 **sub-project B** 의 범위 — 본 문서에서 다루지 않는다.
9
- - 새 verdict kind·classification 값·worker 역할 추가 없음.
10
- - 관계: 이전 작업 [`2026-06-04-adversarial-verification-design.md`](2026-06-04-adversarial-verification-design.md) 가 만든 적대적 convergence 기계를 한 phase 더(`implementation-planning`)로 확장한다. 그 문서의 모드 분기(`convergence.adversarial`)·verdict 매핑·`disagreeBasis`·집계 규칙을 재사용한다.
11
-
12
- ## 1. 동기
13
-
14
- `implementation-planning` 은 거짓 합의 비용이 가장 큰 지점 중 하나다 — 여기서 통과한 계획이 곧바로 `implementation` run 의 실행 대상이 된다. 그런데 현재 이 phase 의 두 검증 라운드는 모두 협조적이다:
15
-
16
- 1. **finding convergence** 는 `convergence.adversarial=false` 라 lightweight 협조적 — 약한 요구-갭/리스크 주장이 적극 반박 없이 `full-consensus` 로 남는다 ([`scripts/okstra_ctl/render.py:917`](../../../scripts/okstra_ctl/render.py)).
17
- 2. **plan-body verification** 은 "이 항목이 깨졌나?" 를 묻되 입증 책임이 반박자 쪽에 있고, `dissent-isolated`(1명만 DISAGREE)는 무사통과한다 ([`skills/okstra-convergence/SKILL.md`](../../../skills/okstra-convergence/SKILL.md) §"Plan-body verification mode"). 깨진 계획 항목을 적극적으로 추적·검증하는 압력이 약하다.
18
-
19
- → 두 라운드 모두 검증 자세를 "동의" 에서 "반박 시도" 로 뒤집되, plan-body 의 *게이트 산술*은 과반을 유지해 한 명의 오탐이 approval 을 막지 않게 한다.
20
-
21
- ## 2. 핵심 설계
22
-
23
- ### 2.1 finding convergence — 기존 적대 기계 재사용
24
-
25
- `scripts/okstra_ctl/render.py` 의 `_build_convergence_block` 가 쓰는 `adversarial_phases` 집합에 `implementation-planning` 을 추가한다 ([`render.py:917`](../../../scripts/okstra_ctl/render.py)). 이 한 줄로 implementation-planning 의 finding convergence 는:
26
-
27
- - `config.adversarial=true`, `config.verificationMode="full-reanalysis"` 를 주입받고,
28
- - §"Adversarial Verification Mode" 의 적대적 프롬프트·집계(1 counter-evidence→강등·burden-not-met)·`disagreeBasis`·인용-증거-한정 재조사를 *그대로* 상속한다.
29
-
30
- `maxRounds` 는 현행 유지(implementation-planning=2). 적대적 full-reanalysis 가 라운드당 비용을 올리지만 재조사 범위가 finding 인용 증거로 한정돼 있어 폭증하지 않으며, 계획 단계의 높은 비용-정당성이 이를 흡수한다.
31
-
32
- ### 2.2 plan-body verification — 적대적 자세, 과반 게이트 유지
33
-
34
- plan-body verification 라운드는 같은 run 의 `config.adversarial` 플래그를 읽어 적대적 자세를 적용한다(별도 플래그 없음 — 한 run 의 적대성은 단일 스위치).
35
-
36
- **바뀌는 것 (프롬프트/자세):**
37
- - 검증자는 각 `P-*` 항목의 인용 경로/심볼/명령을 *직접 열어* 실존·실행성을 확인하며 항목을 깨뜨리려 시도한다. (현행 plan-body 프롬프트의 "원본 재분석 금지" 는 유지하되, *항목이 인용한 경로/명령의 실존 확인*은 허용하도록 좁게 푼다.)
38
- - 입증 책임은 계획 쪽에 있다 — 인용 경로/명령/검증신호를 확인할 수 없으면 해당 `DISAGREE(<kind>)`(a–e 중 적용 가능한 것)로 응답한다.
39
- - plan-body 는 lightweight 전용 그대로다(full-reanalysis 강제 안 함) — "인용 경로 실존 확인" 이 적대적 재조사의 범위.
40
-
41
- **바뀌지 않는 것 (게이트 산술):**
42
- - classification enum(`full-consensus | partial-consensus | dissent-isolated | majority-disagree | contested`) 불변.
43
- - 게이트 규칙 불변 — `majority-disagree`(분석자 **과반** DISAGREE) 일 때만 approval 차단. `dissent-isolated`(1명 DISAGREE)는 종전대로 partial-consensus 로 처리하며 차단하지 않는다.
44
- - gate-result 4값(`passed` / `passed-with-dissent` / `blocked-by-disagreement` / `aborted-non-result`)·`validate_phase_boundary`([`validators/validate-run.py:1180`](../../../validators/validate-run.py)) 불변.
45
-
46
- 즉 plan-body 적대화는 검증의 *질*(능동적 추적·계획 측 입증책임)만 올리고 *판정 임계값*은 그대로다. 이건 LLM 프롬프트 지시 레이어의 변경이며 런타임으로 강제되지 않는다(§4).
47
-
48
- ### 2.3 일관성 sweep (Rule 2 — "어떤 phase 가 적대적인가" 가 적히는 모든 곳)
49
-
50
- `adversarial_phases` 집합이 행동 SSOT 다. 적대적 phase 목록을 *열거*하는 문서 지점을 모두 2개→3개로 갱신한다:
51
-
52
- - [`render.py:906`](../../../scripts/okstra_ctl/render.py) docstring 의 default 설명
53
- - [`skills/okstra-convergence/SKILL.md:49`](../../../skills/okstra-convergence/SKILL.md) Configuration 표 `adversarial` 행
54
- - 같은 파일 §"Adversarial Verification Mode" 전제 문장(현 line 198 부근)
55
- - 같은 파일 Schema rules 의 `config.adversarial` 불릿("default for requirements-discovery / error-analysis")
56
- - [`prompts/profiles/_common-contract.md:17`](../../../prompts/profiles/_common-contract.md) Phase 5.5 문장
57
- - [`agents/SKILL.md`](../../../agents/SKILL.md) `convergence.adversarial` knob 행
58
-
59
- §"Scoped full-reanalysis" 비용-근거 산문(현 line 204·302)의 "requirements-discovery·error-analysis 가 가장 큰 회피 가능 비용" 서술은 *비용 출처 설명*이므로 implementation-planning 을 같은 맥락에 더해 갱신한다.
60
-
61
- ## 3. 변경 파일
62
-
63
- 1. [`scripts/okstra_ctl/render.py`](../../../scripts/okstra_ctl/render.py) `_build_convergence_block` — `adversarial_phases` 집합에 `implementation-planning` 추가 + docstring 갱신.
64
- 2. [`tests/test_render_convergence_adversarial.py`](../../../tests/test_render_convergence_adversarial.py) — `implementation-planning` 을 비적대 파라미터 목록에서 적대 파라미터 목록으로 **이동**.
65
- 3. [`tests/test_plan_body_verification.py`](../../../tests/test_plan_body_verification.py) — `test_convergence_block_default_for_implementation_planning` 의 기대값을 `adversarial: True`, `verificationMode: "full-reanalysis"` 로 갱신.
66
- 4. [`skills/okstra-convergence/SKILL.md`](../../../skills/okstra-convergence/SKILL.md) — (a) §2.3 의 phase-목록 갱신 3곳, (b) §"Plan-body verification mode" 에 "Adversarial plan-body posture" 하위 절 추가(자세/프롬프트 변경 + 게이트 과반 유지 명시).
67
- 5. [`prompts/profiles/implementation-planning.md`](../../../prompts/profiles/implementation-planning.md) — Phase 5.5 finding convergence 적대 선언 + §4.5.9 plan-body 적대 자세 선언.
68
- 6. [`prompts/profiles/_common-contract.md`](../../../prompts/profiles/_common-contract.md) — §2.3 Phase 5.5 문장 갱신.
69
- 7. [`agents/SKILL.md`](../../../agents/SKILL.md) — §2.3 knob 행 갱신.
70
- 8. [`CHANGES.md`](../../../CHANGES.md) — `사용자 영향:` 항목.
71
-
72
- ## 4. Enforcement — 선언과 강제의 구분
73
-
74
- - **machine-강제 (변경됨):** `render.py` 가 implementation-planning 에 `adversarial=true` + `full-reanalysis` 를 주입 — 기존 contract 테스트([`tests/test_convergence_state_contract.py`](../../../tests/test_convergence_state_contract.py)) + render 테스트가 형태를 강제. 본 sub-project 는 render 테스트 + plan-body 블록 테스트의 기대값을 갱신해 이를 반영한다.
75
- - **machine-강제 (불변):** plan-body 의 gate↔approval 대응은 `validate_phase_boundary` 가 종전대로 강제. 게이트 enum·classification enum 불변이라 validator 코드 변경 없음.
76
- - **prompt-only (강제 불가):** finding 의 적대적 반박 행동, plan-body 의 능동적 경로 추적·계획측 입증책임은 lead/워커(LLM) 프롬프트 지시일 뿐 런타임 강제가 아니다. skill·profile 선언으로만 유도한다.
77
-
78
- ## 5. 비용·리스크
79
-
80
- - **비용:** finding convergence 가 lightweight→full-reanalysis(scoped) + 적대적, 최대 2라운드. 재조사 범위 한정으로 폭증 억제. plan-body 는 lightweight 유지라 추가 비용은 인용 경로 확인 정도.
81
- - **리스크 — 계획 finding 거짓 강등:** 적대적 finding convergence 가 참인 요구-갭 주장을 `contested` 로 강등할 수 있음. 완화: `contested` 는 기각이 아니라 "다툼 있음" 분류로 리포트에 남고, counter-evidence 반박은 `file:line` 인용 필수라 사유 추적 가능(기존 기계의 성질 그대로).
82
- - **리스크 — plan-body 오탐:** 게이트 과반 유지로 1명의 오탐이 approval 을 막지 않음(사용자 결정). 능동적 추적이 늘려도 차단은 과반 합의가 필요.
83
-
84
- ## 6. 수용 기준
85
-
86
- 1. `implementation-planning` 의 manifest `convergence` 블록에 `adversarial: true`, `verificationMode: "full-reanalysis"` 가 주입된다. (3개 적대 phase: requirements-discovery / error-analysis / implementation-planning.)
87
- 2. convergence skill 이 plan-body 적대적 자세를 정의하고, 게이트가 과반 유지임을 명시한다.
88
- 3. 적대 phase 목록이 적히는 모든 문서 지점(§2.3)이 3개로 일치한다(grep 일관성).
89
- 4. `python3 -m pytest tests/` + `bash validators/validate-workflow.sh` 통과.
90
- 5. implementation-planning 프로필이 Phase 5.5 적대 + plan-body 적대 자세를 선언한다.
@@ -1,176 +0,0 @@
1
- # Phase 5.5 적대적 검증 (adversarial verification) — 설계
2
-
3
- - 작성일: 2026-06-04
4
- - 범위: `requirements-discovery` / `error-analysis` 두 phase 의 **Phase 5.5 convergence 재검증**을, 검증자가 다른 워커의 주장을 적극적으로 반박(refute)하려 시도하고 입증 책임을 주장 쪽에 두는 **적대적 검증** 구조로 전환한다. 별도 검증자 에이전트나 새 스테이지를 만들지 않고, 기존 convergence 재검증 루프를 phase-조건부 적대적 모드로 재구성한다.
5
- - 비범위
6
- - 신규 worker/agent 추가 없음. `requirements-discovery` / `error-analysis` 의 `Required workers:` 로스터 불변.
7
- - `implementation-planning` / `implementation` / `final-verification` / `release-handoff` 의 convergence 동작 불변 — 이들은 현행 협조적(collaborative) 재검증을 그대로 유지한다.
8
- - `implementation-planning` 의 plan-body verification(`P-*` 큐) 불변 — 본 설계는 finding 큐(`F-*`)만 다룬다.
9
- - convergence 라운드/큐 구조 자체(Round 0 grouping, queue-pruned 루프, Round 2 gate)는 그대로 재사용한다.
10
- - 관계: 본 문서는 [`skills/okstra-convergence/SKILL.md`](../../../skills/okstra-convergence/SKILL.md) 의 §"Verification Mode" 와 §"Lightweight Re-verification Prompt" 를 **두 phase 에 한해** 적대적 변형으로 확장한다. 협조적 모드 정의는 다른 phase 를 위해 그대로 남는다.
11
-
12
- ## 1. 동기 — 현재 재검증은 협조적이라 거짓 합의를 만든다
13
-
14
- 현재 Phase 5.5 의 재검증은 본질적으로 "동의 기본값" 구조다.
15
-
16
- 1. **프롬프트가 협조적이다.** lightweight reverify 프롬프트([`skills/okstra-convergence/SKILL.md:247`](../../../skills/okstra-convergence/SKILL.md)) 는 `AGREE / DISAGREE / SUPPLEMENT` 를 묻고, "제시된 증거에 기반해 유효한가" 를 판단하게 한다. 적극적으로 깨뜨리라는 압력이 없으므로 AGREE 가 저비용 기본값이 된다.
17
- 2. **집계가 반박자에게 입증 책임을 지운다.** 집계 규칙([`skills/okstra-convergence/SKILL.md:120`](../../../skills/okstra-convergence/SKILL.md)) 은 "다수가 AGREE → consensus" 다. 즉 주장은 다수가 적극적으로 반박해야만 강등된다. 틀린 주장이라도 아무도 적극 반박하지 않으면 `full-consensus` 로 살아남는다.
18
- 3. **lightweight 는 텍스트만 본다.** 검증자는 원본 코드/로그를 재조사하지 않고 "제시된 증거"만 본다([`skills/okstra-convergence/SKILL.md:183`](../../../skills/okstra-convergence/SKILL.md)). 잘못된 증거 인용이 그대로 통과한다.
19
-
20
- 특히 `requirements-discovery`(라우팅 결정)와 `error-analysis`(근본 원인 분석)는 **틀린 주장이 다음 phase 전체를 오도**하는 지점이다. 이 두 phase 에서 거짓 합의의 비용이 가장 크다. 따라서 검증의 기본 자세를 "동의" 에서 "반박 시도" 로 뒤집는다.
21
-
22
- ## 2. 핵심 원칙
23
-
24
- ### 2.1 phase-조건부 적대적 모드
25
-
26
- 적대적 검증은 **`requirements-discovery` 와 `error-analysis` 두 phase 에만** 적용한다. convergence skill 은 모든 phase 가 공유하므로, 모드 분기는 manifest 의 `convergence` 블록에 새 플래그로 표현한다.
27
-
28
- | 키 | 두 적대적 phase 기본값 | 그 외 phase 기본값 |
29
- |---|---|---|
30
- | `convergence.adversarial` | `true` | `false` |
31
- | `convergence.verificationMode` | `"full-reanalysis"` | `"lightweight"` |
32
- | `convergence.maxRounds` | req-discovery=`1`, error-analysis=`2` (현행 유지) | 현행 유지 |
33
-
34
- 이 기본값은 [`scripts/okstra_ctl/render.py:899`](../../../scripts/okstra_ctl/render.py) `_build_convergence_block` 가 주입한다. 기존 `maxRounds` 의 phase-aware 분기(`1 if requirements-discovery else 2`) 와 동일한 패턴을 따른다. manifest 가 키를 명시하면 그 값을 우선한다(다른 phase 에서 적대적 검증을 실험적으로 켜는 것은 manifest override 로 가능 — 그러나 기본값으로 권하지 않는다).
35
-
36
- `adversarial=false` 이면 본 설계의 모든 변경은 비활성이고 현행 협조적 동작이 그대로 돈다.
37
-
38
- ### 2.2 적대적 재검증 프롬프트 — 반박이 임무다
39
-
40
- `adversarial=true` 일 때 lead 는 §"Lightweight Re-verification Prompt" 대신 **적대적 프롬프트**를 사용한다. 핵심 지시:
41
-
42
- - "너의 임무는 이 주장을 **깨뜨리는 것**이다. 인용된 원본 증거를 직접 열어 재조사하고, 주장을 무너뜨릴 반대 증거를 적극적으로 찾아라."
43
- - verdict 라벨(프롬프트 표면):
44
- - **REFUTED** — 주장을 반박했다. 반드시 근거를 댄다(아래 `disagreeBasis`).
45
- - **SURVIVES** — 적극적으로 반박을 시도했으나 깨지 못했다. 주장이 공격을 견뎠다.
46
- - **SURVIVES-WITH-CAVEAT** — 견디나 범위 한정/추가 조건/전제를 발견했다.
47
- - **불확실성 처리(BLOCKING):** 원본 증거를 재조사한 뒤에도 주장을 **확인할 수도, 반증할 수도 없으면** 기본 verdict 는 **REFUTED** 다(`disagreeBasis = burden-not-met`). 입증 책임은 주장 쪽에 있으므로, 스스로 입증되지 않은 주장은 살아남지 못한다.
48
-
49
- ### 2.3 verdict 매핑 — 영속 enum 불변, 신규 필드로 적대성 기록
50
-
51
- 상태 아티팩트의 `verdict` enum 은 `{agree, disagree, supplement, verification-error}` 를 **그대로 유지**한다(contract 테스트 enum 변경 최소화). 프롬프트 라벨은 아래로 매핑해 영속한다:
52
-
53
- | 프롬프트 라벨 | 영속 `verdict` |
54
- |---|---|
55
- | SURVIVES | `agree` |
56
- | SURVIVES-WITH-CAVEAT | `supplement` |
57
- | REFUTED | `disagree` |
58
-
59
- 적대성의 핵심 정보는 vote 에 추가하는 신규 필드 **`disagreeBasis`** 로 기록한다:
60
-
61
- | 값 | 의미 |
62
- |---|---|
63
- | `counter-evidence` | 반대 증거를 `file:line`(또는 로그 라인)으로 인용한 **강한 반박**. 인용은 `votes.<worker>.explanation` 에 포함한다. |
64
- | `burden-not-met` | 재조사했으나 확인도 반증도 못 함 → 주장이 입증 책임을 다하지 못함(= "불확실하면 기각"). |
65
- | `null` | verdict 가 `disagree` 가 아닐 때(=agree/supplement/verification-error). |
66
-
67
- `adversarial=true` 인데 verdict 가 `disagree` 이고 `disagreeBasis` 가 null 이면 contract 위반이다(§5 참조). 즉 적대적 모드의 모든 반박은 둘 중 하나의 근거를 반드시 가진다 — 근거 없는 "그냥 반대" 는 허용하지 않는다.
68
-
69
- ### 2.4 적대적 집계 규칙 — 입증 책임을 주장 쪽으로
70
-
71
- `adversarial=true` 일 때 §"Convergence Algorithm" 의 분류 로직을 다음으로 대체한다(협조적 모드 로직은 `adversarial=false` 에서 그대로). 한 finding `F` 에 대해, `verification-error` 표는 분자·분모 모두에서 제외한다(현행과 동일):
72
-
73
- ```text
74
- disagrees = [v for v in non-error votes if v.verdict == "disagree"]
75
- hard_refutes = [v for v in disagrees if v.disagreeBasis == "counter-evidence"]
76
-
77
- IF len(disagrees) == 0:
78
- # 아무도 깨지 못함 → 주장이 공격을 견딤
79
- F.classification = "full-consensus"
80
- (단, supplement(=caveat)가 있으면 "partial-consensus")
81
- ELIF len(hard_refutes) >= 1:
82
- # 증거 기반 반박이 1건이라도 성립 → 즉시 강등 (다수결 무관)
83
- IF 비-발견자 전원이 disagree:
84
- F.classification = "worker-unique" # 사실상 기각
85
- ELSE:
86
- F.classification = "contested"
87
- ELSE:
88
- # disagree 는 있으나 전부 burden-not-met (강한 반박 0건)
89
- IF 비-발견자 전원이 disagree:
90
- F.classification = "worker-unique"
91
- ELIF burden-not-met disagree 가 다수(비-error 표의 과반):
92
- F.classification = "contested"
93
- ELSE:
94
- F.classification = "partial-consensus" # 소수의 약한 의심 — 견딘 것으로 본다
95
- ```
96
-
97
- 설계 의도:
98
- - **`counter-evidence` 반박 1건 = 강등.** 사용자가 명시한 "증거 기반 반박이 1건이라도 성립하면 강등". 다수가 동의해도 누군가 반대 증거를 `file:line` 으로 제시하면 그 주장은 무조건 `contested` 이상으로 내려간다.
99
- - **`burden-not-met` 은 다수일 때만 강등.** 한 검증자가 "잘 모르겠다" 한 것만으로 주장을 죽이지는 않되, 과반이 입증 실패를 보고하면 주장은 입증 책임을 못 다한 것으로 강등한다. 이로써 "불확실하면 기각 쪽으로 기운다" 를 구현한다.
100
- - 반박의 두 종류를 구분 영속하므로, 최종 리포트에서 "왜 강등됐는가"(반대 증거 발견 vs 입증 실패)를 추적할 수 있다.
101
-
102
- multi-라운드(error-analysis maxRounds=2)에서 라운드 간 carry-forward·최종 분류는 현행 규칙을 그대로 따르되, 각 라운드의 분류 판정에 위 적대적 로직을 적용한다.
103
-
104
- ### 2.5 full-reanalysis 의 범위 한정 — 비용 폭증 방지
105
-
106
- 선택된 `verificationMode="full-reanalysis"` 는 검증자가 원본 증거를 직접 재조사하게 한다. 그러나 [`skills/okstra-convergence/SKILL.md:245`](../../../skills/okstra-convergence/SKILL.md) 는 lightweight 를 "requirements-discovery·error-analysis 에서 가장 큰 회피 가능 비용" 이라 명시한다. 전체 instruction-set 재독으로 회귀하면 이 비용을 정면으로 되살린다.
107
-
108
- **해소:** 적대적 full-reanalysis 의 재조사 범위를 **"해당 finding 이 인용한 증거 파일 + 그 인접부"로 한정**한다. 전체 task brief / instruction-set / `final-report-template.md` 재독은 금지한다. 즉 검증자는 공격 대상 주장이 가리키는 코드/로그만 직접 열어 반대 증거를 찾는다.
109
-
110
- - §"Reverify prompt: required-reading suppression (BLOCKING)" 의 full-reanalysis 분기를 적대적 모드용으로 좁힌다: analysis-worker 파일 목록 전체가 아니라 **인용된 증거 경로만** 주입한다.
111
- - maxRounds 는 현행 유지(req-discovery=1, error-analysis=2). 적대적 1라운드면 "한 번 깨뜨려 보기" 에 충분하고, 비용을 라운드 수로 곱하지 않는다.
112
-
113
- ## 3. 데이터 모델
114
-
115
- ### 3.1 convergence 상태 아티팩트 (`runs/<task-type>/state/convergence-<task-type>-<seq>.json`)
116
-
117
- - `schemaVersion` 을 `"1.2"` 로 올린다. reader 는 `"1.0"`/`"1.1"` 을 계속 수용하고 누락 필드는 `null` 로 취급한다.
118
- - `config` 에 신규 키 추가:
119
- - `adversarial`: boolean. 이 run 이 적대적 모드였는지. 현행 두 적대적 phase 는 `true`.
120
- - `findings[].rounds[].votes.<worker>` 에 신규 키 추가:
121
- - `disagreeBasis`: enum `counter-evidence | burden-not-met | null`. §2.3 의 규칙을 따른다.
122
- - 기존 필드(`verdict` enum, `classification` enum, `finalState` 등)는 불변.
123
-
124
- ### 3.2 render.py 가 주입하는 manifest `convergence` 블록
125
-
126
- `_build_convergence_block`([`scripts/okstra_ctl/render.py:899`](../../../scripts/okstra_ctl/render.py)) 가 다음을 추가로 결정한다:
127
-
128
- ```python
129
- adversarial_phases = {"requirements-discovery", "error-analysis"}
130
- is_adversarial = task_type in adversarial_phases
131
- # ...
132
- "adversarial": is_adversarial,
133
- "verificationMode": "full-reanalysis" if is_adversarial else "lightweight",
134
- ```
135
-
136
- `maxRounds` 의 기존 분기는 그대로 둔다.
137
-
138
- ## 4. 변경 대상 파일 (모두 source — `runtime/` 직접 수정 없음)
139
-
140
- 1. [`skills/okstra-convergence/SKILL.md`](../../../skills/okstra-convergence/SKILL.md)
141
- - §"Configuration" 표에 `adversarial` 키 추가, 두 phase 기본값 명시.
142
- - §"Verification Mode" 에 적대적 모드 설명 추가(범위 한정 full-reanalysis 포함).
143
- - §"Convergence Algorithm" 에 `adversarial=true` 분기 집계 로직(§2.4) 추가. 협조적 로직은 그대로 유지.
144
- - §"Lightweight Re-verification Prompt" 옆에 "Adversarial Re-verification Prompt"(§2.2) 신설.
145
- - §"Reverify prompt: required-reading suppression" 의 full-reanalysis 분기를 적대적 모드용 인용-증거-한정으로 좁힘.
146
- - §"Convergence State Artifact" 스키마를 1.2 로 갱신: `config.adversarial`, `votes.<worker>.disagreeBasis`.
147
- 2. [`scripts/okstra_ctl/render.py:899`](../../../scripts/okstra_ctl/render.py) `_build_convergence_block` — §3.2.
148
- 3. [`prompts/profiles/requirements-discovery.md`](../../../prompts/profiles/requirements-discovery.md) + [`prompts/profiles/error-analysis.md`](../../../prompts/profiles/error-analysis.md) — Phase 5.5 가 적대적으로 돈다는 선언 1줄(프로필이 동작의 authoritative 선언처임).
149
- 4. [`prompts/profiles/_common-contract.md:16`](../../../prompts/profiles/_common-contract.md) — "Worker interaction model" 의 Phase 5.5 설명에, 두 phase 는 적대적 peer review 라는 한 줄 추가.
150
- 5. [`tests/test_convergence_state_contract.py`](../../../tests/test_convergence_state_contract.py) + `tests/fixtures/convergence/` — `1.2` 수용, `disagreeBasis` enum 검증, `config.adversarial` 존재 검증, 적대적 fixture 1개 추가(`counter-evidence` 반박 1건 → `contested` 케이스).
151
- 6. [`CHANGES.md`](../../../CHANGES.md) — `사용자 영향:` 항목.
152
-
153
- ## 5. Enforcement — 선언과 강제의 구분
154
-
155
- 정직한 enforcement 경계:
156
-
157
- - **적대적 *행동* 자체(lead 가 실제로 반박을 시도했는지, 검증자가 증거를 재조사했는지)는 런타임으로 강제할 수 없다.** lead 와 워커는 LLM 이므로, 적대성은 skill/프롬프트의 선언과 지시로만 유도된다. 이 한계를 문서에 명시한다.
158
- - **강제되는 것은 아티팩트의 *형태* 뿐이다.** `tests/test_convergence_state_contract.py` 가 fixture 에 대해 검증:
159
- - `config.adversarial` 가 boolean 으로 존재.
160
- - `disagreeBasis` 가 enum `{counter-evidence, burden-not-met, null}` 안에 있음.
161
- - `adversarial==true` 인 fixture 에서, verdict 가 `disagree` 이면 `disagreeBasis != null`.
162
- - convergence 상태는 런타임 `validators/validate-run.py` 가 검사하지 않는다(현행과 동일). 따라서 본 설계는 런타임 run 에 대한 적대성 강제를 **약속하지 않는다** — fixture contract 테스트가 유일한 자동 검증 지점이다.
163
-
164
- ## 6. 비용·리스크
165
-
166
- - **비용:** full-reanalysis 로의 전환은 lightweight 대비 라운드당 비용을 올린다. §2.5 의 인용-증거-한정으로 폭증을 막고, maxRounds 를 현행 유지(req-discovery=1)해 라운드 곱을 억제한다.
167
- - **리스크 — 거짓 강등(false negative):** 적대적 모드는 참인 주장을 `contested` 로 강등할 수 있다(검증자가 잘못된 반대 증거를 제시). 완화: `counter-evidence` 반박은 반드시 `file:line` 인용을 요구하므로(§2.3), 강등 사유가 리포트에 기록되어 사용자가 추적·반박할 수 있다. `contested` 는 기각이 아니라 "다툼 있음" 분류이므로 finding 은 리포트에 남는다.
168
- - **리스크 — burden-not-met 남용:** 검증자가 게으르게 "잘 모르겠다" 로 일관하면 다수 burden-not-met 으로 멀쩡한 주장이 강등될 수 있다. 완화: 프롬프트가 "재조사 후" 에만 burden-not-met 을 허용하도록 지시하고, 단일 burden-not-met 은 강등시키지 않는다(과반 필요, §2.4).
169
-
170
- ## 7. 수용 기준
171
-
172
- 1. `requirements-discovery` / `error-analysis` 의 manifest `convergence` 블록에 `adversarial: true`, `verificationMode: "full-reanalysis"` 가 주입된다. 그 외 phase 는 `adversarial: false`, `lightweight` 유지.
173
- 2. convergence skill 이 `adversarial=true` 분기에서 적대적 프롬프트·적대적 집계·인용-증거-한정 재조사를 정의한다. `adversarial=false` 동작은 byte 단위로 현행과 동일.
174
- 3. 상태 스키마 1.2 가 `config.adversarial` 와 `votes.<worker>.disagreeBasis` 를 문서화하고, contract 테스트가 §5 의 형태 규칙을 강제한다.
175
- 4. `python3 -m pytest tests/` 와 `bash validators/validate-workflow.sh` 통과.
176
- 5. 두 프로필과 `_common-contract.md` 가 적대적 Phase 5.5 를 선언한다.
@@ -1,99 +0,0 @@
1
- # Coverage critic — 설계 (sub-project B1)
2
-
3
- - 작성일: 2026-06-04
4
- - 범위: `requirements-discovery` / `error-analysis` / `implementation-planning` 세 phase 에, Phase 5.5 convergence 직후·Phase 6 report-writer 직전에 도는 **coverage critic pass** 를 추가한다. critic 은 기존 worker subagent 를 *재사용*해 dispatch 되며("아무도 안 본 각도/파일/모달리티, finding 없는 요구사항을 내라"), critic 이 낸 coverage gap 은 **1회 적대적 reverify** 를 거쳐 살아남은 것만 최종 finding/clarification 으로 병합된다. 사용 여부·backing provider 는 **okstra-run 초기 select box** 로 고르며(추천 + "직접 입력"), CLI 파라미터가 넘어오면 그 선택 단계를 건너뛴다. 기본값은 off(opt-in).
5
- - 비범위
6
- - `final-verification` 의 verdict 악마의 변호인은 **sub-project B2** — 본 문서 밖. (critic primitive 는 B2 가 재사용한다.)
7
- - 새 설치형 agent(`critic-worker.md` / `installed-agents.json`) 추가 없음 — 기존 `claude-worker`/`codex-worker`/`gemini-worker` subagent_type 을 critic 프롬프트로 재사용.
8
- - convergence 의 finding/plan-body classification·gate enum 변경 없음 — critic gap 은 기존 adversarial finding classifier 를 그대로 탄다.
9
- - 워커 *수*(로스터 크기) 변경 없음 — critic 은 별도 pass 이지 Phase 4 analyser 로스터를 늘리는 게 아니다.
10
- - 관계: 적대적 convergence 기계([`skills/okstra-convergence/SKILL.md`](../../../skills/okstra-convergence/SKILL.md) §"Adversarial Verification Mode")를 재사용해 critic gap 을 검증한다. wizard select 패턴은 기존 `okstra-run` step 들(`defaults_or_custom` 등)과 동일한 picker 관례를 따른다.
11
-
12
- ## 1. 동기 — 커버리지 갭은 구조적이다
13
-
14
- okstra 의 analyser 워커들은 설계상 *같은* section 1–5 질문을 답한다 — triangulation 이지 partition 이 아니다 ([`skills/okstra-team-contract/SKILL.md:204`](../../../skills/okstra-team-contract/SKILL.md)). 따라서 워커를 늘려도 *같은 종류*의 finding 을 더 찾을 뿐, "아무도 보지 않은 각도" 는 구조적으로 비어 있다. 합의 품질(b)은 적대적 검증으로 올렸지만, 커버리지(c) — 놓친 finding — 는 별도 메커니즘이 필요하다. coverage critic 은 통합 findings 를 입력으로 "무엇이 빠졌나" 만 전담해 이 갭을 메운다.
15
-
16
- ## 2. 핵심 설계
17
-
18
- ### 2.1 critic pass primitive
19
-
20
- Phase 5.5 convergence 가 끝나 findings 가 분류된 직후, Phase 6 report-writer dispatch **전에** lead 가 critic pass 를 1회 실행한다.
21
-
22
- - **재사용 dispatch:** 선택된 provider 의 기존 subagent_type(`claude-worker` / `codex-worker` / `gemini-worker`)에 critic 프롬프트로 dispatch. 새 agent 정의 없음.
23
- - 입력: task brief + Phase 5.5 통합 findings 요약 + 코드베이스 read 접근.
24
- - 프롬프트 골자: "다음은 이미 합의된 findings 다. 아무도 검사하지 않은 파일/디렉터리/실행경로, finding 이 하나도 없는 요구사항/수용기준, 제기됐지만 아무도 검증하지 않은 주장을 찾아라. 각 coverage gap 을 새 finding 으로, 근거(`file:line` 또는 요구사항 인용)와 함께 내라. 이미 있는 finding 을 반복하지 마라."
25
- - 결과 파일: `runs/<task-type>/worker-results/<provider>-critic-<task-type>-<seq>.md`.
26
- - **1회 적대적 reverify (질문3 결정):** critic 이 낸 gap 들을 `originWorker=<provider>-critic` 인 새 finding 으로 verification queue 에 넣고, **Phase 4 analyser 들**(critic 자신 제외)이 1라운드 적대적으로 reverify 한다(기존 §"Adversarial Verification Mode" classifier 재사용: 증거기반 반박 1건 → 강등). `full-consensus`/`partial-consensus` 로 살아남은 gap 만 최종 리포트 finding 으로 병합; 강등(`contested`/`worker-unique`)된 gap 은 환각으로 보고 버리거나 dissent 로만 기록.
27
- - **모델 (질문2 결정):** backing provider 는 `--critic <claude|codex|gemini>` 로 선택, 모델은 그 provider 의 기존 `--<provider>-model` 값(executor 바인딩 패턴 미러링). 별도 critic 모델 플래그는 두지 않는다(YAGNI).
28
-
29
- ### 2.2 선택 UX — wizard select step + CLI bypass
30
-
31
- critic 사용 여부·provider 는 실행 파라미터 전용이 아니라 **okstra-run 초기 select box** 로 고른다.
32
-
33
- - 신규 wizard step `S_CRITIC_PICK` — [`scripts/okstra_ctl/wizard.py`](../../../scripts/okstra_ctl/wizard.py) 의 `_build_*`/`_submit_*` + [`prompts/wizard/prompts.ko.json`](../../../prompts/wizard/prompts.ko.json) SOT. picker 관례(추천 1~2 + 마지막 "직접 입력"):
34
- - `critic 사용 안 함 (기본·추천)` → 비활성
35
- - `claude critic (opus)` *(추천)* → provider=claude, 모델=해당 phase 의 claude 모델
36
- - `직접 입력` → provider(+선택 모델)를 사용자가 직접 지정
37
- - (목록은 현재 analyser 로스터에 맞춰 codex/gemini 옵션을 추천에 추가할 수 있으나, 추천은 최대 2개 + 직접 입력 = 3옵션 관례 유지.)
38
- - **CLI 우선·건너뛰기:** `--critic <provider>` 또는 `--no-critic` 가 넘어오면 `S_CRITIC_PICK` 을 **건너뛴다**. `okstra.sh` / `node bin/okstra` 비대화 경로는 플래그로, 대화형 `okstra-run` 은 select box 로. 플래그 무지정 + 비대화 경로면 기본 off.
39
- - 세 진입점(okstra-run skill / okstra.sh / node CLI)은 모두 `prepare_task_bundle()` 로 수렴하므로, critic 선택은 거기서 manifest 로 직렬화된다(단일 참조점 보존).
40
-
41
- ### 2.3 manifest `convergence.critic` 블록 + render resolve
42
-
43
- [`scripts/okstra_ctl/render.py`](../../../scripts/okstra_ctl/render.py) 가 `convergence` 하위에 `critic` 블록을 emit 한다:
44
-
45
- ```json
46
- "critic": {
47
- "enabled": false,
48
- "provider": null,
49
- "modelExecutionValue": null
50
- }
51
- ```
52
-
53
- - `enabled`: wizard 선택 or `--critic` 플래그가 provider 를 정하면 `true`, 아니면 `false`(기본).
54
- - `provider`: `claude` | `codex` | `gemini` | `null`.
55
- - `modelExecutionValue`: 선택된 provider 의 모델(그 provider 의 `--<provider>-model` 시드에서). `enabled=false` 면 `null`.
56
-
57
- lead 는 Phase 5.5 종료 시 이 블록을 읽어 critic pass 실행 여부/대상을 정한다.
58
-
59
- ### 2.4 적용 phase
60
-
61
- requirements-discovery / error-analysis / implementation-planning. (final-verification 은 B2.) 이 세 phase 는 모두 finding 을 산출하므로 coverage critic 이 의미가 있다. release-handoff/implementation 은 적용하지 않는다.
62
-
63
- ## 3. 데이터 모델
64
-
65
- - **manifest:** §2.3 의 `convergence.critic` 블록.
66
- - **convergence 상태 아티팩트:** critic gap 은 `findings[]` 에 `originWorker: "<provider>-critic"` 로 들어가고 기존 rounds/votes/classification 스키마를 그대로 쓴다. 추적용으로 finding 에 선택 필드 `source: "critic"` 를 둔다(없으면 `null`=일반 워커 발견). schemaVersion 은 `1.2` 유지(optional 필드 추가, reader 는 누락을 null 로 취급) — enum 변경 없음.
67
- - **convergence state `config`:** critic 실행 시 `config.critic` 에 `{ provider, modelExecutionValue, gapsProposed, gapsMerged }` 요약을 기록(감사용).
68
-
69
- ## 4. 변경 파일
70
-
71
- 1. [`scripts/okstra_ctl/render.py`](../../../scripts/okstra_ctl/render.py) `_build_convergence_block` — `critic` 블록 emit + `--critic`/wizard 선택 resolve.
72
- 2. [`scripts/okstra_ctl/run.py`](../../../scripts/okstra_ctl/run.py) — `--critic <provider>` / `--no-critic` argparse + ctx 전달 + 세 phase 한정 적용.
73
- 3. [`scripts/okstra_ctl/wizard.py`](../../../scripts/okstra_ctl/wizard.py) — `S_CRITIC_PICK` step `_build`/`_submit` + 흐름 편입(CLI 미지정 시에만 표시).
74
- 4. [`prompts/wizard/prompts.ko.json`](../../../prompts/wizard/prompts.ko.json) (+ 영문 SOT 있으면 동기) — `critic_pick` step label/options.
75
- 5. [`skills/okstra-convergence/SKILL.md`](../../../skills/okstra-convergence/SKILL.md) — "Coverage critic pass" 절 신설(시점·프롬프트·1회 적대 reverify·병합·`convergence.critic` 스키마).
76
- 6. [`agents/SKILL.md`](../../../agents/SKILL.md) — Phase 5.5→6 흐름에 critic pass + `PROGRESS: phase-5.5-critic provider=<p>` 라인 + (해당 시) 모델/knob 참조.
77
- 7. [`prompts/profiles/requirements-discovery.md`](../../../prompts/profiles/requirements-discovery.md) / [`error-analysis.md`](../../../prompts/profiles/error-analysis.md) / [`implementation-planning.md`](../../../prompts/profiles/implementation-planning.md) — coverage critic opt-in 선언 1줄.
78
- 8. 테스트: render `critic` 블록 resolve(`--critic`/무지정/`--no-critic`), wizard `S_CRITIC_PICK` 빌드+제출, CLI bypass.
79
- 9. [`CHANGES.md`](../../../CHANGES.md) — 사용자 영향 항목.
80
-
81
- ## 5. Enforcement — 선언과 강제의 구분
82
-
83
- - **machine-강제:** `convergence.critic` 블록 형태 + render resolve(`--critic`/`--no-critic`/무지정) → 단위 테스트. wizard `S_CRITIC_PICK` 의 picker 옵션·CLI bypass → wizard 테스트.
84
- - **prompt-only(강제 불가):** critic 이 실제로 의미 있는 gap 을 찾는지, 1회 적대 reverify 가 환각을 거르는지는 lead/워커(LLM) 프롬프트 지시일 뿐 런타임 강제 아님 — skill/profile 선언으로 유도.
85
-
86
- ## 6. 비용·리스크
87
-
88
- - **비용:** opt-in(기본 off). 켜면 critic dispatch 1 + reverify 1라운드(analyser 수만큼). 기본 off 라 미선택 run 은 비용 0.
89
- - **리스크 — 환각 gap:** critic 이 가짜 gap 을 낼 수 있음. 완화: 1회 적대 reverify 가 증거 없는 gap 을 강등. 살아남은 gap 만 finding 으로.
90
- - **리스크 — 중복 finding:** critic 이 기존 finding 을 재서술. 완화: 프롬프트가 "이미 있는 finding 반복 금지" 명시 + reverify 단계의 semantic grouping 이 중복을 흡수.
91
- - **리스크 — reverify 투표자 부족:** critic gap 은 critic 자신을 뺀 Phase 4 analyser 가 검증. 기본 로스터가 ≥2 analyser 라 최소 1명은 항상 투표 가능. analyser 가 1명뿐인 비정상 구성이면 critic gap 은 검증 불가로 표면화만(병합 안 함)하고 그 사실을 기록.
92
-
93
- ## 7. 수용 기준
94
-
95
- 1. wizard 에 `S_CRITIC_PICK` select box 가 추가되고(추천 + "직접 입력"), `--critic`/`--no-critic` 미지정 대화형 run 에서만 표시된다. 플래그 지정 시 건너뛴다.
96
- 2. manifest `convergence.critic` 가 wizard 선택/플래그에서 정확히 resolve 된다(enabled/provider/model). 기본 off.
97
- 3. convergence skill 이 critic pass(시점·프롬프트·1회 적대 reverify·병합)를 정의한다.
98
- 4. 세 적용 phase 프로필이 coverage critic opt-in 을 선언한다.
99
- 5. `python3 -m pytest tests/` + `bash validators/validate-workflow.sh` 통과.