okstra 0.21.0 → 0.21.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 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 스킬 마크다운 소스 (스킬 12종)
31
+ ├── skills/ Claude Code 스킬 마크다운 소스 (스킬 13종)
32
32
  ├── agents/ lead SKILL.md + workers/
33
33
  ├── prompts/, templates/, validators/
34
34
  ├── docs/kr/ 한국어 상세 매뉴얼 (architecture.md, cli.md)
@@ -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/` 아래 스킬 마크다운 12개, `~/.okstra/installed-skills.json` 을 생성합니다. 재실행은 idempotent — 파일별 hash 를 비교하고 바뀐 파일만 갱신합니다.
90
+ `~/.okstra/{lib/python, bin, version}`, `~/.claude/skills/` 아래 스킬 마크다운 13개, `~/.okstra/installed-skills.json` 을 생성합니다. 재실행은 idempotent — 파일별 hash 를 비교하고 바뀐 파일만 갱신합니다.
91
91
 
92
92
  검증:
93
93
 
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 (12 skills)
31
+ ├── skills/ Claude Code skill markdown sources (13 skills)
32
32
  ├── agents/ lead SKILL.md + workers/
33
33
  ├── prompts/, templates/, validators/
34
34
  ├── tests/, tests-e2e/
@@ -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 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.
89
+ Provisions `~/.okstra/{lib/python, bin, version}`, the 13 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
 
@@ -837,6 +837,7 @@ Claude가 작성하는 최종 보고서는 brief에 더 구체적인 형식이
837
837
 
838
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
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
+ - **Claude `/exit` 시 자동 정리**: trace pane 의 `tail -F` 는 tmux 셸의 자식이라 Claude 가 종료돼도 살아남는 문제를 막기 위해, wrapper 는 spawn 한 pane id 를 caller `$TMUX_PANE` 으로 키된 registry (`${TMPDIR:-/tmp}/okstra-trace-panes/<caller-pane>.list`) 에 append 합니다. `templates/reports/settings.template.json` 의 `hooks.SessionEnd` 가 `$HOME/.okstra/bin/okstra-trace-cleanup.sh` 를 호출해 자신의 caller pane registry 만 읽어 `tmux kill-pane` 합니다. caller pane 단위로 scope 가 잡혀 있어 같은 tmux 세션에 Claude 인스턴스가 여러 개 떠 있어도 서로의 trace pane 을 죽이지 않습니다. tmux 가 없거나 stale pane id 인 경우 silent degrade.
840
841
  - 디스크 누적은 `okstra-logs` skill 이 read-only 로 인벤토리 + cleanup 명령을 제안합니다 (실행은 사용자 copy-paste).
841
842
 
842
843
  ### Linked-worktree `.git/` write 권한 (codex / gemini)
package/docs/kr/cli.md CHANGED
@@ -497,5 +497,5 @@ chmod +x ~/.local/bin/okstra-ctl
497
497
 
498
498
  ### Live-log sidecar
499
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* 절 참고.
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`). 분할된 trace pane 은 caller `$TMUX_PANE` 으로 키된 registry 에 등록돼, Claude `/exit` 시 `SessionEnd` 훅이 `okstra-trace-cleanup.sh` 로 자동 정리합니다. 사용량 인벤토리와 `find … -delete` cleanup 명령은 `okstra-logs` skill 이 read-only 로 제안합니다. 자세한 와이어링은 [`docs/kr/architecture.md`](architecture.md) 의 *Live-log mirror* 절 참고.
501
501
 
@@ -165,6 +165,7 @@ okstra/
165
165
  | `okstra-central.sh` | `record_start` 중앙 lock 관리 |
166
166
  | `okstra-codex-exec.sh` | Codex worker executor (live log mirror, tmux trace pane) |
167
167
  | `okstra-gemini-exec.sh` | Gemini worker executor |
168
+ | `okstra-trace-cleanup.sh` | Claude `/exit` 시 trace pane registry 청소 (`SessionEnd` 훅에서 호출) |
168
169
  | `okstra-error-log.py` | Worker 오류 패턴 분석 |
169
170
  | `okstra-spawn-followups.py` | Phase 완료 후 다음 phase dispatch |
170
171
  | `okstra-token-usage.py` | Token collection CLI 엔트리 |
@@ -217,7 +218,7 @@ okstra/
217
218
 
218
219
  ---
219
220
 
220
- ### 3.7 `skills/` — 12개 Claude Code 슬래시 커맨드
221
+ ### 3.7 `skills/` — 13개 Claude Code 슬래시 커맨드
221
222
 
222
223
  | ID | 이름 | 공개 | 용도 |
223
224
  |----|------|------|------|
@@ -233,6 +234,7 @@ okstra/
233
234
  | 10 | okstra-report-finder | NO | 보고서 검색 (자동 트리거) |
234
235
  | 11 | okstra-time-summary | NO | 소요 시간 분석 |
235
236
  | 12 | okstra-logs | YES | 로그 인벤토리·정리 (worker wrapper `*.log` sidecars 조회 및 cleanup 제안) |
237
+ | 13 | okstra-brief | YES | 요구사항 문서·티켓·링크·대화로부터 `okstra-run` 입력용 task brief 마크다운 생성 |
236
238
 
237
239
  각 skill 구조: **Step 0 런타임 검증 → Step 1-N 작업 수행 → 실패 시 사용자 안내**.
238
240
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okstra",
3
- "version": "0.21.0",
3
+ "version": "0.21.1",
4
4
  "description": "Multi-agent cross-verification orchestrator runtime + Claude Code skills.",
5
5
  "license": "MIT",
6
6
  "author": "devonshin",
@@ -1,5 +1,5 @@
1
1
  {
2
- "package": "0.21.0",
3
- "builtAt": "2026-05-14T11:48:06.992Z",
2
+ "package": "0.21.1",
3
+ "builtAt": "2026-05-14T12:50:20.728Z",
4
4
  "repoRoot": "/home/runner/work/okstra/okstra"
5
5
  }
@@ -44,7 +44,9 @@ Unlike the Codex / Gemini workers, you are an in-process Claude subagent — you
44
44
  - If the parent directory does not exist yet, create it before writing.
45
45
 
46
46
  4. Anchor all file operations to the absolute `Project Root` from the lead prompt. Use absolute paths — do NOT rely on inherited cwd. Never use `cd` to change directory.
47
- - **Executor exception (implementation phase only):** when this worker is dispatched as the `Executor` and the lead prompt provides an `EXECUTOR_WORKTREE_PATH` that differs from the session's inherited cwd, cwd-sensitive Bash commands (`cargo *`, `npm *`, `pnpm *`, `bun *`, `pytest`, `make *`, `go *`, language-toolchain test/build commands) MUST be prefixed with `cd <EXECUTOR_WORKTREE_PATH> && ` in the same Bash invocation — e.g. `cd /Users/.../worktrees/foo && cargo test -p bar`. Do NOT wrap the whole thing in `bash -lc "..."` or `bash -c "..."`; pass the chained command directly to the Bash tool so the leading `cd` token remains visible to the permission layer. The `cd` is scoped to the single Bash subshell and does not mutate the session's shell state, so this does not conflict with the "never use cd" rule above (which prevents the worker from drifting the session cwd across calls). Verifier roles do NOT use this exception — they read with absolute paths only.
47
+ - **Executor exception (implementation phase only):** when this worker is dispatched as the `Executor` and the lead prompt provides an `EXECUTOR_WORKTREE_PATH` that differs from the session's inherited cwd, cwd-sensitive Bash commands (`cargo *`, `npm *`, `pnpm *`, `bun *`, `pytest`, `make *`, `go *`, language-toolchain test/build commands) MUST be prefixed with `cd <EXECUTOR_WORKTREE_PATH> && ` in the same Bash invocation — e.g. `cd /Users/.../worktrees/foo && cargo test -p bar`. Do NOT wrap the whole thing in `bash -lc "..."` or `bash -c "..."`; pass the chained command directly to the Bash tool so the leading `cd` token remains visible to the permission layer. The `cd` is scoped to the single Bash subshell and does not mutate the session's shell state, so this does not conflict with the "never use cd" rule above (which prevents the worker from drifting the session cwd across calls).
48
+ - **Verifier QA-gate exception:** verifier roles MAY use the same `cd <WORKTREE> && <cmd>` shape when executing project-declared `qaCommands` (lint / format / typecheck / test) from `project.json`, since those commands are cwd-sensitive by nature. Outside the QA gate, verifiers still read with absolute paths only — do NOT use `cd` for file inspection.
49
+ - **No extra chaining beyond `cd && cmd`:** the permission matcher only allows the exact two-segment shape `cd <PATH> && <single-command>`. Do NOT append additional pipes, semicolons, redirects, or `&&` chains — e.g. `cd ... && cargo test ... 2>&1 | tail -20; echo "exit:$?"` will trigger a permission prompt every dispatch because the trailing `| tail`, `; echo`, and `2>&1` tokens disqualify the prefix match against `Bash(cargo:*)`. Let Claude Code capture the full stdout/stderr and exit code natively — do not post-process with `tail`, `head`, or `echo "exit:$?"`. If output truncation is genuinely needed, run the command first and read the result in a separate tool call.
48
50
 
49
51
  5. **MCP usage**: The canonical list of MCP servers and tools available for this run lives in the lead prompt's `## Available MCP Servers` section (sourced from `.project-docs/okstra/project.json`'s `mcpServers` array). When the task requires inspection of an external system covered by one of those servers, call the listed tool directly by name (e.g. `mcp__<server>__<tool>`). Do NOT shell out via `claude --mcp-cli call ...` or run the tool name as a Bash command — those are not valid invocation paths. If a server you need is not listed, record `MCP not available for this run` in your worker output rather than guessing a tool name.
50
52
 
@@ -172,6 +172,17 @@ if [[ -n "${TMUX:-}" ]]; then
172
172
  if [[ -n "$trace_pane" ]]; then
173
173
  tmux select-pane -t "$trace_pane" -T "codex-${role}-trace" 2>/dev/null || true
174
174
  tmux last-pane 2>/dev/null || true
175
+ # Register the spawned pane so the `SessionEnd` hook (see
176
+ # `okstra-trace-cleanup.sh`) can kill it when the caller's Claude
177
+ # session exits. Scope by caller `$TMUX_PANE` — the pane Claude itself
178
+ # is attached to — so concurrent Claude instances in the same tmux
179
+ # session do not stomp each other's trace panes.
180
+ if [[ -n "${TMUX_PANE:-}" ]]; then
181
+ registry_dir="${TMPDIR:-/tmp}/okstra-trace-panes"
182
+ mkdir -p "$registry_dir" 2>/dev/null || true
183
+ safe_pane="${TMUX_PANE//[^A-Za-z0-9]/_}"
184
+ printf '%s\n' "$trace_pane" >> "$registry_dir/${safe_pane}.list" 2>/dev/null || true
185
+ fi
175
186
  fi
176
187
  fi
177
188
 
@@ -121,6 +121,13 @@ if [[ -n "${TMUX:-}" ]]; then
121
121
  if [[ -n "$trace_pane" ]]; then
122
122
  tmux select-pane -t "$trace_pane" -T "gemini-${role}-trace" 2>/dev/null || true
123
123
  tmux last-pane 2>/dev/null || true
124
+ # See `okstra-codex-exec.sh` for the registry rationale — kept in lock-step.
125
+ if [[ -n "${TMUX_PANE:-}" ]]; then
126
+ registry_dir="${TMPDIR:-/tmp}/okstra-trace-panes"
127
+ mkdir -p "$registry_dir" 2>/dev/null || true
128
+ safe_pane="${TMUX_PANE//[^A-Za-z0-9]/_}"
129
+ printf '%s\n' "$trace_pane" >> "$registry_dir/${safe_pane}.list" 2>/dev/null || true
130
+ fi
124
131
  fi
125
132
  fi
126
133
 
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # okstra-trace-cleanup.sh — kill tmux trace panes spawned by okstra worker
4
+ # wrappers (`okstra-codex-exec.sh`, `okstra-gemini-exec.sh`) for the current
5
+ # Claude Code session.
6
+ #
7
+ # Invoked from the `SessionEnd` hook in
8
+ # `templates/reports/settings.template.json`. The wrappers register every
9
+ # pane they split into a registry file keyed by the caller's `$TMUX_PANE`
10
+ # (i.e. the pane Claude itself is attached to). On Claude `/exit`, the hook
11
+ # runs in that same pane's env, reads its own registry file, and kills each
12
+ # registered pane.
13
+ #
14
+ # Scoping by caller `$TMUX_PANE` (not by tmux session) lets multiple Claude
15
+ # instances coexist in the same tmux session without stomping each other's
16
+ # trace panes.
17
+ #
18
+ # Failures are tolerated silently — a stale pane id, missing $TMUX, or a
19
+ # locked tmux client must never prevent Claude from exiting cleanly.
20
+
21
+ set -u
22
+
23
+ # No tmux pane context → nothing to clean.
24
+ if [[ -z "${TMUX_PANE:-}" ]]; then
25
+ exit 0
26
+ fi
27
+
28
+ registry_dir="${TMPDIR:-/tmp}/okstra-trace-panes"
29
+ safe_pane="${TMUX_PANE//[^A-Za-z0-9]/_}"
30
+ registry_file="$registry_dir/${safe_pane}.list"
31
+
32
+ if [[ ! -f "$registry_file" ]]; then
33
+ exit 0
34
+ fi
35
+
36
+ while IFS= read -r pane_id; do
37
+ [[ -n "$pane_id" ]] || continue
38
+ tmux kill-pane -t "$pane_id" 2>/dev/null || true
39
+ done < "$registry_file"
40
+
41
+ rm -f "$registry_file" 2>/dev/null || true
42
+ exit 0
@@ -143,5 +143,14 @@
143
143
  "mcp__test-context7__resolve-library-id",
144
144
  "mcp__test-context7__query-docs"
145
145
  ]
146
+ },
147
+ "hooks": {
148
+ "SessionEnd": [
149
+ {
150
+ "hooks": [
151
+ { "type": "command", "command": "$HOME/.okstra/bin/okstra-trace-cleanup.sh" }
152
+ ]
153
+ }
154
+ ]
146
155
  }
147
156
  }
package/src/install.mjs CHANGED
@@ -20,6 +20,7 @@ const BIN_ENTRYPOINTS = [
20
20
  "okstra.sh",
21
21
  "okstra-codex-exec.sh",
22
22
  "okstra-gemini-exec.sh",
23
+ "okstra-trace-cleanup.sh",
23
24
  "okstra-central.sh",
24
25
  "okstra-token-usage.py",
25
26
  "okstra-error-log.py",
package/src/uninstall.mjs CHANGED
@@ -7,6 +7,7 @@ const BIN_ENTRYPOINTS = [
7
7
  "okstra.sh",
8
8
  "okstra-codex-exec.sh",
9
9
  "okstra-gemini-exec.sh",
10
+ "okstra-trace-cleanup.sh",
10
11
  "okstra-central.sh",
11
12
  "okstra-token-usage.py",
12
13
  "okstra-error-log.py",