okstra 0.109.0 → 0.111.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 (32) hide show
  1. package/README.kr.md +2 -1
  2. package/README.md +2 -1
  3. package/docs/for-ai/skills/okstra-run.md +7 -5
  4. package/docs/kr/architecture.md +11 -12
  5. package/docs/kr/cli.md +4 -4
  6. package/docs/project-structure-overview.md +12 -12
  7. package/docs/task-process/README.md +4 -4
  8. package/docs/task-process/common-flow.md +8 -5
  9. package/docs/task-process/implementation.md +4 -5
  10. package/docs/task-process/release-handoff.md +3 -3
  11. package/package.json +1 -1
  12. package/runtime/BUILD.json +2 -2
  13. package/runtime/agents/workers/antigravity-worker.md +1 -0
  14. package/runtime/agents/workers/codex-worker.md +1 -0
  15. package/runtime/prompts/lead/convergence.md +7 -7
  16. package/runtime/prompts/profiles/_common-contract.md +1 -1
  17. package/runtime/prompts/profiles/_implementation-diff-review.md +43 -0
  18. package/runtime/prompts/profiles/_implementation-executor.md +7 -9
  19. package/runtime/prompts/profiles/_implementation-self-check.md +11 -5
  20. package/runtime/python/okstra_ctl/codex_dispatch.py +3 -0
  21. package/runtime/python/okstra_ctl/consumers.py +4 -0
  22. package/runtime/python/okstra_ctl/handoff.py +5 -23
  23. package/runtime/python/okstra_ctl/implementation_stage.py +11 -11
  24. package/runtime/python/okstra_ctl/report_views.py +76 -26
  25. package/runtime/python/okstra_ctl/stage_targets.py +152 -0
  26. package/runtime/python/okstra_ctl/wizard.py +47 -0
  27. package/runtime/python/okstra_ctl/worktree.py +14 -13
  28. package/runtime/python/okstra_project/__init__.py +2 -0
  29. package/runtime/python/okstra_project/state.py +44 -2
  30. package/runtime/skills/okstra-run/SKILL.md +21 -17
  31. package/src/commands/execute/wizard.mjs +3 -1
  32. package/src/commands/inspect/task-show.mjs +11 -31
package/README.kr.md CHANGED
@@ -164,6 +164,7 @@ Claude Code 세션 안에서 사용하는 슬래시 커맨드:
164
164
  | `/okstra-rollup` | task-group(또는 프로젝트 전체)의 모든 task run 결과를 모아 task별 run수/소요시간/에러와 그룹 합계를 집계하고, report 들을 묶어 task 횡단 종합 요약 작성 |
165
165
  | `/okstra-schedule` | task-group 전체에 대한 작업 계획표 생성 |
166
166
  | `/okstra-container-build` | 검증 완료된 task 의 코드를 로컬 docker compose 그룹으로 배포하고 컨테이너별 로그를 감시 (sub-command: `up` / `status` / `logs` / `stop-watcher` / `down`) |
167
+ | `/okstra-graphify` | 프로젝트 자체 `.okstra/` 메모리(final report, `decisions/*.md`, `glossary.md`)를 지식그래프로 빌드·질의 (범위는 `.okstra/` 로 한정, 산출물은 `.okstra/graph/` 아래; sub-command: `build` / `query` / `path` / `explain` / `mcp` / `wiki`) |
167
168
  | `/okstra-manager` | 여러 프로젝트에 걸친 okstra task 를 manager-owned plan, assignment, 단방향 project sync snapshot, status, child launch context packet 으로 조정 |
168
169
  | `/okstra-setup` | 프로젝트별 부트스트랩 (§3.2) |
169
170
 
@@ -193,7 +194,7 @@ Claude Code 세션 밖에서 task 를 시작하려면:
193
194
 
194
195
  0.8.0 이후 `main` 에 추가된 workflow 변경:
195
196
 
196
- - **모든 task-type 격리 worktree 자동 provisioning** — prepare 단계에서 `okstra-ctl` 이 task-key 당 한 번 `git worktree add ~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>` 를 수행해 격리된 working tree 와 브랜치 `<work-category-prefix>-<task-id-segment>` (예: `feat-dev-9436`, `fix-dev-7311`) 를 만듭니다. base ref 는 사용자가 `--base-ref` 로 지정 (release-handoff PR base picker 와 동일한 메뉴: `main` / `dev` / `staging` / `preprod` / `prod` / 직접 입력). 첫 phase 에서는 필수이며, okstra-run skill 이 `AskUserQuestion` 으로 수집합니다 — 비대화형 호출자는 `--base-ref` 플래그를 직접 전달해야 prepare 가 통과합니다. 같은 task-key 의 후속 **비-`implementation`** phase(`requirements-discovery` → `error-analysis` → `implementation-planning` → `final-verification` → `release-handoff`)는 같은 path/branch를 재사용합니다. 반면 `implementation` run 은 **stage 격리** 로 동작합니다 — 각 run 이 자신의 `.../<task>/stage-<N>/` worktree(브랜치 `<prefix>-<task>-s<N>`)에서 한 stage 만 실행하므로, 독립(`depends-on (none)`) stage 를 별도 run 으로 **동시에 병렬 구현** 할 수 있습니다(트리 공유 없음). registry 는 task-key 와 **stage-key** 를 함께 flock 예약합니다. caller 가 이미 다른 worktree 안에 있거나 project_root 가 git repo 가 아니면 provisioning 은 skip 됩니다(stage 격리도 평면 경로로 degrade). 수동 cleanup: `git worktree remove <path>` → `git branch -D <branch>` + registry 항목 release/remove. 상세: [`docs/kr/architecture.md`](docs/kr/architecture.md) *Task type* 섹션, [`docs/kr/cli.md#--executor`](docs/kr/cli.md#--executor).
197
+ - **모든 task-type 격리 worktree 자동 provisioning** — prepare 단계에서 `okstra-ctl` 이 task-key 당 한 번 `git worktree add ~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>` 를 수행해 격리된 working tree 와 브랜치 `<work-category-namespace>/<task-id-segment>` (예: `feature/dev-9436`, `fix/dev-7311`) 를 만듭니다. base ref 는 사용자가 `--base-ref` 로 지정 (release-handoff PR base picker 와 동일한 메뉴: `main` / `dev` / `staging` / `preprod` / `prod` / 직접 입력). 첫 phase 에서는 필수이며, okstra-run skill 이 `AskUserQuestion` 으로 수집합니다 — 비대화형 호출자는 `--base-ref` 플래그를 직접 전달해야 prepare 가 통과합니다. 같은 task-key 의 후속 **비-`implementation`** phase(`requirements-discovery` → `error-analysis` → `implementation-planning` → `final-verification` → `release-handoff`)는 같은 path/branch를 재사용합니다. 반면 `implementation` run 은 **stage 격리** 로 동작합니다 — 각 run 이 자신의 `.../<task>/stage-<N>/` worktree(브랜치 `<work-category-namespace>/<task>-s<N>`)에서 한 stage 만 실행하므로, 독립(`depends-on (none)`) stage 를 별도 run 으로 **동시에 병렬 구현** 할 수 있습니다(트리 공유 없음). registry 는 task-key 와 **stage-key** 를 함께 flock 예약합니다. caller 가 이미 다른 worktree 안에 있거나 project_root 가 git repo 가 아니면 provisioning 은 skip 됩니다(stage 격리도 평면 경로로 degrade). 수동 cleanup: `git worktree remove <path>` → `git branch -D <branch>` + registry 항목 release/remove. 상세: [`docs/kr/architecture.md`](docs/kr/architecture.md) *Task type* 섹션, [`docs/kr/cli.md#--executor`](docs/kr/cli.md#--executor).
197
198
  - **`release-handoff` lifecycle phase** — `final-verification` 이 `verdict=accepted` 를 반환한 직후에 실행되는 신규 phase. lead 가 Claude worker (drafter) 를 통해 commit message · PR body 후보를 만들고, `AskUserQuestion` 으로 사용자에게 (1) action (`commit only` / `commit + PR` / `skip`), (2) PR base branch (`staging` / `preprod` / `prod` / `main` / `dev` / 직접 입력), (3) message handling (`use as-is` / `edit then proceed` / `cancel`) 세 가지를 순서대로 묻습니다. 사용자가 메뉴로 선택한 git / gh 명령만 실행되고, force-push, base 브랜치 직접 push, hook bypass (`--no-verify`), release publish (`gh release`, `npm publish`, ...) 는 금지됩니다. 이 phase 에서는 소스 코드를 수정하지 않습니다. profile: [`prompts/profiles/release-handoff.md`](prompts/profiles/release-handoff.md).
198
199
  - **PR 본문 템플릿 설정** (release-handoff) — PR 본문은 마크다운 템플릿에서 채워집니다. 해석 우선순위: 1회성 override (`--pr-template-path` 또는 okstra-run Step 6 prompt) → `<project_root>/.okstra/project.json` 의 `prTemplatePath` → `~/.okstra/config.json` 의 `prTemplatePath` → 스킬 디폴트 `~/.claude/skills/templates/prd/pr-body.template.md`. 템플릿 등록 명령: `okstra config set pr-template-path <path> [--scope project|global]` (project 스코프는 project root 기준 상대경로 허용, global 스코프는 절대경로 또는 `~/` 시작 경로만 허용). 현재 설정 확인: `okstra config get pr-template-path --scope all` 은 각 스코프 값 + 실제로 우승하는 경로(effective) 까지 보여줍니다. 디폴트 템플릿은 `## Summary` / `## Changes` / `## Test plan` / `## Linked issues` 4 섹션 + HTML 주석으로 lead 작성 가이드를 포함하며, PR 생성 직전에 lead 가 주석을 제거합니다.
199
200
  - **프로파일 워커 로스터 검증** — `--workers <csv>` 와 okstra-run Step 6 의 워커 prompt 는 해당 프로파일의 `Required workers:` 블록에 선언된 워커 ID 만 허용합니다. 프로파일에 없는 워커 (예: `release-handoff` 에서 `codex` / `antigravity`) 를 요청하면 명확한 에러로 거절되고, 인터랙티브 prompt 도 프로파일이 실제로 받는 워커만 보여줍니다.
package/README.md CHANGED
@@ -162,6 +162,7 @@ User-facing slash commands inside a Claude Code session:
162
162
  | `/okstra-rollup` | Roll up run results across every task in a task-group (or the whole project) — per-task runs/time/errors plus group totals — and synthesize a cross-task digest from the report files |
163
163
  | `/okstra-schedule` | Generate a work schedule for an entire task-group |
164
164
  | `/okstra-container-build` | Deploy a verified task's code as a local docker compose group and watch each container's logs (sub-commands: `up` / `status` / `logs` / `stop-watcher` / `down`) |
165
+ | `/okstra-graphify` | Build and query a knowledge graph over the project's own `.okstra/` memory (final reports, `decisions/*.md`, `glossary.md`), scoped to `.okstra/` with outputs under `.okstra/graph/` (sub-commands: `build` / `query` / `path` / `explain` / `mcp` / `wiki`) |
165
166
  | `/okstra-manager` | Coordinate cross-project okstra tasks through manager-owned plans, assignments, one-way project sync snapshots, status, and child launch context packets |
166
167
  | `/okstra-setup` | Per-project bootstrap (§3.2) |
167
168
 
@@ -191,7 +192,7 @@ Notable flags added in 0.7.0 / 0.8.0:
191
192
 
192
193
  Recent workflow additions (post-0.8.0, on `main`):
193
194
 
194
- - **Isolated task worktree for every task-type** — prepare automatically runs `git worktree add ~/.okstra/worktrees/<project>/<group>/<task>/` on a fresh branch `<work-category-prefix>-<task-id-segment>` branched from the **user-chosen base ref** (`--base-ref`, mirroring the `release-handoff` PR-base picker: `main` / `dev` / `staging` / `preprod` / `prod` / any local ref) the first time a task-key is seen. `--base-ref` is required on first phase; the okstra-run skill collects it via `AskUserQuestion`, non-interactive callers must pass the flag explicitly. Every subsequent **non-`implementation`** phase of the same task-key (`requirements-discovery` → `error-analysis` → `implementation-planning` → `final-verification` → `release-handoff`) reuses the same path and branch, so phase N inherits the working-tree state phase N-1 left behind. `implementation` runs are **stage-isolated** instead — each run owns exactly one stage in its own `.../<task>/stage-<N>/` worktree on branch `<prefix>-<task>-s<N>`, so independent (`depends-on (none)`) stages can be implemented in parallel across simultaneous runs without sharing a tree. A global registry at `~/.okstra/worktrees/registry.json` (flock-guarded) reserves task-keys **and stage-keys** across concurrent runs; all path/branch segments are sanitised (`/`, `:`, etc. → `-`). The worktree is preserved after every run for follow-up phases, PR authoring, and rollback. Skip paths: when the caller is already inside another worktree or `project_root` is not a git repo, provisioning no-ops (stage isolation degrades to the flat path too). Manual cleanup: `git worktree remove <path>` → `git branch -D <branch>` plus releasing/removing the key from the registry. Details: [`docs/kr/architecture.md`](docs/kr/architecture.md) (*Task type* section) and [`docs/kr/cli.md#--executor`](docs/kr/cli.md#--executor).
195
+ - **Isolated task worktree for every task-type** — prepare automatically runs `git worktree add ~/.okstra/worktrees/<project>/<group>/<task>/` on a fresh branch `<work-category-namespace>/<task-id-segment>` (e.g. `feature/dev-9436`, `fix/dev-7311`) branched from the **user-chosen base ref** (`--base-ref`, mirroring the `release-handoff` PR-base picker: `main` / `dev` / `staging` / `preprod` / `prod` / any local ref) the first time a task-key is seen. `--base-ref` is required on first phase; the okstra-run skill collects it via `AskUserQuestion`, non-interactive callers must pass the flag explicitly. Every subsequent **non-`implementation`** phase of the same task-key (`requirements-discovery` → `error-analysis` → `implementation-planning` → `final-verification` → `release-handoff`) reuses the same path and branch, so phase N inherits the working-tree state phase N-1 left behind. `implementation` runs are **stage-isolated** instead — each run owns exactly one stage in its own `.../<task>/stage-<N>/` worktree on branch `<work-category-namespace>/<task>-s<N>`, so independent (`depends-on (none)`) stages can be implemented in parallel across simultaneous runs without sharing a tree. A global registry at `~/.okstra/worktrees/registry.json` (flock-guarded) reserves task-keys **and stage-keys** across concurrent runs; all path/branch segments are sanitised (`/`, `:`, etc. → `-`). The worktree is preserved after every run for follow-up phases, PR authoring, and rollback. Skip paths: when the caller is already inside another worktree or `project_root` is not a git repo, provisioning no-ops (stage isolation degrades to the flat path too). Manual cleanup: `git worktree remove <path>` → `git branch -D <branch>` plus releasing/removing the key from the registry. Details: [`docs/kr/architecture.md`](docs/kr/architecture.md) (*Task type* section) and [`docs/kr/cli.md#--executor`](docs/kr/cli.md#--executor).
195
196
  - **`release-handoff` lifecycle phase** — runs after `final-verification` returns `verdict=accepted`. The lead drafts a commit message and PR body via a Claude worker, then prompts the user with `AskUserQuestion` for three choices: action (`commit only` / `commit + PR` / `skip`), PR base branch (`staging` / `preprod` / `prod` / `main` / `dev` / free-form), and message handling (`use as-is` / `edit then proceed` / `cancel`). Only user-selected mutating git/gh commands run. Force-push, base-branch direct push, hook bypass (`--no-verify`), and release publishing (`gh release`, `npm publish`, ...) are forbidden. Source code is not edited in this phase. Profile: [`prompts/profiles/release-handoff.md`](prompts/profiles/release-handoff.md).
196
197
  - **Configurable PR body template** (release-handoff) — the PR body is filled from a markdown template chosen in priority order: per-run override (`--pr-template-path` or the okstra-run Step 6 prompt) → `<project_root>/.okstra/project.json` `prTemplatePath` → `~/.okstra/config.json` `prTemplatePath` → bundled skill default at `~/.claude/skills/templates/prd/pr-body.template.md`. Register a template with `okstra config set pr-template-path <path> [--scope project|global]` (project scope accepts paths relative to the project root; global scope requires absolute or `~/`-prefixed). `okstra config get pr-template-path --scope all` reports every scope plus the effective winner. The bundled default ships `## Summary` / `## Changes` / `## Test plan` / `## Linked issues` with HTML comment guidance that the lead strips before opening the PR.
197
198
  - **Profile-roster worker validation** — `--workers <csv>` (and the okstra-run Step 6 worker prompt) are now restricted to the worker IDs declared by the chosen profile's `Required workers:` block. Asking for `codex` / `antigravity` on a profile that does not list them (e.g. `release-handoff`) is rejected with a clear error, and the interactive prompt only offers workers the profile actually accepts.
@@ -124,15 +124,15 @@ okstra wizard confirmation --state-file /tmp/okstra-wizard/state.json
124
124
 
125
125
  `text`를 사용자에게 보여준 뒤 Proceed/Edit/중단 picker를 렌더한다. `Edit`은 wizard가 이전 step으로 rewind한다.
126
126
 
127
- ## render-args와 render-bundle
127
+ ## outcome과 render-bundle
128
128
 
129
129
  `next.kind == "done"`이면:
130
130
 
131
131
  ```bash
132
- okstra wizard render-args --state-file /tmp/okstra-wizard/state.json
132
+ okstra wizard outcome --state-file /tmp/okstra-wizard/state.json
133
133
  ```
134
134
 
135
- `args` object의 key를 `okstra render-bundle` flag로 전달한다. 빈 string 값도 명시적으로 전달한다. 예외: `chain-stages` key는 render-bundle flag가 아니다 — Step 7 무인 연쇄 루프를 구동하는 값이라 flag로 넘기지 않는다(`run.py`는 `--stage`/`--stages`만 받는다). render-bundle block의 `--stage`는 implementation·final-verification 전용, `--stages`는 release-handoff 전용(빈 값 = whole-task)이다.
135
+ `outcome.persistActions[]`를 먼저 실행한 뒤 `outcome.renderArgs` object의 key를 `okstra render-bundle` flag로 전달한다. 빈 string 값도 명시적으로 전달한다. 예외: `chain-stages` key는 render-bundle flag가 아니다 — Step 7 무인 연쇄 루프를 구동하는 값이라 flag로 넘기지 않는다(`run.py`는 `--stage`/`--stages`만 받는다). render-bundle block의 `--stage`는 implementation·final-verification 전용, `--stages`는 release-handoff 전용(빈 값 = whole-task)이다.
136
136
 
137
137
  ```bash
138
138
  okstra render-bundle \
@@ -207,14 +207,16 @@ anchor가 unresolvable이면 `--reset-anchor <ref>`는 사용자 확인 후 실
207
207
 
208
208
  ## PR template persistence
209
209
 
210
- release-handoff에서 `pr-template-path`와 scope가 있으면 render-bundle 전에 config를 저장한다.
210
+ release-handoff에서 `outcome.persistActions[]`가 `config.set` / `pr-template-path` action을 반환하면 render-bundle 전에 config를 저장한다.
211
211
 
212
212
  ```bash
213
+ # action.scope == "project"
213
214
  okstra config set pr-template-path "<path>" --scope project
215
+ # action.scope == "global"
214
216
  okstra config set pr-template-path "<path>" --scope global
215
217
  ```
216
218
 
217
- scope는 wizard state file `pr_template_scope`에 있다. 현재 별도 subcommand가 없으므로 raw state file을 Read tool로 읽는다. shell로 `jq`나 `python3 -c`를 호출하지 않는다.
219
+ scope와 path는 wizard state file 아니라 `okstra wizard outcome`의 persist action에서 읽는다. raw state file을 직접 읽지 않는다.
218
220
 
219
221
  ## Claude lead 전환
220
222
 
@@ -58,7 +58,7 @@
58
58
  - [9. 같은 task 재개](#9-같은-task-재개)
59
59
  - [Lifecycle status and resume](#lifecycle-status-and-resume)
60
60
  - [Final report structure](#final-report-structure)
61
- - [Final report views (slim MD + HTML)](#final-report-views-slim-md--html)
61
+ - [Final report views (HTML)](#final-report-views-html)
62
62
  - [Worker error collection (optional sidecar)](#worker-error-collection-optional-sidecar)
63
63
  - [Token usage and cost accounting](#token-usage-and-cost-accounting)
64
64
  - [Validators](#validators)
@@ -347,8 +347,8 @@ okstra phase 는 PRD / issue file 을 직접 쓰지 않습니다. 동등한 결
347
347
  공통 제약:
348
348
 
349
349
  - `implementation`을 제외한 모든 phase는 source code edit, build, migration, deployment, 그 밖의 state-mutating 명령을 금지합니다(`final-verification`은 read-only 테스트 명령만 허용). `implementation`은 승인된 plan의 파일 목록 안에서만 edit/commit이 허용되며, `git push`·publish·deploy·실제 migration·third-party write API는 여전히 금지됩니다.
350
- - **모든 task-type 격리 worktree (BLOCKING)**: 모든 task-type 의 첫 번째 phase prepare 단계에서 `okstra-ctl` 이 자동으로 task-key 단위 `git worktree` 를 생성하고, 같은 task-key 의 이후 phase (`requirements-discovery` → `error-analysis` → `implementation-planning` → `implementation`) 는 동일한 worktree·브랜치를 재사용합니다. 위치는 `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` (segment 의 `/`·`:` 등 특수문자는 `-` 로 정규화) 이고, 브랜치 이름은 `<work-category-prefix>-<task-id-segment>` (예: `feat-dev-9436`, `fix-dev-7311`) 입니다. base ref 는 첫 phase prepare 시점의 main worktree `HEAD`. `~/.okstra/worktrees/registry.json` (flock-guarded) 가 task-key → path/branch 매핑을 전역 관리해 동시 실행 시 path·branch 충돌을 방지합니다. configured sync dirs 는 main worktree 에서 symlink 로 연결되어 task checkout 사이의 filesystem continuity 를 제공합니다 (sync 대상 목록은 `project.json` 의 `worktreeSyncDirs` 또는 `OKSTRA_WORKTREE_SYNC_DIRS` 환경변수로 override 가능; 빈 배열이면 sync 비활성화). 이 sync 는 okstra context/write boundary 를 확장하지 않습니다. caller 가 이미 다른 worktree 안에 있거나 project_root 가 git repo 가 아니면 provisioning 은 skip 되고 executor 는 project_root 에서 그대로 작업합니다. worktree 는 run 종료 후 자동 삭제되지 않으며 후속 phase·PR 작성·rollback 검증의 권위 artefact 입니다. 수동 cleanup: `git -C <main-worktree> worktree remove <path>` → `git -C <main-worktree> branch -D <branch>` + registry 항목 삭제. 자세한 동작은 `prompts/profiles/implementation.md` 의 *Task worktree* 블록과 `prompts/lead/okstra-lead-contract.md` 의 *Task worktree (BLOCKING for every task-type)* 섹션 참고.
351
- - **implementation stage 격리 worktree (동시 병렬)**: 위 task-key 단위 worktree 는 `requirements-discovery`~`implementation-planning` 의 모델입니다. `implementation` task 는 **stage 격리** 로 동작합니다 — **한 run = 한 stage**, 각 run 이 `.../<task-id-segment>/stage-<N>/` (브랜치 `<prefix>-<task-id-segment>-s<N>`) 격리 worktree 를 발급받습니다. registry 가 task-key 와 **stage-key** (`<task-key>#stage-<N>`) 를 함께 flock 예약하고, `_resolve_effective_stages` `consumers.jsonl` 의 `started` + registry 예약 stage 를 ready 집합에서 제외하므로(점유 SSOT = registry), 사용자가 두 `implementation` run 을 동시에 띄우면 서로 다른 독립 stage 를 충돌 없이 진행합니다. base 결정: 독립 = 공통 anchor(첫 stage 진입 HEAD 고정), 단일 의존 = 선행 done commit, 다중 의존 = 선행이 모두 ancestor 인 task worktree HEAD(`git merge-base --is-ancestor`; 미머지 시 `PrepareError`). cost-aware-design 의 ready-set batch 는 stage 마다 격리 branch 가 필요해 의미를 잃으므로(같은 branch 에 두 stage-key reserve 시 branch-uniqueness 충돌) 폐기되었고, 순차 진행은 stage done 후 다음 run, 동시 진행은 별도 run 으로 — cost 등가. `--stage <auto|N>` 또는 wizard `stage_pick` 으로 stage 를 선택합니다. wizard `stage_pick` 은 각 stage 의 상태(`[완료]`/`[진행중]`/`[준비됨]`/`[대기]`)를 라벨에 표시하는 멀티선택이며, 선택분의 의존성 closure 를 Kahn 위상정렬(`stage_targets.order_stage_closure`)해 render-args 의 `chain-stages` CSV 로 내보냅니다. `okstra-run` SKILL 이 이 큐를 받아 의존성 순서대로 단일-stage run 을 N 회 순차 실행(무인 연쇄)하되, 각 stage 의 Phase 6 `done` 행을 확인한 뒤 다음으로 넘어갑니다. 이는 오케스트레이션 계층일 뿐이며 wizard·prepare 의 **한 run = 한 stage** 격리 불변은 그대로입니다. worktree 뿐 아니라 **run 산출물(report·state·worker-results·manifest)도 `runs/implementation/stage-<N>/` 로 stage 별 격리**되므로 동시 실행하는 두 stage 의 보고서·상태가 섞이지 않습니다. 반면 `consumers.jsonl` 과 worktree registry 는 stage 간 공유되는 조율 SSOT 라 task-type 루트(`runs/implementation/`)에 그대로 둡니다.
350
+ - **모든 task-type 격리 worktree (BLOCKING)**: 모든 task-type 의 첫 번째 phase prepare 단계에서 `okstra-ctl` 이 자동으로 task-key 단위 `git worktree` 를 생성하고, 같은 task-key 의 이후 phase (`requirements-discovery` → `error-analysis` → `implementation-planning` → `implementation`) 는 동일한 worktree·브랜치를 재사용합니다. 위치는 `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` (segment 의 `/`·`:` 등 특수문자는 `-` 로 정규화) 이고, 브랜치 이름은 `<work-category-namespace>/<task-id-segment>` (예: `feature/dev-9436`, `fix/dev-7311`) 입니다. 네임스페이스는 work_category 로 결정됩니다(`feature`·`improvement`→`feature/`, `bugfix`→`fix/`, `refactor`→`refactor/`, `ops`→`ops/`, 미지정→`task/`). base ref 는 첫 phase prepare 시점의 main worktree `HEAD`. `~/.okstra/worktrees/registry.json` (flock-guarded) 가 task-key → path/branch 매핑을 전역 관리해 동시 실행 시 path·branch 충돌을 방지합니다. configured sync dirs 는 main worktree 에서 symlink 로 연결되어 task checkout 사이의 filesystem continuity 를 제공합니다 (sync 대상 목록은 `project.json` 의 `worktreeSyncDirs` 또는 `OKSTRA_WORKTREE_SYNC_DIRS` 환경변수로 override 가능; 빈 배열이면 sync 비활성화). 이 sync 는 okstra context/write boundary 를 확장하지 않습니다. caller 가 이미 다른 worktree 안에 있거나 project_root 가 git repo 가 아니면 provisioning 은 skip 되고 executor 는 project_root 에서 그대로 작업합니다. worktree 는 run 종료 후 자동 삭제되지 않으며 후속 phase·PR 작성·rollback 검증의 권위 artefact 입니다. 수동 cleanup: `git -C <main-worktree> worktree remove <path>` → `git -C <main-worktree> branch -D <branch>` + registry 항목 삭제. 자세한 동작은 `prompts/profiles/implementation.md` 의 *Task worktree* 블록과 `prompts/lead/okstra-lead-contract.md` 의 *Task worktree (BLOCKING for every task-type)* 섹션 참고.
351
+ - **implementation stage 격리 worktree (동시 병렬)**: 위 task-key 단위 worktree 는 `requirements-discovery`~`implementation-planning` 의 모델입니다. `implementation` task 는 **stage 격리** 로 동작합니다 — **한 run = 한 stage**, 각 run 이 `.../<task-id-segment>/stage-<N>/` (브랜치 `<work-category-namespace>/<task-id-segment>-s<N>`) 격리 worktree 를 발급받습니다. registry 가 task-key 와 **stage-key** (`<task-key>#stage-<N>`) 를 함께 flock 예약하고, Stage Lifecycle Snapshot 이 `consumers.jsonl` 의 `done`/`started`, carry sidecar backfill, registry 예약 stage 를 함께 읽어 ready 집합에서 제외하므로(점유 SSOT = registry), 사용자가 두 `implementation` run 을 동시에 띄우면 서로 다른 독립 stage 를 충돌 없이 진행합니다. base 결정: 독립 = 공통 anchor(첫 stage 진입 HEAD 고정), 단일 의존 = 선행 done commit, 다중 의존 = 선행이 모두 ancestor 인 task worktree HEAD(`git merge-base --is-ancestor`; 미머지 시 `PrepareError`). cost-aware-design 의 ready-set batch 는 stage 마다 격리 branch 가 필요해 의미를 잃으므로(같은 branch 에 두 stage-key reserve 시 branch-uniqueness 충돌) 폐기되었고, 순차 진행은 stage done 후 다음 run, 동시 진행은 별도 run 으로 — cost 등가. `--stage <auto|N>` 또는 wizard `stage_pick` 으로 stage 를 선택합니다. wizard `stage_pick` 은 각 stage 의 상태(`[완료]`/`[진행중]`/`[준비됨]`/`[대기]`)를 라벨에 표시하는 멀티선택이며, 선택분의 의존성 closure 를 Kahn 위상정렬(`stage_targets.order_stage_closure`)해 render-args 의 `chain-stages` CSV 로 내보냅니다. `okstra-run` SKILL 이 이 큐를 받아 의존성 순서대로 단일-stage run 을 N 회 순차 실행(무인 연쇄)하되, 각 stage 의 Phase 6 `done` 행을 확인한 뒤 다음으로 넘어갑니다. 이는 오케스트레이션 계층일 뿐이며 wizard·prepare 의 **한 run = 한 stage** 격리 불변은 그대로입니다. worktree 뿐 아니라 **run 산출물(report·state·worker-results·manifest)도 `runs/implementation/stage-<N>/` 로 stage 별 격리**되므로 동시 실행하는 두 stage 의 보고서·상태가 섞이지 않습니다. 반면 `consumers.jsonl` 과 worktree registry 는 stage 간 공유되는 조율 SSOT 라 task-type 루트(`runs/implementation/`)에 그대로 둡니다.
352
352
  - **단일-stage final-verification 의 run 산출물 격리 (동시 병렬)**: 단독-stage `final-verification`(`--stage <N>`)도 implementation 과 동일하게 run 산출물을 `runs/final-verification/stage-<N>/` 하위에 격리하고(seq 도 stage 별 독립), 팀 이름에 `-fv-s<N>` 접미사를 붙입니다 — `-fv-` 구분자로 같은 stage 의 implementation 팀(`-s<N>`)과도, 전체-task 검증의 기본 이름과도 충돌하지 않습니다. 따라서 여러 stage 의 final-verification 을 동시에 띄워도 state·worker-results·보고서·팀이 섞이지 않습니다. worktree 는 새로 만들지 않고 해당 implementation stage worktree 를 registry 에서 read-only 로 재사용하며, 그래서 registry stage-key 예약도 하지 않습니다. `teamName` 라벨에 `-fv-s<N>` 접미사를 붙이는 것은 audit/표시용 구분일 뿐이며, 실제 팀은 세션별 implicit team(`session-<leadSid>`)이라 v2.1.178 이전의 `TeamCreate` 이름 충돌 hard-fail 은 더 이상 발생하지 않습니다. 전체-task 검증(stage 빈 값)은 기존 평면 `runs/final-verification/` 구조를 유지합니다.
353
353
  - `implementation` 과 `release-handoff` 를 제외한 모든 phase 는 source code edit, build, migration, deployment, 그 밖의 state-mutating 명령을 금지합니다 (`final-verification` 은 read-only 테스트 명령만 허용). `implementation` 은 승인된 plan 의 파일 목록 안에서만 edit/commit 이 허용되며, `git push`·publish·deploy·실제 migration·third-party write API 는 여전히 금지됩니다. `release-handoff` 는 source code 자체는 수정하지 않고, 사용자가 메뉴로 선택한 commit / push / PR 명령만 실행합니다 (force push, base 브랜치 직접 push, hook bypass, release publish 는 여전히 금지).
354
354
  - 사용자가 "다음 단계 진행해" 같은 표현을 보내도, 그 발화만으로 다음 phase가 자동 시작되지 않습니다. 다음 phase는 새 `okstra.sh` 실행으로만 시작합니다.
@@ -378,12 +378,12 @@ release-handoff 까지 완료된 task 의 산출물에서 버그가 발견되면
378
378
  - **whole-task (기본)**: task 전체를 1개 PR 로 내보냅니다. 기존 동작입니다.
379
379
  - **stage-group**: 단독-stage final-verification 에서 `accepted` 를 받은 stage 들 중 일부를 골라, 수집(collector) 브랜치로 묶어 1개 PR 로 내보냅니다. task 전체가 끝나기를 기다리지 않고 검증 완료된 stage 묶음 단위로 PR 을 낼 수 있습니다.
380
380
 
381
- 진입은 brief 없이 **task-id 기반**입니다 — brief 는 entry phase 의 입력물이고, release-handoff 는 prepare 가 approved plan 의 Stage Map + `consumers.jsonl` 자격을 판정한 뒤 검증 보고서를 인용하는 input 문서(`<task_root>/release-handoff-input.md`)를 자동 생성합니다. stage 선택은 okstra-run wizard 의 `handoff_stage_pick` 멀티선택(eligible stage 묶음 / accepted whole-task 보고서가 있으면 전체 task) 또는 CLI `--stages <csv>` 로 들어오고, run-context 의 `HANDOFF_MODE` / `HANDOFF_STAGES` 로 lead 에 노출됩니다.
381
+ 진입은 brief 없이 **task-id 기반**입니다 — brief 는 entry phase 의 입력물이고, release-handoff 는 prepare 가 approved plan 의 Stage Map + Stage Lifecycle Snapshot 으로 자격을 판정한 뒤 검증 보고서를 인용하는 input 문서(`<task_root>/release-handoff-input.md`)를 자동 생성합니다. stage 선택은 okstra-run wizard 의 `handoff_stage_pick` 멀티선택(eligible stage 묶음 / accepted whole-task 보고서가 있으면 전체 task) 또는 CLI `--stages <csv>` 로 들어오고, run-context 의 `HANDOFF_MODE` / `HANDOFF_STAGES` 로 lead 에 노출됩니다.
382
382
 
383
383
  stage-group 의 상호작용 순서: **G1 base 선택 → G2 stage 확인(선택은 prepare 전에 끝남 — 재질문 없음) → assemble(수집 브랜치 생성 + 선택 stage 머지) → 충돌 프로브 → PR 초안 → push/PR**.
384
384
 
385
- - 자격 판정의 SSOT 는 `consumers.jsonl` 의 두 행입니다 — `verified`(어떤 stage 가 단독-stage final-verification 에서 accepted 됨), `pr`(어떤 stage 들이 어느 PR 로 나갔는지). `verified` 인데 아직 `pr` 에 안 들어간 stage 자격 후보입니다.
386
- - worktree registry 는 stage-group 점유를 `<task-key>#group-<id>` 키로 예약하고, 수집 브랜치 이름은 `<work-category-prefix>-<task-id-segment>-g2-3` (예: 선택한 stage 가 2·3 이면 `-g2-3`) 형태입니다.
385
+ - 자격 판정의 SSOT 는 Stage Lifecycle Snapshot 입니다. Snapshot 은 `consumers.jsonl` 의 `verified`(어떤 stage 가 단독-stage final-verification 에서 accepted 됨), `pr`(어떤 stage 들이 어느 PR 로 나갔는지), done rows 를 읽어 `verified` 인데 아직 `pr` 에 안 들어간 stage 후보로 계산합니다.
386
+ - worktree registry 는 stage-group 점유를 `<task-key>#group-<id>` 키로 예약하고, 수집 브랜치 이름은 `<work-category-namespace>/<task-id-segment>-g2-3` (예: 선택한 stage 가 2·3 이면 `-g2-3`) 형태입니다.
387
387
  - 강제 지점은 선언이 아니라 Python 모듈 `okstra_ctl.handoff` 입니다 (`okstra handoff <subcommand>`). 서브커맨드 4종: `eligible`(자격 stage 조회) / `assemble`(수집 브랜치 생성·머지) / `record-verified`(`verified` 행 기록) / `record-pr`(`pr` 행 기록). 수집 단계의 머지는 isolation spec 의 "okstra 자동 머지 없음" 비목표에 대한 명시적 예외입니다.
388
388
 
389
389
  ### improvement-discovery (sidetrack entry-point)
@@ -645,18 +645,17 @@ Claude가 작성하는 최종 보고서는 아래 구조를 우선 사용합니
645
645
  차이점이 실질적으로 없으면 억지로 대비를 만들지 말고, 차이가 없음을 명시합니다.
646
646
  저장 실패나 세션 제한에 대한 메타 설명 대신 실제 Markdown 보고서 본문을 파일에 작성해야 합니다.
647
647
 
648
- ## Final report views (slim MD + HTML)
648
+ ## Final report views (HTML)
649
649
 
650
- Phase 7 step 1.5 가 final-report MD 한 본을 입력으로 view 를 결정론적으로 자동 생성합니다.
650
+ Phase 7 step 1.5 가 final-report MD 한 본을 입력으로 self-contained HTML view 를 결정론적으로 자동 생성합니다.
651
651
 
652
- - `reports/final-report-<task-type>-<seq>.slim.md` — AI 다음-phase 입력용. 장식·캡션·sentinel 셀을 제거한 토큰-경제 버전. `validate-run.py` phase substring 검사를 byte-identical 통과합니다.
653
- - `reports/final-report-<task-type>-<seq>.html` — 사람 reviewer 용 self-contained HTML. CSS / JS 인라인 임베드 (외부 URL 0), system color 다크모드, sticky header, 인쇄 대응. §5 `C-*` 행의 의사결정 입력 (체크박스 / 셀렉트 / textarea) 을 화면에서 채우고 `Export user response` 버튼으로 사이드카 markdown 을 생성합니다.
652
+ - `reports/final-report-<task-type>-<seq>.html` — 사람 reviewer self-contained HTML. CSS / JS 인라인 임베드 (외부 URL 0), system color 다크모드, sticky header, 인쇄 대응. §1 `C-*` 행의 의사결정 입력 (체크박스 / 셀렉트 / textarea) 을 화면에서 채우고 `Export user response` 버튼으로 사이드카 markdown 생성합니다.
654
653
 
655
654
  진입점:
656
655
 
657
- - Python 단일 reference: `scripts/okstra_ctl/report_views.py` (`slim_markdown(...)`, `render_html(..., css, js)`, `serialize_user_response(...)`). HTML 내 JS `buildUserResponseMarkdown` 은 Python `serialize_user_response` 와 **byte-identical** (Node `vm.runInThisContext` 단위 테스트로 자동 검증).
656
+ - Python 단일 reference: `scripts/okstra_ctl/report_views.py` (`build_report_view_model(...)`, `render_report_view_model(..., css, js)`, `render_html(..., css, js)`, `serialize_user_response(...)`). HTML 내 JS `buildUserResponseMarkdown` 은 Python `serialize_user_response` 와 **byte-identical** (Node `vm.runInThisContext` 단위 테스트로 자동 검증).
658
657
  - CLI: `scripts/okstra-render-report-views.py <final-report.md>` 또는 Node 위임 wrapper `bin/okstra render-views <md>`.
659
- - 검증: `validators/validate-report-views.py` — slim 의 phase substring 보존, HTML 내 form control 위치, 외부 URL 부재, Response ID parity (`C-*` ↔ HTML), 모듈 substring 상수 drift 모두 검사.
658
+ - 검증: `validators/validate-report-views.py` — HTML 내 form control 위치, 외부 URL 부재, stale source digest, Response ID parity (`C-*` ↔ HTML) 검사.
660
659
  - 사용자 응답 사이드카 스키마 SSOT: `templates/reports/user-response.template.md`.
661
660
 
662
661
  원본 final-report MD 는 어떤 경우에도 view 생성으로 인해 수정되지 않습니다.
package/docs/kr/cli.md CHANGED
@@ -398,8 +398,8 @@ fallback 기본값은 아래와 같습니다.
398
398
  - Claude/Codex/Antigravity 세 verifier 는 executor provider 와 관계없이 항상 dispatch 됩니다. Executor 와 같은 provider 라도 별도 CLI 세션으로 verifier 가 호출되어 context 가 분리되므로 self-review 안전장치는 유지됩니다.
399
399
  - 실제 파일 변경은 Codex/Antigravity 의 경우 각 CLI 의 auto-edit 모드 (예: `codex exec --sandbox workspace-write`) 를 통해 일어나며, Claude-side Edit/Write tool 을 거치지 않습니다. implementation phase 에서 worker 가 mutation 을 수행하는 위치는 다음 항목에서 설명하는 task worktree 이며, 양쪽 wrapper(`scripts/okstra-codex-exec.sh`, `scripts/okstra-antigravity-exec.sh`) 는 worktree 경로를 4번째 positional 인자로 받아 codex 는 `--add-dir`, antigravity 는 `--include-directories` 로 forward 합니다. 누락하면 codex `workspace-write` 샌드박스가 worktree 쓰기를 EPERM 으로 거부합니다.
400
400
  - **Claude executor 의 cwd 처리**: Claude Bash tool 은 per-call cwd 인자를 받지 않고 lead session 의 cwd 를 상속하므로, cwd 에 민감한 toolchain (`cargo`, `npm`, `pnpm`, `bun`, `pytest`, `make`, `go` 등) 을 worktree 안에서 실행하려면 호출을 `cd {{EXECUTOR_WORKTREE_PATH}} && <cmd>` 로 prefix 해야 합니다. 단일 Bash 호출 안에서 `cd` 가 leading token 으로 남아야 Claude Code 의 permission auto-allow 가 정상 동작하므로 `bash -lc "..."` / `bash -c "..."` 로 감싸지 않습니다 (감싸면 `cd` 가 가려져 매 호출마다 permission prompt 가 발생). `git -C <path>`, `cargo --manifest-path`, `pytest --rootdir` 처럼 작업 디렉터리 플래그를 받는 도구는 `cd && ` chain 대신 해당 플래그를 우선 사용합니다. Edit/Write/Read tool 은 이미 절대경로를 사용하므로 별도 cwd 처리가 필요 없습니다. 이 규칙은 Claude executor 에만 적용되고 codex / antigravity executor 는 CLI wrapper 가 cwd 를 주입합니다.
401
- - **Task worktree (모든 task-type 자동 격리)**: 모든 task-type 의 첫 번째 phase prepare 단계에서 `okstra-ctl` 이 `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` 에 `git worktree` 를 생성하고, 브랜치 `<work-category-prefix>-<task-id-segment>` 를 main worktree `HEAD` 에서 분기합니다. 같은 task-key 의 이후 phase 는 동일한 path/branch 를 재사용하므로 status 가 `reused` 로 기록됩니다 (run-prep 시점에 새 `git worktree add` 가 일어나지 않음). 모든 segment 의 `/`·`:` 등 특수문자는 `-` 로 정규화되며, `~/.okstra/worktrees/registry.json` 가 task-key → path/branch 매핑을 전역 관리합니다 (flock-guarded). Executor 의 Edit/Write/build/test/commit, verifier 의 read 는 모두 이 worktree 안에서 수행됩니다. caller 가 이미 다른 worktree 안에 있거나 project_root 가 git repo 가 아니면 provisioning 은 skip 되고 status 가 `skipped-in-worktree` / `skipped-not-git` 로 기록됩니다. 경로·브랜치 충돌은 `PrepareError` 로 즉시 실패시키며, run 종료 후 worktree 는 자동 삭제하지 않습니다 (수동: `git worktree remove` → `git branch -D` + registry 항목 삭제). **단, 아래 implementation stage 격리는 예외입니다.**
402
- - **implementation stage 격리 (동시 병렬)**: 위 task-key 단위 worktree 는 `requirements-discovery`~`implementation-planning` 에만 해당합니다. `implementation` task 의 각 run 은 **stage 별 격리 worktree** (`~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/stage-<N>/`, 브랜치 `<work-category-prefix>-<task-id-segment>-s<N>`)에서 실행됩니다. registry 가 stage-key (`<task-key>#stage-<N>`) 를 flock 으로 원자 예약하고, `_resolve_effective_stages` 가 `consumers.jsonl` 의 `started` 행 + registry 예약 stage 를 제외하며, stage 선택부터 worktree 생성·registry 예약까지가 task-key 단위 프로비저닝 mutex(`~/.okstra/.locks/worktree-provision/`) 한 임계구역 안에서 수행되므로, 두 `implementation` run 을 동시에 띄우면 서로 다른 ready stage 를 안전하게 잡습니다 (**한 run = 한 stage**). stage worktree 의 base 는 의존 종류로 결정됩니다 — 독립(`depends-on (none)`) = 공통 anchor(첫 stage 진입 시 task-key worktree HEAD 1회 고정), 단일 의존(`depends-on X`) = 선행 stage 의 done `head_commit`, 다중 의존(`depends-on X,Y…`) = 선행들이 모두 머지된 task worktree HEAD(`git merge-base --is-ancestor` 로 검증, 미머지 시 `PrepareError` 로 머지 안내). 실행할 stage 는 `--stage <auto|N>` (`okstra.sh`/`render-bundle` 공통) 또는 okstra-run wizard 의 `stage_pick` 단계로 지정합니다. `project_root` 가 git repo 가 아니거나 nested worktree 면 stage 격리도 평면 동작으로 degrade 합니다.
401
+ - **Task worktree (모든 task-type 자동 격리)**: 모든 task-type 의 첫 번째 phase prepare 단계에서 `okstra-ctl` 이 `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` 에 `git worktree` 를 생성하고, 브랜치 `<work-category-namespace>/<task-id-segment>` (예: `feature/dev-9436`, `fix/dev-7311`) 를 main worktree `HEAD` 에서 분기합니다. 같은 task-key 의 이후 phase 는 동일한 path/branch 를 재사용하므로 status 가 `reused` 로 기록됩니다 (run-prep 시점에 새 `git worktree add` 가 일어나지 않음). 모든 segment 의 `/`·`:` 등 특수문자는 `-` 로 정규화되며, `~/.okstra/worktrees/registry.json` 가 task-key → path/branch 매핑을 전역 관리합니다 (flock-guarded). Executor 의 Edit/Write/build/test/commit, verifier 의 read 는 모두 이 worktree 안에서 수행됩니다. caller 가 이미 다른 worktree 안에 있거나 project_root 가 git repo 가 아니면 provisioning 은 skip 되고 status 가 `skipped-in-worktree` / `skipped-not-git` 로 기록됩니다. 경로·브랜치 충돌은 `PrepareError` 로 즉시 실패시키며, run 종료 후 worktree 는 자동 삭제하지 않습니다 (수동: `git worktree remove` → `git branch -D` + registry 항목 삭제). **단, 아래 implementation stage 격리는 예외입니다.**
402
+ - **implementation stage 격리 (동시 병렬)**: 위 task-key 단위 worktree 는 `requirements-discovery`~`implementation-planning` 에만 해당합니다. `implementation` task 의 각 run 은 **stage 별 격리 worktree** (`~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/stage-<N>/`, 브랜치 `<work-category-namespace>/<task-id-segment>-s<N>`)에서 실행됩니다. registry 가 stage-key (`<task-key>#stage-<N>`) 를 flock 으로 원자 예약하고, `_resolve_effective_stages` 가 `consumers.jsonl` 의 `started` 행 + registry 예약 stage 를 제외하며, stage 선택부터 worktree 생성·registry 예약까지가 task-key 단위 프로비저닝 mutex(`~/.okstra/.locks/worktree-provision/`) 한 임계구역 안에서 수행되므로, 두 `implementation` run 을 동시에 띄우면 서로 다른 ready stage 를 안전하게 잡습니다 (**한 run = 한 stage**). stage worktree 의 base 는 의존 종류로 결정됩니다 — 독립(`depends-on (none)`) = 공통 anchor(첫 stage 진입 시 task-key worktree HEAD 1회 고정), 단일 의존(`depends-on X`) = 선행 stage 의 done `head_commit`, 다중 의존(`depends-on X,Y…`) = 선행들이 모두 머지된 task worktree HEAD(`git merge-base --is-ancestor` 로 검증, 미머지 시 `PrepareError` 로 머지 안내). 실행할 stage 는 `--stage <auto|N>` (`okstra.sh`/`render-bundle` 공통) 또는 okstra-run wizard 의 `stage_pick` 단계로 지정합니다. `project_root` 가 git repo 가 아니거나 nested worktree 면 stage 격리도 평면 동작으로 degrade 합니다.
403
403
  - **단일-stage final-verification 산출물 격리**: `--task-type final-verification --stage <N>` 은 해당 implementation stage worktree 를 registry 에서 read-only 로 재사용하면서, run 산출물은 `runs/final-verification/stage-<N>/` 하위에 stage 별로 격리하고 팀 이름에 `-fv-s<N>` 접미사를 붙입니다. 서로 다른 stage 의 final-verification 을 동시에 띄워도 state·worker-results·팀이 충돌하지 않습니다 (같은 stage 를 동시에 두 번 띄우는 것은 격리되지 않음 — TeamCreate 이름 충돌로 즉시 실패). 전체-task 검증(stage 빈 값)은 평면 `runs/final-verification/` 를 유지합니다.
404
404
 
405
405
  예:
@@ -637,7 +637,7 @@ chmod +x ~/.local/bin/okstra-ctl
637
637
  | `okstra rollup [--task-group <group>] [--project-root <dir>] [--cwd <dir>]` | okstra-rollup 스킬의 read-only 백엔드. catalog 의 모든 task(또는 한 task-group)에 대해 task 별 run 수·소요 시간(raw ms)·에러 수·최신 report 경로와 group 차원 합계 및 상태/카테고리/phase 분포를 JSON 으로 출력한다. `--task-group` 생략 시 프로젝트 전체 catalog 를 대상으로 한다. 시간은 raw ms 이며 HH:MM:SS 포맷·report 본문 종합은 호출자(skill)에 위임한다. 단일 task drill-down 은 `okstra inspect` 계열을 쓴다 |
638
638
  | `okstra migrate [--apply] [--cwd <dir>] [--quiet]` | 한 번만 실행: 프로젝트 산출물 루트를 `.project-docs/okstra/` → `.okstra/` 로 이동. 기본 dry-run, `--apply` 로 실제 실행. `git mv` (git worktree) + 빈 `.project-docs/` 제거 + `<PROJECT>/CLAUDE.md` import 라인 + `.gitignore` + `~/.okstra/{recent,active}.jsonl` + `~/.okstra/worktrees/registry.json` 의 해당 프로젝트 row 동기화. 이미 `.okstra/` 가 존재하거나 레거시 디렉토리가 없으면 exit 1 로 거부. v0.x 말까지 유지 후 제거 예정 |
639
639
  | `okstra task-list [--project-root <path>]` | `list_project_tasks` + `read_latest_task` 결과를 합쳐 task 카탈로그 + 최근 task 를 JSON 으로 반환 |
640
- | `okstra task-show <task-key> [--project-root <path>]` | task-manifest.json workflow / phase / status 요약 |
640
+ | `okstra task-show <task-key> [--project-root <path>]` | Task Read-Side Snapshot 기반 workflow / phase / status / artifact 요약 |
641
641
  | `okstra worktree-lookup <task-key>` | `worktree_registry.lookup` 결과 (예약된 path / branch / base ref / 현재 상태) |
642
642
  | `okstra plan-validate <plan-path>` | `_validate_approved_plan` — frontmatter `approved` 인식 결과와 Blocks=approval 미해결 행 진단 |
643
643
  | `okstra render-bundle <args…> [--stage <auto\|N>] [--stages <csv>]` | `prepare_task_bundle(render_only=True)` 의 thin shim — `python3 -m okstra_ctl.run --render-only` 와 동일 시그니처. `--stage` 는 `implementation` / `final-verification` 전용: 실행(검증)할 Stage Map 항목 지정. `implementation` 은 `auto` (기본값) = 의존성이 만족된 가장 빠른 미완료 stage, `<N>` = 강제 지정. `final-verification` 은 `<N>` = 해당 stage 단독 검증(산출물이 `runs/final-verification/stage-<N>/` 에 격리되고 팀 이름에 `-fv-s<N>` 접미사), 빈 값 = 전체-task 검증(평면 구조 유지). `--stages <csv>` 는 `release-handoff` 전용(별개 채널): PR 로 묶을 stage 번호들(stage-group 모드), 빈 값 = whole-task 모드. prepare 가 eligibility(`done`+`verified` accepted+미-`pr`)를 강제하고 검증 보고서 인용 input 문서를 자동 생성한다 |
@@ -645,7 +645,7 @@ chmod +x ~/.local/bin/okstra-ctl
645
645
  | `okstra codex-dispatch --project-root <dir> --run-manifest <path> [--workers codex,antigravity,report-writer]` | `codex-run` 이 준비한 run manifest 를 읽어 Codex-side 지원 worker subset 을 실행한다. `--workers` 생략 시 `claude` 같은 미지원 roster 항목은 건너뛰고, 명시 요청하면 실패한다. report-writer 는 `--enable-codex-report-writer --report-writer-codex-model <model>` opt-in 이 필요하며, 성공 시 token-usage substitution, HTML view 렌더, follow-up task stub 생성, run validation 을 자동 실행한다 |
646
646
  | `okstra team dispatch --project-root <dir> --run-manifest <path> [--workers <csv>] [--jobs-file <path>] [--dry-run]` / `okstra team await --project-root <dir> --run-manifest <path> [--json]` / `okstra team teardown --project-root <dir> --run-manifest <path> [--dry-run] [--json]` | `leadRuntime=external` run manifest 를 읽어 tmux-pane worker dispatch / wait / teardown 을 수행한다. tmux pane 을 만들 수 없으면 CLI wrapper 로 graceful degrade 하고 `workerDispatches[].degradedFrom` 에 기록한다 |
647
647
  | `okstra render-views <final-report.md>` | Phase 7 step 1.5 — 토큰 치환된 final-report MD 한 본을 입력으로 sibling `*.slim.md` (AI 입력용) + `*.html` (사람용 self-contained) 두 view 를 결정론적으로 생성. 원본 MD 는 수정하지 않음. Node 위임 wrapper는 `scripts/okstra-render-report-views.py` 를 호출. `validators/validate-report-views.py` 가 substring 보존 / form-control 위치 / Response ID parity 를 검사 |
648
- | `okstra wizard <init\|step\|render-args\|confirmation> --state-file <path>` | okstra-run 인터랙티브 입력 상태머신 (`okstra_ctl.wizard`). `init` 으로 state file 을 시드한 뒤 skill 이 `step --answer <val>` 을 반복 호출하면 다음 `Prompt` JSON 을 받음. `--answer` 는 **필수**. 응답을 주지 않고 다음 prompt 만 미리 보고 싶다면 `--no-submit` 으로 peek. `render-args` 는 최종 `render-bundle` 인자 맵, `confirmation` 은 사용자 echo 블록을 반환. `implementation` task type 에서는 `approved_plan_pick` 직후 `stage_pick` 단계가 추가되어 실행할 stage 를 선택하고, `executor_pick` 으로 넘어갑니다. brief 단계는 entry task-type(requirements-discovery / error-analysis / improvement-discovery)에서만 나오며, downstream 은 manifest 의 brief 를 자동 carry-in 하고(미등록 시 `brief_carry` 3-옵션 fallback), `release-handoff` 는 brief 없이 `handoff_stage_pick` 멀티선택(eligible stage 묶음 / 전체 task)으로 진입합니다 |
648
+ | `okstra wizard <init\|step\|render-args\|confirmation\|outcome> --state-file <path>` | okstra-run 인터랙티브 입력 상태머신 (`okstra_ctl.wizard`). `init` 으로 state file 을 시드한 뒤 skill 이 `step --answer <val>` 을 반복 호출하면 다음 `Prompt` JSON 을 받음. `--answer` 는 **필수**. 응답을 주지 않고 다음 prompt 만 미리 보고 싶다면 `--no-submit` 으로 peek. `render-args` 는 최종 `render-bundle` 인자 맵, `confirmation` 은 사용자 echo 블록을 반환. `outcome` 은 완료된 wizard 에서 `renderArgs`, `persistActions`, `confirmationText` 를 한 번에 반환하며, release-handoff 의 project/global PR template 저장은 `persistActions[].command == "config.set"` 로 노출된다. `implementation` task type 에서는 `approved_plan_pick` 직후 `stage_pick` 단계가 추가되어 실행할 stage 를 선택하고, `executor_pick` 으로 넘어갑니다. brief 단계는 entry task-type(requirements-discovery / error-analysis / improvement-discovery)에서만 나오며, downstream 은 manifest 의 brief 를 자동 carry-in 하고(미등록 시 `brief_carry` 3-옵션 fallback), `release-handoff` 는 brief 없이 `handoff_stage_pick` 멀티선택(eligible stage 묶음 / 전체 task)으로 진입합니다 |
649
649
  | `okstra token-usage ...` | 설치된 `okstra-token-usage.py` 를 감싸 run token usage 수집/치환을 수행. 세션 jsonl 은 기본적으로 `$OKSTRA_HOME/cache/token-usage/` 의 byte cursor 캐시로 증분 스캔하며, `--no-cache` 로 캐시를 우회해 전체 재스캔을 강제할 수 있음(정확성 폴백) |
650
650
 
651
651
  > 모든 subcommand 는 `bin/okstra` 가 spawn 하는 python 헬퍼 (`src/lib/python-helper.mjs`) 가 `PYTHONPATH` 와 `~/.okstra/lib/python` 을 wire 합니다. 직접 `python3 -m okstra_ctl.*` 으로 호출하면 `PYTHONPATH` 를 사용자가 직접 셋업해야 합니다.
@@ -51,10 +51,10 @@ okstra/
51
51
  │ ├── okstra_ctl/ orchestration core
52
52
  │ ├── okstra_project/ project root / project.json resolver
53
53
  │ ├── okstra_token_usage/ token usage + cost accounting
54
- │ ├── okstra_vendor/ vendored Jinja2 / MarkupSafe
54
+ │ ├── okstra_vendor/ vendored Jinja2 / MarkupSafe + graphify / networkx (okstra-graphify skill)
55
55
  │ ├── lib/okstra/ Bash helpers for okstra.sh
56
56
  │ └── lib/okstra-ctl/ Bash control-center subcommands
57
- ├── skills/ Claude Code skills (8)
57
+ ├── skills/ Claude Code skills (10)
58
58
  ├── agents/ lead SKILL.md + worker agent specs
59
59
  ├── prompts/ launch template, phase profiles, wizard prompt JSON
60
60
  ├── schemas/ JSON schema for final-report data.json
@@ -157,7 +157,7 @@ Runtime/install asset changes follow this checklist:
157
157
  | `git-reconcile` | `src/commands/execute/git-reconcile.mjs` | Reconcile stale stage SHAs after external git history changes |
158
158
  | `handoff` | `src/commands/execute/handoff.mjs` | Stage-group release-handoff eligibility / assemble / record helpers |
159
159
  | `integrate-stages` | `src/commands/execute/integrate-stages.mjs` | Merge verified stages into the task worktree and clean stage worktrees |
160
- | `task-list`, `task-show` | `src/commands/inspect/task-list.mjs`, `src/commands/inspect/task-show.mjs` | Task/run introspection for skills |
160
+ | `task-list`, `task-show` | `src/commands/inspect/task-list.mjs`, `src/commands/inspect/task-show.mjs` | Task/run introspection for skills; `task-show` consumes the Python task read-side snapshot |
161
161
  | `resolve-task-key` | `src/commands/inspect/resolve-task-key.mjs` | Resolve a bare task-id to candidate task-keys from the project catalog |
162
162
  | `time-report`, `log-report`, `error-report`, `error-zip` | `src/commands/inspect/*.mjs` | Read-side task runtime, wrapper log, and error aggregation helpers |
163
163
  | `context-cost` | `src/commands/inspect/context-cost.mjs` | Estimate task bundle file/read context cost |
@@ -169,7 +169,7 @@ Runtime/install asset changes follow this checklist:
169
169
  | `team` | `src/commands/execute/team.mjs` | External lead tmux-pane worker dispatch / await / teardown |
170
170
  | `render-views` | `src/commands/report/render-views.mjs` | Generate slim MD + self-contained HTML report views |
171
171
  | `render-final-report`, `inject-report-index` | `src/commands/report/*.mjs` | Render final-report Markdown from data.json and inject top-of-report index anchors |
172
- | `wizard` | `src/commands/execute/wizard.mjs` | Drive the `okstra-run` interactive state machine |
172
+ | `wizard` | `src/commands/execute/wizard.mjs` | Drive the `okstra-run` interactive state machine, including the final outcome envelope |
173
173
  | `token-usage` | `src/commands/execute/token-usage.mjs` | Wrap installed Python token usage CLI |
174
174
  | `spawn-followups`, `error-log` | `src/commands/execute/*.mjs` | Follow-up task bundle creation and run error-log append helpers |
175
175
  | `memory` | `src/commands/memory/memory.mjs` | Store/find global conversation memory under `~/.okstra/memory-book` |
@@ -193,7 +193,7 @@ Top-level scripts:
193
193
  | `okstra-wrapper-status.py` | Heartbeat sidecar writer used by worker wrappers |
194
194
  | `okstra-token-usage.py` | Token usage CLI entrypoint |
195
195
  | `okstra-render-final-report.py` | Render final-report Markdown from data.json |
196
- | `okstra-render-report-views.py` | Render slim MD + HTML views from final-report Markdown |
196
+ | `okstra-render-report-views.py` | Render self-contained HTML views from final-report Markdown |
197
197
  | `okstra-error-log.py` | Normalize worker/lead error sidecars |
198
198
  | `okstra-spawn-followups.py` | Follow-up spawning helper |
199
199
  | `okstra-trace-cleanup.sh` | tmux okstra pane cleanup (worker-agent + trace, lead pane 제외); `--reclaim-completed` 모드는 `@okstra_status` 가 종료(stage=exited)인 trace pane 만 회수하고 진행 중 pane 은 보존 |
@@ -206,8 +206,8 @@ Important modules:
206
206
  | Module | Role |
207
207
  |---|---|
208
208
  | `run.py` | `prepare_task_bundle()` single authority and CLI parser |
209
- | `implementation_stage.py` | `implementation` 단일-stage run 오케스트레이션 — consumer 상태 복구 → 가용 Stage Map entry 선택 → 격리 stage worktree provision → 선택 stage 를 run context 로 발행 (`run.py` 에서 추출) |
210
- | `stage_targets.py` | Stage readiness/verification 정책 SSOT — 어떤 stage 가 실행 가능한지, 어느 commit 에서 분기하는지, final-verification 이 무엇을 검사하는지 결정 (`consumers.jsonl` 행과 git ancestry 검사를 단일 인터페이스 뒤로 캡슐화). `order_stage_closure` 는 wizard 멀티선택 stage 집합의 의존성 closure 를 Kahn 위상정렬해 `chain-stages` 무인 연쇄 순서를 산출 |
209
+ | `implementation_stage.py` | `implementation` 단일-stage run 오케스트레이션 — Stage Lifecycle Snapshot 읽기 → 가용 Stage Map entry 선택 → 격리 stage worktree provision → 선택 stage 를 run context 로 발행 (`run.py` 에서 추출) |
210
+ | `stage_targets.py` | Stage readiness/verification 정책 SSOT — Stage Lifecycle Snapshot(`consumers.jsonl` ledger + carry sidecar backfill + active registry reservation)으로 어떤 stage 가 실행 가능한지, 어느 commit 에서 분기하는지, final-verification 이 무엇을 검사하는지 결정. `order_stage_closure` 는 wizard 멀티선택 stage 집합의 의존성 closure 를 Kahn 위상정렬해 `chain-stages` 무인 연쇄 순서를 산출 |
211
211
  | `stage_reconcile.py` | stage prepare 흐름 공용 best-effort git reconciliation (`git_reconcile.auto_reconcile` 위임; advisory — 실패는 stderr 보고만, dependency gate 가 권위 판정 유지) |
212
212
  | `run_context.py` | Per-task mutex, run context and run-input persistence; `consumers_mutex` helper for atomic `consumers.jsonl` writes |
213
213
  | `path_hints.py` | Compact path-hint persistence + legacy context hydration — `run-context` / `active-run-context` 를 schemaVersion `2.0` 의 `identity` + `pathHints` compact schema 로 저장하고, host-side reader 가 읽는 순간 기존 flat path key(`RUN_MANIFEST_RELATIVE_PATH`, `TEAM_STATE_PATH` 등)를 메모리에서 hydrate |
@@ -224,7 +224,7 @@ Important modules:
224
224
  | `md_table.py` | Markdown pipe-table escape/split SSOT — `mdcell` 필터(`escape_pipes`)와 `\|` 인식 `split_pipe_row`; renderer·HTML view·validators 공용 |
225
225
  | `qa_commands.py` | QA command deny-list validation for plans |
226
226
  | `pr_template.py` | PR body template resolution for release-handoff |
227
- | `report_views.py`, `render_final_report.py`, `final_report_schema.py` | Final-report data.json → Markdown → slim/HTML pipeline |
227
+ | `report_views.py`, `render_final_report.py`, `final_report_schema.py` | Final-report data.json → Markdown → Report View Model → self-contained HTML pipeline |
228
228
  | `final_report_paths.py`, `report_view_artifacts.py` | Final-report markdown/data.json 쌍 및 생성 view artifact(HTML view, user-responses 디렉터리) 경로 helper SSOT |
229
229
  | `wizard.py` | `okstra-run` prompt state machine; user-facing Korean strings live in `prompts/wizard/prompts.ko.json` |
230
230
  | `wizard_stage_intent.py` | `okstra-run` wizard 출력의 stage 관련 intent projection — whole-task(`__whole_task__`) vs 단일/멀티 stage 선택을 render-args 로 정규화 (`resolve_wizard_stage_intent`) |
@@ -253,7 +253,7 @@ Important modules:
253
253
  Project resolver and read-only state helpers:
254
254
 
255
255
  - `resolver.py`: locate project root and upsert `project.json`
256
- - `state.py`: read project metadata, task catalog, task manifest
256
+ - `state.py`: read project metadata, task catalog, task manifest, and curated task read-side snapshots
257
257
 
258
258
  ### 4.5 `scripts/okstra_token_usage/`
259
259
 
@@ -360,10 +360,10 @@ Non-`implementation` phases share one task-key worktree:
360
360
  ~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/
361
361
  ```
362
362
 
363
- Branch name:
363
+ Branch name (namespace by work_category — `feature`/`improvement` → `feature/`, `bugfix` → `fix/`, `refactor` → `refactor/`, `ops` → `ops/`, unset → `task/`):
364
364
 
365
365
  ```text
366
- <work-category-prefix>-<task-id-segment>
366
+ <work-category-namespace>/<task-id-segment>
367
367
  ```
368
368
 
369
369
  That task-key worktree is reused for `requirements-discovery` through `implementation-planning`, and by whole-task verification / handoff flows after implementation stages have been integrated. `worktreeSyncDirs`, `worktreeSyncFiles`, and `worktreeSnapshotFiles` provide filesystem continuity only; they do not expand okstra's context/write boundary.
@@ -372,7 +372,7 @@ That task-key worktree is reused for `requirements-discovery` through `implement
372
372
 
373
373
  ```text
374
374
  ~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/stage-<N>/
375
- <work-category-prefix>-<task-id-segment>-s<N>
375
+ <work-category-namespace>/<task-id-segment>-s<N>
376
376
  ```
377
377
 
378
378
  Single-stage `final-verification --stage <N>` reuses the matching implementation stage worktree read-only, while run artifacts are isolated under `runs/final-verification/stage-<N>/`. Whole-task final-verification keeps the flat `runs/final-verification/` shape.
@@ -55,14 +55,14 @@ flowchart TD
55
55
  | render-bundle Node shim | [`src/commands/execute/render-bundle.mjs`](../../src/commands/execute/render-bundle.mjs) |
56
56
  | bundle 생성 단일 진입점 | [`scripts/okstra_ctl/run.py`](../../scripts/okstra_ctl/run.py) |
57
57
  | implementation stage 선택/provision | [`scripts/okstra_ctl/implementation_stage.py`](../../scripts/okstra_ctl/implementation_stage.py) |
58
- | stage target/base/verification 정책 | [`scripts/okstra_ctl/stage_targets.py`](../../scripts/okstra_ctl/stage_targets.py) |
58
+ | Stage Lifecycle Snapshot + stage target/base/verification 정책 | [`scripts/okstra_ctl/stage_targets.py`](../../scripts/okstra_ctl/stage_targets.py) |
59
59
  | phase boundary | [`scripts/okstra_ctl/workflow.py`](../../scripts/okstra_ctl/workflow.py) |
60
60
  | task worktree | [`scripts/okstra_ctl/worktree.py`](../../scripts/okstra_ctl/worktree.py) |
61
61
  | stage-group handoff | [`scripts/okstra_ctl/handoff.py`](../../scripts/okstra_ctl/handoff.py) |
62
62
  | worker roster parser | [`scripts/okstra_ctl/workers.py`](../../scripts/okstra_ctl/workers.py) |
63
63
  | lead operating contract | [`prompts/lead/okstra-lead-contract.md`](../../prompts/lead/okstra-lead-contract.md) |
64
64
  | phase profiles | [`prompts/profiles/`](../../prompts/profiles/) |
65
- | final report shape | [`templates/reports/final-report.template.md`](../../templates/reports/final-report.template.md) |
65
+ | final report shape / HTML view | [`templates/reports/final-report.template.md`](../../templates/reports/final-report.template.md), [`scripts/okstra_ctl/report_views.py`](../../scripts/okstra_ctl/report_views.py) |
66
66
 
67
67
  ## 5. 빠른 비교표
68
68
 
@@ -71,6 +71,6 @@ flowchart TD
71
71
  | `requirements-discovery` | 공통 질문만 | profile/brief/base-ref 존재 | multi-worker analysis, convergence 1 round default | `pending-routing-decision` |
72
72
  | `error-analysis` | 공통 질문만 | profile/brief/base-ref 존재 | multi-worker analysis, convergence 2 rounds default | `implementation-planning` |
73
73
  | `implementation-planning` | 공통 질문만 | profile/brief/base-ref 존재 | multi-worker analysis + Phase 6 plan-body verification | `implementation` |
74
- | `implementation` | approved plan, stage multi-pick, executor | approved marker, stage map, stage-key reservation, QA command deny-list | one run = one stage; executor writes in isolated stage worktree, verifiers read-only | `final-verification` |
74
+ | `implementation` | approved plan, stage multi-pick, executor | approved marker, Stage Lifecycle Snapshot, stage-key reservation, QA command deny-list | one run = one stage; executor writes in isolated stage worktree, verifiers read-only | `final-verification` |
75
75
  | `final-verification` | approved plan, stage pick(whole-task or single-stage) | `VERIFICATION_TARGET` 해소; whole-task 자동 통합/teardown 또는 single-stage worktree reuse | whole-task may integrate stages first; analyser verification itself is read-only | `pending-release-handoff` |
76
- | `release-handoff` | handoff scope(stage-group or whole-task), PR template override/scope | accepted verification eligibility, generated `release-handoff-input.md`, empty worker roster | single-lead; whole-task PR or stage-group collector branch/PR | `done-or-follow-up` |
76
+ | `release-handoff` | handoff scope(stage-group or whole-task), PR template override/scope | Stage Lifecycle Snapshot eligibility, generated `release-handoff-input.md`, empty worker roster | single-lead; whole-task PR or stage-group collector branch/PR | `done-or-follow-up` |
@@ -79,8 +79,11 @@ sequenceDiagram
79
79
  participant FS as .okstra
80
80
  participant Home as ~/.okstra
81
81
 
82
- Skill->>Node: okstra wizard render-args
83
- Node-->>Skill: { args: ... }
82
+ Skill->>Node: okstra wizard outcome
83
+ Node-->>Skill: { renderArgs: ..., persistActions: ... }
84
+ opt persistActions present
85
+ Skill->>Node: okstra config set ...
86
+ end
84
87
  Skill->>Node: okstra render-bundle --... --render-only
85
88
  Node->>Py: python3 -m okstra_ctl.run --render-only --...
86
89
  Py->>Py: validate profile, brief, task-type gates
@@ -128,7 +131,7 @@ flowchart TD
128
131
  Runs --> Man[manifests/run-manifest-*.json]
129
132
  Runs --> Prompts[prompts/*-worker-prompt-*.md]
130
133
  Runs --> Results[worker-results/*.md]
131
- Runs --> Reports[reports/final-report-*.md<br/>reports/*.data.json]
134
+ Runs --> Reports[reports/final-report-*.md<br/>reports/*.data.json<br/>reports/final-report-*.html]
132
135
  Runs --> State[state/*.json]
133
136
  Runs --> Status[status/final-status-*.json]
134
137
  Runs --> ImplStage[implementation/stage-N/...]
@@ -138,7 +141,7 @@ flowchart TD
138
141
  Root --> Handoff[release-handoff-input.md]
139
142
  ```
140
143
 
141
- `implementation`과 단일-stage `final-verification`은 run 산출물을 `stage-<N>/` 아래에 격리한다. `implementation`의 carry sidecar와 `consumers.jsonl`은 stage 간 조율 ledger라 phase root에 남는다. `release-handoff`는 brief를 받지 않고 prepare가 `release-handoff-input.md`를 생성한다.
144
+ `implementation`과 단일-stage `final-verification`은 run 산출물을 `stage-<N>/` 아래에 격리한다. `implementation`의 carry sidecar와 `consumers.jsonl`은 stage 간 조율 ledger라 phase root에 남는다. runtime은 이 ledger와 registry 예약을 Stage Lifecycle Snapshot으로 읽어 stage 선택과 handoff eligibility를 계산한다. `release-handoff`는 brief를 받지 않고 prepare가 `release-handoff-input.md`를 생성한다.
142
145
 
143
146
  `runtime/`은 build output이므로 이 흐름을 고칠 때는 source인 `scripts/`, `skills/`, `agents/`, `prompts/`, `templates/`, `validators/`를 수정하고 `npm run build`로 갱신한다.
144
147
 
@@ -164,7 +167,7 @@ flowchart TD
164
167
 
165
168
  중요한 점은 `Use defaults`가 model 기본값을 뜻한다는 것이다. non-implementation task-type에서는 defaults를 골라도 worker roster 질문은 계속 나온다. 반대로 `implementation`은 worker override 질문이 없다. profile default roster와 executor binding을 사용한다.
166
169
 
167
- Worktree 규칙은 phase별로 다르다. `requirements-discovery`부터 `implementation-planning`까지는 task-key worktree를 재사용한다. `implementation`은 task-key worktree를 anchor로 삼되 실제 실행은 stage-key(`stage-<N>`) worktree와 `runs/implementation/stage-<N>/` 산출물에서 한 stage씩 격리한다. `final-verification --stage N`은 해당 implementation stage worktree를 읽기 대상으로 재사용하고, whole-task 모드는 task-key worktree에 stage commit을 자동 통합한 뒤 검증 target을 만든다.
170
+ Worktree 규칙은 phase별로 다르다. `requirements-discovery`부터 `implementation-planning`까지는 task-key worktree를 재사용한다. `implementation`은 task-key worktree를 anchor로 삼되 실제 실행은 stage-key(`stage-<N>`) worktree와 `runs/implementation/stage-<N>/` 산출물에서 한 stage씩 격리한다. `final-verification --stage N`은 해당 implementation stage worktree를 읽기 대상으로 재사용하고, whole-task 모드는 task-key worktree에 stage commit을 자동 통합한 뒤 검증 target을 만든다. Stage Lifecycle Snapshot은 이 저장 구조를 변경하지 않는 read-side view다.
168
171
 
169
172
  ## 8. 주의할 불일치 지점
170
173
 
@@ -58,7 +58,7 @@ sequenceDiagram
58
58
  P->>Plan: file exists?
59
59
  P->>Plan: approval marker regex matches?
60
60
  P->>Plan: unresolved Blocks=approval rows?
61
- P->>Stage: parse Stage Map and recover carry/done rows
61
+ P->>Stage: build Stage Lifecycle Snapshot
62
62
  P->>Reg: read active stage-key reservations
63
63
  P->>Stage: select exactly one ready stage
64
64
  P->>WT: provision stage-N worktree + branch
@@ -94,9 +94,8 @@ Executor만 project file을 mutate할 수 있다. verifier는 같은 worktree에
94
94
  ```mermaid
95
95
  flowchart LR
96
96
  Plan[approved plan<br/>Stage Map] --> Parse[parse stage map]
97
- Parse --> Done[backfill carry<br/>read consumers.jsonl]
98
- Done --> Reserved[read registry<br/>active stage reservations]
99
- Reserved --> Resolve{stage arg}
97
+ Parse --> Snapshot[Stage Lifecycle Snapshot<br/>carry + consumers + reservations]
98
+ Snapshot --> Resolve{stage arg}
100
99
  Resolve -->|auto| Next[lowest ready<br/>not done/started/reserved]
101
100
  Resolve -->|number| Forced[selected stage]
102
101
  Next --> Base[resolve stage base commit]
@@ -106,7 +105,7 @@ flowchart LR
106
105
  Started --> Run[implementation executes one selected stage]
107
106
  ```
108
107
 
109
- stage 선택은 `auto` 또는 숫자다. 다른 task-type에서 `--stage`가 오면 `PrepareError`다. runtime은 `consumers.jsonl`의 `done`/`started`와 registry의 active stage-key를 함께 보고 점유 stage를 제외한다.
108
+ stage 선택은 `auto` 또는 숫자다. 다른 task-type에서 `--stage`가 오면 `PrepareError`다. runtime은 Stage Lifecycle Snapshot에서 `consumers.jsonl`의 `done`/`started`, carry sidecar backfill, registry의 active stage-key를 함께 읽고 점유 stage를 제외한다. Snapshot은 새 저장 파일이 아니라 `stage_targets.py`의 read-side view다.
110
109
 
111
110
  stage worktree base는 dependency 형태로 정한다. 독립 stage는 첫 implementation 진입 때 고정한 task-key worktree HEAD를 anchor로 삼고, 단일 의존 stage는 선행 stage의 done `head_commit`에서 분기한다. 다중 의존 stage는 모든 선행 done commit이 task-key worktree HEAD의 ancestor인지 확인한 뒤 그 HEAD에서 분기한다.
112
111
 
@@ -39,7 +39,7 @@ flowchart TD
39
39
  Confirm --> Render[render-bundle]
40
40
  ```
41
41
 
42
- `release-handoff`는 worker roster prompt가 없다. wizard의 `render_args()`는 `pr-template-path`를 release-handoff일 때만 포함하고, runtime은 worker list를 강제로 empty로 만든다. scope 선택은 prepare 전에 끝난다. whole-task는 accepted whole-task verification report가 있어야 하고, stage-group은 accepted single-stage verification으로 `verified` 처리됐지만 아직 `pr`로 덮이지 않은 stage만 후보가 된다.
42
+ `release-handoff`는 worker roster prompt가 없다. wizard outcome의 `renderArgs`는 `pr-template-path`를 release-handoff일 때만 포함하고, runtime은 worker list를 강제로 empty로 만든다. scope 선택은 prepare 전에 끝나며, project/global 저장은 `outcome.persistActions[]`의 `config.set pr-template-path` action으로 `render-bundle` 전에 실행된다. whole-task는 accepted whole-task verification report가 있어야 하고, stage-group은 Stage Lifecycle Snapshot에서 accepted single-stage verification으로 `verified` 처리됐지만 아직 `pr`로 덮이지 않은 stage만 후보가 된다.
43
43
 
44
44
  주의할 점은 이 phase도 task worktree provisioning 대상이라는 것이다. 정상 흐름은 같은 task-key의 implementation/final-verification 결과를 재사용한다. 새 task로 시작하면 새 branch가 만들어질 수 있고, entry gate의 "implementation commit exists" 조건에서 막힐 가능성이 높다.
45
45
 
@@ -54,7 +54,7 @@ sequenceDiagram
54
54
  participant FS as task artifacts
55
55
 
56
56
  W->>P: task-type=release-handoff, approved-plan, stages csv, optional pr-template-path
57
- P->>P: enforce stage eligibility (consumers verified/pr rows)
57
+ P->>P: enforce stage eligibility (Stage Lifecycle Snapshot)
58
58
  P->>FS: generate release-handoff-input.md (cited verification reports)
59
59
  P->>P: force workers=[]
60
60
  P->>T: resolve PR template
@@ -90,7 +90,7 @@ lead는 사용자에게 push/PR 여부를 묻기 전에 다음을 확인한다.
90
90
 
91
91
  - prepare 가 생성한 input 문서(`release-handoff-input.md`)의 `## Source Verification Report` 가 모드(`HANDOFF_MODE`)와 인용 보고서 표를 담고 있다. brief 는 entry phase 의 입력물이라 release-handoff 에는 없다 — 사용자의 stage 선택은 wizard `handoff_stage_pick` 또는 CLI `--stages` 로 prepare 전에 끝난다.
92
92
  - whole-task mode에서는 인용 report가 `verificationScope=whole-task`이고 `Verdict Token = accepted`여야 한다.
93
- - stage-group mode에서는 인용된 각 single-stage report가 `Verdict Token = accepted`여야 하며, prepare/`okstra handoff assemble`이 eligibility와 dependency closure를 다시 강제한다.
93
+ - stage-group mode에서는 인용된 각 single-stage report가 `Verdict Token = accepted`여야 하며, prepare/`okstra handoff assemble`이 Stage Lifecycle Snapshot 기반 eligibility와 dependency closure를 다시 강제한다.
94
94
  - working tree가 clean이다.
95
95
  - 현재 branch가 `main`, `master`, `prod`, `preprod`, `staging`, `dev` 같은 base branch가 아니다.
96
96
  - `<base>..HEAD` commit range가 비어 있지 않다.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okstra",
3
- "version": "0.109.0",
3
+ "version": "0.111.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.109.0",
3
- "builtAt": "2026-07-02T07:00:18.587Z",
2
+ "package": "0.111.0",
3
+ "builtAt": "2026-07-03T10:57:28.170Z",
4
4
  "repoRoot": "/home/runner/work/okstra/okstra"
5
5
  }
@@ -136,6 +136,7 @@ This wrapper does NOT invoke MCP tools directly. MCP availability inside the Ant
136
136
  - The assigned model execution value is canonical for CLI execution. Do not substitute a different Antigravity model unless the task bundle explicitly changes it.
137
137
  - Pass the prompt received from Lead directly to agy after persisting the exact prompt to the assigned path.
138
138
  - **Executor preflight forwarding check (implementation runs only).** When the lead prompt assigns this dispatch the `Executor` role for an `implementation` run, the persisted prompt body MUST contain the literal heading `Coding-conventions preflight` (the lead appends the body of `prompts/profiles/_coding-conventions-preflight.md` into the dispatch prompt — see `prompts/profiles/_implementation-executor.md` → "Pre-implementation context exploration") — the Antigravity CLI does not share the lead's context, so an unforwarded gate never reaches the process that writes the code. If the heading is absent, return `ANTIGRAVITY_PREFLIGHT_MISSING: executor dispatch prompt lacks the coding-conventions preflight block` instead of invoking the CLI; the lead is responsible for re-dispatching with the block included. This check does NOT apply to verifier or analysis dispatches.
139
+ - **Executor post-write gate forwarding check (implementation runs only).** For the same reason — the Antigravity CLI does not share the lead's context — an `implementation` `Executor` dispatch prompt MUST also carry the two post-write gate bodies the lead appends after the preflight (via `codex_dispatch.py` `_implementation_executor_tail`): the persisted prompt body MUST contain BOTH the literal heading `Pre-commit diff review sweep` (from `prompts/profiles/_implementation-diff-review.md`) and the literal heading `Implementation self-check` (from `prompts/profiles/_implementation-self-check.md`). If either heading is absent, return `ANTIGRAVITY_POSTWRITE_GATE_MISSING: executor dispatch prompt lacks the post-write diff-review / self-check gate block` instead of invoking the CLI; the lead re-dispatches with both blocks included. This check does NOT apply to verifier or analysis dispatches.
139
140
  - Include context (code, diff, file paths) if provided.
140
141
  - For long prompts, dispatch through the wrapper with literal absolute paths (plus the worktree path for implementation phase):
141
142
  ```bash
@@ -136,6 +136,7 @@ This wrapper does NOT invoke MCP tools directly. MCP availability inside the Cod
136
136
  - The assigned model execution value is canonical for CLI execution. Do not substitute a different Codex model unless the task bundle explicitly changes it.
137
137
  - Pass the prompt received from Lead directly to codex after persisting the exact prompt to the assigned path.
138
138
  - **Executor preflight forwarding check (implementation runs only).** When the lead prompt assigns this dispatch the `Executor` role for an `implementation` run, the persisted prompt body MUST contain the literal heading `Coding-conventions preflight` (the lead appends the body of `prompts/profiles/_coding-conventions-preflight.md` into the dispatch prompt — see `prompts/profiles/_implementation-executor.md` → "Pre-implementation context exploration") — the Codex CLI does not share the lead's context, so an unforwarded gate never reaches the process that writes the code. If the heading is absent, return `CODEX_PREFLIGHT_MISSING: executor dispatch prompt lacks the coding-conventions preflight block` instead of invoking the CLI; the lead is responsible for re-dispatching with the block included. This check does NOT apply to verifier or analysis dispatches.
139
+ - **Executor post-write gate forwarding check (implementation runs only).** For the same reason — the Codex CLI does not share the lead's context — an `implementation` `Executor` dispatch prompt MUST also carry the two post-write gate bodies the lead appends after the preflight (via `codex_dispatch.py` `_implementation_executor_tail`): the persisted prompt body MUST contain BOTH the literal heading `Pre-commit diff review sweep` (from `prompts/profiles/_implementation-diff-review.md`) and the literal heading `Implementation self-check` (from `prompts/profiles/_implementation-self-check.md`). If either heading is absent, return `CODEX_POSTWRITE_GATE_MISSING: executor dispatch prompt lacks the post-write diff-review / self-check gate block` instead of invoking the CLI; the lead re-dispatches with both blocks included. This check does NOT apply to verifier or analysis dispatches.
139
140
  - Include context (code, diff, file paths) if provided.
140
141
  - For long prompts, dispatch through the wrapper with literal absolute paths (plus the worktree path for implementation phase):
141
142
  ```bash
@@ -656,12 +656,12 @@ The verdict tokens `AGREE` / `DISAGREE` / `SUPPLEMENT` are reused, but their mea
656
656
 
657
657
  - **AGREE**: the item is executable as written *and* internally consistent with other items in the plan.
658
658
  - **DISAGREE(<kind>)**: the item is broken. `<kind>` MUST be one of:
659
- - `a` — referenced file path / symbol mismatches another step or option's File Structure list
660
- - `b` — command is not executable or is ambiguous
659
+ - `a` — a concrete referenced file path / symbol **contradicts** a different concrete path / symbol for the same artifact in another step or option's File Structure list (a genuine mismatch between two spelled-out references). An abbreviated / ellipsis (`…`) / under-specified path is NOT kind `a` — it contradicts nothing, it is merely imprecise notation; classify it as `b`.
660
+ - `b` — a command **or a referenced path** is not executable or is ambiguous — including an abbreviated, ellipsis, or under-specified path that does not resolve as written
661
661
  - `c` — validation signal is not observable
662
662
  - `d` — rollback violates commit / dependency order
663
663
  - `e` — item contradicts the trade-off matrix
664
- - `f` — requirement coverage row cites no concrete option / stage / step, cites a non-existent option / stage / step, or marks a requirement `covered` while the cited plan item does not satisfy the row's stated requirement
664
+ - `f` — requirement coverage row cites no concrete option / stage / step, cites a non-existent option / stage / step, or marks a requirement `covered` while the cited plan item does not satisfy the row's stated requirement. A row that cites an existing option / stage / step is concrete for this purpose even if that option's File Structure paths are abbreviated — path imprecision inside the cited option is kind `b` on that option's own item, not `f` on the coverage row.
665
665
  - **SUPPLEMENT**: the item is sound but is missing a dependency / edge case / precondition.
666
666
 
667
667
  Worker non-result handling (`timeout`, `error`, no result file, wrapper `cli-failure`) is identical to finding convergence: do NOT aggregate as DISAGREE, record `contract-violation`, and apply the round-level abort rule below.
@@ -679,7 +679,7 @@ When `config.adversarial == true` (the default for `implementation-planning`; se
679
679
  - The burden of proof sits on the plan: an item earns `AGREE` only if the verifier actively tried to break it and could not.
680
680
  - The verifier MUST open the file paths / symbols / commands the item cites and confirm they exist and are executable as written. This is the one allowed widening of the lightweight "judge from internal consistency and stated commands / paths" rule — confirming the existence of cited paths is not "re-analyzing the original requirements".
681
681
  - If a cited path / command / validation signal cannot be confirmed, the verifier responds `DISAGREE(<kind>)` with the applicable breakage kind (a–e); uncertainty resolves toward DISAGREE, not AGREE.
682
- - **Single-vote-blocking kinds.** A single `DISAGREE` is approval-blocking on its own — no majority needed — when the breakage kind is `a` (cited path/symbol mismatch) or `d` (rollback violates commit/dependency order) on *any* plan item, or `f` (requirement-coverage mismatch) on a `P-Req-*` item. These defects are concrete, safety-critical, and adversarially verifiable (the verifier confirmed the cited path / order / requirement), so one correct dissent must not be outvoted. Each creates a `majority-disagree` classification and MUST become a `Blocks=approval` clarification row. Kinds `b` / `c` / `e` still need a majority — `b` especially is prone to planning-vs-implementation environment false positives. **Enforced:** `validators/validate-run.py` `_classify_plan_item_gate` (`_SINGLE_VOTE_BLOCKING_KINDS = {a, d}` + the P-Req `f` rule).
682
+ - **Single-vote-blocking kinds.** A single `DISAGREE` is approval-blocking on its own — no majority needed — when the breakage kind is `a` (cited path/symbol mismatch) or `d` (rollback violates commit/dependency order) on *any* plan item, or `f` (requirement-coverage mismatch) on a `P-Req-*` item. These defects are concrete, safety-critical, and adversarially verifiable (the verifier confirmed the cited path / order / requirement), so one correct dissent must not be outvoted. Each creates a `majority-disagree` classification and MUST become a `Blocks=approval` clarification row. Kinds `b` / `c` / `e` still need a majority — `b` especially is prone to planning-vs-implementation environment false positives. Because `a` is reserved for a concrete contradiction between two spelled-out references (see §"Plan-body verdict semantics"), an abbreviated / ellipsis / under-specified path is raised as `b` (majority-gated), never `a` — a lone "this path is abbreviated" dissent must not single-vote-block on notation alone, and it is especially not blocking on a *rejected* option that will never be implemented. **Enforced:** `validators/validate-run.py` `_classify_plan_item_gate` (`_SINGLE_VOTE_BLOCKING_KINDS = {a, d}` + the P-Req `f` rule).
683
683
 
684
684
  Plan-body verification stays **lightweight** even under this posture — the `verificationMode = "full-reanalysis"` forcing in §"Adversarial Verification Mode" applies to finding convergence only (see §"Mode constraint"); the adversarial posture here only changes verifier behaviour, not the mode. This raises verification *quality* (active refutation, plan-side burden). The gate *threshold* stays majority-based for the majority-gated kinds (`b`/`c`/`e`), with the single-vote-blocking exception above for the concrete, safety-critical kinds (`a`/`d`, and `f` on P-Req). A majority requires at least two participating (non-error) votes, so a lone surviving `DISAGREE` whose peer returned a non-result does NOT block on a majority-gated kind — a worker failure must not make the gate stricter than a healthy roster would.
685
685
 
@@ -767,12 +767,12 @@ verdict:
767
767
  - **AGREE**: The item is executable as written and internally consistent with
768
768
  other items in the plan.
769
769
  - **DISAGREE(<kind>)**: The item is broken. Cite which kind:
770
- (a) referenced file path / symbol mismatches another step or option,
771
- (b) command is not executable or is ambiguous,
770
+ (a) a concrete referenced file path / symbol contradicts a different concrete path / symbol for the same artifact elsewhere — a genuine mismatch; an abbreviated / ellipsis path is NOT (a), use (b),
771
+ (b) command or referenced path is not executable or is ambiguous — including an abbreviated / ellipsis / under-specified path that does not resolve as written,
772
772
  (c) validation signal is not observable,
773
773
  (d) rollback violates commit / dependency order,
774
774
  (e) item contradicts the trade-off matrix,
775
- (f) requirement coverage row does not actually map the stated requirement to a concrete satisfying option / stage / step.
775
+ (f) requirement coverage row does not map the stated requirement to a concrete satisfying option / stage / step — citing an existing option counts as concrete even if that option's paths are abbreviated (that is (b) on the option's item, not (f)).
776
776
  - **SUPPLEMENT**: The item is sound but a dependency / edge case / precondition
777
777
  is missing.
778
778
 
@@ -104,7 +104,7 @@ profile document.
104
104
  The labels `Ticket:` / `Kind:` / `Blocks:` / `Status:` stay English in every locale so the approval-gate parser (`clarification_items.parse_meta_cell`) reads them regardless of report language.
105
105
  Profile-specific addenda may tighten cell content but MUST NOT add, remove, rename, or reorder columns, nor change the meta-cell field order. The `ID` is `C-NNN` (3-digit zero-padded), the `Status` ∈ `{open, answered, resolved, obsolete}`, and the `Kind` / `Blocks` legal values are listed below.
106
106
  - section 1 is a **single unified table** per `final-report-template.md`. Every clarification item — whether the user must attach a file, choose between options, or supply a single number/path — is one row of that table. Do not split it into sub-sections (`1.1 추가 자료 요청` / `1.2 사용자 확인 질문` / `5.5.9 Open Questions` are removed and the validator fails reports that reintroduce them), do not create a parallel table elsewhere in the report, and do not duplicate the same item into an approval block or any other section.
107
- - each row's `Kind` column picks one of `{material, decision, data-point}`: `material` for files / snapshots / logs / screenshots the user must attach (the `User input` cell will hold a path or URL); `decision` for choices and yes/no confirmations only the user can make; `data-point` for a single number, ID, date, or short string the user can answer inline. Items that mix "yes/no + file path if yes" are one row of `Kind=material` with the combined expectation written into `Expected form`.
107
+ - each row's `Kind` column picks one of `{material, decision, data-point}`: `material` for files / snapshots / logs / screenshots the user must attach (the `User input` cell will hold a path or URL); `decision` for choices and yes/no confirmations only the user can make; `data-point` for a single number, ID, date, or short string the user can answer inline. A `decision` alternative must be a terminal choice the user can pick as-is; if acting on an alternative still requires the user to supply a concrete value (a path, string, number, or file), that value is its own `data-point` / `material` row — never phrase a data-entry action (e.g. "경로 구체화", "값 입력") as a selectable `decision` option, because the rendered `<select>` cannot capture the value the option demands. Items that mix "yes/no + file path if yes" are one row of `Kind=material` with the combined expectation written into `Expected form`.
108
108
  - each row's `Blocks` column picks one of `{approval, next-phase, none}`. `approval` is reserved for items that gate an approval action, especially the `implementation-planning` `approved:` frontmatter flip; outside `implementation-planning`, unresolved brief reporter-confirmation rows use `next-phase` instead. `next-phase` blocks the next run from starting cleanly. `none` is informational/audit-only.
109
109
  - write every entry in full, descriptive sentences that a non-developer can act on without further context. Avoid abbreviations and internal jargon. The `Statement` cell must state *what* is needed, *why* the answer / attachment changes the next step, and (for `material`) *where* the user can find it and *where* to place it. The `Expected form` cell must state the answer shape (예/아니오, 보기 중 하나, 숫자/날짜, 파일 경로, 짧은 서술 등); supply concrete option choices when applicable.
110
110
  - if a phase requires a recommended answer, alternatives, or an evidence-check note, encode it inside the existing 4-column schema: put evidence notes in `Statement` as `Evidence checked: <path:line>` or `Evidence checked: none — <human-only reason>`, and put recommendations/options in `Expected form` as `Recommended: <answer> — <rationale>; Alternatives: <options>`. When there is more than one alternative, enumerate them as `(a) … (b) …` so each renders as its own selectable option; a single alternative may be written plainly. Do **not** append a pick-one answer-space summary such as `(A / B 중 택1)` or `(… 중 택N)` to `<options>` — the rendered `<select>` already enforces single choice, and that annotation leaks verbatim into an option label. Do not add `Recommended`, `Evidence`, `Alternatives`, or `evidence-checked` columns, and do not break the merged record-meta cell back into separate columns.