okstra 0.116.0 → 0.118.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.
@@ -1,122 +0,0 @@
1
- # okstra container — CLI 레퍼런스 (한국어)
2
-
3
- > `okstra container` 는 검증된 task 의 코드를 로컬 docker compose 그룹으로 띄우고 컨테이너별로 감시하는 비선형 도구입니다. `okstra.sh` 의 phase 플래그와는 별개 진입점이라 [cli.md](cli.md) 가 아닌 이 문서에서 다룹니다. 모듈 위치는 [project-structure-overview](../project-structure-overview.md) §4.3 을 참고하세요.
4
-
5
- ---
6
-
7
- ## 개요
8
-
9
- - **무엇인가:** 특정 task 의 통합된 코드를 그 task 전용 docker compose 컨테이너 그룹으로 배포(`up`)하고, 컨테이너별 watcher 로 로그를 상시 감시하며, `status`/`logs`/`stop-watcher`/`down` 으로 수명주기를 관리한다.
10
- - **오케스트레이션 전용(생성 안 함):** 대상 프로젝트가 이미 가진 `docker-compose.yml` 을 **재사용**한다. 설정 파일을 생성하지 않으며, `docker-compose.yml` 이 없으면 무엇이 없는지 알리고 중단한다(`Dockerfile` 단독도 동일).
11
- - **비선형:** `PHASE_SEQUENCE` 의 phase 가 아니다. 임의의 task-key 를 검증 통과 여부와 무관하게 띄울 수 있다.
12
- - **단일 진입점:** 스킬 `/okstra-container-build`, `bin okstra container`, python `okstra_ctl.container` 가 모두 [`scripts/okstra_ctl/container.py`](../../scripts/okstra_ctl/container.py) 의 `provision_container_group` 로 수렴한다.
13
- - **컨테이너 존재의 기준값(SSOT):** docker 라벨. `registry.json` 은 tmux 세션/pane/findings 만 담는 보조 인덱스다.
14
-
15
- ## 사전 조건
16
-
17
- - `docker` / `docker compose` 가 설치·동작해야 한다. 미설치 환경에서는 `up` 이 실패하지만, `okstra doctor` 는 `[WARN]` 만 내고 종료 코드 0 을 유지한다(컨테이너 기능은 필수 아님).
18
- - 대상 task-key 의 코드가 task-key worktree HEAD 로 통합돼 있어야 한다. 미통합 stage 가 있으면 `up` 이 머지(stage 트리는 보존)한 뒤 진행하며, 충돌 시 충돌 파일을 알리고 중단한다.
19
- - worktree 루트에 `docker-compose.yml` 이 있어야 한다.
20
-
21
- ## 명령 형식
22
-
23
- ```
24
- okstra container <up|status|logs|stop-watcher|down> --project-root <PATH> --task-key <KEY> [옵션]
25
- ```
26
-
27
- | sub-command | 동작 | 추가 옵션 |
28
- |---|---|---|
29
- | `up` | stage 통합 확인 → `docker-compose.yml` 검증 → env override 합성 → `docker compose -p <project> up -d` → 헬스체크 폴링 → 컨테이너별 tail/watcher pane 기동 | — |
30
- | `status` | docker 라벨 쿼리로 살아있는 컨테이너 그룹 현황 | — |
31
- | `logs` | 컨테이너 로그 조회 | `--service <NAME>` (생략 시 그룹 전체) |
32
- | `stop-watcher` | 해당 task 의 watcher pane 종료(컨테이너는 유지) | — |
33
- | `down` | 컨테이너 그룹 teardown + 딸린 watcher 종료 | `--all` |
34
-
35
- ## 인자
36
-
37
- ### `--project-root` (필수)
38
- 대상 프로젝트 루트의 절대 경로. 모든 sub-command 에 필수.
39
-
40
- ### `--task-key` (필수에 준함)
41
- 배포 대상 task 식별자 `<project-id>:<task-group>:<task-id>`. 기본값은 빈 문자열이나, 실제 동작에는 유효한 task-key 가 필요하다.
42
-
43
- ### `--service` (`logs` 전용)
44
- 특정 compose 서비스의 로그만 조회. 생략하면 그룹 전체.
45
-
46
- ### `--all` (`down` 전용)
47
- 현재 project-root 의 `.okstra/` 범위 안에 있는 **모든** task 컨테이너 그룹과 watcher 를 정리한다. 경계는 `<project-root>/.okstra/` prefix 로 한정되어, 동시 세션의 **다른 프로젝트** pane 은 절대 건드리지 않는다. `--all` 없이 단일 `down` 은 해당 task 의 pane 만 정확히 회수한다.
48
-
49
- ## `up` 의 동작 단계
50
-
51
- 1. **소스 트리 해소** — task-key worktree HEAD. 미통합 stage 는 머지(`teardown=False`, stage worktree 보존). 충돌 시 충돌 파일 명시 후 중단(재시도는 already-merged 멱등이라 안전).
52
- 2. **설정 파일 검증** — worktree 루트 `docker-compose.yml`. 없으면 누락 파일명 명시 후 중단(생성 안 함).
53
- 3. **bind mount 스캔** — `docker compose config` 정규화 결과에서 worktree 밖(`../`·절대경로)을 가리키는 host path 가 있으면 **경고 후 진행**(중단하지 않음 — 컨테이너가 호스트에 파일을 쓸 수 있음을 알림).
54
- 4. **env override 합성** — worktree 의 `.env`(okstra 소유 트리) 위에 task override 를 얹어 `env.override` 로 쓴 뒤 `--env-file <worktree .env> --env-file <env.override>` 순으로 전달(뒤가 우선).
55
- 5. **배포** — `docker compose -p <project-name> ... up -d`. 서비스 목록은 `docker compose config --services`(정본)로 얻는다.
56
- 6. **헬스체크 폴링** — `docker compose ps` 로 각 서비스 기동 확인. healthcheck 가 정의된 서비스는 healthy, 없는 서비스는 `running` 도달을 성공으로 본다.
57
- 7. **감시 기동** — `tmux` 가용 시 detached 세션 `okstra-container-<slug>` 에 컨테이너별 tail pane + watcher 에이전트를 띄운다. 미가용 시 컨테이너만 띄우고 "감시 비활성(tmux 없음)" 을 결과에 명시한다.
58
-
59
- ### 고정 기본값(현재 CLI 플래그 미노출)
60
-
61
- | 값 | 기본 | 의미 |
62
- |---|---|---|
63
- | healthcheck timeout | 120초 | 초과 시 미기동 서비스를 알리고 중단 |
64
- | healthcheck interval | 3초 | `docker compose ps` 폴링 간격 |
65
- | watcher scan interval | 5초 | watcher 로그 증분 스캔 주기 |
66
-
67
- > 이 값들은 `provision_container_group` 의 named 인자로 존재하지만 CLI 플래그로는 노출되지 않아 현재 고정값으로 동작한다.
68
-
69
- ## watcher (에러 트리거 2단계)
70
-
71
- 컨테이너당 watcher 1개가 detached 세션에서 동작한다.
72
-
73
- 1. **경량 스캔** — `docker compose logs --since` 로 증분 로그를 가져와 정규식(`ERROR`/`FATAL`/`Exception`/`Traceback`/비정상 exit code 등)만 매칭. 매칭 0건이면 LLM 호출 없이 다음 주기 → 정상 구간 토큰 비용 0.
74
- 2. **심층 분석** — 패턴 감지 시에만 watcher AI 가 해당 로그 윈도우를 분석해 `findings.md` 에 기록(append). 동일 에러 시그니처는 디바운스(HTTP status·exit code 등 의미 있는 숫자는 보존, 타임스탬프·pid 등 노이즈만 정규화). watcher 는 **탐지·보고만** 하며 코드/설정을 수정하지 않는다.
75
-
76
- watcher/tail pane 은 전용 `@okstra_container_run` 태그만 부착되어 Claude 세션 종료(SessionEnd `--reap`)에도 살아남는다. `stop-watcher` 또는 `down` 으로 종료한다.
77
-
78
- ## 라벨과 산출물
79
-
80
- 배포된 컨테이너에는 세 라벨이 부착되며, `status`/`down` 의 라벨 쿼리가 이를 기준으로 그룹을 찾는다.
81
-
82
- | 라벨 | 값 |
83
- |---|---|
84
- | `okstra.task-key` | `<project-id>:<task-group>:<task-id>` |
85
- | `okstra.project-name` | compose project name `okstra-<proj>-<group>-<task>` |
86
- | `okstra.run-trace` | container 세션명(`okstra-container-<slug>`) |
87
-
88
- okstra 산출물은 전부 `<project-root>/.okstra/tasks/<group>/<task-id>/container/` 아래에 둔다(원본 프로젝트 파일 불변):
89
-
90
- ```
91
- container/
92
- ├── env.override # task 별 주입 변수(프로젝트 .env 위 레이어)
93
- ├── registry.json # tmux 세션/pane/findings (flock-guarded 보조 인덱스)
94
- ├── deploy-state.json # compose project name, 기동 컨테이너, 라벨
95
- └── watchers/<service>-findings.md # watcher 별 에러 분석 로그
96
- ```
97
-
98
- ## 종료/출력
99
-
100
- 각 sub-command 은 결과를 JSON 으로 stdout 에 출력하고 종료 코드 0 을 반환한다. 검증 실패(설정 파일 부재, 머지 충돌, 헬스체크 timeout 등)는 `PrepareError` 로 무엇이 잘못됐는지 명시하며 비정상 종료한다.
101
-
102
- ## 사용 예
103
-
104
- ```bash
105
- # 배포 + 감시 기동
106
- okstra container up --project-root /path/to/proj --task-key proj:auth:login-fix
107
-
108
- # 현황
109
- okstra container status --project-root /path/to/proj --task-key proj:auth:login-fix
110
-
111
- # 특정 서비스 로그
112
- okstra container logs --project-root /path/to/proj --task-key proj:auth:login-fix --service api
113
-
114
- # watcher 만 종료(컨테이너 유지)
115
- okstra container stop-watcher --project-root /path/to/proj --task-key proj:auth:login-fix
116
-
117
- # 그룹 teardown
118
- okstra container down --project-root /path/to/proj --task-key proj:auth:login-fix
119
-
120
- # 이 프로젝트의 모든 컨테이너 그룹 정리
121
- okstra container down --project-root /path/to/proj --all
122
- ```
@@ -1,51 +0,0 @@
1
- # Final Report 가독성 후속: 3안 재검토
2
-
3
- 상태: 보류
4
- 작성일: 2026-07-10
5
-
6
- ## 배경
7
-
8
- 이번 1차 가독성 개선은 범위를 좁게 유지했다.
9
-
10
- - `readerSummary`로 Markdown final-report 앞부분에 사람이 먼저 읽을 요약 진입점을 둔다.
11
- - HTML report view에 Reader Summary dashboard와 reader mode를 추가한다.
12
- - 기존 `final-report` data는 `verdictCard` fallback으로 계속 호환한다.
13
-
14
- 이 문서는 더 큰 3안을 현재 변경에 섞지 않고, 나중에 별도 판단할 재검토 후보로 남긴다.
15
-
16
- ## 보류한 3안
17
-
18
- `final-report` 산출물 자체를 목적별로 분리할지 재검토한다.
19
-
20
- 현재 구조는 하나의 canonical Markdown 문서와 그 문서에서 생성되는 view를 유지한다. 3안은 요약 블록이나 HTML 필터링만으로 충분한지, 아니면 report를 목적별 artifact로 나누는 편이 더 나은지 비교하는 작업이다.
21
-
22
- 비교 후보:
23
-
24
- - 짧은 human handoff report와 별도 audit appendix.
25
- - 같은 `data.json`에서 생성되는 `summary` view와 `audit` view.
26
- - 사람이 먼저 행동하는 섹션만 남기는 phase별 slim report template.
27
- - reporter handoff, implementer handoff, verifier audit, release handoff 같은 role별 view set.
28
-
29
- ## 재검토 트리거
30
-
31
- 아래 중 하나가 반복되면 이 문서를 다시 연다.
32
-
33
- - `readerSummary`와 HTML reader mode 배포 후에도 사용자가 `final-report`를 읽기 어렵다고 말한다.
34
- - 리뷰어가 항상 같은 audit 섹션을 건너뛰거나 더 작은 handoff artifact를 요구한다.
35
- - `final-report` 생성에서 같은 evidence가 여러 섹션에 반복된다.
36
- - 향후 schema migration에서 report artifact 계약을 어차피 건드려야 한다.
37
-
38
- ## 결정할 질문
39
-
40
- - Markdown이 계속 primary human artifact인가, 아니면 `data.json`만 canonical source로 두고 view를 생성할 것인가?
41
- - follow-up task에 기본 첨부할 artifact는 무엇인가?
42
- - 어떤 섹션이 human-action material이고, 어떤 섹션이 audit-only material인가?
43
- - 분리를 validator가 강제해야 하는가, renderer convention으로 둘 것인가?
44
- - 분리가 기존 `render-views`, follow-up spawning, approval sidecar에 어떤 영향을 주는가?
45
-
46
- ## 참조
47
-
48
- - 현재 schema: `schemas/final-report-v1.0.schema.json`
49
- - 현재 Markdown template: `templates/reports/final-report.template.md`
50
- - 현재 HTML renderer: `scripts/okstra_ctl/report_views.py`
51
- - 현재 report UI assets: `templates/reports/report.css`, `templates/reports/report.js`
@@ -1,374 +0,0 @@
1
- # okstra-run 성능 개선 계획 v2
2
-
3
- ## 인덱스
4
-
5
- - [1. 목적](#1-목적)
6
- - [2. 현재 구조 요약](#2-현재-구조-요약)
7
- - [2.1 진입점](#21-진입점)
8
- - [2.2 두 종류의 phase를 구분한다](#22-두-종류의-phase를-구분한다)
9
- - [2.3 prepare 단계의 비용 특성](#23-prepare-단계의-비용-특성)
10
- - [2.4 worker 구조](#24-worker-구조)
11
- - [3. 성능 병목 가설](#3-성능-병목-가설)
12
- - [4. 측정 기준](#4-측정-기준)
13
- - [4.1 실측 결과 (2026-06-11)](#41-실측-결과-2026-06-11-fontradar-v2-api-dev-9186)
14
- - [5. 개선 우선순위](#5-개선-우선순위)
15
- - [P0. Baseline 계측과 용어 정리](#p0-baseline-계측과-용어-정리)
16
- - [P1. Convergence 재검증 범위 축소](#p1-convergence-재검증-범위-축소)
17
- - [P2. Prompt diet: analysis worker 입력 축소](#p2-prompt-diet-analysis-worker-입력-축소)
18
- - [P3. Fast-track routing](#p3-fast-track-routing)
19
- - [P4. Prompt caching 가능성 검증](#p4-prompt-caching-가능성-검증)
20
- - [P5. Prepare render 병렬화](#p5-prepare-render-병렬화)
21
- - [P6. Token usage 증분화](#p6-token-usage-증분화)
22
- - [6. 병렬 작업 계획](#6-병렬-작업-계획)
23
- - [7. P1 구현 체크리스트](#7-p1-구현-체크리스트)
24
- - [8. 리스크와 방어선](#8-리스크와-방어선)
25
- - [9. 이번 계획의 결론](#9-이번-계획의-결론)
26
-
27
- ## 1. 목적
28
-
29
- `okstra-run` 스킬 또는 `scripts/okstra.sh`로 시작하는 cross-verification run이 무겁게 느껴지는 문제를 줄인다. 이 문서는 현재 구조를 정확한 레이어로 나누고, 개선 후보의 우선순위, 측정 기준, 병렬 작업 가능성, 1차 구현 범위를 정리한다.
30
-
31
- 핵심 판단:
32
-
33
- - 가장 큰 비용은 prepare 단계가 아니라 worker dispatch 이후의 반복 검증과 장문 prompt 소비에서 발생한다.
34
- - 먼저 convergence 재검증 범위를 줄여 worker 호출 수와 wall-clock을 낮춘다.
35
- - fast-track, prompt 캐싱, 템플릿/worker 정의 축소는 서로 다른 레이어를 건드리므로 별도 작업으로 분리한다.
36
-
37
- ## 2. 현재 구조 요약
38
-
39
- ### 2.1 진입점
40
-
41
- `scripts/okstra.sh`와 `skills/okstra-run/SKILL.md`는 모두 `scripts/okstra_ctl/run.py`의 `prepare_task_bundle()`을 호출한다. 이 단일 reference point는 유지해야 한다.
42
-
43
- - `scripts/okstra.sh`: CLI 인자 파싱, `prepare_task_bundle()` 호출, non-render-only에서는 `claude` 실행.
44
- - `okstra-run` skill: 현재 Claude 세션 안에서 입력을 모은 뒤 같은 Python entrypoint를 호출하고 lead 역할을 이어받음.
45
- - shared prepare 로직: `scripts/okstra_ctl/run.py`.
46
-
47
- ### 2.2 두 종류의 phase를 구분한다
48
-
49
- 현재 문서/코드에는 이름이 비슷한 phase가 두 층에 존재한다. 성능 개선 작업은 이 둘을 섞으면 안 된다.
50
-
51
- #### Task-type lifecycle
52
-
53
- `scripts/okstra_ctl/workflow.py`의 `PHASE_SEQUENCE`는 다음 6개 task-type만 가진다.
54
-
55
- | 순서 | task-type | 책임 |
56
- |---|---|---|
57
- | 1 | `requirements-discovery` | work-category 분류, 안전한 다음 phase 라우팅, missing input 정리 |
58
- | 2 | `error-analysis` | 증상, 원인 가설, 재현 갭, 검증 경로 분석 |
59
- | 3 | `implementation-planning` | 최소 2개 구현 옵션, trade-off, 실행 순서, validation/rollback, 승인 요청 |
60
- | 4 | `implementation` | 승인된 plan 실행, commit, verifier 검증, rollback evidence |
61
- | 5 | `final-verification` | 수용성 검증, residual risk, release-handoff 진입 판단 |
62
- | 6 | `release-handoff` | 사용자가 선택한 commit/push/PR 전달 작업 |
63
-
64
- 각 okstra invocation은 정확히 하나의 task-type만 수행한다. 다음 task-type으로 넘어가려면 새 invocation이 필요하다.
65
-
66
- #### Claude lead 운영 단계
67
-
68
- `prompts/lead/okstra-lead-contract.md` 안의 Phase 1~7은 하나의 task-type run 내부에서 lead가 수행하는 운영 단계다.
69
-
70
- | 운영 단계 | 이름 | 책임 |
71
- |---|---|---|
72
- | 1 | Intake | task bundle 읽기 |
73
- | 2~5 | Prompt / Team / Execution / Fallback | worker prompt 준비, team 생성, worker dispatch |
74
- | 5.5 | Convergence | worker findings 재검증과 consensus 분류 |
75
- | 6 | Synthesis | report-writer dispatch 또는 lead fallback |
76
- | 7 | Persist | token usage 수집, final report placeholder 치환, manifest/status 정리 |
77
-
78
- 따라서 본 문서에서 "P1 convergence 개선"은 task-type lifecycle을 바꾸는 작업이 아니라 `prompts/lead/okstra-lead-contract.md` / `prompts/lead/convergence.md`가 정의하는 lead 운영 단계의 비용을 줄이는 작업이다.
79
-
80
- ### 2.3 prepare 단계의 비용 특성
81
-
82
- `prepare_task_bundle()`은 instruction-set과 manifest 계열 파일을 순차 작성한다.
83
-
84
- - instruction-set: `analysis-profile.md`, `analysis-material.md`, `task-brief.md`, optional carry-in/directive, `reference-expectations.md`, `final-report-template.md`, `claude-execution-prompt.md`, prompt snapshot.
85
- - manifest/discovery: `team-state`, `task-manifest`, `task-index`, `run-manifest`, `timeline`, task catalog, latest task.
86
-
87
- 이 단계의 직렬 render는 개선 여지가 있지만, 일반적으로 external worker dispatch보다 비용이 작다. 따라서 render 병렬화는 1차 목표가 아니다.
88
-
89
- ### 2.4 worker 구조
90
-
91
- 기본 worker 정의는 `agents/workers/` 아래 4종이다.
92
-
93
- - `claude-worker.md`: Claude subagent.
94
- - `codex-worker.md`: `okstra-codex-exec.sh` wrapper를 통해 Codex CLI 호출.
95
- - `antigravity-worker.md`: `okstra-antigravity-exec.sh` wrapper를 통해 Antigravity CLI 호출.
96
- - `report-writer-worker.md`: final-report author. 분석 worker가 아니며 convergence 투표에서 제외된다.
97
-
98
- ## 3. 성능 병목 가설
99
-
100
- | ID | 병목 | 영향도 | 근거 / 확인 위치 | 판정 |
101
- |---|---|---:|---|---|
102
- | B1 | Convergence reverify round가 worker 수만큼 추가 dispatch를 만든다 | 높음 | `prompts/lead/convergence.md` Round 1-N | **해소** — P1 queue pruning 구현 + critic 직렬화 병렬화(§4.1 ②) |
103
- | B2 | analysis worker prompt와 required reading이 길다 | 높음 | `prompts/lead/okstra-lead-contract.md`, `team-contract`, worker definitions | **대부분 해소** — analysis-packet-primary 실측 22KB/worker(§4.1) |
104
- | B3 | report-writer가 worker 결과 + convergence + final-report-template을 다시 읽는다 | ~~중간~~ 낮음 | `prompts/lead/report-writer.md` | **입력 압축 기각** — 실측상 읽기 1~2분, 생성이 지배(§4.1 ③) |
105
- | B4 | prepare 단계에서 여러 render/write가 직렬 수행된다 | 낮음~중간 | `scripts/okstra_ctl/run.py` render block | 후순위 |
106
- | B5 | token usage collector가 session jsonl을 선형 스캔한다 | 낮음~중간 | `scripts/okstra_token_usage/` | **해소** — P6 증분 캐시 구현 완료 |
107
- | B6 | 단순 작업도 같은 full workflow를 탄다 | 중간 | task-type lifecycle / requirements routing | fast-track 설계 필요 — 남은 최대 레버 |
108
- | B7 | report-writer 의 final-report/data.json **생성량 자체**가 크다 (90~140KB) | 높음 | 실측 §4.1 ③ — 생성 8~19분/run | 보고서 계약 슬림화 또는 report-writer 모델 선택 — **사용자 결정 필요** |
109
-
110
- 확정 전제:
111
-
112
- - `contested`는 2라운드 진입 전 존재하는 분류가 아니다. 현재 알고리즘에서 `contested`는 max round에 도달한 뒤 unresolved finding에 붙는 최종 분류다.
113
- - 그러므로 "contested 항목만 2라운드"가 아니라 "1라운드 이후에도 mixed/unresolved인 verification queue만 2라운드"가 올바른 표현이다.
114
-
115
- ## 4. 측정 기준
116
-
117
- 개선 작업은 최소한 아래 지표를 전후 비교한다.
118
-
119
- | 지표 | 수집 방법 | 목표 |
120
- |---|---|---|
121
- | worker dispatch 수 | team-state `workers[]`, convergence state round history, prompt 파일 수 | P1 적용 run에서 reverify dispatch 감소 |
122
- | wall-clock | team-state worker usage `durationMs`, run start/end timestamp | convergence-heavy run에서 20~40% 단축 |
123
- | raw token | token usage collector의 lead/worker total | reverify prompt 관련 worker token 감소 |
124
- | billable equivalent | `usageSummary.*BillableEquivalentTokens` | 비용 감소 확인 |
125
- | 품질 손상 여부 | final report의 contested/worker-unique 누락 여부, validator 통과 | 기존 contract 유지 |
126
-
127
- P1 구현 전 최소 fixture:
128
-
129
- 1. early convergence 사례: Round 0 또는 Round 1에서 verification queue가 비는 run.
130
- 2. mixed/unresolved 사례: Round 1 후 일부 finding만 남아 선택적 Round 2가 필요한 run.
131
- 3. worker failure 사례: reverify dispatch 일부가 `timeout`/`error`인 run.
132
-
133
- ### 4.1 실측 결과 (2026-06-11, fontradar-v2-api dev-9186)
134
-
135
- 실 run 3개(req-discovery / impl-planning / implementation stage-1)의 산출물 mtime, team-state `phaseTimeline`, report-writer 세션 jsonl 툴콜 타임라인으로 측정했다.
136
-
137
- ① **run 단계별 wall 분해** — 분석 run 에서 "본 분석"은 wall 의 17~24%에 불과하다. 셋업 4~6분 / 분석 16~24분 / convergence+critic 23분 / report-writer 12~24분.
138
-
139
- ② **critic 직렬화** — reverify 종료 후에야 critic 이 디스패치되어 런당 6~12분이 직렬로 낭비됐다. critic 입력은 Round 0 통합 결과로 고정이므로 첫 reverify 라운드와 병렬 디스패치로 변경했다 (`prompts/lead/convergence.md` §When).
140
-
141
- ③ **report-writer 는 생성 지배** — 세션 툴콜 실측: 전체 입력(~404KB, 16 files) 읽기는 **1~2분**, data.json 생성(스켈레톤 Write 후 섹션별 Edit 증분 작성)이 **8~19분**, 자체 검증·audit 이 ~3분. 따라서 B3 입력 압축의 wall 절감은 ~1분 수준이라 **기각**. 남는 레버는 출력 측(B7): 보고서 계약 슬림화(품질 trade-off, 사용자 결정) 또는 `--report-writer-model` 하향(기존 knob).
142
-
143
- ④ **계측 자동화** — Phase 7 수집기가 lead 의 `PROGRESS: phase-*` 마커를 추출해 team-state `phaseTimeline` 으로 영속한다 (`scripts/okstra_token_usage/collect.py :: phase_timeline`). 이후 run 부터 본 섹션의 ①을 수작업 mtime 분석 없이 `/okstra-inspect time` 으로 확인할 수 있다. `okstra context-cost` 의 reportWriter 표면도 실 dispatch 계약(현재 seq + analysis-packet)에 정렬했다.
144
-
145
- ## 5. 개선 우선순위
146
-
147
- ### P0. Baseline 계측과 용어 정리
148
-
149
- 목표:
150
-
151
- - 문서와 코드에서 task-type lifecycle과 lead 운영 단계를 혼동하지 않게 한다.
152
- - convergence state에 `effectiveMaxRounds`, `roundsExecuted`, `dispatchCount`, `queueSizeByRound`, `finalClassificationCounts`를 명시하도록 P1에서 사용할 기준을 정한다.
153
-
154
- 주요 변경 후보:
155
-
156
- - `prompts/lead/convergence.md`
157
- - `prompts/lead/okstra-lead-contract.md`
158
- - 필요 시 convergence state schema 설명
159
-
160
- 완료 기준:
161
-
162
- - 문서가 `contested`를 중간 queue 이름으로 쓰지 않는다.
163
- - 전후 비교에 필요한 지표가 final report 또는 state artifact에서 확인 가능하다.
164
-
165
- ### P1. Convergence 재검증 범위 축소
166
-
167
- 목표:
168
-
169
- - 기본 동작은 1라운드에서 확정 가능한 finding을 즉시 종료한다.
170
- - 2라운드는 Round 1 이후에도 `mixed` 또는 `unresolved` 상태로 남은 verification queue에만 수행한다.
171
- - `full-consensus`, `partial-consensus`, `worker-unique`로 이미 확정된 finding은 다시 worker에게 보내지 않는다.
172
-
173
- 현재 문제:
174
-
175
- - `maxRounds=2`인 task-type에서 Round 1 이후 남은 항목과 이미 확정된 항목의 경계가 문서상 충분히 강하지 않다.
176
- - "모든 항목 재검증"으로 운영되면 worker 수만큼 불필요한 re-dispatch가 늘어난다.
177
-
178
- 개선 알고리즘:
179
-
180
- ```text
181
- Round 0:
182
- worker 결과를 parsing/grouping한다.
183
- 2명 이상이 같은 semantics + 같은 ticket set에 동의하면 full-consensus로 확정한다.
184
- 단일 worker finding만 verification queue에 넣는다.
185
-
186
- Round 1:
187
- queue 항목만 worker별 batch로 재검증한다.
188
- all agree/supplement -> full-consensus로 확정하고 queue에서 제거한다.
189
- majority agree/supplement -> partial-consensus로 확정하고 queue에서 제거한다.
190
- all disagree -> worker-unique로 확정하고 queue에서 제거한다.
191
- mixed/error/insufficient evidence -> unresolved queue에 남긴다.
192
-
193
- Optional Round 2:
194
- unresolved queue가 비어 있으면 실행하지 않는다.
195
- unresolved queue가 있으면 해당 항목만 재검증한다.
196
- Round 2 이후에도 남은 항목은 최종 분류한다:
197
- majority agreement -> partial-consensus
198
- otherwise -> contested
199
- ```
200
-
201
- 2라운드 진입 조건:
202
-
203
- - `effectiveMaxRounds >= 2`
204
- - Round 1 종료 후 unresolved queue가 비어 있지 않음
205
- - unresolved 원인이 단순 worker failure 전부가 아님. 모든 재검증 worker가 terminal non-result이면 추가 dispatch 대신 `verification-error`/blocked evidence를 기록한다.
206
-
207
- 변경 대상:
208
-
209
- - `prompts/lead/convergence.md`: Round 1 이후 queue pruning, Round 2 gate, state artifact 필드 명시.
210
- - `prompts/lead/okstra-lead-contract.md`: `convergence.maxRounds` 설명을 queue-pruned 동작과 맞춘다.
211
- - `prompts/lead/report-writer.md`: final report가 round history와 skipped Round 2 사유를 기록하도록 확인.
212
- - 필요 시 validator 또는 tests: convergence state에 새 필드를 요구하는 경우에만 추가.
213
-
214
- 완료 기준:
215
-
216
- - Round 1에서 확정된 finding이 Round 2 prompt에 다시 포함되지 않는다.
217
- - Round 2가 실행되지 않은 경우 state에 `skippedReason`이 남는다.
218
- - final report에는 네 분류(`Full Consensus`, `Partial Consensus`, `Contested`, `Worker-Unique`)가 계속 모두 표현된다.
219
-
220
- ### P2. Prompt diet: analysis worker 입력 축소
221
-
222
- 목표:
223
-
224
- - analysis worker에게 final-report-template을 읽히지 않는 현재 원칙을 유지하고, 실제 dispatch prompt에도 불필요한 report-writer 전용 자료가 섞이지 않게 한다.
225
- - worker definitions의 반복 문구는 줄이되, path extraction / model line / error sidecar 같은 blocking contract는 유지한다.
226
-
227
- 주의:
228
-
229
- - `agents/workers/_common.md` 추출은 설치/packaging 경로와 skill/agent 로더가 include를 지원하는지 먼저 확인해야 한다.
230
- - 단순히 별도 파일로 빼는 것은 runtime에서 자동 inline되지 않으면 오히려 worker가 파일을 더 읽어야 하므로 비용이 줄지 않을 수 있다.
231
-
232
- 변경 대상:
233
-
234
- - `agents/workers/codex-worker.md`
235
- - `agents/workers/antigravity-worker.md`
236
- - `prompts/lead/team-contract.md`
237
- - 설치/build packaging
238
-
239
- ### P3. Fast-track routing
240
-
241
- 목표:
242
-
243
- - 단순 docs-only, typo, 명확한 1-file fix처럼 full lifecycle이 과한 작업을 더 짧은 경로로 보낸다.
244
-
245
- 권장 설계:
246
-
247
- - task-type lifecycle 자체를 임의로 건너뛰기보다 `requirements-discovery`가 `route=lite-implementation-planning` 또는 `route=direct-implementation-planning` 같은 명시적 routing token을 남긴다.
248
- - source edit은 여전히 `implementation` task-type에서만 수행한다.
249
- - 최소 검증은 `final-verification` 또는 equivalent read-only check로 남긴다.
250
-
251
- 변경 대상:
252
-
253
- - `prompts/profiles/requirements-discovery.md`
254
- - `scripts/okstra_ctl/workflow.py`
255
- - `skills/okstra-run/SKILL.md`의 next phase 선택 UI
256
- - `skills/okstra-status/SKILL.md`
257
- - validator 기대값
258
-
259
- 주의:
260
-
261
- - "fast-track"이 implementation-planning approval gate를 우회하면 single reference point와 승인 계약이 깨진다. 승인 게이트를 줄일지 없앨지는 별도 사용자 결정이 필요하다.
262
-
263
- ### P4. Prompt caching 가능성 검증
264
-
265
- 목표:
266
-
267
- - 지원되는 transport에서만 prompt cache를 활용한다.
268
-
269
- 현재 불확실성:
270
-
271
- - `render.py`는 Markdown 파일을 렌더링한다.
272
- - Codex/Antigravity wrapper는 prompt 파일을 CLI stdin으로 전달한다.
273
- - 이 경로에서 `cache_control: ephemeral` 같은 API-level metadata가 실제로 전달되는지 명확하지 않다.
274
-
275
- 따라서 P4는 바로 구현하지 말고 spike로 시작한다.
276
-
277
- 검증 항목:
278
-
279
- - Claude Agent dispatch prompt에서 cache hint를 표현할 수 있는지.
280
- - Codex CLI stdin prompt에서 cache hint가 의미를 갖는지.
281
- - Antigravity CLI에서 대응 기능이 있는지.
282
- - token usage collector가 cache read/create 변화를 관측할 수 있는지.
283
-
284
- ### P5. Prepare render 병렬화
285
-
286
- 목표:
287
-
288
- - prepare 단계의 독립 파일 render/write를 병렬화한다.
289
-
290
- 주의:
291
-
292
- - `prepare_task_bundle()`이 single authority이므로 병렬화를 하더라도 호출자는 그대로 유지한다.
293
- - manifest/discovery render는 같은 ctx와 파일 순서 의존성이 있으므로 무리하게 섞지 않는다.
294
- - 우선 instruction-set의 독립 write만 검토한다.
295
-
296
- 예상 효과:
297
-
298
- - worker dispatch 비용에 비해 작다.
299
- - render-only smoke test가 많은 환경에서는 체감될 수 있다.
300
-
301
- ### P6. Token usage 증분화
302
-
303
- 목표:
304
-
305
- - 매번 전체 session jsonl을 선형 스캔하지 않고, 이전 offset 또는 session summary cache를 활용한다.
306
-
307
- 주의:
308
-
309
- - Phase 7에서 final-report placeholder substitution과 연결되어 있으므로 정확성이 성능보다 중요하다.
310
- - 재실행/재시도/여러 subagent session aggregate를 깨뜨리면 안 된다.
311
-
312
- ## 6. 병렬 작업 계획
313
-
314
- | 트랙 | 작업 | 주요 파일 | 병렬 가능성 | 선행 조건 |
315
- |---|---|---|---|---|
316
- | A | P1 convergence queue pruning | `prompts/lead/convergence.md`, `prompts/lead/okstra-lead-contract.md`, report-writer contract | 높음 | P0 용어 정리 |
317
- | B | P3 fast-track routing | requirements profile, workflow/status/run UI | 중간 | P0 완료, 승인 게이트 정책 결정 |
318
- | C | P5 prepare render 병렬화 | `scripts/okstra_ctl/run.py`, render tests | 높음 | 없음 |
319
- | D | P2 prompt diet | worker definitions, team contract, packaging | 중간 | P1 후 권장 |
320
- | E | P4 prompt cache spike | wrapper/dispatch 경로별 실험 | 높음 | 없음 |
321
- | F | P6 token usage 증분화 | `scripts/okstra_token_usage/` | 높음 | collector fixture 필요 |
322
-
323
- 권장 순서:
324
-
325
- 1. 트랙 A(P1)를 먼저 수행한다. 가장 큰 비용을 직접 줄이고, 계약 변경 범위가 문서/lead 운영 단계에 집중된다.
326
- 2. 트랙 C(P5) 또는 E(P4 spike)는 병렬로 가능하다.
327
- 3. 트랙 B(P3)는 승인 게이트와 lifecycle semantics를 건드리므로 별도 설계 리뷰 후 진행한다.
328
- 4. 트랙 D(P2)는 P1 이후 prompt contract가 안정된 뒤 진행한다.
329
-
330
- ## 7. P1 구현 체크리스트
331
-
332
- 1. `prompts/lead/convergence.md`의 Round 1-N pseudocode를 queue pruning 방식으로 수정한다.
333
- 2. `contested`를 중간 상태로 쓰지 않고, `unresolved` 또는 `mixed-after-round-1`을 2라운드 후보 이름으로 쓴다.
334
- 3. convergence state artifact에 다음 필드를 명시한다.
335
- - `config.effectiveMaxRounds`
336
- - `rounds[].inputQueueSize`
337
- - `rounds[].resolvedCount`
338
- - `rounds[].carriedForwardCount`
339
- - `rounds[].dispatches[]`
340
- - `rounds[].skippedWorkers[]`
341
- - `finalClassificationCounts`
342
- - `round2SkippedReason`
343
- 4. report-writer contract가 round history와 final classification counts를 final report에 반영하도록 점검한다.
344
- 5. 단순 early convergence fixture와 mixed/unresolved fixture를 만들어 dry-run 또는 contract-level test를 수행한다.
345
- 6. token usage collector 결과로 dispatch/token/wall-clock 전후를 기록한다.
346
-
347
- ## 8. 리스크와 방어선
348
-
349
- - **동조 hallucination 위험**: 1라운드에서 다수 worker가 같은 잘못된 결론을 내면 추가 검증이 줄어든다. 방어선은 `verificationMode=full-reanalysis` opt-in과 evidence quality check다.
350
- - **worker failure 오분류 위험**: worker가 timeout/error인데 disagreement처럼 처리하면 `contested`가 왜곡된다. terminal non-result는 vote가 아니라 `verification-error` evidence로 분리한다.
351
- - **fast-track 오판 위험**: 단순 작업으로 오분류하면 승인/검증이 부족해질 수 있다. P3는 approval gate 우회 여부를 별도 정책으로 결정해야 한다.
352
- - **캐싱 착시 위험**: API-level cache hint가 CLI stdin 경로에서 무시될 수 있다. P4는 구현 전 spike가 필수다.
353
- - **템플릿 축소로 validator 실패**: final-report heading이나 token placeholder를 줄이면 `validate-run.py`와 Phase 7 substitution이 깨질 수 있다. P2/P4는 validator 계약을 먼저 열거해야 한다.
354
-
355
- ## 9. 이번 계획의 결론
356
-
357
- 현재 작업 계획은 P1을 최우선으로 둔 방향은 맞지만, 기존 표현의 "7-phase lifecycle"과 "contested-only 2라운드"는 코드와 맞지 않았다. 개선된 계획은 다음처럼 재정렬한다.
358
-
359
- 1. P0로 용어와 측정 기준을 고정한다.
360
- 2. P1에서 convergence queue pruning을 구현한다.
361
- 3. P3 fast-track과 P4 prompt caching은 별도 설계/검증이 필요한 후속 작업으로 둔다.
362
- 4. prepare render 병렬화와 token usage 증분화는 효과가 작거나 종료 단계 비용이므로 P1 이후 병렬 보조 작업으로 처리한다.
363
-
364
- **2026-06-11 갱신** — §4.1 실측으로 P0/P1/P6 + critic 병렬화 + phaseTimeline 계측이 완료됐고, B3(report-writer 입력 압축)는 기각됐다. 남은 우선순위는 두 개뿐이며 둘 다 사용자 결정이 선행한다:
365
-
366
- 1. **B7 — report-writer 출력 측 단축**: 보고서 계약 슬림화(템플릿/스키마 축소, validator 계약 변경 수반) 또는 기본 report-writer 모델 하향. 런당 5~12분 절감 추정.
367
- 2. **B6/P3 — fast-track routing**: 단순 작업의 lifecycle 단축. 승인 게이트 정책 결정 필요.
368
-
369
- ### 구현 plan 링크
370
-
371
- - P0 + P1: 구현 완료 — convergence state v1.2 에 반영
372
- - P6: 구현 완료 — token usage 증분 스캔에 반영
373
- - critic 병렬화 + phaseTimeline 계측: plan 없이 직접 구현 (2026-06-11, `CHANGES.md` 해당 항목 참조)
374
- - P3 / P4 / P5 / B7: 미작성 (각 트랙별로 별도 plan 작성 필요)