okstra 0.75.0 → 0.77.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 (46) hide show
  1. package/README.kr.md +5 -3
  2. package/README.md +5 -3
  3. package/bin/okstra +10 -2
  4. package/docs/kr/architecture.md +1 -1
  5. package/docs/kr/cli.md +20 -4
  6. package/docs/pr-template-usage.md +3 -3
  7. package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +1 -1
  8. package/docs/superpowers/specs/2026-06-12-codex-lead-adapter-design.md +358 -0
  9. package/package.json +1 -1
  10. package/runtime/BUILD.json +2 -2
  11. package/runtime/agents/workers/codex-worker.md +1 -1
  12. package/runtime/agents/workers/gemini-worker.md +1 -1
  13. package/runtime/bin/lib/okstra/cli.sh +5 -1
  14. package/runtime/bin/lib/okstra/globals.sh +1 -0
  15. package/runtime/bin/lib/okstra/usage.sh +6 -4
  16. package/runtime/bin/okstra.sh +1 -0
  17. package/runtime/prompts/launch.template.md +4 -13
  18. package/runtime/prompts/profiles/_coding-conventions-preflight.md +21 -0
  19. package/runtime/prompts/profiles/_implementation-executor.md +3 -6
  20. package/runtime/prompts/profiles/error-analysis.md +6 -0
  21. package/runtime/prompts/profiles/improvement-discovery.md +5 -0
  22. package/runtime/prompts/profiles/release-handoff.md +2 -2
  23. package/runtime/prompts/wizard/prompts.ko.json +12 -4
  24. package/runtime/python/okstra_ctl/analysis_packet.py +17 -0
  25. package/runtime/python/okstra_ctl/codex_dispatch.py +1484 -0
  26. package/runtime/python/okstra_ctl/lead_events.py +129 -0
  27. package/runtime/python/okstra_ctl/paths.py +3 -0
  28. package/runtime/python/okstra_ctl/pr_template.py +1 -1
  29. package/runtime/python/okstra_ctl/render.py +160 -29
  30. package/runtime/python/okstra_ctl/run.py +78 -15
  31. package/runtime/python/okstra_ctl/wizard.py +23 -9
  32. package/runtime/python/okstra_token_usage/codex.py +12 -7
  33. package/runtime/python/okstra_token_usage/collect.py +243 -54
  34. package/runtime/python/okstra_token_usage/gemini.py +12 -7
  35. package/runtime/skills/okstra-setup/SKILL.md +1 -1
  36. package/runtime/validators/validate-run.py +56 -22
  37. package/runtime/validators/validate_session_conformance.py +121 -4
  38. package/src/codex-dispatch.mjs +70 -0
  39. package/src/codex-run.mjs +68 -0
  40. package/src/doctor.mjs +40 -4
  41. package/src/install.mjs +122 -26
  42. package/src/paths.mjs +17 -3
  43. package/src/render-bundle.mjs +2 -0
  44. package/src/runtime-manifest.mjs +26 -0
  45. package/src/uninstall.mjs +26 -4
  46. /package/runtime/{skills/okstra-run/templates → templates/prd}/pr-body.template.md +0 -0
package/README.kr.md CHANGED
@@ -63,6 +63,7 @@ okstra/ npm 패키지 = repo 루트
63
63
  ├── lib/python/ okstra_project/, okstra_ctl/, okstra_token_usage/, lib/
64
64
  ├── bin/ okstra.sh, codex-exec, gemini-exec, ...
65
65
  ├── templates/ report asset, settings template
66
+ ├── installed-runtimes.json 설치된 runtime adapter 매니페스트
66
67
  ├── installed-skills.json 설치된 스킬 매니페스트 (uninstall 이 사용)
67
68
  ├── installed-agents.json 설치된 워커 에이전트 매니페스트 (uninstall 이 사용)
68
69
  ├── recent.jsonl, active.jsonl run 인덱스
@@ -127,7 +128,7 @@ okstra --version # CLI 가 PATH 에 잡혔는지 확인
127
128
  okstra install # 'npx -y okstra@latest install' 와 동일
128
129
  ```
129
130
 
130
- 글로벌 설치는 Node CLI 를 PATH 에 등록할 뿐입니다. 런타임(`~/.okstra/`) 과 Claude 스킬(`~/.claude/skills/`) 은 여전히 `okstra install` 이 생성합니다 — `npm i -g` 에 포함되지 않습니다. 이후 업그레이드: `npm i -g okstra@latest && okstra install`. 글로벌 바이너리 제거: `npm uninstall -g okstra` (`~/.okstra/` 는 그대로; 그것까지 지우려면 `okstra uninstall`).
131
+ 글로벌 설치는 Node CLI 를 PATH 에 등록할 뿐입니다. 런타임(`~/.okstra/`) 과 Claude 스킬(`~/.claude/skills/`) 은 여전히 `okstra install` 이 생성합니다 — `npm i -g` 에 포함되지 않습니다. 실험적 Codex lead adapter 용 공유 runtime 만 설치하려면 `okstra install --runtime codex` 를 사용하세요 (`~/.claude` 자산은 건너뜀). 이후 업그레이드: `npm i -g okstra@latest && okstra install`. 글로벌 바이너리 제거: `npm uninstall -g okstra` (`~/.okstra/` 는 그대로; 그것까지 지우려면 `okstra uninstall`).
131
132
 
132
133
  **글로벌 설치 시 스킬 동작.** 모든 okstra 스킬은 PATH 에 잡힌 `okstra` 를 자동 감지하여 `npx -y okstra@latest` 대신 우선 사용합니다. 즉 글로벌 설치를 해두면 매 스킬 호출(`okstra-run`, `okstra-inspect`, `okstra-schedule`, `okstra-setup` Step 2 의 Step 0) 마다 npx 가 패키지 fetch / 버전 체크하던 비용이 사라집니다. 스킬이 본인이 설치한 버전을 그대로 쓰므로 **업그레이드 타이밍은 사용자가 통제** 합니다 — 더 이상 호출마다 `@latest` 가 강제되지 않습니다. 새 릴리스를 받으려면 원하는 시점에 `npm i -g okstra@latest && okstra install` 을 실행하세요. `okstra` 가 PATH 에 없으면 스킬은 자동으로 npx fallback 으로 동작하므로 글로벌 설치가 없는 환경에서도 변경 없이 그대로 동작합니다.
133
134
 
@@ -189,8 +190,9 @@ Claude Code 세션 밖에서 task 를 시작하려면:
189
190
 
190
191
  - **모든 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/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md`](docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md), [`docs/kr/cli.md#--executor`](docs/kr/cli.md#--executor).
191
192
  - **`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).
192
- - **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/okstra-run/templates/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 가 주석을 제거합니다.
193
+ - **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 가 주석을 제거합니다.
193
194
  - **프로파일 워커 로스터 검증** — `--workers <csv>` 와 okstra-run Step 6 의 워커 prompt 는 해당 프로파일의 `Required workers:` 블록에 선언된 워커 ID 만 허용합니다. 프로파일에 없는 워커 (예: `release-handoff` 에서 `codex` / `gemini`) 를 요청하면 명확한 에러로 거절되고, 인터랙티브 prompt 도 프로파일이 실제로 받는 워커만 보여줍니다.
195
+ - **실험적 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/Gemini 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 로 복제하지 않습니다.
194
196
  - **다단계 `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 를 소비했는지 추적됩니다.
195
197
  - **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` 로 발행되며, gate 가 `blocked-by-disagreement` 또는 `aborted-non-result` 일 때 writer 는 `approved: false` 를 유지해야 하고 (이런 gate 결과로 `approved: true` 로 ship 된 report 는 validator 가 거부), `majority-disagree` 항목을 `## 1. Clarification Items` 의 `Blocks=approval` row 로 변환합니다. 빠른 반복용 opt-out: `--no-plan-verification` (기본값: 활성). 자세한 라운드 프로토콜은 [`skills/okstra-convergence/SKILL.md`](skills/okstra-convergence/SKILL.md) 의 "Plan-body verification mode" 섹션과 [`docs/kr/cli.md#--no-plan-verification`](docs/kr/cli.md#--no-plan-verification).
196
198
  - **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`).
@@ -203,7 +205,7 @@ Claude Code 세션 밖에서 task 를 시작하려면:
203
205
  | 커맨드 | 용도 |
204
206
  |---|---|
205
207
  | `npx -y okstra@latest paths` | 런타임 경로 출력 (`--field <name>` 또는 `--shell`) |
206
- | `npx -y okstra@latest doctor` | 런타임 + 스킬 + python import 진단 |
208
+ | `npx -y okstra@latest doctor [--runtime claude-code\|codex\|all]` | 런타임 + 스킬 + python import 진단. `codex` 는 Claude skill checks 를 제외 |
207
209
  | `npx -y okstra@latest ensure-installed` | Idempotent 체크, stale 이면 자동 재설치 (스킬이 내부적으로 호출) |
208
210
  | `npx -y okstra@latest setup --project-id <id>` | 현재 프로젝트를 등록 (`.okstra/project.json`) |
209
211
  | `npx -y okstra@latest check-project` | 현재 프로젝트가 `setup` 으로 등록됐는지 검증 |
package/README.md CHANGED
@@ -62,6 +62,7 @@ okstra/ npm package = repo root
62
62
  ├── lib/python/ okstra_project/, okstra_ctl/, okstra_token_usage/, lib/
63
63
  ├── bin/ okstra.sh, codex-exec, gemini-exec, ...
64
64
  ├── templates/ report assets, settings template
65
+ ├── installed-runtimes.json manifest of installed runtime adapters
65
66
  ├── installed-skills.json manifest of installed skills (used by uninstall)
66
67
  ├── installed-agents.json manifest of installed worker agents (used by uninstall)
67
68
  ├── recent.jsonl, active.jsonl run index
@@ -126,7 +127,7 @@ okstra --version # confirm the CLI is on PATH
126
127
  okstra install # same as 'npx -y okstra@latest install'
127
128
  ```
128
129
 
129
- The global install only registers the Node CLI on your PATH. The runtime (`~/.okstra/`) and the Claude skills (`~/.claude/skills/`) are still provisioned by `okstra install` — they are not part of `npm i -g`. To upgrade later: `npm i -g okstra@latest && okstra install`. To remove the global binary: `npm uninstall -g okstra` (leaves `~/.okstra/` untouched; remove that with `okstra uninstall`).
130
+ The global install only registers the Node CLI on your PATH. The runtime (`~/.okstra/`) and the Claude skills (`~/.claude/skills/`) are still provisioned by `okstra install` — they are not part of `npm i -g`. To install only the shared runtime for the experimental Codex lead adapter, use `okstra install --runtime codex` (skips `~/.claude` assets). To upgrade later: `npm i -g okstra@latest && okstra install`. To remove the global binary: `npm uninstall -g okstra` (leaves `~/.okstra/` untouched; remove that with `okstra uninstall`).
130
131
 
131
132
  **Skill behaviour with a global install.** All okstra skills auto-detect a PATH-resolved `okstra` and prefer it over `npx -y okstra@latest`. That means a global install removes the per-call npx fetch / version-check from every skill invocation (Step 0 of `okstra-run`, `okstra-inspect`, `okstra-schedule`, `okstra-setup` Step 2). Since the skill uses your globally installed version directly, *you* control upgrade timing — `@latest` is no longer forced on each call. Run `npm i -g okstra@latest && okstra install` whenever you want to pull a new release. If `okstra` is not on PATH the skill silently falls back to npx, so machines without a global install keep working unchanged.
132
133
 
@@ -188,8 +189,9 @@ Recent workflow additions (post-0.8.0, on `main`):
188
189
 
189
190
  - **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), [`docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md`](docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md), and [`docs/kr/cli.md#--executor`](docs/kr/cli.md#--executor).
190
191
  - **`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).
191
- - **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/okstra-run/templates/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.
192
+ - **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.
192
193
  - **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` / `gemini` 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.
194
+ - **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/Gemini 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.
193
195
  - **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.
194
196
  - **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 now 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`; when the gate is `blocked-by-disagreement` or `aborted-non-result` the writer MUST keep it `false` (the validator refuses any report that publishes `approved: true` under such a gate) and convert `majority-disagree` items into `## 1. Clarification Items` rows with `Blocks=approval`. Disable for fast iteration with `--no-plan-verification` (default: enabled). Details: [`skills/okstra-convergence/SKILL.md`](skills/okstra-convergence/SKILL.md) "Plan-body verification mode" and [`docs/kr/cli.md#--no-plan-verification`](docs/kr/cli.md#--no-plan-verification).
195
197
  - **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,7 +204,7 @@ Recent workflow additions (post-0.8.0, on `main`):
202
204
  | Command | Use |
203
205
  |---|---|
204
206
  | `npx -y okstra@latest paths` | Print runtime paths (`--field <name>` or `--shell`) |
205
- | `npx -y okstra@latest doctor` | Diagnose runtime + skills + python import |
207
+ | `npx -y okstra@latest doctor [--runtime claude-code\|codex\|all]` | Diagnose runtime + skills + python import. `codex` skips Claude skill checks |
206
208
  | `npx -y okstra@latest ensure-installed` | Idempotent check, auto-reinstall if stale (skills call this internally) |
207
209
  | `npx -y okstra@latest setup --project-id <id>` | Register the current project (`.okstra/project.json`) |
208
210
  | `npx -y okstra@latest check-project` | Verify the current project has been registered with `setup` |
package/bin/okstra CHANGED
@@ -40,6 +40,11 @@ const COMMANDS = new Map([
40
40
  "render-bundle",
41
41
  () => import("../src/render-bundle.mjs").then((m) => m.run),
42
42
  ],
43
+ ["codex-run", () => import("../src/codex-run.mjs").then((m) => m.run)],
44
+ [
45
+ "codex-dispatch",
46
+ () => import("../src/codex-dispatch.mjs").then((m) => m.run),
47
+ ],
43
48
  ["render-views", () => import("../src/render-views.mjs").then((m) => m.run)],
44
49
  [
45
50
  "render-final-report",
@@ -77,11 +82,11 @@ Usage:
77
82
  okstra <command> [options]
78
83
 
79
84
  Admin commands:
80
- install Install runtime to ~/.okstra and skills to ~/.claude/skills
85
+ install Install runtime; --runtime codex skips ~/.claude assets
81
86
  ensure-installed Verify install is fresh; reinstall if stale (idempotent)
82
87
  uninstall Remove runtime + skills (user data preserved by default)
83
88
  setup Register the current project (.okstra/project.json)
84
- doctor Diagnostic check of the installed runtime
89
+ doctor Diagnostic check; --runtime codex skips Claude skills
85
90
  check-project Verify the current project has been registered with setup
86
91
  config Read / write okstra settings (e.g. PR template path)
87
92
  migrate Move legacy .project-docs/okstra/ to .okstra/ (one-shot)
@@ -97,6 +102,9 @@ Introspection commands (JSON output, used by skills to avoid python heredocs):
97
102
  plan-validate Check an approved-plan file for the approval marker
98
103
  render-bundle Preview prepare_task_bundle() output (forwards to
99
104
  python3 -m okstra_ctl.run --render-only)
105
+ codex-run Prepare a render-only Codex lead task bundle
106
+ (--lead-runtime codex, no worker dispatch)
107
+ codex-dispatch Dispatch CLI-backed workers for a prepared Codex run
100
108
  wizard Drive the okstra-run interactive input state machine
101
109
  (init / step / render-args / confirmation)
102
110
  token-usage Collect token usage for a run (wraps the installed
@@ -18,7 +18,7 @@
18
18
  - **Single python authority**: 모든 prepare wiring(profile/workers/model 해소, path 계산, render, central record_start)이 [`okstra_ctl.run.prepare_task_bundle()`](../../scripts/okstra_ctl/run.py) 한 함수에 모여 있습니다. `okstra.sh` 와 `okstra-run` skill 은 같은 함수를 호출하는 thin caller 이며, 환경 변수로 상태를 전달하지 않습니다 — task 정체성·경로·workflow 상태는 모두 디스크 권위 파일에서 매번 계산됩니다.
19
19
  - **Claude handoff (두 모드)**: (a) `okstra.sh` 가 새 `claude` 프로세스를 띄우는 전통 방식, (b) `okstra-run` skill 이 현재 claude 세션 안에서 prepare 후 lead 역할을 그대로 인계받는 in-session 모드. 둘 다 `prepare_task_bundle` 의 산출물(instruction-set 등)을 그대로 사용합니다.
20
20
  - **Required team contract**: 각 phase profile의 `Required workers:` 블록이 roster의 권위입니다. 일반 분석 phase는 Claude/Codex analyser + report-writer를 기본으로 하고, Gemini는 profile과 `--workers`가 허용할 때만 포함됩니다. `release-handoff`처럼 lead-only에 가까운 phase는 별도 roster를 가집니다.
21
- - **User-home install + project-local task bundles**: `npx okstra@latest install` 한 명령이 런타임(`~/.okstra/{lib/python, bin, templates}`), 스킬 11종(`~/.claude/skills/<name>/SKILL.md`), worker agent 4종(`~/.claude/agents/*-worker.md`)을 설치합니다. 전역 대화 메모리는 프로젝트와 분리된 `~/.okstra/memory-book/` 에 저장됩니다. 대상 프로젝트에는 task bundle 과 discovery metadata 가 `.okstra/` 아래 저장되고, **추가로 `<PROJECT_ROOT>/.claude/settings.local.json` 이 `~/.okstra/templates/settings.local.json` 을 가리키는 symlink 로 provisioning** 됩니다 (`okstra setup` 또는 `okstra-ctl` prepare 가 idempotent 하게 관리; 기존에 일반 파일이 있었다면 `.bak.<timestamp>` 로 백업 후 교체). 이 symlink 가 host Claude Code 세션에 자동 로드되어 codex/gemini worker wrapper 호출 권한을 부여하므로, 사용자의 글로벌 `~/.claude/settings.json` 은 건드리지 않습니다. 개발용 `okstra install --link <repo>` 는 설치 파일을 repo source로 symlink합니다.
21
+ - **User-home install + project-local task bundles**: `npx okstra@latest install` 한 명령이 런타임(`~/.okstra/{lib/python, bin, templates}`), 스킬 11종(`~/.claude/skills/<name>/SKILL.md`), worker agent 4종(`~/.claude/agents/*-worker.md`)을 설치합니다. `--runtime codex` 는 실험적 Codex lead adapter 용 공유 runtime 만 설치하고 `~/.claude` 자산을 건너뜁니다. 전역 대화 메모리는 프로젝트와 분리된 `~/.okstra/memory-book/` 에 저장됩니다. 대상 프로젝트에는 task bundle 과 discovery metadata 가 `.okstra/` 아래 저장되고, **추가로 `<PROJECT_ROOT>/.claude/settings.local.json` 이 `~/.okstra/templates/settings.local.json` 을 가리키는 symlink 로 provisioning** 됩니다 (`okstra setup` 또는 `okstra-ctl` prepare 가 idempotent 하게 관리; 기존에 일반 파일이 있었다면 `.bak.<timestamp>` 로 백업 후 교체). 이 symlink 가 host Claude Code 세션에 자동 로드되어 codex/gemini worker wrapper 호출 권한을 부여하므로, 사용자의 글로벌 `~/.claude/settings.json` 은 건드리지 않습니다. 개발용 `okstra install --link <repo>` 는 설치 파일을 repo source로 symlink합니다.
22
22
  - **Resume and clarification**: `--task-key`, `--resume-clarification`, `--clarification-response`로 같은 task 재개와 lead의 추가 질문 응답 흐름을 지원합니다.
23
23
  - **Derived views and telemetry**: final-report data.json → Markdown → slim MD / self-contained HTML view, worker error sidecar, wrapper log sidecar, token usage / cost accounting을 제공합니다.
24
24
 
package/docs/kr/cli.md CHANGED
@@ -22,6 +22,7 @@
22
22
  - [`--directive`](#--directive)
23
23
  - [`--fix-cycle`](#--fix-cycle)
24
24
  - [`--workers`](#--workers)
25
+ - [`--lead-runtime`](#--lead-runtime)
25
26
  - [`--claude-model`](#--claude-model)
26
27
  - [`--lead-model`](#--lead-model)
27
28
  - [`--codex-model`](#--codex-model)
@@ -52,7 +53,7 @@
52
53
  기본 명령(첫 진입 / full args):
53
54
 
54
55
  ```bash
55
- scripts/okstra.sh [--render-only] [--yes] [--no-plan-verification] --task-type <task-type> [--workers worker1,worker2] [--lead-model <model>] [--claude-model <model>] [--codex-model <model>] [--gemini-model <model>] [--report-writer-model <model>] [--executor claude|codex|gemini] [--critic off|claude|codex|gemini] [--related-tasks taskA,taskB] [--work-category bugfix|feature|refactor|ops|improvement|unknown] [--base-ref <branch|tag|sha>] [--clarification-response <previous-final-report>] [--approved-plan <plan-path>] [--approve] --project-id <project-id> --task-group <task-group> --task-id <task-id> --task-brief <brief-path> [--directive <directive>] [--fix-cycle <yes|no>]
56
+ scripts/okstra.sh [--render-only] [--yes] [--no-plan-verification] --task-type <task-type> [--workers worker1,worker2] [--lead-runtime claude-code|codex] [--lead-model <model>] [--claude-model <model>] [--codex-model <model>] [--gemini-model <model>] [--report-writer-model <model>] [--executor claude|codex|gemini] [--critic off|claude|codex|gemini] [--related-tasks taskA,taskB] [--work-category bugfix|feature|refactor|ops|improvement|unknown] [--base-ref <branch|tag|sha>] [--clarification-response <previous-final-report>] [--approved-plan <plan-path>] [--approve] --project-id <project-id> --task-group <task-group> --task-id <task-id> --task-brief <brief-path> [--directive <directive>] [--fix-cycle <yes|no>]
56
57
  ```
57
58
 
58
59
  후속 phase 단축 형식(기존 task-manifest.json이 존재할 때):
@@ -307,6 +308,19 @@ scripts/okstra.sh --task-type implementation-planning ... \
307
308
  scripts/okstra.sh --task-type implementation-planning --workers claude,codex --project-id jobs --task-group tasks --task-id 8852 --task-brief .project-docs/tasks/8852/BUG_REPORT.md
308
309
  ```
309
310
 
311
+ ### `--lead-runtime`
312
+
313
+ Lead 실행 adapter 를 지정합니다. 기본값은 `claude-code` 입니다.
314
+
315
+ - `claude-code`: 현재 기본 실행 경로입니다. Claude Code lead 가 `TeamCreate` / `Agent(...)` / Claude session jsonl 기반으로 worker dispatch 와 사용량 집계를 수행합니다.
316
+ - `codex`: Codex lead adapter 용 runtime marker 입니다. `okstra codex-run` 이 `--render-only --lead-runtime codex` 를 소유해 task bundle 을 준비하고, 준비된 run manifest 는 `okstra codex-dispatch` 로 CLI-backed worker 실행에 넘길 수 있습니다.
317
+
318
+ Codex lead dry-run 은 `okstra codex-run <args...>` 를 쓰면 됩니다. 이 명령은 `--render-only --lead-runtime codex` 를 직접 붙이고, worker dispatch 없이 준비된 task bundle 과 lead prompt 를 출력합니다.
319
+ 생성된 team-state / run-manifest / task-manifest 는 `leadEventsPath` 로 `runs/<task-type>/state/lead-events-<task-type>-<seq>.jsonl` 를 가리키며, render 단계는 `bundle-prepared` event 를 기록합니다.
320
+ 이후 `okstra codex-dispatch --project-root <dir> --run-manifest <run-manifest> --workers codex[,gemini[,report-writer]]` 가 기존 CLI wrapper 기반 worker 를 실행합니다. `--workers` 를 생략하면 run roster 중 Codex-side 지원 worker(`codex`, `gemini`, opt-in 된 `report-writer`)만 자동 선택하고, `claude` 처럼 지원하지 않는 worker 를 명시 요청하면 실패합니다. `report-writer` 는 명시 opt-in (`--enable-codex-report-writer --report-writer-codex-model <model>`) 이 필요하며, 성공 시 token-usage substitution → render-views → spawn-followups → validate-run 후처리를 순서대로 수행합니다.
321
+
322
+ Codex worker(`--workers codex`, `--codex-model`)와 Codex lead runtime 은 별개입니다. 전자는 Claude Code lead 가 dispatch 하는 worker provider 선택이고, 후자는 lead 자체를 Codex adapter 로 실행하기 위한 상위 runtime 경계입니다.
323
+
310
324
  > 모든 `--*-model` 플래그는 `scripts/okstra_ctl/models.py` 의 provider 별 mapping 에 등록된 alias 만 허용합니다. 등록되지 않은 값은 `UnknownModelError` 로 즉시 거부됩니다 (manifest 의 `modelExecutionValue` 와 실제 실행값 불일치로 인한 contract-violation 을 사전에 차단). 허용값:
311
325
  > - Claude (`--lead-model` / `--claude-model` / `--report-writer-model`): `fable`, `fable-5`, `claude-fable-5`, `opus`, `opus-4-8`, `claude-opus-4-8`, `opus-4-7`, `claude-opus-4-7`, `opus-4-6`, `claude-opus-4-6`, `sonnet`, `sonnet-4-6`, `claude-sonnet-4-6`, `haiku`, `haiku-4-5`, `claude-haiku-4-5`, `claude-haiku-4-5-20251001`
312
326
  > - Codex (`--codex-model`): `gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.3-codex`, `gpt-5.2`, `codex-auto-review`
@@ -592,10 +606,10 @@ chmod +x ~/.local/bin/okstra-ctl
592
606
  | 명령 | 용도 |
593
607
  |---|---|
594
608
  | `okstra paths [--field <name>\|--shell]` | package/runtime/home/bin/pythonpath/version 경로 출력 |
595
- | `okstra install [--refresh\|--dry-run\|--link <repo>]` | runtime, templates, skills, agents 설치/갱신 |
596
- | `okstra ensure-installed [-q]` | 설치 상태 확인, stale이면 재설치 |
609
+ | `okstra install [--runtime claude-code\|codex\|all] [--refresh\|--dry-run\|--link <repo>]` | runtime, templates, skills, agents 설치/갱신. 기본값 `claude-code` 는 기존처럼 Claude skills/agents 까지 설치한다. `codex` 는 공유 runtime 만 설치하고 `~/.claude` 자산을 건드리지 않는다 |
610
+ | `okstra ensure-installed [--runtime claude-code\|codex\|all] [-q]` | 설치 상태 확인, stale이면 같은 runtime 으로 재설치. `codex` runtime 은 Claude skills/agents drift 검사를 건너뛴다 |
597
611
  | `okstra uninstall [--purge -y]` | 설치 자산 제거. 기본값은 사용자 데이터 보존 |
598
- | `okstra doctor` | runtime + Python import + skill/agent 설치 진단 |
612
+ | `okstra doctor [--runtime claude-code\|codex\|all]` | runtime + Python import + skill/agent 설치 진단. `codex` runtime 은 Claude skill checks 를 제외한다 |
599
613
  | `okstra setup --project-id <id>` | 현재 프로젝트의 `.okstra/project.json` 생성/갱신 |
600
614
  | `okstra check-project [--json]` | 현재 프로젝트가 등록되었는지 검증 |
601
615
  | `okstra config <get\|set\|unset\|show> [key] [value] [--scope project\|global\|all]` | 영구 설정 관리 (예: `pr-template-path`). 원자적 JSON 쓰기 |
@@ -606,6 +620,8 @@ chmod +x ~/.local/bin/okstra-ctl
606
620
  | `okstra worktree-lookup <task-key>` | `worktree_registry.lookup` 결과 (예약된 path / branch / base ref / 현재 상태) |
607
621
  | `okstra plan-validate <plan-path>` | `_validate_approved_plan` — frontmatter `approved` 인식 결과와 Blocks=approval 미해결 행 진단 |
608
622
  | `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 문서를 자동 생성한다 |
623
+ | `okstra codex-run <args…>` | Codex lead adapter dry-run entrypoint. `render-bundle` 과 같은 인자를 받되 `--render-only --lead-runtime codex` 를 wrapper 가 소유한다. task bundle 을 준비하고 Codex lead 가 읽을 prompt 를 출력하지만 worker dispatch 는 하지 않는다 |
624
+ | `okstra codex-dispatch --project-root <dir> --run-manifest <path> [--workers codex,gemini,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 을 자동 실행한다 |
609
625
  | `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 를 검사 |
610
626
  | `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)으로 진입합니다 |
611
627
  | `okstra token-usage ...` | 설치된 `okstra-token-usage.py` 를 감싸 run token usage 수집/치환을 수행. 세션 jsonl 은 기본적으로 `$OKSTRA_HOME/cache/token-usage/` 의 byte cursor 캐시로 증분 스캔하며, `--no-cache` 로 캐시를 우회해 전체 재스캔을 강제할 수 있음(정확성 폴백) |
@@ -19,8 +19,8 @@
19
19
 
20
20
  ## 2. default 후보 경로
21
21
 
22
- 1. `$OKSTRA_SKILLS_DIR/okstra-run/templates/pr-body.template.md` — 환경변수 `OKSTRA_SKILLS_DIR` 가 설정돼 있을 때만.
23
- 2. `~/.claude/skills/okstra-run/templates/pr-body.template.md` — `npx okstra install` 이 깔아두는 표준 위치.
22
+ 1. `$OKSTRA_SKILLS_DIR/templates/prd/pr-body.template.md` — 환경변수 `OKSTRA_SKILLS_DIR` 가 설정돼 있을 때만.
23
+ 2. `~/.claude/skills/templates/prd/pr-body.template.md` — `npx okstra install` 이 깔아두는 표준 위치.
24
24
 
25
25
  후보들은 우선순위 순서대로 시도되며, 모두 부재 시 다음과 같이 명시적인 에러로 끝난다.
26
26
 
@@ -28,7 +28,7 @@
28
28
 
29
29
  ## 3. 소스 리포지토리 안 원본
30
30
 
31
- - [`skills/okstra-run/templates/pr-body.template.md`](../skills/okstra-run/templates/pr-body.template.md) — `npx okstra install` 이 §2 의 default 위치로 복사하는 원본. 카피를 바꾸고 싶으면 이 파일을 수정한 뒤 다시 install 한다.
31
+ - [`skills/templates/prd/pr-body.template.md`](../templates/prd/pr-body.template.md) — `npx okstra install` 이 §2 의 default 위치로 복사하는 원본. 카피를 바꾸고 싶으면 이 파일을 수정한 뒤 다시 install 한다.
32
32
 
33
33
  ## 4. 설정 명령 — 영속화
34
34
 
@@ -25,7 +25,7 @@
25
25
  | Python 호출자 (하드코드) | ~15 | `scripts/okstra_ctl/{render,run,seeding,wizard,worktree,backfill,pr_template,sequence}.py`, `okstra-spawn-followups.py`, `okstra_token_usage/collect.py`, `validators/validate-*.py` |
26
26
  | Shell 스크립트 | 5 | `scripts/lib/okstra/{interactive,project-resolver,usage}.sh`, `scripts/lib/okstra-ctl/cmd-rerun.sh`, `validators/{lib/paths,lib/fixtures,validate-brief,validate-workflow}.sh` |
27
27
  | 스킬 / 프로필 / 에이전트 | 13 | `skills/okstra-*/SKILL.md`, `prompts/profiles/*.md`, `agents/{SKILL.md,workers/claude-worker.md}` |
28
- | 템플릿 | 4 | `templates/okstra.CLAUDE.md`, `templates/reports/{brief,task-brief}.template.md`, `skills/okstra-run/templates/pr-body.template.md` |
28
+ | 템플릿 | 4 | `templates/okstra.CLAUDE.md`, `templates/reports/{brief,task-brief}.template.md`, `skills/templates/prd/pr-body.template.md` |
29
29
  | 테스트 | ~20 | `tests/test_okstra_*.py`, `tests-e2e/scenario-*.sh` 2개 |
30
30
  | 문서 | ~12 | `README{,.kr}.md`, `CLAUDE.md`, `docs/kr/{architecture,cli}.md`, `docs/project-structure-overview.md`, `docs/task-process/common-flow.md`, `docs/superpowers/plans/*` |
31
31
  | 제외 | — | `graphify-out/` (다음 update 시 재생성), `.project-docs/2026-05-10/feature-checklist.md` (okstra 무관) |
@@ -0,0 +1,358 @@
1
+ # Claude Code / Codex lead adapter split design
2
+
3
+ - 날짜: 2026-06-12
4
+ - 상태: 설계 초안
5
+ - 대상: okstra runtime, installed skills, lead orchestration contract
6
+
7
+ ## 1. 배경
8
+
9
+ okstra 의 core runtime 은 이미 비교적 플랫폼 중립적이다.
10
+ `prepare_task_bundle()` 이 task bundle, manifests, prompts, worktree,
11
+ validators 를 생성하고, Node CLI 는 이 Python core 를 호출한다.
12
+
13
+ 문제는 lead 실행 계층이 Claude Code 전용 계약을 강하게 전제한다는 점이다.
14
+
15
+ - skills 는 `~/.claude/skills/` 에 설치된다.
16
+ - worker agents 는 `~/.claude/agents/` 에 설치된다.
17
+ - in-session run 은 `AskUserQuestion` 과 Claude Code slash skill 흐름을 전제한다.
18
+ - team execution 은 `TeamCreate` / `Agent(...)` / `team_name` 을 전제한다.
19
+ - resume, token usage, team reconcile 은 Claude session jsonl 과
20
+ `~/.claude/projects`, `~/.claude/teams` 를 읽는다.
21
+
22
+ 따라서 Codex 에서 같은 저장소를 사용하려면 프로젝트를 통째로 둘로 복사하는 대신
23
+ **lead adapter** 를 나눠야 한다.
24
+
25
+ ## 2. 결정
26
+
27
+ okstra 는 하나의 공통 core 와 두 lead adapter 로 분리한다.
28
+
29
+ ```text
30
+ okstra core
31
+ - prepare_task_bundle
32
+ - task/run manifests
33
+ - worktree registry
34
+ - final-report schema/render/validators
35
+ - wizard state machine
36
+ - worker result / convergence schemas
37
+
38
+ lead adapters
39
+ - claude-code adapter
40
+ - codex adapter
41
+ ```
42
+
43
+ Claude Code adapter 는 현재 동작을 유지한다. Codex adapter 는 Claude Teams 를
44
+ 흉내내지 않고 Codex 가 제공하는 방식으로 같은 artifact contract 를 채운다.
45
+
46
+ ## 3. 비목표
47
+
48
+ - `prepare_task_bundle()` 를 Claude/Codex 별로 복제하지 않는다.
49
+ - phase profile, schema, validator 를 provider 별로 fork 하지 않는다.
50
+ - Codex adapter 가 Claude Code 의 `TeamCreate` 나 `Agent(...)` 를 동일하게
51
+ 재현한다고 주장하지 않는다.
52
+ - 기존 Claude Code slash skill UX 를 깨지 않는다.
53
+
54
+ ## 4. Adapter 경계
55
+
56
+ ### 4.1 공통 core 로 남길 것
57
+
58
+ | 영역 | 이유 |
59
+ |---|---|
60
+ | `scripts/okstra_ctl/run.py::prepare_task_bundle` | task identity 와 artifact layout 의 single authority |
61
+ | `scripts/okstra_ctl/worktree*.py` | provider 와 무관한 격리/동시성 계약 |
62
+ | `scripts/okstra_ctl/workers.py` | phase profile 이 허용하는 logical roster 검증 |
63
+ | `scripts/okstra_ctl/render*.py` | manifests, prompts, final report rendering |
64
+ | `schemas/`, `validators/`, `templates/` | output contract 의 SSOT |
65
+ | `prompts/profiles/*.md` | lifecycle phase 규칙의 SSOT |
66
+
67
+ ### 4.2 Claude Code adapter 로 남길 것
68
+
69
+ | 영역 | 현재 결합 |
70
+ |---|---|
71
+ | installed skills | `~/.claude/skills/okstra-*` |
72
+ | installed agents | `~/.claude/agents/*-worker.md` |
73
+ | interactive UI | `AskUserQuestion` |
74
+ | worker dispatch | `TeamCreate`, `Agent(...)`, `team_name` |
75
+ | resume | `claude --resume <session-id>` |
76
+ | session accounting | Claude session jsonl, `~/.claude/projects` |
77
+ | team cleanup | `~/.claude/teams`, `TeamDelete` |
78
+
79
+ ### 4.3 Codex adapter 로 새로 둘 것
80
+
81
+ Codex adapter 는 다음을 담당한다.
82
+
83
+ | 책임 | Codex 방식 |
84
+ |---|---|
85
+ | input collection | CLI wizard JSON 을 Codex 대화/질문으로 relay |
86
+ | task bundle prepare | 기존 `okstra render-bundle` / `prepare_task_bundle()` 호출 |
87
+ | lead progress logging | `PROGRESS:` line 을 assistant text + run artifact 에 기록 |
88
+ | worker fan-out | Codex sub-agent tool, or CLI wrapper process, or sequential fallback |
89
+ | worker result persistence | 기존 `worker-results/*.md` contract 에 맞춰 파일 작성 |
90
+ | convergence | 기존 `okstra-convergence` 알고리즘을 lead-local 로 실행 |
91
+ | report writing | report-writer worker 가 없으면 explicit fallback status 를 기록한 뒤 lead-authored path 사용, 또는 Codex 전용 report-writer role 을 정의 |
92
+ | resume | Codex session resume 가 아니라 run artifact checkpoint 기준 재진입 |
93
+
94
+ ## 5. Execution modes
95
+
96
+ ### 5.1 `leadRuntime=claude-code`
97
+
98
+ 현재 기본값이다.
99
+
100
+ - 설치: `okstra install` 이 `~/.claude/skills` 와 `~/.claude/agents` 를 채운다.
101
+ - 실행: slash skill 또는 `okstra.sh` 가 Claude lead 를 시작한다.
102
+ - worker dispatch: `TeamCreate` / `Agent(...)`.
103
+ - validator: 기존 session conformance 를 그대로 적용한다.
104
+
105
+ ### 5.2 `leadRuntime=codex`
106
+
107
+ 신규 모드다.
108
+
109
+ - 설치: Claude assets 는 선택 설치로 바꾸고, Codex adapter assets 를 별도 설치한다.
110
+ - 실행: `okstra codex-run` 또는 `okstra run --lead-runtime codex`.
111
+ - worker dispatch:
112
+ - 가능한 경우 Codex sub-agent fan-out 사용.
113
+ - 불가능하면 CLI wrapper 또는 sequential local analysis 로 degrade.
114
+ - team-state 는 Claude team fields 대신 `leadRuntime: "codex"` 와
115
+ `dispatchMode` 를 명시한다.
116
+ - validator 는 `leadRuntime` 별 conformance rule 을 고른다.
117
+
118
+ ## 6. Contract changes
119
+
120
+ ### 6.1 manifest
121
+
122
+ `task-manifest.json` 또는 run manifest 에 다음 필드를 추가한다.
123
+
124
+ ```json
125
+ {
126
+ "leadRuntime": "claude-code",
127
+ "leadAdapter": {
128
+ "name": "claude-code",
129
+ "dispatchMode": "team",
130
+ "sessionAccounting": "claude-jsonl"
131
+ }
132
+ }
133
+ ```
134
+
135
+ Codex run 예:
136
+
137
+ ```json
138
+ {
139
+ "leadRuntime": "codex",
140
+ "leadAdapter": {
141
+ "name": "codex",
142
+ "dispatchMode": "codex-subagents",
143
+ "sessionAccounting": "artifact-only"
144
+ }
145
+ }
146
+ ```
147
+
148
+ ### 6.2 validator
149
+
150
+ `validate_session_conformance.py` 는 현재 Claude session jsonl 을 검사한다.
151
+ 이를 다음처럼 분기한다.
152
+
153
+ | runtime | conformance source |
154
+ |---|---|
155
+ | `claude-code` | existing Claude session jsonl scan |
156
+ | `codex` | run artifact event log scan |
157
+
158
+ Codex adapter 는 `runs/<task-type>/state/lead-events-<task-type>-<seq>.jsonl`
159
+ 에 진행 이벤트를 기록한다.
160
+
161
+ Token/cost validation is runtime-aware. `claude-code` keeps the existing
162
+ fail-close `okstra token-usage --substitute-data` requirement. `codex` does
163
+ not run the Claude session-jsonl auto-recovery path. Codex runtime worker
164
+ usage is collected from `lead-events-*.jsonl` dispatch windows matched against
165
+ Codex rollout / Gemini session logs, so CLI-backed worker and report-writer
166
+ cost can be summarized without Claude wrapper jsonls. Codex lead token
167
+ accounting is still unavailable, and validator does not yet force
168
+ final-report token substitution for Codex runs.
169
+
170
+ ### 6.3 report author
171
+
172
+ 기존 규칙은 "report-writer worker 가 roster 에 있으면 lead 가 직접 쓰지 않는다"이다.
173
+ Codex adapter 에서도 이 원칙은 유지하되, report-writer role 의 구현을 runtime 별로 둔다.
174
+
175
+ ```text
176
+ logical role: report-writer
177
+ claude-code implementation: Agent(subagent_type=report-writer-worker)
178
+ codex implementation: Codex report-writer subagent or explicit recorded fallback
179
+ ```
180
+
181
+ ## 7. Install layout
182
+
183
+ 현재 설치는 Claude Code 를 전제로 한다. 설치 command 를 runtime-aware 로 분리한다.
184
+
185
+ ```bash
186
+ okstra install --runtime claude-code # default, current behavior
187
+ okstra install --runtime codex # codex adapter assets only
188
+ okstra install --runtime all # both adapters
189
+ ```
190
+
191
+ 권장 내부 구조:
192
+
193
+ ```text
194
+ adapters/
195
+ claude-code/
196
+ skills/
197
+ agents/
198
+ settings/
199
+ codex/
200
+ skills/
201
+ prompts/
202
+ adapter.md
203
+ ```
204
+
205
+ 단, 첫 구현에서는 물리 디렉터리 이동 없이 installer option 과 manifest field 만
206
+ 도입해도 된다. 대규모 파일 이동은 후속 cleanup 으로 둔다.
207
+
208
+ ## 8. 단계별 구현 계획
209
+
210
+ ### Stage 1 — runtime marker only
211
+
212
+ - `--lead-runtime <claude-code|codex>` flag 를 `render-bundle` / `okstra.sh` /
213
+ `prepare_task_bundle()` 에 추가한다.
214
+ - 기본값은 `claude-code`.
215
+ - manifests 와 team-state 에 `leadRuntime` / `leadAdapter` 를 기록한다.
216
+ - `codex` 는 dispatch adapter 가 생기기 전까지 `--render-only` 에서만 허용하고,
217
+ non-render prepare 는 명확히 fail 한다.
218
+
219
+ ### Stage 2 — Codex dry-run adapter
220
+
221
+ - `okstra codex-run` 를 추가한다.
222
+ - wrapper 가 `--render-only --lead-runtime codex` 를 소유하고, 사용자가 직접
223
+ 중복 전달하면 거부한다.
224
+ - wizard/render-bundle 로 task bundle 을 만들고, Codex lead prompt 를 출력한다.
225
+ - worker dispatch 는 하지 않는다.
226
+ - 목적: Codex 에서 task bundle intake, profile reading, phase boundary 를 안정화.
227
+
228
+ ### Stage 3 — Codex artifact event log
229
+
230
+ - `lead-events-*.jsonl` writer/reader 를 추가한다.
231
+ - `runs/<task-type>/state/lead-events-<task-type>-<seq>.jsonl` 를
232
+ team-state / run-manifest / task-manifest artifacts 에 노출한다.
233
+ - Codex render-only adapter 는 우선 `bundle-prepared` event 를 기록한다.
234
+ - validator 는 `leadRuntime=codex` 일 때 Claude session jsonl 대신 event log 를
235
+ 읽고 `progress` / `artifact-read` 이벤트를 checkpoint / implementation
236
+ sidecar-read 증거로 사용한다.
237
+ - 후속 dispatch 단계에서 `worker-dispatched`, `worker-result-collected` event 를
238
+ 기록한다.
239
+
240
+ ### Stage 4 — Codex worker dispatch
241
+
242
+ - logical worker role 을 유지하면서 Codex adapter 의 dispatch backend 를 붙인다.
243
+ - backend 우선순위:
244
+ 1. Codex sub-agent dispatch
245
+ 2. CLI wrapper dispatch
246
+ 3. sequential fallback with terminal status markers
247
+ - 모든 backend 는 기존 `worker-results/*.md`, prompt history, errors sidecar 를
248
+ 같은 path 에 써야 한다.
249
+ - 첫 구현 범위(2026-06-12): `okstra codex-run` 으로 준비된 run manifest 를
250
+ 입력으로 받는 `okstra codex-dispatch` 보조 명령을 추가한다.
251
+ - 지원 worker: 기존 CLI wrapper 계약이 있는 `codex`, `gemini`.
252
+ - `report-writer` 는 Stage 5 의 명시 opt-in 경로에서 지원한다.
253
+ - 미지원 worker: `--workers` 를 생략한 기본 dispatch 에서는 `claude` 같은
254
+ Codex-side 미지원 roster 항목을 건너뛴다. 사용자가 `--workers claude` 처럼
255
+ 명시 요청하면 Codex-native 구현 전까지 즉시 unsupported 로 실패한다.
256
+ - 실행 방식: shell 없이 wrapper 를 `subprocess.run([...])` 으로 호출하고,
257
+ team-state worker status 와 `lead-events-*.jsonl` 의
258
+ `worker-dispatched` / `worker-result-collected` / `worker-failed` 이벤트를
259
+ 갱신한다.
260
+ - prompt history 파일이 아직 없으면 run manifest / active-run-context 에서
261
+ 자동 생성한다. 기존 prompt 파일은 덮어쓰지 않는다.
262
+ - dispatch plan 과 lead-events 는 worker 별 `backend` / `dispatchMode` 를
263
+ 기록한다. 현재 값은 모두 `cli-wrapper` 이며, `_run_worker()` 는 backend router
264
+ 로 분리되어 미지원 backend 를 wrapper 실행 전에 거부한다.
265
+ - 비범위: Claude TeamCreate 대체, final-report Phase 7 token substitution,
266
+ report-writer 후처리, token/session accounting. 이후 Stage 5 에서
267
+ report-writer 후처리가 추가됐고, Stage 5.5 에서 worker CLI token accounting
268
+ 이 추가됐다.
269
+
270
+ ### Stage 5 — Codex report-writer
271
+
272
+ - report-writer logical role 을 Codex sub-agent 로 구현한다.
273
+ - 실패 시 기존 fallback 규칙처럼 dispatch attempt 와 terminal status 를 기록한다.
274
+ - final-report data.json -> renderer -> views -> token/cost placeholder 처리 순서는
275
+ Claude adapter 와 동일하게 유지한다.
276
+ - 첫 구현 범위(2026-06-12): `okstra codex-dispatch` 에 준비된
277
+ report-writer prompt 를 Codex wrapper 로 실행하는 opt-in 경로를 추가한다.
278
+ - 사용자는 `--workers report-writer --enable-codex-report-writer
279
+ --report-writer-codex-model <model>` 을 명시해야 한다.
280
+ - 이유: run manifest 의 report-writer model assignment 는 아직 Claude provider
281
+ 기준(`REPORT_WRITER_MODEL_EXECUTION_VALUE`)으로 렌더되므로, Codex CLI 에
282
+ 넘길 모델은 dispatch 단계에서 명시 override 해야 한다.
283
+ - dispatcher 는 prompt 의 `**Model:** Report writer worker, ...` header 를
284
+ override 값으로 갱신하고, wrapper 실행 성공 후 세 artifact 를 모두 확인한다:
285
+ `reports/final-report-*.data.json`, 렌더된 `reports/final-report-*.md`,
286
+ `worker-results/report-writer-worker-*.md` audit sidecar.
287
+ - artifact 확인 후 idempotent 한 후처리 네 개를 실행한다:
288
+ `okstra-token-usage.py --write --substitute-data` 로 token/cost 값을
289
+ data.json 과 markdown 에 치환하고,
290
+ `okstra-render-report-views.py` 로 HTML view 를 렌더하고,
291
+ `okstra-spawn-followups.py` 로 `followUpTasks[]` 의 auto-spawn 항목을
292
+ task stub 으로 만들고,
293
+ `validators/validate-run.py` 로 final-report schema / markdown contract /
294
+ report-view contract 를 검증한다. HTML view 가 치환 후 markdown 을 읽도록
295
+ token substitution 이 항상 render-views 보다 먼저 실행되며, validation 은
296
+ 더 이상 실패할 후처리 단계가 없는 마지막 gate 로 실행된다. 후처리가 실패하면
297
+ report-writer 는 failed 로 기록한다.
298
+ - report-writer prompt history 파일이 아직 없으면 dispatcher 가 자동 생성한다.
299
+ 이때 `Result Path` 는 `.data.json`, `Worker Result Path` 는 audit sidecar,
300
+ `Report Language` 는 project/global config 또는 task brief 추론값으로 채운다.
301
+ - 비범위: Codex lead 자체 token/cost accounting.
302
+
303
+ ### Stage 5.5 — Codex worker CLI token accounting
304
+
305
+ - Codex runtime 은 Claude Agent wrapper session 을 생성하지 않으므로,
306
+ `okstra token-usage` 가 `lead-events-*.jsonl` 의 worker dispatch window 를
307
+ session source 로 사용한다.
308
+ - `codex` worker 와 Codex opt-in `report-writer` 는 Codex rollout JSONL 을,
309
+ `gemini` worker 는 Gemini chat session JSON 을 window 안에서 매칭한다.
310
+ - `usageSummary.workerTotalTokens` 와 `estimatedCostUsd.cliWorkers` 는 CLI worker
311
+ totals 를 반영한다.
312
+ - report-writer 후처리 중에는 `worker-result-collected` 이벤트가 아직 append
313
+ 되기 전이므로, collector 는 `status=running` worker 의 active dispatch 를
314
+ 수집 시각까지의 open window 로 사용할 수 있다.
315
+ - Codex lead 자체 token/cost 는 아직 공식 수집원이 없어 `leadUsage.source =
316
+ "unavailable"` 로 남긴다.
317
+ - validator 는 Codex run 에 대해 token substitution auto-recovery 를 강제하지
318
+ 않는다. 이 단계의 목적은 collector data 를 먼저 정확히 채우는 것이다.
319
+
320
+ ### Stage 6 — install packaging cleanup
321
+
322
+ - `okstra install --runtime <claude-code|codex|all>` 을 추가한다.
323
+ - `claude-code` 기본값은 기존 동작 그대로 공유 runtime + Claude skills/agents 를
324
+ 설치한다.
325
+ - `codex` 는 공유 runtime/bin/templates/schema/validators/settings 만 설치하고
326
+ `~/.claude/skills` / `~/.claude/agents` 를 건드리지 않는다.
327
+ - `all` 은 Claude assets 포함 설치와 동일하다. 별도 Codex-only asset tree 가
328
+ 생기면 여기서 함께 설치한다.
329
+ - `okstra ensure-installed --runtime <...>` 는 같은 runtime 으로 재설치하며,
330
+ `codex` 는 Claude skill/agent drift 검사를 건너뛴다.
331
+ - `okstra doctor --runtime <...>` 는 `codex` 에서 Claude skill checks 를 제외하고
332
+ JSON 출력에 선택 runtime 을 포함한다.
333
+ - `~/.okstra/installed-runtimes.json` 을 추가해 선택 runtime 과 asset 범위를
334
+ `installed-skills.json` / `installed-agents.json` 과 분리해 기록한다.
335
+ codex-only manifest 는 uninstall 이 레거시 fallback 으로 `~/.claude` 자산을
336
+ 제거하지 않도록 막는다.
337
+ - README / docs 는 Codex-only install + doctor 경로를 노출한다.
338
+ - 남은 cleanup: Codex 전용 skill/adapter asset 이 생기면
339
+ `installed-runtimes.json` 의 Codex asset 범위를 실제 파일 manifest 로 확장한다.
340
+
341
+ ## 9. 위험과 대응
342
+
343
+ | 위험 | 대응 |
344
+ |---|---|
345
+ | validator 가 Claude session jsonl 만 신뢰 | `leadRuntime` 별 conformance source 분기 |
346
+ | worker output contract drift | logical worker role/schema 는 공유하고 dispatch backend 만 교체 |
347
+ | report-writer authorship 규칙 훼손 | runtime 별 report-writer implementation 을 두고 fallback 은 명시 기록 |
348
+ | 설치 경로 혼란 | `okstra doctor --runtime <name>` 로 runtime 별 진단 |
349
+ | 두 버전 문서 drift | phase profile/schema/validator 는 fork 금지, adapter docs 만 분리 |
350
+
351
+ ## 10. 결론
352
+
353
+ 가능하다. 단, "Claude Code 버전"과 "Codex 버전"을 제품 복사본으로 나누는 것이
354
+ 아니라, **lead runtime adapter 를 나누는 방식**이어야 한다.
355
+
356
+ 가장 작고 안전한 첫 PR 은 `leadRuntime` marker 와 Codex dry-run adapter 이다.
357
+ 이 PR 은 기존 Claude Code 사용자를 깨지 않으면서 Codex 실행 경로를 공식적으로
358
+ 받아들일 수 있는 구조를 만든다.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okstra",
3
- "version": "0.75.0",
3
+ "version": "0.77.0",
4
4
  "description": "Multi-agent cross-verification orchestrator runtime + Claude Code skills.",
5
5
  "license": "MIT",
6
6
  "author": "devonshin",