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,254 +0,0 @@
|
|
|
1
|
-
# Implementation Plan Body Verification — Design
|
|
2
|
-
|
|
3
|
-
- Date: 2026-05-15
|
|
4
|
-
- Scope: okstra phase `implementation-planning` only
|
|
5
|
-
- Status: Designed (pending implementation)
|
|
6
|
-
- Implementation plan: `docs/superpowers/plans/2026-05-15-implementation-plan-verification.md` (to be written)
|
|
7
|
-
|
|
8
|
-
## 1. 목적
|
|
9
|
-
|
|
10
|
-
`implementation-planning` phase는 현재 다음 흐름을 따른다.
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
Phase 4 (워커 독립 분석)
|
|
14
|
-
→ Phase 5.5 (워커 finding 상호 검증 — convergence)
|
|
15
|
-
→ Phase 6 (report-writer가 통합 plan draft 작성)
|
|
16
|
-
→ User Approval gate
|
|
17
|
-
→ implementation phase
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
Phase 5.5의 convergence는 **워커의 finding (section 1~5)** 만 cross-verify한다. 그 뒤 report-writer가 합성한 **통합 plan body (section 4.5: Option Candidates / Trade-off / Recommended Option / Stepwise Execution Order / Dependency / Validation Checklist / Rollback)** 에 대해서는 워커의 재검증이 없다. lead의 self-review pass만 거치고 User Approval로 직행한다.
|
|
21
|
-
|
|
22
|
-
본 변경은 Phase 6 직후, User Approval 직전에 **합성 결과물 자체를 워커가 peer-review하는 라운드**를 끼워 넣는다. 통합 plan의 내적 일관성 / 실행 가능성 / 누락된 step / 깨진 file path 등을 워커들이 잡아내고, majority disagreement는 `## 5. Clarification Items`에 `Blocks=approval` row로 변환해 사용자에게 던진다.
|
|
23
|
-
|
|
24
|
-
## 2. 결정된 분기 (대화에서 확정)
|
|
25
|
-
|
|
26
|
-
| ID | 결정 |
|
|
27
|
-
|----|-----|
|
|
28
|
-
| Q1 | **gating**. majority DISAGREE는 User Approval 체크박스를 막고 clarification 변환 경로로 보낸다. `contested` 와 `partial-consensus` 는 보고서에 기록만 하고 통과. |
|
|
29
|
-
| Q2 | **lifecycle 내부 step**. 외부 6-phase 계약 유지. `/okstra-status` 에는 implementation-planning 내부의 `plan-verification` sub-state로만 노출. |
|
|
30
|
-
| Q3 | **maxRounds = 1**. plan body 검증은 사실 검증이 아닌 일관성·완전성 검증이며 추가 라운드 이득이 작음. manifest로 override 가능. |
|
|
31
|
-
| Q4 | **자동 revise 안 함**. majority DISAGREE 항목은 lead가 직접 `## 5. Clarification Items` 표의 `Blocks=approval` row로 변환. report-writer 재호출 없음. |
|
|
32
|
-
|
|
33
|
-
## 3. Plan Item 분리 규칙
|
|
34
|
-
|
|
35
|
-
report-writer가 draft한 final-report의 `## 4.5 Implementation Plan Deliverables` 본문을 lead가 파싱해 다음 형식의 plan-item으로 쪼갠다.
|
|
36
|
-
|
|
37
|
-
| Prefix | 출처 섹션 | 1 row의 정의 |
|
|
38
|
-
|--------|----------|--------------|
|
|
39
|
-
| `P-Opt-<N>` | `4.5 Option Candidates` | Option 1개 전체 (File Structure / 인터페이스 / blast radius 묶음) |
|
|
40
|
-
| `P-Step-<N>` | `Stepwise Execution Order` | step 1개 (file path + command + 성공 신호) |
|
|
41
|
-
| `P-Dep-<N>` | `Dependency` | dependency row 1개 |
|
|
42
|
-
| `P-Val-<N>` | `Validation Checklist` | checklist item 1개 |
|
|
43
|
-
| `P-Rb-<N>` | `Rollback` | rollback path 1개 (보통 1행) |
|
|
44
|
-
|
|
45
|
-
`Trade-off matrix`, `Recommended Option`은 별도 plan-item으로 만들지 않는다 (각 Option 자체가 P-Opt-* 로 평가되므로 중복).
|
|
46
|
-
|
|
47
|
-
Ticket ID 표기는 기존 규칙 그대로 (`[TICKETID: ...]`) plan-item 라인에 강제.
|
|
48
|
-
|
|
49
|
-
## 4. 평결 스키마 (재사용)
|
|
50
|
-
|
|
51
|
-
기존 convergence의 `AGREE` / `DISAGREE` / `SUPPLEMENT` 스키마와 워커 실패 처리 규칙을 그대로 재사용. plan-body 모드에서의 각 평결 의미는 다음과 같다.
|
|
52
|
-
|
|
53
|
-
| 평결 | plan-body 모드 의미 |
|
|
54
|
-
|------|--------------------|
|
|
55
|
-
| `AGREE` | 항목이 실행 가능하고 다른 항목과 내적으로 일관됨 |
|
|
56
|
-
| `DISAGREE` | 항목이 깨짐 — 다음 중 하나 이상: (a) 참조된 file path / symbol 이 다른 step·option과 불일치, (b) command가 실행 불가하거나 ambiguity, (c) validation step이 관측 불가, (d) rollback이 commit 순서·dependency 위반, (e) 명시된 trade-off와 모순 |
|
|
57
|
-
| `SUPPLEMENT` | 항목 자체는 OK이나 누락된 dependency / edge case / 사전조건 보강이 필요함 |
|
|
58
|
-
|
|
59
|
-
워커 non-result(`timeout`/`error`/no result file) 처리는 finding convergence와 동일 — DISAGREE로 집계하지 않고 `contract-violation` 이벤트만 기록.
|
|
60
|
-
|
|
61
|
-
## 5. 최종 분류 → Gate 매핑
|
|
62
|
-
|
|
63
|
-
`effectiveMaxRounds = 1` 이므로 단일 라운드 결과로 결정.
|
|
64
|
-
|
|
65
|
-
| 항목 분류 | Gate 동작 |
|
|
66
|
-
|----------|----------|
|
|
67
|
-
| `full-consensus AGREE` | 통과. 보고서에 기록. |
|
|
68
|
-
| `partial-consensus` (majority AGREE, 일부 DISAGREE) | 통과(`passed-with-dissent`). 반대 의견은 보고서 4.5.9 섹션에 기록. |
|
|
69
|
-
| `majority DISAGREE` | **gate 차단**. clarification row 변환. User Approval 체크박스 라인 자체를 렌더하지 않음. |
|
|
70
|
-
| `worker-unique DISAGREE` (1명만 반대) | 통과. 보고서 기록만. |
|
|
71
|
-
| `contested` (round 1 종료 시 큐 잔류 — maxRounds=1에서는 partial-consensus 와 동일 취급) | partial-consensus 로 fold-in. |
|
|
72
|
-
| 모든 워커 non-result | 라운드 전체 실패. `aborted-non-result` 기록 + User Approval 체크박스 라인 렌더하지 않음 + clarification에 "plan-body verification could not run" row 추가. |
|
|
73
|
-
|
|
74
|
-
## 6. 변경 파일
|
|
75
|
-
|
|
76
|
-
### 6.1 `prompts/profiles/implementation-planning.md`
|
|
77
|
-
- `Required deliverable shape` 끝에 새 bullet: "the final report MUST include a `## 4.5.9 Plan Body Verification` section populated by the post-synthesis worker verification round (see `okstra-convergence` "Plan-body verification mode")."
|
|
78
|
-
- `Approval gate` 항목 보강: User Approval 체크박스 라인은 **plan-body verification gate가 `passed` 또는 `passed-with-dissent`일 때만 렌더된다**. `blocked-by-disagreement` / `aborted-non-result` 면 라인 자체를 생략하고 clarification 표로 사용자에게 던진다.
|
|
79
|
-
- `Self-review pass` 끝에 6번 항목 신설: "If plan-body verification produced `DISAGREE` majority on any P-* item, convert each into a row of `## 5. Clarification Items` with `Blocks=approval`. Do NOT create a parallel `Open Questions` block."
|
|
80
|
-
|
|
81
|
-
### 6.2 `skills/okstra-convergence/SKILL.md`
|
|
82
|
-
- 신규 섹션 추가: "Plan-body verification mode (implementation-planning only)"
|
|
83
|
-
- 본문 내용:
|
|
84
|
-
- **선행 흐름**: Phase 5.5 finding convergence → Phase 6 report-writer → plan-body verification round → User Approval
|
|
85
|
-
- finding 큐와 plan-item 큐는 **서로 독립**. 같은 워커, 같은 평결 스키마, 같은 wrapper 인프라를 재사용하되 state file은 별도(`plan-body-verification.json`).
|
|
86
|
-
- **MUTUAL EXCLUSION (BLOCKING)**: finding convergence 의 reverify prompt에 P-* item을 끼워 넣거나, plan-body 라운드의 reverify prompt에 F-* finding을 끼워 넣지 말 것.
|
|
87
|
-
- plan-body 라운드 전용 reverify prompt 본문 템플릿 (§7 참고).
|
|
88
|
-
- prompt anchor 5종은 finding convergence와 동일하게 유지.
|
|
89
|
-
|
|
90
|
-
### 6.3 `templates/reports/final-report.template.md`
|
|
91
|
-
- 신규 sub-section `### 4.5.9 Plan Body Verification` 추가. 위치: 기존 `### 4.5.8 User Approval Request` 직후, `## 4.6 Release Handoff Deliverables` 직전 (implementation-planning 4.5 블록의 마지막 sub-section).
|
|
92
|
-
- 필드:
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
## 4.5.9 Plan Body Verification
|
|
96
|
-
|
|
97
|
-
- Round count: <N>
|
|
98
|
-
- Gate result: <passed | passed-with-dissent | blocked-by-disagreement | aborted-non-result>
|
|
99
|
-
- Verdict table:
|
|
100
|
-
|
|
101
|
-
| Plan item | Ticket ID | Section | <worker1> | <worker2> | ... | Classification |
|
|
102
|
-
|-----------|-----------|---------|-----------|-----------|-----|----------------|
|
|
103
|
-
| P-Opt-1 | ... | 4.5.1 | AGREE | AGREE | ... | full-consensus |
|
|
104
|
-
| P-Step-3 | ... | 4.5.4 | DISAGREE | DISAGREE | ... | majority-disagree → C-7 |
|
|
105
|
-
|
|
106
|
-
- Dissent log: (partial-consensus / worker-unique 인 항목의 반대 의견 본문)
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### 6.4 `validators/validate-run.py`
|
|
110
|
-
- `implementation-planning` phase 일 때 final-report에서 다음 substring을 필수로 검사:
|
|
111
|
-
- `Plan Body Verification`
|
|
112
|
-
- Approval gate 라인 검사 로직 보강: gate 결과가 `passed` / `passed-with-dissent` 이면 `- [ ] Approved` / `- [x] Approved` 라인이 반드시 존재해야 하고, `blocked-by-disagreement` / `aborted-non-result` 이면 해당 라인이 **존재하지 않아야** 한다.
|
|
113
|
-
|
|
114
|
-
### 6.5 `scripts/okstra_ctl/render.py` (task-manifest payload)
|
|
115
|
-
현재 codebase 에는 task-manifest 를 위한 Python dataclass 가 없다 (`models.py` 는 model alias 전용). manifest payload 는 `render_task_manifest()` 안에서 dict literal 로 직접 구성된다. 기존 `convergence` 블록은 아직 manifest 에 출력되지 않으며, skill 문서에만 "있으면 읽고 없으면 default" 로 기술돼 있다. 따라서:
|
|
116
|
-
|
|
117
|
-
- `render_task_manifest()` payload 에 신규 `convergence` 블록을 명시적으로 출력한다:
|
|
118
|
-
|
|
119
|
-
```json
|
|
120
|
-
"convergence": {
|
|
121
|
-
"enabled": true,
|
|
122
|
-
"maxRounds": <phase-aware default>,
|
|
123
|
-
"verificationMode": "lightweight",
|
|
124
|
-
"planBodyVerification": {
|
|
125
|
-
"enabled": true,
|
|
126
|
-
"maxRounds": 1,
|
|
127
|
-
"gating": true
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
- `maxRounds`: `requirements-discovery` 면 1, 그 외 phase 면 2 (기존 skill 문서의 default 그대로).
|
|
133
|
-
- `planBodyVerification.enabled`: task-type 이 `implementation-planning` 일 때만 의미를 가진다. 다른 phase 에서는 무시되어도 안전한 dead-letter 필드 (스키마 일관성을 위해 항상 출력).
|
|
134
|
-
- ctx 입력 키 (CLI / wizard / interactive 입력 → ctx env 로 합류):
|
|
135
|
-
- `OKSTRA_PLAN_VERIFICATION` ∈ `{"true","false",""}` — 빈 값이면 default(true). 명령행 `--no-plan-verification` 가 `"false"` 로 set.
|
|
136
|
-
- 추후 `OKSTRA_PLAN_VERIFICATION_MAX_ROUNDS` 같은 추가 knob 가능하지만 본 spec 범위에서는 1 고정.
|
|
137
|
-
- 기존 manifest 와의 호환: render 마다 payload 가 매 회 다시 쓰이므로 (`render_task_manifest` 의 `existing` 머지 대상은 `workflow` 일부와 `createdAt`/`latestRunPath` 같은 lifecycle 키뿐) `convergence` 블록은 매 render 마다 새로 작성된다. legacy task-key 의 resume 시 ctx 가 default(true) 면 자동으로 enabled 가 set 된다 (§8 마이그레이션 항목 그대로).
|
|
138
|
-
|
|
139
|
-
### 6.6 `agents/SKILL.md` (lead orchestration skill — markdown only, no Python)
|
|
140
|
-
|
|
141
|
-
**아키텍처 정정**: okstra 의 orchestration 패턴은 conversational-only 다. Python 코드(`scripts/okstra_ctl/`)는 task bundle 준비 / 템플릿 렌더링 / validation 만 담당하고, Phase 4 (워커 dispatch), Phase 5.5 (convergence), Phase 6 (report-writer dispatch) 등 **모든 phase 실행은 lead 가 SKILL.md 명세를 따라 inline 으로 Agent() 호출**로 수행한다. `render.py:1133` 의 rendered prompt 문구 ("convergence loop. The Claude lead performs every step inline") 와 run.py 에 convergence 관련 dispatch 함수가 존재하지 않는 점이 이 패턴을 확인해 준다.
|
|
142
|
-
|
|
143
|
-
따라서 plan-body verification 도 별도 Python 함수 추가 없이, lead skill 의 Phase 6 섹션 확장만으로 wiring 한다.
|
|
144
|
-
|
|
145
|
-
- `agents/SKILL.md` 의 "Phase 6: Final report assembly" 섹션 끝에 새 sub-step 추가:
|
|
146
|
-
- report-writer draft 검토 후 → `task_type == "implementation-planning"` 이고 manifest 의 `convergence.planBodyVerification.enabled == true` 면 → `okstra-convergence` "Plan-body verification mode" sub-skill invoke (이 명세는 §6.2 Phase D 에서 추가됨).
|
|
147
|
-
- 라운드 결과(`gateResult`) 에 따라 §6.3 양식의 `### 4.5.9 Plan Body Verification` 섹션을 final-report 에 직접 채우고, `majority-disagree` 항목은 `## 5. Clarification Items` 의 `Blocks=approval` row 로 변환. (이 변환 로직은 §6.1 Phase C 의 self-review step 6 가 lead 에게 BLOCKING 으로 명령.)
|
|
148
|
-
- 변환 완료 후, Gate result 에 따라 top-of-report Approval marker 의 렌더 / 비렌더 결정 (이 룰은 §6.1 Phase C 의 Approval gate bullet 이 BLOCKING 으로 명령, §6.4 Phase B 의 validator 가 실행 후 검사).
|
|
149
|
-
- `agents/SKILL.md` 상단 "Lifecycle / Skill index" 표(line 28 근처)에 plan-body verification 이 Phase 6 의 sub-step 임을 한 줄 명시 — 별도 phase 식별자는 부여하지 **않는다** (spec §2 Q2 = lifecycle 내부 step).
|
|
150
|
-
|
|
151
|
-
**Single-reference-point invariant**: Python dispatch 함수가 존재하지 않으므로 분기 가능성 자체가 없다. 모든 entry point (CLI / skill / interactive) 가 동일한 `task-manifest.json` 의 `convergence.planBodyVerification` 블록을 읽고, 동일한 `okstra-convergence` SKILL.md "Plan-body verification mode" 명세를 따라 lead 가 수행한다. 메모리상의 `prepare_task_bundle` 수렴 invariant 는 manifest 생성 시점에서만 의미를 가지며, 이는 §6.5 Phase B 에서 이미 완료됨.
|
|
152
|
-
|
|
153
|
-
### 6.7 CLI 진입점 (single reference point 준수)
|
|
154
|
-
세 진입점 모두 동일한 manifest write 경로(`prepare_task_bundle`)로 수렴해야 한다.
|
|
155
|
-
|
|
156
|
-
- `scripts/okstra.sh` — `--no-plan-verification` 플래그 추가 (boolean off)
|
|
157
|
-
- `scripts/lib/okstra-ctl/` Bash 라우팅 — flag → CLI args 통과만 (business logic 없음)
|
|
158
|
-
- `bin/okstra` (Node CLI) — `setup` / `config set` 경로에서 `plan-verification` 키 지원
|
|
159
|
-
- `okstra config set plan-verification <on|off> [--scope project|global]` 명령 추가 (기존 `pr-template-path` 패턴 답습)
|
|
160
|
-
|
|
161
|
-
flag 우선순위: 명령행 `--no-plan-verification` > 프로젝트 config (`project.json` `planVerification`) > 글로벌 config (`~/.okstra/config.json` `planVerification`) > 기본값 ON.
|
|
162
|
-
|
|
163
|
-
### 6.8 인터랙티브 skill 진입점
|
|
164
|
-
`skills/okstra-run/SKILL.md` 의 Step 6 (worker / option 선택) 에 다음 질문 추가:
|
|
165
|
-
|
|
166
|
-
> "implementation-planning 의 plan-body 검증 라운드를 활성화할까요? (default: yes — 합성된 plan을 워커가 peer-review)"
|
|
167
|
-
|
|
168
|
-
`AskUserQuestion` 의 옵션은 yes / no 단일 선택. 사용자 선택은 manifest의 `plan_body_verification.enabled` 로 기록.
|
|
169
|
-
|
|
170
|
-
## 7. plan-body 모드 reverify prompt 템플릿 (lightweight 만 지원)
|
|
171
|
-
|
|
172
|
-
`full-reanalysis` 모드는 plan-body에 대해서는 의미가 약함(원본은 워커 자신의 분석 + lead 합성 결과이므로 "원본 재검토"의 정의가 모호). 따라서 plan-body 모드는 lightweight만 지원하고 manifest의 `verificationMode` 와는 독립적으로 동작한다.
|
|
173
|
-
|
|
174
|
-
```
|
|
175
|
-
You are <worker-role> performing plan-body verification for <task-key> (round 1).
|
|
176
|
-
|
|
177
|
-
## Instructions
|
|
178
|
-
|
|
179
|
-
Review the following items extracted from the consolidated implementation plan
|
|
180
|
-
authored after your initial analysis. For EACH item, respond with exactly one verdict:
|
|
181
|
-
|
|
182
|
-
- **AGREE**: The item is executable as written and internally consistent with
|
|
183
|
-
other items in the plan.
|
|
184
|
-
- **DISAGREE**: The item is broken. Cite which kind of breakage:
|
|
185
|
-
(a) referenced file path / symbol mismatches another step or option,
|
|
186
|
-
(b) command is not executable or is ambiguous,
|
|
187
|
-
(c) validation signal is not observable,
|
|
188
|
-
(d) rollback violates commit / dependency order,
|
|
189
|
-
(e) item contradicts the trade-off matrix.
|
|
190
|
-
- **SUPPLEMENT**: The item is sound but a dependency / edge case / precondition
|
|
191
|
-
is missing.
|
|
192
|
-
|
|
193
|
-
Do NOT re-analyze the original requirements. Judge solely from plan internal
|
|
194
|
-
consistency and stated commands / paths.
|
|
195
|
-
|
|
196
|
-
## Plan items to verify
|
|
197
|
-
|
|
198
|
-
### P-Step-3 [TICKETID: <id>]: <one-line summary>
|
|
199
|
-
**From section**: 4.5.4 Stepwise Execution Order
|
|
200
|
-
**Original text**:
|
|
201
|
-
> <verbatim quote of the step>
|
|
202
|
-
|
|
203
|
-
**Check**:
|
|
204
|
-
- Are referenced file paths consistent with the option's File Structure list?
|
|
205
|
-
- Is the named command executable as written?
|
|
206
|
-
- Does the success criterion produce an observable signal?
|
|
207
|
-
|
|
208
|
-
### P-Opt-2 [TICKETID: <id>]: <one-line summary>
|
|
209
|
-
...
|
|
210
|
-
|
|
211
|
-
## Response format
|
|
212
|
-
|
|
213
|
-
### P-Step-3
|
|
214
|
-
**Verdict**: AGREE | DISAGREE(<a|b|c|d|e>) | SUPPLEMENT
|
|
215
|
-
**Explanation**: <2-3 sentences>
|
|
216
|
-
|
|
217
|
-
### P-Opt-2
|
|
218
|
-
...
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
## 8. 마이그레이션 / 호환성
|
|
222
|
-
|
|
223
|
-
- **신규 task-key**: manifest에 plan_body_verification 기본값 ON으로 기록. 정상 동작.
|
|
224
|
-
- **legacy task-key** (이미 implementation-planning을 한 번 돌렸으나 implementation으로 넘어가지 않은 task-key): manifest에 `plan_body_verification` 키 없음.
|
|
225
|
-
- resume 시 lead가 기본값 ON으로 채워 1라운드 dispatch를 추가 실행한다.
|
|
226
|
-
- **사용자 영향**: 기존 IP 산출물이 있어도 resume 시 한 라운드가 추가됨. 원치 않는 경우 resume 명령에 `--no-plan-verification`을 명시하거나 project config로 영구 off.
|
|
227
|
-
- 이 동작은 `CHANGES.md` 의 `사용자 영향:` 라인에 명시한다.
|
|
228
|
-
|
|
229
|
-
## 9. 검증 가능성 / 테스트 포인트
|
|
230
|
-
|
|
231
|
-
1. **manifest 기본값 / override**: `plan_body_verification` 키 누락 시 기본값 주입, `--no-plan-verification` 명령행 옵션 우선순위 (unit).
|
|
232
|
-
2. **plan-item 파서**: §3 분리 규칙대로 P-Opt / P-Step / P-Dep / P-Val / P-Rb 가 추출되는지, Ticket ID 태그 보존 (unit).
|
|
233
|
-
3. **verdict aggregation**: §5 매핑 4가지 케이스 모두 (unit).
|
|
234
|
-
4. **majority DISAGREE → clarification row 변환** round-trip: P-* item → `## 5. Clarification Items` row(`Blocks=approval`) → `--resume-clarification` 흐름에서 사용자 응답이 다음 run에 carry-in (unit + e2e).
|
|
235
|
-
5. **Approval 체크박스 라인 조건부 렌더**: gate 결과 4가지에 따라 라인 존재/부재 (unit + validator).
|
|
236
|
-
6. **e2e 시나리오**: 의도적으로 깨진 plan(예: step의 file path가 option의 File Structure와 불일치)을 inject한 task를 돌려, DISAGREE 발생 → clarification 자동 추가 → resume 후 통과까지의 full happy path (e2e).
|
|
237
|
-
7. **워커 non-result**: 모든 워커가 timeout / error 일 때 `aborted-non-result` 분류 + Approval 라인 부재 + clarification에 "could not run" row (unit).
|
|
238
|
-
|
|
239
|
-
## 10. 위험 / 미해결 항목
|
|
240
|
-
|
|
241
|
-
1. **report-writer 재호출 안 함** (Q4=b) 으로 인해, majority DISAGREE → clarification 변환 누락이 발생하면 사용자에게 dead-end(Approval 라인은 사라졌는데 무엇을 고쳐야 하는지 안 보이는 상태) 가 노출된다. 변환 round-trip 단위 테스트를 BLOCKING으로 잠근다.
|
|
242
|
-
|
|
243
|
-
2. **convergence 스킬 안에 mode 두 개 공존** (finding / plan-body). 본문 첫 줄에 MUTUAL EXCLUSION 박스를 두고 future Claude 가 두 큐를 섞지 않도록 명시.
|
|
244
|
-
|
|
245
|
-
3. **maxRounds=1의 `contested` 정의**: 기존 finding convergence의 `contested`는 maxRounds 도달 시점의 잔류 큐에 부여되는 라벨. plan-body 모드에서 maxRounds=1 인 경우 round 1 종료 직후의 partial-consensus와 사실상 구별 불가. §5 표에서 `contested → partial-consensus 로 fold-in` 으로 명시했지만, 사용자가 manifest 에서 maxRounds=2,3 으로 override 한 경우엔 finding 모드와 동일한 정의가 살아남는다는 점을 스킬 본문에 명시 필요.
|
|
246
|
-
|
|
247
|
-
4. **plan-item 파서의 robustness**: report-writer 가 markdown 구조를 약간 다르게 작성할 가능성(예: option 헤더 들여쓰기 깊이). 파서는 `## 4.5`, `### 4.5.x` 헤더 + `Stepwise Execution Order` substring 같은 anchored 검색을 사용하고, 추출 실패 시 `aborted-non-result` 와 동등하게 처리한다.
|
|
248
|
-
|
|
249
|
-
5. **CLI flag 단일 진입점**: 메모리상의 invariant(`prepare_task_bundle` 단일 수렴) 를 유지해야 함. flag → manifest 의 변환은 Python 측 한 곳에서만 수행되도록 분기 막기.
|
|
250
|
-
|
|
251
|
-
## 11. 후속 작업 (out of scope)
|
|
252
|
-
|
|
253
|
-
- error-analysis 결과물 (cause analysis 통합본) 에도 유사한 검증 라운드를 추가할지 여부 — 본 spec 범위 밖. plan-body 검증이 안정화된 후 별도 spec으로 검토.
|
|
254
|
-
- requirements-discovery 의 routing decision 자체에 대한 검증 라운드 — 동일하게 후속 검토 대상.
|
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
# Final Report Language Configuration — Design Spec
|
|
2
|
-
|
|
3
|
-
- Date: 2026-05-20
|
|
4
|
-
- Status: Approved (pending writing-plans)
|
|
5
|
-
- Owner: Claude lead (this session)
|
|
6
|
-
- Related: `templates/reports/final-report.template.md`, `scripts/okstra-render-final-report.py`, `skills/okstra-setup/SKILL.md`, `skills/okstra-report-writer/SKILL.md`, `agents/SKILL.md`
|
|
7
|
-
|
|
8
|
-
## 1. Problem
|
|
9
|
-
|
|
10
|
-
The okstra final report is currently hardcoded to Korean in three places:
|
|
11
|
-
|
|
12
|
-
1. `skills/okstra-report-writer/SKILL.md` Writing Guidelines — `Write the final report body in Korean.`
|
|
13
|
-
2. `templates/reports/final-report.template.md` — ~30–40 lines of Korean fixed text (section intros, empty-state lines, column headers, token-summary "읽는 법" block, release-handoff 4.6.x labels, etc.).
|
|
14
|
-
3. `agents/SKILL.md` line 322 — lead's post-persistence reply hardcoded to Korean.
|
|
15
|
-
|
|
16
|
-
There is no way to opt into English (or any other language) without manually patching skill / template files. The user request: add a setup step that selects the final-report language, defaulting to English.
|
|
17
|
-
|
|
18
|
-
## 2. Goals & non-goals
|
|
19
|
-
|
|
20
|
-
### Goals
|
|
21
|
-
|
|
22
|
-
- One project-level setting (`reportLanguage`) decides the language of (a) the prose authored by the report-writer worker and (b) the fixed labels rendered from the template.
|
|
23
|
-
- Default for **new** setups is English. Default for **existing** projects whose `project.json` predates this change is `auto` (no surprise switch to English for Korean-speaking users).
|
|
24
|
-
- `auto` resolves to `en` or `ko` based on the task brief's main prose language.
|
|
25
|
-
- Validator-checked English identifiers (`Option Candidates`, `Verdict Token`, `accepted` / `conditional-accept` / `blocked`, etc.) remain English in both languages.
|
|
26
|
-
|
|
27
|
-
### Non-goals (this spec)
|
|
28
|
-
|
|
29
|
-
- Worker analysis prose, lead user-facing messages outside the final-report flow, `okstra-status` / `okstra-schedule` skill responses, and `prompts/profiles/*.md` Korean preferences are **out of scope**.
|
|
30
|
-
- Languages other than `en` and `ko`. (Adding a third language later requires only a new `i18n/<lang>.yaml` file plus extending the enum.)
|
|
31
|
-
- Worker-results audit files under `runs/.../worker-results/*.md` stay in their current language (Korean prose by default).
|
|
32
|
-
|
|
33
|
-
## 3. Data model
|
|
34
|
-
|
|
35
|
-
### 3.1 `project.json` — new optional field
|
|
36
|
-
|
|
37
|
-
```json
|
|
38
|
-
{
|
|
39
|
-
"projectId": "...",
|
|
40
|
-
"projectRoot": "...",
|
|
41
|
-
"reportLanguage": "auto" | "en" | "ko"
|
|
42
|
-
}
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
- Listed as a user-managed field in `scripts/okstra_project/resolver.py` so runtime `upsert_project_json` preserves it across `okstra setup` / `okstra run` invocations (same treatment as `worktreeSyncDirs`, `qaCommands`, `prTemplatePath`).
|
|
46
|
-
- Absent field ⇒ runtime treats as `"auto"`.
|
|
47
|
-
|
|
48
|
-
### 3.2 `~/.okstra/config.json` — optional global fallback
|
|
49
|
-
|
|
50
|
-
```json
|
|
51
|
-
{ "reportLanguage": "auto" | "en" | "ko" }
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Same enum, used only when `project.json` doesn't have the field.
|
|
55
|
-
|
|
56
|
-
### 3.3 `final-report-v1.0.schema.json` — audit field
|
|
57
|
-
|
|
58
|
-
Add required `meta.reportLanguage` ∈ `{"en", "ko"}` (no `"auto"` — the lead resolves before dispatching).
|
|
59
|
-
|
|
60
|
-
Rationale: the renderer needs an SSOT inside the data.json so re-rendering after the fact (e.g. someone re-runs `okstra-render-final-report.py` without a `--report-language` flag) produces the same artifact.
|
|
61
|
-
|
|
62
|
-
### 3.4 Resolution priority (lead)
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
CLI flag `--report-language`
|
|
66
|
-
> project.json.reportLanguage
|
|
67
|
-
> ~/.okstra/config.json.reportLanguage
|
|
68
|
-
> "auto"
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
If the resolved value is `"auto"`, the lead inspects the task brief and picks `en` or `ko` based on its main prose language. Default to `en` when the brief is mostly code/identifiers and the language is ambiguous. The lead writes the resolved literal `en`/`ko` into the report-writer dispatch prompt's `**Report Language:**` line and into `data.json.meta.reportLanguage`.
|
|
72
|
-
|
|
73
|
-
## 4. Setup flow
|
|
74
|
-
|
|
75
|
-
### 4.1 `skills/okstra-setup/SKILL.md` — add Step 4.9
|
|
76
|
-
|
|
77
|
-
Insert between current Step 4.8 (PR body template) and Step 5 (`okstra doctor`).
|
|
78
|
-
|
|
79
|
-
```
|
|
80
|
-
## Step 4.9 (optional): choose final report language
|
|
81
|
-
|
|
82
|
-
Skip-friendly. Default behaviour when this step is skipped is `auto`
|
|
83
|
-
(report-writer infers from the task brief, falling back to English).
|
|
84
|
-
|
|
85
|
-
AskUserQuestion (fixed options):
|
|
86
|
-
- Question: "Final report를 어느 언어로 작성할까요?"
|
|
87
|
-
- Options:
|
|
88
|
-
1. English (recommended) → reportLanguage: "en"
|
|
89
|
-
2. 한국어 → reportLanguage: "ko"
|
|
90
|
-
3. Auto (task brief 언어로 추론, 불분명하면 영어) → reportLanguage: "auto"
|
|
91
|
-
|
|
92
|
-
After selection:
|
|
93
|
-
okstra config set report-language <en|ko|auto> --scope project
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Project scope only at this step. Global scope is mentioned in README but not prompted during setup (advanced).
|
|
97
|
-
|
|
98
|
-
### 4.2 New CLI subcommands
|
|
99
|
-
|
|
100
|
-
Same handler pattern as the existing `okstra config set pr-template-path`:
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
okstra config set report-language <en|ko|auto> --scope <project|global>
|
|
104
|
-
okstra config get report-language --scope <project|global>
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Validation:
|
|
108
|
-
- Value must be one of `en`, `ko`, `auto`. Any other value exits `1` with a clear error.
|
|
109
|
-
- `--scope` is required and must be `project` or `global`.
|
|
110
|
-
- Atomic write (`config-write` path used by `pr-template-path`).
|
|
111
|
-
- Output: JSON to stdout naming which file was updated, same shape as the existing `pr-template-path` command.
|
|
112
|
-
|
|
113
|
-
Confirm during implementation that `okstra config get` already exists for `pr-template-path`; if not, extend it to support both keys.
|
|
114
|
-
|
|
115
|
-
## 5. Template i18n
|
|
116
|
-
|
|
117
|
-
### 5.1 Dictionary location
|
|
118
|
-
|
|
119
|
-
```
|
|
120
|
-
templates/reports/i18n/en.yaml
|
|
121
|
-
templates/reports/i18n/ko.yaml
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
YAML chosen because the Korean help text (e.g. the "읽는 법" block) is multi-line and benefits from `|` literal blocks; JSON would require escaped `\n` everywhere. If PyYAML is not already a runtime dependency of okstra Python (to be confirmed during implementation), fall back to JSON with `\n` escapes.
|
|
125
|
-
|
|
126
|
-
### 5.2 Key naming
|
|
127
|
-
|
|
128
|
-
Dot-namespaced groups. Jinja accesses via `t.section.subkey`.
|
|
129
|
-
|
|
130
|
-
```yaml
|
|
131
|
-
verdictCard:
|
|
132
|
-
intro: >-
|
|
133
|
-
At-a-glance verdict card. Every value in this table MUST exactly match
|
|
134
|
-
the authoritative values in `## 2. Final Verdict` and `## 6.
|
|
135
|
-
Recommended Next Steps`.
|
|
136
|
-
|
|
137
|
-
tokenSummary:
|
|
138
|
-
heading: "Token Usage Summary"
|
|
139
|
-
columns:
|
|
140
|
-
item: "Item"
|
|
141
|
-
raw: "Raw tokens"
|
|
142
|
-
billable: "Billable tokens (input-equiv.)"
|
|
143
|
-
cost: "Cost (USD)"
|
|
144
|
-
rows:
|
|
145
|
-
lead: "Lead"
|
|
146
|
-
workerTotal: "Worker subtotal"
|
|
147
|
-
grandTotal: "**Grand total**"
|
|
148
|
-
cliExtra: "Codex/Gemini CLI add-on"
|
|
149
|
-
howToRead: |
|
|
150
|
-
**How to read**: "Raw tokens" is the sum of input + output +
|
|
151
|
-
cache_creation + cache_read processed by the model …
|
|
152
|
-
|
|
153
|
-
emptyState:
|
|
154
|
-
consensusItems: "- No consensus items."
|
|
155
|
-
contestedItems: "- No items missing consensus."
|
|
156
|
-
primaryEvidence: "- No primary evidence."
|
|
157
|
-
secondaryEvidence: "- No secondary evidence or alternate interpretations."
|
|
158
|
-
risks: "- No missing information or risks."
|
|
159
|
-
dependencyRisk: "- No dependency / migration risks."
|
|
160
|
-
dissent: "- No dissenting opinions."
|
|
161
|
-
outOfPlanEdits: "- No out-of-plan edits."
|
|
162
|
-
noFollowUp: "- No follow-up tasks. The next phase for this run is in §6 (Recommended Next Steps)."
|
|
163
|
-
noClarification: "- No additional information requested. The Section 2 verdict stands as-is."
|
|
164
|
-
|
|
165
|
-
sectionAside:
|
|
166
|
-
dependencyRisk: "Dependency / Migration Risk"
|
|
167
|
-
validationChecklist: "Validation Checklist"
|
|
168
|
-
rollbackStrategy: "Rollback Strategy"
|
|
169
|
-
planBodyVerification: "Plan Body Verification"
|
|
170
|
-
recommendedOption: "Recommended Option"
|
|
171
|
-
optionCandidates: "Option Candidates"
|
|
172
|
-
tradeOffMatrix: "Trade-off Matrix"
|
|
173
|
-
stepwiseExecutionOrder: "Stepwise Execution Order"
|
|
174
|
-
|
|
175
|
-
# ... and similar groups for release-handoff 4.6.x, evidence column
|
|
176
|
-
# headers, etc.
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
The `ko.yaml` mirror keeps Korean strings; **both files must have identical key sets** (enforced by a unit test — see §8).
|
|
180
|
-
|
|
181
|
-
### 5.3 Validator-checked English substrings
|
|
182
|
-
|
|
183
|
-
These remain English in both `en.yaml` and `ko.yaml` (i.e. `sectionAside.optionCandidates` in `ko.yaml` is still the English string `Option Candidates`):
|
|
184
|
-
|
|
185
|
-
- Phase-specific heading anchors: `Option Candidates`, `Trade-off`, `Recommended Option`, `Stepwise Execution Order`, `Dependency`, `Validation Checklist`, `Rollback`, `User Approval Request`, `Plan Body Verification`, `Gate result:`
|
|
186
|
-
- Verdict tokens: `accepted`, `conditional-accept`, `blocked`, `not-applicable`
|
|
187
|
-
- Direction tokens: `continue-investigation`, `begin-implementation`, `approve`, `reject`, `hold`
|
|
188
|
-
|
|
189
|
-
Korean parenthetical aside is i18n'd. For Korean reports this renders as `### Recommended Option (권장 옵션)`; for English reports it renders as `### Recommended Option (Recommended Option)` — which looks silly. **Decision:** when Korean and English would produce the same string, the template omits the parenthetical entirely. Template form:
|
|
190
|
-
|
|
191
|
-
```jinja
|
|
192
|
-
### Recommended Option{% if t.sectionAside.recommendedOption != "Recommended Option" %} ({{ t.sectionAside.recommendedOption }}){% endif %}
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### 5.4 Missing-key policy
|
|
196
|
-
|
|
197
|
-
Jinja `Environment(undefined=StrictUndefined)` — referencing a missing key raises `UndefinedError` at render time. No silent fallback to the key name. This makes "I forgot to translate X" fail loudly during e2e instead of shipping `{{ t.foo.bar }}` literal in production reports.
|
|
198
|
-
|
|
199
|
-
### 5.5 Template conversion scope
|
|
200
|
-
|
|
201
|
-
Run `grep -P '[\x{AC00}-\x{D7A3}]'` (Korean Unicode range) against `templates/reports/final-report.template.md` until 0 matches remain. Estimated 50–70 i18n keys across the categories:
|
|
202
|
-
|
|
203
|
-
1. Section intro prose (lines 35, 49, 54, 84, 131, 243, 275, 525)
|
|
204
|
-
2. Empty-state lines (lines 122, 136, 162, 176, 188, 248, 299, 424, 449, 495, 527, 530, 570)
|
|
205
|
-
3. Column headers (line 56 "한 줄 요약 / 출처", line 86 "처리 토큰 / 환산 토큰 / 비용", line 267 "확인 방법")
|
|
206
|
-
4. Heading Korean aside (lines 245, 257, 273, the 4.5.x series)
|
|
207
|
-
5. The token-summary "읽는 법" blockquote
|
|
208
|
-
6. release-handoff 4.6.x Korean labels (lines 325, 329, 448, 473, etc.)
|
|
209
|
-
|
|
210
|
-
Identifier strings (`Verdict Token`, JSON code blocks, model names, file paths) stay verbatim.
|
|
211
|
-
|
|
212
|
-
## 6. Renderer changes
|
|
213
|
-
|
|
214
|
-
### 6.1 `scripts/okstra-render-final-report.py`
|
|
215
|
-
|
|
216
|
-
```python
|
|
217
|
-
import argparse, json, yaml
|
|
218
|
-
from pathlib import Path
|
|
219
|
-
import jinja2
|
|
220
|
-
|
|
221
|
-
def main():
|
|
222
|
-
ap = argparse.ArgumentParser()
|
|
223
|
-
ap.add_argument("data_json", type=Path)
|
|
224
|
-
ap.add_argument("--report-language", choices=["en", "ko"], default=None)
|
|
225
|
-
args = ap.parse_args()
|
|
226
|
-
|
|
227
|
-
data = json.loads(args.data_json.read_text())
|
|
228
|
-
lang = (
|
|
229
|
-
args.report_language
|
|
230
|
-
or data.get("meta", {}).get("reportLanguage")
|
|
231
|
-
or "en"
|
|
232
|
-
)
|
|
233
|
-
if lang not in {"en", "ko"}:
|
|
234
|
-
raise SystemExit(f"reportLanguage must be 'en' or 'ko', got {lang!r}")
|
|
235
|
-
|
|
236
|
-
i18n_path = Path(__file__).parent.parent / "templates" / "reports" / "i18n" / f"{lang}.yaml"
|
|
237
|
-
i18n = yaml.safe_load(i18n_path.read_text())
|
|
238
|
-
|
|
239
|
-
env = jinja2.Environment(
|
|
240
|
-
loader=jinja2.FileSystemLoader(...),
|
|
241
|
-
undefined=jinja2.StrictUndefined,
|
|
242
|
-
autoescape=False,
|
|
243
|
-
keep_trailing_newline=True,
|
|
244
|
-
)
|
|
245
|
-
tmpl = env.get_template("final-report.template.md")
|
|
246
|
-
out_path = args.data_json.with_suffix("").with_suffix(".md")
|
|
247
|
-
out_path.write_text(tmpl.render(**data, t=i18n))
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
(Sketch — actual file structure follows the existing renderer's conventions; the changes are: `--report-language` flag, `meta.reportLanguage` read, YAML loader, `t=i18n` context key, `StrictUndefined`.)
|
|
251
|
-
|
|
252
|
-
### 6.2 `scripts/okstra-render-report-views.py`
|
|
253
|
-
|
|
254
|
-
Reads the rendered markdown — no logic change needed. The HTML view inherits whatever language the markdown was rendered in.
|
|
255
|
-
|
|
256
|
-
## 7. Worker / lead contract changes
|
|
257
|
-
|
|
258
|
-
### 7.1 `agents/SKILL.md` (Claude lead)
|
|
259
|
-
|
|
260
|
-
Add to the Phase 6 preparation checklist:
|
|
261
|
-
|
|
262
|
-
```
|
|
263
|
-
- Resolve report language: read `project.json.reportLanguage`
|
|
264
|
-
(fallback `~/.okstra/config.json.reportLanguage`, then literal `auto`).
|
|
265
|
-
If the resolved value is `auto`, inspect the task brief and pick `en`
|
|
266
|
-
or `ko` based on its main prose language (default `en` when the brief
|
|
267
|
-
is mostly code/identifiers). Pass the final `en`/`ko` value as
|
|
268
|
-
`**Report Language:**` in the report-writer dispatch prompt and ensure
|
|
269
|
-
the worker writes the same value into `data.json.meta.reportLanguage`.
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
Replace line 322:
|
|
273
|
-
|
|
274
|
-
```diff
|
|
275
|
-
- After persistence, reply briefly in Korean with: completion status, ...
|
|
276
|
-
+ After persistence, reply briefly in the resolved Report Language with:
|
|
277
|
-
+ completion status, ...
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
### 7.2 `skills/okstra-report-writer/SKILL.md`
|
|
281
|
-
|
|
282
|
-
Add a new entry to the Phase 6 dispatch prompt's required-header list. The list currently has 11 items; insert the new entry immediately after the convergence-classifications item (current item 9) and renumber the remaining items:
|
|
283
|
-
|
|
284
|
-
```
|
|
285
|
-
**Report Language:** <en|ko> # auto must be pre-resolved by the lead;
|
|
286
|
-
# the worker writes this verbatim into
|
|
287
|
-
# data.json.meta.reportLanguage
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
Replace the two hardcoded "Korean" lines (Writing Guidelines + Response after Persistence):
|
|
291
|
-
|
|
292
|
-
```diff
|
|
293
|
-
- - Write the final report body in Korean.
|
|
294
|
-
+ - Write the final report body in the language passed as **Report Language**
|
|
295
|
-
+ in the dispatch prompt. The template's fixed labels (section asides,
|
|
296
|
-
+ empty-states, token summary, etc.) are i18n-rendered by
|
|
297
|
-
+ `okstra-render-final-report.py` from `templates/reports/i18n/<lang>.yaml`;
|
|
298
|
-
+ focus on the prose you author (Section 1 categories, Section 3 evidence
|
|
299
|
-
+ narratives, Section 4 risks, Section 6 recommendations, etc.).
|
|
300
|
-
+ Code identifiers, file paths, model names, status tokens, and the
|
|
301
|
-
+ validator-checked English substrings stay in English regardless of
|
|
302
|
-
+ Report Language.
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
```diff
|
|
306
|
-
- Provide a concise report in Korean covering the following:
|
|
307
|
-
+ Provide a concise report in the Report Language covering the following:
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
Add to the data.json contract (alongside the token-cell-null paragraph):
|
|
311
|
-
|
|
312
|
-
```
|
|
313
|
-
- Set `meta.reportLanguage` to the resolved `en` or `ko` value passed in
|
|
314
|
-
**Report Language**. `auto` is forbidden here — the lead has already
|
|
315
|
-
resolved it. The renderer reads this field as the SSOT when no CLI
|
|
316
|
-
`--report-language` flag is given.
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
### 7.3 `agents/workers/report-writer-worker.md`
|
|
320
|
-
|
|
321
|
-
Add `templates/reports/i18n/en.yaml` and `templates/reports/i18n/ko.yaml` to the worker's reading set. One-line reminder that the `Report Language` header value goes into `data.json.meta.reportLanguage` verbatim.
|
|
322
|
-
|
|
323
|
-
## 8. Tests
|
|
324
|
-
|
|
325
|
-
### 8.1 Unit (`tests/`)
|
|
326
|
-
|
|
327
|
-
- `test_report_language_resolver.py` — resolution priority (CLI flag > project.json > global config > `"auto"`).
|
|
328
|
-
- `test_report_language_config_set.py` — `okstra config set report-language` accepts `en`/`ko`/`auto`, rejects others; writes to project.json or `~/.okstra/config.json` per scope.
|
|
329
|
-
- `test_i18n_keysets_match.py` — `en.yaml` and `ko.yaml` have **identical key sets** (set diff must be empty in both directions).
|
|
330
|
-
- `test_i18n_missing_key_raises.py` — referencing an undefined `t.foo.bar` from the template raises `jinja2.UndefinedError`.
|
|
331
|
-
- `test_render_meta_report_language.py` — renderer reads `data.json.meta.reportLanguage` as SSOT when no `--report-language` flag is given.
|
|
332
|
-
- `test_template_no_korean_glyphs.py` — `grep -P '[\x{AC00}-\x{D7A3}]'` against `templates/reports/final-report.template.md` returns zero matches. (Regression guard for "someone re-introduced Korean fixed text".)
|
|
333
|
-
|
|
334
|
-
### 8.2 E2E (`tests-e2e/`)
|
|
335
|
-
|
|
336
|
-
- `scenario-N-final-report-en.sh` — full okstra run with `reportLanguage: "en"`. Asserts the rendered markdown contains the English `Token Usage Summary` heading and does NOT contain Korean characters in template-owned regions.
|
|
337
|
-
- `scenario-M-final-report-ko.sh` — same with `reportLanguage: "ko"`. Asserts the Korean `토큰 사용량 요약` heading is present.
|
|
338
|
-
|
|
339
|
-
## 9. Migration / rollout
|
|
340
|
-
|
|
341
|
-
- pre-v1 → no compat shims. Existing reports are not re-rendered.
|
|
342
|
-
- Existing `project.json` files have no `reportLanguage` field → runtime treats as `"auto"`. Korean-speaking users writing Korean briefs continue to get Korean reports without any action.
|
|
343
|
-
- New `okstra setup` runs see Step 4.9 with `English` as the recommended default — users explicitly opt into the new default through that prompt.
|
|
344
|
-
- `CHANGES.md` entry:
|
|
345
|
-
|
|
346
|
-
```
|
|
347
|
-
### feat(setup): final report language is now configurable
|
|
348
|
-
- 사용자 영향: 신규 `okstra setup` 의 final report 기본 언어가 영어로 바뀝니다.
|
|
349
|
-
기존 프로젝트(`project.json.reportLanguage` 미설정)는 `auto` 로 동작하여
|
|
350
|
-
task brief 의 주 서술 언어를 따라가므로, 한국어 brief 를 쓰던 사용자에게
|
|
351
|
-
재설정 없이 종전과 같은 한국어 보고서가 출력됩니다.
|
|
352
|
-
- 새 CLI: `okstra config set report-language <en|ko|auto> --scope <project|global>`.
|
|
353
|
-
- i18n 사전: `templates/reports/i18n/{en,ko}.yaml`.
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
## 10. Files touched (final list)
|
|
357
|
-
|
|
358
|
-
| File | Change |
|
|
359
|
-
|---|---|
|
|
360
|
-
| `templates/reports/final-report.template.md` | Korean fixed text → `{{ t.* }}` i18n references |
|
|
361
|
-
| `templates/reports/i18n/en.yaml` | NEW |
|
|
362
|
-
| `templates/reports/i18n/ko.yaml` | NEW |
|
|
363
|
-
| `scripts/okstra-render-final-report.py` | `--report-language` flag, YAML loader, `StrictUndefined`, `t=i18n` |
|
|
364
|
-
| `schemas/final-report-v1.0.schema.json` | Add required `meta.reportLanguage` ∈ `{en, ko}` |
|
|
365
|
-
| `scripts/okstra_project/resolver.py` | `reportLanguage` added to preserved user fields list |
|
|
366
|
-
| `src/config.mjs` (or wherever `pr-template-path` lives) | `set/get report-language` subcommands |
|
|
367
|
-
| `skills/okstra-setup/SKILL.md` | Step 4.9 |
|
|
368
|
-
| `skills/okstra-report-writer/SKILL.md` | Dispatch prompt header + Writing Guidelines + data.json contract |
|
|
369
|
-
| `agents/SKILL.md` | Phase 6 prep checklist + line 322 |
|
|
370
|
-
| `agents/workers/report-writer-worker.md` | Reading set + `meta.reportLanguage` reminder |
|
|
371
|
-
| `tests/test_*.py` (6 new) | See §8.1 |
|
|
372
|
-
| `tests-e2e/scenario-N-final-report-en.sh` | NEW |
|
|
373
|
-
| `tests-e2e/scenario-M-final-report-ko.sh` | NEW |
|
|
374
|
-
| `CHANGES.md` | New entry per §9 |
|
|
375
|
-
|
|
376
|
-
## 11. Open implementation questions
|
|
377
|
-
|
|
378
|
-
To be resolved during writing-plans / implementation:
|
|
379
|
-
|
|
380
|
-
1. Whether PyYAML is already a runtime dependency of okstra Python (otherwise fall back to JSON dictionaries).
|
|
381
|
-
2. Whether `okstra config get` exists today for `pr-template-path` — extend if yes, add if no.
|
|
382
|
-
3. Exact i18n key namespacing for the release-handoff 4.6.x labels (largest single chunk of Korean text outside §4.5).
|
|
383
|
-
4. Test scenario sequencing — pick free `scenario-NN` numbers in `tests-e2e/`.
|