okstra 0.98.1 → 0.99.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 (41) hide show
  1. package/docs/for-ai/README.md +55 -0
  2. package/docs/for-ai/skills/okstra-brief.md +240 -0
  3. package/docs/for-ai/skills/okstra-container.md +161 -0
  4. package/docs/for-ai/skills/okstra-inspect.md +260 -0
  5. package/docs/for-ai/skills/okstra-memory.md +127 -0
  6. package/docs/for-ai/skills/okstra-run.md +229 -0
  7. package/docs/for-ai/skills/okstra-schedule.md +321 -0
  8. package/docs/for-ai/skills/okstra-setup.md +140 -0
  9. package/docs/kr/architecture.md +5 -5
  10. package/docs/superpowers/plans/2026-06-23-phase-batch-cleanup-enforcement.md +409 -0
  11. package/package.json +1 -1
  12. package/runtime/BUILD.json +2 -2
  13. package/runtime/agents/workers/claude-worker.md +1 -1
  14. package/runtime/bin/okstra-team-reconcile.sh +7 -7
  15. package/runtime/prompts/coding-preflight/overview.md +1 -1
  16. package/runtime/prompts/lead/context-loader.md +1 -1
  17. package/runtime/prompts/lead/convergence.md +3 -4
  18. package/runtime/prompts/lead/okstra-lead-contract.md +26 -24
  19. package/runtime/prompts/lead/report-writer.md +6 -7
  20. package/runtime/prompts/lead/team-contract.md +4 -4
  21. package/runtime/prompts/profiles/_common-contract.md +16 -16
  22. package/runtime/prompts/profiles/forbidden-actions.json +1 -1
  23. package/runtime/prompts/profiles/release-handoff.md +2 -2
  24. package/runtime/python/okstra_ctl/paths.py +1 -5
  25. package/runtime/python/okstra_ctl/render.py +38 -49
  26. package/runtime/python/okstra_ctl/run.py +1 -1
  27. package/runtime/python/okstra_ctl/session.py +1 -1
  28. package/runtime/python/okstra_ctl/team_reconcile.py +10 -12
  29. package/runtime/python/okstra_ctl/worktree.py +2 -3
  30. package/runtime/python/okstra_ctl/worktree_registry.py +3 -3
  31. package/runtime/python/okstra_project/dirs.py +31 -4
  32. package/runtime/python/okstra_token_usage/collect.py +7 -5
  33. package/runtime/skills/okstra-brief/SKILL.md +24 -13
  34. package/runtime/skills/okstra-run/SKILL.md +3 -3
  35. package/runtime/validators/lib/fixtures.sh +8 -7
  36. package/runtime/validators/validate-brief.py +36 -2
  37. package/runtime/validators/validate-run.py +18 -15
  38. package/runtime/validators/validate_session_conformance.py +45 -6
  39. package/src/commands/lifecycle/config.mjs +2 -4
  40. package/src/commands/memory/memory.mjs +2 -3
  41. package/src/lib/paths.mjs +28 -2
@@ -0,0 +1,321 @@
1
+ # okstra-schedule AI Manual
2
+
3
+ ## 원천
4
+
5
+ - 스킬 원문: [`skills/okstra-schedule/SKILL.md`](../../../skills/okstra-schedule/SKILL.md)
6
+ - schedule 템플릿: [`templates/reports/schedule.template.md`](../../../templates/reports/schedule.template.md)
7
+ - schedule validator: [`validators/validate-schedule.py`](../../../validators/validate-schedule.py)
8
+ - workStatus inference 참조: [`skills/okstra-inspect/SKILL.md`](../../../skills/okstra-inspect/SKILL.md)
9
+
10
+ ## 목적
11
+
12
+ `okstra-schedule`은 task-group 안의 non-done task들을 모아 클라이언트용 작업 일정 Markdown을 만든다. 실행 task를 시작하는 스킬이 아니며, 단일 task 분석도 아니다.
13
+
14
+ 출력 위치:
15
+
16
+ ```text
17
+ <PROJECT_ROOT>/.okstra/tasks/<task-group-segment>/schedule/<task-group-segment>-plan-<YYYY-MM-DD_HH-MM-SS>.md
18
+ ```
19
+
20
+ ## 사용 조건
21
+
22
+ 사용한다:
23
+
24
+ - 사용자가 task-group 전체의 "일정", "schedule", "작업 계획표"를 요청한다.
25
+ - `.okstra/discovery/task-catalog.json`에 해당 task-group이 있고, `done`이 아닌 task가 하나 이상 있다.
26
+
27
+ 사용하지 않는다:
28
+
29
+ - 단일 task 상태/분석: `okstra-inspect status`
30
+ - 실제 phase 실행: `okstra-run`
31
+ - 이미 완료된 task-group: 파일을 만들지 않고 모든 task가 done이라고 말한다.
32
+
33
+ ## Preflight
34
+
35
+ 각각 별도 Bash 호출:
36
+
37
+ ```bash
38
+ okstra ensure-installed --runtime claude-code
39
+ okstra check-project --json
40
+ ```
41
+
42
+ runtime이나 project setup이 없으면 `/okstra-setup` 안내 후 멈춘다.
43
+
44
+ ## model gate
45
+
46
+ 스킬 frontmatter는 `model: opus`다. 활성 모델이 Opus-class 또는 Fable-class가 아니면 사용자에게 전환을 권한다. 사용자가 lower model로 진행하겠다고 명시하면 진행하되, 생성 schedule 상단에 reduced-quality warning을 넣는다.
47
+
48
+ ## task-group 해석
49
+
50
+ 1. `.okstra/discovery/task-catalog.json`을 읽는다.
51
+ 2. 사용자 입력 task-group을 lowercase하고 `[a-z0-9]` 외 문자를 제거한다.
52
+ 3. catalog entry의 `taskGroupPathSegment`에도 같은 변환을 적용해 비교한다.
53
+ 4. raw `taskGroup` fallback은 쓰지 않는다.
54
+ 5. 매칭된 각 task의 `task-manifest.json`을 직접 읽는다. catalog는 stale일 수 있고 manifest가 authoritative다.
55
+
56
+ ## workStatus filter
57
+
58
+ 각 manifest에서 workStatus를 확인한다. 없거나 비어 있으면 `okstra-inspect`의 `status.4` inference table을 적용한다.
59
+
60
+ 제외:
61
+
62
+ - explicit `done`
63
+ - inferred `done`
64
+
65
+ 포함:
66
+
67
+ - `todo`
68
+ - `in-progress`
69
+ - `blocked`
70
+ - `phase-done`
71
+ - 그 밖의 non-done inferred/display 상태
72
+
73
+ 필터 후 0개면 schedule file을 만들지 않는다.
74
+
75
+ ## per-task data extraction
76
+
77
+ manifest에서 읽는다:
78
+
79
+ - `taskId`, `taskGroup`, `taskKey`
80
+ - `workCategory`
81
+ - `workflow.currentPhase`
82
+ - `workflow.currentPhaseState`
83
+ - `taskType`
84
+ - `workStatus`
85
+ - `latestReportPath`
86
+
87
+ report에서 파싱한다:
88
+
89
+ - Title / Problem statement
90
+ - Solution / Architecture
91
+ - Work Breakdown
92
+ - Verification Commands
93
+ - Rollback strategy
94
+ - Effort, Risk, Priority, Scope, Repos
95
+
96
+ report가 없거나 manifest pointer가 stale이면 fallback:
97
+
98
+ 1. `taskRootPath`를 기준으로 `runs/<taskType>/reports/final-report-*.md`에서 mtime이 최신인 파일을 찾는다.
99
+ 2. 없으면 `runs/*/reports/final-report-*.md`도 본다.
100
+ 3. 찾으면 parse하고 schedule task block에 fallback note를 넣는다.
101
+ 4. 끝까지 없으면 `[NEEDS-OKSTRA-RUN]`으로 표시하고 manifest metadata만 사용한다.
102
+
103
+ 특정 section parse 실패는 `[PARSE-ERROR: <section>]`으로 표시하고 계속한다.
104
+
105
+ ## client-facing audience rule
106
+
107
+ schedule은 클라이언트용 작업 계획이다. 내부 report의 approval, blocking decision, 사용자 확인 필요 항목을 schedule에 노출하지 않는다.
108
+
109
+ 출력에서 제거한다:
110
+
111
+ - permission/authority 확인 step
112
+ - approval waiting buffer
113
+ - stakeholder coordination
114
+ - 법무/조직 sign-off
115
+ - `Consolidated User Decision Checklist`
116
+ - `#### 사용자 확인 필요 항목`
117
+ - `Done`, `Ready?`, `Blocking Decisions` column
118
+ - checkbox list/cell
119
+
120
+ effort와 Gantt는 engineering duration만 반영한다.
121
+
122
+ ## phase classification
123
+
124
+ 기본 mapping:
125
+
126
+ | workCategory | phase |
127
+ |---|---|
128
+ | `bugfix` | High/Med-High risk이면 Phase 1, 아니면 Phase 2 |
129
+ | `feature` | Phase 2 |
130
+ | `improvement` | Phase 2 |
131
+ | `refactor` | Phase 3 |
132
+ | `ops` | Phase 3 |
133
+ | `docs` / `doc` | Phase 2 |
134
+ | `unknown` 또는 미정의 | Phase 2, rationale note 추가 |
135
+
136
+ priority override:
137
+
138
+ - `P0`: Phase 1
139
+ - `P1`, `P2`: Phase 2
140
+ - `P3`: Phase 3
141
+
142
+ ambiguous하면 가장 가까운 phase에 두고 rationale을 phase section 상단에 쓴다. 이 rationale은 현재 validator gap으로 문서에서 책임진다.
143
+
144
+ ## section contract
145
+
146
+ 템플릿의 heading 순서와 spelling을 따른다. `validate-schedule.py`가 section order, title suffix, metadata, field labels, enum, Gantt axis 등을 검사한다.
147
+
148
+ top-level 계약 sections:
149
+
150
+ 1. `## At a Glance`
151
+ 2. `## Executive Summary`
152
+ 3. `## Task Dependency Graph`
153
+ 4. `## Phase 1: Critical Fixes`
154
+ 5. `## Phase 2: Enhancements`
155
+ 6. `## Phase 3: Architecture`
156
+ 7. `## Execution Priority Matrix`
157
+ 8. `## Cross-Task Dependencies & Shared Concerns`
158
+ 9. `## Risk Mitigation Strategy`
159
+ 10. `## Recommended Immediate Actions`
160
+
161
+ optional sections:
162
+
163
+ - `## Gantt Chart`: `Task Dependency Graph`와 `Phase 1` 사이.
164
+ - `## Glossary`: 마지막 section. opaque code가 본문에 남을 때만 사용.
165
+
166
+ phase에 task가 없어도 heading을 유지하고 `_없음_`을 쓴다.
167
+
168
+ ## top header
169
+
170
+ 형태:
171
+
172
+ ```markdown
173
+ # <Title> — Work Schedule
174
+
175
+ > Generated: <YYYY-MM-DD HH:MM> | Project: <project-id> | Task Group: <task-group>
176
+ > Source: okstra <mode> (<N> tasks included, <M> done excluded)
177
+ ```
178
+
179
+ title suffix `— Work Schedule`은 validator가 검사한다.
180
+
181
+ ## At a Glance
182
+
183
+ 다음 totals line이 정확히 있어야 한다.
184
+
185
+ ```markdown
186
+ **총 <N>개 task / 예상 소요: <X.X> ~ <Y.Y> days (Effort 합산)**
187
+ ```
188
+
189
+ Effort-to-day mapping은 template의 `### Effort Sizing 기준` table이 SSOT다. lower/upper 합산으로 total day range를 만든다.
190
+
191
+ enum 값:
192
+
193
+ | Field | 값 |
194
+ |---|---|
195
+ | Effort | `S`, `M`, `L`, `XL`, `XXL` |
196
+ | Priority | `P0`, `P1`, `P2`, `P3` |
197
+ | Risk | `Very Low`, `Low`, `Medium`, `Med-High`, `High` |
198
+ | Phase | `1`, `2`, `3` |
199
+
200
+ `Med-High`가 canonical이다.
201
+
202
+ ## per-task block
203
+
204
+ 모든 task block은 `| Item | Detail |` table을 가진다. field row 순서:
205
+
206
+ 1. `**Category**`
207
+ 2. `**Priority**`
208
+ 3. `**Effort**`
209
+ 4. `**Status**`
210
+ 5. `**Risk**`
211
+ 6. `**Scope**`
212
+ 7. `**Repo**`
213
+
214
+ 그 뒤 subsection 순서:
215
+
216
+ 1. `**Problem**:`
217
+ 2. `**Solution**:`
218
+ 3. `**Work Breakdown**:`
219
+ 4. `**Verification Commands**:`
220
+ 5. `**Rollback**:`
221
+
222
+ `[NEEDS-OKSTRA-RUN]` 또는 `[PARSE-ERROR: <section>]` task는 가능한 field만 채우되 marker를 task heading 바로 아래 둔다.
223
+
224
+ ## Task Dependency Graph
225
+
226
+ dependency가 없으면 literal:
227
+
228
+ ```markdown
229
+ _의존 정보 없음_
230
+ ```
231
+
232
+ dependency가 있으면 plain fenced block을 사용한다. language tag를 붙이지 않는다.
233
+
234
+ ````
235
+ ```
236
+ DEV-1 -> DEV-2, DEV-3
237
+ DEV-2 -> DEV-4
238
+ ```
239
+ ````
240
+
241
+ arrow는 ASCII `->`만 사용한다.
242
+
243
+ ## Gantt Chart
244
+
245
+ 기본은 렌더한다. day signal이 하나라도 있으면 rough estimate라도 chart를 만든다.
246
+
247
+ 렌더 조건 예:
248
+
249
+ - 2개 이상 task에 effort sizing이 있다.
250
+ - 1개 task라도 effort range가 있다.
251
+ - source report에 Part/Phase/Step decomposition이 있다.
252
+ - total effort가 3 days 이상이다.
253
+
254
+ skip은 모든 task가 XXL이고 decomposition이 없거나, 모든 task에 effort와 decomposition이 없을 때만 한다. skip하면 `Gantt Chart` 위치에 다음 blockquote를 둔다.
255
+
256
+ ```markdown
257
+ > _Gantt Chart 생략: <actual data를 근거로 한 이유>._
258
+ ```
259
+
260
+ Gantt는 plain fenced ASCII다. Mermaid, PlantUML, Graphviz, date axis를 쓰지 않는다.
261
+
262
+ ````
263
+ ```
264
+ Day: 1 5 10 15 20
265
+ | | | | |
266
+ Phase 1
267
+ DEV-1 (M) ██████ ! crit
268
+ Phase 2
269
+ DEV-2 (L) ██████░░ est
270
+ ```
271
+ ````
272
+
273
+ axis는 relative day count만 사용한다. calendar date, weekday, "오늘 + N"을 넣지 않는다.
274
+
275
+ ## opaque code 처리
276
+
277
+ 내부 report code(`FC-5`, `UC-3`, `M2` 등)는 그대로 노출하지 않는다.
278
+
279
+ 선택 A: 짧은 설명으로 inline replacement.
280
+
281
+ 선택 B: 반복되는 code가 많으면 마지막 `## Glossary`에 모든 code를 해석한다.
282
+
283
+ decision-item letter code(`A1`, `B2`, `C3`, `D4`)는 schedule에 넣지 않는다.
284
+
285
+ ## validation
286
+
287
+ 작성 후 완료 메시지 전에 다시 읽고 validator를 실행한다.
288
+
289
+ ```bash
290
+ python3 ~/.okstra/lib/validators/validate-schedule.py <output-path>
291
+ ```
292
+
293
+ 설치본 validator가 없으면 repo validator를 쓴다.
294
+
295
+ ```bash
296
+ python3 validators/validate-schedule.py <output-path>
297
+ ```
298
+
299
+ 실패하면 파일을 고치고 재검증한다. validator가 없을 때만 manual checklist로 대체한다.
300
+
301
+ ## 완료 메시지
302
+
303
+ ```text
304
+ Schedule 생성 완료: <relative-path>
305
+ - 포함 task: N개
306
+ - 제외(done) task: M개
307
+ - 예상 소요: X.X ~ Y.Y days (Effort 합산)
308
+ - 모드: lightweight
309
+ ```
310
+
311
+ ## 금지 패턴
312
+
313
+ - heading을 한국어/프랑스어 등으로 번역하기.
314
+ - `## Cumulative Timeline` 추가.
315
+ - `## Effort-to-Day 매핑` 같은 extra top-level section 추가.
316
+ - Gantt를 mermaid로 렌더하기.
317
+ - Gantt axis에 calendar date를 넣기.
318
+ - checkbox, Done, Ready, Blocking Decisions column 만들기.
319
+ - internal approval/blocker/user-decision 항목을 클라이언트 schedule에 노출하기.
320
+ - report가 없다고 task를 제외하기. `[NEEDS-OKSTRA-RUN]`으로 포함한다.
321
+ - timestamp collision 시 기존 파일을 덮어쓰기. `-2`, `-3` suffix를 붙인다.
@@ -0,0 +1,140 @@
1
+ # okstra-setup AI Manual
2
+
3
+ ## 원천
4
+
5
+ - 스킬 원문: [`skills/okstra-setup/SKILL.md`](../../../skills/okstra-setup/SKILL.md)
6
+ - CLI registry: [`src/cli-registry.mjs`](../../../src/cli-registry.mjs)
7
+ - project 등록 구현: `src/commands/lifecycle/setup.mjs`
8
+ - install/ensure-installed 구현: `src/commands/lifecycle/install.mjs`
9
+
10
+ ## 목적
11
+
12
+ `okstra-setup`은 두 가지를 처리한다.
13
+
14
+ 1. 머신 단위 runtime 설치: `~/.okstra/`, `~/.claude/skills/`, `~/.claude/agents/`
15
+ 2. 프로젝트 단위 등록: `<PROJECT_ROOT>/.okstra/project.json`
16
+
17
+ 일상적인 task 실행 스킬이 아니다. task가 이미 준비된 상태면 `okstra-run` 또는 `okstra-inspect`로 라우팅한다.
18
+
19
+ ## 사용 조건
20
+
21
+ 사용한다:
22
+
23
+ - 사용자가 "okstra setup", "setup okstra", "initialize okstra", "okstra init", "처음 설정"을 요청한다.
24
+ - `~/.okstra/version`이 없거나 오래된 것으로 보인다.
25
+ - 현재 프로젝트에 `.okstra/project.json`이 없다.
26
+
27
+ 사용하지 않는다:
28
+
29
+ - task run을 시작하려는 경우. 이때는 `okstra-run`.
30
+ - status/history/report를 보려는 경우. 이때는 `okstra-inspect`.
31
+ - 이미 `.okstra/project.json`이 있고 day-to-day 사용만 필요한 경우.
32
+
33
+ ## 실행 전 확인
34
+
35
+ 사용자에게 Node 18+, Python 3.10+가 필요하다고 알린다. 현재 working directory가 okstra 메타데이터를 둘 프로젝트 안인지 불명확하면, 프로젝트 루트를 먼저 확인한다.
36
+
37
+ 설치 명령:
38
+
39
+ ```bash
40
+ npx -y okstra@latest install --runtime claude-code
41
+ ```
42
+
43
+ 이 명령은 idempotent로 취급한다. 이미 설치되어 있어도 다시 실행해 runtime, skill, agent payload를 현재 package 버전과 맞춘다. 실패하면 stderr를 그대로 사용자에게 보여준다. legacy `okstra-install.sh`로 우회하지 않는다.
44
+
45
+ ## 명령 호출 규칙
46
+
47
+ `okstra install` 이후에는 후속 명령이 모두 `okstra` literal token으로 시작해야 한다.
48
+
49
+ 허용되는 형태:
50
+
51
+ ```bash
52
+ okstra check-project --json
53
+ okstra setup --yes --project-root /abs/project --project-id my-project
54
+ okstra doctor --runtime claude-code
55
+ ```
56
+
57
+ 피해야 하는 형태:
58
+
59
+ - `export PYTHONPATH=...`
60
+ - `eval "$(okstra paths --shell)"`
61
+ - `$PROJECT_ROOT` 같은 shell 변수
62
+ - `$(...)` command substitution
63
+ - `if`, `&&`, `||`로 감싼 okstra 호출
64
+
65
+ `okstra <subcmd>`가 자체적으로 Python path를 부트스트랩하므로 `okstra paths --shell`은 이 스킬에서 쓰지 않는다. 경로가 필요하면 `okstra paths --json`을 별도 호출로 실행하고 JSON 값을 읽는다.
66
+
67
+ ## 프로젝트 루트 해석
68
+
69
+ 먼저 실행:
70
+
71
+ ```bash
72
+ okstra check-project --json
73
+ ```
74
+
75
+ 결과 처리:
76
+
77
+ - `ok: true`: 이미 등록된 프로젝트다. `projectRoot`, `projectJsonPath`, `projectId`를 사용자에게 보여주고 유지 여부를 확인한다.
78
+ - `ok: false`, `stage: "resolve"`: 사용자에게 절대 project root를 받아 `okstra check-project --cwd /abs/path --json`을 다시 실행한다.
79
+ - `ok: false`, `stage: "project_json_missing"`: 정상 생성 경로로 진행한다.
80
+ - 그 외 실패 stage: JSON의 `reason`을 그대로 보여주고, 원문이 지시하는 recovery를 따른다.
81
+
82
+ ## project.json 생성 또는 유지
83
+
84
+ `<PROJECT_ROOT>/.okstra/project.json`이 있으면 `projectId`와 `projectRoot`를 보여주고 유지/덮어쓰기 여부를 확인한다. 기본은 유지다. 기존 `projectId`를 바꾸려면 파일 삭제가 필요하므로 자동으로 덮어쓰지 않는다.
85
+
86
+ 파일이 없으면 project id를 물어본다. 답변은 비어 있지 않고 alphanumeric 문자를 하나 이상 포함해야 한다. 빈 값으로 `okstra setup --yes`를 호출하면 실패하므로 다시 묻는다.
87
+
88
+ 생성 명령:
89
+
90
+ ```bash
91
+ okstra setup --yes --project-root /abs/project --project-id my-project
92
+ ```
93
+
94
+ ## 선택 설정
95
+
96
+ 원문상 Step 4.5-4.9는 사용자가 명시적으로 원할 때만 수행하는 선택 설정이다. 기본값으로 충분하면 건너뛰고 doctor로 간다.
97
+
98
+ 선택 설정:
99
+
100
+ - `worktreeSyncDirs`: task worktree에 symlink할 프로젝트 상대 디렉터리 목록. 기본은 `.project-docs`, `.scratch`, `graphify-out`, `.claude`.
101
+ - `qaCommands`: implementation verifier가 실행할 check-only lint/format/typecheck/test 명령.
102
+ - `qaEnv`: Tier 3 conformance script가 사용할 replica/test DB, local app URL, env file, surface patterns.
103
+ - PR body template: `okstra config set pr-template-path "<path>" --scope project|global`
104
+ - final report language: `okstra config set report-language <en|ko|auto> --scope project`
105
+
106
+ `qaCommands.cmd`는 mutation을 암시하는 token을 담으면 verifier가 거부한다. deny-list의 실제 권위는 `scripts/okstra_ctl/qa_commands.py`다.
107
+
108
+ ## 자동 Claude 설정 symlink
109
+
110
+ `okstra setup`은 `<PROJECT_ROOT>/.claude/settings.local.json`을 `~/.okstra/templates/settings.local.json` symlink로 provision한다. 기존 regular file이 있으면 `.bak.<timestamp>`로 백업한 뒤 symlink를 둔다. 실패 메시지가 나오면 사용자가 기존 project-specific rule을 수동 병합해야 한다.
111
+
112
+ ## 검증
113
+
114
+ 마지막에 실행:
115
+
116
+ ```bash
117
+ okstra doctor --runtime claude-code
118
+ ```
119
+
120
+ 모든 check가 OK면 setup 완료로 보고한다. 실패가 있으면 출력 내용을 그대로 보여주고, 재설치/스킵 여부는 사용자가 결정하게 한다.
121
+
122
+ ## 완료 메시지
123
+
124
+ 짧게 다음 정보를 포함한다.
125
+
126
+ - runtime 위치: `~/.okstra`
127
+ - project metadata: `<PROJECT_ROOT>/.okstra/project.json`
128
+ - `projectId`
129
+ - 다음 단계: `/okstra-run`
130
+
131
+ ## 흔한 실패 처리
132
+
133
+ | 증상 | 처리 |
134
+ |---|---|
135
+ | `command not found: npx` | Node 18+ 설치 안내 |
136
+ | `--project-id is required` | project id를 다시 물어보고 non-empty 값으로 재실행 |
137
+ | `projectId mismatch` | 어떤 id가 canonical인지 사용자에게 확인. 자동 삭제하지 않음 |
138
+ | `.okstra/` 쓰기 EACCES | ownership/writability 문제를 설명 |
139
+ | `.claude/settings.local.json` symlink warning | 백업 파일과 symlink 상태를 사용자에게 보여주고 수동 병합 안내 |
140
+
@@ -233,8 +233,8 @@ per-process 환경 변수에 task 정체성·경로·workflow 상태를 보관
233
233
  - handoff된 메인 Claude는 `Claude lead`로 동작하며 orchestration과 final synthesis를 담당합니다.
234
234
  - standard workflow의 기본 worker role은 `Claude worker`, `Codex worker`, `Report writer worker`이며, `Antigravity worker`는 `--workers` 또는 프로필에서 명시할 때만 포함되는 옵션입니다.
235
235
  - worker 역할 분담과 최종 판단은 Claude가 task bundle을 읽고 수행합니다.
236
- - 사용자 홈에 설치된 okstra Claude assets(`~/.claude/skills`, `~/.claude/agents`) 는 Agent Teams 우선 시도하고, 구성이 불가능할 때만 sequential/background fallback 사용하도록 Claude 유도합니다.
237
- - **팀 lifecycle**: lead 는 Phase 3 에서 `TeamCreate(team_name: "okstra-<task-key>")` 팀을 만들고 워커를 멤버로 dispatch 합니다. run 종료 시 Phase 7 토큰 집계 이후 먼저 잔여 tmux pane 사용자에게 보여 주고 닫을지 확인한 뒤, Teams mode 에서만 worker teammate `okstra-<task-key>` 을 해제할지 다시 확인합니다. 사용자가 승인하면 `okstra-team-reconcile.sh` 로 dead-pane stale-active 멤버를 정리하고 `TeamDelete` 팀을 해제합니다. `TeamDelete` `~/.claude/teams/<team>/`·`~/.claude/tasks/<team>/` 지우고 토큰 집계 소스인 `~/.claude/projects/` jsonl 보존합니다. 사용자가 유지하거나 teardown 실패하면 worker teammate FleetView roster 에 남으며, lead 는 Teams/FleetView 에서 해당 team 을 삭제하라고 안내합니다 (`prompts/profiles/_common-contract.md` 의 *Run-end teammate teardown*). no-`team_name` fallback 에서는 팀이 없으므로 silent-skip.
236
+ - 사용자 홈에 설치된 okstra Claude assets(`~/.claude/skills`, `~/.claude/agents`) 는 `Agent(name: ...)` 워커를 dispatch 하도록 Claude 유도합니다 워커는 세션의 implicit team 자동 합류합니다.
237
+ - **팀 lifecycle (Claude Code v2.1.178+)**: v2.1.178 이 `TeamCreate` / `TeamDelete` 도구와 `Agent(...)` 의 `team_name` 파라미터를 제거했습니다. `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`(`okstra install` 이 `settings.json` 에 시드) 이면 세션마다 implicit team 1개가 시작 시점에 자동 생성됩니다. lead 는 Phase 3 에서 팀을 만드는 도구를 호출하지 않고, `teamName` audit 라벨과 `teamCreate: { attempted: false, status: "implicit", splitPane: <$TMUX 유무> }` 기록한 워커를 `Agent(name: "<role>-worker", run_in_background: true)`(team_name 없음)로 dispatch 합니다. split-pane teammate 는 `$TMUX` 가 설정돼 있고 `teammateMode: auto` 일 때 나타나며, tmux 밖이면 in-process 로 돕니다(둘 다 정상). run 종료 시 Phase 7 토큰 집계 이후 잔여 tmux pane 정리를 확인하고, split-pane run 에서만 worker teammate 정리할지 확인합니다. 승인 `okstra-team-reconcile.sh` 로 dead-pane stale-active 멤버를 inactive 로 정리하고 완료 teammate `SendMessage` shutdown_request 보냅니다 implicit team 자체를 지우는 도구는 없으며, 팀은 세션 종료와 함께 사라집니다. 사용자가 유지하면 teammate FleetView roster 에 남고, lead 는 Teams/FleetView 에서 제거하라고 안내합니다 (`prompts/profiles/_common-contract.md` 의 *Run-end teammate teardown*). Phase 7 토큰 집계는 `teamCreate.status` `implicit`/`skipped`/`error` `agentName` 기반으로 워커 세션을 찾습니다(implicit team 은 jsonl 을 `session-<leadSid>` 로 태깅하므로 okstra 의 `teamName` 라벨 needle 만으로는 lead 만 잡힘).
238
238
 
239
239
  ## Claude prompt contract
240
240
 
@@ -348,7 +348,7 @@ okstra phase 는 PRD / issue file 을 직접 쓰지 않습니다. 동등한 결
348
348
  - `implementation`을 제외한 모든 phase는 source code edit, build, migration, deployment, 그 밖의 state-mutating 명령을 금지합니다(`final-verification`은 read-only 테스트 명령만 허용). `implementation`은 승인된 plan의 파일 목록 안에서만 edit/commit이 허용되며, `git push`·publish·deploy·실제 migration·third-party write API는 여전히 금지됩니다.
349
349
  - **모든 task-type 격리 worktree (BLOCKING)**: 모든 task-type 의 첫 번째 phase prepare 단계에서 `okstra-ctl` 이 자동으로 task-key 단위 `git worktree` 를 생성하고, 같은 task-key 의 이후 phase (`requirements-discovery` → `error-analysis` → `implementation-planning` → `implementation`) 는 동일한 worktree·브랜치를 재사용합니다. 위치는 `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` (segment 의 `/`·`:` 등 특수문자는 `-` 로 정규화) 이고, 브랜치 이름은 `<work-category-prefix>-<task-id-segment>` (예: `feat-dev-9436`, `fix-dev-7311`) 입니다. base ref 는 첫 phase prepare 시점의 main worktree `HEAD`. `~/.okstra/worktrees/registry.json` (flock-guarded) 가 task-key → path/branch 매핑을 전역 관리해 동시 실행 시 path·branch 충돌을 방지합니다. configured sync dirs 는 main worktree 에서 symlink 로 연결되어 task checkout 사이의 filesystem continuity 를 제공합니다 (sync 대상 목록은 `project.json` 의 `worktreeSyncDirs` 또는 `OKSTRA_WORKTREE_SYNC_DIRS` 환경변수로 override 가능; 빈 배열이면 sync 비활성화). 이 sync 는 okstra context/write boundary 를 확장하지 않습니다. caller 가 이미 다른 worktree 안에 있거나 project_root 가 git repo 가 아니면 provisioning 은 skip 되고 executor 는 project_root 에서 그대로 작업합니다. worktree 는 run 종료 후 자동 삭제되지 않으며 후속 phase·PR 작성·rollback 검증의 권위 artefact 입니다. 수동 cleanup: `git -C <main-worktree> worktree remove <path>` → `git -C <main-worktree> branch -D <branch>` + registry 항목 삭제. 자세한 동작은 `prompts/profiles/implementation.md` 의 *Task worktree* 블록과 `prompts/lead/okstra-lead-contract.md` 의 *Task worktree (BLOCKING for every task-type)* 섹션 참고.
350
350
  - **implementation stage 격리 worktree (동시 병렬)**: 위 task-key 단위 worktree 는 `requirements-discovery`~`implementation-planning` 의 모델입니다. `implementation` task 는 **stage 격리** 로 동작합니다 (spec `docs/superpowers/specs/2026-06-06-stage-worktree-isolation-design.md`) — **한 run = 한 stage**, 각 run 이 `.../<task-id-segment>/stage-<N>/` (브랜치 `<prefix>-<task-id-segment>-s<N>`) 격리 worktree 를 발급받습니다. registry 가 task-key 와 **stage-key** (`<task-key>#stage-<N>`) 를 함께 flock 예약하고, `_resolve_effective_stages` 가 `consumers.jsonl` 의 `started` + registry 예약 stage 를 ready 집합에서 제외하므로(점유 SSOT = registry), 사용자가 두 `implementation` run 을 동시에 띄우면 서로 다른 독립 stage 를 충돌 없이 진행합니다. base 결정: 독립 = 공통 anchor(첫 stage 진입 HEAD 고정), 단일 의존 = 선행 done commit, 다중 의존 = 선행이 모두 ancestor 인 task worktree HEAD(`git merge-base --is-ancestor`; 미머지 시 `PrepareError`). cost-aware-design 의 ready-set batch 는 stage 마다 격리 branch 가 필요해 의미를 잃으므로(같은 branch 에 두 stage-key reserve 시 branch-uniqueness 충돌) 폐기되었고, 순차 진행은 stage done 후 다음 run, 동시 진행은 별도 run 으로 — cost 등가. `--stage <auto|N>` 또는 wizard `stage_pick` 으로 stage 를 선택합니다. worktree 뿐 아니라 **run 산출물(report·state·worker-results·manifest)도 `runs/implementation/stage-<N>/` 로 stage 별 격리**되므로 동시 실행하는 두 stage 의 보고서·상태가 섞이지 않습니다. 반면 `consumers.jsonl` 과 worktree registry 는 stage 간 공유되는 조율 SSOT 라 task-type 루트(`runs/implementation/`)에 그대로 둡니다.
351
- - **단일-stage final-verification 의 run 산출물 격리 (동시 병렬)**: 단독-stage `final-verification`(`--stage <N>`)도 implementation 과 동일하게 run 산출물을 `runs/final-verification/stage-<N>/` 하위에 격리하고(seq 도 stage 별 독립), 팀 이름에 `-fv-s<N>` 접미사를 붙입니다 — `-fv-` 구분자로 같은 stage 의 implementation 팀(`-s<N>`)과도, 전체-task 검증의 기본 이름과도 충돌하지 않습니다. 따라서 여러 stage 의 final-verification 을 동시에 띄워도 state·worker-results·보고서·팀이 섞이지 않습니다. worktree 는 새로 만들지 않고 해당 implementation stage worktree 를 registry 에서 read-only 로 재사용하며, 그래서 registry stage-key 예약도 하지 않습니다 **같은 stage final-verification 동시에 번** 띄우는 경우는 격리되지 않고 `TeamCreate` 이름 충돌로 즉시 실패합니다(알려진 제약). 전체-task 검증(stage 빈 값)은 기존 평면 `runs/final-verification/` 구조를 유지합니다.
351
+ - **단일-stage final-verification 의 run 산출물 격리 (동시 병렬)**: 단독-stage `final-verification`(`--stage <N>`)도 implementation 과 동일하게 run 산출물을 `runs/final-verification/stage-<N>/` 하위에 격리하고(seq 도 stage 별 독립), 팀 이름에 `-fv-s<N>` 접미사를 붙입니다 — `-fv-` 구분자로 같은 stage 의 implementation 팀(`-s<N>`)과도, 전체-task 검증의 기본 이름과도 충돌하지 않습니다. 따라서 여러 stage 의 final-verification 을 동시에 띄워도 state·worker-results·보고서·팀이 섞이지 않습니다. worktree 는 새로 만들지 않고 해당 implementation stage worktree 를 registry 에서 read-only 로 재사용하며, 그래서 registry stage-key 예약도 하지 않습니다. `teamName` 라벨에 `-fv-s<N>` 접미사를 붙이는 것은 audit/표시용 구분일 뿐이며, 실제 팀은 세션별 implicit team(`session-<leadSid>`)이라 v2.1.178 이전의 `TeamCreate` 이름 충돌 hard-fail 이상 발생하지 않습니다. 전체-task 검증(stage 빈 값)은 기존 평면 `runs/final-verification/` 구조를 유지합니다.
352
352
  - `implementation` 과 `release-handoff` 를 제외한 모든 phase 는 source code edit, build, migration, deployment, 그 밖의 state-mutating 명령을 금지합니다 (`final-verification` 은 read-only 테스트 명령만 허용). `implementation` 은 승인된 plan 의 파일 목록 안에서만 edit/commit 이 허용되며, `git push`·publish·deploy·실제 migration·third-party write API 는 여전히 금지됩니다. `release-handoff` 는 source code 자체는 수정하지 않고, 사용자가 메뉴로 선택한 commit / push / PR 명령만 실행합니다 (force push, base 브랜치 직접 push, hook bypass, release publish 는 여전히 금지).
353
353
  - 사용자가 "다음 단계 진행해" 같은 표현을 보내도, 그 발화만으로 다음 phase가 자동 시작되지 않습니다. 다음 phase는 새 `okstra.sh` 실행으로만 시작합니다.
354
354
  - **Authority & permissions assumption (모든 task-type 및 `okstra-schedule` 공통)**: 사용자(및 팀)는 예상되는 모든 작업에 대해 완전한 권한·승인 권한을 보유한다고 가정합니다. 외부 승인, 서드파티 액세스, 역할/IAM 권한, 조직적 sign-off, 법무·보안 검토, 벤더 협의, "권한 보유 여부 확인" 같은 항목을 routing 결정·missing inputs·clarification questions·risk·dependency·open questions·effort/day 추정에 포함하지 않습니다. okstra 내부 phase 핸드오프(`implementation-planning`의 `approved:` frontmatter 등)는 사용자 본인이 즉시 승인 가능한 내부 게이트이므로 영향 없으며, `implementation`의 forbidden actions(`git push`, prod deploy, shared-DB migration 등)도 권한 사유가 아닌 **안전 사유**로 계속 적용됩니다.
@@ -683,7 +683,7 @@ Phase 7 step 1.5 가 final-report MD 한 본을 입력으로 두 view 를 결정
683
683
  - tmux 가 reachable 한 lead 환경이면 wrapper 가 sibling pane 을 자동 분할해 `tail -F <log-path>` 를 띄웁니다. trace pane title 은 caller (worker) pane title 에 `-tail` 을 붙인 `<cli>-<role>-<pid>-tail` (e.g. `codex-worker-93421-tail`); 동일 시점에 caller (worker) pane title 은 `<cli>-<role>-<pid>` 로 셋팅됩니다. `<pid>` 는 wrapper 자기 자신의 PID 라서 동일 role 의 worker 가 둘 이상 동시에 spawn 돼도 서로 구분되고, 운영자는 `<caller> ↔ <caller>-tail` 로 시각적으로 매핑할 수 있습니다. **caller pane 해석** — Claude Code Bash tool 은 이제 `$TMUX` 와 `$TMUX_PANE` 를 둘 다 환경에서 제거하므로 env 변수에 의존하지 않습니다. wrapper 는 (1) prompt path 로부터 `<RUN_DIR>` (= `dirname(dirname(prompt_path))`, paths.py SSOT) 를 도출하고, (2) lead 가 자기 foreground pane 에서 1회 기록한 `<RUN_DIR>/state/lead-pane.id` 를 읽어 split anchor 로 씁니다 (background dispatch 에서도 신뢰 가능 — active-pane 추정과 달리 사용자가 pane 을 옮겨도 안전). 기록 파일이 없거나 pane 이 stale 이면 `tmux display-message -p '#{pane_id}'` (active pane) 으로 fallback. trace pane split 은 그 caller pane 을 `-t` 로 명시 anchor 합니다. role 은 wrapper 의 5번째 optional positional 인자이며, 누락 시 기본값 `worker`. caller pane title 은 capture 해두고 EXIT trap 에서 복원하므로 dispatch 사이의 stale title 이 남지 않습니다. focus 는 caller pane 으로 복귀하고, CLI 종료 후 pane 은 유지돼 스크롤백 가능. tmux 미reachable, split 실패, 구버전 tmux 등 모든 경로는 silent degrade.
684
684
  - **run-scoped 태깅으로 정리**: trace pane 의 `tail -F` 는 tmux 셸의 자식이라 Claude 가 종료돼도 살아남습니다. wrapper 는 spawn 한 pane 을 `tmux set-option -p @okstra_trace_run=<RUN_DIR>` 로 태깅하고, `okstra-trace-cleanup.sh` 는 `tmux list-panes -a` 에서 그 태그로 pane 을 server-wide 발견해 `tmux kill-pane` 합니다. tmux env 변수·pane-id registry 없이 동작하며, run-scoped 태그라 동시에 도는 다른 okstra run 의 trace pane 을 죽이지 않습니다. cleanup 은 두 진입 형태를 가집니다 — lead 가 `--run-dir <RUN_DIR>` 로 호출(해당 run 의 trace + worker-agent pane 정리)하거나, `templates/reports/settings.template.json` 의 `hooks.SessionEnd` 가 `--reap` 로 호출(`$CLAUDE_PROJECT_DIR/.okstra/` 하위 태그를 가진 trace pane 일괄 정리; 단일 run-dir 이 없는 종료 시점용). tmux 가 없거나 stale pane id 인 경우 silent degrade.
685
685
  - **phase 전환 시 자동 정리 + worker-agent pane 포함**: `okstra-trace-cleanup.sh --run-dir <RUN_DIR>` 는 태깅된 trace pane 뿐 아니라 dispatch 된 서브에이전트가 점유하는 worker-agent pane(title `claude-worker` / `codex-worker` / `antigravity-worker` / `report-writer-worker`)도 lead 세션(`tmux list-panes -s -t <lead-pane>`) 범위에서 title allowlist 로 식별해 닫습니다(worker-agent pane 은 harness 소유라 태깅 불가). 세션 scope 와 lead 자기 pane 제외는 `<RUN_DIR>/state/lead-pane.id` 로 결정되며, lead 자신의 pane 은 title 이 걸려도 절대 죽이지 않습니다. lead 는 새 phase 의 worker 를 dispatch 하기 직전(`PROGRESS: phase-5.5-convergence` / `phase-6-synthesis` 마커 직전) 이 스크립트를 `--run-dir` 로 호출해 이전 phase 의 pane 을 prompt 없이 정리합니다.
686
- - **Phase 종료 시 사용자 확인**: run 최종 종료 시점(마지막 단계)에 lead 가 `okstra-trace-cleanup.sh --list --run-dir <RUN_DIR>` 로 잔여 okstra pane(worker-agent + trace) 목록을 출력한 뒤 사용자에게 "모두 닫기 / 그대로 두기" 양자택일을 묻고 응답대로 처리합니다 (`prompts/profiles/_common-contract.md` 의 *Phase wrap-up* 항목). 그 다음 Teams mode 인 경우 worker teammate 팀을 해제할지 별도로 묻고, 승인 시 `okstra-team-reconcile.sh` + `TeamDelete` 를 실행합니다. lead 는 이 pane 단계를 `lead-pane.id` 를 직접 해석해 게이트하지 않고 **항상** 스크립트를 호출하며, tmux 밖이면 스크립트가 빈 pane 목록으로 안전하게 no-op 합니다. teammate 단계는 `teamCreate.status` 가 아니라 on-disk team config(`~/.claude/teams/session-*/config.json` 의 `leadSessionId` 매칭) 존재로 판단합니다. `--list` 모드는 pane 을 죽이지 않고 `<pane_id>\t<pane_title>` 만 출력하므로 사용자가 무엇이 닫힐지 시각적으로 확인할 수 있습니다.
686
+ - **Phase 종료 시 사용자 확인**: run 최종 종료 시점(마지막 단계)에 lead 가 `okstra-trace-cleanup.sh --list --run-dir <RUN_DIR>` 로 잔여 okstra pane(worker-agent + trace) 목록을 출력한 뒤 사용자에게 "모두 닫기 / 그대로 두기" 양자택일을 묻고 응답대로 처리합니다 (`prompts/profiles/_common-contract.md` 의 *Phase wrap-up* 항목). 그 다음 split-pane run 인 경우 worker teammate 정리할지 별도로 묻고, 승인 시 `okstra-team-reconcile.sh` dead-pane 멤버를 inactive 로 정리한 뒤 각 완료 teammate 에 `SendMessage` shutdown_request 보냅니다(`TeamDelete` 는 v2.1.178 에서 제거 — implicit team 은 세션 종료와 함께 사라짐). lead 는 이 pane 단계를 `lead-pane.id` 를 직접 해석해 게이트하지 않고 **항상** 스크립트를 호출하며, tmux 밖이면 스크립트가 빈 pane 목록으로 안전하게 no-op 합니다. teammate 단계는 `teamCreate.status` 가 아니라 on-disk team config(`~/.claude/teams/session-*/config.json` 의 `leadSessionId` 매칭) 존재로 판단합니다. `--list` 모드는 pane 을 죽이지 않고 `<pane_id>\t<pane_title>` 만 출력하므로 사용자가 무엇이 닫힐지 시각적으로 확인할 수 있습니다.
687
687
  - 디스크 누적은 `okstra-inspect logs` 흐름이 read-only 로 인벤토리 + cleanup 명령을 제안합니다 (실행은 사용자 copy-paste).
688
688
 
689
689
  ### Linked-worktree `.git/` write 권한 (codex / antigravity)
@@ -738,7 +738,7 @@ phase 산출물의 출고 가능 여부를 강제하는 진입점:
738
738
  - project-level current-task convenience pointer는 `.okstra/discovery/latest-task.json`입니다.
739
739
  - project-level canonical task inventory는 `.okstra/discovery/task-catalog.json`입니다.
740
740
  - okstra skill asset은 `okstra install` 시점에 존재하는 agent home 기준으로 seed됩니다: `~/.claude/skills/` + `~/.claude/agents/`, `~/.codex/skills/`, 또는 fallback `~/.omp/agent/skills/` (per-project seeding은 더 이상 수행되지 않음).
741
- - seeded okstra Claude assets는 Agent Teams 우선, sequential/background fallback 차선 규칙을 Claude에게 제공합니다. Codex/OMP targets 는 skill markdown 만 받습니다.
741
+ - seeded okstra Claude assets는 세션의 implicit team 에 `Agent(name: ...)` 워커를 dispatch 하는 규칙을 Claude에게 제공합니다(v2.1.178 이 `TeamCreate`/`TeamDelete` 제거). Codex/OMP targets 는 skill markdown 만 받습니다.
742
742
  - 최종 판단은 스크립트가 아니라 Claude가 수행합니다.
743
743
  - stable task key를 유지해야 이후 bug 추적, 재수정, 재검증이 가능합니다.
744
744
  - 워커 에러는 옵션 sidecar `runs/<task-type>/logs/errors-<task-type>-<seq>.jsonl`로 수집되며 lead가 단독 writer입니다. 진입점 helper는 `scripts/okstra-error-log.py`입니다.