okstra 0.122.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 (108) hide show
  1. package/README.md +5 -2
  2. package/docs/architecture/storage-model.md +15 -1
  3. package/docs/architecture.md +45 -7
  4. package/docs/cli.md +47 -5
  5. package/docs/for-ai/README.md +42 -36
  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 +320 -0
  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 +92 -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 +52 -28
  26. package/docs/task-process/implementation.md +51 -32
  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 +3 -3
  36. package/runtime/prompts/coding-preflight/frameworks/node-server.md +1 -1
  37. package/runtime/prompts/launch.template.md +6 -3
  38. package/runtime/prompts/lead/convergence.md +11 -21
  39. package/runtime/prompts/lead/okstra-lead-contract.md +16 -18
  40. package/runtime/prompts/lead/plan-body-verification.md +47 -18
  41. package/runtime/prompts/lead/report-writer.md +50 -45
  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 +4 -2
  45. package/runtime/prompts/profiles/_implementation-executor.md +6 -1
  46. package/runtime/prompts/profiles/_implementation-verifier.md +3 -3
  47. package/runtime/prompts/profiles/error-analysis.md +2 -2
  48. package/runtime/prompts/profiles/final-verification.md +3 -1
  49. package/runtime/prompts/profiles/implementation-planning.md +24 -14
  50. package/runtime/prompts/profiles/implementation.md +1 -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 +18 -18
  54. package/runtime/prompts/wizard/prompts.ko.json +44 -0
  55. package/runtime/python/okstra_ctl/codex_dispatch.py +23 -1
  56. package/runtime/python/okstra_ctl/design_prep.py +1462 -0
  57. package/runtime/python/okstra_ctl/design_surfaces.py +243 -0
  58. package/runtime/python/okstra_ctl/final_report_schema.py +33 -1
  59. package/runtime/python/okstra_ctl/implementation_stage.py +35 -0
  60. package/runtime/python/okstra_ctl/incremental_carry.py +294 -21
  61. package/runtime/python/okstra_ctl/incremental_scope.py +51 -5
  62. package/runtime/python/okstra_ctl/material.py +1 -1
  63. package/runtime/python/okstra_ctl/model_discovery.py +98 -0
  64. package/runtime/python/okstra_ctl/models.py +8 -3
  65. package/runtime/python/okstra_ctl/render.py +5 -0
  66. package/runtime/python/okstra_ctl/run.py +53 -5
  67. package/runtime/python/okstra_ctl/user_response.py +67 -2
  68. package/runtime/python/okstra_ctl/wizard.py +283 -3
  69. package/runtime/python/okstra_token_usage/report.py +11 -0
  70. package/runtime/schemas/final-report-v1.0.schema.json +336 -0
  71. package/runtime/skills/_fragments/bash-invocation-rule.md +1 -0
  72. package/runtime/skills/_fragments/preflight-outdated-cli.md +1 -0
  73. package/runtime/skills/_fragments/python-bootstrap-note.md +1 -0
  74. package/runtime/skills/okstra-brief-gen/SKILL.md +117 -122
  75. package/runtime/skills/okstra-container-build/SKILL.md +24 -14
  76. package/runtime/skills/okstra-graphify/SKILL.md +12 -4
  77. package/runtime/skills/okstra-inspect/SKILL.md +105 -99
  78. package/runtime/skills/okstra-manager/SKILL.md +1 -1
  79. package/runtime/skills/okstra-memory/SKILL.md +3 -3
  80. package/runtime/skills/okstra-rollup/SKILL.md +12 -6
  81. package/runtime/skills/okstra-run/SKILL.md +49 -88
  82. package/runtime/skills/{okstra-schedule → okstra-schedule-gen}/SKILL.md +38 -32
  83. package/runtime/skills/okstra-setup/SKILL.md +1 -1
  84. package/runtime/skills/okstra-setup/references/project-config.md +17 -16
  85. package/runtime/skills/okstra-usage/SKILL.md +5 -2
  86. package/runtime/skills/okstra-user-response/SKILL.md +23 -9
  87. package/runtime/templates/prd/brief.template.md +92 -92
  88. package/runtime/templates/reports/error-analysis-input.template.md +1 -1
  89. package/runtime/templates/reports/fan-out-unit.template.md +6 -6
  90. package/runtime/templates/reports/final-report.template.md +67 -0
  91. package/runtime/templates/reports/final-verification-input.template.md +6 -6
  92. package/runtime/templates/reports/i18n/en.json +31 -0
  93. package/runtime/templates/reports/i18n/ko.json +31 -0
  94. package/runtime/templates/reports/implementation-input.template.md +1 -1
  95. package/runtime/templates/reports/implementation-planning-input.template.md +1 -1
  96. package/runtime/templates/reports/improvement-discovery-input.template.md +1 -1
  97. package/runtime/templates/reports/quick-input.template.md +1 -1
  98. package/runtime/templates/reports/release-handoff-input.template.md +1 -1
  99. package/runtime/templates/reports/schedule.template.md +22 -22
  100. package/runtime/templates/reports/task-brief.template.md +3 -3
  101. package/runtime/templates/reports/user-response.template.md +20 -20
  102. package/runtime/templates/worker-prompt-preamble.md +111 -13
  103. package/runtime/validators/validate-run.py +426 -5
  104. package/runtime/validators/validate-schedule.py +5 -5
  105. package/src/cli-registry.mjs +7 -0
  106. package/src/commands/inspect/design-prep.mjs +23 -0
  107. package/src/lib/skill-catalog.mjs +2 -1
  108. package/docs/for-ai/skills/okstra-schedule.md +0 -320
@@ -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
 
@@ -57,19 +69,21 @@ Carry the chosen entry's `reportPath` and `taskKey` forward.
57
69
  okstra user-response show --report <reportPath>
58
70
  ```
59
71
 
60
- Returns `{reportPath, rows: [{id, kind, blocks, status, statement, recommended, alternatives, contextRefs}]}`. For each open `C-*` row, present to the user:
72
+ Returns `{reportPath, rows: [{id, kind, blocks, status, statement, recommended, alternatives, contextRefs, resolvedRefs}]}`. `resolvedRefs` is `[{ref, definition}]` — the CLI has already looked up what each internal token (`RB-002`, `FU-001`, `§4.7`, …) means in the report body; `definition` is `null` only when the report text alone could not resolve it (e.g. a `path:line` pointer).
73
+
74
+ **Do NOT paste the raw `statement` as the question.** A `statement` like `Rewrite RB-002 rollback (see §4.7)` is meaningless to the user on its own — that is the whole reason this skill exists. For each open `C-*` row, you MUST present:
61
75
 
62
- - **`id`** and its **`statement`** (the original question).
63
- - **`recommended`** — the answer okstra proposed (+ rationale). It is only a recommendation.
64
- - **`alternatives[]`** — list them if present.
65
- - **`contextRefs[]`** — the report `§`/`C-id`/`path:line` references this question points at.
76
+ - **A rewritten, self-contained question** (lead with this): rewrite `statement` in plain language with **every internal token expanded inline** from its `resolvedRefs` `definition` — the user must never have to know what `RB-002` is to answer. If a token's `definition` is `null`, resolve it yourself **using Read** on the report `§`/`path:line` before asking; only if it is genuinely unresolvable do you say so plainly.
77
+ - **`recommended`** — the answer okstra proposed (+ rationale), also stated in plain language. It is only a recommendation.
78
+ - **`alternatives[]`** — list them if present, each in plain language.
79
+ - **Raw source** (secondary, for traceability): the raw `id` + `statement` so the mapping back to the report stays visible.
66
80
 
67
81
  ## Step 3: Per-item — collect the user's decision (4 branches)
68
82
 
69
83
  For each open item, the user picks one of four dispositions. You relay and transcribe; you never choose:
70
84
 
71
85
  1. **Answer** — the user accepts the recommendation or gives their own answer. `disposition: "answer"`, `value` = the user's utterance verbatim.
72
- 2. **Ask-to-explain** — if the user asks "what does this mean?", open the report `§`/`path:line` that this item's `contextRefs[]` points at **using Read** and explain it in plain language. Only explain — **do not pick the answer for the user**; after explaining, hand the decision back to the user.
86
+ 2. **Ask-to-explain (fallback)** — Step 2 already expanded every internal token, so the question should already be self-contained. If the user still asks "what does this mean?" or a `resolvedRefs` `definition` was `null`, open the report `§`/`path:line` that this item's `contextRefs[]` points at **using Read** and explain it in plain language. Only explain — **do not pick the answer for the user**; after explaining, hand the decision back to the user.
73
87
  3. **Free-form** — the user gives a narrative answer that matches neither a recommendation nor an alternative. `value` = that narrative verbatim, with the rationale in `rationale` if needed. `disposition: "answer"`.
74
88
  4. **Hold + reframe** — if the user asks to "re-frame this question itself", record it as `disposition: "reframe"`. Put what the user wants re-asked into `value` verbatim. A reframe is not an answer, so it does not satisfy the approval gate — the next run re-frames that question.
75
89
 
@@ -14,14 +14,14 @@ taskType: "{{FM_TASK_TYPE}}"
14
14
  # OKSTRA Task Brief
15
15
 
16
16
  <!--
17
- 이 brief은 okstra 워커(Claude/Codex/Antigravity)가 코드베이스/도메인 사전지식 없이 분석할 수 있도록 준비하는 단일 source-of-truth 문서입니다.
18
-
19
- 원칙:
20
- 1. 워커는 외부 링크에 접근할 수 없음 → 모든 1차 증거는 inline으로 박을 것 (fenced code block).
21
- 2. 워커는 도메인 용어를 모름 → Domain Glossary로 핵심 용어를 사전 정의.
22
- 3. 운영자(operator)용 정보(okstra.sh 명령, working directory)는 brief에 두지 말 것 — 별도 runbook으로.
23
- 4. Task Type에 따라 작성해야 할 섹션이 다름 → 해당 태스크의 conditional 블록을 채울 것.
24
- 5. 비어 있는 섹션은 `_N/A — <reason>_`로 명시. 침묵은 워커 혼란의 원인.
17
+ This brief is the single source-of-truth document that lets an okstra worker (Claude/Codex/Antigravity) analyze the task without any prior knowledge of the codebase or domain.
18
+
19
+ Principles:
20
+ 1. Workers cannot reach external links → embed every piece of primary evidence inline (fenced code block).
21
+ 2. Workers don't know domain terms → predefine the key terms in the Domain Glossary.
22
+ 3. Keep operator-facing information (okstra.sh commands, working directory) out of the brief — put it in a separate runbook.
23
+ 4. The sections you must fill differ by Task Type → complete that task's conditional block.
24
+ 5. Mark empty sections explicitly with `_N/A — <reason>_`. Silence is a source of worker confusion.
25
25
  -->
26
26
 
27
27
  ## Identity
@@ -34,51 +34,51 @@ taskType: "{{FM_TASK_TYPE}}"
34
34
  | Task ID | `<TASK-ID>` |
35
35
  | Task Type | `requirements-discovery` \| `error-analysis` \| `implementation-planning` \| `final-verification` |
36
36
  | Issue / Ticket | `<TASK-ID> · <title in original language> (English: <translation if non-English>)` |
37
- | Requested Outcome | <한 문장. 이 run이 산출해야 할 핵심 결과물> |
37
+ | Requested Outcome | <one sentence. The key deliverable this run must produce> |
38
38
 
39
39
  ---
40
40
 
41
41
  ## Request Summary
42
42
 
43
43
  - **What is being requested or changed?**
44
- <한 문단 또는 bullet 3-5개>
44
+ <one paragraph, or 3-5 bullets>
45
45
  - **Why now?**
46
- <비즈니스/기술 트리거. 마감일, 인시던트, 의존 태스크 등>
46
+ <business/technical trigger. Deadline, incident, dependent task, etc.>
47
47
  - **New / Continuation / Reopened?**
48
- <One of the three + 직전 run 식별자(있다면)>
48
+ <One of the three + prior run identifier (if any)>
49
49
  - **What decision should this run produce?**
50
- <이 run이 답해야 할 핵심 결정 1-3개. 모호하면 워커가 산만해짐>
50
+ <the 1-3 key decisions this run must answer. Vagueness distracts the worker>
51
51
 
52
52
  ---
53
53
 
54
54
  ## Inline Evidence
55
55
 
56
56
  <!--
57
- 워커는 외부 URL/Notion/Linear/Slack에 접근할 수 없습니다. 1차 증거는 모두 여기에 inline 박을 것.
57
+ Workers cannot reach external URLs / Notion / Linear / Slack. Embed all primary evidence inline here.
58
58
  -->
59
59
 
60
60
  ### Symptom / Sample Payload
61
61
 
62
62
  ```
63
- <관찰된 현상, 응답 페이로드 샘플, UI 스크린샷 caption 등 — 텍스트로>
63
+ <observed symptom, sample response payload, UI screenshot caption, etc. — as text>
64
64
  ```
65
65
 
66
- ### Logs / Stack Trace (해당되는 경우)
66
+ ### Logs / Stack Trace (if applicable)
67
67
 
68
68
  ```
69
- <로그 발췌. 민감정보는 마스킹>
69
+ <log excerpt. Mask sensitive information>
70
70
  ```
71
71
 
72
72
  ### Relevant Code Excerpts
73
73
 
74
74
  ```typescript
75
75
  // path: src/domains/upload/dto/upload-job.view.ts:23-45
76
- <코드 발췌 — 워커가 파일 전체를 읽지 않아도 핵심을 파악할 수 있어야 함>
76
+ <code excerpt — the worker should grasp the essentials without reading the whole file>
77
77
  ```
78
78
 
79
- ### External Doc Excerpts (Notion/Linear/Confluence 발췌)
79
+ ### External Doc Excerpts (Notion/Linear/Confluence excerpts)
80
80
 
81
- > <원문 인용. 링크는 보조이고 인용이 본체>
81
+ > <quote from the source. The link is secondary; the quote is the substance>
82
82
  > -- Source: <doc title + section>
83
83
 
84
84
  ---
@@ -86,27 +86,27 @@ taskType: "{{FM_TASK_TYPE}}"
86
86
  ## Domain Glossary
87
87
 
88
88
  <!--
89
- Codex/Antigravity는 이 코드베이스를 모릅니다. 핵심 용어 5-15개를 한 문장씩 정의.
90
- 없는 용어를 워커가 추측하면 분석 품질이 즉시 떨어집니다.
89
+ Codex/Antigravity don't know this codebase. Define 5-15 key terms, one sentence each.
90
+ If a worker guesses at an undefined term, analysis quality drops immediately.
91
91
  -->
92
92
 
93
93
  | Term | Definition |
94
94
  |------|-----------|
95
- | `<도메인 용어 1>` | <1-2 문장 정의> |
96
- | `<도메인 용어 2>` | <1-2 문장 정의> |
97
- | `<코드 식별자 1>` | <역할 + 위치 + 다른 entity와의 관계> |
95
+ | `<domain term 1>` | <1-2 sentence definition> |
96
+ | `<domain term 2>` | <1-2 sentence definition> |
97
+ | `<code identifier 1>` | <role + location + relationship to other entities> |
98
98
 
99
99
  ---
100
100
 
101
101
  ## Current Context
102
102
 
103
103
  - **Current behavior or state**:
104
- <지금 시스템이 어떻게 동작하는가>
104
+ <how the system behaves today>
105
105
  - **Desired behavior or outcome**:
106
- <어떻게 동작해야 하는가>
106
+ <how it should behave>
107
107
  - **Existing related implementation**:
108
- - `<file-path>:<line-range>` — <역할 한 줄>
109
- - **Related code paths** (참조용 — 직접 발췌는 Inline Evidence에):
108
+ - `<file-path>:<line-range>` — <one-line role>
109
+ - **Related code paths** (for reference — put direct excerpts in Inline Evidence):
110
110
  - `<path>`
111
111
  - `<path>`
112
112
 
@@ -115,74 +115,74 @@ Codex/Antigravity는 이 코드베이스를 모릅니다. 핵심 용어 5-15개
115
115
  ## Out of Scope
116
116
 
117
117
  <!--
118
- 명시적 제외 목록. 워커 scope-creep 방지의 핵심.
118
+ An explicit exclusion list. Central to preventing worker scope-creep.
119
119
  -->
120
120
 
121
- 이 run에서는 **다루지 않을** 것들:
121
+ Things this run will **not** address:
122
122
 
123
- - <out-of-scope item 1 + 제외 이유>
124
- - <out-of-scope item 2 + 제외 이유>
125
- - <별도 ticket/run으로 다룰 항목 — ticket ID 명시>
123
+ - <out-of-scope item 1 + reason for exclusion>
124
+ - <out-of-scope item 2 + reason for exclusion>
125
+ - <item to be handled in a separate ticket/run — specify the ticket ID>
126
126
 
127
127
  ---
128
128
 
129
129
  ## Task-Type Focus
130
130
 
131
131
  <!--
132
- 아래 두 블록 중 현재 task-type에 해당하는 것만 채우고, 나머지는 삭제하세요.
132
+ Of the two blocks below, fill only the one matching the current task-type and delete the rest.
133
133
  -->
134
134
 
135
135
  ### If `requirements-discovery`
136
136
 
137
137
  - **Why might this be a bugfix?**
138
- <증거 또는 "weak signal — none observed">
138
+ <evidence, or "weak signal — none observed">
139
139
  - **Why might this be a feature/improvement?**
140
- <증거>
140
+ <evidence>
141
141
  - **Why might this be a refactor/ops?**
142
- <증거>
143
- - **Classification blockers** — 무엇이 분류 확신을 막고 있는가?
144
- <evidence gap을 구체적으로>
142
+ <evidence>
143
+ - **Classification blockers** — what is preventing a confident classification?
144
+ <the evidence gap, specifically>
145
145
 
146
146
  ### If `error-analysis`
147
147
 
148
- - **Symptom** — 사용자/시스템이 무엇을 관찰하는가?
149
- - **Reproduction Steps** — 1-2-3 형식. 환경/사전조건 명시.
148
+ - **Symptom** — what does the user/system observe?
149
+ - **Reproduction Steps** — 1-2-3 format. State the environment/preconditions.
150
150
  ```
151
151
  1. <env: staging | local | prod>
152
152
  2. <action>
153
153
  3. <action>
154
154
  4. Expected: <…> / Actual: <…>
155
155
  ```
156
- - **Frequency** — 항상 / 간헐적 / 특정 조건에서만 / 1회성?
157
- - **Blast Radius** — 영향받는 사용자/요청/data 범위
158
- - **Suspected Cause(s)** — 현재까지의 가설. 각각 신뢰도(High/Med/Low)와 근거.
159
- - **What has been ruled out** — 이미 검증한 false leads (워커가 같은 길 가지 않게)
156
+ - **Frequency** — always / intermittent / only under specific conditions / one-off?
157
+ - **Blast Radius** — scope of affected users/requests/data
158
+ - **Suspected Cause(s)** — hypotheses so far. Each with confidence (High/Med/Low) and rationale.
159
+ - **What has been ruled out** — false leads already verified (so the worker doesn't retread them)
160
160
 
161
161
  ---
162
162
 
163
163
  ## Constraints and Risks
164
164
 
165
- - **Business constraints**: <e.g. 개인정보, SLA — 외부 승인/권한 항목은 적지 말 것 (사용자가 모든 권한을 가진다고 가정)>
166
- - **Technical constraints**: <e.g. backward-compat, 기존 client, schema>
167
- - **Delivery constraints**: <마감, 의존 배포, 롤아웃 게이트 — 단, 외부 승인 대기·권한 확인은 일정 요소로 적지 말 것>
168
- - **Approval / review checkpoints**: _N/A — 사용자가 모든 권한·승인 권한을 보유한다고 가정 (okstra 기본 규칙). 정말로 외부 차단 요소가 있을 때만 구체적으로 기술._
169
- - **Known assumptions**: <명시적 가정 — 워커가 검증할 항목>
170
- - **Open uncertainties**: <확인 필요한 것 — 답이 나오면 결정이 잠금 해제됨. 외부 권한·승인 관련 항목은 제외>
165
+ - **Business constraints**: <e.g. PII, SLA — do not list external approval/authorization items (assume the user holds all permissions)>
166
+ - **Technical constraints**: <e.g. backward-compat, existing client, schema>
167
+ - **Delivery constraints**: <deadline, dependent deployment, rollout gate — but do not list waiting on external approval or permission checks as schedule factors>
168
+ - **Approval / review checkpoints**: _N/A — assume the user holds all permission and approval authority (okstra default rule). Describe specifically only when a genuine external blocker exists._
169
+ - **Known assumptions**: <explicit assumptions — items for the worker to verify>
170
+ - **Open uncertainties**: <things to confirm — answering them unlocks a decision. Exclude external permission/approval items>
171
171
 
172
172
  ---
173
173
 
174
174
  ## Configuration / Deployment Context
175
175
 
176
176
  <!--
177
- 이 섹션은 *해당되는 경우에만* 채우세요. DTO 변경, 순수 로직 수정, 문서 작업 등은 보통 _N/A_입니다.
178
- 무관할 때는 본 섹션 전체를 다음 한 줄로 대체:
177
+ Fill this section *only when applicable*. DTO changes, pure logic edits, docs work, etc. are usually _N/A_.
178
+ When irrelevant, replace the entire section with this single line:
179
179
 
180
180
  _N/A — this task does not touch config or deployment._
181
181
  -->
182
182
 
183
- - **Config files in scope**: `<path>` — <어떤 키가 관련>
184
- - **Current observed values**: <key=value, 출처 명시>
185
- - **Expected values / invariants**: <변하면 안 되는 것 + 변해야 하는 것>
183
+ - **Config files in scope**: `<path>` — <which keys are relevant>
184
+ - **Current observed values**: <key=value, cite the source>
185
+ - **Expected values / invariants**: <what must not change + what must change>
186
186
  - **Deployment manifests in scope**: `<helm chart / k8s manifest / terraform path>`
187
187
  - **Rollout invariants**: <e.g. zero-downtime, version skew window>
188
188
 
@@ -191,45 +191,45 @@ Codex/Antigravity는 이 코드베이스를 모릅니다. 핵심 용어 5-15개
191
191
  ## External Resource Hints (for Lead pre-fetch)
192
192
 
193
193
  <!--
194
- okstra Lead가 워커 프롬프트에 inline으로 박아야 할 외부 자원 목록.
195
- 워커는 MCP/외부 도구에 직접 접근하지 않으므로 Lead가 사전에 snapshot해서 prompt에 embed합니다.
194
+ A list of external resources the okstra Lead must embed inline into the worker prompt.
195
+ Workers don't access MCP/external tools directly, so the Lead snapshots them ahead of time and embeds them in the prompt.
196
196
  -->
197
197
 
198
198
  | Resource | Type | Why needed |
199
199
  |----------|------|-----------|
200
- | `<table-name>` | MySQL schema | <어느 분석에서 schema 검증 필요> |
201
- | `<library@version>` | Library docs (`mcp__test-context7`) | <API 시그니처 확인용> |
202
- | `<aws-doc-keyword>` | AWS knowledge base | <설계 검증용> |
200
+ | `<table-name>` | MySQL schema | <which analysis needs schema verification> |
201
+ | `<library@version>` | Library docs (`mcp__test-context7`) | <to confirm API signatures> |
202
+ | `<aws-doc-keyword>` | AWS knowledge base | <for design verification> |
203
203
  | `/Volumes/.../app/<sibling-project>/<path>` | Cross-project file | <reference impl> |
204
204
 
205
- 자원 없음이 명확하면 본 섹션을 `_N/A_`로 표시.
205
+ If it's clear there are no resources, mark this section `_N/A_`.
206
206
 
207
207
  ---
208
208
 
209
209
  ## Related Tasks
210
210
 
211
211
  <!--
212
- 관계 라벨을 반드시 명시: blocker | blocked-by | sibling | follow-up | duplicate | shares-codepath
212
+ You must specify a relation label: blocker | blocked-by | sibling | follow-up | duplicate | shares-codepath
213
213
  -->
214
214
 
215
215
  | Task | Relation | Note |
216
216
  |------|----------|------|
217
- | `DEV-XXXX` | `sibling` | 같은 epic, 같은 코드베이스, 동시 변경 가능성 |
218
- | `DEV-YYYY` | `blocker` | 이 task는 DEV-YYYY 완료 후에만 시작 가능 |
217
+ | `DEV-XXXX` | `sibling` | same epic, same codebase, possible concurrent changes |
218
+ | `DEV-YYYY` | `blocker` | this task can start only after DEV-YYYY completes |
219
219
 
220
220
  ---
221
221
 
222
222
  ## Definition of Done (for this run)
223
223
 
224
224
  <!--
225
- Requested Outcome은 큰 그림. 여기서는 "이 run의 산출물이 충족해야 할 검증 가능한 조건"을 적습니다.
225
+ Requested Outcome is the big picture. Here you write "the verifiable conditions this run's output must satisfy."
226
226
  -->
227
227
 
228
- 이 run의 final report는 다음을 모두 충족해야 합니다:
228
+ This run's final report must satisfy all of the following:
229
229
 
230
- - [ ] <결정 항목 1에 대한 명시적 답변 또는 "결정 불가 + 이유">
231
- - [ ] <결정 항목 2에 대한 명시적 답변>
232
- - [ ] <남은 blocking question 목록>
230
+ - [ ] <explicit answer to decision item 1, or "undecidable + reason">
231
+ - [ ] <explicit answer to decision item 2>
232
+ - [ ] <list of remaining blocking questions>
233
233
  - [ ] <recommended next phase + reasoning>
234
234
 
235
235
  ---
@@ -237,13 +237,13 @@ Requested Outcome은 큰 그림. 여기서는 "이 run의 산출물이 충족해
237
237
  ## Questions for Workers
238
238
 
239
239
  <!--
240
- P0(반드시 답해야 함) / P1(가능하면 답) / P2(보너스)로 우선순위 명시.
240
+ Specify priority as P0 (must answer) / P1 (answer if possible) / P2 (bonus).
241
241
  -->
242
242
 
243
- 1. **[P0]** <핵심 질문 1>
244
- 2. **[P0]** <핵심 질문 2>
245
- 3. **[P1]** <보조 질문>
246
- 4. **[P2]** <탐색적 질문>
243
+ 1. **[P0]** <key question 1>
244
+ 2. **[P0]** <key question 2>
245
+ 3. **[P1]** <secondary question>
246
+ 4. **[P2]** <exploratory question>
247
247
 
248
248
  ---
249
249
 
@@ -261,26 +261,26 @@ P0(반드시 답해야 함) / P1(가능하면 답) / P2(보너스)로 우선순
261
261
  ## Notes for Lead (synthesis emphasis)
262
262
 
263
263
  <!--
264
- 워커 셀렉션(어느 모델을 쓸지)은 task-manifest.json의 recommendedWorkers에서 자동 결정되므로 여기에 적지 마세요.
265
- 이 섹션은 *합성 시 강조점*만 다룹니다.
264
+ Worker selection (which model to use) is decided automatically from recommendedWorkers in task-manifest.json, so don't write it here.
265
+ This section covers *synthesis emphasis* only.
266
266
  -->
267
267
 
268
- - **Synthesis priority**: <e.g. 안전성 vs 속도, public/private 경계 정확성, backward compat>
269
- - **Where worker disagreement matters most**: <consensus가 가장 중요한 지점>
270
- - **Where reduced confidence is acceptable**: <탐색 영역 — 가설만 나와도 충분>
268
+ - **Synthesis priority**: <e.g. safety vs speed, public/private boundary accuracy, backward compat>
269
+ - **Where worker disagreement matters most**: <the point where consensus matters most>
270
+ - **Where reduced confidence is acceptable**: <exploratory areas — a hypothesis alone is enough>
271
271
 
272
272
  ---
273
273
 
274
274
  ## Brief Hygiene Checklist
275
275
 
276
- 작성 후 자가 점검:
277
-
278
- - [ ] 모든 외부 링크에 대해 inline 발췌가 박혀 있다
279
- - [ ] Domain Glossary에 코드베이스 무지식 워커가 알아야 할 용어가 모두 있다
280
- - [ ] Out of Scope가 명시적으로 적혀 있다
281
- - [ ] Task-Type Focus의 해당 블록만 남아 있다 (다른 블록은 삭제됨)
282
- - [ ] error-analysis라면 Reproduction Steps가 채워져 있다
283
- - [ ] Definition of Done이 검증 가능한 체크리스트 형태다
284
- - [ ] Configuration / Deployment 섹션은 해당 시에만 내용이 있고, 무관 시 `_N/A_`로 닫혀 있다
285
- - [ ] 한글/영문/원어 ticket title 모두 식별 가능하다
286
- - [ ] Related Tasks에 관계 라벨이 명시되어 있다
276
+ Self-check after writing:
277
+
278
+ - [ ] Every external link has an inline excerpt embedded
279
+ - [ ] The Domain Glossary has every term a codebase-blind worker needs to know
280
+ - [ ] Out of Scope is written explicitly
281
+ - [ ] Only the relevant block of Task-Type Focus remains (the other block is deleted)
282
+ - [ ] If error-analysis, Reproduction Steps are filled in
283
+ - [ ] Definition of Done is a verifiable checklist
284
+ - [ ] The Configuration / Deployment section has content only when applicable, and is closed with `_N/A_` when irrelevant
285
+ - [ ] The ticket title is identifiable in Korean/English/original language
286
+ - [ ] Related Tasks have relation labels specified
@@ -20,7 +20,7 @@ taskType: "{{FM_TASK_TYPE}}"
20
20
  - Task ID:
21
21
  - Related Tasks:
22
22
  - Issue / Ticket:
23
- - 값이 비면 워커는 `Task ID`로 폴백한다 (prefix 없이 `8852`처럼). 한 run이 여러 ticket을 동시에 다루면 콤마로 구분 (`TICKET-123, TICKET-456`). 어느 쪽으로도 식별 불가하면 `unknown`을 허용한다.
23
+ - If left empty, workers fall back to the `Task ID` (without a prefix, like `8852`). When a single run handles multiple tickets at once, separate them with commas (`TICKET-123, TICKET-456`). If neither can be identified, `unknown` is allowed.
24
24
  - Task Type: `error-analysis`
25
25
  - Requested Outcome:
26
26
 
@@ -2,24 +2,24 @@
2
2
  ---
3
3
  unit-id: {{UNIT_ID}}
4
4
  domain: {{DOMAIN}}
5
- <!-- depends-on 예: [unit-001] (의존 없으면 []) -->
5
+ <!-- depends-on example: [unit-001] (use [] if there are no dependencies) -->
6
6
  depends-on: {{DEPENDS_ON}}
7
7
  recommended-next-phase: {{NEXT_PHASE}}
8
8
  ---
9
9
 
10
10
  # Fan-out Unit: {{UNIT_ID}} ({{DOMAIN}})
11
11
 
12
- > requirements-discovery fan-out 산출 packet. `okstra-run --task-brief <이 파일 경로>`
13
- > 로 새 task-key 를 시작한다. 이 파일은 그 run 의 입력 packet 이다.
12
+ > Packet produced by requirements-discovery fan-out. Start a new task-key with `okstra-run --task-brief <this file's path>`.
13
+ > This file is the input packet for that run.
14
14
 
15
15
  ## Scope
16
16
 
17
- <!-- 이 단위가 다루는 작업 항목 1개를 자족적으로 서술. 다른 단위와 섞지 말 것. -->
17
+ <!-- Self-contained description of the single work item this unit covers. Do not mix it with other units. -->
18
18
 
19
19
  ## Evidence
20
20
 
21
- <!-- path:line 근거. requirements-discovery 가 file inspection 으로 확인한 위치. -->
21
+ <!-- path:line evidence. Locations that requirements-discovery confirmed via file inspection. -->
22
22
 
23
23
  ## Depends-on rationale
24
24
 
25
- <!-- depends-on 에 적은 각 unit 에 왜 의존하는지 1줄씩. 없으면 _(none)_ -->
25
+ <!-- One line per unit listed in depends-on explaining why it depends on that unit. Use _(none)_ if there are none. -->
@@ -387,6 +387,73 @@ Carried-forward plan items retain their prior verdicts verbatim; each such item
387
387
  {% endfor %}
388
388
  {%- endif %}
389
389
 
390
+ ### 5.5.10 Implementation Design Preparation{% if t("implementationPlanning.designPreparation.heading") != "Implementation Design Preparation" %} ({{ t("implementationPlanning.designPreparation.heading") }}){% endif %}
391
+
392
+ - **{{ t("implementationPlanning.designPreparation.mode") }}:** `{{ implementationPlanning.designPreparation.mode }}`
393
+ - **{{ t("implementationPlanning.designPreparation.reason") }}:** {{ implementationPlanning.designPreparation.reason }}
394
+
395
+ {% if implementationPlanning.designPreparation["items"] | length == 0 -%}
396
+ {{ t("implementationPlanning.designPreparation.empty") }}
397
+ {%- else %}
398
+ {% for item in implementationPlanning.designPreparation["items"] %}
399
+ #### {{ item.id }} — {{ item.title }}
400
+
401
+ - **{{ t("implementationPlanning.designPreparation.kind") }}:** `{{ item.kind }}`
402
+ - **{{ t("implementationPlanning.designPreparation.status") }}:** `{{ item.status }}`
403
+ - **{{ t("implementationPlanning.designPreparation.stages") }}:** {{ item.stageRefs | join(", ") }}
404
+ - **{{ t("implementationPlanning.designPreparation.need") }}:** {{ item.need }}
405
+ {% if item.knownFacts %}
406
+ - **{{ t("implementationPlanning.designPreparation.knownFacts") }}:**
407
+ {% for fact in item.knownFacts %}
408
+ - {{ fact.statement }} — {{ fact.evidence }}
409
+ {% endfor %}
410
+ {% endif %}
411
+ {% if item.openQuestions %}
412
+ - **{{ t("implementationPlanning.designPreparation.openQuestions") }}:** {{ item.openQuestions | join("; ") }}
413
+ {% endif %}
414
+ - **{{ t("implementationPlanning.designPreparation.aiProposal") }}:** {{ item.aiProposal.summary }}
415
+ - **{{ t("implementationPlanning.designPreparation.proposalDetails") }}:** {{ item.aiProposal.details | join("; ") or t("implementationPlanning.designPreparation.none") }}
416
+ - **{{ t("implementationPlanning.designPreparation.proposalAssumptions") }}:** {{ item.aiProposal.assumptions | join("; ") or t("implementationPlanning.designPreparation.none") }}
417
+ - **{{ t("implementationPlanning.designPreparation.proposalEvidence") }}:** {{ item.aiProposal.evidence | join("; ") or t("implementationPlanning.designPreparation.none") }}
418
+ - **{{ t("implementationPlanning.designPreparation.proposalConfidence") }}:** `{{ item.aiProposal.confidence }}`
419
+ - **{{ t("implementationPlanning.designPreparation.humanConfirmation") }}:**
420
+ - **{{ t("implementationPlanning.designPreparation.confirmationRequired") }}:** `{% if item.humanConfirmation.required %}yes{% else %}no{% endif %}`
421
+ - **{{ t("implementationPlanning.designPreparation.confirmationReason") }}:** {{ item.humanConfirmation.reason }}
422
+ - **{{ t("implementationPlanning.designPreparation.suggestedAction") }}:** {{ item.humanConfirmation.suggestedAction }}
423
+ {% if item.replanTriggerFields %}
424
+ - **{{ t("implementationPlanning.designPreparation.replanTriggerFields") }}:** `{{ item.replanTriggerFields | join("`, `") }}`
425
+ {% endif %}
426
+ {% if item.workingAssumption %}
427
+ - **{{ t("implementationPlanning.designPreparation.workingAssumption") }}:** {{ item.workingAssumption }}
428
+ {% endif %}
429
+ {% if item.guardrails %}
430
+ - **{{ t("implementationPlanning.designPreparation.guardrails") }}:** {{ item.guardrails | join("; ") }}
431
+ {% endif %}
432
+ {% if item.reviewAt %}
433
+ {% if item.reviewAt.stage %}
434
+ - **{{ t("implementationPlanning.designPreparation.reviewAt") }}:** {{ item.reviewAt.phase }} — stage {{ item.reviewAt.stage }}
435
+ {% else %}
436
+ - **{{ t("implementationPlanning.designPreparation.reviewAt") }}:** {{ item.reviewAt.phase }}
437
+ {% endif %}
438
+ {% endif %}
439
+ {% if item.ifStillOpen %}
440
+ - **{{ t("implementationPlanning.designPreparation.ifStillOpen") }}:** `{{ item.ifStillOpen }}`
441
+ {% endif %}
442
+ {% if item.requestPath %}
443
+ - **{{ t("implementationPlanning.designPreparation.requestPath") }}:** `{{ item.requestPath }}`
444
+ {% endif %}
445
+ {% if item.blockReason %}
446
+ - **{{ t("implementationPlanning.designPreparation.blockReason") }}:** {{ item.blockReason }}
447
+ {% endif %}
448
+ {% if item.requiredDecision %}
449
+ - **{{ t("implementationPlanning.designPreparation.requiredDecision") }}:** {{ item.requiredDecision }}
450
+ {% endif %}
451
+ {% if item.notApplicableReason %}
452
+ - **{{ t("implementationPlanning.designPreparation.notApplicableReason") }}:** {{ item.notApplicableReason }}
453
+ {% endif %}
454
+ {% endfor %}
455
+ {%- endif %}
456
+
390
457
  {% endif %}
391
458
  {% if header.taskType == 'release-handoff' %}
392
459
  ## 5.6 Release Handoff Deliverables
@@ -29,18 +29,18 @@ taskType: "{{FM_TASK_TYPE}}"
29
29
  - What was supposed to be delivered?
30
30
  - What is the intended acceptance decision?
31
31
 
32
- ## 검증 모드
32
+ ## Verification Mode
33
33
 
34
- - 기본은 **전체-task** 검증입니다(`--stage auto`): 모든 Stage Map stage 가 구현·머지된 뒤 한 번 실행합니다.
35
- - 특정 stage 만 격리 검증하려면 `--stage N` 으로 **단독-stage** 모드를 씁니다(release-handoff 진입 불가, 부분 검증).
36
- - worktree / base / head 는 okstra 가 registry 와 `consumers.jsonl` 에서 자동 해소하므로 이 입력서에 수동 기입하지 않습니다.
34
+ - The default is **whole-task** verification (`--stage auto`): it runs once after every Stage Map stage has been implemented and merged.
35
+ - To verify only a specific stage in isolation, use **single-stage** mode with `--stage N` (cannot enter release-handoff; partial verification).
36
+ - okstra automatically resolves worktree / base / head from the registry and `consumers.jsonl`, so do not fill them in manually in this input sheet.
37
37
 
38
38
  ## Source Implementation Report
39
39
 
40
40
  - Path (project-relative) to the originating `implementation` final-report:
41
41
  - Quoted `Commit list` / `Diff summary` excerpt from the implementation report:
42
42
 
43
- > 보고서 경로가 비거나 누락된 보고서를 가리키면 final-verification 은 status `blocked` 으로 끝내고 `implementation` 또는 `implementation-planning` 으로 라우팅합니다. 검증 대상(worktree/base)은 okstra 가 자동 해소하므로 수동 기입이 어긋나 막히는 일은 없습니다.
43
+ > If the report path is empty or points to a missing report, final-verification ends with status `blocked` and routes to `implementation` or `implementation-planning`. The verification target (worktree/base) is resolved automatically by okstra, so a mismatched manual entry cannot cause a block.
44
44
 
45
45
  ## Requirement Coverage Source
46
46
 
@@ -49,7 +49,7 @@ taskType: "{{FM_TASK_TYPE}}"
49
49
  - Requirement IDs / acceptance IDs to verify:
50
50
  - Requirements intentionally excluded from this verification:
51
51
 
52
- > final-verification 은 위 source 의 각 requirement / acceptance id 마다 Validation Evidence 에 artifact 를 cite 해야 한다. source 가 비면 brief 의 `## Acceptance Criteria` 를 기본 source 로 사용한다.
52
+ > final-verification MUST cite an artifact in Validation Evidence for each requirement / acceptance id in the source above. If the source is empty, use the brief's `## Acceptance Criteria` as the default source.
53
53
 
54
54
  ## Verification Evidence
55
55
 
@@ -129,6 +129,37 @@
129
129
  "decision": "Decision",
130
130
  "consequences": "Consequences",
131
131
  "alternativesConsidered": "Alternatives Considered"
132
+ },
133
+ "designPreparation": {
134
+ "heading": "Implementation Design Preparation",
135
+ "mode": "Mode",
136
+ "reason": "Reason",
137
+ "kind": "Kind",
138
+ "status": "Status",
139
+ "stages": "Stages",
140
+ "need": "Need",
141
+ "knownFacts": "Known facts",
142
+ "openQuestions": "Open questions",
143
+ "aiProposal": "AI proposal",
144
+ "proposalDetails": "Details",
145
+ "proposalAssumptions": "Assumptions",
146
+ "proposalEvidence": "Evidence",
147
+ "proposalConfidence": "Confidence",
148
+ "humanConfirmation": "Human confirmation",
149
+ "confirmationRequired": "Required",
150
+ "confirmationReason": "Confirmation reason",
151
+ "suggestedAction": "Suggested action",
152
+ "replanTriggerFields": "Replan trigger fields",
153
+ "workingAssumption": "Working assumption",
154
+ "guardrails": "Guardrails",
155
+ "reviewAt": "Review at",
156
+ "ifStillOpen": "If still open",
157
+ "requestPath": "Request path",
158
+ "blockReason": "Block reason",
159
+ "requiredDecision": "Required decision",
160
+ "notApplicableReason": "Not applicable reason",
161
+ "none": "(none)",
162
+ "empty": "No implementation design preparation items."
132
163
  }
133
164
  },
134
165
  "releaseHandoff": {