okstra 0.123.0 → 0.124.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 (82) hide show
  1. package/README.md +1 -0
  2. package/docs/architecture/storage-model.md +1 -1
  3. package/docs/architecture.md +11 -1
  4. package/docs/cli.md +2 -0
  5. package/docs/for-ai/README.md +41 -35
  6. package/docs/for-ai/skills/okstra-brief-gen.md +105 -105
  7. package/docs/for-ai/skills/okstra-container-build.md +61 -61
  8. package/docs/for-ai/skills/okstra-graphify.md +64 -0
  9. package/docs/for-ai/skills/okstra-inspect.md +86 -86
  10. package/docs/for-ai/skills/okstra-manager.md +32 -32
  11. package/docs/for-ai/skills/okstra-memory.md +49 -50
  12. package/docs/for-ai/skills/okstra-pr-gen.md +48 -0
  13. package/docs/for-ai/skills/okstra-rollup.md +58 -58
  14. package/docs/for-ai/skills/okstra-run.md +95 -95
  15. package/docs/for-ai/skills/okstra-schedule-gen.md +106 -106
  16. package/docs/for-ai/skills/okstra-setup.md +63 -64
  17. package/docs/for-ai/skills/okstra-user-response.md +48 -0
  18. package/docs/performance-improvement-plan-v2.md +4 -4
  19. package/docs/pr-template-usage.md +34 -34
  20. package/docs/project-structure-overview.md +91 -70
  21. package/docs/task-process/README.md +33 -33
  22. package/docs/task-process/common-flow.md +26 -26
  23. package/docs/task-process/error-analysis.md +20 -21
  24. package/docs/task-process/final-verification.md +41 -41
  25. package/docs/task-process/implementation-planning.md +33 -33
  26. package/docs/task-process/implementation.md +38 -38
  27. package/docs/task-process/release-handoff.md +46 -46
  28. package/docs/task-process/requirements-discovery.md +22 -23
  29. package/package.json +1 -1
  30. package/runtime/BUILD.json +2 -2
  31. package/runtime/agents/workers/antigravity-worker.md +4 -4
  32. package/runtime/agents/workers/claude-worker.md +2 -2
  33. package/runtime/agents/workers/codex-worker.md +4 -4
  34. package/runtime/agents/workers/report-writer-worker.md +4 -4
  35. package/runtime/prompts/coding-preflight/frameworks/node-server.md +1 -1
  36. package/runtime/prompts/launch.template.md +1 -1
  37. package/runtime/prompts/lead/convergence.md +10 -20
  38. package/runtime/prompts/lead/okstra-lead-contract.md +14 -16
  39. package/runtime/prompts/lead/plan-body-verification.md +18 -18
  40. package/runtime/prompts/lead/report-writer.md +43 -44
  41. package/runtime/prompts/lead/team-contract.md +11 -122
  42. package/runtime/prompts/profiles/_common-contract.md +15 -22
  43. package/runtime/prompts/profiles/_implementation-deliverable.md +1 -1
  44. package/runtime/prompts/profiles/_implementation-executor.md +1 -1
  45. package/runtime/prompts/profiles/_implementation-verifier.md +2 -2
  46. package/runtime/prompts/profiles/error-analysis.md +2 -2
  47. package/runtime/prompts/profiles/final-verification.md +1 -1
  48. package/runtime/prompts/profiles/implementation-planning.md +13 -13
  49. package/runtime/prompts/profiles/implementation.md +1 -1
  50. package/runtime/prompts/profiles/improvement-discovery.md +1 -1
  51. package/runtime/prompts/profiles/release-handoff.md +3 -3
  52. package/runtime/prompts/profiles/requirements-discovery.md +18 -18
  53. package/runtime/skills/_fragments/bash-invocation-rule.md +1 -0
  54. package/runtime/skills/_fragments/preflight-outdated-cli.md +1 -0
  55. package/runtime/skills/_fragments/python-bootstrap-note.md +1 -0
  56. package/runtime/skills/okstra-brief-gen/SKILL.md +117 -122
  57. package/runtime/skills/okstra-container-build/SKILL.md +24 -14
  58. package/runtime/skills/okstra-graphify/SKILL.md +12 -4
  59. package/runtime/skills/okstra-inspect/SKILL.md +104 -98
  60. package/runtime/skills/okstra-manager/SKILL.md +1 -1
  61. package/runtime/skills/okstra-memory/SKILL.md +3 -3
  62. package/runtime/skills/okstra-rollup/SKILL.md +12 -6
  63. package/runtime/skills/okstra-run/SKILL.md +49 -88
  64. package/runtime/skills/okstra-schedule-gen/SKILL.md +36 -30
  65. package/runtime/skills/okstra-setup/SKILL.md +1 -1
  66. package/runtime/skills/okstra-setup/references/project-config.md +17 -16
  67. package/runtime/skills/okstra-usage/SKILL.md +5 -2
  68. package/runtime/skills/okstra-user-response/SKILL.md +15 -3
  69. package/runtime/templates/prd/brief.template.md +92 -92
  70. package/runtime/templates/reports/error-analysis-input.template.md +1 -1
  71. package/runtime/templates/reports/fan-out-unit.template.md +6 -6
  72. package/runtime/templates/reports/final-verification-input.template.md +6 -6
  73. package/runtime/templates/reports/implementation-input.template.md +1 -1
  74. package/runtime/templates/reports/implementation-planning-input.template.md +1 -1
  75. package/runtime/templates/reports/improvement-discovery-input.template.md +1 -1
  76. package/runtime/templates/reports/quick-input.template.md +1 -1
  77. package/runtime/templates/reports/release-handoff-input.template.md +1 -1
  78. package/runtime/templates/reports/schedule.template.md +22 -22
  79. package/runtime/templates/reports/task-brief.template.md +3 -3
  80. package/runtime/templates/reports/user-response.template.md +20 -20
  81. package/runtime/templates/worker-prompt-preamble.md +111 -13
  82. package/runtime/validators/validate-schedule.py +1 -1
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: okstra-inspect
3
3
  description: >-
4
- Use this for everything that happens AFTER a single okstra task has already run — inspecting it or light bookkeeping on it, never launching new work. The tell is usually a named task id (PROD-1623, dev-9184), often dropped without the word "okstra." Reach for it when the user wants one task's: status, current/next phase, blockers, or approval gate; its final report — where it is or whether it passed (결론·통과); its elapsed time (소요 시간) or context/read cost (컨텍스트 비용); its run history, re-run, or resume; to mark it done / in-progress / blocked / todo; or a failed run's error logs gathered into a report (에러 리포트). Also bundles cross-project okstra errors into an anonymized feedback zip (에러 환류). Use it even for a bare "mark it done" or "where's the report." NOT for starting a run (okstra-run), rollups/schedules (okstra-rollup / okstra-schedule-gen), a brief (okstra-brief-gen), setup (okstra-setup), or cross-project management (okstra-manager).
4
+ Use this for everything that happens AFTER a single okstra task has already run — inspecting it or light bookkeeping on it, never launching new work. The tell is usually a named task id (PROD-1623, dev-9184), often dropped without the word "okstra." Reach for it when the user wants one task's: status, current/next phase, blockers, or approval gate; its final report — where it is or whether it passed (verdict / pass); its elapsed time or context/read cost; its run history, re-run, or resume; to mark it done / in-progress / blocked / todo; or a failed run's error logs gathered into a report (error report). Also bundles cross-project okstra errors into an anonymized feedback zip (error feedback). Use it even for a bare "mark it done" or "where's the report." NOT for starting a run (okstra-run), rollups/schedules (okstra-rollup / okstra-schedule-gen), a brief (okstra-brief-gen), setup (okstra-setup), or cross-project management (okstra-manager).
5
5
  ---
6
6
 
7
7
  # OKSTRA Inspect
@@ -22,7 +22,9 @@ Single read-side entry point for okstra runtime inspection plus the one status m
22
22
 
23
23
  ## Step 0: Preflight (shared)
24
24
 
25
- Before any sub-command, run one Bash tool call, starting with the literal token `okstra` (never wrapped in `if`/`eval`/`export`/`$(...)`/`VAR=...`/`||`/`&&`/`npx` — a non-literal leading token defeats the `Bash(okstra:*)` permission match):
25
+ <!-- BEGIN FRAGMENT: bash-invocation-rule -->
26
+ Run one Bash tool call, starting with the literal token `okstra` (never wrapped in `if`/`eval`/`export`/`$(...)`/`VAR=...`/`||`/`&&`/`npx` — a non-literal leading token defeats the `Bash(okstra:*)` permission match):
27
+ <!-- END FRAGMENT: bash-invocation-rule -->
26
28
 
27
29
  ```bash
28
30
  okstra preflight --runtime claude-code --json
@@ -32,13 +34,21 @@ The project check only sees the cwd of the Bash call. When the user is asking ab
32
34
 
33
35
  Branch on the stdout JSON:
34
36
  - `ok: true` → carry `projectRoot` as a literal string; it is the base for every sub-command step below.
35
- - `ok: false` → before concluding "no setup", ask whether the user pointed at a specific project directory. If they did, re-run targeting it: `okstra preflight --runtime claude-code --cwd <that-dir> --json` (`--cwd` is the sanctioned way to target a project — a leading `cd` would break the permission match). Only if this **also** returns `ok:false` do you tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop. If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
37
+ - `ok: false` → before concluding "no setup", ask whether the user pointed at a specific project directory. If they did, re-run targeting it: `okstra preflight --runtime claude-code --cwd <that-dir> --json` (`--cwd` is the sanctioned way to target a project — a leading `cd` would break the permission match). Only if this **also** returns `ok:false` do you tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop.
36
38
 
37
- Carry the resolved `projectRoot` into the sub-commands: read file artifacts under `<projectRoot>/.okstra/...`, and for sub-command CLIs that accept it (e.g. `recap`, `context-cost`) pass `--cwd <projectRoot>` / `--project-root <projectRoot>` so they target the same project rather than the Bash cwd. Subsequent `okstra <subcmd>` calls self-bootstrap their Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
39
+ <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
40
+ If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
41
+ <!-- END FRAGMENT: preflight-outdated-cli -->
42
+
43
+ Carry the resolved `projectRoot` into the sub-commands: read file artifacts under `<projectRoot>/.okstra/...`, and for sub-command CLIs that accept it (e.g. `recap`, `context-cost`) pass `--cwd <projectRoot>` / `--project-root <projectRoot>` so they target the same project rather than the Bash cwd.
44
+
45
+ <!-- BEGIN FRAGMENT: python-bootstrap-note -->
46
+ Every subsequent `okstra <subcmd>` call self-bootstraps its Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
47
+ <!-- END FRAGMENT: python-bootstrap-note -->
38
48
 
39
49
  ## Step 1: Dispatch by intent
40
50
 
41
- Classify the user's request into one sub-command using the trigger table above. If ambiguous (e.g. "okstra 보여줘"), ask which facet — do not silently default. After routing, the chosen sub-command's section below governs the rest of the response.
51
+ Classify the user's request into one sub-command using the trigger table above. If ambiguous (e.g. "show me okstra"), ask which facet — do not silently default. After routing, the chosen sub-command's section below governs the rest of the response.
42
52
 
43
53
  When you ask which facet, the option list is **authoritative**: enumerate every sub-command in the `Sub-command | What it does` table above as a numbered text list, in table order, each with its one-line description, and let the user pick by number or name. Never present a hand-picked subset — the AskUserQuestion 4-option cap is not a reason to drop facets; render the full menu as text in the question body so no facet (e.g. a newly added one) is ever hidden. The table is the single source of truth for this menu; adding a row there is all it takes for the facet to appear here.
44
54
 
@@ -48,7 +58,7 @@ When the user chains multiple facets in one message (e.g. "status, and then time
48
58
 
49
59
  ## status
50
60
 
51
- Trigger phrases: "okstra status", "task status", "current phase", "next phase", "what is pending", "resume point", "okstra status set", "okstra mark", "<task-id> done", "<task-id> in-progress", "<task-id> 진행중", "<task-id> 완료".
61
+ Trigger phrases: "okstra status", "task status", "current phase", "next phase", "what is pending", "resume point", "okstra status set", "okstra mark", "<task-id> done", "<task-id> in-progress", "<task-id> in progress", "<task-id> complete".
52
62
 
53
63
  ### status.1 — Overall project status
54
64
 
@@ -64,7 +74,7 @@ Read `.okstra/discovery/task-catalog.json`. The catalog is the authoritative sou
64
74
  | `currentPhaseState` | lifecycle phase state |
65
75
  | `nextRecommendedPhase` | next recommended phase |
66
76
  | `routingStatus` | routing decision status |
67
- | `awaitingApproval` | approval 대기 여부 |
77
+ | `awaitingApproval` | whether awaiting approval |
68
78
  | `latestRunStatus` | latest run status |
69
79
  | `latestReportPath` | latest report path |
70
80
  | `latestResumeCommandPath` | latest resume command |
@@ -149,7 +159,7 @@ Recognize requests to change a task's `workStatus` and update the corresponding
149
159
 
150
160
  **Trigger patterns** (recognize both):
151
161
 
152
- Natural language: "DEV-6827 done으로 바꿔줘", "PROD-1623을 blocked로 표시", "DEV-9047 진행중", "Mark DEV-6827 as done".
162
+ Natural language: "change DEV-6827 to done", "mark PROD-1623 as blocked", "set DEV-9047 in progress", "Mark DEV-6827 as done".
153
163
 
154
164
  Explicit phrasing (recognized user utterances — normalize each to a `okstra set-work-status` call below):
155
165
  - `okstra status set <task-id> <status>`
@@ -166,14 +176,14 @@ okstra set-work-status <token> <status> --project-root <projectRoot> --json
166
176
  ```
167
177
 
168
178
  - `<token>` is a full task-key or a bare task-id. Add `--task-group <group>` to scope a duplicated id, `--note "<note>"` to set `workStatusNote` (flag omitted → any existing note is left untouched).
169
- - Branch on the stdout JSON: `ok: true` → confirm below. `stage: "ambiguous"` → list `matches[]` (with `_matchedVia`) via a 3-option picker and retry with the chosen full task-key. `stage: "not-found"` → `<TASK-ID>를 찾을 수 없습니다.` An invalid `<status>` makes the CLI exit 2 with the allowed-values list — surface it verbatim; nothing was modified.
179
+ - Branch on the stdout JSON: `ok: true` → confirm below. `stage: "ambiguous"` → list `matches[]` (with `_matchedVia`) via a 3-option picker and retry with the chosen full task-key. `stage: "not-found"` → `<TASK-ID> cannot be found.` An invalid `<status>` makes the CLI exit 2 with the allowed-values list — surface it verbatim; nothing was modified.
170
180
 
171
181
  Confirm in Korean:
172
182
  ```
173
183
  ✓ <TASK-ID> workStatus: <previousWorkStatus> → <workStatus>
174
- ✓ task-manifest.json 업데이트됨
184
+ ✓ task-manifest.json updated
175
185
  ```
176
- `<previousWorkStatus>` = `(없음)` when the JSON's `previousWorkStatus` is empty.
186
+ `<previousWorkStatus>` = `(none)` when the JSON's `previousWorkStatus` is empty.
177
187
 
178
188
  **Default value convention:** if `workStatus` is missing or empty, infer the display value from lifecycle state (DO NOT default to a static `in-progress`):
179
189
 
@@ -192,7 +202,7 @@ Annotate inferred values with `(inferred)` or `(default)`. Do not back-fill on r
192
202
 
193
203
  ## history
194
204
 
195
- Trigger phrases: "okstra history", "past runs", "run history", "re-run", "list tasks", "다시 실행", "resume", "이어서".
205
+ Trigger phrases: "okstra history", "past runs", "run history", "re-run", "list tasks", "run again", "resume", "continue".
196
206
 
197
207
  **Re-run vs Resume — decide upfront.** Re-run = start a fresh run (new run-seq, new manifest, new report) reusing an old run's parameters → `history.3`. Resume = continue an interrupted Claude session for an existing run, no new run-seq → `history.4`. If the user is ambiguous, ask — defaulting to the wrong one either wastes a fresh run-seq or silently abandons a recoverable session.
198
208
 
@@ -293,7 +303,7 @@ Lookup methods (in priority order):
293
303
 
294
304
  A. **`task-catalog.json` (fast):** read `.okstra/discovery/task-catalog.json`, match `taskKey` lowercase. `latestReportPath` is task-type-agnostic "most recent report".
295
305
 
296
- B. **`task-manifest.json` (direct):** if catalog missing, slugify task-group / task-id, read `.okstra/tasks/<group-segment>/<id-segment>/task-manifest.json`, use `latestReportPath` (task-type-agnostic).
306
+ B. **`task-manifest.json` (direct):** if catalog missing, slugify task-group / task-id, read `.okstra/tasks/<group-segment>/<task-id-segment>/task-manifest.json`, use `latestReportPath` (task-type-agnostic).
297
307
 
298
308
  C. **`timeline.json` (specific run):** for a specific date or run, read `.okstra/tasks/<group-segment>/<id-segment>/history/timeline.json`, filter `runs[]` by `runTimestamp` / `status` / `taskType`, use `runs[].reportPath`.
299
309
 
@@ -304,23 +314,23 @@ D. **Specific task-type (fallback):** `latestReportPath` is task-type-agnostic.
304
314
  1. Verify `latestReportPath` is non-empty AND the file exists on disk. Either signal indicates report presence (tolerant).
305
315
  2. If present, display the path and ask the user whether to read it.
306
316
  3. If absent, check `task-manifest.json` signals:
307
- - `latestReportPath` empty/missing AND `currentStatus != completed` AND `workStatus != done` AND `workflow.routingStatus` not completion-like → `이 task는 아직 완료되지 않았습니다 (currentStatus: <currentStatus>, workStatus: <workStatus>).`
308
- - Any signal indicates completion but the file is missing → `보고서 파일이 존재하지 않습니다: <path>`
317
+ - `latestReportPath` empty/missing AND `currentStatus != completed` AND `workStatus != done` AND `workflow.routingStatus` not completion-like → `This task is not yet complete (currentStatus: <currentStatus>, workStatus: <workStatus>).`
318
+ - Any signal indicates completion but the file is missing → `Report file does not exist: <path>`
309
319
 
310
320
  `workStatus` enum: `todo | in-progress | blocked | done`. `currentStatus`: `completed` / `contract-violated` etc. `"completed"` string does NOT exist in `workStatus` — do not confuse the two.
311
321
 
312
322
  ### report.3 — Read + next-step guidance
313
323
 
314
- Match the depth of read to the request — final reports routinely run 300+ lines / 50K+ tokens, so ingesting the whole file just to answer "핵심만 요약" is wasteful:
324
+ Match the depth of read to the request — final reports routinely run 300+ lines / 50K+ tokens, so ingesting the whole file just to answer "just the gist" is wasteful:
315
325
 
316
- - **Summary / verdict intent** ("요약", "핵심만", "결론", "통과했어?", "verdict"): do **not** read the whole report first. Read the `final-<task-type-segment>-<NNN>.status` sidecar under `runs/<task-type-segment>/status/` (stage-isolated: `runs/<task-type-segment>/stage-<N>/status/`) for the machine verdict, then read only the report's leading summary block (the first "종합 판정" / "Executive" / verdict heading and its body) to quote the gist. Offer to read the full report if the user wants detail.
317
- - **Full-read intent** ("전체", "다 읽어", "본문"): ingest the resolved report file.
326
+ - **Summary / verdict intent** ("summary", "just the key points", "conclusion", "did it pass?", "verdict"): do **not** read the whole report first. Read the `final-<task-type-segment>-<NNN>.status` sidecar under `runs/<task-type-segment>/status/` (stage-isolated: `runs/<task-type-segment>/stage-<N>/status/`) for the machine verdict, then read only the report's leading summary block (the first "Overall Verdict" / "Executive" / verdict heading and its body) to quote the gist. Offer to read the full report if the user wants detail.
327
+ - **Full-read intent** ("the whole thing", "read it all", "full body"): ingest the resolved report file.
318
328
 
319
329
  After reading, surface follow-up options:
320
330
 
321
- 1. **구현 진행:** based on the report's "권장 다음 단계" section.
322
- 2. **추가 검증:** to launch a new okstra run with the same task-key, assemble the command through the `history` sub-command — it offers the full option set (base-ref, workers, render-only) and renders a host-correct invocation.
323
- 3. **관련 task 확인:** if the report references related task-keys, fetch their reports too.
331
+ 1. **Proceed to implementation:** based on the report's "Recommended Next Steps" section.
332
+ 2. **Additional verification:** to launch a new okstra run with the same task-key, assemble the command through the `history` sub-command — it offers the full option set (base-ref, workers, render-only) and renders a host-correct invocation.
333
+ 3. **Check related tasks:** if the report references related task-keys, fetch their reports too.
324
334
 
325
335
  ### report — Output template
326
336
 
@@ -341,7 +351,7 @@ After reading, surface follow-up options:
341
351
 
342
352
  ## time
343
353
 
344
- Trigger phrases: "작업 시간", "소요 시간", "time summary", "duration", "elapsed", "얼마나 걸렸", "시간 분석".
354
+ Trigger phrases: "work time", "elapsed time", "time summary", "duration", "elapsed", "how long did it take", "time analysis".
345
355
 
346
356
  Aggregate elapsed work time for a task, grouped by **task type** and broken down by **worker** (lead + each worker). The `time-report` CLI reads both data sources (`history/timeline.json` runs + each run's `team-state-*.json` usage blocks) and does **all** aggregation — cross-run sums, CPU-sum vs wall-clock, timestamp parsing, unavailable detection. You only resolve the task-key, call it, and render. **Never recompute durations by hand.**
347
357
 
@@ -368,7 +378,7 @@ Convert every `*Ms` to `HH:MM:SS` (zero-pad; never show raw ms). Task types in `
368
378
 
369
379
  - **By task type** — `| Task type | Runs | CPU sum | Lead | Workers |` from `byTaskType`, plus a `grandTotal` row. `CPU sum` (= Lead + Workers) overlaps because workers run inside the lead's window — it is *not* wall-clock. Surface wall-clock only when the user explicitly asks, from `perRunWallClock`.
370
380
  - **Per worker** (per task type) — `| Worker | Runs | Total | Avg/run |` from `perWorker`. Render the worker as bare `workerId` when `agents` is empty, else `workerId (agent1, agent2)`.
371
- - **Phase breakdown** — "단계별"/"stage별"/"어느 단계가 오래" in okstra most often means the **lifecycle stage (task-type)** view, which the *By task type* table above already answers — lead with that table, do not treat the request as unanswerable. Render the intra-run phase timeline only when the user clearly means within-a-run phases ("어느 phase가", "Phase 1~7", "phase timeline"): one table per run from `phaseTimelines`: `| Phase | Start | Wall to next |` using `firstAt`/`wallMsToNext` (`null` → `--`). When `phaseTimelines` is empty, do **not** headline "측정 불가" — the By-task-type table is the stage answer; mention the missing intra-run markers only as a trailing footnote.
381
+ - **Phase breakdown** — "by stage"/"per stage"/"which stage took longest" in okstra most often means the **lifecycle stage (task-type)** view, which the *By task type* table above already answers — lead with that table, do not treat the request as unanswerable. Render the intra-run phase timeline only when the user clearly means within-a-run phases ("which phase", "Phase 1~7", "phase timeline"): one table per run from `phaseTimelines`: `| Phase | Start | Wall to next |` using `firstAt`/`wallMsToNext` (`null` → `--`). When `phaseTimelines` is empty, do **not** headline "not measurable" — the By-task-type table is the stage answer; mention the missing intra-run markers only as a trailing footnote.
372
382
  - If `unavailable[]` is non-empty, append a trailing note listing each run with its reason. Never fold them into totals.
373
383
  - Show the resolved `<task-key>` in the heading.
374
384
 
@@ -396,7 +406,7 @@ Convert every `*Ms` to `HH:MM:SS` (zero-pad; never show raw ms). Task types in `
396
406
 
397
407
  ## cost
398
408
 
399
- Trigger phrases: "okstra context-cost", "context cost", "context-cost", "컨텍스트 비용", "읽기 비용", "산출물 비용", "task bundle cost", "agent read cost".
409
+ Trigger phrases: "okstra context-cost", "context cost", "context-cost", "context cost (Korean)", "read cost", "artifact cost", "task bundle cost", "agent read cost".
400
410
 
401
411
  Read-only estimate of how much file/context surface a prepared task bundle asks the lead, analysis workers, and report-writer to absorb. This sub-command does **not** mutate task artifacts.
402
412
 
@@ -423,11 +433,11 @@ okstra resolve-task-key <token> --project-root <projectRoot> --json
423
433
  ```
424
434
 
425
435
  Branch on the stdout JSON `matches[]` — this **standard 0/1/N rule** is referenced by `errors`/`recap` below:
426
- - **0개** → report the task cannot be found. Do not guess.
427
- - **1개** → use that entry's `taskKey`.
428
- - **N개** → list the candidate `taskKey`s (with `updatedAt`, and `_matchedVia` so the user sees which came from a task-id vs a task-group) and ask via a 3-option picker (1~2 추천 + `직접 입력`), then use the chosen `taskKey`.
436
+ - **0** → report the task cannot be found. Do not guess.
437
+ - **1** → use that entry's `taskKey`.
438
+ - **N** → list the candidate `taskKey`s (with `updatedAt`, and `_matchedVia` so the user sees which came from a task-id vs a task-group) and ask via a 3-option picker (1–2 recommendations + `Enter directly`), then use the chosen `taskKey`.
429
439
 
430
- If the user asks generally ("컨텍스트 비용 보여줘") and does not name a task:
440
+ If the user asks generally ("show me the context cost") and does not name a task:
431
441
 
432
442
  1. Read `.okstra/discovery/task-catalog.json`.
433
443
  2. If exactly one task exists, use it.
@@ -492,7 +502,7 @@ Interpretation rules:
492
502
 
493
503
  ## logs
494
504
 
495
- Trigger phrases: "okstra logs", "로그 현황", "로그 파일", "log files", "log size", "log status", "로그 정리", "log cleanup".
505
+ Trigger phrases: "okstra logs", "log status", "log files", "log files", "log size", "log status", "log cleanup", "log cleanup".
496
506
 
497
507
  Read-only inventory of codex/antigravity wrapper log files written next to each prompt history file (`<prompt>.log`). Reports sizes, ages, totals, and suggests cleanup commands. **Does not delete** — the user runs whichever `find … -delete` line they like.
498
508
 
@@ -536,31 +546,31 @@ Emit a fenced bash block the user can copy-paste. Do NOT execute. Each block pai
536
546
  ```markdown
537
547
  ## Cleanup options (manual)
538
548
 
539
- # 7일 이상 된 로그만 삭제
549
+ # Delete only logs older than 7 days
540
550
  find <PROJECT_ROOT>/.okstra/tasks \
541
551
  -type f -path '*/runs/*/prompts/*.log' -mtime +7 -print # dry-run
542
552
  find <PROJECT_ROOT>/.okstra/tasks \
543
553
  -type f -path '*/runs/*/prompts/*.log' -mtime +7 -delete
544
554
 
545
- # 30일 이상 된 로그만 삭제
555
+ # Delete only logs older than 30 days
546
556
  find <PROJECT_ROOT>/.okstra/tasks \
547
557
  -type f -path '*/runs/*/prompts/*.log' -mtime +30 -print # dry-run
548
558
  find <PROJECT_ROOT>/.okstra/tasks \
549
559
  -type f -path '*/runs/*/prompts/*.log' -mtime +30 -delete
550
560
 
551
- # 특정 task-group 의 로그 일괄 삭제 (예: dev-9388)
561
+ # Delete all logs for a specific task-group (e.g. dev-9388)
552
562
  find <PROJECT_ROOT>/.okstra/tasks/dev-9388 \
553
563
  -type f -name '*.log' -print # dry-run
554
564
  find <PROJECT_ROOT>/.okstra/tasks/dev-9388 \
555
565
  -type f -name '*.log' -delete
556
566
 
557
- # 특정 task-id 의 로그 일괄 삭제 (예: dev-9428)
567
+ # Delete all logs for a specific task-id (e.g. dev-9428)
558
568
  find <PROJECT_ROOT>/.okstra/tasks/*/dev-9428 \
559
569
  -type f -name '*.log' -print # dry-run
560
570
  find <PROJECT_ROOT>/.okstra/tasks/*/dev-9428 \
561
571
  -type f -name '*.log' -delete
562
572
 
563
- # 전체 일괄 삭제 (주의)
573
+ # Delete everything (caution)
564
574
  find <PROJECT_ROOT>/.okstra/tasks \
565
575
  -type f -path '*/runs/*/prompts/*.log' -print # dry-run
566
576
  find <PROJECT_ROOT>/.okstra/tasks \
@@ -580,7 +590,7 @@ Substitute the literal `<PROJECT_ROOT>` with the resolved absolute path so the c
580
590
 
581
591
  ## errors
582
592
 
583
- Trigger phrases: "okstra errors", "error report", "에러 리포트", "에러 보고", "에러 모아줘", "실패 로그 정리".
593
+ Trigger phrases: "okstra errors", "error report", "error report (Korean)", "error summary", "gather the errors", "clean up failure logs".
584
594
 
585
595
  Aggregate a task's okstra-run error logs (`runs/*/logs/errors-*.jsonl`, lead-observed + worker-reported) into a timestamped markdown report and summarize it. This sub-command renders a **read-derived artifact** (a `.md` file) but never mutates task state (`task-manifest.json`, catalog, timeline).
586
596
 
@@ -592,7 +602,7 @@ Accepted target forms (same as `cost`):
592
602
  2. Bare token (task-id or task-group) — resolve via `okstra resolve-task-key <token> --project-root <projectRoot> --json` and branch on `matches[]` using the standard 0/1/N rule from `cost.1` (0 = not found, 1 = use, N = picker).
593
603
  3. Task root path.
594
604
 
595
- 사용자가 task 를 지정하지 않고 그냥 에러 리포트를 요청하면, `cost.1` 과 동일한 no-task fallback 을 적용한다 — 플레이스홀더 형식만 나열하고 되묻지 않는다: `.okstra/discovery/task-catalog.json` 을 읽어 task 가 1개면 그대로 사용하고, 여러 개면 `updatedAt` 최신 10개를 실제 task-key 로 나열해 물어본다(추측 금지).
605
+ If the user asks for an error report without naming a task, apply the same no-task fallback as `cost.1` — list only the placeholder forms and do not ask back: read `.okstra/discovery/task-catalog.json`, use the single task as-is if there is one, and if there are several, list the latest 10 by `updatedAt` as real task-keys and ask (no guessing).
596
606
 
597
607
  ### errors.2 — Run the renderer
598
608
 
@@ -619,7 +629,7 @@ Parse the stdout JSON and report:
619
629
  | By agent | `byAgent[]` |
620
630
  | Parse-skipped lines | `parseSkipped` |
621
631
 
622
- - If `reportPath` is empty AND `totals.errorCount == 0`: report `이 task 에는 기록된 에러 로그가 없습니다.` and do not claim a file was written.
632
+ - If `reportPath` is empty AND `totals.errorCount == 0`: report `This task has no recorded error logs.` and do not claim a file was written.
623
633
  - Otherwise show the `.md` path and offer to read it.
624
634
  - If `parseSkipped > 0`, surface it (do not silently hide malformed lines).
625
635
 
@@ -641,147 +651,143 @@ Parse the stdout JSON and report:
641
651
  |---|---:|
642
652
  | codex-worker | 2 |
643
653
 
644
- <If parseSkipped > 0: "⚠ 파싱 건너뛴 줄: <N>">
654
+ <If parseSkipped > 0: "⚠ Parse-skipped lines: <N>">
645
655
  ```
646
656
 
647
657
  ---
648
658
 
649
659
  ## error-zip
650
660
 
651
- Trigger phrases: "okstra error-zip", "에러 zip", "에러 환류", "에러 번들", "cross-project 에러".
661
+ Trigger phrases: "okstra error-zip", "error zip", "error feedback", "error bundle", "cross-project errors".
652
662
 
653
- 머신 내 모든 타겟 프로젝트의 okstra 실행 에러(`runs/*/logs/errors-*.jsonl`)를 글로벌 run-index 로 수집·익명화해 `.zip`(집계 리포트 + 익명화 JSONL)으로 묶는다. 모든 타겟의 `.okstra/` 에 대해 read-only.
663
+ Collect and anonymize the okstra run errors (`runs/*/logs/errors-*.jsonl`) of every target project on the machine into the global run-index, then bundle them as a `.zip` (aggregate report + anonymized JSONL). Read-only over every target's `.okstra/`.
654
664
 
655
- ### error-zip.1 — 출력 경로 결정 (picker)
665
+ ### error-zip.1 — Decide the output path (picker)
656
666
 
657
- 이전 출력 경로를 `~/.okstra/error-zip.json` 의 `lastOutputPath` 에서 읽는다. 그 값이 있으면 3-옵션 picker 로 제시:
667
+ Read the previous output path from `lastOutputPath` in `~/.okstra/error-zip.json`. If that value exists, present it in a 3-option picker:
658
668
 
659
- 1. (이전 경로 있음) `<lastOutputPath>` 재사용 — 추천, 첫 옵션.
660
- (이전 경로 없음) 기본 경로 `~/okstra-error-feedback-<YYYY-MM-DD>.zip` 제안 — 추천.
661
- 2. 직접 입력 (항상 마지막 옵션).
669
+ 1. (previous path exists) reuse `<lastOutputPath>` — recommended, first option.
670
+ (no previous path) propose the default path `~/okstra-error-feedback-<YYYY-MM-DD>.zip` — recommended.
671
+ 2. Enter directly (always the last option).
662
672
 
663
- `~/.okstra/error-zip.json` 읽기는 Read 로 직접 수행한다(없으면 이전 경로 없음으로 간주).
673
+ Read `~/.okstra/error-zip.json` directly with Read (if absent, treat it as no previous path).
664
674
 
665
- ### error-zip.2 — 렌더 실행
675
+ ### error-zip.2 — Run the renderer
666
676
 
667
677
  ```bash
668
- okstra error-zip --out <결정된 경로>
678
+ okstra error-zip --out <resolved-path>
669
679
  ```
670
680
 
671
- ### error-zip.3 — 요약 보고
681
+ ### error-zip.3 — Report the summary
672
682
 
673
- stdout JSON 을 파싱해 보고:
683
+ Parse the stdout JSON and report:
674
684
 
675
- | 필드 | 출처 |
685
+ | Field | Source |
676
686
  |---|---|
677
- | 출력 zip | `outPath` |
678
- | 총 에러 | `errorCount` |
679
- | 로그(run) | `runCount` |
680
- | 도달 불가 run | `unreachableRuns` |
681
- | 클러스터 수 | `clusterCount` |
682
- | 프로젝트 수 | `projectCount` |
687
+ | Output zip | `outPath` |
688
+ | Total errors | `errorCount` |
689
+ | Logs (runs) | `runCount` |
690
+ | Unreachable runs | `unreachableRuns` |
691
+ | Cluster count | `clusterCount` |
692
+ | Project count | `projectCount` |
683
693
 
684
- - `unreachableRuns > 0` 이면 표면화한다(침묵 누락 금지).
685
- - 끝에 다음 단계를 안내한다: "이 zip 으로 okstra 자신을 고치려면 `/okstra-brief-gen` 의 error-feedback variant 로 brief 를 만든 뒤 `okstra-run --task-type error-analysis` 를 okstra 레포에서 실행하세요."
694
+ - If `unreachableRuns > 0`, surface it (no silent omission).
695
+ - End with the next step: "To fix okstra itself with this zip, build a brief with the error-feedback variant of `/okstra-brief-gen`, then run `okstra-run --task-type error-analysis` in the okstra repo."
686
696
 
687
697
  ---
688
698
 
689
699
  ## recap
690
700
 
691
- Trigger phrases: "okstra recap", "recap", "작업 요약", "이 task 요약", "전후 요약", "이 작업 설명해줘", "task 질문".
701
+ Trigger phrases: "okstra recap", "recap", "work summary", "summarize this task", "before/after summary", "explain this work", "task question".
692
702
 
693
- task-id 하나에 쌓인 `.okstra` 산출물 위에서 (a) 처리 전/후 요약을 내고, (b) 그 작업에 대한 자유 질문에 답한다. 기본은 `.okstra/` 서브트리만 읽는다(artifact 모드). 사용자가 명시적으로 코드 변경까지 봐 달라고 요청할 때만 code 모드로 확장한다. 이 sub-command 는 `recap/recap-log.jsonl` append 와 `notes/` 노트 작성(recap.5)만 수행하고 `task-manifest.json` / catalog / timeline 은 절대 mutate 하지 않는다.
703
+ On top of the `.okstra` artifacts accumulated for a single task-id, (a) produce a before/after summary and (b) answer free-form questions about that work. By default it reads only the `.okstra/` subtree (artifact mode). It expands to code mode only when the user explicitly asks to look at the code changes too. This sub-command performs only the `recap/recap-log.jsonl` append and the `notes/` note authoring (recap.5); it never mutates `task-manifest.json` / catalog / timeline.
694
704
 
695
705
  ### recap.1 — Resolve target
696
706
 
697
- `cost` / `errors` 와 동일한 3형식: ① full task-key, ② bare token(task-id 또는 task-group → `okstra resolve-task-key <token> --project-root <projectRoot> --json`; `cost.1` 의 표준 0/1/N 분기), ③ task-root path.
698
-
699
- 사용자가 task 를 지정하지 않고 그냥 recap 을 요청하면(예: "이 작업 요약해줘"), `cost.1` 과 동일한 no-task fallback 을 적용한다 — 절대 `<task-group>` 같은 플레이스홀더 형식만 나열하고 되묻지 않는다:
707
+ The same three forms as `cost` / `errors`: ① full task-key, ② bare token (task-id or task-group → `okstra resolve-task-key <token> --project-root <projectRoot> --json`; the standard 0/1/N branch from `cost.1`), ③ task-root path.
700
708
 
701
- 1. `.okstra/discovery/task-catalog.json` 을 읽는다.
702
- 2. task 가 정확히 1개면 그 task 를 그대로 사용한다.
703
- 3. 여러 개면 `updatedAt` 최신 10개를 실제 task-key 로 나열하고 어느 task 인지 물어본다(추측 금지).
709
+ If the user asks for a recap without naming a task (e.g. "summarize this work"), apply the `cost.1` no-task fallback as-is — do not list only a placeholder form like `<task-group>` and ask back; read `.okstra/discovery/task-catalog.json`, use the single task as-is if there is one, and if there are several, list the latest 10 by `updatedAt` as real task-keys and ask (no guessing).
704
710
 
705
711
  ### recap.2 — Assemble the before/after summary
706
712
 
707
- CLI 출력을 source of truth 로 쓴다:
713
+ Use the CLI output as the source of truth:
708
714
 
709
715
  ```bash
710
716
  okstra recap assemble <resolved-target> --project-root <projectRoot>
711
717
  ```
712
718
 
713
- stdout JSON(`{taskKey, runCount, transitions[], latestPhaseStates}`)을 파싱해 run 단위 전/후 전이를 서술한다. 각 `transitions[]` 항목의 `fromPhase → toPhase`(직전 run currentPhase → 이번 run currentPhase), `status`, `lastCompletedPhase`, `nextRecommendedPhase`, `reportPath` 를 시간순으로 보여준다. `runCount == 0` 이면 "이 task 에는 기록된 run 이 없습니다." 라고만 답하고 파일을 읽었다고 주장하지 않는다.
719
+ Parse the stdout JSON (`{taskKey, runCount, transitions[], latestPhaseStates}`) and narrate the per-run before/after transitions. For each `transitions[]` entry, show `fromPhase → toPhase` (previous run currentPhase → this run currentPhase), `status`, `lastCompletedPhase`, `nextRecommendedPhase`, and `reportPath` in chronological order. If `runCount == 0`, answer only "This task has no recorded runs." and do not claim to have read any file.
714
720
 
715
- `reportPath` 가 있는 run 은 사용자가 더 깊은 요약을 원할 때만 해당 final-report 를 읽어 보강한다(자동으로 모두 읽지 않는다).
721
+ For a run that has a `reportPath`, read that final-report to enrich the summary only when the user wants a deeper one (do not read them all automatically).
716
722
 
717
723
  ### recap.3 — Free-form Q&A loop
718
724
 
719
- 요약 출력 뒤 사용자의 임의 질문을 받는다.
725
+ After the summary output, take the user's free-form questions.
720
726
 
721
- - **artifact 모드(기본)**: `.okstra/` 산출물(timeline, task-manifest, 해당 run 의 final-report)만 근거로 답한다. 모든 사실 주장은 `.okstra` 파일 `path:line` 인용을 동반한다.
722
- - **code 모드(opt-in)**: 사용자가 "코드 변경까지 / diff 까지 봐줘" 류로 **명시적으로 요청**할 때만, 해당 task 의 worktree/브랜치에서 `git diff` · `git log` 를 추가로 읽어 코드 레벨로 답한다. recap 진입만으로는 절대 code 모드로 넘어가지 않는다.
727
+ - **artifact mode (default)**: answer only from `.okstra/` artifacts (timeline, task-manifest, that run's final-report). Every factual claim is accompanied by a `path:line` citation to the `.okstra` file.
728
+ - **code mode (opt-in)**: only when the user **explicitly asks** — "look at the code changes / the diff too" — additionally read `git diff` · `git log` from that task's worktree/branch and answer at the code level. Entering recap never by itself switches to code mode.
723
729
 
724
730
  ### recap.4 — Persist each turn
725
731
 
726
- 요약 1건과 각 Q&A 답변을 로그에 남긴다(append-only):
732
+ Log one summary and each Q&A answer (append-only):
727
733
 
728
734
  ```bash
729
735
  okstra recap record <resolved-target> --project-root <projectRoot> \
730
736
  --kind <summary|qa> --mode <artifact|code> \
731
- --question "<질문 또는 생략>" --answer "<한두 줄 요약>" \
737
+ --question "<question or omit>" --answer "<one or two line summary>" \
732
738
  --citation "<path:line>" --citation "<path:line>"
733
739
  ```
734
740
 
735
- `--answer` 에는 전체 답변 전사가 아니라 한두 줄 요약을 넣는다. 인용이 여러 개면 `--citation` 을 반복한다. 기록 실패(비정상 종료)는 조용히 넘기지 말고 사용자에게 알린다.
741
+ Put a one-or-two-line summary in `--answer`, not the full answer transcript. If there are multiple citations, repeat `--citation`. Do not silently swallow a recording failure (abnormal exit) — tell the user.
736
742
 
737
743
  ### recap — Output template
738
744
 
739
745
  ```markdown
740
746
  ## okstra Recap — <task-key>
741
747
 
742
- 전/후 요약 (runs: <N>):
748
+ Before/after summary (runs: <N>):
743
749
 
744
750
  | # | when | task-type | from → to | status | next |
745
751
  |---|---|---|---|---|---|
746
- | 1 | <ts> | requirements-discovery | (시작) → requirements-discovery | done | error-analysis |
752
+ | 1 | <ts> | requirements-discovery | (start) → requirements-discovery | done | error-analysis |
747
753
 
748
- <이후 자유 질문을 받습니다. 코드 변경까지 보려면 "diff 까지 봐줘" 라고 요청하세요.>
754
+ <Free-form questions follow. To include code changes, ask "also show me the diff".>
749
755
  ```
750
756
 
751
- ### recap.5 — Agent 저작 노트 (`notes/`)
757
+ ### recap.5 — Agent-authored notes (`notes/`)
752
758
 
753
- recap 중에 네가 **okstra task 를 위해** 만든 산출물 — 검증 증거, 설계·decision 초안, 분석 노트 — 이 앞으로의 run 에 근거로 쓰일 수 있고, 그 내용이 **렌더된 report 도 아니고 사용자 결정도 아닐 때**만 `notes/` 에 남긴다.
759
+ Leave something in `notes/` only when, during recap, you produced an artifact **for the okstra task** — verification evidence, a design/decision draft, an analysis note — that may serve as grounding for future runs, and whose content is **neither a rendered report nor a user decision**.
754
760
 
755
- **소유권으로 라우팅한다.** 지금 쓰려는 것이 아래 어디에 해당하는지 먼저 판별한다:
761
+ **Route by ownership.** First determine which of the following the thing you are about to write belongs to:
756
762
 
757
- | 내용 | 레인(경로) | 저작 주체 |
763
+ | Content | Lane (path) | Author |
758
764
  |---|---|---|
759
- | final report 본문 | `runs/<type>/reports/*.md` (`*.data.json` 에서 렌더) | okstra 렌더러 — 절대 수기 편집 금지 |
760
- | clarification 에 대한 사용자 답변 | `runs/<type>/user-responses/*.md` (`created-by: user`) | 사용자만 |
761
- | 확정된 ADR | `.okstra/decisions/NNNN-*.md` | 승격·관리됨 |
762
- | **Agent 증거 / 설계 초안 / 분석** | **`.okstra/tasks/<group>/<id>/notes/`** | 너(AI) |
765
+ | final report body | `runs/<type>/reports/*.md` (rendered from `*.data.json`) | okstra renderer — never hand-edit |
766
+ | user's answer to a clarification | `runs/<type>/user-responses/*.md` (`created-by: user`) | user only |
767
+ | finalized ADR | `.okstra/decisions/NNNN-*.md` | promoted / managed |
768
+ | **Agent evidence / design draft / analysis** | **`.okstra/tasks/<group>/<id>/notes/`** | you (the AI) |
763
769
 
764
- 렌더 산출물도, 사용자 결정도 아닌 **너 자신의 근거·초안**이면 `notes/` 로 간다. 노트는 손으로 찍지 말고 CLI 로 쓴다 — 경로·frontmatter·날짜를 코드가 보장하고, 다음 run 에 넘길 인자를 출력해 준다:
770
+ If it is **your own grounding/draft** — not a rendered artifact, not a user decision — it goes to `notes/`. Do not hand-stamp the note; write it via the CLI — code guarantees the path/frontmatter/date and prints the argument to pass into the next run:
765
771
 
766
772
  ```bash
767
773
  okstra recap note <resolved-target> --project-root <projectRoot> \
768
774
  --kind <verification-evidence|decision-draft|analysis-note> \
769
775
  --slug <short-topic-slug> \
770
- --purpose "<한 줄 — 무엇이며 어느 run/decision 에 투입되는지>" \
771
- --scope-note "<한 줄 — 무엇이 아닌지, 예: C-00x 에 대한 사용자 결정이 아님>" \
772
- --body-file <노트 본문 마크다운 경로>
776
+ --purpose "<one line — what it is and which run/decision it feeds>" \
777
+ --scope-note "<one line — what it is NOT, e.g. not a user decision on C-00x>" \
778
+ --body-file <note-body markdown path>
773
779
  ```
774
780
 
775
- 본문은 먼저 scratchpad 에 마크다운으로 쓴 뒤 `--body-file` 로 넘긴다(짧으면 `--body "<md>"` 인라인도 가능). CLI 는 `.okstra/tasks/<group>/<id>/notes/<slug>-<YYYY-MM-DD>.md` 를 생성하고 stdout JSON 으로 `notePath` 와 `clarificationResponseArg` 를 돌려준다.
781
+ Write the body to the scratchpad as markdown first, then pass it with `--body-file` (if short, an inline `--body "<md>"` also works). The CLI creates `.okstra/tasks/<group>/<id>/notes/<slug>-<YYYY-MM-DD>.md` and returns `notePath` and `clarificationResponseArg` as stdout JSON.
776
782
 
777
- **self-check 규칙 (validator 가 없으니 스스로 지킨다):**
783
+ **self-check rules (there is no validator, so you keep them yourself):**
778
784
 
779
- 1. **렌더된 report 를 수기 편집하지 않는다** (`runs/*/reports/` 아래 `*.md` / `*.data.json` / `*.html`). `data.json` 에서 재생성되므로 편집은 덮어써지고 SSOT 와 어긋난다. 발견 내용은 `notes/` 에 쓴다.
780
- 2. **`user-responses/` 파일을 작성하거나 `created-by: user` 를 달지 않는다.** 그건 사용자의 결정이며, 대신 쓰면 사용자가 내리지 않은 결정을 위조하는 것이다. 네 증거가 특정 답을 뒷받침하면 `notes/` 에 그렇게 적고 결정은 사용자에게 맡긴다. 단, `okstra-user-response` 스킬의 에코백 확인 흐름은 예외다 — 그 흐름에서는 사용자가 세션에서 직접 결정을 내리고 CLI 는 전사 채널일 뿐이므로, `write` 로 `created-by: user` sidecar 를 기록하는 것이 정당하다. 이 예외는 사용자가 명시적으로 "맞음" 을 확인한 뒤에만, verbatim 입력에 대해서만 성립한다.
781
- 3. **okstra 관리 디렉토리에 쓰지 않는다** (`runs/`, `instruction-set/`, `history/`, `recap/`, `.okstra/decisions/`). `notes/` 만이 agent 소유 레인이다. `recap/recap-log.jsonl` 은 예외적으로 쓰되 손으로 편집하지 말고 `okstra recap record` CLI 로만 남긴다.
782
- 4. **`notes/` 는 okstra 에 inert 하다** — 어떤 run 도 자동으로 읽지 않는다. 작성 후 CLI 가 출력한 `clarificationResponseArg`(예: `--clarification-response <notePath>`)를 사용자에게 그대로 알려, 다음 run 을 그 인자와 함께 실행해야만 반영된다는 것을 전한다.
785
+ 1. **Do not hand-edit a rendered report** (`*.md` / `*.data.json` / `*.html` under `runs/*/reports/`). Because it is regenerated from `data.json`, an edit is overwritten and diverges from the SSOT. Write findings to `notes/` instead.
786
+ 2. **Do not author a `user-responses/` file or apply `created-by: user`.** That is the user's decision, and writing it for them forges a decision the user never made. If your evidence supports a particular answer, write that in `notes/` and leave the decision to the user. The one exception is the echo-back confirmation flow of the `okstra-user-response` skill — there the user makes the decision in-session and the CLI is merely a transcription channel, so recording a `created-by: user` sidecar with `write` is legitimate. This exception holds only after the user has explicitly confirmed "correct", and only for verbatim input.
787
+ 3. **Do not write to okstra-managed directories** (`runs/`, `instruction-set/`, `history/`, `recap/`, `.okstra/decisions/`). `notes/` is the only agent-owned lane. `recap/recap-log.jsonl` is the exception — write it, but not by hand; only via the `okstra recap record` CLI.
788
+ 4. **`notes/` is inert to okstra** — no run reads it automatically. After writing, relay the `clarificationResponseArg` the CLI printed (e.g. `--clarification-response <notePath>`) to the user verbatim, telling them it only takes effect when the next run is executed with that argument.
783
789
 
784
- **Guardrail:** `.okstra/` 는 gitignored 다 — `notes/` 는 로컬 scratch 로 취급하고 절대 `git add` 하지 않는다. 새 노트 생성은 되돌리기 쉬우니(파일 삭제), 생성물이나 사용자 소유 파일을 편집하는 것보다 항상 이쪽을 택한다.
790
+ **Guardrail:** `.okstra/` is gitignored — treat `notes/` as local scratch and never `git add` it. Creating a new note is easy to undo (delete the file), so always prefer it over editing a generated or user-owned file.
785
791
 
786
792
  ---
787
793
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: okstra-manager
3
- description: Use when the user wants to manage okstra work across multiple project roots, register or discover projects under a manager, create or update a shared manager task, sync project child-task status into manager state, or launch a child task from manager context. Trigger words include "okstra manager", "okstra-manager", "여러 프로젝트", "cross-project", "프로젝트 묶어서", "manager task".
3
+ description: Use when the user wants to manage okstra work across multiple project roots, register or discover projects under a manager, create or update a shared manager task, sync project child-task status into manager state, or launch a child task from manager context. Trigger words include "okstra manager", "okstra-manager", "multiple projects", "cross-project", "group projects together", "manager task".
4
4
  ---
5
5
 
6
6
  # OKSTRA Manager
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: okstra-memory
3
- description: Use when the user wants to preserve, remember, store, recall, search, or archive AI/human conversation notes in okstra's global Memory Book. Trigger words include "okstra 에 정리해서 보관해", "memory-book", "기억해둬", "대화 저장", "정리해서 저장", "remember this", "store this conversation", "save this decision", "memory-book 검색", "저장한 메모 찾아줘", "recall a saved decision".
3
+ description: Use when the user wants to preserve, remember, store, recall, search, or archive AI/human conversation notes in okstra's global Memory Book. Trigger words include "organize and store this in okstra", "memory-book", "remember this for me", "save the conversation", "summarize and save", "remember this", "store this conversation", "save this decision", "search the memory-book", "find the note I saved", "recall a saved decision".
4
4
  ---
5
5
 
6
6
  # okstra-memory
@@ -14,7 +14,7 @@ explicitly cites a memory entry later.
14
14
 
15
15
  ## When to use
16
16
 
17
- - The user says "okstra 에 정리해서 보관해", "기억해둬", "대화 저장",
17
+ - The user says "organize and store this in okstra", "remember this for me", "save the conversation",
18
18
  "remember this", or similar.
19
19
  - The user asks to search, list, show, or archive stored conversation memory.
20
20
  - The user wants decisions, preferences, requirements, people/context notes,
@@ -58,7 +58,7 @@ searching so the rest of the skill can scope to it.
58
58
  ```
59
59
 
60
60
  2. Present a 3-option picker (most-used existing group, next existing group,
61
- then always `직접 입력`). For a personal note, recommend `private` as the
61
+ then always `Enter directly`). For a personal note, recommend `private` as the
62
62
  first option. If `groups` is empty or the user makes no selection, the
63
63
  default group is `global` (the CLI default in `memory.mjs`).
64
64
  3. Carry the chosen group name into every `add` (`--project-group <name>`) and
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: okstra-rollup
3
3
  description: |
4
- Use when the user wants run results from MULTIPLE okstra tasks collected and summarized at once — a task-group digest or a whole-project roll-up, not a single task. Aggregates per-task run count, elapsed time, error count, and latest report path, plus group-level totals and status/category/phase tallies, then synthesizes a cross-task prose summary from the report files. Make sure to use this skill whenever the user mentions "okstra rollup", "롤업", "task-group 요약", "그룹 단위 리포트", "여러 task 결과 모아", "전체 task 현황 요약", "cross-task summary", "그룹 종합 리포트", "모든 task 정리", "run 결과 한꺼번에", even if they don't say "rollup". For a SINGLE task's report/time/errors/recap use okstra-inspect instead; for a forward-looking work plan over non-done tasks use okstra-schedule-gen.
4
+ Use when the user wants run results from MULTIPLE okstra tasks collected and summarized at once — a task-group digest or a whole-project roll-up, not a single task. Aggregates per-task run count, elapsed time, error count, and latest report path, plus group-level totals and status/category/phase tallies, then synthesizes a cross-task prose summary from the report files. Make sure to use this skill whenever the user mentions "okstra rollup", "rollup", "task-group summary", "group-level report", "collect multiple task results", "whole-project task status summary", "cross-task summary", "consolidated group report", "organize all tasks", "run results all at once", even if they don't say "rollup". For a SINGLE task's report/time/errors/recap use okstra-inspect instead; for a forward-looking work plan over non-done tasks use okstra-schedule-gen.
5
5
  ---
6
6
 
7
7
  # OKSTRA Rollup
@@ -12,18 +12,24 @@ This skill is read-only. It never mutates task artifacts.
12
12
 
13
13
  ## Step 0: Preflight
14
14
 
15
- Run one Bash tool call, starting with the literal token `okstra` (never wrapped in `if`/`eval`/`$(...)`/`VAR=...`/`||`/`&&`/`npx` — a non-literal leading token defeats the `Bash(okstra:*)` permission match):
15
+ <!-- BEGIN FRAGMENT: bash-invocation-rule -->
16
+ Run one Bash tool call, starting with the literal token `okstra` (never wrapped in `if`/`eval`/`export`/`$(...)`/`VAR=...`/`||`/`&&`/`npx` — a non-literal leading token defeats the `Bash(okstra:*)` permission match):
17
+ <!-- END FRAGMENT: bash-invocation-rule -->
16
18
 
17
19
  ```bash
18
20
  okstra preflight --runtime claude-code --json
19
21
  ```
20
22
 
21
- Parse the stdout JSON. `ok: true` → carry `projectRoot` as a literal string. `ok: false` → tell the user to run `/okstra-setup` first, then stop. If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
23
+ Parse the stdout JSON. `ok: true` → carry `projectRoot` as a literal string. `ok: false` → tell the user to run `/okstra-setup` first, then stop.
24
+
25
+ <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
26
+ If the call fails with `unknown command: preflight`, the `okstra` binary on PATH predates this skill — tell the user to update it (`npm i -g okstra@latest`), then stop (`/okstra-setup` does not update the binary).
27
+ <!-- END FRAGMENT: preflight-outdated-cli -->
22
28
 
23
29
  ## Step 1: Resolve scope
24
30
 
25
- - User named a task-group (e.g. "alpha 그룹 요약") → use it as `--task-group <group>`.
26
- - User asked for the whole project ("전체 task", "프로젝트 전체") or named no scope → omit `--task-group` (whole catalog).
31
+ - User named a task-group (e.g. "summarize the alpha group") → use it as `--task-group <group>`.
32
+ - User asked for the whole project ("all tasks", "the whole project") or named no scope → omit `--task-group` (whole catalog).
27
33
  - If genuinely ambiguous, ask once: one task-group, or the whole project? Do not silently guess a specific group.
28
34
 
29
35
  ## Step 2: Fetch the roll-up
@@ -62,7 +68,7 @@ Render `Report` as `✓` when `reportPath` is non-empty, else `—`. Build the s
62
68
 
63
69
  ## Step 4: Synthesize the digest (the summary)
64
70
 
65
- This is the skill's value-add over a bare table. When the user asked to "요약"/"summarize"/"digest"/"정리" (the common case), produce a short cross-task narrative:
71
+ This is the skill's value-add over a bare table. When the user asked to "summarize"/"digest"/"organize" (the common case), produce a short cross-task narrative:
66
72
 
67
73
  1. For each task with a non-empty `reportPath` whose file exists under `<projectRoot>/<reportPath>`, read it and write a 1–2 line summary of what it accomplished and its recommended next step.
68
74
  2. Above the per-task lines, write a 2–4 sentence group-level synthesis: what was delivered across the group, where the open work sits (use `byWorkStatus`/`byCurrentPhase`), and any error hot-spots (tasks with high `errorCount`).