okstra 0.39.0 → 0.40.0
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/docs/kr/architecture.md +10 -2
- package/docs/kr/cli.md +1 -1
- package/docs/project-structure-overview.md +1 -1
- package/docs/superpowers/plans/2026-06-02-final-verification-protocol-hardening.md +326 -0
- package/docs/superpowers/plans/2026-06-02-okstra-run-branch-confirm-step.md +337 -0
- package/docs/superpowers/plans/2026-06-02-okstra-run-phase-pane-cleanup.md +410 -0
- package/docs/superpowers/specs/2026-06-02-okstra-run-branch-confirm-step-design.md +113 -0
- package/docs/superpowers/specs/2026-06-02-okstra-run-phase-pane-cleanup-design.md +173 -0
- package/package.json +3 -2
- package/runtime/BUILD.json +2 -2
- package/runtime/{python → bin}/lib/okstra/usage.sh +3 -2
- package/runtime/bin/okstra-codex-exec.sh +3 -3
- package/runtime/bin/okstra-trace-cleanup.sh +64 -26
- package/runtime/prompts/profiles/_common-contract.md +9 -5
- package/runtime/prompts/profiles/final-verification.md +18 -16
- package/runtime/prompts/profiles/implementation-planning.md +1 -0
- package/runtime/prompts/wizard/prompts.ko.json +11 -0
- package/runtime/python/okstra_ctl/consumers.py +1 -1
- package/runtime/python/okstra_ctl/migrate.py +18 -6
- package/runtime/python/okstra_ctl/reconcile.py +2 -2
- package/runtime/python/okstra_ctl/render_final_report.py +0 -1
- package/runtime/python/okstra_ctl/run_context.py +9 -12
- package/runtime/python/okstra_ctl/wizard.py +70 -5
- package/runtime/python/okstra_ctl/worktree.py +74 -27
- package/runtime/schemas/final-report-v1.0.schema.json +34 -27
- package/runtime/skills/okstra-convergence/SKILL.md +1 -1
- package/runtime/skills/okstra-run/SKILL.md +2 -0
- package/runtime/templates/reports/final-report.template.md +24 -13
- package/runtime/templates/reports/final-verification-input.template.md +16 -5
- package/runtime/templates/reports/i18n/en.json +6 -3
- package/runtime/templates/reports/i18n/ko.json +6 -3
- package/runtime/templates/worker-prompt-preamble.md +7 -0
- package/runtime/validators/lib/fixtures.sh +2 -2
- package/runtime/validators/lib/validate-assets.sh +9 -0
- package/runtime/validators/validate-implementation-plan-stages.py +19 -11
- package/runtime/validators/validate-run.py +88 -0
- package/runtime/validators/validate-schedule.py +4 -4
- package/src/_proc.mjs +31 -0
- package/src/check-project.mjs +1 -25
- package/src/config.mjs +7 -31
- package/src/doctor.mjs +10 -29
- package/src/install.mjs +2 -10
- package/src/migrate.mjs +1 -18
- package/src/setup.mjs +1 -24
- /package/runtime/{python → bin}/lib/okstra/cli.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra/globals.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra/interactive.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra/project-resolver.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/cmd-batch.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/cmd-list.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/cmd-open.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/cmd-projects.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/cmd-reconcile.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/cmd-reindex.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/cmd-rerun.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/cmd-show.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/cmd-tail.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/main.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/prepare.sh +0 -0
- /package/runtime/{python → bin}/lib/okstra-ctl/usage.sh +0 -0
package/docs/kr/architecture.md
CHANGED
|
@@ -384,6 +384,13 @@ okstra phase 는 PRD / issue file 을 직접 쓰지 않습니다. 동등한 결
|
|
|
384
384
|
위상정렬이 담고, task 화 이후의 통합 일정은 okstra-schedule 이 맡는다. okstra-brief 는
|
|
385
385
|
이 경로에 개입하지 않는다. 검증: `validators/validate_fanout.py`(validate-run 훅).
|
|
386
386
|
|
|
387
|
+
### branch_confirm (worktree 결정 확인)
|
|
388
|
+
|
|
389
|
+
okstra-run wizard 는 최종 confirm 직전에 `branch_confirm` 단계로 "새 브랜치/worktree 생성 vs
|
|
390
|
+
현재 worktree 재사용"을 명시 확인한다. 결정은 `worktree.preview_worktree_decision()`(부수효과 없음)
|
|
391
|
+
으로 미리보고, 같은 헬퍼를 `provision_task_worktree` 가 실행에 쓰므로 미리보기와 실제가 일치한다.
|
|
392
|
+
worktree 격리 동작 자체는 변경 없음(확인 게이트만).
|
|
393
|
+
|
|
387
394
|
|
|
388
395
|
---
|
|
389
396
|
|
|
@@ -855,7 +862,7 @@ Claude가 작성하는 최종 보고서는 아래 구조를 우선 사용합니
|
|
|
855
862
|
- `## 1. 문제 또는 검증 대상 요약` — §1.1 Consensus / §1.2 Differences 표 각각 `Source items (worker:item)` 컬럼 보존 (cross-worker traceability).
|
|
856
863
|
- `## 2. 에이전트별 실행 현황`
|
|
857
864
|
- `## 3. Cross Verification 결과` — §3.1 Primary Evidence 에 `Source items (worker:item)` + `Source (path:line / log)` 컬럼.
|
|
858
|
-
- `## 4. 최종 판단` — `implementation-planning` 의 §4.5.9 Plan Body Verification 은
|
|
865
|
+
- `## 4. 최종 판단` — `implementation-planning` 의 §4.5.9 Plan Body Verification 은 `Verdict details` 표 (5-열, plan item × worker) 하나로 emit.
|
|
859
866
|
- `## 5. Clarification Items` — 통합 8-열 표 한 곳. 기존 §5.1 / §5.2 / §4.5.8 / §4.5.9 Open Questions 는 deprecated 되어 validator 가 등장 시 fail.
|
|
860
867
|
- `## 6. 권장 다음 단계`
|
|
861
868
|
- `## Token Usage Summary` — sentinel (`pending` / `N/A` / `--` / `?` / 빈 셀) 또는 zero (`0` / `$0.00`) 박제 시 validator 가 출고를 차단합니다. `Codex/Gemini CLI 추가 비용` 행만 "CLI 미사용" 의미로 `$0.00` 허용.
|
|
@@ -904,7 +911,8 @@ Phase 7 step 1.5 가 final-report MD 한 본을 입력으로 두 view 를 결정
|
|
|
904
911
|
- `scripts/okstra-codex-exec.sh`, `scripts/okstra-gemini-exec.sh` 는 dispatch 마다 prompt path 옆에 `<prompt>.log` sidecar 를 만들고 stdout 을 거기로 mirror 합니다 (`tee`, `PIPESTATUS[0]` 로 종료코드 보존). stderr 은 같은 파일에 append (subagent stderr 캡처 contract 보존), 매 dispatch 시 truncate. 호출 subagent 의 `BashOutput` 폴링은 60s 간격이라 long-running run (analysis 의 large-codebase scan, implementation 의 cargo / pytest) 동안 사용자가 stalled state 를 탐지할 수 없는 문제를 해소합니다.
|
|
905
912
|
- `$TMUX` 가 셋팅된 lead 환경이면 wrapper 가 sibling pane 을 자동 분할해 `tail -F <log-path>` 를 띄웁니다. trace pane title 은 `<cli>-<role>-<pid>-trace[from=<caller-pane-id>]` (e.g. `codex-worker-93421-trace[from=%5]`, `gemini-executor-93422-trace[from=%5]`); 동일 시점에 caller (worker) pane title 도 `<cli>-<role>-<pid>` 로 셋팅됩니다. `<pid>` 는 wrapper 자기 자신의 PID 라서 동일 role 의 worker 가 둘 이상 동시에 spawn 돼도 서로 구분되며, trace title 에 박힌 caller pane id 덕분에 worker pane title 이 외부에서 덮어써져도 (Claude Code TUI 가 OSC 2 escape 로 자기 pane title 을 지속 emit) trace ↔ worker 매핑이 깨지지 않습니다. caller pane id 는 우선 `$TMUX_PANE` 에서, 비어 있으면 `tmux display-message -p '#{pane_id}'` (active pane) 으로 fallback — Claude Code Bash tool 환경처럼 `$TMUX_PANE` 가 stripping 돼도 caller pane 을 정확히 잡습니다. trace pane split 도 caller pane 을 `-t` 로 명시 anchor 합니다. role 은 wrapper 의 5번째 optional positional 인자이며, 누락 시 기본값 `worker` 로 떨어집니다. caller 가 다른 라벨(예: `executor`)을 원하면 5번째 인자로 명시해야 합니다. wrapper 진입 직전의 caller pane title 은 capture 해두고 EXIT trap 에서 복원하므로, dispatch 사이의 stale title 이 남지 않습니다. focus 는 caller pane 으로 복귀하고, CLI 종료 후 pane 은 유지돼 스크롤백 가능. `$TMUX` 미설정, split 실패, 구버전 tmux 등 모든 경로는 silent degrade.
|
|
906
913
|
- **Claude `/exit` 시 자동 정리**: trace pane 의 `tail -F` 는 tmux 셸의 자식이라 Claude 가 종료돼도 살아남는 문제를 막기 위해, wrapper 는 spawn 한 pane id 를 caller `$TMUX_PANE` 으로 키된 registry (`${TMPDIR:-/tmp}/okstra-trace-panes/<caller-pane>.list`) 에 append 합니다. `templates/reports/settings.template.json` 의 `hooks.SessionEnd` 가 `$HOME/.okstra/bin/okstra-trace-cleanup.sh` 를 호출해 자신의 caller pane registry 만 읽어 `tmux kill-pane` 합니다. caller pane 단위로 scope 가 잡혀 있어 같은 tmux 세션에 Claude 인스턴스가 여러 개 떠 있어도 서로의 trace pane 을 죽이지 않습니다. tmux 가 없거나 stale pane id 인 경우 silent degrade.
|
|
907
|
-
- **
|
|
914
|
+
- **phase 전환 시 자동 정리 + worker-agent pane 포함**: `okstra-trace-cleanup.sh` 는 trace pane(registry) 뿐 아니라 dispatch 된 서브에이전트가 점유하는 worker-agent pane(title `claude-worker` / `codex-worker` / `gemini-worker` / `report-writer-worker`)도 lead 세션(`tmux list-panes -s`) 범위에서 title allowlist 로 식별해 닫습니다. lead 자신의 pane(`$TMUX_PANE`)은 title 이 걸려도 절대 죽이지 않습니다. lead 는 새 phase 의 worker 를 dispatch 하기 직전(`PROGRESS: phase-5.5-convergence` / `phase-6-synthesis` 마커 직전) 이 스크립트를 무인자로 호출해 이전 phase 의 pane 을 prompt 없이 정리합니다.
|
|
915
|
+
- **Phase 종료 시 사용자 확인**: run 최종 종료 시점(마지막 단계)에 lead 가 `okstra-trace-cleanup.sh --list` 로 잔여 okstra pane(worker-agent + trace) 목록을 출력한 뒤 사용자에게 "모두 닫기 / 그대로 두기" 양자택일을 묻고 응답대로 처리합니다 (`prompts/profiles/_common-contract.md` 의 *Phase wrap-up* 항목). `$TMUX_PANE` 미설정 환경에서는 단계 자체가 silent-skip. `--list` 모드는 pane 을 죽이지 않고 `<pane_id>\t<pane_title>` 만 출력하므로 사용자가 무엇이 닫힐지 시각적으로 확인할 수 있습니다.
|
|
908
916
|
- 디스크 누적은 `okstra-logs` skill 이 read-only 로 인벤토리 + cleanup 명령을 제안합니다 (실행은 사용자 copy-paste).
|
|
909
917
|
|
|
910
918
|
### Linked-worktree `.git/` write 권한 (codex / gemini)
|
package/docs/kr/cli.md
CHANGED
|
@@ -591,4 +591,4 @@ chmod +x ~/.local/bin/okstra-ctl
|
|
|
591
591
|
|
|
592
592
|
### Live-log sidecar
|
|
593
593
|
|
|
594
|
-
codex / gemini wrapper 는 매 dispatch 마다 `runs/<task-type>/prompts/<worker>-prompt-<phase>-<seq>.log` sidecar 를 만들고 stdout / stderr 를 mirror 합니다. tmux 안에서 lead 를 띄우면 wrapper 가 자동으로 `tail -F` pane 을 분할합니다 (trace pane title: `<cli>-<role>-<pid>-trace`, caller (worker) pane title: `<cli>-<role>-<pid>` — wrapper PID 가 동일 role 의 동시 dispatch 를 구분합니다). 분할된 trace pane 은 caller `$TMUX_PANE` 으로 키된 registry 에 등록돼, Claude `/exit` 시 `SessionEnd` 훅이 `okstra-trace-cleanup.sh` 로 자동 정리합니다. 사용량 인벤토리와 `find … -delete` cleanup 명령은 `okstra-logs` skill 이 read-only 로 제안합니다. 자세한 와이어링은 [`docs/kr/architecture.md`](architecture.md) 의 *Live-log mirror* 절 참고.
|
|
594
|
+
codex / gemini wrapper 는 매 dispatch 마다 `runs/<task-type>/prompts/<worker>-prompt-<phase>-<seq>.log` sidecar 를 만들고 stdout / stderr 를 mirror 합니다. tmux 안에서 lead 를 띄우면 wrapper 가 자동으로 `tail -F` pane 을 분할합니다 (trace pane title: `<cli>-<role>-<pid>-trace`, caller (worker) pane title: `<cli>-<role>-<pid>` — wrapper PID 가 동일 role 의 동시 dispatch 를 구분합니다). 분할된 trace pane 은 caller `$TMUX_PANE` 으로 키된 registry 에 등록돼, Claude `/exit` 시 `SessionEnd` 훅이 `okstra-trace-cleanup.sh` 로 자동 정리합니다. 같은 스크립트는 dispatch 된 worker-agent pane(title `claude-worker` / `codex-worker` / `gemini-worker` / `report-writer-worker`)도 lead 세션 범위에서 함께 정리하며(lead 자신의 pane 은 제외), lead 는 새 phase dispatch 직전 이를 호출해 이전 phase 의 okstra pane 을 자동 정리합니다. 사용량 인벤토리와 `find … -delete` cleanup 명령은 `okstra-logs` skill 이 read-only 로 제안합니다. 자세한 와이어링은 [`docs/kr/architecture.md`](architecture.md) 의 *Live-log mirror* 절 참고.
|
|
@@ -163,7 +163,7 @@ Top-level scripts:
|
|
|
163
163
|
| `okstra-render-report-views.py` | Render slim MD + HTML views from final-report Markdown |
|
|
164
164
|
| `okstra-error-log.py` | Normalize worker/lead error sidecars |
|
|
165
165
|
| `okstra-spawn-followups.py` | Follow-up spawning helper |
|
|
166
|
-
| `okstra-trace-cleanup.sh` | tmux
|
|
166
|
+
| `okstra-trace-cleanup.sh` | tmux okstra pane cleanup (worker-agent + trace, lead pane 제외) |
|
|
167
167
|
|
|
168
168
|
### 4.3 `scripts/okstra_ctl/` — Python orchestration core
|
|
169
169
|
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# final-verification 검증 프로토콜 강화 Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** final-verification 을 "리뷰 의견 수집"에서 **target 일치성 → 요구사항 커버리지 → read-only validation → 구조화된 verdict** 로 이어지는 검증 프로토콜로 강화한다.
|
|
6
|
+
|
|
7
|
+
**Architecture:** lead 의 강한 entry gate 와 동일한 기준을 (1) 워커 dispatch contract, (2) 입력 템플릿, (3) report schema/template, (4) validator 에 구조화해 전달·강제한다. 변경은 저위험 prose/contract(PR1)와 고위험 schema/validator(PR2) 둘로 나눈다.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Markdown 프로파일/템플릿, JSON Schema, Python(validate-run.py + pytest), Jinja2 렌더 + i18n(en/ko json), okstra 빌드(`npm run build`).
|
|
10
|
+
|
|
11
|
+
근거: 본 계획은 두 출처를 병합한다 — (A) 검증 초점 분석(이 세션), (B) 다른 에이전트의 final-verification contract 분석. 아래 모든 항목은 소스 직접 확인으로 검증됨.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 범위 결정 (먼저 확인)
|
|
16
|
+
|
|
17
|
+
- **PR1 (저위험, schema 무변경):** 프로파일 prose 정정 + 검증 초점 재설계 + 워커 dispatch target snapshot + 입력 템플릿. 단독으로 가치 있음.
|
|
18
|
+
- **PR2 (고위험, breaking — pre-1.0 라 compat 불필요):** report schema/template/i18n + validator 강제 + golden fixture. PR1 위에 쌓는다.
|
|
19
|
+
- **범위 밖 (별도):** `analysis-material` 이 brief 전체를 복사하는 중복([material.py](../../../scripts/okstra_ctl/material.py)). **모든 task-type 에 영향을 주는 cross-cutting** 이라 이 PR 들에 섞지 않고 별도 후속 작업으로 분리.
|
|
20
|
+
|
|
21
|
+
브랜치: PR1/PR2 각각 `main` 기준 새 브랜치 (pane-cleanup PR 과 무관).
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## File Structure
|
|
26
|
+
|
|
27
|
+
**PR1**
|
|
28
|
+
- Modify: `prompts/profiles/final-verification.md` — 검증 초점 재설계, no-mutation audit 범위 축소, routing vocab, section-name 호환, conditional-accept 참조, deliverable target-snapshot.
|
|
29
|
+
- Modify: `templates/worker-prompt-preamble.md` — `implementation` 전용 Worktree 블록을 `final-verification` 까지 확장(+ base ref / head SHA / diff stat anchor).
|
|
30
|
+
- Modify: `templates/reports/final-verification-input.template.md` — `## Requirement Coverage Source` 섹션 + target/requirement 질문.
|
|
31
|
+
|
|
32
|
+
**PR2**
|
|
33
|
+
- Modify: `schemas/final-report-v1.0.schema.json` — `sourceImplementationReport`(diffSummaryQuote/implementationBaseRef/gitDiffStat), `finalVerdict`(conditionalAcceptanceConditions), `ReadonlyCommandRow`(status/nullable exitCode/rejectionReason).
|
|
34
|
+
- Modify: `templates/reports/final-report.template.md` — §4.8.1 새 필드 렌더, §4.8.x Conditional Acceptance Conditions, Read-only Command Log status 렌더.
|
|
35
|
+
- Modify: `templates/reports/i18n/en.json` + `ko.json` — 신규 `evidenceMeta`/라벨 키.
|
|
36
|
+
- Modify: `validators/validate-run.py` — verdict↔blocker/condition/routing 일관성 강제 + 섹션 목록.
|
|
37
|
+
- Modify: `tests/test_validate_run.py`(또는 해당 파일) — 강제 로직 회귀 테스트.
|
|
38
|
+
- Modify: `tests/fixtures/reports/golden-final-verification.md`, `tests/fixtures/final-report-data/final-verification-001.data.json` — 새 필드 반영.
|
|
39
|
+
- Modify: `CHANGES.md` — 사용자 영향 엔트리(PR2 에서, 또는 양쪽).
|
|
40
|
+
|
|
41
|
+
`runtime/` 는 gitignored build output — 커밋에 포함 안 함. profile/template/preamble/schema/i18n 변경 후 `npm run build` 로 동기화.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
# PR1 — 저위험 prose / contract
|
|
46
|
+
|
|
47
|
+
## Task 1: 검증 초점 재설계 + Expected output emphasis 제거
|
|
48
|
+
|
|
49
|
+
**Files:** Modify `prompts/profiles/final-verification.md:11-21`
|
|
50
|
+
|
|
51
|
+
- [ ] **Step 1:** `Primary focus areas` + `Expected output emphasis` 블록(11-21행)을 아래로 교체.
|
|
52
|
+
|
|
53
|
+
```markdown
|
|
54
|
+
- Primary focus areas (each maps to a deliverable section below):
|
|
55
|
+
- Acceptance-gating — a failure here pushes the verdict toward `blocked` / `conditional-accept`:
|
|
56
|
+
- requirement & acceptance coverage — every must-pass point in the brief's `## Acceptance Criteria` (and the approved plan's requirements) is covered with a cited artifact or raised as an Acceptance Blocker; no silent omissions
|
|
57
|
+
- delivered artifacts match recorded expected values in `reference-expectations` (config files, deployment manifests, other recorded expected states); when reference-expectations are absent, record it as missing information rather than assuming a match
|
|
58
|
+
- test & validation suite pass status — independently re-run the read-only two-tier command set (Tier 1 = brief/approved-plan `validation`, Tier 2 = `project.json` `qaCommands`) and confirm each passes on the verified head, citing exact command + exit code
|
|
59
|
+
- test correctness — delivered tests actually assert the intended behaviour: no gutted/weakened assertions, no tautological or always-passing tests, no tests exercising only mocks; new behaviour has matching coverage
|
|
60
|
+
- no new defects introduced — the diff does not break previously-working behaviour and adds no new bug (logic/off-by-one, null/empty handling, resource leaks, broken error paths)
|
|
61
|
+
- scope conformance — the delivered diff stays within the approved plan's scope; flag out-of-scope edits, unrelated file changes, leftover debug/commented-out code, and unintended deletions
|
|
62
|
+
- Residual-tracked — note as Residual Risk unless severe enough to block:
|
|
63
|
+
- unresolved edge cases
|
|
64
|
+
- regression risk in adjacent code paths not directly changed
|
|
65
|
+
- documentation or rollout gaps
|
|
66
|
+
- production-specific failure modes not caught by tests (env/config drift across stages, secrets & permission/auth changes, migration ordering & rollback executability, observability gaps)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- [ ] **Step 2:** `grep -n "Expected output emphasis" prompts/profiles/final-verification.md` → 0건(제거 확인). `grep -rn "Expected output emphasis" tests/ validators/` → 0건(참조 없음, 이미 확인됨).
|
|
70
|
+
- [ ] **Step 3:** `npm run build && bash validators/validate-workflow.sh` → OK.
|
|
71
|
+
- [ ] **Step 4:** commit `feat(profiles/final-verification): 검증 초점 재설계 — gating/residual 2계층 + 테스트정확성·범위·신규버그 추가`.
|
|
72
|
+
|
|
73
|
+
## Task 2: no-mutation audit 범위 축소 (자기모순 제거)
|
|
74
|
+
|
|
75
|
+
**Files:** Modify `prompts/profiles/final-verification.md:43`
|
|
76
|
+
|
|
77
|
+
- [ ] **Step 1:** self-review 5번 항목을 교체.
|
|
78
|
+
|
|
79
|
+
old:
|
|
80
|
+
```
|
|
81
|
+
5. **No-mutation audit** — scan the run's session transcripts for any Edit / Write / mutating Bash command. Any occurrence means the run has crossed into implementation and MUST be re-routed; do NOT silently strip the evidence.
|
|
82
|
+
```
|
|
83
|
+
new:
|
|
84
|
+
```
|
|
85
|
+
5. **No source-mutation audit** — scan the run's session transcripts for Edit / Write or state-mutating Bash commands that touch paths OUTSIDE `<PROJECT_ROOT>/.okstra/**` and outside the assigned run-artifact paths. Writes to worker prompts, audit sidecars, team-state, the final-report `data.json`, and rendered reports under the run directory are allowed okstra artifacts. Any source/schema/deployment mutation means the run has crossed into implementation and MUST be re-routed; do NOT silently strip the evidence.
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- [ ] **Step 2:** `npm run build` → OK. commit `fix(profiles/final-verification): no-mutation audit 를 source-mutation 으로 한정 (.okstra artifact 허용)`.
|
|
89
|
+
|
|
90
|
+
## Task 3: routing vocabulary + section-name 호환 + conditional-accept 참조
|
|
91
|
+
|
|
92
|
+
**Files:** Modify `prompts/profiles/final-verification.md` (23, 29, 35행)
|
|
93
|
+
|
|
94
|
+
- [ ] **Step 1 (routing, 35행):** `Routing recommendation` deliverable 줄 교체.
|
|
95
|
+
|
|
96
|
+
old:
|
|
97
|
+
```
|
|
98
|
+
- **Routing recommendation**: brief note on the next safe phase (`done`, `error-analysis`, `implementation-planning`) tied to the verdict and blocker list.
|
|
99
|
+
```
|
|
100
|
+
new:
|
|
101
|
+
```
|
|
102
|
+
- **Routing recommendation**: the next safe phase — one of `release-handoff`, `done`, `error-analysis`, `implementation-planning` — tied to the verdict and blocker list. `release-handoff` is allowed ONLY when the Verdict Token is `accepted`.
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- [ ] **Step 2 (section-name 호환, 23행):** entry-gate 줄에서 implementation report 필수 섹션 인용을 양쪽 표기 허용으로.
|
|
106
|
+
|
|
107
|
+
old fragment: ``includes `Plan link & approval evidence`, `Commit list`, ``
|
|
108
|
+
new fragment: ``includes the approved-plan reference (heading `Approved Plan Reference` or `Plan link & approval evidence`), `Commit list`, ``
|
|
109
|
+
|
|
110
|
+
- [ ] **Step 3 (conditional-accept 참조, 29행):** `conditional-accept` 설명에 구조화 deliverable 참조 추가(현 문장 끝에 append).
|
|
111
|
+
|
|
112
|
+
append: ` Each condition MUST be recorded as a row in the **Conditional Acceptance Conditions** deliverable (id, condition, evidence required, blocks-release-handoff).`
|
|
113
|
+
|
|
114
|
+
> 주의: 이 줄은 PR2 의 §4.8 Conditional Acceptance Conditions 섹션·schema 와 짝이다. PR1 만 단독 머지할 경우 이 Step 3 는 PR2 와 함께 가도록 보류 가능 — 실행 시점에 결정.
|
|
115
|
+
|
|
116
|
+
- [ ] **Step 4:** `npm run build && bash validators/validate-workflow.sh` → OK. commit `fix(profiles/final-verification): routing 에 release-handoff 추가 + approved-plan 섹션명 호환`.
|
|
117
|
+
|
|
118
|
+
## Task 4: 워커 dispatch 에 verification target snapshot 전달
|
|
119
|
+
|
|
120
|
+
**Files:** Modify `templates/worker-prompt-preamble.md:84-88`, `prompts/profiles/final-verification.md`(deliverable)
|
|
121
|
+
|
|
122
|
+
- [ ] **Step 1 (preamble):** `For the implementation phase specifically...` 블록(84-88)을 implementation + final-verification 둘 다 커버하도록 교체.
|
|
123
|
+
|
|
124
|
+
old:
|
|
125
|
+
```
|
|
126
|
+
For the **implementation phase** specifically, the dispatched prompt MUST also include:
|
|
127
|
+
|
|
128
|
+
- `**Worktree:** <absolute-path>` — the task worktree path.
|
|
129
|
+
- `cwd for every mutating command: <absolute-path>` — same as Worktree path; used by codex / gemini wrappers as `--add-dir` / `--include-directories`.
|
|
130
|
+
```
|
|
131
|
+
new:
|
|
132
|
+
```
|
|
133
|
+
For the **implementation phase** specifically, the dispatched prompt MUST also include:
|
|
134
|
+
|
|
135
|
+
- `**Worktree:** <absolute-path>` — the task worktree path.
|
|
136
|
+
- `cwd for every mutating command: <absolute-path>` — same as Worktree path; used by codex / gemini wrappers as `--add-dir` / `--include-directories`.
|
|
137
|
+
|
|
138
|
+
For the **final-verification phase** specifically, the dispatched prompt MUST also include the verification target snapshot so every analyser verifies the SAME target the lead captured at the entry gate:
|
|
139
|
+
|
|
140
|
+
- `**Worktree:** <absolute-path>` — the checkout under verification (read-only).
|
|
141
|
+
- `**Verification base ref:** <base-ref>` — the implementation base for the diff.
|
|
142
|
+
- `**Verification head SHA:** <sha>` — head SHA captured at run start.
|
|
143
|
+
- `**Verification diff stat:** <git diff --stat output>` — the captured diff-stat that bounds the verification scope.
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
- [ ] **Step 2 (profile deliverable, final-verification.md "Source Implementation Report" deliverable 28행 근처):** 워커가 이 snapshot 을 기준으로 검증하고 보고서가 cite 하도록, deliverable 의 Source Implementation Report 항목에 한 줄 추가:
|
|
147
|
+
|
|
148
|
+
append: ` The lead injects this same target snapshot into every analyser prompt (`**Worktree:** / **Verification base ref:** / **Verification head SHA:** / **Verification diff stat:**`); a worker that cannot confirm its analysis ran against that exact head MUST record a `tool-failure` rather than verify an ambiguous target.`
|
|
149
|
+
|
|
150
|
+
- [ ] **Step 3:** `npm run build && bash validators/validate-workflow.sh` → OK. commit `feat(worker-preamble,final-verification): 워커 dispatch 에 verification target snapshot 전달`.
|
|
151
|
+
|
|
152
|
+
## Task 5: 입력 템플릿에 Requirement Coverage Source 추가
|
|
153
|
+
|
|
154
|
+
**Files:** Modify `templates/reports/final-verification-input.template.md` (`## Source Implementation Report` 다음)
|
|
155
|
+
|
|
156
|
+
- [ ] **Step 1:** `## Source Implementation Report` 블록 종료(40행 인용구) 다음에 신규 섹션 삽입.
|
|
157
|
+
|
|
158
|
+
```markdown
|
|
159
|
+
|
|
160
|
+
## Requirement Coverage Source
|
|
161
|
+
|
|
162
|
+
- Approved implementation-planning report path:
|
|
163
|
+
- Requirement source used for coverage (plan section / brief Acceptance Criteria):
|
|
164
|
+
- Requirement IDs / acceptance IDs to verify:
|
|
165
|
+
- Requirements intentionally excluded from this verification:
|
|
166
|
+
|
|
167
|
+
> final-verification 은 위 source 의 각 requirement / acceptance id 마다 Validation Evidence 에 artifact 를 cite 해야 한다. source 가 비면 brief 의 `## Acceptance Criteria` 를 기본 source 로 사용한다.
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
- [ ] **Step 2:** 입력 템플릿의 analyser 질문 목록(85행 근처) 맨 앞에 target-integrity 질문 2개 추가:
|
|
171
|
+
|
|
172
|
+
```markdown
|
|
173
|
+
1. Does the verification target (head SHA / diff stat) match the implementation report's commit list and diff summary?
|
|
174
|
+
2. For each requirement / acceptance criterion, what exact artifact (commit SHA, test output, log line, config value) proves coverage?
|
|
175
|
+
```
|
|
176
|
+
(기존 번호 질문들은 뒤로 밀린다.)
|
|
177
|
+
|
|
178
|
+
- [ ] **Step 3:** `npm run build`. 렌더 검증: `python3 -m pytest tests/test_template_full_render_both_langs.py -q` → PASS. commit `feat(final-verification-input): Requirement Coverage Source + target-integrity 질문`.
|
|
179
|
+
|
|
180
|
+
## Task 6: PR1 검증 + PR
|
|
181
|
+
|
|
182
|
+
- [ ] **Step 1:** `python3 -m pytest tests/ -q` → 전부 PASS(또는 tmux skip). `bash validators/validate-workflow.sh` → OK. `node bin/okstra --version`.
|
|
183
|
+
- [ ] **Step 2:** diff critique — 새 토큰 grep(`grep -rn "Verification base ref\|Requirement Coverage Source\|No source-mutation audit" prompts/ templates/`), runtime parity.
|
|
184
|
+
- [ ] **Step 3:** push + `gh pr create --base main` (제목 `feat(final-verification): 검증 프로토콜 강화 — 초점/target snapshot/입력 (PR1)`).
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
# PR2 — report contract (schema / template / i18n / validator)
|
|
189
|
+
|
|
190
|
+
> PR1 머지 후 `main` 기준 새 브랜치에서 진행. breaking schema 변경(pre-1.0, compat 불필요).
|
|
191
|
+
|
|
192
|
+
## Task 7: schema — sourceImplementationReport diff-stat 분리
|
|
193
|
+
|
|
194
|
+
**Files:** Modify `schemas/final-report-v1.0.schema.json` (`sourceImplementationReport`, 현 ~547행)
|
|
195
|
+
|
|
196
|
+
- [ ] **Step 1 (test first):** schema 검증 테스트 추가 — diff-stat/diffSummaryQuote 누락 시 invalid. (해당 schema 검증 테스트 파일은 `tests/test_validate_run*.py` 또는 schema 단위 테스트; 실행 시 위치 확인 후 케이스 추가.)
|
|
197
|
+
- [ ] **Step 2:** `sourceImplementationReport` 를 교체:
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
"sourceImplementationReport": {
|
|
201
|
+
"type": "object",
|
|
202
|
+
"required": ["path", "commitListQuote", "diffSummaryQuote", "worktreePath", "implementationBaseRef", "capturedHeadSha", "gitStatusShort", "gitDiffStat"],
|
|
203
|
+
"additionalProperties": false,
|
|
204
|
+
"properties": {
|
|
205
|
+
"path": { "type": "string" },
|
|
206
|
+
"commitListQuote": { "type": "string" },
|
|
207
|
+
"diffSummaryQuote": { "type": "string" },
|
|
208
|
+
"worktreePath": { "type": "string" },
|
|
209
|
+
"implementationBaseRef": { "type": "string" },
|
|
210
|
+
"capturedHeadSha": { "type": "string" },
|
|
211
|
+
"gitStatusShort": { "type": "string" },
|
|
212
|
+
"gitDiffStat": { "type": "string" }
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
(주의: 기존 `baseHeadSha` → `implementationBaseRef` + `capturedHeadSha` 분리. template/i18n/fixture 동반 수정 필요 — Task 10/11.)
|
|
217
|
+
|
|
218
|
+
- [ ] **Step 3:** schema 테스트 PASS. commit.
|
|
219
|
+
|
|
220
|
+
## Task 8: schema — conditionalAcceptanceConditions
|
|
221
|
+
|
|
222
|
+
**Files:** Modify `schemas/final-report-v1.0.schema.json` (`finalVerdict` + `$defs`)
|
|
223
|
+
|
|
224
|
+
- [ ] **Step 1 (test first):** verdict=`conditional-accept` 인데 conditions 비면 invalid 케이스.
|
|
225
|
+
- [ ] **Step 2:** `finalVerdict.properties` 에 추가 + `$defs` 에 row 정의:
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
"conditionalAcceptanceConditions": {
|
|
229
|
+
"type": "array",
|
|
230
|
+
"items": { "$ref": "#/$defs/ConditionalAcceptanceConditionRow" }
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
```json
|
|
234
|
+
"ConditionalAcceptanceConditionRow": {
|
|
235
|
+
"type": "object",
|
|
236
|
+
"required": ["id", "condition", "evidenceRequired", "blocksReleaseHandoff"],
|
|
237
|
+
"additionalProperties": false,
|
|
238
|
+
"properties": {
|
|
239
|
+
"id": { "type": "string", "pattern": "^CA-\\d{3,}$" },
|
|
240
|
+
"condition": { "type": "string", "minLength": 1 },
|
|
241
|
+
"evidenceRequired": { "type": "string", "minLength": 1 },
|
|
242
|
+
"blocksReleaseHandoff": { "type": "boolean" }
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
(`finalVerdict.required` 에는 넣지 않음 — accepted/blocked 에선 빈 배열 허용; 강제는 validator 에서 verdict 조건부로.)
|
|
247
|
+
|
|
248
|
+
- [ ] **Step 3:** 테스트 PASS. commit.
|
|
249
|
+
|
|
250
|
+
## Task 9: schema — ReadonlyCommandRow status / nullable exitCode
|
|
251
|
+
|
|
252
|
+
**Files:** Modify `schemas/final-report-v1.0.schema.json` (`ReadonlyCommandRow`, 현 ~1306행)
|
|
253
|
+
|
|
254
|
+
- [ ] **Step 1 (test first):** status=`rejected`, exitCode=null 인 row 가 valid 케이스 + status=`executed` 인데 exitCode=null 이면 invalid(아래 Step 2 의 조건).
|
|
255
|
+
- [ ] **Step 2:** `ReadonlyCommandRow` 교체:
|
|
256
|
+
|
|
257
|
+
```json
|
|
258
|
+
"ReadonlyCommandRow": {
|
|
259
|
+
"type": "object",
|
|
260
|
+
"required": ["number", "tier", "command", "status", "exitCode", "outputTail"],
|
|
261
|
+
"additionalProperties": false,
|
|
262
|
+
"properties": {
|
|
263
|
+
"number": { "type": "integer", "minimum": 1 },
|
|
264
|
+
"tier": { "enum": [1, 2] },
|
|
265
|
+
"command": { "type": "string", "minLength": 1 },
|
|
266
|
+
"status": { "enum": ["executed", "rejected", "not-configured"] },
|
|
267
|
+
"exitCode": { "type": ["integer", "null"] },
|
|
268
|
+
"rejectionReason": { "type": ["string", "null"] },
|
|
269
|
+
"outputTail": { "type": "string" }
|
|
270
|
+
},
|
|
271
|
+
"allOf": [
|
|
272
|
+
{ "if": { "properties": { "status": { "const": "executed" } } },
|
|
273
|
+
"then": { "properties": { "exitCode": { "type": "integer" } } } },
|
|
274
|
+
{ "if": { "properties": { "status": { "const": "rejected" } } },
|
|
275
|
+
"then": { "required": ["rejectionReason"] } }
|
|
276
|
+
]
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
- [ ] **Step 3:** 테스트 PASS. commit.
|
|
281
|
+
|
|
282
|
+
## Task 10: template §4.8 — 새 필드 렌더
|
|
283
|
+
|
|
284
|
+
**Files:** Modify `templates/reports/final-report.template.md` (§4.8.1, + 신규 conditions 섹션, Read-only Command Log)
|
|
285
|
+
|
|
286
|
+
- [ ] **Step 1:** §4.8.1 Source Implementation Report 렌더에 diffSummaryQuote / implementationBaseRef / gitDiffStat 추가, baseHeadSha → capturedHeadSha 로 변경 (i18n 키는 Task 11).
|
|
287
|
+
- [ ] **Step 2:** §4.8.x `Conditional Acceptance Conditions` 섹션 추가 — verdict=`conditional-accept` 일 때 행 렌더, 아니면 `- Not applicable (verdict is not conditional-accept).`.
|
|
288
|
+
- [ ] **Step 3:** Read-only Command Log 렌더에 `status` 열 + rejected 행의 `rejectionReason`, exitCode null 처리.
|
|
289
|
+
- [ ] **Step 4:** `npm run build`. `python3 -m pytest tests/test_template_full_render_both_langs.py tests/test_render_phase_blocks.py -q` → PASS(또는 fixture 갱신 후). commit.
|
|
290
|
+
|
|
291
|
+
## Task 11: i18n 키 + golden fixture
|
|
292
|
+
|
|
293
|
+
**Files:** Modify `templates/reports/i18n/en.json`, `ko.json`, `tests/fixtures/reports/golden-final-verification.md`, `tests/fixtures/final-report-data/final-verification-001.data.json`
|
|
294
|
+
|
|
295
|
+
- [ ] **Step 1:** `en.json` + `ko.json` 의 `evidenceMeta` 에 키 추가: `diffSummaryAtRunStart`, `implementationBaseRef`, `gitDiffStatAtRunStart` (+ conditions/command-status 라벨). 기존 `capturedHeadBaseSha` → `capturedHeadSha` 의미로 정리.
|
|
296
|
+
- [ ] **Step 2:** golden data.json 에 새 필드 채우고, golden md 를 새 렌더 결과로 갱신 (`npm run build` 후 렌더러로 재생성하거나 수동 갱신).
|
|
297
|
+
- [ ] **Step 3:** `python3 -m pytest tests/test_template_full_render_both_langs.py tests/test_report_views.py -q` → PASS. commit.
|
|
298
|
+
|
|
299
|
+
## Task 12: validator — verdict↔blocker/condition/routing 일관성 강제
|
|
300
|
+
|
|
301
|
+
**Files:** Modify `validators/validate-run.py` (final-verification 블록 ~1172), `tests/test_validate_run*.py`
|
|
302
|
+
|
|
303
|
+
- [ ] **Step 1 (test first):** 4개 회귀 테스트 추가:
|
|
304
|
+
- verdict=`accepted` + acceptanceBlockers 비어있지 않음 → fail
|
|
305
|
+
- verdict=`blocked` + acceptanceBlockers 0개 → fail
|
|
306
|
+
- verdict=`conditional-accept` + conditions 0개 → fail
|
|
307
|
+
- routingRecommendation 이 `release-handoff` 인데 verdict ≠ `accepted` → fail
|
|
308
|
+
- [ ] **Step 2:** `if task_type == "final-verification":` 블록(1172)에 위 4개 검사 추가. 신규 §4.8 섹션 추가했으면 `FINAL_VERIFICATION_REQUIRED_SECTIONS`(876)에 `"Conditional Acceptance Conditions"` 등 반영.
|
|
309
|
+
- [ ] **Step 3:** `python3 -m pytest tests/test_validate_run.py -q` → PASS. commit.
|
|
310
|
+
|
|
311
|
+
## Task 13: PR2 검증 + docs + PR
|
|
312
|
+
|
|
313
|
+
- [ ] **Step 1:** `python3 -m pytest tests/ -q`, `bash validators/validate-workflow.sh`, golden 렌더 테스트 전부 PASS.
|
|
314
|
+
- [ ] **Step 2:** `CHANGES.md` 에 사용자 영향 엔트리(verdict 일관성 강제 + diff-stat/conditions/command-status 구조화).
|
|
315
|
+
- [ ] **Step 3:** diff critique(rule #5) — schema↔template↔i18n↔fixture↔validator 5자 정합, 새 식별자 grep.
|
|
316
|
+
- [ ] **Step 4:** push + `gh pr create --base main` (`feat(final-verification): report contract 구조화 — diff-stat/conditions/command-status + verdict 강제 (PR2)`).
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Self-Review (작성자 체크)
|
|
321
|
+
|
|
322
|
+
- **Spec coverage:** 다른 에이전트 8개 항목 매핑 — #1 target snapshot=Task4, #2 diff-stat=Task7/10/11, #3 requirement source=Task5, #4 no-mutation=Task2, #5 conditions=Task3/8/10/12, #6 command status=Task9/10/12, #7 routing=Task3, #8 section-name=Task3. + 검증 초점 재설계=Task1.
|
|
323
|
+
- **범위 밖 명시:** material.py 중복(cross-cutting)은 별도 — spawn 권장.
|
|
324
|
+
- **Placeholder:** schema/profile/preamble/input 은 완전한 텍스트 포함. template/i18n/fixture(Task10/11)는 정확한 위치·키를 지정하되, 렌더 결과 golden md 는 빌드로 재생성하는 절차로 둠(수작업 전체 전사 비현실적).
|
|
325
|
+
- **enforcement 정직성:** 검증 초점(Task1)·no-mutation(Task2)·target snapshot(Task4)은 선언 레벨(런타임 강제 없음). verdict↔blocker/condition/routing(Task12)·schema 필드(Task7-9)는 validator/schema 가 런타임 강제.
|
|
326
|
+
- **의존성:** Task3 Step3(conditional 참조)는 PR2 의 conditions 와 짝 — PR1 단독이면 보류.
|