okstra 0.123.0 → 0.125.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 (98) hide show
  1. package/README.md +1 -0
  2. package/docs/architecture/storage-model.md +3 -1
  3. package/docs/architecture.md +16 -2
  4. package/docs/cli.md +3 -1
  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 +87 -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 +6 -6
  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/bin/lib/okstra/usage.sh +1 -1
  36. package/runtime/prompts/coding-preflight/frameworks/node-server.md +1 -1
  37. package/runtime/prompts/launch.template.md +1 -1
  38. package/runtime/prompts/lead/convergence.md +10 -20
  39. package/runtime/prompts/lead/okstra-lead-contract.md +15 -17
  40. package/runtime/prompts/lead/plan-body-verification.md +18 -18
  41. package/runtime/prompts/lead/report-writer.md +46 -44
  42. package/runtime/prompts/lead/team-contract.md +11 -122
  43. package/runtime/prompts/profiles/_common-contract.md +15 -22
  44. package/runtime/prompts/profiles/_implementation-deliverable.md +1 -1
  45. package/runtime/prompts/profiles/_implementation-executor.md +1 -1
  46. package/runtime/prompts/profiles/_implementation-verifier.md +28 -2
  47. package/runtime/prompts/profiles/error-analysis.md +2 -2
  48. package/runtime/prompts/profiles/final-verification.md +1 -1
  49. package/runtime/prompts/profiles/implementation-planning.md +13 -13
  50. package/runtime/prompts/profiles/implementation.md +2 -1
  51. package/runtime/prompts/profiles/improvement-discovery.md +1 -1
  52. package/runtime/prompts/profiles/release-handoff.md +3 -3
  53. package/runtime/prompts/profiles/requirements-discovery.md +17 -18
  54. package/runtime/python/okstra_ctl/models.py +4 -2
  55. package/runtime/python/okstra_ctl/run.py +8 -2
  56. package/runtime/python/okstra_ctl/stage_fix_carry.py +112 -0
  57. package/runtime/schemas/final-report-v1.0.schema.json +6 -6
  58. package/runtime/skills/_fragments/bash-invocation-rule.md +1 -0
  59. package/runtime/skills/_fragments/preflight-outdated-cli.md +1 -0
  60. package/runtime/skills/_fragments/python-bootstrap-note.md +1 -0
  61. package/runtime/skills/okstra-brief-gen/SKILL.md +117 -122
  62. package/runtime/skills/okstra-container-build/SKILL.md +24 -14
  63. package/runtime/skills/okstra-graphify/SKILL.md +12 -4
  64. package/runtime/skills/okstra-inspect/SKILL.md +39 -747
  65. package/runtime/skills/okstra-inspect/facets/cost.md +84 -0
  66. package/runtime/skills/okstra-inspect/facets/error-zip.md +41 -0
  67. package/runtime/skills/okstra-inspect/facets/errors.md +69 -0
  68. package/runtime/skills/okstra-inspect/facets/history.md +90 -0
  69. package/runtime/skills/okstra-inspect/facets/logs.md +89 -0
  70. package/runtime/skills/okstra-inspect/facets/recap.md +96 -0
  71. package/runtime/skills/okstra-inspect/facets/report.md +61 -0
  72. package/runtime/skills/okstra-inspect/facets/status.md +145 -0
  73. package/runtime/skills/okstra-inspect/facets/time.md +56 -0
  74. package/runtime/skills/okstra-manager/SKILL.md +1 -1
  75. package/runtime/skills/okstra-memory/SKILL.md +3 -3
  76. package/runtime/skills/okstra-pr-gen/SKILL.md +3 -3
  77. package/runtime/skills/okstra-rollup/SKILL.md +12 -6
  78. package/runtime/skills/okstra-run/SKILL.md +49 -88
  79. package/runtime/skills/okstra-schedule-gen/SKILL.md +36 -30
  80. package/runtime/skills/okstra-setup/SKILL.md +1 -1
  81. package/runtime/skills/okstra-setup/references/project-config.md +17 -16
  82. package/runtime/skills/okstra-usage/SKILL.md +5 -2
  83. package/runtime/skills/okstra-user-response/SKILL.md +15 -3
  84. package/runtime/templates/prd/brief.template.md +92 -92
  85. package/runtime/templates/project-docs/task-index.template.md +1 -1
  86. package/runtime/templates/reports/error-analysis-input.template.md +1 -1
  87. package/runtime/templates/reports/fan-out-unit.template.md +6 -6
  88. package/runtime/templates/reports/final-verification-input.template.md +6 -6
  89. package/runtime/templates/reports/implementation-input.template.md +1 -1
  90. package/runtime/templates/reports/implementation-planning-input.template.md +1 -1
  91. package/runtime/templates/reports/improvement-discovery-input.template.md +1 -1
  92. package/runtime/templates/reports/quick-input.template.md +1 -1
  93. package/runtime/templates/reports/release-handoff-input.template.md +1 -1
  94. package/runtime/templates/reports/schedule.template.md +22 -22
  95. package/runtime/templates/reports/task-brief.template.md +3 -3
  96. package/runtime/templates/reports/user-response.template.md +20 -20
  97. package/runtime/templates/worker-prompt-preamble.md +111 -13
  98. package/runtime/validators/validate-schedule.py +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: okstra-schedule-gen
3
- description: Use when the user asks for a task-group work schedule, a consolidated implementation plan across multiple tasks in a task-group, or wants to generate a "schedule" / "일정" / "작업 계획표" for non-done tasks. Trigger words include "okstra schedule", "<task-group> 일정 만들어", "<task-group> schedule 생성", "task-group 작업 계획".
3
+ description: Use when the user asks for a task-group work schedule, a consolidated implementation plan across multiple tasks in a task-group, or wants to generate a "schedule" / "work plan" for non-done tasks. Trigger words include "okstra schedule", "make a schedule for <task-group>", "generate a <task-group> schedule", "task-group work plan".
4
4
  model: opus
5
5
  ---
6
6
 
@@ -10,7 +10,7 @@ Generate a consolidated work schedule for the selected `implementation-planning`
10
10
 
11
11
  ## When to Use
12
12
 
13
- - User asks to generate a work schedule / plan / "일정" for an entire `task-group`
13
+ - User asks to generate a work schedule / plan / "schedule" for an entire `task-group`
14
14
  - User wants a single document that summarizes all non-done tasks with effort, risk, and dependencies
15
15
 
16
16
  **Do NOT use** for single-task analysis (use `okstra-inspect status`) or to execute one task (use `okstra-run`).
@@ -19,37 +19,43 @@ Explicit command form: `okstra schedule <task-group> [--title "<custom title>"]
19
19
 
20
20
  ## Step 0: Preflight
21
21
 
22
+ <!-- BEGIN FRAGMENT: bash-invocation-rule -->
22
23
  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):
24
+ <!-- END FRAGMENT: bash-invocation-rule -->
23
25
 
24
26
  ```bash
25
27
  okstra preflight --runtime claude-code --json
26
28
  ```
27
29
 
28
- Parse the stdout JSON. `ok: true` → carry `projectRoot` as a literal string and use it to locate `.okstra/discovery/task-catalog.json` and the task-group directory. `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).
30
+ Parse the stdout JSON. `ok: true` → carry `projectRoot` as a literal string and use it to locate `.okstra/discovery/task-catalog.json` and the task-group directory. `ok: false` → tell the user to run `/okstra-setup` first, then stop.
31
+
32
+ <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
33
+ 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).
34
+ <!-- END FRAGMENT: preflight-outdated-cli -->
29
35
 
30
36
  ## Audience & authority (READ FIRST — drives everything below)
31
37
 
32
- **The schedule is a client-facing work plan.** It assumes the team has all permissions and can proceed without further approval. Even when the underlying per-task reports flag blocking items, missing approvals, or "사용자 확인 필요 항목", **the schedule MUST NOT surface them** — those belong in the internal report. Never emit a decision checklist, a `#### 사용자 확인 필요 항목` sub-section, `Done`/`Ready?`/`Blocking Decisions` columns, or checkbox lists; "Status" reflects work phase only.
38
+ **The schedule is a client-facing work plan.** It assumes the team has all permissions and can proceed without further approval. Even when the underlying per-task reports flag blocking items, missing approvals, or "items requiring user confirmation", **the schedule MUST NOT surface them** — those belong in the internal report. Never emit a decision checklist, a `#### Items requiring user confirmation` sub-section, `Done`/`Ready?`/`Blocking Decisions` columns, or checkbox lists; "Status" reflects work phase only.
33
39
 
34
40
  **Assume the user and their team hold full authority and every permission required.** External approvals, access grants, sign-off, and vendor coordination are treated as already satisfied unless a report names a concrete external dependency outside the user's control. Concretely:
35
41
 
36
42
  - **Effort sizing & day totals** count engineering work only — strip approval-waiting / coordination buffers from source sizings (note the adjustment in `## Executive Summary` if material).
37
43
  - **Gantt bars** represent engineering duration only; no dead-time gaps for approval cycles. `(after <TASK-ID>)` marks genuine engineering dependencies only.
38
44
  - **Risk Mitigation Strategy** lists real engineering risks (data loss, regression surface, rollback path) — permission/coordination items are dropped.
39
- - **Recommended Immediate Actions / Next Action** are concrete engineering steps; "권한 확인", "승인 요청", "이해관계자 정렬" 류는 출력 금지.
45
+ - **Recommended Immediate Actions / Next Action** are concrete engineering steps; items like "permission check", "approval request", "stakeholder alignment" MUST NOT be emitted.
40
46
  - **Cross-Task Dependencies** covers engineering coupling only (shared modules, release order, package versions).
41
47
 
42
- **The schedule must be self-contained.** Opaque codes pulled from internal reports (`FC-5`, `UC-12`, `M1`, decision-item letters, …) must not appear unresolved. Choose one per identifier: **Form A** (≤3 codes) — replace the code inline with a 5–20 one-line description of the item; **Form B** (≥4 recurring codes) — keep the codes and emit a `## Glossary` table as the last section resolving every one. Decision-item letters (`A1`, `B2`, …) are approval items and may not appear at all. TASK-IDs listed in `## At a Glance` need neither.
48
+ **The schedule must be self-contained.** Opaque codes pulled from internal reports (`FC-5`, `UC-12`, `M1`, decision-item letters, …) must not appear unresolved. Choose one per identifier: **Form A** (≤3 codes) — replace the code inline with a 5–20 character one-line description of the item; **Form B** (≥4 recurring codes) — keep the codes and emit a `## Glossary` table as the last section resolving every one. Decision-item letters (`A1`, `B2`, …) are approval items and may not appear at all. TASK-IDs listed in `## At a Glance` need neither.
43
49
 
44
50
  ## Contract SSOT — template + validator
45
51
 
46
- The installed template `~/.okstra/templates/reports/schedule.template.md` is the **byte-for-byte SSOT** for the output shape: frontmatter, top header block, the mandatory `##` heading list and order, per-task `Item / Detail` field labels and sub-section order, table column shapes, the ASCII Gantt format (relative day axis, plain fence, `█`/`░`/`! crit`/`est` legend), the dependency-graph shapes, and the optional `## Glossary` gate. **Read the template before writing the schedule and follow it exactly** — do not re-derive section shapes from memory. Headings and field labels stay English literals regardless of the source-report language; body prose is Korean. When a section has no data, render its heading with `_없음_` — never delete or reorder headings. Never emit mermaid or any graph DSL.
52
+ The installed template `~/.okstra/templates/reports/schedule.template.md` is the **byte-for-byte SSOT** for the output shape: frontmatter, top header block, the mandatory `##` heading list and order, per-task `Item / Detail` field labels and sub-section order, table column shapes, the ASCII Gantt format (relative day axis, plain fence, `█`/`░`/`! crit`/`est` legend), the dependency-graph shapes, and the optional `## Glossary` gate. **Read the template before writing the schedule and follow it exactly** — do not re-derive section shapes from memory. Headings and field labels stay English literals regardless of the source-report language; body prose is Korean. When a section has no data, render its heading with `_none_` — never delete or reorder headings. Never emit mermaid or any graph DSL.
47
53
 
48
54
  `~/.okstra/lib/validators/validate-schedule.py` is the enforcement for all of the above (heading order, field labels, controlled vocabulary — e.g. `Med-High` is the canonical risk form — forbidden translations, checkbox bans, Gantt fence rules, unresolved-code detection). The Step 4 ambiguous-classification rationale line is the one rule the validator does not yet enforce — emit it yourself.
49
55
 
50
56
  One computation rule the template scaffold cannot carry inline:
51
57
 
52
- - **Effort-to-Day mapping**: day ranges per size are defined once in the template's `### Effort Sizing 기준` table. For the At a Glance totals line, sum that table's lower bounds across in-scope tasks for the lower total and upper bounds for the upper total.
58
+ - **Effort-to-Day mapping**: day ranges per size are defined once in the template's `### Effort Sizing Criteria` table. For the At a Glance totals line, sum that table's lower bounds across in-scope tasks for the lower total and upper bounds for the upper total.
53
59
 
54
60
  ## Procedure
55
61
 
@@ -58,10 +64,10 @@ One computation rule the template scaffold cannot carry inline:
58
64
  1. Read `.okstra/discovery/task-catalog.json`.
59
65
  2. **Resolve which task-group to schedule — never silently guess.**
60
66
  - The user **explicitly named a task-group** (as the `okstra schedule <task-group>` argument or unambiguously in the request) → use that token; skip the picker and go to sub-step 3.
61
- - The user **named no task-group, or the named token matches 0 or ≥2 groups** → present a 3-option picker via `AskUserQuestion` and do NOT proceed until the user chooses. Build the options from the catalog: walk `tasks[]` in catalog order (already `updatedAt` desc — see `scripts/okstra_ctl/render.py:654`), collect distinct `taskGroupPathSegment` values that have ≥1 entry whose resolved `workStatus` is **non-done** (defer to Step 2's inference table), and offer the newest **1–2** such groups as recommendations. The **last option is always `직접 입력`** (free-text group token, fed into sub-step 3). Label each recommendation with its non-done task count (e.g. `uploadFont (non-done 3)`).
62
- - If **zero groups have a non-done task** (or the catalog is empty), do NOT open a picker — emit `해당 task-group 모든 task가 done 상태입니다. 생성할 schedule 없습니다.` (or `해당 task-group 찾을 없습니다.` when the catalog has no tasks at all) and stop **without creating a file**.
67
+ - The user **named no task-group, or the named token matches 0 or ≥2 groups** → present a 3-option picker via `AskUserQuestion` and do NOT proceed until the user chooses. Build the options from the catalog: walk `tasks[]` in catalog order (already `updatedAt` desc — see `scripts/okstra_ctl/render.py:654`), collect distinct `taskGroupPathSegment` values that have ≥1 entry whose resolved `workStatus` is **non-done** (defer to Step 2's inference table), and offer the newest **1–2** such groups as recommendations. The **last option is always `Enter directly`** (free-text group token, fed into sub-step 3). Label each recommendation with its non-done task count (e.g. `uploadFont (non-done 3)`).
68
+ - If **zero groups have a non-done task** (or the catalog is empty), do NOT open a picker — emit `All tasks in this task-group are done. There is no schedule to generate.` (or `That task-group could not be found.` when the catalog has no tasks at all) and stop **without creating a file**.
63
69
  3. **Normalise the resolved `<task-group>`:** lowercase it, then strip every character that is not `[a-z0-9]`. Apply the same transform to each entry's `taskGroupPathSegment`. Match on equality — this is the single comparison rule; do NOT also fall back to the raw `taskGroup` field.
64
- 4. If no tasks found, output `해당 task-group 찾을 없습니다.` and stop.
70
+ 4. If no tasks found, output `That task-group could not be found.` and stop.
65
71
  5. For each matched task, read `.okstra/tasks/<task-group-segment>/<task-id-segment>/task-manifest.json` directly. Catalog data may be stale; the manifest is authoritative.
66
72
  6. **Derive `<project-id>`** for the header: prefer `task-catalog.json`'s top-level `projectId`, otherwise the first matched manifest's `projectId`. Do not invent a value.
67
73
 
@@ -69,7 +75,7 @@ One computation rule the template scaffold cannot carry inline:
69
75
 
70
76
  For inference when `workStatus` is missing or empty, defer to the inference table in `skills/okstra-inspect/SKILL.md` (`status.4` → "Default value convention") — do not duplicate it here. Then filter: resolved `done` → exclude; everything else (`todo` / `in-progress` / `blocked` / `phase-done` / inferred non-done) → include.
71
77
 
72
- If 0 tasks remain, output `해당 task-group 모든 task가 done 상태입니다. 생성할 schedule 없습니다.` and stop **without creating a file**.
78
+ If 0 tasks remain, output `All tasks in this task-group are done. There is no schedule to generate.` and stop **without creating a file**.
73
79
 
74
80
  ### Step 3: Per-task stage extraction (Stage Map source)
75
81
 
@@ -83,7 +89,7 @@ For each in-scope task, the **authoritative source is its `implementation-planni
83
89
 
84
90
  **No planning Stage Map** (`stage-map` returned `stages: []`) → this task cannot be stage-scheduled. Tag it `[NEEDS-PLANNING]`, skip the Step 3.5 stage picker for it, and render it under its phase section as a single banner line with task-level metadata only (no Gantt bars, no day total). Continue with the remaining tasks.
85
91
 
86
- **`remainingStages` is empty** (every stage done but `workStatus` not `done`) → not a scheduling target. Render the task as `_완료남은 stage 없음_` under its phase section; contribute no forward day total.
92
+ **`remainingStages` is empty** (every stage done but `workStatus` not `done`) → not a scheduling target. Render the task as `_Completeno remaining stage_` under its phase section; contribute no forward day total.
87
93
 
88
94
  ### Step 3.5: Stage selection (per task, user input)
89
95
 
@@ -96,8 +102,8 @@ Run this **once per in-scope task that has a non-empty `remainingStages`**, sequ
96
102
  3. If `remainingStages` has ≤2 stages, emit only the bundles that are distinct (1–2), never pad to 3.
97
103
 
98
104
  **Render the picker** with `AskUserQuestion` (one question for this task):
99
- - Options = the distinct bundles + a final `"남은 stage 전부"` option. `AskUserQuestion`'s built-in Other slot serves the `직접 입력` (arbitrary stage subset) case; when the user supplies a custom subset, close it under `depends_on` before accepting.
100
- - **Degenerate skip:** if only one distinct bundle exists AND it already equals all remaining stages, skip the picker for this task and set `selectedStages = remainingStages` (log `> _Stage picker 생략: 남은 stage가 단일 의존성 체인._`).
105
+ - Options = the distinct bundles + a final `"All remaining stages"` option. `AskUserQuestion`'s built-in Other slot serves the `Enter directly` (arbitrary stage subset) case; when the user supplies a custom subset, close it under `depends_on` before accepting.
106
+ - **Degenerate skip:** if only one distinct bundle exists AND it already equals all remaining stages, skip the picker for this task and set `selectedStages = remainingStages` (log `> _Stage picker skipped: remaining stages form a single dependency chain._`).
101
107
 
102
108
  Record the chosen `selectedStages` for this task. Any custom selection that breaks `depends_on` closure is rejected — re-prompt the same task.
103
109
 
@@ -110,19 +116,19 @@ Record the chosen `selectedStages` for this task. Any custom selection that brea
110
116
  | `bugfix` | Phase 1 when risk is High/Med-High; otherwise Phase 2 |
111
117
  | `feature` / `improvement` / `docs` / `doc` | Phase 2 |
112
118
  | `refactor` / `ops` | Phase 3 |
113
- | `unknown` (or unmatched / missing) | Phase 2, with rationale `> _workCategory '<raw-value>' 미정의 — Phase 2로 기본 분류._` at the top of that phase section |
119
+ | `unknown` (or unmatched / missing) | Phase 2, with rationale `> _workCategory '<raw-value>' undefineddefaulting to Phase 2._` at the top of that phase section |
114
120
 
115
121
  Priority overrides category: `P0` → Phase 1; `P1`/`P2` → Phase 2; `P3` or multi-repo + infrastructure scope → Phase 3. When still ambiguous, place the task in the closest phase and add a one-line rationale at the top of that phase section (not validator-enforced — emit it yourself).
116
122
 
117
- Phase bucketing stays **task-level** (a task lands in one Phase by its `workCategory`/Priority). Within a task's per-task section, the **selected stages become the Work Breakdown rows**: one row per `selectedStages` entry with its `title`, `step_count`-derived effort, and `depends_on`. Stages excluded from `selectedStages` because they are already done are listed once as `> _완료 stage: stage <n>, …_` and carry no forward effort. This keeps the mandatory heading skeleton unchanged while moving the unit of work to the stage.
123
+ Phase bucketing stays **task-level** (a task lands in one Phase by its `workCategory`/Priority). Within a task's per-task section, the **selected stages become the Work Breakdown rows**: one row per `selectedStages` entry with its `title`, `step_count`-derived effort, and `depends_on`. Stages excluded from `selectedStages` because they are already done are listed once as `> _Done stages: stage <n>, …_` and carry no forward effort. This keeps the mandatory heading skeleton unchanged while moving the unit of work to the stage.
118
124
 
119
125
  ### Step 5: Gantt decision (render by default)
120
126
 
121
- `## Gantt Chart` is **rendered by default** — skip ONLY when literally no day signal exists (every task is effort=XXL with no visible decomposition, or all tasks lack both effort sizing and decomposition). Render whenever any of these hold: 2+ tasks with effort sizing; 1 task whose effort yields a range (mid-point bar, or `lo`/`hi` two-bar form); 1 task with Part/Phase/Step decomposition in the source (bars at decomposition-unit level); total estimated effort ≥ 3 days. When per-unit day allocations aren't itemized, split the parent range across the visible units yourself and append the `est` annotation (or add `> 일별 배분은 추정치이며 차단 항목 해소 갱신 권장.`). "Range is wide", "single task", "user decisions pending" are NOT skip reasons — render an estimate-tagged chart instead.
127
+ `## Gantt Chart` is **rendered by default** — skip ONLY when literally no day signal exists (every task is effort=XXL with no visible decomposition, or all tasks lack both effort sizing and decomposition). Render whenever any of these hold: 2+ tasks with effort sizing; 1 task whose effort yields a range (mid-point bar, or `lo`/`hi` two-bar form); 1 task with Part/Phase/Step decomposition in the source (bars at decomposition-unit level); total estimated effort ≥ 3 days. When per-unit day allocations aren't itemized, split the parent range across the visible units yourself and append the `est` annotation (or add `> Per-day allocation is an estimate; refresh recommended after blocking items are resolved.`). "Range is wide", "single task", "user decisions pending" are NOT skip reasons — render an estimate-tagged chart instead.
122
128
 
123
129
  When the source is a Stage Map, the Gantt **bars are the selected stages** (one bar per `selectedStages` entry), day length split from `step_count` (or the effort range across the stage's steps), and cross-stage `(after stage <n>)` / `(after <TASK-ID>)` edges follow `depends_on`. Already-done stages never get a bar. A task tagged `[NEEDS-PLANNING]` contributes no bars.
124
130
 
125
- When you do skip, insert in the section's position exactly: `> _Gantt Chart 생략: <concrete reason referencing the actual data>._`
131
+ When you do skip, insert in the section's position exactly: `> _Gantt Chart skipped: <concrete reason referencing the actual data>._`
126
132
 
127
133
  **Directive override (highest priority).** Before applying the heuristic, check for a `## Directive` section, first hit wins: (1) the `--directive-file <abs-path>` argument; (2) `<PROJECT_ROOT>/.okstra/tasks/<task-group-segment>/schedule/instruction-set/analysis-material.md`; (3) none → apply the default heuristic silently. A found directive overrides the render/skip heuristic for the affected section — note it inline as `> _Per Directive directive: <verbatim short excerpt>._` — and its pre-supplied day allocations / phase weights are used verbatim as bar lengths. A directive file without a `## Directive` heading counts as "no directive".
128
134
 
@@ -159,11 +165,11 @@ Reached only after Step 5.5 returns `pass`. **Promote** the verified staging dra
159
165
  ### Step 8: Completion message (Korean)
160
166
 
161
167
  ```
162
- ✓ Schedule 생성 완료: <relative-path>
163
- - 포함 task: N
164
- - 제외(done) task: M
165
- - 예상 소요: X.X ~ Y.Y days (Effort 합산)
166
- - 모드: lead + verifier
168
+ ✓ Schedule generated: <relative-path>
169
+ - Included tasks: N
170
+ - Excluded (done) tasks: M
171
+ - Estimated effort: X.X ~ Y.Y days (Effort sum)
172
+ - Mode: lead + verifier
167
173
  ```
168
174
 
169
175
  ## Edge Cases
@@ -171,12 +177,12 @@ Reached only after Step 5.5 returns `pass`. **Promote** the verified staging dra
171
177
  | Case | Handling |
172
178
  |------|----------|
173
179
  | `workStatus` absent or empty | Resolve via the `okstra-inspect status.4` inference table; include unless resolved `done` |
174
- | Filtered task count is 0 | Emit "모든 task가 done" message; do NOT create a file |
175
- | implementation-planning 리포트 없음 | `[NEEDS-PLANNING]` 배너로만 나열, stage picker·Gantt·day total 없음 |
176
- | 남은 stage 0개(전부 done, workStatus 미표기) | `_완료남은 stage 없음_`, forward 산출 없음 |
177
- | 남은 stage ≤2 | 누적 묶음을 나오는 만큼만(1~2), 단일 체인이면 picker 생략·전부 진행 |
178
- | verifier 2회 미통과 | 최종 파일 미작성, 잔여 missing/extra/order 사용자 보고 |
179
- | `task-group` matches no tasks | "해당 task-group 찾을 없습니다." and stop |
180
+ | Filtered task count is 0 | Emit the "all tasks are done" message; do NOT create a file |
181
+ | No implementation-planning report | List with a `[NEEDS-PLANNING]` banner only; no stage picker / Gantt / day total |
182
+ | 0 remaining stages (all done, workStatus unmarked) | `_Completeno remaining stage_`, no forward computation |
183
+ | ≤2 remaining stages | Emit only as many cumulative bundles as arise (12); a single chain skips the picker and proceeds with all |
184
+ | verifier fails twice | Final file not written; report residual missing/extra/order to the user |
185
+ | `task-group` matches no tasks | "That task-group could not be found." and stop |
180
186
  | Catalog and manifest disagree on `workStatus` | Manifest wins (catalog may be stale) |
181
187
  | task-group casing / punctuation variants | Normalise both sides (lowercase + strip non-`[a-z0-9]`), compare against `taskGroupPathSegment` only; use the manifest's segment verbatim for path output |
182
188
 
@@ -140,7 +140,7 @@ Inform the user with a short summary:
140
140
  | `command not found: npx` | Node missing | Install node 18+. |
141
141
  | `okstra ensure-installed` keeps reinstalling | `~/.okstra/version` write fails (permissions) | Check `~/.okstra` ownership and writability. |
142
142
  | `error: --project-id is required (no existing project.json, not a TTY)` | `okstra setup --yes` invoked without `--project-id`, or with empty answer to Step 3 prompt | Re-ask Step 3 and pass a non-empty id via `--project-id`. |
143
- | `projectId mismatch` / `projectId 불일치` | `project.json` already exists with a different id | Decide which id is canonical; manually delete `<PROJECT_ROOT>/.okstra/project.json` to re-register, or re-run with the existing id. |
143
+ | `projectId mismatch` / `projectId mismatch` | `project.json` already exists with a different id | Decide which id is canonical; manually delete `<PROJECT_ROOT>/.okstra/project.json` to re-register, or re-run with the existing id. |
144
144
  | `EACCES` writing under `.okstra/` | directory owned by another user (e.g. created by a previous root-shell run) | `chown -R "$USER" <PROJECT_ROOT>/.okstra` or delete and let setup recreate. |
145
145
  | `warning: failed to provision .claude/settings.local.json symlink` | a non-symlink `.claude/settings.local.json` already exists and the backup-and-replace step failed | Inspect `<PROJECT_ROOT>/.claude/settings.local.json{,.bak.*}`; manually merge project-specific rules, then re-run setup. |
146
146
  | `npx okstra@latest install` succeeds but `doctor` shows FAIL | runtime/{python,bin,skills} sync not yet performed (pre-release package) | Use dev install: clone the repo and run `node bin/okstra install --link <repo>`. |
@@ -140,19 +140,19 @@ overwriting silently.
140
140
  `~/.okstra/templates/prd/pr-body.template.md`. Most projects want their own
141
141
  (e.g. `.github/PULL_REQUEST_TEMPLATE.md`). Pre-registration during setup is
142
142
  opt-in; the same prompt is offered again on the first `release-handoff` run,
143
- so deferring (`나중에`) is safe.
143
+ so deferring (`Later`) is safe.
144
144
 
145
145
  Ask with `AskUserQuestion` (fixed options — file path entry happens in the
146
146
  follow-up plain text prompt):
147
147
 
148
- - **Question**: `" 프로젝트에서 release-handoff 사용할 PR 본문 템플릿을 등록할까요?"`
148
+ - **Question**: `"Register the PR body template that release-handoff will use for this project?"`
149
149
  - **Options**:
150
- 1. `이번 프로젝트만 (project scope)` — writes `prTemplatePath` to `<PROJECT_ROOT>/.okstra/project.json`.
151
- 2. `전역 (global scope)` — writes `prTemplatePath` to `~/.okstra/config.json`.
152
- 3. `나중에` — skip.
150
+ 1. `This project only (project scope)` — writes `prTemplatePath` to `<PROJECT_ROOT>/.okstra/project.json`.
151
+ 2. `Global (global scope)` — writes `prTemplatePath` to `~/.okstra/config.json`.
152
+ 3. `Later` — skip.
153
153
 
154
154
  If scope 1 or 2, follow up with a plain text prompt:
155
- `"PR 본문 템플릿 파일 경로를 알려주세요. project 스코프는 project-root 기준 상대경로 또는 절대경로, global 스코프는 절대경로 또는 ~/ 시작 경로만 허용됩니다."`
155
+ `"Tell me the PR body template file path. project scope accepts a project-root-relative or absolute path; global scope accepts only an absolute path or a ~/ path."`
156
156
  Consume the next user message, then run:
157
157
 
158
158
  ```bash
@@ -160,23 +160,24 @@ okstra config set pr-template-path "<typed-path>" --scope <project|global>
160
160
  ```
161
161
 
162
162
  The command validates the value (global rejects relative paths) and writes
163
- atomically. Surface its stdout JSON. If the user chose `나중에`, tell them
163
+ atomically. Surface its stdout JSON. If the user chose `Later`, tell them
164
164
  they can register later via the same `okstra config set` command or the
165
165
  per-run override prompt during the next release-handoff run.
166
166
 
167
167
  ## E. Final report language (`reportLanguage`)
168
168
 
169
- 기본은 영어. Skip 하면 `reportLanguage` 필드를 두지 않고 runtime 이 `auto` 로
170
- 처리한다 task brief 서술 언어를 따라간다 (한국어 brief → 한국어
171
- report, 영어 brief → 영어 report).
169
+ The default is English. If you skip, no `reportLanguage` field is written and
170
+ the runtime treats it as `auto` it follows the task brief's primary
171
+ narration language (Korean brief → Korean report, English brief → English
172
+ report).
172
173
 
173
174
  AskUserQuestion (fixed options):
174
- - Question: `"Final report 어느 언어로 작성할까요?"`
175
+ - Question: `"Which language should the final report be written in?"`
175
176
  - Options:
176
177
  1. `English (recommended)` → `en`
177
- 2. `한국어` → `ko`
178
- 3. `Auto (task brief 언어로 추론, 불분명하면 영어)` → `auto`
179
- 4. `나중에` → skip (필드 미설정 → runtime auto 처리)
178
+ 2. `Korean` → `ko`
179
+ 3. `Auto (infer from the task brief language; English if unclear)` → `auto`
180
+ 4. `Later` → skip (no field set → runtime treats it as auto)
180
181
 
181
182
  If the user picks 1/2/3:
182
183
 
@@ -184,5 +185,5 @@ If the user picks 1/2/3:
184
185
  okstra config set report-language <en|ko|auto> --scope project
185
186
  ```
186
187
 
187
- 전역 기본값은 README "global config" 안내대로 `--scope global` 수동
188
- 설정한다 flow 에서는 project 스코프만 제공한다.
188
+ Set the global default manually with `--scope global` as described in the
189
+ README's "global config" guidance this flow offers only project scope.
@@ -21,8 +21,11 @@ okstra preflight --runtime claude-code --json
21
21
  ```
22
22
 
23
23
  On `ok:true`, carry `projectRoot`. On `ok:false`, tell the user to run `/okstra-setup` first
24
- and stop. On `unknown command: preflight`, tell the user to run
25
- `npm i -g okstra@latest` and stop.
24
+ and stop.
25
+
26
+ <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
27
+ 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).
28
+ <!-- END FRAGMENT: preflight-outdated-cli -->
26
29
 
27
30
  ## Step 1: Resolve the day window
28
31
 
@@ -18,7 +18,11 @@ Single entry point for answering the clarification questions an okstra run left
18
18
 
19
19
  ## Step 0: Preflight (shared)
20
20
 
21
- Before anything, run one Bash tool call whose leading token is the literal `okstra` (never wrapped in `if`/`eval`/`export`/`$(...)`/`VAR=...`/`||`/`&&`/`npx` — a non-literal leading token defeats the `Bash(okstra:*)` permission match):
21
+ Before anything:
22
+
23
+ <!-- BEGIN FRAGMENT: bash-invocation-rule -->
24
+ 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
+ <!-- END FRAGMENT: bash-invocation-rule -->
22
26
 
23
27
  ```bash
24
28
  okstra preflight --runtime claude-code --json
@@ -26,7 +30,11 @@ okstra preflight --runtime claude-code --json
26
30
 
27
31
  Branch on the stdout JSON:
28
32
  - `ok: true` → carry `projectRoot` and `projectId` as literal strings; they are the base for every step below.
29
- - `ok: false` → this project has no okstra setup. Tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop. If the user pointed at a specific project directory, 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 that **also** returns `ok:false` do you 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).
33
+ - `ok: false` → this project has no okstra setup. Tell the user: "this project has no okstra setup. Run `/okstra-setup` first." Then stop. If the user pointed at a specific project directory, 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 that **also** returns `ok:false` do you stop.
34
+
35
+ <!-- BEGIN FRAGMENT: preflight-outdated-cli -->
36
+ 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
+ <!-- END FRAGMENT: preflight-outdated-cli -->
30
38
 
31
39
  Then resolve the okstra home once (the `list` sub-command needs it):
32
40
 
@@ -34,7 +42,11 @@ Then resolve the okstra home once (the `list` sub-command needs it):
34
42
  okstra paths --field home
35
43
  ```
36
44
 
37
- Paste the printed path literally into `--home` below. Every subsequent `okstra <subcmd>` call self-bootstraps its Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
45
+ Paste the printed path literally into `--home` below.
46
+
47
+ <!-- BEGIN FRAGMENT: python-bootstrap-note -->
48
+ Every subsequent `okstra <subcmd>` call self-bootstraps its Python path, so this skill never needs `okstra paths --shell` / `export PYTHONPATH=...`.
49
+ <!-- END FRAGMENT: python-bootstrap-note -->
38
50
 
39
51
  ## Step 1: List awaiting tasks → picker
40
52