okstra 0.64.1 → 0.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/okstra +1 -0
- package/docs/kr/architecture.md +2 -0
- package/docs/kr/cli.md +12 -4
- package/docs/kr/performance-improvement-plan-v2.md +2 -1
- package/docs/project-structure-overview.md +1 -0
- package/docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md +1029 -0
- package/docs/superpowers/specs/2026-06-10-blocking-contract-posthoc-conformance-design.md +168 -0
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/SKILL.md +4 -2
- package/runtime/agents/workers/claude-worker.md +1 -1
- package/runtime/agents/workers/codex-worker.md +1 -0
- package/runtime/agents/workers/gemini-worker.md +1 -0
- package/runtime/bin/lib/okstra/cli.sh +4 -0
- package/runtime/bin/lib/okstra/globals.sh +1 -0
- package/runtime/bin/lib/okstra/usage.sh +4 -1
- package/runtime/bin/okstra.sh +1 -0
- package/runtime/prompts/profiles/_implementation-executor.md +1 -0
- package/runtime/python/okstra_ctl/clarification_items.py +96 -37
- package/runtime/python/okstra_ctl/context_cost.py +86 -8
- package/runtime/python/okstra_ctl/locks.py +32 -0
- package/runtime/python/okstra_ctl/migrate.py +45 -6
- package/runtime/python/okstra_ctl/models.py +5 -0
- package/runtime/python/okstra_ctl/pr_template.py +2 -7
- package/runtime/python/okstra_ctl/render_final_report.py +2 -1
- package/runtime/python/okstra_ctl/run.py +58 -44
- package/runtime/python/okstra_ctl/run_context.py +3 -8
- package/runtime/python/okstra_ctl/seeding.py +25 -18
- package/runtime/python/okstra_ctl/wizard.py +9 -11
- package/runtime/python/okstra_ctl/worktree.py +13 -0
- package/runtime/python/okstra_project/dirs.py +10 -1
- package/runtime/python/okstra_token_usage/claude.py +226 -61
- package/runtime/python/okstra_token_usage/cli.py +10 -1
- package/runtime/python/okstra_token_usage/collect.py +34 -27
- package/runtime/python/okstra_token_usage/cursor.py +93 -0
- package/runtime/python/okstra_token_usage/paths.py +29 -2
- package/runtime/python/okstra_token_usage/pricing.py +7 -3
- package/runtime/skills/okstra-coding-preflight/clean-code.md +15 -0
- package/runtime/skills/okstra-inspect/SKILL.md +16 -11
- package/runtime/skills/okstra-run/templates/pr-body.template.md +13 -16
- package/runtime/skills/okstra-schedule/SKILL.md +3 -3
- package/runtime/skills/okstra-team-contract/SKILL.md +1 -1
- package/runtime/validators/lib/fixtures.sh +73 -10
- package/runtime/validators/lib/runners.sh +4 -0
- package/runtime/validators/validate-run.py +53 -0
- package/runtime/validators/validate_session_conformance.py +430 -0
- package/src/migrate.mjs +31 -0
package/bin/okstra
CHANGED
|
@@ -19,6 +19,7 @@ const COMMANDS = new Map([
|
|
|
19
19
|
() => import("../src/check-project.mjs").then((m) => m.run),
|
|
20
20
|
],
|
|
21
21
|
["config", () => import("../src/config.mjs").then((m) => m.run)],
|
|
22
|
+
["migrate", () => import("../src/migrate.mjs").then((m) => m.run)],
|
|
22
23
|
["task-list", () => import("../src/task-list.mjs").then((m) => m.run)],
|
|
23
24
|
["task-show", () => import("../src/task-show.mjs").then((m) => m.run)],
|
|
24
25
|
["context-cost", () => import("../src/context-cost.mjs").then((m) => m.run)],
|
package/docs/kr/architecture.md
CHANGED
|
@@ -934,6 +934,7 @@ Phase 7 step 1.5 가 final-report MD 한 본을 입력으로 두 view 를 결정
|
|
|
934
934
|
- Gemini CLI: `~/.gemini/tmp/*/chats/session-*.json`의 per-message `tokens.total`
|
|
935
935
|
- billable-equivalent token math와 USD cost estimation을 함께 기록합니다. Anthropic billing ratio(`cache_creation_5m=1.25x`, `cache_creation_1h=2.0x`, `cache_read=0.1x`, `output=5x`)를 반영합니다. transcript 의 `usage.cache_creation.ephemeral_5m_input_tokens` / `ephemeral_1h_input_tokens` 분해가 있으면 분리 집계합니다.
|
|
936
936
|
- 가격표는 `scripts/okstra_token_usage/pricing.py` 에서 중앙 관리합니다. 모델 가격이 바뀌면 거기서 갱신합니다. 가격 매칭에 실패한 모델 id 는 `usageSummary.unmatchedModels` 필드로 사용자에게 노출됩니다 (silent zero 사고 방지).
|
|
937
|
+
- **증분 스캔 캐시 (P6)**: 세션 jsonl 재스캔을 피하기 위해 `$OKSTRA_HOME/cache/token-usage/<transcript-dir>/<sessionId>.json` 에 파일별 byte cursor + 윈도우 적용 전 usage 이벤트 추출본을 보존합니다 (`scripts/okstra_token_usage/cursor.py`). run 윈도우(since/until)는 매 호출 시 이벤트 위에서 재평가하므로 재실행으로 윈도우가 좁아져도 합계는 전체 스캔과 동일합니다. 캐시는 파생 데이터라 식별자 불일치·truncate·손상 시 자동으로 전체 재스캔으로 폴백하며, `okstra-token-usage.py --no-cache` 로 강제 우회할 수 있습니다.
|
|
937
938
|
|
|
938
939
|
## Validators
|
|
939
940
|
|
|
@@ -1019,4 +1020,5 @@ phase 산출물의 출고 가능 여부를 강제하는 진입점:
|
|
|
1019
1020
|
- `OKSTRA_CTL_MAX_SPAWN`: rerun 동시 spawn 임계 기본값.
|
|
1020
1021
|
- `OKSTRA_CTL_SKIP_BACKFILL=1`: 첫 호출 시 자동 백필 스킵.
|
|
1021
1022
|
- `OKSTRA_CTL_SKIP_RECONCILE=1`: lazy reconcile 스킵(테스트/디버깅용).
|
|
1023
|
+
- `OKSTRA_SKIP_INSTALL_CHECK=1`: `verify_installation` 의 설치 자산 검사 스킵(테스트용; workspace 존재 검증은 유지).
|
|
1022
1024
|
- `OKSTRA_RUN_SEQ_OVERRIDE`: rerun 시 okstra.sh 가 사용할 run-seq 강제값 (okstra-ctl 내부 자동 주입).
|
package/docs/kr/cli.md
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
- [`--gemini-model`](#--gemini-model)
|
|
28
28
|
- [`--report-writer-model`](#--report-writer-model)
|
|
29
29
|
- [`--executor`](#--executor)
|
|
30
|
+
- [`--critic`](#--critic)
|
|
30
31
|
- [`--approved-plan`](#--approved-plan)
|
|
31
32
|
- [`--approve`](#--approve)
|
|
32
33
|
- [`--work-category`](#--work-category)
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
기본 명령(첫 진입 / full args):
|
|
51
52
|
|
|
52
53
|
```bash
|
|
53
|
-
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] [--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>]
|
|
54
|
+
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>]
|
|
54
55
|
```
|
|
55
56
|
|
|
56
57
|
후속 phase 단축 형식(기존 task-manifest.json이 존재할 때):
|
|
@@ -295,7 +296,7 @@ scripts/okstra.sh --task-type implementation-planning --workers claude,codex --p
|
|
|
295
296
|
```
|
|
296
297
|
|
|
297
298
|
> 모든 `--*-model` 플래그는 `scripts/okstra_ctl/models.py` 의 provider 별 mapping 에 등록된 alias 만 허용합니다. 등록되지 않은 값은 `UnknownModelError` 로 즉시 거부됩니다 (manifest 의 `modelExecutionValue` 와 실제 실행값 불일치로 인한 contract-violation 을 사전에 차단). 허용값:
|
|
298
|
-
> - Claude (`--lead-model` / `--claude-model` / `--report-writer-model`): `opus`, `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`
|
|
299
|
+
> - 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`
|
|
299
300
|
> - Codex (`--codex-model`): `gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.3-codex`, `gpt-5.2`, `codex-auto-review`
|
|
300
301
|
> - Gemini (`--gemini-model`): `auto`, `pro`, `gemini-3-flash-preview`, `gemini-3-pro-preview` (그리고 `gemini auto` / `gemini pro` 별칭)
|
|
301
302
|
|
|
@@ -353,7 +354,7 @@ fallback 기본값은 아래와 같습니다.
|
|
|
353
354
|
- 실제 파일 변경은 Codex/Gemini 의 경우 각 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-gemini-exec.sh`) 는 worktree 경로를 4번째 positional 인자로 받아 codex 는 `--add-dir`, gemini 는 `--include-directories` 로 forward 합니다. 누락하면 codex `workspace-write` 샌드박스가 worktree 쓰기를 EPERM 으로 거부합니다.
|
|
354
355
|
- **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 / gemini executor 는 CLI wrapper 가 cwd 를 주입합니다.
|
|
355
356
|
- **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 격리는 예외입니다.**
|
|
356
|
-
- **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 를
|
|
357
|
+
- **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 합니다.
|
|
357
358
|
|
|
358
359
|
예:
|
|
359
360
|
|
|
@@ -366,6 +367,13 @@ scripts/okstra.sh --task-type implementation \
|
|
|
366
367
|
--task-brief .project-docs/tasks/8852/BUG_REPORT.md
|
|
367
368
|
```
|
|
368
369
|
|
|
370
|
+
### `--critic`
|
|
371
|
+
|
|
372
|
+
Phase 5.6 의 opt-in critic pass 를 수행할 provider 를 선택합니다. 값은 `off` | `claude` | `codex` | `gemini` 중 하나이며 기본값은 `off` 입니다.
|
|
373
|
+
|
|
374
|
+
- critic pass 는 convergence(Phase 5.5) 직후 reused-worker 1라운드로 수행됩니다 — discovery / error-analysis / implementation-planning 에서는 coverage gap 탐지, final-verification 에서는 acceptance devil's-advocate 역할입니다. 상세 규약은 `okstra-convergence` skill 의 "Coverage critic pass" / "Acceptance critic pass" 섹션을 따릅니다.
|
|
375
|
+
- in-session `okstra-run` wizard 의 critic 선택 단계와 동일한 값 공간을 공유합니다. 허용값 검증은 `prepare_task_bundle` 의 `_resolve_model_bindings` 가 수행하며, 그 외 값은 `PrepareError` 로 즉시 거부됩니다.
|
|
376
|
+
|
|
369
377
|
### `--approved-plan`
|
|
370
378
|
|
|
371
379
|
`--task-type implementation` 의 입력으로, 이전 `implementation-planning` run 의 final report 경로를 받습니다. 이 파일의 YAML frontmatter 에는 `approved` field 가 있어야 하며 값이 `true` 여야 합니다.
|
|
@@ -587,7 +595,7 @@ chmod +x ~/.local/bin/okstra-ctl
|
|
|
587
595
|
| `okstra render-bundle <args…> [--stage <auto\|N>]` | `prepare_task_bundle(render_only=True)` 의 thin shim — `python3 -m okstra_ctl.run --render-only` 와 동일 시그니처. `--stage` 는 `implementation` task 전용: 실행할 Stage Map 항목 지정. `auto` (기본값) = 의존성이 만족된 가장 빠른 미완료 stage, `<N>` = 강제 지정 |
|
|
588
596
|
| `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 를 검사 |
|
|
589
597
|
| `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` 으로 넘어갑니다 |
|
|
590
|
-
| `okstra token-usage ...` | 설치된 `okstra-token-usage.py` 를 감싸 run token usage 수집/치환을
|
|
598
|
+
| `okstra token-usage ...` | 설치된 `okstra-token-usage.py` 를 감싸 run token usage 수집/치환을 수행. 세션 jsonl 은 기본적으로 `$OKSTRA_HOME/cache/token-usage/` 의 byte cursor 캐시로 증분 스캔하며, `--no-cache` 로 캐시를 우회해 전체 재스캔을 강제할 수 있음(정확성 폴백) |
|
|
591
599
|
|
|
592
600
|
> 모든 subcommand 는 `bin/okstra` 가 spawn 하는 python 헬퍼 (`src/_python-helper.mjs`) 가 `PYTHONPATH` 와 `~/.okstra/lib/python` 을 wire 합니다. 직접 `python3 -m okstra_ctl.*` 으로 호출하면 `PYTHONPATH` 를 사용자가 직접 셋업해야 합니다.
|
|
593
601
|
|
|
@@ -350,4 +350,5 @@ Optional Round 2:
|
|
|
350
350
|
### 구현 plan 링크
|
|
351
351
|
|
|
352
352
|
- P0 + P1: `docs/superpowers/plans/2026-05-14-convergence-queue-pruning.md`
|
|
353
|
-
-
|
|
353
|
+
- P6: `docs/superpowers/plans/2026-06-10-p6-token-usage-incremental.md` (구현 완료)
|
|
354
|
+
- P2 / P3 / P4 / P5: 미작성 (각 트랙별로 별도 plan 작성 필요)
|
|
@@ -204,6 +204,7 @@ Token/cost accounting:
|
|
|
204
204
|
|
|
205
205
|
- provider adapters: `claude.py`, `codex.py`, `gemini.py`
|
|
206
206
|
- aggregation: `collect.py`, `blocks.py`, `jsonl_io.py`, `paths.py`
|
|
207
|
+
- incremental scan cache: `cursor.py` (`$OKSTRA_HOME/cache/token-usage/` byte cursor + usage event extracts; bypass with `--no-cache`)
|
|
207
208
|
- pricing: `pricing.py`
|
|
208
209
|
- report substitution: `report.py`
|
|
209
210
|
- CLI: `cli.py` via `scripts/okstra-token-usage.py` and `okstra token-usage`
|