okstra 0.112.0 → 0.114.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.
Files changed (37) hide show
  1. package/README.kr.md +2 -2
  2. package/README.md +2 -2
  3. package/docs/for-ai/README.md +2 -2
  4. package/docs/for-ai/skills/{okstra-brief.md → okstra-brief-gen.md} +3 -3
  5. package/docs/for-ai/skills/okstra-inspect.md +1 -1
  6. package/docs/kr/architecture.md +9 -9
  7. package/docs/kr/cli.md +1 -1
  8. package/docs/project-structure-overview.md +2 -2
  9. package/package.json +1 -1
  10. package/runtime/BUILD.json +2 -2
  11. package/runtime/agents/workers/antigravity-worker.md +1 -1
  12. package/runtime/agents/workers/claude-worker.md +1 -1
  13. package/runtime/agents/workers/codex-worker.md +1 -1
  14. package/runtime/prompts/lead/context-loader.md +2 -2
  15. package/runtime/prompts/profiles/_common-contract.md +3 -3
  16. package/runtime/prompts/profiles/_implementation-self-check.md +1 -0
  17. package/runtime/prompts/profiles/_implementation-verifier.md +1 -1
  18. package/runtime/prompts/profiles/final-verification.md +6 -5
  19. package/runtime/prompts/profiles/implementation-planning.md +5 -3
  20. package/runtime/prompts/profiles/improvement-discovery.md +1 -0
  21. package/runtime/prompts/profiles/requirements-discovery.md +3 -2
  22. package/runtime/python/okstra_ctl/fix_cycles.py +1 -1
  23. package/runtime/python/okstra_ctl/wizard.py +3 -3
  24. package/runtime/schemas/final-report-v1.0.schema.json +6 -4
  25. package/runtime/skills/{okstra-brief → okstra-brief-gen}/SKILL.md +6 -6
  26. package/runtime/skills/{okstra-brief → okstra-brief-gen}/references/reporter-confirmations.md +1 -1
  27. package/runtime/skills/{okstra-brief → okstra-brief-gen}/references/tracker-recursion.md +1 -1
  28. package/runtime/skills/okstra-inspect/SKILL.md +2 -2
  29. package/runtime/templates/reports/brief.template.md +2 -2
  30. package/runtime/templates/reports/final-report.template.md +24 -1
  31. package/runtime/templates/reports/improvement-discovery-input.template.md +3 -2
  32. package/runtime/templates/worker-prompt-preamble.md +4 -0
  33. package/runtime/validators/validate-brief.py +5 -5
  34. package/runtime/validators/validate-brief.sh +1 -1
  35. package/runtime/validators/validate-run.py +1 -0
  36. package/src/commands/lifecycle/uninstall.mjs +2 -1
  37. package/src/lib/skill-catalog.mjs +2 -1
package/README.kr.md CHANGED
@@ -157,7 +157,7 @@ Claude Code 세션 안에서 사용하는 슬래시 커맨드:
157
157
 
158
158
  | 커맨드 | 용도 |
159
159
  |---|---|
160
- | `/okstra-brief` | ticket, 요구사항 문서, 링크, 대화 내용을 `okstra-run`용 task brief로 변환 |
160
+ | `/okstra-brief-gen` | ticket, 요구사항 문서, 링크, 대화 내용을 `okstra-run`용 task brief로 변환 |
161
161
  | `/okstra-run` | 새 task 시작 (또는 기존 task 의 다음 phase 이어가기) |
162
162
  | `/okstra-memory` | `~/.okstra/memory-book` 전역 대화 메모리 저장·검색·보관 |
163
163
  | `/okstra-inspect` | 통합 read-side 스킬. sub-command: `status` (phase / 상태, workStatus 설정), `history` (과거 task / re-run / resume), `report` (final-report 조회·읽기), `time` (소요 시간 breakdown), `logs` (wrapper log sidecar 조회·정리 제안), `cost` (task bundle 컨텍스트/읽기 비용), `errors` (run 에러 로그를 리포트로 집계), `error-zip` (cross-project 에러 로그를 익명화 zip 으로 수집·클러스터 요약), `recap` (run 간 전/후 요약 + task 의 `.okstra` 산출물 위 자유 Q&A) |
@@ -201,7 +201,7 @@ Claude Code 세션 밖에서 task 를 시작하려면:
201
201
  - **실험적 Codex lead adapter** — `okstra codex-run <render-bundle args...>` 가 Claude Code 를 띄우지 않고 `leadRuntime=codex` task bundle 을 준비합니다. 이어서 `okstra codex-dispatch --project-root <dir> --run-manifest <path>` 로 roster 중 Codex-side 지원 subset 을 실행합니다(Codex/Antigravity CLI worker 기본, Codex report-writer 는 `--enable-codex-report-writer --report-writer-codex-model <model>` opt-in 필요). 성공한 Codex report-writer dispatch 는 token/cost substitution, HTML view 렌더, follow-up stub 생성, run validation 을 순서대로 자동 실행합니다. Claude lead 경로와 같은 manifest/schema 를 공유하며, 프로젝트를 Codex 전용 fork 로 복제하지 않습니다.
202
202
  - **다단계 `implementation-planning` / `implementation`** — `implementation-planning` 은 항상 Stage Map + N 개 stage 섹션으로 산출합니다. 각 stage 의 step 은 ≤ 6 이며 `depends-on (none)` 인 stage 들은 별도 `implementation` run 으로 병렬 실행할 수 있습니다. 각 `implementation` 호출은 한 stage 만 실행하고 (`--stage <auto|N>`), 자동 생성되는 evidence sidecar (`carry/stage-<N>.json`) 가 다음 stage 의 carry-in 으로 흡수됩니다. `implementation-planning` run 디렉터리에 `consumers.jsonl` 역링크가 누적되어 어느 run 이 어느 stage 를 소비했는지 추적됩니다.
203
203
  - **Phase 6 plan-body verification (implementation-planning 전용)** — Report writer worker 가 final-report draft 를 작성한 직후, 사용자 승인 gate 직전에 lead 가 1 라운드의 사후 검증을 추가로 돌립니다. 합성된 `## 5.5` implementation plan deliverables 본문에서 `P-Opt-*` / `P-Step-*` / `P-Dep-*` / `P-Val-*` / `P-Rb-*` plan-item 을 추출해 모든 analyser 워커에게 `AGREE` / `DISAGREE(a-e)` / `SUPPLEMENT` 평결을 요청합니다. 집계된 gate 결과는 `passed` / `passed-with-dissent` / `blocked-by-disagreement` / `aborted-non-result` 중 하나입니다. frontmatter `approved` 필드는 항상 `false` 로 발행되며, blocking gate 결과는 이를 false 로 유지하고 `## 1. Clarification Items` row 로 변환합니다. 빠른 반복용 opt-out 은 `--no-plan-verification` 입니다. 세부 계약: [`prompts/lead/convergence.md`](prompts/lead/convergence.md) "Plan-body verification mode", [`docs/kr/cli.md#--no-plan-verification`](docs/kr/cli.md#--no-plan-verification).
204
- - **Brief = translation layer + Step 6.5 reporter batch confirmation** — `okstra-brief` 가 외부 입력 (이슈 ticket, 요구사항 문서, 사용자 메시지) 을 verbatim 으로 옮기되 okstra 가 추가한 부분은 labelled augmentation 으로 구분하는 translation layer 가 됐습니다. Step 6.5 가 brief 가 옮기는 과정에서 의미 변화가 발생했는지 사용자에게 일괄 확인받아 `Reporter Confirmations` 섹션에 기록하고, 모든 분석 profile 은 이 섹션의 존재를 phase 분석 진입 precondition 으로 강제합니다 (validator: `validators/validate-brief.py`).
204
+ - **Brief = translation layer + Step 6.5 reporter batch confirmation** — `okstra-brief-gen` 가 외부 입력 (이슈 ticket, 요구사항 문서, 사용자 메시지) 을 verbatim 으로 옮기되 okstra 가 추가한 부분은 labelled augmentation 으로 구분하는 translation layer 가 됐습니다. Step 6.5 가 brief 가 옮기는 과정에서 의미 변화가 발생했는지 사용자에게 일괄 확인받아 `Reporter Confirmations` 섹션에 기록하고, 모든 분석 profile 은 이 섹션의 존재를 phase 분석 진입 precondition 으로 강제합니다 (validator: `validators/validate-brief.py`).
205
205
  - **Artifact-home rule (`.okstra/`)** — okstra 의 project artifact root 는 `<project>/.okstra/` 하나뿐입니다. 이 root 밖은 okstra memory 가 아니며, Source Material 또는 Reporter Confirmations 가 명시적으로 cite 한 경우에만 read-only 로 읽습니다. 쓰기는 같은 explicit request path 를 요구합니다. okstra-internal 등가물: 용어집 `glossary.md`, 결정 기록 `decisions/<NNNN>-<slug>.md` (`implementation-planning` phase 에서 평가).
206
206
  - **Self-contained HTML final-report view** — Phase 7 가 `final-report-<task-type>-<seq>.md` 를 쓰면 `okstra render-views` 가 같은 `reports/` 폴더에 사람 reviewer 용 self-contained HTML view (CSS/JS 인라인, 외부 URL 0) 를 자동 생성합니다. HTML 의 `Export user response` 버튼은 `## 1. Clarification Items` 입력을 `runs/<task-type>/user-responses/user-response-<task-type>-<seq>.md` 사이드카로 직렬화해 다음 phase 가 소비합니다. 원본 MD 는 어떤 경우에도 view 생성으로 인해 수정되지 않습니다.
207
207
  - **`improvement-discovery` task-type (sidetrack entry-point)** — 코드베이스 범위 + 우선순위 lens 화이트리스트 안에서 multi-worker 합의 기반 개선 후보 N개 (기본 8, 절대 cap 12) 도출. `PHASE_SEQUENCE` 외부 sidetrack entry-point — 사용자가 후보를 골라 각각 새 task-id 로 `requirements-discovery` / `implementation-planning` / `error-analysis` 진입. lens enum SSOT: [`scripts/okstra_ctl/improvement_lenses.py`](scripts/okstra_ctl/improvement_lenses.py). 출력 섹션: `## 4.9 Improvement Candidates` (10-column 표). validator: [`validators/validate_improvement_report.py`](validators/validate_improvement_report.py).
package/README.md CHANGED
@@ -155,7 +155,7 @@ User-facing slash commands inside a Claude Code session:
155
155
 
156
156
  | Command | Use |
157
157
  |---|---|
158
- | `/okstra-brief` | Turn a ticket, requirements doc, link, or conversation into an `okstra-run` task brief |
158
+ | `/okstra-brief-gen` | Turn a ticket, requirements doc, link, or conversation into an `okstra-run` task brief |
159
159
  | `/okstra-run` | Start a new task (or resume the next phase of an existing one) |
160
160
  | `/okstra-memory` | Store/search/archive global conversation memory in `~/.okstra/memory-book` |
161
161
  | `/okstra-inspect` | Unified read-side. Sub-commands: `status` (phase / state, workStatus update), `history` (past runs, re-run, resume), `report` (find/read final-report), `time` (elapsed-time breakdown), `logs` (wrapper log sidecar inventory + cleanup), `cost` (task bundle context/read cost), `errors` (aggregate run error logs into a report), `error-zip` (collect cross-project error logs into an anonymized zip and summarize clusters), `recap` (run-to-run before/after summary + free-form Q&A over a task's `.okstra` artifacts) |
@@ -199,7 +199,7 @@ Recent workflow additions (post-0.8.0, on `main`):
199
199
  - **Experimental Codex lead adapter** — `okstra codex-run <render-bundle args...>` prepares a `leadRuntime=codex` task bundle without launching Claude Code. `okstra codex-dispatch --project-root <dir> --run-manifest <path>` can then run the supported Codex-side subset of the roster (Codex/Antigravity CLI workers by default; Codex report-writer only with `--enable-codex-report-writer --report-writer-codex-model <model>`). Successful Codex report-writer dispatch runs token/cost substitution, HTML view rendering, follow-up stub generation, and run validation in order. This shares the same manifests/schemas as the Claude lead path; it does not clone the project into a separate Codex-specific fork.
200
200
  - **Multi-stage `implementation-planning` / `implementation`** — `implementation-planning` always produces a Stage Map plus N stage sections; each stage has ≤6 steps and stages whose `depends-on (none)` can be executed in parallel by separate `implementation` runs. Each `implementation` invocation picks one stage (via `--stage <auto|N>`) and emits an evidence sidecar (`carry/stage-<N>.json`) that the next stage automatically inherits. The `implementation-planning` run directory accumulates a `consumers.jsonl` reverse-link showing which `implementation` runs consumed which stage.
201
201
  - **Phase 6 plan-body verification (implementation-planning only)** — after the Report writer worker authors the final-report draft and before the user approval gate, the lead runs one additional verification round: it extracts `P-Opt-*` / `P-Step-*` / `P-Dep-*` / `P-Val-*` / `P-Rb-*` items from the consolidated `## 5.5` implementation plan deliverables body and dispatches them to every analyser worker as `AGREE` / `DISAGREE(a-e)` / `SUPPLEMENT`. The aggregated gate result is one of `passed` / `passed-with-dissent` / `blocked-by-disagreement` / `aborted-non-result`. The frontmatter `approved` flag is always emitted as `false`; blocking gate results keep it false and become `## 1. Clarification Items` rows. Details: [`prompts/lead/convergence.md`](prompts/lead/convergence.md) "Plan-body verification mode" and [`docs/kr/cli.md#--no-plan-verification`](docs/kr/cli.md#--no-plan-verification).
202
- - **Brief as translation layer + reporter batch confirmation (Step 6.5)** — `okstra-brief` now produces the brief as a translation layer that preserves external inputs (issue ticket, requirements doc, user message) verbatim while labelling okstra augmentations. A new Step 6.5 walks the user through a single batch confirmation of any rewordings, recorded in a `Reporter Confirmations` section. Every analysis profile blocks phase entry until this section exists (validator: `validators/validate-brief.py`).
202
+ - **Brief as translation layer + reporter batch confirmation (Step 6.5)** — `okstra-brief-gen` now produces the brief as a translation layer that preserves external inputs (issue ticket, requirements doc, user message) verbatim while labelling okstra augmentations. A new Step 6.5 walks the user through a single batch confirmation of any rewordings, recorded in a `Reporter Confirmations` section. Every analysis profile blocks phase entry until this section exists (validator: `validators/validate-brief.py`).
203
203
  - **Artifact-home rule (`.okstra/`)** — okstra's project artifact root is only `<project>/.okstra/`. Anything outside that root is not okstra memory; it may be read only when explicitly cited as Source Material or Reporter Confirmations, and writes require the same explicit request path. okstra-internal equivalents: `glossary.md` for terminology and `decisions/<NNNN>-<slug>.md` for decision records (evaluated in `implementation-planning`).
204
204
  - **Self-contained HTML final-report view** — after Phase 7 writes `final-report-<task-type>-<seq>.md`, `okstra render-views` automatically emits a sibling self-contained HTML view (inline CSS/JS, no external URLs) in the same `reports/` directory for human review. The HTML lets a reviewer fill in `## 1. Clarification Items` decisions and export them to `runs/<task-type>/user-responses/user-response-<task-type>-<seq>.md`, which the next phase consumes as input. The original MD is never modified by view generation.
205
205
  - **`improvement-discovery` task-type (sidetrack entry-point)** — Discover ranked improvement candidates within a codebase scope and lens whitelist via multi-worker consensus (default top-8, hard cap 12). Outside `PHASE_SEQUENCE`; the user selects candidates and opens each as a new task with `requirements-discovery`, `implementation-planning`, or `error-analysis`. Lens enum SSOT: [`scripts/okstra_ctl/improvement_lenses.py`](scripts/okstra_ctl/improvement_lenses.py). Output section: `## 4.9 Improvement Candidates` (10-column table). Validator: [`validators/validate_improvement_report.py`](validators/validate_improvement_report.py).
@@ -17,7 +17,7 @@
17
17
  | 사용자 의도 | 사용할 스킬 | 매뉴얼 |
18
18
  |---|---|---|
19
19
  | 새 프로젝트나 새 머신에서 okstra 설치/초기화 | `okstra-setup` | [`skills/okstra-setup.md`](skills/okstra-setup.md) |
20
- | 요구사항, 티켓, 링크, 코드베이스 스캔, error-zip을 okstra 입력 brief로 변환 | `okstra-brief` | [`skills/okstra-brief.md`](skills/okstra-brief.md) |
20
+ | 요구사항, 티켓, 링크, 코드베이스 스캔, error-zip을 okstra 입력 brief로 변환 | `okstra-brief-gen` | [`skills/okstra-brief-gen.md`](skills/okstra-brief-gen.md) |
21
21
  | 현재 Claude Code 세션에서 okstra run 시작 또는 다음 phase 실행 | `okstra-run` | [`skills/okstra-run.md`](skills/okstra-run.md) |
22
22
  | 여러 프로젝트에 걸친 okstra task 묶음, 할당, sync snapshot, child launch packet 관리 | `okstra-manager` | [`skills/okstra-manager.md`](skills/okstra-manager.md) |
23
23
  | 상태, history, report, time, logs, cost, errors, error-zip, recap 확인 | `okstra-inspect` | [`skills/okstra-inspect.md`](skills/okstra-inspect.md) |
@@ -48,7 +48,7 @@
48
48
  `src/lib/skill-catalog.mjs` 기준 공개 스킬은 다음 9개다.
49
49
 
50
50
  - `okstra-setup`
51
- - `okstra-brief`
51
+ - `okstra-brief-gen`
52
52
  - `okstra-run`
53
53
  - `okstra-manager`
54
54
  - `okstra-memory`
@@ -1,15 +1,15 @@
1
- # okstra-brief AI Manual
1
+ # okstra-brief-gen AI Manual
2
2
 
3
3
  ## 원천
4
4
 
5
- - 스킬 원문: [`skills/okstra-brief/SKILL.md`](../../../skills/okstra-brief/SKILL.md)
5
+ - 스킬 원문: [`skills/okstra-brief-gen/SKILL.md`](../../../skills/okstra-brief-gen/SKILL.md)
6
6
  - brief 템플릿: [`templates/reports/brief.template.md`](../../../templates/reports/brief.template.md)
7
7
  - brief validator: [`validators/validate-brief.py`](../../../validators/validate-brief.py)
8
8
  - lens enum SSOT: [`scripts/okstra_ctl/improvement_lenses.py`](../../../scripts/okstra_ctl/improvement_lenses.py)
9
9
 
10
10
  ## 목적
11
11
 
12
- `okstra-brief`는 okstra pipeline에 넣을 task brief를 만든다. brief는 pre-discovery 산출물이다. 요구사항을 구현 계획으로 바꾸는 문서가 아니라, reporter가 준 원문과 AI가 확인한 증거/해석을 라벨로 분리해 다음 phase가 질문 없이 출발하게 만드는 handoff 문서다.
12
+ `okstra-brief-gen`는 okstra pipeline에 넣을 task brief를 만든다. brief는 pre-discovery 산출물이다. 요구사항을 구현 계획으로 바꾸는 문서가 아니라, reporter가 준 원문과 AI가 확인한 증거/해석을 라벨로 분리해 다음 phase가 질문 없이 출발하게 만드는 handoff 문서다.
13
13
 
14
14
  출력 위치:
15
15
 
@@ -213,7 +213,7 @@ okstra error-zip --out <path>
213
213
  - `clusterCount`
214
214
  - `projectCount`
215
215
 
216
- 마지막에 `/okstra-brief`의 error-feedback variant로 brief를 만든 뒤 okstra repo에서 `error-analysis`를 실행하라고 안내한다.
216
+ 마지막에 `/okstra-brief-gen`의 error-feedback variant로 brief를 만든 뒤 okstra repo에서 `error-analysis`를 실행하라고 안내한다.
217
217
 
218
218
  ## recap
219
219
 
@@ -147,9 +147,9 @@ okstra 의 prepare 책임은 단일 python 진입점 [`okstra_ctl.run.prepare_ta
147
147
  - [`prompts/lead/okstra-lead-contract.md`](../../prompts/lead/okstra-lead-contract.md) — main okstra lead contract. 런타임 리소스(`~/.okstra/prompts/lead/`)이며 agent skill 이 아닙니다.
148
148
  - [`skills/okstra-setup/SKILL.md`](../../skills/okstra-setup/SKILL.md) — **첫 실행 부트스트랩**. `okstra install` + `project.json` 생성.
149
149
  - [`skills/okstra-run/SKILL.md`](../../skills/okstra-run/SKILL.md) — **현재 claude 세션 안에서 okstra task 를 시작**하는 in-session 진입점. `prepare_task_bundle` 직접 호출.
150
- - 사용자 호출 가능 스킬은 `skills/okstra-setup/SKILL.md`, `skills/okstra-brief/SKILL.md`, `skills/okstra-run/SKILL.md`, `skills/okstra-manager/SKILL.md`, `skills/okstra-memory/SKILL.md`, `skills/okstra-inspect/SKILL.md`, `skills/okstra-rollup/SKILL.md`, `skills/okstra-schedule/SKILL.md`, `skills/okstra-container-build/SKILL.md` 9종뿐이며, 이것만 agent skill home 으로 복사됩니다 — brief 작성, phase 진행, cross-project manager task 조정, 전역 Memory Book 저장/검색, status/history/report/time/logs/cost/errors/recap read-side, task-group 단위 run 결과 종합(rollup), schedule 보조, 그리고 `okstra-container-build` 는 검증 완료된 task 코드를 docker compose 그룹으로 배포하고 컨테이너별 watcher 로 감시하는 비선형(PHASE_SEQUENCE 외부) 컨테이너 배포/감시 스킬. `okstra-manager` 는 `okstra manager` CLI JSON/launch packet 을 source of truth 로 사용하며, manager-owned plan/assignment/directive/snapshot/event 는 `~/.okstra/managers/<manager-id>/` 아래에 저장합니다. `okstra-rollup` 은 단일 task 집계기(`okstra-inspect` 의 time/errors/recap)를 task-group(또는 프로젝트 전체 catalog)으로 fan-out 하는 read-side 레이어로, deterministic 집계는 `okstra rollup` CLI 가 맡고 report 본문 종합 요약만 스킬(LLM)이 작성합니다. `okstra-inspect` 의 read-side facet 은 `skills/okstra-inspect/SKILL.md` 의 sub-command 표가 정본입니다. `okstra-inspect logs` 는 codex/antigravity wrapper 가 매 dispatch 마다 `runs/<task-type>/prompts/<worker>-prompt-<phase>-<seq>.log` 로 남기는 live-log sidecar 의 인벤토리·정리 안내(read-only), `okstra-inspect cost` 는 `okstra context-cost` 결과 요약, `okstra-inspect errors` 는 task 의 okstra-run 에러 로그를 타임스탬프 markdown error-report 로 모아 렌더하고 요약을 출력, `okstra-inspect recap` 은 task 의 run 간 phase 전·후 요약에 더해 `.okstra` 산출물에 대한 자유 Q&A 까지 답합니다.
150
+ - 사용자 호출 가능 스킬은 `skills/okstra-setup/SKILL.md`, `skills/okstra-brief-gen/SKILL.md`, `skills/okstra-run/SKILL.md`, `skills/okstra-manager/SKILL.md`, `skills/okstra-memory/SKILL.md`, `skills/okstra-inspect/SKILL.md`, `skills/okstra-rollup/SKILL.md`, `skills/okstra-schedule/SKILL.md`, `skills/okstra-container-build/SKILL.md` 9종뿐이며, 이것만 agent skill home 으로 복사됩니다 — brief 작성, phase 진행, cross-project manager task 조정, 전역 Memory Book 저장/검색, status/history/report/time/logs/cost/errors/recap read-side, task-group 단위 run 결과 종합(rollup), schedule 보조, 그리고 `okstra-container-build` 는 검증 완료된 task 코드를 docker compose 그룹으로 배포하고 컨테이너별 watcher 로 감시하는 비선형(PHASE_SEQUENCE 외부) 컨테이너 배포/감시 스킬. `okstra-manager` 는 `okstra manager` CLI JSON/launch packet 을 source of truth 로 사용하며, manager-owned plan/assignment/directive/snapshot/event 는 `~/.okstra/managers/<manager-id>/` 아래에 저장합니다. `okstra-rollup` 은 단일 task 집계기(`okstra-inspect` 의 time/errors/recap)를 task-group(또는 프로젝트 전체 catalog)으로 fan-out 하는 read-side 레이어로, deterministic 집계는 `okstra rollup` CLI 가 맡고 report 본문 종합 요약만 스킬(LLM)이 작성합니다. `okstra-inspect` 의 read-side facet 은 `skills/okstra-inspect/SKILL.md` 의 sub-command 표가 정본입니다. `okstra-inspect logs` 는 codex/antigravity wrapper 가 매 dispatch 마다 `runs/<task-type>/prompts/<worker>-prompt-<phase>-<seq>.log` 로 남기는 live-log sidecar 의 인벤토리·정리 안내(read-only), `okstra-inspect cost` 는 `okstra context-cost` 결과 요약, `okstra-inspect errors` 는 task 의 okstra-run 에러 로그를 타임스탬프 markdown error-report 로 모아 렌더하고 요약을 출력, `okstra-inspect recap` 은 task 의 run 간 phase 전·후 요약에 더해 `.okstra` 산출물에 대한 자유 Q&A 까지 답합니다.
151
151
  - 내부 운영 계약 — `context-loader` / `team-contract` / `convergence` / `report-writer` 와 lead 계약 — 은 `prompts/lead/*.md` 로, 구현/검증 워커의 언어별 coding preflight 는 `prompts/coding-preflight/*` (overview 라우터 + clean-code + languages/frameworks/architectures 3단계 선택) 로 이동했습니다. 모두 `~/.okstra/prompts/` 에 설치되는 런타임 리소스이며 skill discovery 대상이 아닙니다. generated launch prompt 가 lead 에게 절대 경로를 제공하고, 재설치 시 과거 `okstra-context-loader` / `okstra-team-contract` / `okstra-convergence` / `okstra-report-writer` / `okstra-coding-preflight` / `okstra` skill 디렉터리는 exact-name prune 됩니다.
152
- - 플러그인 매니페스트: [`../../.claude-plugin/plugin.json`](../../.claude-plugin/plugin.json) — `npx skills@latest add Devonshin/okstra` 보조 채널이 참조. 일반 셋업에는 `npx okstra@latest install` 을 사용한다. 플러그인 매니페스트는 사용자 진입점 9개(`okstra-setup`, `okstra-brief`, `okstra-run`, `okstra-manager`, `okstra-memory`, `okstra-inspect`, `okstra-rollup`, `okstra-schedule`, `okstra-container-build`)만 노출한다.
152
+ - 플러그인 매니페스트: [`../../.claude-plugin/plugin.json`](../../.claude-plugin/plugin.json) — `npx skills@latest add Devonshin/okstra` 보조 채널이 참조. 일반 셋업에는 `npx okstra@latest install` 을 사용한다. 플러그인 매니페스트는 사용자 진입점 9개(`okstra-setup`, `okstra-brief-gen`, `okstra-run`, `okstra-manager`, `okstra-memory`, `okstra-inspect`, `okstra-rollup`, `okstra-schedule`, `okstra-container-build`)만 노출한다.
153
153
  - 설치 위치: `~/.claude/skills/<name>/SKILL.md` 또는 `~/.agents/skills/<name>/SKILL.md`.
154
154
  - 릴리스 절차: [`../../RELEASING.md`](../../RELEASING.md) — npm publish 흐름과 release-please / manual fallback.
155
155
 
@@ -316,7 +316,7 @@ okstra 의 project artifact root 는 `<PROJECT_ROOT>/.okstra/` 하나뿐입니
316
316
  okstra 는 자기 subtree 안에 자체 institutional memory 를 유지합니다.
317
317
 
318
318
  - `<PROJECT_ROOT>/.okstra/glossary.md` — run 을 가로지르며 누적되는 okstra 용어집.
319
- - `<PROJECT_ROOT>/.okstra/decisions/<NNNN>-<slug>.md` — okstra 의 결정 기록. 평가 시점은 `implementation-planning` phase 이며 `okstra-brief` 단계에서는 후보만 표시합니다.
319
+ - `<PROJECT_ROOT>/.okstra/decisions/<NNNN>-<slug>.md` — okstra 의 결정 기록. 평가 시점은 `implementation-planning` phase 이며 `okstra-brief-gen` 단계에서는 후보만 표시합니다.
320
320
 
321
321
  okstra phase 는 PRD / issue file 을 직접 쓰지 않습니다. 동등한 결정 산출물은 `requirements-discovery` 와 `implementation-planning` 이 `.okstra/` 내부에 만듭니다.
322
322
 
@@ -369,7 +369,7 @@ release-handoff 까지 완료된 task 의 산출물에서 버그가 발견되면
369
369
  - **진입**: okstra-run wizard 가 완료 task + entry phase 재진입을 감지해 `fix_cycle_confirm` 단계로 확인합니다. CLI 는 `--fix-cycle <yes|no>` (미지정 시 기록하지 않음). `--fix-cycle yes` 는 두 가드를 모두 통과해야 cycle 을 엽니다 — task-type 이 entry phase 이고, manifest 의 `workflow.lastCompletedPhase` 가 `release-handoff` 여야 하며, 위반 시 `PrepareError`. open cycle 은 task 당 동시 1개입니다.
370
370
  - **부착**: cycle 이 open 인 동안 같은 task 의 모든 run 이 (이후 `--fix-cycle` 플래그 없이도) `run` 행으로 부착되고, run-manifest / timeline 항목에 `fixCycleId` 가 찍힙니다.
371
371
  - **종료**: open cycle 에 release-handoff run 이 부착된 뒤 manifest 의 `workflow.lastCompletedPhase` 가 `release-handoff` 가 되면, 다음 prepare 가 `closed` 행을 lazy-append 합니다.
372
- - **소비처 (전부 파생 뷰)**: ① 후속 run 의 analysis-packet `## Fix History` 섹션 ② okstra-brief 의 Task Continuity Notes 인용 ③ final-report `## 5.10 Fix History` (run-manifest 에 `fixCycleId` 가 있으면 data.json `fixCycle` 블록을 validator `_validate_fix_cycle` 가 강제) ④ task-manifest `fixCycles` 요약 + task-index / task-catalog 한 줄. 네 소비처 모두 `fix_cycles.summarize()` / `packet_summary()` 파생 뷰만 읽습니다.
372
+ - **소비처 (전부 파생 뷰)**: ① 후속 run 의 analysis-packet `## Fix History` 섹션 ② okstra-brief-gen 의 Task Continuity Notes 인용 ③ final-report `## 5.10 Fix History` (run-manifest 에 `fixCycleId` 가 있으면 data.json `fixCycle` 블록을 validator `_validate_fix_cycle` 가 강제) ④ task-manifest `fixCycles` 요약 + task-index / task-catalog 한 줄. 네 소비처 모두 `fix_cycles.summarize()` / `packet_summary()` 파생 뷰만 읽습니다.
373
373
 
374
374
  ### release-handoff stage-group 모드
375
375
 
@@ -397,14 +397,14 @@ stage-group 의 상호작용 순서: **G1 base 선택 → G2 stage 확인(선택
397
397
  [requirements-discovery | implementation-planning | error-analysis] (선택된 후보별로 새 task-id 로)
398
398
  ````
399
399
 
400
- `PHASE_SEQUENCE` 의 정식 멤버에 들어가지 않는 sidetrack entry-point. 단방향 라이프사이클을 깨지 않으면서 코드베이스 발견 시나리오를 흡수한다. lens 화이트리스트와 candidate-cap 은 `scripts/okstra_ctl/improvement_lenses.py` SSOT 1개에서 통일된다. final-report 의 `## 5.9 Improvement Candidates` 표 (10 column) 는 `validators/validate_improvement_report.py` 의 11항목 contract 가 강제한다. 양방향 grilling 두 지점 (`okstra-brief` Step 4 강화 budget 8 + lead 의 Phase 1.5 reflect-back budget 12) 으로 사용자와 AI 의 이해도를 일치시킨다.
400
+ `PHASE_SEQUENCE` 의 정식 멤버에 들어가지 않는 sidetrack entry-point. 단방향 라이프사이클을 깨지 않으면서 코드베이스 발견 시나리오를 흡수한다. lens 화이트리스트와 candidate-cap 은 `scripts/okstra_ctl/improvement_lenses.py` SSOT 1개에서 통일된다. final-report 의 `## 5.9 Improvement Candidates` 표 (10 column) 는 `validators/validate_improvement_report.py` 의 11항목 contract 가 강제한다. 양방향 grilling 두 지점 (`okstra-brief-gen` Step 4 강화 budget 8 + lead 의 Phase 1.5 reflect-back budget 12) 으로 사용자와 AI 의 이해도를 일치시킨다.
401
401
 
402
402
  ### requirements-discovery fan-out
403
403
 
404
404
  혼합/다항목 요청은 requirements-discovery 가 도메인(work-category 5-enum)별 packet 으로
405
405
  분해해 `runs/requirements-discovery/fan-out/unit-*.md` 에 발행한다. 각 packet 은
406
406
  `okstra-run --task-brief <경로>` 로 새 task-key 가 된다. 순서는 `index.md` 의 depends-on
407
- 위상정렬이 담고, task 화 이후의 통합 일정은 okstra-schedule 이 맡는다. okstra-brief 는
407
+ 위상정렬이 담고, task 화 이후의 통합 일정은 okstra-schedule 이 맡는다. okstra-brief-gen
408
408
  이 경로에 개입하지 않는다. 검증: `validators/validate_fanout.py`(validate-run 훅).
409
409
 
410
410
  ### confirm 단계의 worktree 미리보기
@@ -433,7 +433,7 @@ okstra-run wizard 는 별도 분기 확인 단계를 두지 않고, 최종 `conf
433
433
 
434
434
  brief 의 **입력 시점은 entry phase 전용**입니다 — 사용자가 brief 경로를 직접 대는 것은 `requirements-discovery` / `error-analysis` / `improvement-discovery` 뿐이고, downstream phase(implementation-planning / implementation / final-verification)는 task manifest 의 `taskBriefPath` 를 자동 carry-in 합니다 (okstra-run wizard 가 묻지 않음; 미등록 시 entry 전환을 추천하는 fallback picker). `release-handoff` 는 brief 자체가 없으며 prepare 가 검증 보고서 인용 input 문서를 생성합니다.
435
435
 
436
- brief 는 **translation layer** 입니다 — 외부 입력 (이슈 트래커 ticket, 요구사항 문서, 사용자 메시지) 을 okstra-readable 형식으로 옮기되, 원문은 verbatim 으로 보존하고 okstra 가 추가한 부분은 labelled augmentation 으로 명확히 구분합니다. `okstra-brief` skill 의 산출이 source SSOT 이고, `prepare_task_bundle()` 은 분석 phase 마다 여기서 필요한 frontmatter, task-specific brief 섹션, reference expectations, carry-in clarification, directive 를 추출해 `instruction-set/analysis-packet.md` 를 만듭니다. 분석 워커의 1차 입력은 이 compact packet 이며, 원본 brief 와 profile/material 파일은 근거 확인이나 누락 보완이 필요할 때만 여는 fallback evidence 입니다.
436
+ brief 는 **translation layer** 입니다 — 외부 입력 (이슈 트래커 ticket, 요구사항 문서, 사용자 메시지) 을 okstra-readable 형식으로 옮기되, 원문은 verbatim 으로 보존하고 okstra 가 추가한 부분은 labelled augmentation 으로 명확히 구분합니다. `okstra-brief-gen` skill 의 산출이 source SSOT 이고, `prepare_task_bundle()` 은 분석 phase 마다 여기서 필요한 frontmatter, task-specific brief 섹션, reference expectations, carry-in clarification, directive 를 추출해 `instruction-set/analysis-packet.md` 를 만듭니다. 분석 워커의 1차 입력은 이 compact packet 이며, 원본 brief 와 profile/material 파일은 근거 확인이나 누락 보완이 필요할 때만 여는 fallback evidence 입니다.
437
437
 
438
438
  brief에는 보통 아래를 포함합니다.
439
439
 
@@ -446,10 +446,10 @@ brief에는 보통 아래를 포함합니다.
446
446
  - worker에게 줄 질문
447
447
  - 기대 출력
448
448
  - 이전 run 또는 연관 task 정보
449
- - (선택) glossary 추가 후보 — okstra-brief Step 4.5 가 `<PROJECT_ROOT>/.okstra/glossary.md` 에 직접 기록
449
+ - (선택) glossary 추가 후보 — okstra-brief-gen Step 4.5 가 `<PROJECT_ROOT>/.okstra/glossary.md` 에 직접 기록
450
450
  - (선택) decisions 후보 — `implementation-planning` phase 에서 평가 후 `.okstra/decisions/<NNNN>-<slug>.md` 로 승격
451
451
 
452
- okstra-brief 의 Step 6.5 는 **reporter batch confirmation** 입니다. brief 가 외부 입력을 옮기는 도중 의미 변화가 발생했는지를 사용자에게 일괄 확인받고 그 결과를 `Reporter Confirmations` 섹션에 기록합니다. 모든 분석 profile 은 이 섹션의 존재를 phase 분석 진입의 precondition 으로 강제합니다 (validator: `validators/validate-brief.py`).
452
+ okstra-brief-gen 의 Step 6.5 는 **reporter batch confirmation** 입니다. brief 가 외부 입력을 옮기는 도중 의미 변화가 발생했는지를 사용자에게 일괄 확인받고 그 결과를 `Reporter Confirmations` 섹션에 기록합니다. 모든 분석 profile 은 이 섹션의 존재를 phase 분석 진입의 precondition 으로 강제합니다 (validator: `validators/validate-brief.py`).
453
453
 
454
454
  기본 템플릿:
455
455
 
package/docs/kr/cli.md CHANGED
@@ -127,7 +127,7 @@ interactive terminal에서 실행하면 다음 규칙이 추가로 적용됩니
127
127
  - Verdict Token: `candidates-ready` / `no-candidates` / `blocked`.
128
128
  - 라우팅: 자동 spin-off 없음. 사용자가 후보를 골라 새 task-id 로 `requirements-discovery` / `implementation-planning` / `error-analysis` 진입.
129
129
  - 워커: claude + codex + antigravity + report-writer 모두 필수.
130
- - 양방향 grilling 두 지점: `okstra-brief` Step 4 강화 (budget 8) + lead 의 Phase 1.5 reflect-back (budget 12).
130
+ - 양방향 grilling 두 지점: `okstra-brief-gen` Step 4 강화 (budget 8) + lead 의 Phase 1.5 reflect-back (budget 12).
131
131
  - Validator: `validators/validate_improvement_report.py` 가 `improvement-discovery` final-report 의 11항목 contract 를 강제.
132
132
  - `improvement-discovery` run 은 `PHASE_SEQUENCE` 에 포함되지 않으므로 `--task-key` 단축 경로의 `nextRecommendedPhase` 자동 채움 대상이 아닙니다.
133
133
 
@@ -310,7 +310,7 @@ Token/cost accounting:
310
310
 
311
311
  | Skill | User-invocable | Role |
312
312
  |---|---:|---|
313
- | `okstra-brief` | yes | Produce task brief from ticket/doc/link/conversation |
313
+ | `okstra-brief-gen` | yes | Produce task brief from ticket/doc/link/conversation |
314
314
  | `okstra-run` | yes | Start/resume okstra task in current Claude Code session |
315
315
  | `okstra-memory` | yes | Store/search/archive global conversation memory under `~/.okstra/memory-book` |
316
316
  | `okstra-inspect` | yes | Unified read-side — sub-commands `status` (lifecycle + workStatus), `history` (past runs / re-run / resume), `report` (find final-report), `time` (elapsed-time breakdown), `logs` (wrapper log inventory + cleanup), `cost` (task bundle context/read cost) |
@@ -454,7 +454,7 @@ Project-local `<PROJECT_ROOT>/.claude/settings.local.json` is provisioned as a s
454
454
 
455
455
  ### 7.2 Brief creation
456
456
 
457
- `/okstra-brief` turns source material into a validated task brief. It preserves source material verbatim, labels okstra augmentation, and records reporter confirmations.
457
+ `/okstra-brief-gen` turns source material into a validated task brief. It preserves source material verbatim, labels okstra augmentation, and records reporter confirmations.
458
458
 
459
459
  ### 7.3 Task run
460
460
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okstra",
3
- "version": "0.112.0",
3
+ "version": "0.114.0",
4
4
  "description": "Multi-agent cross-verification orchestrator runtime + Claude Code skills.",
5
5
  "license": "MIT",
6
6
  "author": "devonshin",
@@ -1,5 +1,5 @@
1
1
  {
2
- "package": "0.112.0",
3
- "builtAt": "2026-07-04T17:45:47.952Z",
2
+ "package": "0.114.0",
3
+ "builtAt": "2026-07-08T17:31:16.739Z",
4
4
  "repoRoot": "/home/runner/work/okstra/okstra"
5
5
  }
@@ -112,7 +112,7 @@ The wrapper exists because Claude Code's Bash permission matcher rejects simple-
112
112
  ```
113
113
  Emit that line first, then the stdout unmodified. The model line is the ONLY addition permitted — do not otherwise summarize or alter the CLI output. This applies to convergence reverify dispatches too.
114
114
 
115
- 9. When `Task Type` is `improvement-discovery`, the lead's Phase 1.5 reflect-back log at `<RUN_DIR>/state/phase-1.5-grilling.md` is the authoritative scope and lens definition. Read its `Resolved scope` and `Resolved lenses` blocks and do NOT re-interpret the brief's raw `scan-scope` / `priority-lenses` fields. Findings that violate the resolved lens whitelist or scope are rejected by `validators/validate_improvement_report.py`.
115
+ 9. If your dispatch prompt carries a `**Phase 1.5 Grilling Log:** <abs-path>` anchor header (the lead injects it only on `improvement-discovery` runs), the file it points to is the authoritative scope and lens definition. Read it at the absolute path from the anchor — do NOT synthesize the path from `<RUN_DIR>`. Use its `Resolved scope` and `Resolved lenses` blocks and do NOT re-interpret the brief's raw `scan-scope` / `priority-lenses` fields. Findings that violate the resolved lens whitelist or scope are rejected by `validators/validate_improvement_report.py`.
116
116
 
117
117
  ## Stop Condition
118
118
 
@@ -51,7 +51,7 @@ Unlike the Codex / Antigravity workers, you are an in-process Claude subagent
51
51
 
52
52
  5. **MCP usage**: The canonical list of MCP servers and tools available for this run lives in the lead prompt's `## Available MCP Servers` section (sourced from `.okstra/project.json`'s `mcpServers` array). When the task requires inspection of an external system covered by one of those servers, call the listed tool directly by name (e.g. `mcp__<server>__<tool>`). Do NOT shell out via `claude --mcp-cli call ...` or run the tool name as a Bash command — those are not valid invocation paths. If a server you need is not listed, record `MCP not available for this run` in your worker output rather than guessing a tool name.
53
53
 
54
- 6. When `Task Type` is `improvement-discovery`, the lead's Phase 1.5 reflect-back log at `<RUN_DIR>/state/phase-1.5-grilling.md` is the authoritative scope and lens definition. Read its `Resolved scope` and `Resolved lenses` blocks and do NOT re-interpret the brief's raw `scan-scope` / `priority-lenses` fields. Findings that violate the resolved lens whitelist or scope are rejected by `validators/validate_improvement_report.py`.
54
+ 6. If your dispatch prompt carries a `**Phase 1.5 Grilling Log:** <abs-path>` anchor header (the lead injects it only on `improvement-discovery` runs), the file it points to is the authoritative scope and lens definition. Read it at the absolute path from the anchor — do NOT synthesize the path from `<RUN_DIR>`. Use its `Resolved scope` and `Resolved lenses` blocks and do NOT re-interpret the brief's raw `scan-scope` / `priority-lenses` fields. Findings that violate the resolved lens whitelist or scope are rejected by `validators/validate_improvement_report.py`.
55
55
 
56
56
  ## Required Reading Before Any Analysis
57
57
 
@@ -112,7 +112,7 @@ The wrapper exists because Claude Code's Bash permission matcher rejects simple-
112
112
  ```
113
113
  Emit that line first, then the stdout unmodified. The model line is the ONLY addition permitted — do not otherwise summarize or alter the CLI output. This applies to convergence reverify dispatches too.
114
114
 
115
- 9. When `Task Type` is `improvement-discovery`, the lead's Phase 1.5 reflect-back log at `<RUN_DIR>/state/phase-1.5-grilling.md` is the authoritative scope and lens definition. Read its `Resolved scope` and `Resolved lenses` blocks and do NOT re-interpret the brief's raw `scan-scope` / `priority-lenses` fields. Findings that violate the resolved lens whitelist or scope are rejected by `validators/validate_improvement_report.py`.
115
+ 9. If your dispatch prompt carries a `**Phase 1.5 Grilling Log:** <abs-path>` anchor header (the lead injects it only on `improvement-discovery` runs), the file it points to is the authoritative scope and lens definition. Read it at the absolute path from the anchor — do NOT synthesize the path from `<RUN_DIR>`. Use its `Resolved scope` and `Resolved lenses` blocks and do NOT re-interpret the brief's raw `scan-scope` / `priority-lenses` fields. Findings that violate the resolved lens whitelist or scope are rejected by `validators/validate_improvement_report.py`.
116
116
 
117
117
  ## Stop Condition
118
118
 
@@ -25,7 +25,7 @@
25
25
  4. If multiple candidates are found based on `task-id` alone, the situation is ambiguous, so `task-group` or the full `taskKey` is required.
26
26
  5. If the user has not provided an explicit task key/path, first read `.okstra/discovery/latest-task.json` using the current-task convenience pointer.
27
27
  6. If the latest-task pointer is missing or corrupted but the task catalog exists, list candidates from the catalog. Do not use the legacy `CLAUDE.md`, project guide, or task scan fallback.
28
- 7. If **neither** `latest-task.json` **nor** `task-catalog.json` exists, ABORT Phase 1 with `OKSTRA_CONTEXT_NOT_INITIALIZED`. Suggest the user run `/okstra-setup` and `/okstra-brief` to bootstrap the project. Do NOT crawl `.okstra/tasks/` directly — discovery pointers are the only supported entry path.
28
+ 7. If **neither** `latest-task.json` **nor** `task-catalog.json` exists, ABORT Phase 1 with `OKSTRA_CONTEXT_NOT_INITIALIZED`. Suggest the user run `/okstra-setup` and `/okstra-brief-gen` to bootstrap the project. Do NOT crawl `.okstra/tasks/` directly — discovery pointers are the only supported entry path.
29
29
 
30
30
  ## Step 2: Open and Parse task-manifest.json
31
31
 
@@ -128,7 +128,7 @@ Read source files lazily:
128
128
 
129
129
  After reading `task-brief.md`, extract the frontmatter `reporter-confirmations` field (`complete | partial | pending | skipped`) and apply the shared handling matrix in `prompts/profiles/_common-contract.md` "Brief handoff contract" → "Reporter confirmation precondition" — that block is the single authority on per-value semantics; do not re-derive them here.
130
130
 
131
- Loader-level flow control only: on `pending` (or field missing), emit `REPORTER_CONFIRMATION_PENDING` and STOP — do not invoke `team-contract` or any analyser; the operator must rerun `okstra-brief` Step 6.5 before Phase 2 can start. Every other value proceeds to Step 5 (with the matrix's flags carried forward for the phase profile).
131
+ Loader-level flow control only: on `pending` (or field missing), emit `REPORTER_CONFIRMATION_PENDING` and STOP — do not invoke `team-contract` or any analyser; the operator must rerun `okstra-brief-gen` Step 6.5 before Phase 2 can start. Every other value proceeds to Step 5 (with the matrix's flags carried forward for the phase profile).
132
132
 
133
133
  ## Step 5: Read Run Manifest and Team State
134
134
 
@@ -31,13 +31,13 @@ profile document.
31
31
  - Anti-escalation rule (shared):
32
32
  - treating "다음 단계 진행해" or equivalent user phrases as authorisation to start a *different* lifecycle phase is forbidden. The next phase begins only in a separate okstra run launched with the new `--task-type`. Per-profile documents may further restrict this within their own scope.
33
33
  - Run-scoped pane & teammate lifecycle (shared — run-start pane recording, per-batch cleanup, wrap-up pane disposition, run-end teammate teardown): these are lead-only operating duties and live in `prompts/lead/okstra-lead-contract.md` "Run-scoped pane & teammate lifecycle". Profiles do not restate them.
34
- - Brief handoff contract (shared — applies whenever the run consumes a task brief produced by `okstra-brief`):
34
+ - Brief handoff contract (shared — applies whenever the run consumes a task brief produced by `okstra-brief-gen`):
35
35
  - the brief is a **pre-discovery artifact**: it converts a domain-reporter's words (non-expert *or* developer) into expert-consumable form so this and later phases can run with zero fill-in questions to the operator. The brief is **not** authoritative on solution decisions; it is authoritative on the reporter's intent.
36
- - **Reporter confirmation precondition (BLOCKING)**: the brief's frontmatter carries `reporter-confirmations: <complete | partial | pending | skipped>` set by `okstra-brief` Step 6.5. Every phase that consumes the brief MUST read this field before doing analysis. The handling matrix is:
36
+ - **Reporter confirmation precondition (BLOCKING)**: the brief's frontmatter carries `reporter-confirmations: <complete | partial | pending | skipped>` set by `okstra-brief-gen` Step 6.5. Every phase that consumes the brief MUST read this field before doing analysis. The handling matrix is:
37
37
  - `complete` → proceed normally.
38
38
  - `partial` → proceed; treat still-unmarked `intent-check:` / `conversion-block:` rows as the `skipped` branch.
39
39
  - `skipped` → do NOT silently infer the missing answers. Promote each unmarked `intent-check:` / `conversion-block:` row into this run's `## 1. Clarification Items` as `Kind=decision`. Use `Blocks=approval` in `implementation-planning`, where the row gates the `approved:` frontmatter flip; otherwise use `Blocks=next-phase`. The recommended answer is drawn from the brief's matching content and clearly labelled `보고자 직접 확인 권장`.
40
- - `pending` (or field missing) → ABORT analysis; render the Verdict Card with `Verdict Token = blocked` + `Direction = hold` and write a single `## Reporter Confirmation Required` block (no leading number) summarising which rows are pending. The `## 1. Clarification Items` table carries one row per pending item with `Blocks=approval` in `implementation-planning`, otherwise `Blocks=next-phase`. The operator must rerun `okstra-brief` Step 6.5. Do NOT emit `## 0.` for this case — Section 0 is reserved for clarification-response carry-in only.
40
+ - `pending` (or field missing) → ABORT analysis; render the Verdict Card with `Verdict Token = blocked` + `Direction = hold` and write a single `## Reporter Confirmation Required` block (no leading number) summarising which rows are pending. The `## 1. Clarification Items` table carries one row per pending item with `Blocks=approval` in `implementation-planning`, otherwise `Blocks=next-phase`. The operator must rerun `okstra-brief-gen` Step 6.5. Do NOT emit `## 0.` for this case — Section 0 is reserved for clarification-response carry-in only.
41
41
  `[CONFIRMED <YYYY-MM-DD> → RC-N]` markers on `Open Questions` rows are the per-row signal that the reporter has answered; their answers live verbatim under `## Reporter Confirmations` in the brief.
42
42
  - `Source Material` is reporter-verbatim. Do NOT paraphrase, summarize, reorder, or restructure it. Quote it directly when needed.
43
43
  - `Related Task Graph` is the structured task-topology handoff. If the section is present and not `_(none)_`, read it before classification, diagnosis, candidate discovery, fan-out, or next-step routing. Preserve the edge direction exactly as written: `From` → `To` is load-bearing for `depends-on`, `blocks`, parent/child, follow-up, and split relations.
@@ -20,6 +20,7 @@ fails, fix it or surface the violation — do not claim done on a failing item.
20
20
  - conventions: applied the routed pack + project patterns (name which ones)
21
21
  - names & comments: names say what, comments say why; no obvious-restatement comments; no truthful-name violations
22
22
  - verification: ran the actual build/test — paste the exact command line and its real exit code / output tail, never a paraphrased "tests pass"
23
+ - acceptance: each implemented plan step's `Acceptance:` condition is observably met — cite the RED→GREEN test (or the command output) proving it per step, not one global "acceptance met"; and each `Test case (success|boundary|failure)` the plan declared for this stage has a matching test in the diff (name the test), so declared edge/failure cases are not silently uncovered
23
24
  - cleanup: no dead or commented-out code left behind
24
25
 
25
26
  Close with a `Self-check coverage:` line naming the files you verified the
@@ -85,7 +85,7 @@ The final report keeps both — executor's `Validation evidence` AND each verifi
85
85
 
86
86
  ### Static design & test-quality review (gate — runs after the command re-run, before the verdict)
87
87
 
88
- Re-running commands proves the diff *builds and passes*; it does NOT prove the diff is *well-designed*. Lint/test green is necessary but not sufficient — self-mocked tests, interaction-only assertions, and untruthful names all survive a green pipeline. This gate is the filter for exactly those defects, so the executor's design errors are caught here instead of in post-merge PR review. It is a real gate, not a checklist: it enumerates the full diff and a blocking hit forces `FAIL`.
88
+ Re-running commands proves the diff *builds and passes*; it does NOT prove the diff is *well-designed*. Lint/test green is necessary but not sufficient — self-mocked tests, interaction-only assertions, and untruthful names all survive a green pipeline. This gate is the filter for exactly those defects, so the executor's design errors are caught here instead of in post-merge PR review. It is a real gate, not a checklist: it enumerates the full diff and a blocking hit forces `FAIL`. This blocking-check taxonomy is the **gate counterpart** of the executor's `Pre-commit diff review sweep` (`_implementation-diff-review.md`) prevention pass — the same defect families, different action (executor fixes in place; verifier fails the verdict). Both lists are inlined on purpose: each sidecar is delivered stand-alone into a flat CLI prompt (lazy-read, not INCLUDE-expanded), so neither can factor the taxonomy into a shared fragment.
89
89
 
90
90
  - **Scope (no silent sampling).** Enumerate every changed source/test file via `git diff --name-only <base>...HEAD` and review each one. Skipping a changed file silently is a `contract-violated` outcome. If a file's language has no reference and is not covered by the agnostic checks below, record `design-review skipped: <file> (language=<x> no reference)` — never pass it silently.
91
91
  - **Load the same conventions the executor used via the routed pack.** Use this worker prompt's `**Coding preflight pack:**` anchor header as the absolute path to the installed routed pack. Read `overview.md` first, then `clean-code.md`, then apply the router's three ordered stages: language, framework, architecture. In each stage, iterate every rule, treat a rule as matched when any listed condition is true, and accumulate every matching resource — including `frameworks/node-server.md` for server-side Node work and `architectures/hexagonal.md` for ports-and-adapters / NestJS-hex layouts. Degrade to the agnostic checks below when the resolved pack is unreadable, and record either `coding-conventions: resources=<...>` or `coding-conventions: resource-unavailable → applied <project rules + agnostic principles>`. The verifier does NOT inline language rules — it loads the same situation-specific resources as the executor preflight.
@@ -14,7 +14,7 @@
14
14
  - 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
15
15
  - 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
16
16
  - 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
17
- - DB / IO / SQL real-execution evidence — trigger: the diff touches DB/IO/SQL (ORM / query-builder, `*.repository.*`, model / `migrations/**` / `*.sql`, or changed query strings). Then Validation Evidence MUST cite a real (or faithful-replica) DB execution — the `db-test` command + exit code — not a mock-only suite. Rationale: a mock-only suite cannot observe the SQL actually emitted (observed failure class: `prompts/profiles/_implementation-verifier.md` §"DB / IO / SQL change — real-execution gate"). A DB-touching change whose only evidence is mocked, or for which no `db-test` ran, is an **Acceptance Blocker** (`major`+); since `accepted` requires zero blockers the verdict becomes `conditional-accept` / `blocked`. This gate stops an unverified DB change from reaching `release-handoff` and being pushed.
17
+ - DB / IO / SQL real-execution evidence — trigger: the diff touches DB/IO/SQL (ORM / query-builder, `*.repository.*`, model / `migrations/**` / `*.sql`, or changed query strings). Then Validation Evidence MUST cite a real (or faithful-replica) DB execution — the `db-test` command + exit code — not a mock-only suite. Rationale: a mock-only suite cannot observe the SQL actually emitted (observed failure class: `prompts/profiles/_implementation-verifier.md` §"DB / IO / SQL change — real-execution gate"). A DB-touching change whose only evidence is mocked, or for which no `db-test` ran, is an **Acceptance Blocker** (`major`+; per the Verdict vocabulary below, any blocker moves the verdict off `accepted`). This gate stops an unverified DB change from reaching `release-handoff` and being pushed.
18
18
  - 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)
19
19
  - 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
20
20
  - project review-rule packs (when present) — search `<PROJECT_ROOT>/skills/*review*`, `<PROJECT_ROOT>/.claude/skills/*review*`, and up to two parent directories' `skills/*review*/SKILL.md`; read the matching `SKILL.md` + referenced `references/*.md` and apply their rules as an acceptance overlay (record `project-review-rules: <paths read>` or `project-review-rules: none found`). This is a static review pass, not a PR-comment workflow — do NOT dispatch reviewer subagents. Because this phase verifies the **whole-task merged diff**, it is the gate that catches **cross-stage findings a per-stage `implementation` verifier structurally cannot see** (each implementation run reviews only its own stage diff): most importantly two cross-stage conditions: (a) the same helper stack / transform / domain rule duplicated across stages or services — byte-identical duplication is always an Acceptance Blocker, and semantically-equivalent transforms across services are blockers unless the approved plan explicitly justified keeping them separate; (b) an API newly orphaned because its only caller was removed in a different stage. A confirmed cross-stage duplication of this kind is an Acceptance Blocker (`major`+) that cites every `path:line` location and names the shared-module location to converge on. (Single-stage scope sees only one stage, so it cannot raise cross-stage findings — note that limitation rather than implying coverage.)
@@ -31,14 +31,15 @@
31
31
  - the lead still captures `git status --short` from the injected worktree to confirm the analysis ran against the delivered work-tree state; an unexpected divergence (dirty tree outside `.okstra/`, missing worktree) is a `tool-failure`, not a silent proceed.
32
32
  - Required deliverable shape (final report, in addition to the standard sections):
33
33
  - **Source Implementation Report(s)**: the `VERIFICATION_TARGET` snapshot verbatim — verification scope, worktree path, base ref, the list of stages under verification, and one row per stage citing its originating implementation final-report (`report_path` from `consumers.jsonl`; render `(report_path unrecorded)` when absent). The lead injects this same snapshot into every analyser prompt (`**Verification scope:** / **Worktree:** / **Verification base ref:** / **Verification diff stat:**`); a worker that cannot confirm its analysis ran against that worktree's delivered diff (against `base ref`) MUST record a `tool-failure`.
34
- - **Verdict vocabulary**: Section 7 (`Final Verdict`) MUST include a `Verdict Token` field whose value is exactly one of `accepted`, `conditional-accept`, or `blocked`. `conditional-accept` requires an explicit, exhaustive list of conditions; ambiguous verdicts ("looks good", "mostly ready") are not allowed. Each condition MUST be recorded as a row in the **Conditional Acceptance Conditions** deliverable (`id` `CA-NNN`, `condition`, `evidenceRequired`, `blocksReleaseHandoff`). The validator enforces verdict↔deliverable consistency: `accepted` ⇒ zero acceptance blockers, `blocked` ⇒ at least one, `conditional-accept` ⇒ at least one condition, and a `release-handoff` routing recommendation is allowed only when the verdict is `accepted`.
34
+ - **Verdict vocabulary**: Section 7 (`Final Verdict`) MUST include a `Verdict Token` field whose value is exactly one of `accepted`, `conditional-accept`, or `blocked`. `conditional-accept` requires an explicit, exhaustive list of conditions; ambiguous verdicts ("looks good", "mostly ready") are not allowed. Each condition MUST be recorded as a row in the **Conditional Acceptance Conditions** deliverable (`id` `CA-NNN`, `condition`, `evidenceRequired`, `blocksReleaseHandoff`). The validator enforces verdict↔deliverable consistency: `accepted` ⇒ zero acceptance blockers, `blocked` ⇒ at least one, `conditional-accept` ⇒ at least one condition, and a `release-handoff` routing recommendation is allowed only when the verdict is `accepted`. **Any Acceptance Blocker therefore forces the verdict off `accepted` (to `conditional-accept` or `blocked`); the gates below cite this rule instead of restating the arithmetic.**
35
35
  - **Acceptance Blockers block** (under section 4): one row per blocker with `id`, `severity` (`critical` / `major` / `minor`), evidence (file path, log excerpt, or test output), and the recommended follow-up phase (`error-analysis` or `implementation-planning`). Empty block is acceptable and preferred — render the single line `- No acceptance blockers found.`
36
36
  - **Residual Risk block** (under section 4): risks that are not blockers but should be tracked, each with mitigation owner and a trigger that would escalate them to a blocker.
37
37
  - **Validation Evidence**: for every requirement in the originating plan or task brief, cite the artifact (commit SHA, test output, log line, MCP SELECT result) that demonstrates coverage. Paraphrased "verified" claims without an artifact are rejected.
38
- - **Read-only command log**: any pre-existing test/validation command executed during this run MUST be listed with its exact command line and exit code. No mutating commands may appear here.
38
+ - **Read-only command log**: any pre-existing test/validation command touched during this run MUST be listed with its exact command line and one honest status — `executed` (ran; carries its exit code) / `env-unavailable` (should run but cannot in this environment — missing replica DB, container, or service; carries the reason, never a faked pass) / `not-configured` (no such qa-command tier) / `rejected` (a mutating/denied token skipped, carries the denied token). A check that could not run locally is recorded as `env-unavailable` with the reason — never silently dropped and never reported as `executed` with an invented exit code. Mutating-command prohibition is the shared read-only boundary (see Non-goals); it is not restated per row.
39
39
  - **Two-tier command lookup (shared with `implementation`):** when this phase performs its own independent re-validation, the command source is exactly the same two tiers `implementation` verifiers use — Tier 1 is the originating task brief / approved plan's `validation` set, Tier 2 is `<PROJECT_ROOT>/.okstra/project.json` under `qaCommands`. Auto-detecting tools from manifest files is forbidden; missing tiers are recorded as `qa-command not configured: <category>` rather than guessed. The `cmd` deny-list (`--fix`, `--write`, ` -w`, ` -u`, `--snapshot-update`, `INSTA_UPDATE=<not-no>`, `cargo update`, `npm install` without `ci`, etc.) is enforced identically. NOTE: runtime fail-fast validation (`okstra_ctl.qa_commands.validate_qa_commands`) only fires at `--task-type implementation` run-prep, so this phase MUST self-check each `qaCommands` entry against the deny-list before executing it — if a denied token is present, skip the command and record it as a `Read-only command log` line `qa-command rejected (denied token: <token>): <label>`.
40
- - **Tier 3 — stage conformance scripts (whole-task union):** because this phase verifies the **integrated, merged** state, it re-runs conformance against that state rather than per-stage. Read the task-level manifest `<task_root>/qa/conformance-manifest.json` (the directory is the `TASK_QA_PATH` token) and, in **whole-task scope**, run the `runCommand` of **every** `entries[]` item against the merged worktree, refreshing each `<task_root>/qa/result-<stageKey>.json` (`{ "stageKey", "overall": "PASS"|"FAIL"|"MISSING", "ranAt", "requirements" }`). In **single-stage scope**, run only the entry whose `stageKey` matches the verified stage. An entry carrying an `exemption` or user `waiver` is NOT executed — record the skip and reason; a `waiver` becomes a `conditional-accept` condition surfaced in the section 7 Verdict (conformance left unverified by user acknowledgement). Each `runCommand` runs in the worktree cwd with `qaEnv` env (replica DB DSN / app base URL / env file) — **replica / test environment only**, never shared / staging / prod, and the same source/lockfile mutation deny-list applies (a conformance script MAY mutate only its `qaEnv` replica datastore). Interpret each result from the exit code + stdout `QA-RESULT: PASS|FAIL` (last wins) and `REQ <id>: PASS|FAIL: <reason>` lines; no `QA-RESULT` marker → `MISSING`. Any entry whose result is not `PASS` (including `MISSING` or a never-run/missing sidecar) is an **Acceptance Blocker** (`major`+), so the verdict becomes `conditional-accept` / `blocked`. This is the same gate the `validate-run.py` Tier 3 check enforces on the result sidecars.
40
+ - **Tier 3 — stage conformance scripts (whole-task union):** because this phase verifies the **integrated, merged** state, it re-runs conformance against that state rather than per-stage. Read the task-level manifest `<task_root>/qa/conformance-manifest.json` (the directory is the `TASK_QA_PATH` token) and, in **whole-task scope**, run the `runCommand` of **every** `entries[]` item against the merged worktree, refreshing each `<task_root>/qa/result-<stageKey>.json` (`{ "stageKey", "overall": "PASS"|"FAIL"|"MISSING", "ranAt", "requirements" }`). In **single-stage scope**, run only the entry whose `stageKey` matches the verified stage. An entry carrying an `exemption` or user `waiver` is NOT executed — record the skip and reason; a `waiver` becomes a `conditional-accept` condition surfaced in the section 7 Verdict (conformance left unverified by user acknowledgement). Each `runCommand` runs in the worktree cwd with `qaEnv` env (replica DB DSN / app base URL / env file) — **replica / test environment only**, never shared / staging / prod, and the same source/lockfile mutation deny-list applies (a conformance script MAY mutate only its `qaEnv` replica datastore). Interpret each result from the exit code + stdout `QA-RESULT: PASS|FAIL` (last wins) and `REQ <id>: PASS|FAIL: <reason>` lines; no `QA-RESULT` marker → `MISSING`. Any entry whose result is not `PASS` (including `MISSING` or a never-run/missing sidecar) is an **Acceptance Blocker** (`major`+). This is the same gate the `validate-run.py` Tier 3 check enforces on the result sidecars.
41
41
  - **Manual user test results**: take each item from the source implementation report's §5.7.9 Manual User Test (Draft), execute the ones reproducible in this environment (e.g. `/okstra-container-build`, which runs `okstra container up`, then the documented steps), and record `result` (`pass` / `fail` / `blocked`) + observed value in §5.8.7 (data field `finalVerification.manualUserTest`). Steps that need human-only interaction this run cannot perform are recorded as `blocked` with the reason (handed to the user), never silently skipped. A failed manual test is an Acceptance Blocker. If the draft was an exemption (`applicable=false`), reaffirm the reason in one line (`applicable=false` + `exemptionReaffirm`).
42
+ - **Could-not-verify roll-up (§5.8.9)**: the template mechanically aggregates every not-confirmed check into one scannable list — `gap` requirement-coverage rows, `not-configured` / `env-unavailable` / `rejected` command rows, and `blocked` manual tests. You do not hand-author it, but you MUST give those rows their honest status so nothing unverified hides across sections: a check silently recorded as `executed`/`covered` will not surface in the roll-up. This is okstra's answer to "say what could not be verified this run."
42
43
  - **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`. `release-handoff` is additionally allowed ONLY when the verification scope (the `Verification scope:` line of the injected `VERIFICATION_TARGET` block, recorded as the report's `verificationScope` field) is `whole-task`; a `single-stage` accepted run routes to `release-handoff(stage-group)` (or `implementation` / `done`); plain `release-handoff` remains whole-task-only. Enforcement: `validators/validate-run.py` rejects a `single-stage` report whose routing cites plain `release-handoff`.
43
44
  - **Verified-row recording** (single-stage scope only): when the Verdict Token is `accepted`, the lead MUST run `okstra handoff record-verified --plan-run-root <plan-run-root> --stage <N> --report-path <final-report.md path> --data-json <final-report data.json path>` and quote the command + exit code in the report. The helper re-validates taskType/scope/verdict from data.json, so a non-accepted or whole-task report is rejected at the tool layer.
44
45
  - Clarification request policy (phase-specific addendum — shared policy is in `_common-contract.md`):
@@ -50,7 +51,7 @@
50
51
  4. **Verifier dissent preserved** — if workers reach different verdicts, the disagreement is visible in section 1.2; synthesis hides nothing.
51
52
  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.
52
53
  - Cross-verification mode:
53
- - **Acceptance critic (opt-in)**: when `convergence.critic.enabled=true` (chosen via the okstra-run picker or `--critic`), a reused-worker **acceptance devil's-advocate** pass is dispatched concurrently with the first convergence reverify round to surface candidate acceptance blockers the verifiers may have missed; candidates are verified only after convergence completes. Each candidate is verified **confirm-or-downgrade**: confirmed → an `Acceptance Blockers` row (which, since `accepted` requires zero blockers, moves the verdict to `conditional-accept` / `blocked`); unconfirmed → a `Residual Risk` row (never dropped). See `prompts/lead/convergence.md` "Acceptance critic pass (final-verification)".
54
+ - **Acceptance critic (opt-in)**: when `convergence.critic.enabled=true` (chosen via the okstra-run picker or `--critic`), a reused-worker **acceptance devil's-advocate** pass is dispatched concurrently with the first convergence reverify round to surface candidate acceptance blockers the verifiers may have missed; candidates are verified only after convergence completes. Each candidate is verified **confirm-or-downgrade**: confirmed → an `Acceptance Blockers` row; unconfirmed → a `Residual Risk` row (never dropped). See `prompts/lead/convergence.md` "Acceptance critic pass (final-verification)".
54
55
  - Non-goals:
55
56
  - proposing unrelated refactors beyond the delivered scope
56
57
  - **source code edits, follow-up bug fixes, or scope expansion** — this run renders a verdict only; defects detected here become inputs to a new `error-analysis` or `implementation-planning` run
@@ -20,6 +20,7 @@
20
20
  - **codebase-first ambiguity resolution**: any ambiguity that can be answered by `Read` / `Grep` MUST be resolved that way and recorded with file:line evidence. Only ambiguities that genuinely require a human decision are escalated as `Clarification Items` rows. Writing a clarification row for something the code already answers is a defect of this phase.
21
21
  - flag any requirement that is ambiguous, contradictory, or missing success criteria — register each one as a row in the report's `## 1. Clarification Items` table with `Blocks=approval` instead of guessing
22
22
  - read `<PROJECT_ROOT>/.okstra/glossary.md` and `<PROJECT_ROOT>/.okstra/decisions/` titles if present. Absent okstra memory files are the normal state — do not error. Treat the brief's `terminology:*` resolutions from `requirements-discovery` (if any) as authoritative; if missing, resolve any remaining fuzzy term as a `Blocks=approval` clarification row.
23
+ - **spec-settled short-circuit**: when the brief already carries a decision-complete design the reporter has confirmed (a `requirements-discovery` outcome whose approach sits behind a `[CONFIRMED …]` marker, or a verbatim reporter-approved plan in `Source Material`), do NOT re-litigate the settled decision. Present that design as the `Recommended Option`, and record the alternatives it already weighed as the remaining Option Candidate(s) tagged `(considered & rejected upstream — <why>)` rather than manufacturing fresh competing options to fill the slot. The Stage Map, validation, gates, and the ≥2-candidate shape all still apply — this short-circuits re-deliberation, not the plan's structure.
23
24
  - Primary focus areas:
24
25
  - requirement gaps
25
26
  - affected components and boundaries
@@ -65,6 +66,7 @@
65
66
  - estimated blast radius (units, configs, deployment manifests, data migrations)
66
67
  - trade-off matrix across options (rows = options, columns at minimum: complexity, risk, reversibility, test coverage cost, rollout cost)
67
68
  - recommended option with rationale tied to the design principles above
69
+ - **Working Assumptions (non-blocking)**: inside the `Recommended Option` section, an `Assumptions:` labelled list recording each assumption the plan proceeds on **without** user confirmation but that does NOT block approval — a sensible default the reviewer can still veto (e.g. "assuming the existing retry policy stays; not re-tuning it here"). This is distinct from `## 1. Clarification Items`, which gates approval: anything that must be answered before coding is a clarification row, never an assumption. Omit the list only when there are genuinely none. (No new scanned heading — it lives under the existing `Recommended Option`. The `Authority & permissions` class from the shared contract is explicitly NOT recorded here — that class is suppressed, not surfaced.)
68
70
  - **Stage Map (mandatory — always emitted, even when N=1):** a table of all stages with `stage | title | depends-on | step-count | exit-contract-summary`. `depends-on` is `(none)` or a comma-separated stage number list. Stages with `depends-on (none)` can be implemented in parallel by two simultaneous `implementation` runs.
69
71
  - **Keep the table at exactly 5 columns** — do NOT add a column. `validators/validate-implementation-plan-stages.py` parses `stage | title | depends-on | step-count | exit-contract-summary` and silently skips any row that is not exactly 5 cells, so a 6th column would drop every stage and bypass S2–S11.
70
72
  - **Multi-project plans only** (the plan's work spans more than one project — see the Project-boundary partition rule below): prefix each stage's `title` cell with a `[<project>]` tag (e.g. `[okstra] Add X`) so the project each stage belongs to is readable at a glance, and add exactly one line directly under the Stage Map table — `Cross-project parallelism: <which per-project stages run in parallel, which are sequenced, and the cross-project dependency that forces each sequencing>`. Single-project plans omit both the tag and the line.
@@ -92,7 +94,7 @@
92
94
  - **Parallel-feasibility check (mandatory for every multi-project plan):** disjoint files (S9 below) is necessary but NOT sufficient for parallelism — a cross-project API/contract/schema/deploy-order dependency forces sequencing even when no file overlaps. For each pair of projects, explicitly determine and record (in the `Cross-project parallelism:` line) whether they are independent (run in parallel) or sequenced (and the exact dependency that forces the order).
93
95
  - **Parallel-safety invariant (BLOCKING):** any two stages that are both `depends-on (none)` MUST predict disjoint file sets in their `Stage Exit Contract`. Two parallel `implementation` runs would otherwise edit the same file concurrently. Work touching a shared file must either go in one stage or be ordered with `depends-on`. Enforced by `validators/validate-implementation-plan-stages.py` check S9.
94
96
  - **Cross-project dependency rows (`crossProjectDependencies` 배열 — 옛 `## Cross-Repo Carry` 부록을 대체):** 타 프로젝트(다른 repo / 다른 top-level 독립 배포 모듈 / published 패키지)에 대한 의존은 freeform `## Cross-Repo Carry` 부록이 아니라 **구조 필드 `crossProjectDependencies` 의 `XP-NNN` 행**으로 기록한다. 한 프로젝트 의존마다 한 XP 행을 두고, 양방향 중 해당하는 `direction` 을 채운다(렌더는 `### Cross-Project Dependencies` §5.4; 단일 프로젝트 계획은 빈 배열). 행 필드는 옛 세 subsection 을 다음으로 대체한다 — `requiredWork`(상대가 만들어야 할 구체 작업) / `verificationSignal`(이 run 이 관측할 신호) / `linkedWork`(신호 충족 전 막히는 이 계획의 stage·step) / `howToStart`(상대 repo 에서의 정확한 handoff).
95
- - `direction: upstream-precondition` — 이 run 이 상대의 **선행 작업을 기다림(선행 필수)**: `requiredWork` = 상대가 먼저 구현해야 할 구체 작업, `verificationSignal` = 이 run 이 진행 전 관측해야 할 신호(PR 머지 / 엔드포인트 live / 버전 publish), `linkedWork` = 신호 충족 전 막히는 이 계획의 stage·step, `howToStart` = 상대 repo 에서 `okstra-brief`(**이 보고서의 절대경로를 Source Material 로 인용** — 유일하게 허용된 cross-`<PROJECT_ROOT>` read) → `okstra-run`.
97
+ - `direction: upstream-precondition` — 이 run 이 상대의 **선행 작업을 기다림(선행 필수)**: `requiredWork` = 상대가 먼저 구현해야 할 구체 작업, `verificationSignal` = 이 run 이 진행 전 관측해야 할 신호(PR 머지 / 엔드포인트 live / 버전 publish), `linkedWork` = 신호 충족 전 막히는 이 계획의 stage·step, `howToStart` = 상대 repo 에서 `okstra-brief-gen`(**이 보고서의 절대경로를 Source Material 로 인용** — 유일하게 허용된 cross-`<PROJECT_ROOT>` read) → `okstra-run`.
96
98
  - `direction: downstream-carry` — 이 run 이 상대가 쓸 것을 **만들어 줌(기존 carry)**: `requiredWork` = 상대가 후속 구현할 self-contained B-portion(상대 관점의 신규 `R-NNN`·제안 stage·영향 파일), `verificationSignal` = 상대가 진행 전 확인할(이 run 이 인도한) 신호, `linkedWork` = 그 신호를 인도하는 이 계획의 stage·step, `howToStart` 는 upstream 과 동일. 이 run 의 이미 `done` 인 stage 를 상대 stage 인 양 넘기지 않는다 — 상대가 아직 만들어야 할 portion 만 담는다.
97
99
  - **cross-repo 의존은 `depends-on` 으로 표현 불가:** 그 게이트는 한 repo git graph 내부 커밋만 해소하므로(`scripts/okstra_ctl/run.py` `_resolve_stage_base_commit`) 다른 repo 의 커밋을 가리킬 수 없다. cross-repo 작업은 stage 가 아니라 별도 okstra run + XP 행으로 분리한다(Different-repos 규칙). 상대 run 은 구조적으로 독립이라 이 run 의 완료 stage 를 `done` 으로 자동 인식하지 않으며(인식해서도 안 됨 — 이 repo 의 작업), XP 행은 상대 planning 을 seed 하는 narrative 입력일 뿐이다. 이 run 은 상대 repo 트리·그 `.okstra/` 에 쓰지 않는다(이 보고서의 XP 행만 emit). 옛 "Recognition caveat" 문구는 렌더 노트(i18n `crossProjectRecognitionNote`)로 이전돼 `### Cross-Project Dependencies` 섹션에 자동 출력된다.
98
100
  - **Stage exit contract is the carry surface:** keep it as narrow as possible. Wider surface = more downstream coupling.
@@ -106,7 +108,7 @@
106
108
  - the YAML frontmatter MUST include the line `approved: false` (report-writer always emits the unflipped value). The user authorises the next `implementation` run by flipping it to `approved: true` (manual edit or `--approve` CLI). Do NOT recreate any `User Approval Request` body block — the validator fails reports that contain one (see `validators/validate-run.py` deprecated patterns).
107
109
  - the YAML frontmatter MUST include the line `implementation-option:` directly under `approved:` (report-writer always emits it with an **empty value**). The user selects which Option Candidate the next `implementation` run executes by filling this line with that option's name (manual edit or `--implementation-option <name>` CLI). When left empty, the `implementation` run falls back to the `Recommended Option`.
108
110
  - **the frontmatter `approved: false` line is rendered unconditionally; if the plan-body verification gate (§5.5.9) returns `blocked-by-disagreement` or `aborted-non-result`, the writer MUST keep `approved: false` and the validator refuses any report that ships with `approved: true` under such a gate result.**
109
- - every ambiguity flagged during pre-planning that the user must resolve before approval registered as a `Blocks=approval` row in the `## 1. Clarification Items` table (do NOT create a separate `Open Questions` block under the implementation plan body — the unified table is the single home)
111
+ - every ambiguity flagged during pre-planning that the user must resolve before approval registered as a `Blocks=approval` row in the `## 1. Clarification Items` table (the unified table is the single home for these — the "no separate `Open Questions` block" rule is in the shared `_common-contract.md` clarification policy)
110
112
  - **§5.5.9 Plan Body Verification (BLOCKING).** After report-writer finishes the draft, the lead MUST run a worker peer-review round on the consolidated plan body (Option Candidates / Trade-off Matrix / Recommended Option / Stage Map and per-stage sections / Dependency / Validation Checklist / Rollback / Requirement Coverage) and populate `### 5.5.9 Plan Body Verification` in the final report. The round protocol, plan-item ID scheme (`P-Opt-*` / `P-Step-*` / `P-Dep-*` / `P-Val-*` / `P-Rb-*`), verdict semantics, gate-result classification, and dissent log format are defined in `prompts/lead/plan-body-verification.md`. The four gate-result values are `passed`, `passed-with-dissent`, `blocked-by-disagreement`, `aborted-non-result`. When the gate would have been `blocked-by-disagreement` or `aborted-non-result`, the lead MUST NOT silently flip it to one of the passing values to "unblock" the run — that is a contract violation. **Enforced:** `validators/validate-run.py` `_validate_plan_body_gate_recompute` re-derives the gate from `planItems[].verdicts` and fails when the declared `gateResult` claims a healthier outcome than the recorded votes support; `_validate_plan_item_extraction_completeness` fails when any plan-body deliverable category is under-extracted into `planItems`, so a dropped item can no longer dodge the gate. When `convergence.adversarial=true` (the default for this phase), this round uses the adversarial posture — verifiers confirm cited paths/commands and the burden of proof is on the plan — but the gate threshold stays `majority-disagree` (see that skill's §"Adversarial plan-body posture").
111
113
  - **Decision-record evaluation (sole owner)**: this phase is the **single owner** of decision-record evaluation in the okstra lifecycle. The brief never evaluates or drafts decision records — it only forwards `adr-candidate:*` signals. Every `adr-candidate:*` entry inherited from the brief's `Open Questions` is a mandatory evaluation target. In addition, evaluate every decision the recommended option introduces against the three criteria:
112
114
  1. **Hard to reverse** — would changing the decision later cost meaningfully more than deciding now?
@@ -127,7 +129,7 @@
127
129
  4. **Ambiguity check** — any requirement that could be read two ways must be made explicit or moved to the `## 1. Clarification Items` table as a `Blocks=approval` row.
128
130
  5. **Scope check** — if the recommended plan now spans multiple independent subsystems, recommend splitting into separate planning runs rather than shipping an oversized plan.
129
131
  6. **Review-rule preflight check** — if a project review rule pack exists, map each relevant rule to the recommended option. Reject the draft if it knowingly creates a violation that the later PR reviewer would flag, unless the plan records a specific rationale and follow-up. In particular, scan for repeated helper stacks across planned files, tests that assert delegation to the same calculator/helper they exercise, public names that hide side effects, domain rules placed in repositories/adapters, and APIs made dead by this change.
130
- 7. **Plan-body verification reconciliation (BLOCKING for implementation-planning).** For every §5.5.9 `planItems[]` entry whose verdicts make it `majority-disagree`, set that item's `clarificationId` to a `C-<N>` row that MUST exist in `## 1. Clarification Items` with `Kind` chosen per the standard policy and `Blocks=approval`. Do NOT create a parallel `Open Questions` block under the implementation plan body — the unified table is the single home. **Enforced:** `validators/validate-run.py` `_validate_plan_body_clarification_matching` recomputes each item's class and fails when a majority-disagree item has no `clarificationId`, or its `clarificationId` is dangling / points at a non-`approval` row. For `partial-consensus` and `dissent-isolated` plan-items, the dissenting opinion lives in §5.5.9 `Dissent log` and is NOT promoted to §5.
132
+ 7. **Plan-body verification reconciliation (BLOCKING for implementation-planning).** For every §5.5.9 `planItems[]` entry whose verdicts make it `majority-disagree`, set that item's `clarificationId` to a `C-<N>` row that MUST exist in `## 1. Clarification Items` with `Kind` chosen per the standard policy and `Blocks=approval`. **Enforced:** `validators/validate-run.py` `_validate_plan_body_clarification_matching` recomputes each item's class and fails when a majority-disagree item has no `clarificationId`, or its `clarificationId` is dangling / points at a non-`approval` row. For `partial-consensus` and `dissent-isolated` plan-items, the dissenting opinion lives in §5.5.9 `Dissent log` and is NOT promoted to §5.
131
133
  8. **Stage Map self-check** — for every stage, count the effective rows of its `Stepwise Execution Order` table by hand; reject the draft if any stage exceeds 8. Confirm each stage declares a non-empty `Slice value:` and `Acceptance:` line, the three `Test case (success|boundary|failure):` lines (or carries a `TDD exemption:` line), and that its first step `action` starts with `RED:` with a later `GREEN:` — this is what validator S10 enforces, including S10d on the test-case lines. Read each stage's three test-case lines as a reviewer: reject any that restates the happy path in all three slots, leaves `boundary` blank, or writes `N/A` where a real edge input exists. Walk the `depends-on` graph and confirm it is a DAG (no cycle, no self-reference). For each `depends-on` link, confirm it encodes a real data/contract dependency — do NOT add links to serialise unrelated work, and do NOT split a stage merely to create more parallel stages. **Parallel-safety:** for every pair of `depends-on (none)` stages, confirm their `Stage Exit Contract` predicted file sets are disjoint; if they share a file, merge them or add a `depends-on` link (validator S9 rejects overlap). **Project-boundary:** confirm no stage mixes edits from two projects (different repo/`PROJECT_ROOT` or different top-level deployable module); if any stage does, split it per project. For multi-project plans, confirm each stage's `title` carries its `[<project>]` tag and the `Cross-project parallelism:` line under the table records the parallel-vs-sequenced determination (with the forcing dependency) for every project pair; for cross-repo work, confirm it is split into separate per-repo runs (required — one run structurally cannot touch another repo) rather than crammed into one task's stages.
132
134
  9. **Cross-project dependency check** — 타 repo / 다른 top-level 배포 모듈 / published 패키지에 대한 의존을 빠뜨리지 않았는지 확인한다. `dependencyMigrationRisk` 에 `kind: cross-project` 행이 있으면 매칭되는 `direction: upstream-precondition` `XP-NNN` 행이 `crossProjectDependencies` 에 있고, 그 `requiredWork` 가 추상 표현("상대 작업 완료")이 아니라 상대가 실제로 만들어야 할 구체 작업인지 reviewer 로서 다시 읽는다(validator S 가 존재만 보므로 구체성은 self-review 가 책임짐). cross-repo 작업을 한 task 의 stage 로 욱여넣지 않고 별도 run + XP 행으로 분리했는지, cross-project substance 가 `§3 Recommended Next Steps` 에 중복되지 않고 `§5.4 Cross-Project Dependencies` 에만 있는지 확인한다.
133
135
  10. **Decision-draft materialization check** — `decisionDrafts` 가 비어있지 않으면, 매칭 materialization step(`.okstra/decisions/<NNNN>-<slug>.md` 생성)이 어느 stage 의 stepwise 에 존재하는지, draft 개수와 materialization step 이 1:1 로 대응하는지 reviewer 로서 확인한다. validator 는 step 의 *존재*만 보므로 `<NNNN>-<slug>` 정확성·개수 대응은 self-review 가 책임진다.
@@ -33,6 +33,7 @@
33
33
  - For each open question Lead asks ONE `AskUserQuestion` with a `(Recommended)` answer drawn from a codebase-first inspection. Budget: at most 12 questions in this phase.
34
34
  - Stop conditions (OR): all questions resolved / budget exhausted / user signals proceed.
35
35
  - Lead persists the round at `<RUN_DIR>/state/phase-1.5-grilling.md` with one section per question (question / recommended / user answer) and a closing `Resolved scope` / `Resolved lenses` block. Worker prompts use this resolved block as the authoritative scope and lens definition.
36
+ - After writing the log and before Phase 4 dispatch, the lead injects its **absolute path** into every analyser prompt as the `**Phase 1.5 Grilling Log:** <absolute-path>` anchor header (see `templates/worker-prompt-preamble.md` §"Anchor headers"). This is the improvement-discovery counterpart to the `**Worktree:**` / `**Verification …:**` anchors that implementation / final-verification inject: workers read the log from this explicit path rather than re-deriving `<RUN_DIR>`. The path is byte-identical across all analysers, so it does not break the dispatch-prompt invariant.
36
37
  - Decision-tree walk (bounded):
37
38
  - When candidates branch on a structural question (e.g. "is module X meant to own this responsibility?"), resolve via `Read` / `Grep` first. Only escalate to the user inside the Phase 1.5 budget.
38
39
  - Expected output emphasis:
@@ -17,6 +17,7 @@
17
17
  - Primary focus areas:
18
18
  - classify the work as bugfix, feature, improvement, refactor, or ops
19
19
  - determine whether `error-analysis` or `implementation-planning` is the next safe step. Direct `implementation` handoff is never a valid routing target — implementation requires an approved `implementation-planning` report
20
+ - capture the reporter's **rejection criteria** — the delivered outcome that would make this work wrong or unacceptable — as a routing input. Consume it from the brief's `Desired Outcome` / `Out of Scope` / `Source Material` when present; when it is absent AND it would change the classification (e.g. bugfix vs feature) or the next-phase choice, raise it as one `decision` clarification row with `Evidence checked: none — reporter intent`. Never infer it — this is a reporter-intent signal, the mirror of improvement-discovery's `Anti-goals`
20
21
  - identify missing materials that block reliable routing
21
22
  - define task continuity expectations for long-running work under the same task key
22
23
  - capture approval or confirmation points before the next phase starts
@@ -48,7 +49,7 @@
48
49
  - evidence-backed routing decision
49
50
  - uncertainty boundaries and missing inputs
50
51
  - next recommended phase and safe resume guidance
51
- - canonical-term resolution for every `terminology:*` brief item, written as a one-line `<term> = <definition>` line in a new `Domain Alignment` subsection of the final report; alongside each, propose whether `<PROJECT_ROOT>/.okstra/glossary.md` should be updated (proposal only — actual writes happen via `okstra-brief` Step 4.5 on a subsequent run)
52
+ - canonical-term resolution for every `terminology:*` brief item, written as a one-line `<term> = <definition>` line in a new `Domain Alignment` subsection of the final report; alongside each, propose whether `<PROJECT_ROOT>/.okstra/glossary.md` should be updated (proposal only — actual writes happen via `okstra-brief-gen` Step 4.5 on a subsequent run)
52
53
  - Clarification request policy (phase-specific addenda — shared policy is in `_common-contract.md`):
53
54
  - if any blocking input is missing at the time of writing the final report, populate `## 1. Clarification Items` in `final-report-template.md` (a single unified table; `Blocks=next-phase` for items the next run cannot start without)
54
55
  - prefer concrete questions whose answers map directly to a routing decision (`bugfix` vs `feature`, `error-analysis` vs `implementation-planning`, etc.). State each option in plain language with one sentence describing what choosing it would mean for the next phase.
@@ -61,6 +62,6 @@
61
62
  - Non-goals:
62
63
  - full implementation design unless it is required to decide the next phase
63
64
  - **source code edits, plan authoring, builds, or deployments** — this run only classifies the work and routes it; deeper analysis and planning belong to subsequent phases
64
- - **writes outside `<PROJECT_ROOT>/.okstra/`** — this phase only uses okstra's artifact root. Glossary additions land in `<PROJECT_ROOT>/.okstra/glossary.md` (via `okstra-brief` Step 4.5); decision drafts land in `<PROJECT_ROOT>/.okstra/decisions/` (via `implementation-planning`).
65
+ - **writes outside `<PROJECT_ROOT>/.okstra/`** — this phase only uses okstra's artifact root. Glossary additions land in `<PROJECT_ROOT>/.okstra/glossary.md` (via `okstra-brief-gen` Step 4.5); decision drafts land in `<PROJECT_ROOT>/.okstra/decisions/` (via `implementation-planning`).
65
66
  - 작업 단위 분해(fan-out)는 이 phase 의 in-scope 다 — 단, 각 단위의 *해법 설계*·소스
66
67
  편집·plan 작성은 여전히 non-goal 이며 다운스트림 phase 가 담당한다
@@ -3,7 +3,7 @@
3
3
  완료(release-handoff)된 task 에 재진입하는 버그 핫픽스 run 묶음(fix cycle)의
4
4
  SSOT. consumers.jsonl 과 같은 idiom — append-only + dir flock + last-wins 읽기.
5
5
  이 모듈이 유일한 reader/writer 이며, 소비처(analysis-packet / manifest /
6
- final-report / okstra-brief)는 모두 summarize()/packet_summary() 파생 뷰를 쓴다.
6
+ final-report / okstra-brief-gen)는 모두 summarize()/packet_summary() 파생 뷰를 쓴다.
7
7
 
8
8
  행 3종 (event 필드로 구분):
9
9
  {"event":"opened","cycle":"fc-01","target_report":...,"symptom":...,"opened_at":...}
@@ -209,7 +209,7 @@ def _brief_suggestions(path: Path) -> tuple[str, str]:
209
209
 
210
210
  - ``task_group`` ← frontmatter ``task-group``.
211
211
  - ``task_id`` ← frontmatter ``brief-id`` (which matches the
212
- filename stem in okstra-brief output and is the
212
+ filename stem in okstra-brief-gen output and is the
213
213
  strongest single identifier of the task).
214
214
 
215
215
  A brief without frontmatter, or with placeholder values, yields two
@@ -1261,9 +1261,9 @@ def _recently_used_brief_times(state: WizardState) -> dict[str, float]:
1261
1261
 
1262
1262
 
1263
1263
  def _suggest_group_briefs(state: WizardState, limit: int = 6) -> list[str]:
1264
- """Return recent okstra-brief outputs for the selected task-group.
1264
+ """Return recent okstra-brief-gen outputs for the selected task-group.
1265
1265
 
1266
- ``okstra-brief`` writes to ``.okstra/briefs/<task-group>/**/*.md``. The
1266
+ ``okstra-brief-gen`` writes to ``.okstra/briefs/<task-group>/**/*.md``. The
1267
1267
  wizard exposes those paths after task-group selection so users can pick a
1268
1268
  generated brief instead of typing its path. Paths are project-relative.
1269
1269
  """
@@ -696,7 +696,7 @@
696
696
  "properties": {
697
697
  "target": { "type": "string" },
698
698
  "performed": { "type": "string" },
699
- "result": { "type": "string" },
699
+ "result": { "enum": ["pass", "fail", "blocked"] },
700
700
  "observed": { "type": "string" }
701
701
  }
702
702
  }
@@ -1691,16 +1691,18 @@
1691
1691
  "number": { "type": "integer", "minimum": 1 },
1692
1692
  "tier": { "enum": [1, 2] },
1693
1693
  "command": { "type": "string", "minLength": 1 },
1694
- "status": { "enum": ["executed", "rejected", "not-configured"] },
1694
+ "status": { "enum": ["executed", "rejected", "not-configured", "env-unavailable"] },
1695
1695
  "exitCode": { "type": ["integer", "null"] },
1696
- "rejectionReason": { "type": ["string", "null"] },
1696
+ "statusReason": { "type": ["string", "null"] },
1697
1697
  "outputTail": { "type": "string" }
1698
1698
  },
1699
1699
  "allOf": [
1700
1700
  { "if": { "properties": { "status": { "const": "executed" } } },
1701
1701
  "then": { "properties": { "exitCode": { "type": "integer" } } } },
1702
1702
  { "if": { "properties": { "status": { "const": "rejected" } } },
1703
- "then": { "required": ["rejectionReason"] } }
1703
+ "then": { "required": ["statusReason"] } },
1704
+ { "if": { "properties": { "status": { "const": "env-unavailable" } } },
1705
+ "then": { "required": ["statusReason"] } }
1704
1706
  ]
1705
1707
  },
1706
1708
 
@@ -1,9 +1,9 @@
1
1
  ---
2
- name: okstra-brief
2
+ name: okstra-brief-gen
3
3
  description: Use when the user wants to generate a task brief file for okstra from a requirements document, an existing markdown file, an issue-tracker ticket (Linear / Jira / GitHub / Notion), a link URL, conversation context, or short user input. Produces the markdown brief consumed by `okstra-run` Step 5 (task-brief). Trigger words include "okstra brief", "make a brief", "brief 생성", "요구사항 brief 만들어", "okstra 입력 만들어", "task brief 작성", "이 티켓으로 brief", "이 링크로 brief".
4
4
  ---
5
5
 
6
- # okstra-brief
6
+ # okstra-brief-gen
7
7
 
8
8
  Generate a single `task brief` markdown file under the okstra project domain
9
9
  (`.okstra/briefs/<task-group>/<task-id>.md`) so it can be fed to
@@ -41,21 +41,21 @@ cross-verification and would conflict with anything decided here.
41
41
  ## Intended chain
42
42
 
43
43
  ```
44
- okstra-brief (reporter-input variant)
44
+ okstra-brief-gen (reporter-input variant)
45
45
  → okstra-run (requirements-discovery | error-analysis)
46
46
  → okstra-run (implementation-planning)
47
47
  → okstra-run (implementation)
48
48
  → okstra-run (final-verification)
49
49
  → okstra-run (release-handoff)
50
50
 
51
- okstra-brief (codebase-scan variant)
51
+ okstra-brief-gen (codebase-scan variant)
52
52
  → okstra-run (improvement-discovery)
53
53
  → okstra-run (implementation-planning)
54
54
  → okstra-run (implementation)
55
55
  → okstra-run (final-verification)
56
56
  → okstra-run (release-handoff)
57
57
 
58
- okstra-brief (error-feedback variant)
58
+ okstra-brief-gen (error-feedback variant)
59
59
  → okstra-run (error-analysis)
60
60
  → okstra-run (implementation-planning)
61
61
  → okstra-run (implementation)
@@ -737,7 +737,7 @@ The installed template `~/.okstra/templates/reports/brief.template.md` is the by
737
737
  notion | url | user-input`).
738
738
  - `task-group` echoes the Step 2a value.
739
739
  - `created` is the brief's creation date (`YYYY-MM-DD`).
740
- - `generator: okstra-brief` is a fixed value.
740
+ - `generator: okstra-brief-gen` is a fixed value.
741
741
  - `reporter-confirmations` is set by Step 6.5 (`complete | partial | pending |
742
742
  skipped`).
743
743
  - `scope` is `codebase` for the codebase-scan variant; omit it (⇒
@@ -18,7 +18,7 @@ rows, sort by priority and ask only the top 12 this round:
18
18
 
19
19
  Any rows beyond the cap are left unanswered in this run; set
20
20
  `reporter-confirmations: partial` in the frontmatter and tell the user which
21
- rows remain. The next `okstra-brief` re-run (or the downstream phase that
21
+ rows remain. The next `okstra-brief-gen` re-run (or the downstream phase that
22
22
  consumes `Blocks=next-phase`) handles the remainder.
23
23
 
24
24
  Each question carries:
@@ -1,7 +1,7 @@
1
1
  # Sub-ticket / child-issue recursion (tracker sources)
2
2
 
3
3
  Read this only when a fetched tracker ticket shows one or more child references
4
- (okstra-brief Step 1b sub-step 6). It defines how the child tree is discovered,
4
+ (okstra-brief-gen Step 1b sub-step 6). It defines how the child tree is discovered,
5
5
  which briefs are emitted, and how re-runs stay idempotent.
6
6
 
7
7
  ## 1. Discover child references per tracker
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: okstra-inspect
3
3
  description: >-
4
- Use this for everything that happens AFTER a single okstra task has already run — inspecting it or light bookkeeping on it, never launching new work. The tell is usually a named task id (PROD-1623, dev-9184), often dropped without the word "okstra." Reach for it when the user wants one task's: status, current/next phase, blockers, or approval gate; its final report — where it is or whether it passed (결론·통과); its elapsed time (소요 시간) or context/read cost (컨텍스트 비용); its run history, re-run, or resume; to mark it done / in-progress / blocked / todo; or a failed run's error logs gathered into a report (에러 리포트). Also bundles cross-project okstra errors into an anonymized feedback zip (에러 환류). Use it even for a bare "mark it done" or "where's the report." NOT for starting a run (okstra-run), rollups/schedules (okstra-rollup / okstra-schedule), a brief (okstra-brief), setup (okstra-setup), or cross-project management (okstra-manager).
4
+ Use this for everything that happens AFTER a single okstra task has already run — inspecting it or light bookkeeping on it, never launching new work. The tell is usually a named task id (PROD-1623, dev-9184), often dropped without the word "okstra." Reach for it when the user wants one task's: status, current/next phase, blockers, or approval gate; its final report — where it is or whether it passed (결론·통과); its elapsed time (소요 시간) or context/read cost (컨텍스트 비용); its run history, re-run, or resume; to mark it done / in-progress / blocked / todo; or a failed run's error logs gathered into a report (에러 리포트). Also bundles cross-project okstra errors into an anonymized feedback zip (에러 환류). Use it even for a bare "mark it done" or "where's the report." NOT for starting a run (okstra-run), rollups/schedules (okstra-rollup / okstra-schedule), a brief (okstra-brief-gen), setup (okstra-setup), or cross-project management (okstra-manager).
5
5
  ---
6
6
 
7
7
  # OKSTRA Inspect
@@ -682,7 +682,7 @@ stdout JSON 을 파싱해 보고:
682
682
  | 프로젝트 수 | `projectCount` |
683
683
 
684
684
  - `unreachableRuns > 0` 이면 표면화한다(침묵 누락 금지).
685
- - 끝에 다음 단계를 안내한다: "이 zip 으로 okstra 자신을 고치려면 `/okstra-brief` 의 error-feedback variant 로 brief 를 만든 뒤 `okstra-run --task-type error-analysis` 를 okstra 레포에서 실행하세요."
685
+ - 끝에 다음 단계를 안내한다: "이 zip 으로 okstra 자신을 고치려면 `/okstra-brief-gen` 의 error-feedback variant 로 brief 를 만든 뒤 `okstra-run --task-type error-analysis` 를 okstra 레포에서 실행하세요."
686
686
 
687
687
  ---
688
688
 
@@ -7,7 +7,7 @@ source-type: <file | linear | jira | github | notion | url | user-input>
7
7
  task-group: <task-group>
8
8
  depth: 0 # 0=parent/single, 1=child, 2=grandchild, ...
9
9
  created: <YYYY-MM-DD>
10
- generator: okstra-brief
10
+ generator: okstra-brief-gen
11
11
  reporter-confirmations: <complete | partial | pending | skipped> # set by Step 6.5
12
12
  # codebase-scan variant frontmatter (omit for reporter-input briefs):
13
13
  scope: <reporter-input | codebase> # 'codebase' for codebase-scan variant; omit for reporter-input variant
@@ -19,7 +19,7 @@ candidate-cap: 8 # codebase-scan only: 1..12, de
19
19
 
20
20
  # Task Brief: <task_group>/<filename-without-ext>
21
21
 
22
- > Generated: okstra-brief · <YYYY-MM-DD>
22
+ > Generated: okstra-brief-gen · <YYYY-MM-DD>
23
23
  > Source type: <file | linear | jira | github | notion | url | user-input>
24
24
  > Tracker key (if any): <LIN-1234 | PROJ-42 | gh-repo-123 | notion-abcdef12>
25
25
  > Parent brief (child briefs only): <relative path>
@@ -609,7 +609,7 @@ implementation-option: {{ frontmatter.implementationOption | yaml_scalar }}
609
609
  | # | Tier | Command (verbatim) | Status | Exit code | Output tail |
610
610
  |---|------|---------------------|--------|-----------|-------------|
611
611
  {% for row in finalVerification.readonlyCommandLog -%}
612
- | {{ row.number | mdcell }} | {{ row.tier | mdcell }} | `{{ row.command | mdcell }}` | `{{ row.status | mdcell }}` | {{ (row.exitCode if row.exitCode is not none else '—') | mdcell }} | {{ (row.rejectionReason if row.status == 'rejected' else row.outputTail) | mdcell }} |
612
+ | {{ row.number | mdcell }} | {{ row.tier | mdcell }} | `{{ row.command | mdcell }}` | `{{ row.status | mdcell }}` | {{ (row.exitCode if row.exitCode is not none else '—') | mdcell }} | {{ (row.statusReason if row.status in ['rejected', 'env-unavailable'] else row.outputTail) | mdcell }} |
613
613
  {% endfor %}
614
614
 
615
615
  ### 5.8.6 Conditional Acceptance Conditions
@@ -640,6 +640,29 @@ implementation-option: {{ frontmatter.implementationOption | yaml_scalar }}
640
640
 
641
641
  {{ finalVerification.routingRecommendation }}
642
642
 
643
+ ### 5.8.9 Could-Not-Verify Roll-up
644
+
645
+ Single scan of every agreed check that this run did NOT confirm — requirement gaps, commands not run (rejected / not-configured / env-unavailable), and blocked manual tests — aggregated from the sections above.
646
+
647
+ {% set nv = namespace(any=false) -%}
648
+ {% for row in finalVerification.validationEvidence if row.status == 'gap' -%}
649
+ {% set nv.any = true -%}
650
+ - `{{ row.id | mdcell }}` requirement gap — {{ row.requirement | mdcell }}
651
+ {% endfor -%}
652
+ {% for row in finalVerification.readonlyCommandLog if row.status in ['rejected', 'not-configured', 'env-unavailable'] -%}
653
+ {% set nv.any = true -%}
654
+ - `{{ row.command | mdcell }}` — {{ row.status | mdcell }}: {{ row.statusReason | mdcell }}
655
+ {% endfor -%}
656
+ {% if finalVerification.manualUserTest.applicable -%}
657
+ {% for row in finalVerification.manualUserTest.results if row.result == 'blocked' -%}
658
+ {% set nv.any = true -%}
659
+ - manual: {{ row.target | mdcell }} — {{ row.performed | mdcell }} (blocked): {{ row.observed | mdcell }}
660
+ {% endfor -%}
661
+ {% endif -%}
662
+ {% if not nv.any -%}
663
+ - All agreed checks were executed or covered — nothing left unverified.
664
+ {%- endif %}
665
+
643
666
  {% endif %}
644
667
  {% if header.taskType == 'improvement-discovery' %}
645
668
  ## 5.9 Improvement Candidates
@@ -51,8 +51,9 @@ taskType: "{{FM_TASK_TYPE}}"
51
51
  ## Phase 1.5 — Lead Reflect-Back Grilling
52
52
 
53
53
  This section is filled in by the lead during Phase 1.5 before worker dispatch.
54
- Workers MUST read the resolved values from `runs/improvement-discovery/<seq>/state/phase-1.5-grilling.md`
55
- rather than the unresolved brief.
54
+ Workers MUST read the resolved values from the log the lead points to via the
55
+ `**Phase 1.5 Grilling Log:** <abs-path>` dispatch-prompt anchor
56
+ (`runs/improvement-discovery/<seq>/state/phase-1.5-grilling.md`) rather than the unresolved brief.
56
57
 
57
58
  - Reflect-back summary:
58
59
  - Open questions (Q1..QN):
@@ -103,6 +103,10 @@ For the **final-verification phase** specifically, the dispatched prompt MUST al
103
103
  - `**Verification base ref:** <base-ref>` — the implementation base for the diff.
104
104
  - `**Verification diff stat:** <git diff --stat output>` — the captured diff-stat that bounds the verification scope.
105
105
 
106
+ For the **improvement-discovery phase** specifically, the dispatched prompt MUST also include the resolved-scope log the lead wrote during Phase 1.5, so workers key off an explicit absolute path instead of re-deriving the run directory:
107
+
108
+ - `**Phase 1.5 Grilling Log:** <absolute-path>` — the lead's Phase 1.5 reflect-back log (`<RUN_DIR>/state/phase-1.5-grilling.md`, written before dispatch). Its `Resolved scope` / `Resolved lenses` blocks are the authoritative scope and lens definition for this run. Read the file at this absolute path; do NOT re-derive it from `<RUN_DIR>`, and do NOT re-interpret the brief's raw `scan-scope` / `priority-lenses`. The presence of this anchor is itself the signal that this is an improvement-discovery run — no separate task-type detection is required.
109
+
106
110
  When a worker reads any project-relative path from the prompt, it MUST resolve it against `Project Root` (e.g. `<Project Root>/<Result Path>`) — never use bare relative paths that depend on cwd.
107
111
 
108
112
  ---
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env python3
2
- """Validate brief markdown files produced by the okstra-brief skill.
2
+ """Validate brief markdown files produced by the okstra-brief-gen skill.
3
3
 
4
4
  Checks performed per brief file:
5
5
 
@@ -34,7 +34,7 @@ Checks performed per brief file:
34
34
  non-empty and Priority Lenses lists 1–4 values from the lens whitelist
35
35
  (`scripts/okstra_ctl/improvement_lenses.py` SSOT).
36
36
  12. When present, `Related Task Graph` is a markdown table with the canonical
37
- columns and relation/direction values from the okstra-brief contract.
37
+ columns and relation/direction values from the okstra-brief-gen contract.
38
38
  13. The requirement/objective section `## Desired Outcome` (required in every
39
39
  brief variant) exists and its body is not blank. `_(none)_` stays valid.
40
40
 
@@ -406,7 +406,7 @@ def check_requirement_section(text: str, errors: list[str]) -> None:
406
406
  """The requirement/objective section must exist and carry a non-blank body.
407
407
 
408
408
  `## Desired Outcome` is the "shape of success" required by every brief
409
- variant (okstra-brief SKILL.md Step 5 §"Required sections by variant").
409
+ variant (okstra-brief-gen SKILL.md Step 5 §"Required sections by variant").
410
410
  Without this check a brief that drops the heading — or wipes its body —
411
411
  still passes, letting implementation-planning report 100% Requirement
412
412
  Coverage against an empty objective. `_(none)_` stays valid: it is the
@@ -464,9 +464,9 @@ def validate_brief(path: Path, briefs_root: Path) -> list[str]:
464
464
  if fm.get("type") != "brief":
465
465
  errors.append(f"frontmatter type must be 'brief', got {fm.get('type')!r}")
466
466
 
467
- if fm.get("generator") != "okstra-brief":
467
+ if fm.get("generator") != "okstra-brief-gen":
468
468
  errors.append(
469
- f"frontmatter generator must be 'okstra-brief', got {fm.get('generator')!r}"
469
+ f"frontmatter generator must be 'okstra-brief-gen', got {fm.get('generator')!r}"
470
470
  )
471
471
 
472
472
  if fm.get("reporter-confirmations") not in REPORTER_CONFIRMATION_VALUES:
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bash
2
2
  #
3
- # Validate brief markdown files produced by okstra-brief.
3
+ # Validate brief markdown files produced by okstra-brief-gen.
4
4
  #
5
5
  # Usage:
6
6
  # validators/validate-brief.sh <briefs-dir> [--briefs-root <dir>]
@@ -1220,6 +1220,7 @@ FINAL_VERIFICATION_REQUIRED_SECTIONS = (
1220
1220
  "Conditional Acceptance Conditions",
1221
1221
  "Manual User Test Results",
1222
1222
  "Routing Recommendation",
1223
+ "Could-Not-Verify Roll-up",
1223
1224
  )
1224
1225
 
1225
1226
  # Allowed Verdict Token vocabulary, by task-type. `release-handoff` is
@@ -10,13 +10,14 @@ import {
10
10
  const FALLBACK_SKILL_NAMES = [
11
11
  "okstra",
12
12
  "okstra-setup",
13
- "okstra-brief",
13
+ "okstra-brief-gen",
14
14
  "okstra-run",
15
15
  "okstra-memory",
16
16
  "okstra-inspect",
17
17
  "okstra-schedule",
18
18
  "okstra-container-build",
19
19
  "okstra-container",
20
+ "okstra-brief",
20
21
  "okstra-context-loader",
21
22
  "okstra-team-contract",
22
23
  "okstra-convergence",
@@ -6,7 +6,7 @@
6
6
 
7
7
  export const USER_SKILL_NAMES = Object.freeze([
8
8
  "okstra-setup",
9
- "okstra-brief",
9
+ "okstra-brief-gen",
10
10
  "okstra-run",
11
11
  "okstra-manager",
12
12
  "okstra-memory",
@@ -29,6 +29,7 @@ export const OBSOLETE_SKILL_NAMES = Object.freeze([
29
29
  "okstra-report-writer",
30
30
  "okstra-coding-preflight",
31
31
  "okstra-container",
32
+ "okstra-brief",
32
33
  ]);
33
34
 
34
35
  export function userSkillNames() {