okstra 0.19.1 → 0.20.1
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/README.kr.md +4 -4
- package/README.md +4 -4
- package/docs/kr/architecture.md +13 -1
- package/docs/kr/cli.md +18 -0
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/codex-worker.md +6 -4
- package/runtime/agents/workers/gemini-worker.md +6 -4
- package/runtime/bin/okstra-codex-exec.sh +5 -6
- package/runtime/bin/okstra-gemini-exec.sh +6 -8
- package/runtime/python/okstra_ctl/run.py +0 -6
- package/runtime/python/okstra_ctl/worktree.py +0 -3
- package/runtime/python/okstra_token_usage/blocks.py +0 -2
- package/runtime/python/okstra_token_usage/claude.py +0 -2
package/README.kr.md
CHANGED
|
@@ -28,7 +28,7 @@ okstra/ npm 패키지 = repo 루트
|
|
|
28
28
|
├── tools/build.mjs runtime/ 동기화 스크립트 (prepack 에서 호출)
|
|
29
29
|
├── runtime/ gitignored 빌드 산출물; ~/.okstra 로 배포되는 유일한 자산
|
|
30
30
|
├── scripts/ python + bash 런타임 소스
|
|
31
|
-
├── skills/ Claude Code 스킬 마크다운 소스 (스킬
|
|
31
|
+
├── skills/ Claude Code 스킬 마크다운 소스 (스킬 12종)
|
|
32
32
|
├── agents/ lead SKILL.md + workers/
|
|
33
33
|
├── prompts/, templates/, validators/
|
|
34
34
|
├── docs/kr/ 한국어 상세 매뉴얼 (architecture.md, cli.md)
|
|
@@ -56,7 +56,7 @@ okstra/ npm 패키지 = repo 루트
|
|
|
56
56
|
└── archive/ 완료된 run
|
|
57
57
|
|
|
58
58
|
~/.claude/skills/ Claude Code 가 자동 인식
|
|
59
|
-
└── okstra-*/SKILL.md 스킬
|
|
59
|
+
└── okstra-*/SKILL.md 스킬 12종 (§3.3 참조)
|
|
60
60
|
|
|
61
61
|
~/.claude/agents/ Claude Code 가 자동 인식 (subagent 디스커버리 경로)
|
|
62
62
|
└── {claude,codex,gemini,report-writer}-worker.md worker subagent 정의
|
|
@@ -87,7 +87,7 @@ okstra/ npm 패키지 = repo 루트
|
|
|
87
87
|
npx -y okstra@latest install
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
`~/.okstra/{lib/python, bin, version}`, `~/.claude/skills/` 아래 스킬 마크다운
|
|
90
|
+
`~/.okstra/{lib/python, bin, version}`, `~/.claude/skills/` 아래 스킬 마크다운 12개, `~/.okstra/installed-skills.json` 을 생성합니다. 재실행은 idempotent — 파일별 hash 를 비교하고 바뀐 파일만 갱신합니다.
|
|
91
91
|
|
|
92
92
|
검증:
|
|
93
93
|
|
|
@@ -140,7 +140,7 @@ Claude Code 세션 안에서 사용하는 슬래시 커맨드:
|
|
|
140
140
|
| `/okstra-schedule` | task-group 전체에 대한 작업 계획표 생성 |
|
|
141
141
|
| `/okstra-setup` | 프로젝트별 부트스트랩 (§3.2) |
|
|
142
142
|
|
|
143
|
-
이 외에 `okstra-context-loader`, `okstra-team-contract`, `okstra-convergence`, `okstra-report-writer`, `okstra-time-summary`, `okstra-report-finder`
|
|
143
|
+
이 외에 `okstra-context-loader`, `okstra-team-contract`, `okstra-convergence`, `okstra-report-writer`, `okstra-time-summary`, `okstra-report-finder`, `okstra-logs` 7종은 `user-invocable: false` 로 표시되어 슬래시 커맨드로 노출되지 않습니다. lead 또는 Claude 가 자연어 트리거(예: "이 task 얼마나 걸렸어?" → `okstra-time-summary`, "보고서 찾아줘" → `okstra-report-finder`, "codex/gemini 로그 용량 보여줘" → `okstra-logs` — wrapper 가 매 dispatch 마다 남기는 `<prompt>.log` sidecar 의 용량을 집계하고 task / phase / worker 별로 즉시 복사 가능한 `find … -delete` cleanup 명령을 제시하되 직접 실행하지는 않음)로 자동 호출합니다.
|
|
144
144
|
|
|
145
145
|
### 3.4 CLI 모드 (선택)
|
|
146
146
|
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ okstra/ npm package = repo root
|
|
|
28
28
|
├── tools/build.mjs runtime/ sync script (invoked by prepack)
|
|
29
29
|
├── runtime/ gitignored build output; the only thing shipped to ~/.okstra
|
|
30
30
|
├── scripts/ python + bash runtime sources
|
|
31
|
-
├── skills/ Claude Code skill markdown sources (
|
|
31
|
+
├── skills/ Claude Code skill markdown sources (12 skills)
|
|
32
32
|
├── agents/ lead SKILL.md + workers/
|
|
33
33
|
├── prompts/, templates/, validators/
|
|
34
34
|
├── tests/, tests-e2e/
|
|
@@ -55,7 +55,7 @@ okstra/ npm package = repo root
|
|
|
55
55
|
└── archive/ completed runs
|
|
56
56
|
|
|
57
57
|
~/.claude/skills/ discovered automatically by Claude Code
|
|
58
|
-
└── okstra-*/SKILL.md
|
|
58
|
+
└── okstra-*/SKILL.md 12 skills total (see §3.3)
|
|
59
59
|
|
|
60
60
|
~/.claude/agents/ discovered automatically by Claude Code
|
|
61
61
|
└── {claude,codex,gemini,report-writer}-worker.md subagent definitions
|
|
@@ -86,7 +86,7 @@ okstra/ npm package = repo root
|
|
|
86
86
|
npx -y okstra@latest install
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
Provisions `~/.okstra/{lib/python, bin, version}`, the
|
|
89
|
+
Provisions `~/.okstra/{lib/python, bin, version}`, the 12 skill markdown files under `~/.claude/skills/`, and `~/.okstra/installed-skills.json`. Re-running is idempotent — per-file hashes are compared and only changed files are touched.
|
|
90
90
|
|
|
91
91
|
Verify:
|
|
92
92
|
|
|
@@ -139,7 +139,7 @@ User-facing slash commands inside a Claude Code session:
|
|
|
139
139
|
| `/okstra-schedule` | Generate a work schedule for an entire task-group |
|
|
140
140
|
| `/okstra-setup` | Per-project bootstrap (§3.2) |
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
Seven additional skills — `okstra-context-loader`, `okstra-team-contract`, `okstra-convergence`, `okstra-report-writer`, `okstra-time-summary`, `okstra-report-finder`, `okstra-logs` — are marked `user-invocable: false` and do not appear as slash commands. Claude still invokes them automatically via natural-language triggers (e.g. "이 task 얼마나 걸렸어?" routes to `okstra-time-summary`; "show me the report for X" routes to `okstra-report-finder`; "codex/gemini 로그 용량 보여줘" routes to `okstra-logs`, which inventories the `<prompt>.log` sidecars produced by every CLI dispatch and emits ready-to-copy `find … -delete` cleanup lines without executing them).
|
|
143
143
|
|
|
144
144
|
### 3.4 CLI mode (optional)
|
|
145
145
|
|
package/docs/kr/architecture.md
CHANGED
|
@@ -149,7 +149,7 @@ okstra 의 prepare 책임은 단일 python 진입점 [`okstra_ctl.run.prepare_ta
|
|
|
149
149
|
- [`agents/SKILL.md`](agents/SKILL.md) — main okstra skill (cross-verify 트리거).
|
|
150
150
|
- [`skills/okstra-setup/SKILL.md`](skills/okstra-setup/SKILL.md) — **첫 실행 부트스트랩**. `okstra install` + `project.json` 생성.
|
|
151
151
|
- [`skills/okstra-run/SKILL.md`](skills/okstra-run/SKILL.md) — **현재 claude 세션 안에서 okstra task 를 시작**하는 in-session 진입점. `prepare_task_bundle` 직접 호출.
|
|
152
|
-
- `skills/okstra-{status,history,convergence,schedule,context-loader,team-contract,report-finder,report-writer,time-summary}/SKILL.md` — phase 진행·status·history 보조 skill.
|
|
152
|
+
- `skills/okstra-{status,history,convergence,schedule,context-loader,team-contract,report-finder,report-writer,time-summary,logs}/SKILL.md` — phase 진행·status·history 보조 skill. `okstra-logs` 는 codex/gemini wrapper 가 매 dispatch 마다 `runs/<task-type>/prompts/<worker>-prompt-<phase>-<seq>.log` 로 남기는 live-log sidecar 의 인벤토리·정리 안내 (read-only, find-delete cleanup 명령 제안만 함).
|
|
153
153
|
- 플러그인 매니페스트: [`.claude-plugin/plugin.json`](.claude-plugin/plugin.json) — `npx skills@latest add Devonshin/okstra` 보조 채널이 참조. 0.3.0 부터는 `npx okstra install` 한 명령이 동일 결과를 보장하므로 일반 셋업에는 이 채널이 필요 없다.
|
|
154
154
|
- 설치 위치: `~/.claude/skills/<name>/SKILL.md` (`okstra-install.sh` dev 설치, 또는 위 npx 채널).
|
|
155
155
|
- 릴리스 절차: [`RELEASING.md`](RELEASING.md) — npm publish 흐름과 GitHub Actions 워크플로(`v*.*.*` tag → 자동 publish), 자동화 토큰 셋업, 검증/롤백.
|
|
@@ -828,10 +828,22 @@ Claude가 작성하는 최종 보고서는 brief에 더 구체적인 형식이
|
|
|
828
828
|
- `source` 필드(`worker-reported` | `lead-observed`)와 `errorType`(`tool-failure` | `cli-failure` | `contract-violation`)으로 발생원과 종류를 구분합니다.
|
|
829
829
|
- `stderrExcerpt`는 한 줄 jsonl 가독성을 위해 2KB 상한, `PIPE_BUF`(4096B) atomic append 가드를 강제합니다.
|
|
830
830
|
- run-manifest 또는 team-state의 `errorsLogPath` 필드에 `logs/errors-<task-type>-<seq>.jsonl` 경로를 1회 기록해 발견 가능하게 합니다.
|
|
831
|
+
- Path delivery 와이어링 (`f6f9f69`): `scripts/okstra_ctl/paths.py` 가 `RUN_ERRORS_LOG_FILE` / `RUN_ERRORS_LOG_RELATIVE_PATH` 와 worker 별 sidecar 경로를 export 하고, `scripts/okstra_ctl/render.py` 가 `{{RUN_ERRORS_LOG_PATH}}` / `{{<WORKER>_ERRORS_SIDECAR_PATH}}` 템플릿 토큰을 노출합니다. `prompts/launch.template.md` 의 `## Run Logs (error-log wiring)` 섹션이 resolved absolute path 를 lead 에 전달하고, lead 는 이를 worker dispatch prompt 의 `**Errors log path:**` / `**Errors sidecar path:**` 라인으로 forward 해야 합니다 — literal `<runDir>/logs/...` template fragment 만 들고 있을 때 worker 가 argparse-exit 으로 entry 를 흘리는 회귀가 있어 path delivery 가 정식 contract 화 됐습니다.
|
|
831
832
|
- Helper CLI: `scripts/okstra-error-log.py`
|
|
832
833
|
- 단일 진입점으로 record를 append 합니다.
|
|
833
834
|
- 워커 sidecar dump(`append_observed`, schema version 가드)와 lead 관찰(`lead-observed`) 모두 동일 helper를 사용합니다.
|
|
834
835
|
|
|
836
|
+
### Live-log mirror (codex / gemini wrapper)
|
|
837
|
+
|
|
838
|
+
- `scripts/okstra-codex-exec.sh`, `scripts/okstra-gemini-exec.sh` 는 dispatch 마다 prompt path 옆에 `<prompt>.log` sidecar 를 만들고 stdout 을 거기로 mirror 합니다 (`tee`, `PIPESTATUS[0]` 로 종료코드 보존). stderr 은 같은 파일에 append (subagent stderr 캡처 contract 보존), 매 dispatch 시 truncate. 호출 subagent 의 `BashOutput` 폴링은 60s 간격이라 long-running run (analysis 의 large-codebase scan, implementation 의 cargo / pytest) 동안 사용자가 stalled state 를 탐지할 수 없는 문제를 해소합니다.
|
|
839
|
+
- `$TMUX` 가 셋팅된 lead 환경이면 wrapper 가 sibling pane 을 자동 분할해 `tail -F <log-path>` 를 띄웁니다. pane title 은 `<cli>-<role>-trace` (e.g. `codex-worker-trace`, `gemini-worker-trace`); role 은 wrapper 의 5번째 optional positional 인자이며, 누락 시 기본값 `worker` 로 떨어집니다. caller 가 다른 라벨(예: `executor`)을 원하면 5번째 인자로 명시해야 합니다. focus 는 caller pane 으로 복귀하고, CLI 종료 후 pane 은 유지돼 스크롤백 가능. `$TMUX` 미설정, split 실패, 구버전 tmux 등 모든 경로는 silent degrade.
|
|
840
|
+
- 디스크 누적은 `okstra-logs` skill 이 read-only 로 인벤토리 + cleanup 명령을 제안합니다 (실행은 사용자 copy-paste).
|
|
841
|
+
|
|
842
|
+
### Linked-worktree `.git/` write 권한 (codex / gemini)
|
|
843
|
+
|
|
844
|
+
- `--executor codex|gemini` 의 worktree 안에서 `git add` / `git commit` 은 main repo 의 per-worktree metadata (`<main-repo>/.git/worktrees/<name>/index`, refs, HEAD) 와 shared object DB (`<main-repo>/.git/objects/`) 에 써야 하지만, 이 경로는 worktree directory 밖이라 단순히 worktree path 만 sandbox 에 열어주면 index.lock 생성 시 EPERM 으로 실패합니다 (executor 가 step commit contract 를 만족하지 못해 edit 을 revert 하고 종료).
|
|
845
|
+
- wrapper 가 worktree 안에서 `git -C <worktree> rev-parse --git-common-dir` 로 main repo `.git/` 절대경로를 해석하고 `--add-dir <main-repo>/.git` (codex) 또는 `--include-directories <main-repo>/.git` append (gemini) 로 sandbox 에 함께 forward 합니다.
|
|
846
|
+
|
|
835
847
|
상세 설계 및 jq 회고 레시피는 `docs/superpowers/specs/2026-04-28-worker-error-collection-design.md`를 참고합니다.
|
|
836
848
|
|
|
837
849
|
## Token usage and cost accounting
|
package/docs/kr/cli.md
CHANGED
|
@@ -481,3 +481,21 @@ chmod +x ~/.local/bin/okstra-ctl
|
|
|
481
481
|
| 활성 run 재조정 | `okstra-ctl reconcile [--project <id|all>]` |
|
|
482
482
|
| 배치 진행 | `okstra-ctl batch status <batch-id>` |
|
|
483
483
|
|
|
484
|
+
### `okstra` Node CLI — introspection subcommands
|
|
485
|
+
|
|
486
|
+
`okstra` Node CLI (`bin/okstra`) 가 skill / agent 에서 사용하는 read-only introspection subcommand 를 제공합니다. 모두 JSON 을 stdout 으로 emit 합니다. 별도 python heredoc 대신 단일 allowlisted command 로 호출 가능 — Claude Code 가 매 호출마다 permission prompt 를 띄우지 않습니다 (`Bash(okstra:*)` 가 runtime settings template 의 allow 룰에 포함).
|
|
487
|
+
|
|
488
|
+
| 명령 | 용도 |
|
|
489
|
+
|---|---|
|
|
490
|
+
| `okstra task-list [--project-root <path>]` | `list_project_tasks` + `read_latest_task` 결과를 합쳐 task 카탈로그 + 최근 task 를 JSON 으로 반환 |
|
|
491
|
+
| `okstra task-show <task-key> [--project-root <path>]` | task-manifest.json 의 workflow / phase / status 요약 |
|
|
492
|
+
| `okstra worktree-lookup <task-key>` | `worktree_registry.lookup` 결과 (예약된 path / branch / base ref / 현재 상태) |
|
|
493
|
+
| `okstra plan-validate <plan-path>` | `_validate_approved_plan` — approval marker 인식 결과와 sanitization 후 diff |
|
|
494
|
+
| `okstra render-bundle <args…>` | `prepare_task_bundle(render_only=True)` 의 thin shim — `python3 -m okstra_ctl.run --render-only` 와 동일 시그니처 |
|
|
495
|
+
|
|
496
|
+
> 모든 subcommand 는 `bin/okstra` 가 spawn 하는 python 헬퍼 (`src/_python-helper.mjs`) 가 `PYTHONPATH` 와 `~/.okstra/lib/python` 을 wire 합니다. 직접 `python3 -m okstra_ctl.*` 으로 호출하면 `PYTHONPATH` 를 사용자가 직접 셋업해야 합니다.
|
|
497
|
+
|
|
498
|
+
### Live-log sidecar
|
|
499
|
+
|
|
500
|
+
codex / gemini wrapper 는 매 dispatch 마다 `runs/<task-type>/prompts/<worker>-prompt-<phase>-<seq>.log` sidecar 를 만들고 stdout / stderr 를 mirror 합니다. tmux 안에서 lead 를 띄우면 wrapper 가 자동으로 `tail -F` pane 을 분할합니다 (title: `<cli>-<role>-trace`). 사용량 인벤토리와 `find … -delete` cleanup 명령은 `okstra-logs` skill 이 read-only 로 제안합니다. 자세한 와이어링은 [`docs/kr/architecture.md`](architecture.md) 의 *Live-log mirror* 절 참고.
|
|
501
|
+
|
package/package.json
CHANGED
package/runtime/BUILD.json
CHANGED
|
@@ -27,9 +27,11 @@ You are a Codex worker agent. Your job is to execute the OpenAI Codex CLI and re
|
|
|
27
27
|
|
|
28
28
|
**Required form (uses the okstra wrapper to avoid redirect-triggered permission prompts):**
|
|
29
29
|
```bash
|
|
30
|
-
$HOME/.okstra/bin/okstra-codex-exec.sh "<absolute-project-root>" "<assigned-model-execution-value>" "<absolute-prompt-history-path>" [<absolute-worktree-path>]
|
|
30
|
+
$HOME/.okstra/bin/okstra-codex-exec.sh "<absolute-project-root>" "<assigned-model-execution-value>" "<absolute-prompt-history-path>" [<absolute-worktree-path>] [<role>]
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
The fifth argument `<role>` is the trace-pane label suffix (`codex-<role>-trace`); pass the literal string `worker` for every dispatch from this subagent. The wrapper defaults to `worker` when the argument is omitted, but pass it explicitly so the dispatch is self-describing.
|
|
34
|
+
|
|
33
35
|
The fourth argument is **mandatory for implementation phase** and optional otherwise. It must be the literal `EXECUTOR_WORKTREE_PATH` recorded in the run context; the wrapper forwards it to codex as `--add-dir`, which grants the codex sandbox write access to the worktree (where all implementation-phase mutations occur). Without it, codex's `workspace-write` sandbox is anchored only at `<project-root>` and rejects every Edit/Write that targets the worktree (EPERM), which is the failure pattern that originally motivated this argument.
|
|
34
36
|
|
|
35
37
|
The wrapper internally runs:
|
|
@@ -73,7 +75,7 @@ The wrapper exists because Claude Code's Bash permission matcher rejects simple-
|
|
|
73
75
|
|
|
74
76
|
**Dispatch (background, no foreground timeout):**
|
|
75
77
|
```bash
|
|
76
|
-
$HOME/.okstra/bin/okstra-codex-exec.sh "<absolute-project-root>" "<assigned-model-execution-value>" "<absolute-prompt-history-path>" "<absolute-worktree-path>"
|
|
78
|
+
$HOME/.okstra/bin/okstra-codex-exec.sh "<absolute-project-root>" "<assigned-model-execution-value>" "<absolute-prompt-history-path>" "<absolute-worktree-path>" "worker"
|
|
77
79
|
```
|
|
78
80
|
Call `Bash` with `run_in_background: true`. Capture the returned `bash_id` (a.k.a. `shell_id`). Pass the positional arguments verbatim — do NOT use environment variables, `cd`, `&&` chains, or pipes from `cat`. Substitute the literal extracted Project Root, model execution value, prompt-history path, and worktree path. The fourth argument is **mandatory for implementation phase** (extract from `EXECUTOR_WORKTREE_PATH` in the lead prompt's run context or the `**Worktree:**` / `cwd for every mutating command:` line) and **may be omitted only for non-implementation analysis phases** that do not mutate the worktree. Omitting it during implementation will cause every Edit/Write to fail with EPERM. The wrapper handles `-C`, `--add-dir`, `--model`, `--sandbox workspace-write`, the stdin redirect from the prompt file, and stderr suppression internally. Calling `codex exec` directly (without the wrapper) is an error in this skill: the redirect tokens disqualify the prefix match against `Bash(codex exec:*)` and produce a permission prompt every dispatch.
|
|
79
81
|
|
|
@@ -114,7 +116,7 @@ This wrapper does NOT invoke MCP tools directly. MCP availability inside the Cod
|
|
|
114
116
|
- Include context (code, diff, file paths) if provided.
|
|
115
117
|
- For long prompts, the wrapper script reads from the saved project-local prompt history file via stdin redirect internally. The caller invokes the wrapper with three required positional args + the worktree path for implementation phase:
|
|
116
118
|
```bash
|
|
117
|
-
$HOME/.okstra/bin/okstra-codex-exec.sh "<literal-project-root>" "<assigned-model-execution-value>" "<literal-prompt-history-path>" "<literal-worktree-path>"
|
|
119
|
+
$HOME/.okstra/bin/okstra-codex-exec.sh "<literal-project-root>" "<assigned-model-execution-value>" "<literal-prompt-history-path>" "<literal-worktree-path>" "worker"
|
|
118
120
|
```
|
|
119
121
|
- If the parent directory does not exist yet, create it before writing the prompt file.
|
|
120
122
|
|
|
@@ -184,7 +186,7 @@ and the run-level error log staying empty.
|
|
|
184
186
|
--agent codex-worker --agent-role worker \
|
|
185
187
|
--model "<assigned-model-execution-value>" \
|
|
186
188
|
--error-type cli-failure \
|
|
187
|
-
--command "$HOME/.okstra/bin/okstra-codex-exec.sh <project-root> <m> <prompt-path> <worktree-path>" \
|
|
189
|
+
--command "$HOME/.okstra/bin/okstra-codex-exec.sh <project-root> <m> <prompt-path> <worktree-path> worker" \
|
|
188
190
|
--command-kind cli-invoke \
|
|
189
191
|
--exit-code <N> --duration-ms <ms> \
|
|
190
192
|
--message "<one-line summary>" \
|
|
@@ -27,9 +27,11 @@ You are a Gemini worker agent. Your job is to execute the Google Gemini CLI and
|
|
|
27
27
|
|
|
28
28
|
**Required form (uses the okstra wrapper to avoid redirect-triggered permission prompts):**
|
|
29
29
|
```bash
|
|
30
|
-
$HOME/.okstra/bin/okstra-gemini-exec.sh "<absolute-project-root>" "<assigned-model-execution-value>" "<absolute-prompt-history-path>" [<absolute-worktree-path>]
|
|
30
|
+
$HOME/.okstra/bin/okstra-gemini-exec.sh "<absolute-project-root>" "<assigned-model-execution-value>" "<absolute-prompt-history-path>" [<absolute-worktree-path>] [<role>]
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
The fifth argument `<role>` is the trace-pane label suffix (`gemini-<role>-trace`); pass the literal string `worker` for every dispatch from this subagent. The wrapper defaults to `worker` when the argument is omitted, but pass it explicitly so the dispatch is self-describing.
|
|
34
|
+
|
|
33
35
|
The fourth argument is **mandatory for implementation phase** and optional otherwise. It must be the literal `EXECUTOR_WORKTREE_PATH` recorded in the run context; the wrapper appends it to gemini's `--include-directories` list so the model can both read and operate on the worktree alongside project-root.
|
|
34
36
|
|
|
35
37
|
The wrapper internally runs:
|
|
@@ -73,7 +75,7 @@ The wrapper exists because Claude Code's Bash permission matcher rejects simple-
|
|
|
73
75
|
|
|
74
76
|
**Dispatch (background, no foreground timeout):**
|
|
75
77
|
```bash
|
|
76
|
-
$HOME/.okstra/bin/okstra-gemini-exec.sh "<absolute-project-root>" "<assigned-model-execution-value>" "<absolute-prompt-history-path>" "<absolute-worktree-path>"
|
|
78
|
+
$HOME/.okstra/bin/okstra-gemini-exec.sh "<absolute-project-root>" "<assigned-model-execution-value>" "<absolute-prompt-history-path>" "<absolute-worktree-path>" "worker"
|
|
77
79
|
```
|
|
78
80
|
Call `Bash` with `run_in_background: true`. Capture the returned `bash_id` (a.k.a. `shell_id`). Pass the positional arguments verbatim — do NOT use environment variables, `cd`, `&&` chains, or pipes from `cat`. Substitute the literal extracted Project Root, model execution value, prompt-history path, and worktree path. The fourth argument is **mandatory for implementation phase** (extract from `EXECUTOR_WORKTREE_PATH` in the lead prompt's run context or the `**Worktree:**` / `cwd for every mutating command:` line) and **may be omitted only for non-implementation analysis phases** that do not mutate the worktree. The wrapper handles `-p -`, `-m`, `-o text`, `--include-directories`, the stdin redirect from the prompt file, and stderr suppression internally. Calling `gemini` directly (without the wrapper) is an error in this skill: the redirect tokens disqualify the prefix match against `Bash(gemini:*)` and produce a permission prompt every dispatch.
|
|
79
81
|
|
|
@@ -114,7 +116,7 @@ This wrapper does NOT invoke MCP tools directly. MCP availability inside the Gem
|
|
|
114
116
|
- Include context (code, diff, file paths) if provided.
|
|
115
117
|
- For long prompts, dispatch through the wrapper with literal absolute paths (plus the worktree path for implementation phase):
|
|
116
118
|
```bash
|
|
117
|
-
$HOME/.okstra/bin/okstra-gemini-exec.sh "<literal-project-root>" "<assigned-model-execution-value>" "<literal-prompt-history-path>" "<literal-worktree-path>"
|
|
119
|
+
$HOME/.okstra/bin/okstra-gemini-exec.sh "<literal-project-root>" "<assigned-model-execution-value>" "<literal-prompt-history-path>" "<literal-worktree-path>" "worker"
|
|
118
120
|
```
|
|
119
121
|
- If the parent directory does not exist yet, create it before writing the prompt file.
|
|
120
122
|
|
|
@@ -184,7 +186,7 @@ and the run-level error log staying empty.
|
|
|
184
186
|
--agent gemini-worker --agent-role worker \
|
|
185
187
|
--model "<assigned-model-execution-value>" \
|
|
186
188
|
--error-type cli-failure \
|
|
187
|
-
--command "$HOME/.okstra/bin/okstra-gemini-exec.sh <project-root> <m> <prompt-path> <worktree-path>" \
|
|
189
|
+
--command "$HOME/.okstra/bin/okstra-gemini-exec.sh <project-root> <m> <prompt-path> <worktree-path> worker" \
|
|
188
190
|
--command-kind cli-invoke \
|
|
189
191
|
--exit-code <N> --duration-ms <ms> \
|
|
190
192
|
--message "<one-line summary>" \
|
|
@@ -53,10 +53,7 @@ project_root="$1"
|
|
|
53
53
|
model="$2"
|
|
54
54
|
prompt_path="$3"
|
|
55
55
|
worktree_path="${4-}"
|
|
56
|
-
role="${5
|
|
57
|
-
if [[ -z "$role" ]]; then
|
|
58
|
-
if [[ -n "$worktree_path" ]]; then role="executor"; else role="worker"; fi
|
|
59
|
-
fi
|
|
56
|
+
role="${5:-worker}"
|
|
60
57
|
|
|
61
58
|
if [[ -z "$project_root" || ! -d "$project_root" ]]; then
|
|
62
59
|
printf 'okstra-codex-exec: project-root is missing or not a directory: %q\n' "$project_root" >&2
|
|
@@ -127,8 +124,10 @@ log_path="${prompt_path%.md}.log"
|
|
|
127
124
|
# for the wrapper to exit. This fires in every phase the wrapper is invoked
|
|
128
125
|
# from (analysis, error-analysis, implementation-planning, implementation,
|
|
129
126
|
# …) — long-running codex dispatches are not implementation-specific. The
|
|
130
|
-
# new pane carries the title `codex-<role>-trace`
|
|
131
|
-
#
|
|
127
|
+
# new pane carries the title `codex-<role>-trace` — `role` is the optional
|
|
128
|
+
# 5th positional arg (defaults to `worker`); callers that dispatch a
|
|
129
|
+
# different role (e.g. `executor`) must pass it explicitly. The pane uses
|
|
130
|
+
# `tail -F`
|
|
132
131
|
# (follow-by-name) so it survives any truncation a re-dispatch performs on
|
|
133
132
|
# the same log path. Failures are tolerated silently: missing $TMUX, a tmux
|
|
134
133
|
# that refuses to split (size constraints, locked client), or a stale socket
|
|
@@ -45,10 +45,7 @@ project_root="$1"
|
|
|
45
45
|
model="$2"
|
|
46
46
|
prompt_path="$3"
|
|
47
47
|
worktree_path="${4-}"
|
|
48
|
-
role="${5
|
|
49
|
-
if [[ -z "$role" ]]; then
|
|
50
|
-
if [[ -n "$worktree_path" ]]; then role="executor"; else role="worker"; fi
|
|
51
|
-
fi
|
|
48
|
+
role="${5:-worker}"
|
|
52
49
|
|
|
53
50
|
if [[ -z "$project_root" || ! -d "$project_root" ]]; then
|
|
54
51
|
printf 'okstra-gemini-exec: project-root is missing or not a directory: %q\n' "$project_root" >&2
|
|
@@ -112,10 +109,11 @@ log_path="${prompt_path%.md}.log"
|
|
|
112
109
|
# When a tmux session is reachable, split a sibling pane tailing the log so
|
|
113
110
|
# the operator can watch progress live. This fires in every phase the
|
|
114
111
|
# wrapper is invoked from — long-running gemini dispatches are not
|
|
115
|
-
# implementation-specific. Title `gemini-<role>-trace`
|
|
116
|
-
#
|
|
117
|
-
#
|
|
118
|
-
# the silent-degrade failure
|
|
112
|
+
# implementation-specific. Title `gemini-<role>-trace` — `role` is the
|
|
113
|
+
# optional 5th positional arg (defaults to `worker`); callers that
|
|
114
|
+
# dispatch a different role must pass it explicitly. See the codex
|
|
115
|
+
# wrapper for the full design rationale and the silent-degrade failure
|
|
116
|
+
# model.
|
|
119
117
|
if [[ -n "${TMUX:-}" ]]; then
|
|
120
118
|
trace_pane=$(tmux split-window -h -P -F '#{pane_id}' \
|
|
121
119
|
-c "$(dirname "$log_path")" \
|
|
@@ -19,7 +19,6 @@ import json
|
|
|
19
19
|
import os
|
|
20
20
|
import re
|
|
21
21
|
import shutil
|
|
22
|
-
import subprocess
|
|
23
22
|
from dataclasses import dataclass, field
|
|
24
23
|
from datetime import datetime, timezone
|
|
25
24
|
from pathlib import Path
|
|
@@ -819,11 +818,6 @@ def prepare_task_bundle(inp: PrepareInputs) -> PrepareOutputs:
|
|
|
819
818
|
)
|
|
820
819
|
|
|
821
820
|
|
|
822
|
-
def claude_is_available() -> bool:
|
|
823
|
-
"""`claude` CLI 가 PATH 에 있는지 확인."""
|
|
824
|
-
return shutil.which("claude") is not None
|
|
825
|
-
|
|
826
|
-
|
|
827
821
|
def main(argv: list[str]) -> int:
|
|
828
822
|
"""CLI dispatcher for bash thin-wrapper use. Parses a flat list of argv
|
|
829
823
|
(the same flags `okstra.sh` accepts), runs prepare_task_bundle, prints
|
|
@@ -43,9 +43,6 @@ from .ids import _safe_fs_segment
|
|
|
43
43
|
from . import worktree_registry
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
OKSTRA_WORKTREES_RELATIVE = Path(".okstra/worktrees")
|
|
47
|
-
|
|
48
|
-
|
|
49
46
|
# Project-root directories that hold okstra task state, ignored by git, or
|
|
50
47
|
# otherwise required for the executor to operate but NOT carried across by
|
|
51
48
|
# `git worktree add`. Each is symlinked from the MAIN worktree into the new
|
|
@@ -15,8 +15,6 @@ def claude_session_totals(jsonl_path: Path) -> dict:
|
|
|
15
15
|
model: str | None = None
|
|
16
16
|
first_ts: str | None = None
|
|
17
17
|
last_ts: str | None = None
|
|
18
|
-
started_at: str | None = None
|
|
19
|
-
ended_at: str | None = None
|
|
20
18
|
for rec in iter_jsonl(jsonl_path):
|
|
21
19
|
if agent_name is None and rec.get("agentName"):
|
|
22
20
|
agent_name = rec["agentName"]
|