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
@@ -10,9 +10,9 @@ The data.json schema is `schemas/final-report-v1.0.schema.json`. The renderer +
10
10
 
11
11
  Two `frontmatter` approval fields are always emitted with their unset default — never pre-fill them: `frontmatter.approved` is emitted as `false`, and `frontmatter.implementationOption` is emitted as an empty string `""`. The user later flips `approved` to `true` (via `--approve` or manual edit) and fills `implementationOption` with the chosen Option Candidate name (via `--implementation-option <name>` or manual edit) to authorise and scope the next `implementation` run.
12
12
 
13
- If you are reading this contract **as the report-writer worker**, YOU are the one writing the data.json and invoking the renderer through the available execution interface. Do not return either artifact inline — the files on disk are the canonical record.
13
+ **As the report-writer worker:** YOU write the data.json and invoke the renderer; the files on disk are the canonical record, so do not return either artifact inline.
14
14
 
15
- If you are reading this contract **as the lead**, your job in Phase 6 is to prepare the report-writer prompt, dispatch the Report writer worker per the Phase 6 dispatch template in okstra-lead-contract.md, and review both files in Phase 7. Do not call `write_artifact` against either report path yourself when Report writer worker is in the roster.
15
+ **As the lead:** prepare the report-writer prompt, dispatch the Report writer worker per the Phase 6 dispatch template in okstra-lead-contract.md, and review both files in Phase 7. Do not call `write_artifact` against either report path yourself when Report writer worker is in the roster.
16
16
 
17
17
  ## When to Use
18
18
 
@@ -45,7 +45,7 @@ The prompt MUST include, in this order at the top:
45
45
  8. The full `[Required reading]` clause (see [team-contract](./team-contract.md)) — for Phase 6 it adds two **per-task-type, instruction-set-local** read-only files, both scoped to this run's task-type by `okstra-ctl` at prep time:
46
46
  - `<instruction-set>/final-report-schema.json` — a task-type excerpt of the data.json schema (the other task-types' deliverable blocks and their unreachable `$defs` are stripped; ~38% of the full schema is `$defs` alone). This is your authoring contract for the data.json shape. Do **NOT** pull the full `schemas/final-report-v1.0.schema.json` — it carries all task-types and its `schemas/...` path is not part of the task bundle. (Validation still runs against the full schema post-hoc via the renderer, so the excerpt never relaxes the contract.)
47
47
  - `<instruction-set>/final-report-template.md` — the **phase-stripped** template (every other task-type's §5.x deliverable block removed by `render.py`'s `_strip_phase_blocks`, leaving only your run's §5.x). Do **NOT** also pull the full `templates/reports/final-report.template.md` source (it re-adds ~330 lines of other phases' deliverables and is not in the task bundle).
48
- 9. A one-line MCP pointer instead of the verbatim block — `**MCP servers:** follow the task brief's "## Available MCP Servers" section (already in your Required reading).` The brief is already in the report-writer's Required reading (item 8), so the verbatim block is redundant.
48
+ 9. A one-line MCP pointer instead of the verbatim block (redundant the brief is already in the report-writer's Required reading, item 8): `**MCP servers:** follow the task brief's "## Available MCP Servers" section (already in your Required reading).`
49
49
  10. The convergence classifications (Full/Partial/Contested/Worker-Unique), the round history data (`roundHistory[]`), the `round2SkippedReason` value, and pointers to all worker result files under `worker-results/`. The report-writer worker populates `crossVerification.roundHistory` in the data.json so Section 6 can show which rounds executed, queue sizes, and why Round 2 was (or was not) skipped. The renderer prints the full per-round table only when more than one round ran; single-round or zero-round histories are auto-collapsed to a one-line summary.
50
50
  11. `**Report Language:** <en|ko>` — must be either `en` or `ko`; `auto`
51
51
  has been resolved by the lead from project.json / global config
@@ -53,6 +53,9 @@ The prompt MUST include, in this order at the top:
53
53
  into `data.json.meta.reportLanguage`.
54
54
  12. For implementation-planning runs: a literal block listing the 10 required English section headings (`Option Candidates`, `Trade-off`, `Recommended Option`, `Stepwise Execution Order`, `Dependency`, `Validation Checklist`, `Rollback`, `User Approval Request`, `Plan Body Verification`, `Implementation Design Preparation`). The writer uses these exact substrings as section headings (Korean translation in parentheses is allowed), and the `Plan Body Verification` section carries its required `Gate result:` line.
55
55
  13. An explicit instruction: `You are the author of TWO files: (a) the final-report data.json at <Result Path>, (b) the worker-results audit file at <Worker Result Path>. After writing the data.json, invoke "okstra render-final-report <Result Path>" through the available execution interface so the markdown sibling is rendered before you return. Do not return the report inline. The validator fails the run when (a)'s schema validation fails, when the rendered markdown is absent, or when (b) is missing.`
56
+ 14. The prose budget (dedup contract): `verdictCard.finalConclusion` is the conclusion SSOT — at most 3 sentences. `rationale.*` fields stay within 2 sentences each and reference the verdict card / row IDs instead of restating their prose; `readerSummary` fields are one line each; `summary` stays at 3-5 rows unless the run covers multiple tickets. The schema field descriptions carry the same budgets (`tests/contract/test_report_prose_budget.py` guards both surfaces). Generation time scales with output volume, so exceeding the budget is a cost bug, not extra diligence.
57
+
58
+ **Fix-run incremental authoring (applies when the run's profile carries a "Fix-Run Carry" block).** Do not author the data.json from scratch. Start by copying the previous run's data.json (the `Previous report` path in the Fix-Run Carry block) to this run's Result Path, then update ONLY the blocks the fix run changed: `meta`/`header` (run seq, dates), `executionStatus`, `implementation.verifierResults`, `implementation.validationEvidence`, `implementation.commitList` / `diffSummary`, `crossVerification`, `verdictCard`, `finalVerdict`, and any `evidence` rows the fix touched. Deliverable prose for unchanged sections is carried forward verbatim — do not re-generate it. Then invoke the renderer exactly as in a full run. The schema validation and renderer contract are unchanged, so an incrementally-authored data.json passes the same post-hoc gates. The lead's dispatch prompt MUST include the previous data.json path when the carry block is present.
56
59
 
57
60
  **Completion detection after dispatch (BLOCKING).** A dispatch acknowledgement is NOT completion — detect completion via the SSOT protocol in [team-contract](./team-contract.md) "Worker-completion detection", with a one-entry pending set covering the data.json (Result Path) and the worker-results file (Worker Result Path). Do NOT end the turn with a prose "waiting for the report" statement.
58
61
 
@@ -100,11 +103,11 @@ The four Phase 7 steps below MUST execute in this exact order. Reordering them i
100
103
 
101
104
  Output (idempotent — re-running overwrites):
102
105
  - `runs/<task-type>/reports/final-report-<task-type>-<seq>.html` — single-file self-contained human view, **generated when the report has at least one §1 `C-*` clarification row OR an implementation-planning Plan Approval widget target** (a sibling `final-report-*.data.json` carrying `implementationPlanning.optionCandidates`). Clarification rows with `Status` ∈ {`open`, `answered`} embed form widgets (`<select>` for enum-style decisions, `<input>` for material / data-point kinds, `<textarea>` fallback); an `Export user response` button serialises form values to a markdown sidecar (schema in [`templates/reports/user-response.template.md`](../../templates/reports/user-response.template.md)) and downloads it as `user-response-<task-type>-<seq>.md`; the user saves it to `runs/<task-type>/user-responses/` (the renderer pre-creates that directory), and `--resume-clarification` auto-appends every sidecar found there to the next run's `clarification-response.md` (`clarification_items.clarification_response_with_sidecars`). The original final-report MD is **never** mutated by user input — the sidecar is the single write target.
103
- - implementation-planning 보고서에는 본문 끝에 **Plan Approval** 섹션(구현 옵션 `<select>` + 승인 체크박스) 렌더된다 — §1 `Blocks: approval` 행이 미해소면 disabled. 승인을 체크하고 Export 하면 sidecar 본문에 `## APPROVAL` 블록이 실리고, implementation 시작 마법사의 approve-confirm 단계가 그것을 감지해 사용자 확인 기존 `--approve` / `--implementation-option` 경로로 적용한다.
106
+ - the implementation-planning report renders a **Plan Approval** section at the end of the body (implementation-option `<select>` + an approval checkbox) — disabled while any §1 `Blocks: approval` row is unresolved. Checking approval and exporting embeds a `## APPROVAL` block in the sidecar body, and the implementation-start wizard's approve-confirm step detects it and, after user confirmation, applies it through the existing `--approve` / `--implementation-option` path.
104
107
  - When the report has **no** `C-*` clarification rows and is **not** a Plan Approval widget target, the html carries no interactive forms (it would only duplicate the MD), so the renderer prints `html: skipped (...)` and writes nothing. This is the expected state for such runs — `validators/validate-report-views.py` treats "no C-* rows + no approval target + no html" as a pass, not a missing artifact.
105
108
 
106
109
  This step runs after usage collection so token placeholders are substituted in any rendered html and before routing persistence so the html artifact, when generated, exists for the validator step that checks it.
107
- 3. **Complete routing and follow-up persistence.** Run the follow-up task spawner when Section 4 is non-empty. It turns the report's `## 4. Follow-up Tasks (후속 작업)` rows into `tasks/<task-group>/<new-task-id>/` stubs.
110
+ 3. **Complete routing and follow-up persistence.** Run the follow-up task spawner when Section 4 is non-empty. It turns the report's `## 4. Follow-up Tasks` rows into `tasks/<task-group>/<new-task-id>/` stubs.
108
111
 
109
112
  ```bash
110
113
  okstra spawn-followups \
@@ -131,7 +134,7 @@ The four Phase 7 steps below MUST execute in this exact order. Reordering them i
131
134
 
132
135
  ## Final Report Structure
133
136
 
134
- The final report follows the structure encoded in `schemas/final-report-v1.0.schema.json`. The schema is the single source of truth for section names, row shapes, enum values, and task-type-conditional blocks. The Jinja2 template `templates/reports/final-report.template.md` produces the human-readable form from any data.json that validates against the schema. The structure description below is a reading guide for writers; the schema is the binding contract.
137
+ The final report follows the structure encoded in `schemas/final-report-v1.0.schema.json` the single source of truth for section names, row shapes, enum values, and task-type-conditional blocks. The Jinja2 template `templates/reports/final-report.template.md` produces the human-readable form from any data.json that validates against the schema. The structure description below is a reading guide for writers; the schema is the binding contract.
135
138
 
136
139
  ### Report Header
137
140
 
@@ -151,7 +154,7 @@ Milestone 1 keeps the final-report schema unchanged. Read the exact permitted va
151
154
  ### Agent-Specific Execution Status Table
152
155
 
153
156
  ```markdown
154
- | Agent | Role | Model | Status | 처리 토큰 | 환산 토큰 | 비용 (USD) | Duration | Summary of Key Findings |
157
+ | Agent | Role | Model | Status | Raw tokens | Billable tokens | Cost (USD) | Duration | Summary of Key Findings |
155
158
  |-------|------|-------|--------|-----------|-----------|------------|----------|------------------------|
156
159
  | <team-state.lead.agent> | <team-state.lead.role> | <model> | completed | <tokens> | <billable> | <cost> | <duration> | Final synthesis status |
157
160
  | <team-state.workers[].agent> | <team-state.workers[].role> | <model> | <status> | <tokens> | <billable> | <cost> | <duration> | Key findings summary |
@@ -160,10 +163,10 @@ Milestone 1 keeps the final-report schema unchanged. Read the exact permitted va
160
163
  Table Generation Rules:
161
164
  - The first row derives its agent identifier and role from `team-state.lead.agent` / `team-state.lead.role` and its usage data from `leadUsage`; subsequent rows follow `recommendedWorkers` / `resultContract.requiredWorkerRoles` order.
162
165
  - Every worker agent identifier and role derives from its persisted team-state entry; the common contract does not infer labels from provider names.
163
- - **처리 토큰** = `usage.totalTokens` (input + output + cache_creation + cache_read; the raw volume processed).
164
- - **환산 토큰** = `usage.billableEquivalentTokens` (cache reads weighted at 0.1×, cache_creation 1.25×, output 5×; useful as a single number for "how big was this session in cost terms").
165
- - **비용 (USD)** = `usage.estimatedCostUsd`. For Codex/Antigravity workers that actually invoked the CLI, append `(+ CLI $X.XX)` from `usage.cliEstimatedCostUsd`.
166
- - For Codex/Antigravity workers, append `(CLI: <cliTotalTokens>)` to the 처리 토큰 cell when `usage.cliTotalTokens` is set.
166
+ - **Raw tokens** = `usage.totalTokens` (input + output + cache_creation + cache_read; the raw volume processed).
167
+ - **Billable tokens** = `usage.billableEquivalentTokens` (cache reads weighted at 0.1×, cache_creation 1.25×, output 5×; useful as a single number for "how big was this session in cost terms").
168
+ - **Cost (USD)** = `usage.estimatedCostUsd`. For Codex/Antigravity workers that actually invoked the CLI, append `(+ CLI $X.XX)` from `usage.cliEstimatedCostUsd`.
169
+ - For Codex/Antigravity workers, append `(CLI: <cliTotalTokens>)` to the Raw tokens cell when `usage.cliTotalTokens` is set.
167
170
  - Status values are retrieved from team-state; format duration as `Xm Ys` from `usage.durationMs`.
168
171
  - Workers with status `not-run` or unavailable usage evidence show `--` for tokens/cost/duration; quote the `note` underneath the table if useful.
169
172
 
@@ -194,9 +197,9 @@ Token Summary Generation Rules:
194
197
  CLI `--report-language` flag is given.
195
198
  - All values come from `usageSummary` (populated by `scripts/okstra-token-usage.py` at the start of Phase 7). Do not estimate or invent.
196
199
  - **Lead** row: `usageSummary.leadTotalTokens` / `usageSummary.leadBillableEquivalentTokens` / `usageSummary.estimatedCostUsd.lead`.
197
- - **Worker subtotal** (ko: `Worker 합계`) row: `usageSummary.workerTotalTokens` / `usageSummary.workerBillableEquivalentTokens` / `usageSummary.estimatedCostUsd.claudeWorkers`.
198
- - **Grand total** (ko: `전체 합계`) row: `usageSummary.grandTotalTokens` / `usageSummary.grandBillableEquivalentTokens` / sum of `lead + claudeWorkers`.
199
- - **Codex/Antigravity CLI add-on** (ko: `Codex/Antigravity CLI 추가 비용`) row: `usageSummary.estimatedCostUsd.cliWorkers`. If 0, still show the row so the reader sees that no CLI work was billed under those providers (or that CLI fallback occurred).
200
+ - **Worker subtotal** row: `usageSummary.workerTotalTokens` / `usageSummary.workerBillableEquivalentTokens` / `usageSummary.estimatedCostUsd.claudeWorkers`.
201
+ - **Grand total** row: `usageSummary.grandTotalTokens` / `usageSummary.grandBillableEquivalentTokens` / sum of `lead + claudeWorkers`.
202
+ - **Codex/Antigravity CLI add-on** row: `usageSummary.estimatedCostUsd.cliWorkers`. If 0, still show the row so the reader sees that no CLI work was billed under those providers (or that CLI fallback occurred).
200
203
  - Format tokens with comma separators (e.g., `32,500`); format USD with two decimals (e.g., `$1.43`).
201
204
  - If `lead` or any `worker.usage` records unavailable evidence, show `--` for that row and append a one-line note (`reason: <note>`).
202
205
  - If pricing for a model is unknown, the script omits `estimatedCostUsd` for that block — show `N/A` in that column and add a note like `pricing missing for model <model>`.
@@ -207,32 +210,32 @@ When the run's `task-type` is `implementation-planning`, the final report MUST c
207
210
 
208
211
  | # | Required substring | Recommended heading form |
209
212
  |---|--------------------|--------------------------|
210
- | 1 | `Option Candidates` | `### Option Candidates (옵션 후보)` |
211
- | 2 | `Trade-off` | `### Trade-off Matrix (트레이드오프 매트릭스)` |
212
- | 3 | `Recommended Option` | `### Recommended Option (권장 옵션)` |
213
- | 4 | `Stepwise Execution Order` | `### Stepwise Execution Order (단계별 실행 순서)` |
214
- | 5 | `Dependency` | `### Dependency / Migration Risk (의존성·마이그레이션 위험)` |
215
- | 6 | `Validation Checklist` | `### Validation Checklist (검증 체크리스트)` |
216
- | 7 | `Rollback` | `### Rollback Strategy (롤백 전략)` |
217
- | 8 | `User Approval Request` | Satisfied by the top-of-report `## User Approval Request (사용자 승인 게이트)` block. Do NOT recreate a `### 5.5.8 User Approval Request` body stub — the validator now fails reports that contain one. |
218
- | 9 | `Plan Body Verification` + `Gate result:` | `### Plan Body Verification (계획 본문 검증)` containing a `Gate result:` line — copy `templates/reports/final-report.template.md §5.5.9` verbatim. Validator checks both substrings. |
219
- | 10 | `Implementation Design Preparation` | `### Implementation Design Preparation (구현 설계 준비)` — rendered from `implementationPlanning.designPreparation` by `templates/reports/final-report.template.md §5.5.10`. |
213
+ | 1 | `Option Candidates` | `### Option Candidates (Korean gloss)` |
214
+ | 2 | `Trade-off` | `### Trade-off Matrix (Korean gloss)` |
215
+ | 3 | `Recommended Option` | `### Recommended Option (Korean gloss)` |
216
+ | 4 | `Stepwise Execution Order` | `### Stepwise Execution Order (Korean gloss)` |
217
+ | 5 | `Dependency` | `### Dependency / Migration Risk (Korean gloss)` |
218
+ | 6 | `Validation Checklist` | `### Validation Checklist (Korean gloss)` |
219
+ | 7 | `Rollback` | `### Rollback Strategy (Korean gloss)` |
220
+ | 8 | `User Approval Request` | Satisfied by the top-of-report `## User Approval Request (User Approval Gate)` block. Do NOT recreate a `### 5.5.8 User Approval Request` body stub — the validator now fails reports that contain one. |
221
+ | 9 | `Plan Body Verification` + `Gate result:` | `### Plan Body Verification (Korean gloss)` containing a `Gate result:` line — copy `templates/reports/final-report.template.md §5.5.9` verbatim. Validator checks both substrings. |
222
+ | 10 | `Implementation Design Preparation` | `### Implementation Design Preparation (Korean gloss)` — rendered from `implementationPlanning.designPreparation` by `templates/reports/final-report.template.md §5.5.10`. |
220
223
 
221
224
  The Korean translation in parentheses is optional but the English keyword is mandatory. The body of each section is written in the Report Language per the writing rules below. For non-`implementation-planning` runs, omit this entire block — these headings are NOT validator-checked for other task-types.
222
225
 
223
226
  The final-report template `templates/reports/final-report.template.md` Section 5.5 already encodes this contract — copy that block verbatim and fill in.
224
227
 
225
- ### Self-fix rewrite (plan-body self-fix 라운드)
228
+ ### Self-fix rewrite (plan-body self-fix round)
226
229
 
227
- lead self-fix 라운드를 지시하면(대상 `P-*` 목록 + 결함 사유 전달), 지정된 planner-fixable 항목이 가리키는 **계획 섹션만** 교정한다 전체 draft 다시 쓰지 않는다:
230
+ When lead instructs a self-fix round (passing the target `P-*` list + the reason for each defect), correct **only the plan section** each designated planner-fixable item points todo NOT rewrite the entire draft:
228
231
 
229
- - 경로 축약 → `<PROJECT_ROOT>` 기준 전체 상대경로로 교체(File Structure / Stepwise `files`).
230
- - prose command → 작업 디렉터리·인자·task-type 포함된 실행 가능한 명령 시퀀스로 구체화.
231
- - placeholder(`stage-<N>`) → 구체 파일명·재생성 계획으로 교체.
232
- - requirement-coverage 매핑 오류실재하는 option/stage/step 또는 XP 행으로 재매핑.
233
- - missing/weak design-prep contract → kind-specific inline detail 또는 concrete `aiProposal` 을 가진 AI-prepared PREP item 으로 교정. 사용자·외부 권한 사실은 만들어내지 않고 `blocked` + request material 로 유지한다.
232
+ - abbreviated pathreplace with the full relative path from `<PROJECT_ROOT>` (File Structure / Stepwise `files`).
233
+ - prose command → make it concrete as an executable command sequence including the working directory, arguments, and task-type.
234
+ - placeholder (e.g. `stage-<N>`) → replace with concrete filenames / a regeneration plan.
235
+ - requirement-coverage mapping errorremap to a real option/stage/step or XP row.
236
+ - missing/weak design-prep contract → fix with kind-specific inline detail or an AI-prepared PREP item carrying a concrete `aiProposal`. Do NOT invent facts requiring user/external authority — keep them `blocked` + request material.
234
237
 
235
- 교정 해당 `planItems[].selfFixNote` 에 `self-fixed in round <N>: <무엇을 고쳤는지>` 남기고, `planBodyVerification.selfFixRoundApplied = true` 로 표시한다. `needs-user-input` 항목은 절대 교정 대상이 아니다그대로 clarification 으로 승격된다.
238
+ After correcting, leave `self-fixed in round <N>: <what was fixed>` in that `planItems[].selfFixNote` and mark `planBodyVerification.selfFixRoundApplied = true`. `needs-user-input` items are NEVER a correction target they are promoted to clarification as-is.
236
239
 
237
240
  ### Final-verification verdict token contract (BLOCKING)
238
241
 
@@ -272,34 +275,34 @@ Skipping this file because "the real report is in `reports/`" is wrong. Both fil
272
275
 
273
276
  ### Main Body Section
274
277
 
275
- Section numbering follows `templates/reports/final-report.template.md` exactly — that file is the documentation SSOT for section names and ordering. For full body structure at authoring time, consult your run's **phase-stripped** `final-report-template.md` (the instruction-set copy of the same template, with other task-types' §5.x deliverable blocks removed); the "copy that block verbatim" references below mean the §-block as it appears in that stripped copy, not a re-read of the full source.
278
+ Section numbering follows `templates/reports/final-report.template.md` exactly — that file is the documentation SSOT for section names and ordering. For full body structure at authoring time, consult your run's **phase-stripped** `final-report-template.md` (the per-task-type instruction-set copy defined in Phase 6 dispatch item 8); the "copy that block verbatim" references below mean the §-block as it appears in that stripped copy, not a re-read of the full source.
276
279
 
277
280
  **Verdict Card (top-of-report, mandatory).** Render `## Verdict Card` between the report header and the (conditional) Approval block. Its `Verdict Token` / `Direction` / `Next Step` cells MUST byte-match the corresponding cells in `## 7. Final Verdict` and the first item of `## 6.`. Divergence is `contract-violated`.
278
281
 
279
- **Background and Rationale (top-of-report, mandatory — every task-type).** Fill the data.json `rationale` object (rendered as `## 작업 배경과 근거`, right after the Verdict Card). It is the reviewer-facing narrative that answers four questions, in order — write each as **prose**, not a table:
280
- - `motivation` — 작업을 하는가 (목표·맥락).
281
- - `problem` — 이게 문제인가 (현재 상태의 결함).
282
- - `approach` — 그래서 어떤 작업이 필요한가 (택한 방향).
283
- - `justification` — 이게 합리적 선택인가 (대안 대비, 근거).
282
+ **Background and Rationale (top-of-report, mandatory — every task-type).** Fill the data.json `rationale` object (rendered as `## Background and Rationale`, right after the Verdict Card). It is the reviewer-facing narrative that answers four questions, in order — write each as **prose**, not a table:
283
+ - `motivation` — why we are doing this work (goal / context).
284
+ - `problem` — why this is a problem (the flaw in the current state).
285
+ - `approach` — what work is therefore needed (the chosen direction).
286
+ - `justification` — why this is a reasonable choice (versus alternatives, with rationale).
284
287
 
285
- Every field MUST anchor its claim with at least one evidence reference — a `path:line`, an **in-report** ID (`C-001` / `E-006` / `§5.4`), or another cited source already present in this report. When the evidence is genuinely insufficient, say so explicitly (`근거 불충분<이유>`) instead of inventing one. `validators/validate-run.py` → `_validate_rationale_evidence` fails any field carrying neither a citation nor an insufficiency marker, so an ungrounded or fabricated rationale is rejected at validation time.
288
+ Every field MUST anchor its claim with at least one evidence reference — a `path:line`, an **in-report** ID (`C-001` / `E-006` / `§5.4`), or another cited source already present in this report. When the evidence is genuinely insufficient, say so explicitly (`insufficient evidence<reason>`) instead of inventing one. `validators/validate-run.py` → `_validate_rationale_evidence` fails any field carrying neither a citation nor an insufficiency marker, so an ungrounded or fabricated rationale is rejected at validation time.
286
289
 
287
290
  **Reader-facing prose MUST NOT cite a bare brief/worker-internal ID that this report never surfaces** — `RC-*` (reporter confirmations, defined in the brief), `RF-*` / `F-*` (findings, defined in worker-results) have no anchor in the final report, so a reader hits an opaque token with nothing to click. Either expand it inline (`the confirmed version target 1.27.47→1.27.48`) or, for an audit trail, namespace it (`claude:F-005`). **Enforced:** `_validate_no_opaque_id_references` fails a bare `RC-*` / `RF-*` / non-namespaced `F-*` appearing in `verdictCard` / `finalVerdict` / `rationale` / `clarificationItems[].statement`. (The renderer anchors + links in-report IDs of any digit width, so a surfaced `RC-4`-style id does resolve.) Do NOT restate the Verdict Card or the §5.4 trade-off matrix verbatim — this section is the *why*, in connected prose, that those tables compress.
288
291
 
289
292
  0. **Clarification Response Carried In** — render this `## 0.` heading ONLY when `{{CLARIFICATION_RESPONSE_RELATIVE_PATH}}` is non-empty. Walk every `C-*` row of the prior report's `## 1. Clarification Items` table, reconcile against new evidence, and record the outcome (`resolved` / `obsolete`) with citation before drafting the verdict. When no carry-in path was provided, OMIT the `## 0.` heading entirely — the validator fails an empty Section 0 stub. The lead calls `okstra incremental-scope` exactly once, combining answered-clarification stage impacts (`--impacted`) and changed PREP IDs (`--prep-items`); selected-option, Stage Map, or recommended-approach changes pass both CSVs empty to force full mode. Record that single decision JSON verbatim into `implementationPlanning.incrementalDecision` (`mode`, `reverifyStages`, `carryStages`, `reason`); the renderer emits the `### 0.1 Incremental Re-Verification Scope` audit block from it, and the validator fails an `incremental`-mode run whose Section 0 omits that block. In `incremental` mode this run's `planItems` MUST carry every plan-item id from the re-verified stages forward with its updated verdict; if re-verification concludes a plan item should be REMOVED, that is a signal the answer's blast radius is not local — do not drop it here, tell the lead to abandon incremental and re-route to a FULL re-verification, because the carry merge only adds prior items and would resurrect the removed item's stale verdict. After authoring the current data.json, call `okstra incremental-carry`, passing the decision's `carryStages` CSV to `--carry-stages` and its `reverifyStages` CSV to `--reverify-stages`. A `CarryError` means the stage/PREP ownership contract is unsafe: discard the partial merged output and route the run through full re-verification; never publish a partially merged report.
290
- 1. **Cross Verification Results** — 4 categories (Full / Partial / Contested / Worker-Unique) when convergence is enabled, per `convergence`. Prepend the Round History sub-table (columns: `Round | inputQueueSize | resolvedCount | carriedForwardCount | dispatches | skippedWorkers`) plus a `round2SkippedReason: <value>` note, pulled verbatim from `convergence-<task-type>-<seq>.json`. Empty contested list renders as `- 합의 미달 항목 없음.`. Convergence-disabled runs use the legacy Consensus/Differences format and omit the round table.
293
+ 1. **Cross Verification Results** — 4 categories (Full / Partial / Contested / Worker-Unique) when convergence is enabled, per `convergence`. Prepend the Round History sub-table (columns: `Round | inputQueueSize | resolvedCount | carriedForwardCount | dispatches | skippedWorkers`) plus a `round2SkippedReason: <value>` note, pulled verbatim from `convergence-<task-type>-<seq>.json`. Empty contested list renders as `- No items lacking consensus.`. Convergence-disabled runs use the legacy Consensus/Differences format and omit the round table.
291
294
  2. **Final Verdict** — `Direction` ∈ `continue-investigation` / `begin-implementation` / `approve` / `reject` / `hold`. **Verdict Token** is `not-applicable` for every task-type except `final-verification` — see "Final-verification verdict token contract" below for that case.
292
295
  3. **Evidence and Detailed Analysis** — primary evidence rows (file path, line, snippet); secondary evidence / alternate interpretations. If `reference-expectations.md` lists explicit expected values, record match/gap per row.
293
296
  4. **Missing Information and Risks** — uncertain / "I don't know" items. `implementation-planning` adds §5.5 (see heading contract below); `release-handoff` adds §5.6.
294
- 5. **Clarification Items** — single unified `C-*` table; column schema (4 columns with the short fields stacked in one record-meta cell), ID convention, and rerun behaviour are owned by `_common-contract.md §Clarification request policy` (SSOT). The deprecated `5.5.9 Open Questions` / `1.1 추가 자료 요청` / `1.2 사용자 확인 질문` sub-sections are removed; the validator fails reports that reintroduce them.
295
- 6. **Recommended Next Steps** — prioritized actions. After Phase 7's follow-up spawner runs, append a row per newly created task-key (see "Phase 6 → Phase 7 execution sequence" above). **Approval-gate consistency:** when §1 carries any `Blocks: approval` row with `Status` ∈ {open, answered}, the Verdict Card `Next Step` and the first recommended step MUST point to the clarification rerun (`resume-clarification` of the SAME task-type) — never to "frontmatter `approved: true` 플립 → `implementation` 직행". Run-prep enforces this gate (`run.py _validate_approved_plan` fail-closes on those rows and on a blocking data.json `gateResult`), so a direct-implementation next-step is an instruction the reader cannot actually follow. **Cross-project pointer rule:** cross-project 의존( repo / 다른 top-level 배포 모듈 / published 패키지) `crossProjectDependencies`(§5.4 Cross-Project Dependencies) authoritative — `recommendedNextSteps` 에는 substance(선행 작업·검증 신호·handoff) 복제하지 말고 섹션을 가리키는 포인터 줄만 둔다(이중 기록 금지).
297
+ 5. **Clarification Items** — single unified `C-*` table; column schema (4 columns with the short fields stacked in one record-meta cell), ID convention, and rerun behaviour are owned by `_common-contract.md §Clarification request policy` (SSOT). The deprecated `5.5.9 Open Questions` / `1.1 Additional Material Request` / `1.2 User Confirmation Questions` sub-sections are removed; the validator fails reports that reintroduce them.
298
+ 6. **Recommended Next Steps** — prioritized actions. After Phase 7's follow-up spawner runs, append a row per newly created task-key (see "Phase 6 → Phase 7 execution sequence" above). **Approval-gate consistency:** when §1 carries any `Blocks: approval` row with `Status` ∈ {open, answered}, the Verdict Card `Next Step` and the first recommended step MUST point to the clarification rerun (`resume-clarification` of the SAME task-type) — never to "flip frontmatter `approved: true` → jump straight to `implementation`". Run-prep enforces this gate (`run.py _validate_approved_plan` fail-closes on those rows and on a blocking data.json `gateResult`), so a direct-implementation next-step is an instruction the reader cannot actually follow. **Cross-project pointer rule:** for cross-project dependencies (another repo / a different top-level deployment module / a published package), `crossProjectDependencies` (§5.4 Cross-Project Dependencies) is authoritative — do NOT duplicate that substance (prerequisite work / verification signals / handoff) into `recommendedNextSteps`; put only a one-line pointer to that section (no double-recording).
296
299
  7. **Follow-up Tasks** — auto-spawn-eligible table. Each row drives `okstra-spawn-followups.py`; see template §7 for the row schema.
297
300
 
298
301
  **§5.10 Fix History (data-presence gated).** When the run-manifest carries a `fixCycleId`, fill the data.json `fixCycle` block (`cycle` / `targetReport` / `symptom` / `runs`). Read the values from the task root's `history/fix-cycles.jsonl`: `cycle` MUST equal `fixCycleId`, `targetReport` / `symptom` come from that cycle's `opened` row, and `runs` lists its attached `run` rows (`taskType` / `runSeq` / `runManifest`). The validator (`validators/validate-run.py` → `_validate_fix_cycle`) fails the run when the block is missing or `fixCycle.cycle` does not match `fixCycleId`. When the run-manifest has no `fixCycleId`, OMIT the `fixCycle` block entirely — the renderer omits §5.10.
299
302
 
300
303
  ### Writing Guidelines
301
304
 
302
- - Write in Markdown. **Prefer tables over prose bullet lists** for any section that enumerates multiple items with the same shape (evidence rows, risks, options, dependencies, rollback steps, follow-ups, open questions). Bullets are reserved for short, single-line standalone statements (e.g., "- 추가 정보 요청 없음."). When the template provides a table form, do NOT degrade it back to bullets in the rendered report. **Exception — `## 작업 배경과 근거` (`rationale`) is deliberately prose**: it is connected narrative explaining the *why*, not a same-shape enumeration, so write full sentences there rather than forcing it into a table.
305
+ - Write in Markdown. **Prefer tables over prose bullet lists** for any section that enumerates multiple items with the same shape (evidence rows, risks, options, dependencies, rollback steps, follow-ups, open questions). Bullets are reserved for short, single-line standalone statements (e.g., "- No additional information requested."). When the template provides a table form, do NOT degrade it back to bullets in the rendered report. **Exception — `## Background and Rationale` (`rationale`) is deliberately prose**: it is connected narrative explaining the *why*, not a same-shape enumeration, so write full sentences there rather than forcing it into a table.
303
306
  - Write the final report body in the language passed in **Report Language**
304
307
  above (`en` or `ko`). The template's fixed labels (section asides,
305
308
  empty-states, token summary, column headers, release-handoff labels)
@@ -311,7 +314,6 @@ Every field MUST anchor its claim with at least one evidence reference — a `pa
311
314
  validator-checked English substrings (`Option Candidates`,
312
315
  `Verdict Token`, `accepted`/`conditional-accept`/`blocked`, etc.)
313
316
  stay in English regardless of Report Language.
314
- - Keep technical identifiers such as file paths, code symbols, model names, and status values in their original form when needed.
315
317
  - If only one worker is usable, perform a reduced-confidence synthesis
316
318
  - If evidence is insufficient, explicitly state "I don't know"
317
319
  - If expected values are present in `reference-expectations.md`, list matches, gaps, and missing evidence separately
@@ -61,16 +61,7 @@ Only workers selected from `recommendedWorkers` in `task-manifest.json` and `res
61
61
 
62
62
  ## Worker Prompt Composition
63
63
 
64
- Every worker prompt MUST start with the following anchor headers, in this exact order, before any other content:
65
-
66
- 1. `**Project Root:** <absolute-path>` — absolute target project root (from `{{PROJECT_ROOT}}` in the lead's prompt). Required so the worker can self-anchor without relying on inherited cwd.
67
- 2. `**Prompt History Path:** <project-relative-path>`
68
- 3. `**Result Path:** <project-relative-path>` — canonical destination for the worker's result file. Workers resolve it to absolute against `**Project Root:**` and use it for the post-completion existence check (see CLI wrapper agents' step 8c, and Lead's redispatch policy below). The path identifies a single file; do NOT deliver a directory.
69
- 4. `Assigned worker prompt history path: <absolute-path>` — same as the prompt-history path but resolved against `Project Root`. Codex/Antigravity wrapper subagents extract this exact line.
70
- 5. `**Worker Preamble Path:** <absolute-path>` — points to `~/.okstra/templates/worker-prompt-preamble.md` (canonical SSOT for Required Reading + Error Reporting + Anchor / Output sections). Workers Read this file end-to-end before producing any output. This anchor replaces the ~80 lines of inlined `[Required reading]` / `[Error reporting]` boilerplate that earlier versions injected into every dispatch.
71
- 6. `**Coding preflight pack:** <absolute-path>` — points to the installed runtime resource pack under `<OKSTRA_HOME>/prompts/coding-preflight`. Implementation executors and verifiers use this to read `overview.md`, `clean-code.md`, and routed language/framework/architecture resources. Other worker roles may ignore it.
72
- 7. `**Errors log path:** <absolute-path>` — run-level errors JSONL.
73
- 8. `**Errors sidecar path:** <absolute-path>` — this worker's per-run sidecar JSON.
64
+ Every worker prompt MUST start with the anchor headers rendered by `okstra_ctl.worker_prompt_headers.worker_prompt_headers()` (the generating SSOT — never hand-author or reorder them). Their meaning and extraction rules for workers are documented in the worker preamble §"Anchor headers". Phase-specific extra headers (implementation worktree, final-verification target snapshot, improvement-discovery grilling log) are listed there too.
74
65
 
75
66
  The body must include: role name, task type, task key, required bundle paths, assigned model, output contract, evidence handling rules, and any relevant config/deployment expectations from `reference-expectations.md`.
76
67
 
@@ -78,17 +69,17 @@ When a worker reads any project-relative path from the prompt, it MUST resolve i
78
69
 
79
70
  If the task brief contains an `## Available MCP Servers` section, inject only the one-line pointer into every analysis worker's prompt (and into the report-writer prompt when it is dispatched in Phase 6) — the brief is already in every worker's [Required reading], so verbatim copy is redundant: `**MCP servers:** follow the task brief's "## Available MCP Servers" section (already in your Required reading).` Codex/Antigravity workers run external CLIs whose MCP availability is governed by their own CLI configs; they can record `MCP not available in this CLI` cleanly after reading that section in the brief.
80
71
 
81
- Before dispatching any required worker, lead persists the exact worker prompt to the assigned current-run prompt history path under `runs/<task-type>/prompts/`. Do not use `/tmp/*prompt*.txt` as the canonical artifact path.
72
+ Persist the exact worker prompt before dispatch per Operating Rule 6; never use `/tmp/*prompt*.txt` as the canonical artifact path.
82
73
 
83
- Send byte-identical dispatch prompts to every analysis worker (Claude / Codex / Antigravity), modulo the role label and the wrapper-specific path headers enumerated in the "Dispatch-prompt invariant" rule of the Role Definitions section. Per-worker emphasis in the body biases each worker toward its lens and silently kills convergence (see Role Definitions for the failure mode). Specialization lives in Section 6 of the worker output, not in the dispatch prompt body.
74
+ Send byte-identical dispatch prompts to every analysis worker per the "Dispatch-prompt invariant" (Role Definitions). Specialization lives in Section 6 of the worker output, not in the dispatch prompt body.
84
75
 
85
76
  ### Required Reading + Error Reporting via Worker Preamble (SSOT)
86
77
 
87
- The lead does NOT inline `[Required reading]` or `[Error reporting]` blocks into worker prompts. Both contracts live in a single canonical file at `~/.okstra/templates/worker-prompt-preamble.md` (source: `templates/worker-prompt-preamble.md`). The lead injects the path via the `**Worker Preamble Path:**` anchor header (header #5 above) and each worker Reads that file end-to-end before producing output.
78
+ The lead does NOT inline `[Required reading]` or `[Error reporting]` blocks into worker prompts. Both contracts live in a single canonical file at `~/.okstra/templates/worker-prompt-preamble.md` (source: `templates/worker-prompt-preamble.md`). The lead injects the path via the `**Worker Preamble Path:**` anchor header and each worker Reads that file end-to-end before producing output.
88
79
 
89
80
  What the lead MUST still do per dispatch:
90
81
  - Inject the input file enumeration into the dispatch prompt body via an `## Inputs` section (or any heading the recipient agent expects), listing the actual project-relative primary inputs derived from the run's `instruction-set/`. For analysis workers, list `analysis-packet.md` as the required primary input and list task-brief / analysis-profile / analysis-material / reference-expectations / clarification-response as source/fallback paths only when useful. The preamble describes the rules; the lead provides the specific paths for THIS run.
91
- - Inject the absolute `**Errors log path:**` and `**Errors sidecar path:**` headers (#7 and #8 above) — workers cannot synthesize these paths.
82
+ - Inject the absolute `**Errors log path:**` and `**Errors sidecar path:**` anchor headers — workers cannot synthesize these paths.
92
83
  - Omit the preamble pointer for reverify dispatches (Phase 5.5 lightweight mode) — see [convergence](./convergence.md) "Reverify prompt: required-reading suppression".
93
84
 
94
85
  Audience-scoped file enumeration (performance optimization — mandatory):
@@ -143,88 +134,12 @@ After each worker subagent returns (regardless of role), Lead MUST verify the ca
143
134
 
144
135
  ## Worker Output Contract
145
136
 
146
- **Authoritative source.** If other documents (okstra-lead-contract.md, worker agent definitions) disagree with this section, this section wins.
147
-
148
- ### Result Frontmatter (mandatory, precedes Section 1)
149
-
150
- Every worker result file MUST begin with a YAML frontmatter block. For analysis workers, values are sourced from `analysis-packet.md` frontmatter; fall back to `analysis-material.md` or `task-brief.md` only if the packet is missing a field. Report-writer can use `analysis-material.md` / `task-brief.md` as before. Copy values verbatim; do NOT regenerate them. Only `workerId` and `title` are worker-specific.
151
-
152
- ```yaml
153
- ---
154
- title: OKSTRA <Worker Role> Result - <task-key>
155
- id: "<task-key with ':' replaced by '-'>"
156
- aliases: ["<id>-<task-type>"]
157
- tags: ["worker-result", "<task-type>"]
158
- taskType: "<task-type>"
159
- workerId: "<claude|codex|antigravity|report-writer>"
160
- task-id: "<task-id>"
161
- task-group: "<task-group>"
162
- project-id: "<project-id>"
163
- date: <YYYY-MM-DD>
164
- ---
165
- ```
166
-
167
- Concrete example for a `claude-worker` result on task-key `fontsninja-classifier-v2:DEV-9388:DEV-9429` and task-type `implementation`:
168
-
169
- ```yaml
170
- ---
171
- title: OKSTRA Claude Worker Result - fontsninja-classifier-v2:DEV-9388:DEV-9429
172
- id: "fontsninja-classifier-v2-DEV-9388-DEV-9429"
173
- aliases: ["fontsninja-classifier-v2-DEV-9388-DEV-9429-implementation"]
174
- tags: ["worker-result", "implementation"]
175
- taskType: "implementation"
176
- workerId: "claude"
177
- task-id: "DEV-9429"
178
- task-group: "DEV-9388"
179
- project-id: "fontsninja-classifier-v2"
180
- date: 2026-05-15
181
- ---
182
- ```
183
-
184
- Rules:
185
- - `id` is the run's `task-key` with `:` replaced by `-`. It is a scalar string, NOT an array.
186
- - `aliases` is a YAML array containing a single value `"<id>-<task-type>"`.
187
- - `taskType` mirrors the run's task type (`requirements-discovery`, `error-analysis`, `implementation-planning`, `implementation`, `final-verification`, `release-handoff`).
188
- - `workerId` identifies which worker produced the file. Required values: `claude` / `codex` / `antigravity` / `report-writer`.
189
- - Other fields (`task-id`, `task-group`, `project-id`, `date`) MUST match the input files' frontmatter exactly. If the input frontmatter is missing or unreadable, the worker MUST record a `tool-failure` and stop instead of guessing.
190
-
191
- The same frontmatter contract applies to the `Report writer worker`'s final-report file — the report-writer copies these values from its inputs and only swaps `workerId` to `report-writer`.
192
-
193
- A successful worker result must include the following sections in this exact order, beneath the frontmatter block:
194
-
195
- > **Reading Confirmation lives in the audit sidecar, NOT in the main worker result.** Section 0 is intentionally absent from the main file. The worker writes Reading Confirmation to `runs/<task-type>/worker-results/<worker>-audit-<task-type>-<seq>.md` per the dispatch-prompt clause above; the validator FAILS any main worker-result file that contains a `## 0. Reading Confirmation` heading. If a file was skipped or only partially read, the worker MUST NOT produce sections 1–5 — instead it records a `tool-failure` in the errors sidecar and stops.
196
-
197
- 1. Findings
198
- 2. Missing Information or Assumptions
199
- 3. Safe or Reasonable Areas
200
- 4. Uncertain Points
201
- 5. Recommended Next Actions
202
- 6. **Specialization Lens (optional, worker-specific deep dive)** — additive content produced from this worker's specialization lens (see Role Definitions table). Items here are NOT subject to convergence cross-verification and MUST NOT duplicate sections 1–5. If the worker has nothing additional to add from its lens, omit Section 6 entirely or write `- No additional lens-specific findings.`
203
-
204
- **Sections 1–5 are the common core.** Every analysis worker (Claude / Codex / Antigravity) MUST cover the same set of dimensions in sections 1–5 — feasibility, requirement interpretation, hidden assumptions, alternatives, and execution risk — regardless of which model is producing the result. The point of running three models is to triangulate the same answer space, not to partition it. A worker that produces "Findings" populated only with items from its own lens (e.g. Codex only listing implementation-feasibility findings) is in breach of contract; convergence will treat coverage gaps as `verification-error`.
205
-
206
- **Section 6 is the only legal home for specialization.** When the worker has a depth-of-perspective contribution that genuinely sits outside the common core (e.g. a Codex-specific stack-trace decomposition, a Claude-specific assumption-chain teardown, a Antigravity-specific alternative-architecture sketch), put it there. Lead and convergence treat Section 6 as additive context, not as input to consensus measurement.
207
-
208
- Code evidence must include file paths and line numbers.
209
-
210
- ### Ticket Tagging (mandatory for sections 1–5)
211
-
212
- Every item in sections 1–5 MUST be tagged with the ticket(s) it relates to. This applies whenever the run's task type is `requirements-discovery`, `error-analysis`, `implementation-planning`, or `implementation`.
213
-
214
- - **Table-form items**: include a `Ticket ID` column. The column is placed immediately after the row-ID column (e.g. after `F-001`, `M-001`).
215
- - **Bullet / numbered-list items**: prepend `[TICKETID: <id>]` to the item title, immediately after the row ID and before the body text. Example: `- F-001 [TICKETID: TICKET-123] — <summary> (path:line)`.
216
- - **Section headers in the final report** (e.g. `### 5.5.3 Recommended Option`): append `[TICKETID: <id>]` to the header when the section is scoped to a specific ticket. Headers that span all tickets in the run omit the tag.
137
+ The canonical worker output contract — result frontmatter schema, section ordering (1–5 + optional Section 6), item-ID rules, ticket tagging, and the worker result header standard lives in the worker preamble (`templates/worker-prompt-preamble.md`), the file every worker reads before producing output.
217
138
 
218
- Ticket ID fill rule (in order):
139
+ Lead-facing duties that stay here:
219
140
 
220
- 1. Use the `Issue / Ticket` value from the run's input template.
221
- 2. If empty, fall back to the `Task ID` value (no prefix; write `8852` not `task:8852`).
222
- 3. If both are absent, write `unknown`. This is allowed but signals an input-template defect — the worker SHOULD also record a `Missing Information` item noting the absent identifier.
223
- 4. When a single item maps to multiple tickets, separate them with commas: `TICKET-123, TICKET-456`. Ticket IDs containing commas are not supported.
224
-
225
- Workers MUST apply these rules to every item in sections 1–5. Lead and report-writer MUST preserve the tagging when carrying worker findings into the final report.
226
-
227
- For phases other than the four listed above (e.g. `release-handoff`, `final-verification`), ticket tagging is optional.
141
+ - Lead and report-writer MUST preserve worker ticket tagging and `worker:item` source pairs when carrying findings into the final report.
142
+ - Lead's result-missing redispatch check parses the frontmatter and sections 1–5 presence per the preamble contract (see "Lead Redispatch Policy on Result-Missing").
228
143
 
229
144
  ### Optional errors sidecar (worker-reported)
230
145
 
@@ -270,8 +185,8 @@ Workers MUST use only `errorType: "tool-failure"` in the **sidecar file**.
270
185
  **Path delivery contract (BLOCKING).** Workers do NOT synthesize the
271
186
  run-level errors log path or their sidecar path from the
272
187
  `runs/<task-type>/...` template syntax. Both absolute paths are delivered
273
- by Lead via anchor headers #7 / #8 (Worker Prompt Composition above); Lead
274
- obtains the values from the launch prompt's `## Run Logs (error-log
188
+ by Lead via the `**Errors log path:**` / `**Errors sidecar path:**` anchor
189
+ headers; Lead obtains the values from the launch prompt's `## Run Logs (error-log
275
190
  wiring)` section (resolved by the okstra runtime via `paths.py`). If Lead
276
191
  omits either header, the worker MUST return `<WORKER>_ERRORS_PATH_MISSING`
277
192
  without proceeding.
@@ -305,32 +220,6 @@ without proceeding.
305
220
  | `verification-timeout` | Re-verification timeout |
306
221
  | `verification-error` | Re-verification error |
307
222
 
308
- ## Worker Result Header Standard
309
-
310
- Every worker result file under `worker-results/` must begin with a standardized header:
311
-
312
- ```markdown
313
- # <Role> Analysis — <task-key>
314
-
315
- **Target:** <path or scope> <!-- OPTIONAL: include when the run is scoped to a specific file/module -->
316
- **Model:** <Role>, <AI model>
317
- ```
318
-
319
- Task-type and date are **not** repeated in this human header — the YAML frontmatter (`taskType`, `date`) is the single source for both (and the copy Obsidian indexes). The `Target:` line is optional — include it when the run is scoped to a specific path or module, omit it for whole-project runs; when present, place it between the title and the `Model:` line.
320
-
321
- Example (Codex / Report-writer headers are identical modulo the role name and model id):
322
-
323
- ```markdown
324
- # Claude Worker Analysis — jobs:tasks:8852
325
-
326
- **Target:** server/auth.ts
327
- **Model:** Claude worker, opus
328
- ```
329
-
330
- Use the actual model identifier recorded in team-state (never invent a model ID — read it from `resultContract.requiredWorkerRoles[*].modelExecutionValue` or the tool response metadata).
331
-
332
- The header is followed by the standard worker output contract sections (Findings, Missing Information, etc.).
333
-
334
223
  ## Usage Tracking
335
224
 
336
225
  At the start of Phase 7, call `collect_usage(source)` through the selected adapter. `source` is `team-state.leadAdapter.sessionAccounting` plus the dispatch backend's recorded event source. Never read another runtime's session store as a fallback. Persist the resulting `leadUsage`, worker usage, and `usageSummary` in team-state before report substitution and cleanup.
@@ -5,20 +5,15 @@ Edit here once; every profile picks the change up at next render. Do NOT
5
5
  add phase-specific rules to this file — phase rules stay in the per-
6
6
  profile document.
7
7
  -->
8
- - Team contract (shared):
9
- - `Claude lead` is synthesis-only and stays distinct from `Claude worker` (or, in `implementation`, the `Executor` and verifiers).
10
- - `Report writer worker` is the **author** of the final-report file; `Claude lead` reviews and approves the produced draft and does NOT write the file itself (see `team-contract` and `report-writer` for the authoritative contract).
11
- - default model assignments are resolved from centralised defaults; the fallback values are `Claude lead`/`Report writer worker`=`opus`, `Claude worker`=`opus`, `Codex worker`=`gpt-5.6-sol`, `Antigravity worker`=`auto`. Phase-specific overrides (e.g. `implementation`'s executor binding) live in the per-profile document.
12
- - every required worker listed in the per-profile `Required workers:` block must be attempted; the final verdict waits until each has either a result or an explicit terminal status (`timeout`, `error`, `not-run`).
13
- - unnamed generic parallel workers must not replace the required role roster, and no additional sub-agent dispatch is allowed beyond this roster.
8
+ - Team contract (shared): roster roles, model-assignment rules, dispatch invariants, and required-worker attempt rules are canonical in the team contract (`prompts/lead/team-contract.md`). Two consequences every phase honours: `Claude lead` is synthesis-only (in `implementation`, distinct from the `Executor` and verifiers), and unnamed generic parallel workers never replace or extend the per-profile `Required workers:` roster. Prep-time model recommendations come from the catalog defaults in `okstra_ctl.models` (e.g. `Codex worker` → `gpt-5.6-sol`); at dispatch time the task-manifest's materialized assignment is the only source — there is no dispatch-time fallback.
14
9
  - Worker interaction model (shared — read before inferring behaviour from the roster):
15
10
  - the per-profile `Required workers:` block is a **roster**, not a behaviour contract. Each role's interaction mode changes across operating phases of the same run.
16
11
  - **Phase 4 / 5 (independent analysis)**: analyser workers (`claude`, `codex`, `antigravity` when opted in) produce findings independently and have no access to one another's outputs. `report-writer` does not analyse.
17
- - **Phase 5.5 (convergence — peer review by workers)**: the lead replays each analyser's findings to the *other* analysers and collects `AGREE` / `DISAGREE` / `SUPPLEMENT` verdicts across up to `effectiveMaxRounds` rounds. Workers act as peer reviewers of each other's findings in this phase; the lead mediates but does not vote. See `prompts/lead/convergence.md` for the round protocol, queue invariants, and final classification (`full-consensus` / `partial-consensus` / `contested` / `worker-unique`). For `requirements-discovery`, `error-analysis`, and `implementation-planning` this phase runs in **adversarial mode** (`convergence.adversarial=true`): verifiers try to refute each finding against its cited evidence and the burden of proof sits on the claim — see that skill's §"Adversarial Verification Mode".
12
+ - **Phase 5.5 (convergence — peer review by workers)**: workers peer-review each other's findings across up to `effectiveMaxRounds` rounds; the lead mediates but does not vote. See `prompts/lead/convergence.md` for the round protocol (replay of findings, `AGREE` / `DISAGREE` / `SUPPLEMENT` verdicts), queue invariants, and final classification (`full-consensus` / `partial-consensus` / `contested` / `worker-unique`). For `requirements-discovery`, `error-analysis`, and `implementation-planning` this phase runs in **adversarial mode** (`convergence.adversarial=true`): verifiers try to refute each finding against its cited evidence and the burden of proof sits on the claim — see that skill's §"Adversarial Verification Mode".
18
13
  - Do NOT conclude "no peer review happens" from the roster alone — every profile that lists ≥2 analyser workers runs convergence by default (`convergence.enabled=true` in `task-manifest.json`).
19
14
  - **provider-unavailable fallback (tolerance).** A worker dispatch can fail to produce a result for two distinct reasons, and both take the same recovery path. (1) **Pane budget:** the dispatch is rejected with `no room for another tmux split` (or an equivalent teammate-pane creation failure). (2) **Sandbox CLI-start failure (non-tmux path):** an external CLI worker wrapper exits non-zero within seconds with empty stdout and its live-log shows `operation not permitted` (e.g. `agy`'s `listen tcp 127.0.0.1:0: bind` under a seatbelt sandbox around a non-tmux subagent's Bash tool). In either case the lead retries that worker in-process without `run_in_background`; if it was an external CLI worker, the lead instead **substitutes** an in-process `claude` analysis. Either way the lead records the substitution as provider unavailable in the run log and the convergence notes. Completed external-CLI worker trace panes are reclaimed automatically by the `SubagentStop` hook, but okstra cannot directly reclaim the teammate panes the harness creates, so this fallback is the last line of defence against pane-budget exhaustion and sandbox-blocked CLI workers. (This is a prompt instruction, not a code-enforced gate.)
20
15
  - Tooling — read-only MCP availability (shared):
21
- - MCP is not implicit okstra context. Query an MCP server only when the task brief explicitly lists it as source material for this run. Any MCP-derived finding MUST cite server, table, and the SELECT used. MCP MUST NEVER be used as a write path — schema/data mutations go through repository migration files reviewed by humans.
16
+ - MCP is not implicit context; query a server only when the task brief explicitly lists it as source material for this run. Any MCP-derived finding MUST cite server, table, and the SELECT used. MCP MUST NEVER be a write path — schema/data mutations go through repository migration files reviewed by humans.
22
17
  - Resource boundary (shared — artifact-home rule):
23
18
  - Okstra-owned project artifacts live only under `<PROJECT_ROOT>/.okstra/**`. Treat `project.json`, task bundles, run artifacts, `glossary.md`, and `decisions/` under that subtree as the canonical okstra memory.
24
19
  - Treat paths outside `<PROJECT_ROOT>/.okstra/**` as source material only when the task brief's `Source Material` or `Reporter Confirmations` explicitly cites them; they never become okstra memory.
@@ -29,14 +24,14 @@ profile document.
29
24
  - Internal okstra phase handoffs (e.g. the `approved:` frontmatter gate in `implementation-planning`) are unaffected — those are the user themselves approving and proceed without external coordination.
30
25
  - This rule does NOT relax any phase-specific Forbidden actions list; safety rules in the per-profile document remain in force regardless of the user's authority.
31
26
  - Anti-escalation rule (shared):
32
- - treating "다음 단계 진행해" or equivalent user phrases as authorisation to start a *different* lifecycle phase is forbidden. The next phase begins only in a separate okstra run launched with the new `--task-type`. Per-profile documents may further restrict this within their own scope.
27
+ - treating "proceed to the next step" or equivalent user phrases as authorisation to start a *different* lifecycle phase is forbidden. The next phase begins only in a separate okstra run launched with the new `--task-type`. Per-profile documents may further restrict this within their own scope.
33
28
  - Run-scoped worker-resource lifecycle (shared — run-start resource setup, per-batch cleanup, wrap-up resource disposition, run-end shutdown): these are lead-only operating duties and live in `prompts/lead/okstra-lead-contract.md` "Run-scoped worker-resource lifecycle". Profiles do not restate them.
34
29
  - Brief handoff contract (shared — applies whenever the run consumes a task brief produced by `okstra-brief-gen`):
35
30
  - the brief is a **pre-discovery artifact**: it converts a domain-reporter's words (non-expert *or* developer) into expert-consumable form so this and later phases can run with zero fill-in questions to the operator. The brief is **not** authoritative on solution decisions; it is authoritative on the reporter's intent.
36
31
  - **Reporter confirmation precondition (BLOCKING)**: the brief's frontmatter carries `reporter-confirmations: <complete | partial | pending | skipped>` set by `okstra-brief-gen` Step 6.5. Every phase that consumes the brief MUST read this field before doing analysis. The handling matrix is:
37
32
  - `complete` → proceed normally.
38
33
  - `partial` → proceed; treat still-unmarked `intent-check:` / `conversion-block:` rows as the `skipped` branch.
39
- - `skipped` → do NOT silently infer the missing answers. Promote each unmarked `intent-check:` / `conversion-block:` row into this run's `## 1. Clarification Items` as `Kind=decision`. Use `Blocks=approval` in `implementation-planning`, where the row gates the `approved:` frontmatter flip; otherwise use `Blocks=next-phase`. The recommended answer is drawn from the brief's matching content and clearly labelled `보고자 직접 확인 권장`.
34
+ - `skipped` → do NOT silently infer the missing answers. Promote each unmarked `intent-check:` / `conversion-block:` row into this run's `## 1. Clarification Items` as `Kind=decision`. Use `Blocks=approval` in `implementation-planning`, where the row gates the `approved:` frontmatter flip; otherwise use `Blocks=next-phase`. The recommended answer is drawn from the brief's matching content and clearly labelled `reporter direct-confirmation recommended`.
40
35
  - `pending` (or field missing) → ABORT analysis; render the Verdict Card with `Verdict Token = blocked` + `Direction = hold` and write a single `## Reporter Confirmation Required` block (no leading number) summarising which rows are pending. The `## 1. Clarification Items` table carries one row per pending item with `Blocks=approval` in `implementation-planning`, otherwise `Blocks=next-phase`. The operator must rerun `okstra-brief-gen` Step 6.5. Do NOT emit `## 0.` for this case — Section 0 is reserved for clarification-response carry-in only.
41
36
  `[CONFIRMED <YYYY-MM-DD> → RC-N]` markers on `Open Questions` rows are the per-row signal that the reporter has answered; their answers live verbatim under `## Reporter Confirmations` in the brief.
42
37
  - `Source Material` is reporter-verbatim. Do NOT paraphrase, summarize, reorder, or restructure it. Quote it directly when needed.
@@ -47,18 +42,18 @@ profile document.
47
42
  - `Augmentation` entries carry one of four labels — `evidence-link`, `format-conversion`, `terminology-mapping`, `intent-inference`. Treat them as follows:
48
43
  - `evidence-link` / `format-conversion` → trust without re-verification.
49
44
  - `terminology-mapping` → verify against `<PROJECT_ROOT>/.okstra/glossary.md` (authoritative); raise a `Clarification Items` row if the mapping is missing or contradicts the glossary.
50
- - `intent-inference` → treat as an **unverified hypothesis**. Every `intent-inference` augmentation MUST be paired in the brief with an `Open Questions` row prefixed `intent-check:`. Promote that row into the run's `## 1. Clarification Items` table as `Kind=decision, Blocks=next-phase` (or `Blocks=approval` for `implementation-planning`) with the recommended answer set to "보고자에게 직접 확인 응답" unless the codebase can be inspected to confirm or refute the inference.
45
+ - `intent-inference` → treat as an **unverified hypothesis**. Every `intent-inference` augmentation MUST be paired in the brief with an `Open Questions` row prefixed `intent-check:`. Promote that row into the run's `## 1. Clarification Items` table as `Kind=decision, Blocks=next-phase` (or `Blocks=approval` for `implementation-planning`) with the recommended answer set to "confirm directly with the reporter, then answer" unless the codebase can be inspected to confirm or refute the inference.
51
46
  - `Open Questions` row prefixes are signals — do not strip them when promoting:
52
47
  - `intent-check:` → `Kind=decision`, recommended answer = reporter confirmation. NEVER silently resolve an `intent-check:` by inference at this layer.
53
48
  - `terminology:` → `Kind=decision`, recommended answer = canonical term from `<PROJECT_ROOT>/.okstra/glossary.md` (or "extend okstra glossary via brief Step 4.5").
54
- - `conversion-block:` → `Kind=decision`, recommended answer = "보고자에게 직접 확인". The brief is explicitly signalling that translation failed; further inference is forbidden until the reporter clarifies.
49
+ - `conversion-block:` → `Kind=decision`, recommended answer = "confirm directly with the reporter". The brief is explicitly signalling that translation failed; further inference is forbidden until the reporter clarifies.
55
50
  - `adr-candidate:` → handled by `implementation-planning`; carry forward without modification. Approved decision files land only at `<PROJECT_ROOT>/.okstra/decisions/<NNNN>-<slug>.md`.
56
51
  - `general:` → free-form; classify per the standard `Clarification Items` rules.
57
52
  - Any decision in this run that contradicts the brief's `Source Material` must be raised back to the reporter via a `Clarification Items` row; it must NOT be silently overridden. Disagreement with the reporter is allowed only after the row is resolved.
58
53
  - This contract is the single authority on brief consumption. Phase-specific addenda may *tighten* these rules but may not relax them.
59
54
  - Clarification request policy (shared — applies whenever a profile uses `## 1. Clarification Items`):
60
55
  - **Canonical column schema (SSOT — must match `templates/reports/final-report.template.md` §1 exactly):** every `## 1. Clarification Items` table has exactly these 4 columns, in this order:
61
- `| <record-meta> | Statement | Expected form | User input |` (the first header is the i18n `columns.recordMeta` label — `항목` / `Record`).
56
+ `| <record-meta> | Statement | Expected form | User input |` (the first header is the i18n `columns.recordMeta` label — `Record`).
62
57
  The five short fields (ID, Ticket ID, Kind, Blocks, Status) are stacked inside the single record-meta cell, one per line separated by `<br>`, in this fixed order (mirrors the §2.1 Primary-Evidence meta column):
63
58
 
64
59
  ```
@@ -67,11 +62,11 @@ profile document.
67
62
 
68
63
  The labels `Ticket:` / `Kind:` / `Blocks:` / `Status:` stay English in every locale so the approval-gate parser (`clarification_items.parse_meta_cell`) reads them regardless of report language.
69
64
  Profile-specific addenda may tighten cell content but MUST NOT add, remove, rename, or reorder columns, nor change the meta-cell field order. The `ID` is `C-NNN` (3-digit zero-padded), the `Status` ∈ `{open, answered, resolved, obsolete}`, and the `Kind` / `Blocks` legal values are listed below.
70
- - section 1 is a **single unified table** per `final-report-template.md`. Every clarification item — whether the user must attach a file, choose between options, or supply a single number/path — is one row of that table. Do not split it into sub-sections (`1.1 추가 자료 요청` / `1.2 사용자 확인 질문` / `5.5.9 Open Questions` are removed and the validator fails reports that reintroduce them), do not create a parallel table elsewhere in the report, and do not duplicate the same item into an approval block or any other section.
71
- - each row's `Kind` column picks one of `{material, decision, data-point}`: `material` for files / snapshots / logs / screenshots the user must attach (the `User input` cell will hold a path or URL); `decision` for choices and yes/no confirmations only the user can make; `data-point` for a single number, ID, date, or short string the user can answer inline. A `decision` alternative must be a terminal choice the user can pick as-is; if acting on an alternative still requires the user to supply a concrete value (a path, string, number, or file), that value is its own `data-point` / `material` row — never phrase a data-entry action (e.g. "경로 구체화", " 입력") as a selectable `decision` option, because the rendered `<select>` cannot capture the value the option demands. Items that mix "yes/no + file path if yes" are one row of `Kind=material` with the combined expectation written into `Expected form`.
65
+ - section 1 is a **single unified table** per `final-report-template.md`. Every clarification item — whether the user must attach a file, choose between options, or supply a single number/path — is one row of that table. Do not split it into sub-sections (`1.1 Additional Material Request` / `1.2 User Confirmation Question` / `5.5.9 Open Questions` are removed and the validator fails reports that reintroduce them), do not create a parallel table elsewhere in the report, and do not duplicate the same item into an approval block or any other section.
66
+ - each row's `Kind` column picks one of `{material, decision, data-point}`: `material` for files / snapshots / logs / screenshots the user must attach (the `User input` cell will hold a path or URL); `decision` for choices and yes/no confirmations only the user can make; `data-point` for a single number, ID, date, or short string the user can answer inline. A `decision` alternative must be a terminal choice the user can pick as-is; if acting on an alternative still requires the user to supply a concrete value (a path, string, number, or file), that value is its own `data-point` / `material` row — never phrase a data-entry action (e.g. "specify the path", "enter a value") as a selectable `decision` option, because the rendered `<select>` cannot capture the value the option demands. Items that mix "yes/no + file path if yes" are one row of `Kind=material` with the combined expectation written into `Expected form`.
72
67
  - each row's `Blocks` column picks one of `{approval, next-phase, none}`. `approval` is reserved for items that gate an approval action, especially the `implementation-planning` `approved:` frontmatter flip; outside `implementation-planning`, unresolved brief reporter-confirmation rows use `next-phase` instead. `next-phase` blocks the next run from starting cleanly. `none` is informational/audit-only.
73
- - write every entry in full, descriptive sentences that a non-developer can act on without further context. Avoid abbreviations and internal jargon. The `Statement` cell must state *what* is needed, *why* the answer / attachment changes the next step, and (for `material`) *where* the user can find it and *where* to place it. The `Expected form` cell must state the answer shape (예/아니오, 보기 하나, 숫자/날짜, 파일 경로, 짧은 서술 ); supply concrete option choices when applicable.
74
- - if a phase requires a recommended answer, alternatives, or an evidence-check note, encode it inside the existing 4-column schema: put evidence notes in `Statement` as `Evidence checked: <path:line>` or `Evidence checked: none — <human-only reason>`, and put recommendations/options in `Expected form` as `Recommended: (a) <answer> — <rationale>; Alternatives: (b) <option> (c) <option>`. The recommended answer is always the first option and MUST carry the `(a)` label; alternatives continue the same letter sequence from `(b)` (a lone alternative is `(b) <option>`, never restart at `(a)`), so the full option set reads `(a) (b) (c) …` in order and renders each as its own selectable option. Do **not** append a pick-one answer-space summary such as `(A / B 중 택1)` or `( 택N)` to `<options>` — the rendered `<select>` already enforces single choice, and that annotation leaks verbatim into an option label. Do not add `Recommended`, `Evidence`, `Alternatives`, or `evidence-checked` columns, and do not break the merged record-meta cell back into separate columns.
68
+ - write every entry in full, descriptive sentences that a non-developer can act on without further context. Avoid abbreviations and internal jargon. The `Statement` cell must state *what* is needed, *why* the answer / attachment changes the next step, and (for `material`) *where* the user can find it and *where* to place it. The `Expected form` cell must state the answer shape (yes/no, one of the options, number/date, file path, short description, etc.); supply concrete option choices when applicable.
69
+ - if a phase requires a recommended answer, alternatives, or an evidence-check note, encode it inside the existing 4-column schema: put evidence notes in `Statement` as `Evidence checked: <path:line>` or `Evidence checked: none — <human-only reason>`, and put recommendations/options in `Expected form` as `Recommended: (a) <answer> — <rationale>; Alternatives: (b) <option> (c) <option>`. The recommended answer is always the first option and MUST carry the `(a)` label; alternatives continue the same letter sequence from `(b)` (a lone alternative is `(b) <option>`, never restart at `(a)`), so the full option set reads `(a) (b) (c) …` in order and renders each as its own selectable option. Do **not** append a pick-one answer-space summary such as `(pick 1 of A / B)` or `(pick N of …)` to `<options>` — the rendered `<select>` already enforces single choice, and that annotation leaks verbatim into an option label. Do not add `Recommended`, `Evidence`, `Alternatives`, or `evidence-checked` columns, and do not break the merged record-meta cell back into separate columns.
75
70
  - the same `final-report.md` file is the canonical artifact carried into the next run; the user appends answers inline before rerunning. The preferred turn-around is `scripts/okstra.sh --resume-clarification --task-key <project-id>:<task-group>:<task-id>` (opens the latest report in `$EDITOR`, then auto-reruns the same phase with `--clarification-response` carry-in). The lower-level form `--clarification-response <path>` remains available for scripted runs.
76
71
  - if a clarification response was carried in for this run, render the conditional `## 0. Clarification Response Carried In From Previous Run` section (the template's `RENDER_IF` guard activates it), walk every `C-*` row of the prior report's `## 1. Clarification Items` table, reconcile each one against new evidence, and update its `Status` to `resolved` or `obsolete` before issuing the next decision/verdict. When no carry-in path was provided, omit the `## 0.` heading entirely — the validator fails reports that emit an empty Section 0 stub (e.g. "No prior clarification response was provided for this run.").
77
72
  - Verdict Card (shared — applies to every final-report regardless of profile):
@@ -80,15 +75,13 @@ profile document.
80
75
  - **Worker-side item IDs (free-form but unique within the worker).** Every row item in sections 1–5 (and any optional section 6) of an analysis worker's output MUST carry an item ID that is unique within that one worker's result file. The ID convention is the worker's choice — `F-001` / `F-002` per the suggested schema, `1.1` / `1.2` / `1.3` as Codex tends to use, or any other shape — but it MUST appear as the leading column of the row (for table-form items) or as a `[<ID>]` prefix (for bullet/numbered items). Workers that emit findings without IDs make cross-worker reconciliation impossible.
81
76
  - **Lead-side ID assignment + source preservation.** When the lead (or `report-writer-worker`) synthesises `## 6.1 Consensus` / `## 6.2 Differences` / `## 2.1 Primary Evidence` rows from worker outputs, the lead assigns a fresh `C-NNN` / `D-NNN` / `E-NNN` row ID. The `Source items` column (or, where the template still calls it `Supporting workers` / `Workers (position)` / `Source`, that same column) MUST list every contributing worker:item pair (e.g. `claude:F-001, codex:1.1, antigravity:F-3`) so a reviewer can trace the synthesised row back to each worker's original wording without re-reading every worker-results file. Bare worker names without item IDs (e.g. `claude, codex, antigravity`) are deprecated for these tables; the validator does not yet fail on them but the readability pass treats it as a contract violation.
82
77
  - **Why this matters.** A real run had `claude=F-1..F-11`, `codex=1.1..1.8`, `antigravity=F-3..F-9` — three incompatible ID schemes. When the lead synthesised `C-1..C-8`, the link from `C-3` back to "which sentence in which worker file" was lost. Source-item preservation restores that link without forcing every worker to adopt a single ID prefix, which would over-constrain worker output style.
83
- - Audit sidecar (shared applies to every analysis-worker output and every final-report):
84
- - Reading Confirmation lines (one short line per input file confirming end-to-end reading) live in the **worker audit sidecar** at `runs/<task-type>/worker-results/<worker>-audit-<task-type>-<seq>.md`, NOT in the worker's main worker-results file. The worker-results body starts at section 1 (Findings). The validator fails worker-results files that contain a `## 0. Reading Confirmation` heading.
85
- - The audit sidecar carries any other meta the worker wants to log (tool-call counts, MCP query summaries, timing notes). The lead's final-report does NOT duplicate this content — it is consumed by the validator and by post-run audit tooling, not by end-user readers.
78
+ - Audit sidecar (shared): Reading Confirmation placement and audit-sidecar rules are canonical in the worker preamble (`templates/worker-prompt-preamble.md` §"Reading rules"). Profiles do not restate them; the main worker-results body starts at section 1.
86
79
 
87
80
  - Markdown authoring (shared — applies to markdown documents not already governed by an okstra template/schema):
88
81
  - ad-hoc markdown documents should begin with an `Index` section. Template-governed artifacts such as final-reports, worker-results, and briefs follow their own schema first.
89
- - include only information necessary to fulfill the user's stated purpose and directly related requirements.
82
+ - include only information necessary for the user's stated purpose and directly related requirements.
90
83
  - follow only the sections, format, tone, and scope specified by the user, plus the required `Index` section.
91
- - when writing task instructions or work orders, define the scope of work clearly and specifically, including deliverables, acceptance criteria, and verification steps when relevant.
84
+ - when writing task instructions or work orders, define the scope of work, including deliverables, acceptance criteria, and verification steps when relevant.
92
85
  - define scope positively by stating what work is included. Work outside the defined scope must not be performed.
93
86
  - before adding any structure or content not explicitly specified, ask the user for confirmation, except for the required `Index` section.
94
87
  - before completion, verify that the document exactly matches the requested scope and contains no unrelated material.
@@ -33,7 +33,7 @@ are collected and convergence finished. Phase 1-5 do not need it.
33
33
  - **Manual user test draft**: when this run produces a user-observable change (UI / API / CLI / artifact), write `target / environment / steps / expected result` per change into §5.7.9 (data field `implementation.manualUserTest`, `applicable=true` with `items`). Treat effective `manual-user-test` PREP content only as a seed: reconcile it with the approved plan's `Acceptance:` and this run's actual diff before writing the final steps. Environment line: if the project has a `docker-compose.yml`, use `/okstra-container-build` (which runs `okstra container up <task-id>`) then connect to the published port; otherwise the project's run command (e.g. `npm start`). When there is no user-observable change, set `applicable=false` and give a one-line `exemptionReason` instead of items. These are the steps a human (or `final-verification`) re-runs by hand, NOT the automated validation commands in `Validation evidence`; planning PREP is never a second final-verification manual-test source.
34
34
  - **Design preparation handoff**: `implementation.manualUserTest` remains the only manual-test handoff to final-verification. For each effective non-`manual-user-test` item whose `reviewAt.phase` is `final-verification` and whose question remains unresolved after inspecting the actual diff, add one common `missingInformation` row. Set `source` to `design-prep:<PREP-ID>:<assessment-fingerprint>`, put `ifStillOpen` and the unresolved question in `item`, and put the guardrails plus risk in `risk`. Do not introduce an implementation-only PREP schema.
35
35
  - **Routing recommendation for `final-verification`**: brief note on whether the changes are ready for final-verification phase or need a new error-analysis / planning loop first.
36
- - **Follow-up tasks (Section 4 of the final report)**: every item discovered during this run that was *not* delivered MUST appear in the final report's `## 4. Follow-up Tasks (후속 작업)` table with a concrete `Origin`, `New Task ID`, `Suggested task-type`, `Scope`, and `Reason / Why deferred`. Sources include: out-of-scope discoveries that the executor consciously chose not to fold into this run, verifier concerns the executor declined to fix in-place, scope-boundary items from the approved plan that turned out to need their own ticket, and any unresolved `## 1. Clarification Items` row carried over from the approved plan (`Status` ∈ `{open, answered}` at approval time). An empty section is acceptable but only when expressed as the single line `- 후속 작업 없음.` — silence is treated as a contract violation. Rows with `Auto-spawn? = yes` will be materialised by `scripts/okstra-spawn-followups.py` in Phase 7; rows with `Auto-spawn? = no` MUST also appear in `Section 3. Recommended Next Steps` so the user knows to act manually.
36
+ - **Follow-up tasks (Section 4 of the final report)**: every item discovered during this run that was *not* delivered MUST appear in the final report's `## 4. Follow-up Tasks` table with a concrete `Origin`, `New Task ID`, `Suggested task-type`, `Scope`, and `Reason / Why deferred`. Sources include: out-of-scope discoveries that the executor consciously chose not to fold into this run, verifier concerns the executor declined to fix in-place, scope-boundary items from the approved plan that turned out to need their own ticket, and any unresolved `## 1. Clarification Items` row carried over from the approved plan (`Status` ∈ `{open, answered}` at approval time). An empty section is acceptable but only when expressed as the single line `- No follow-up tasks.` — silence is treated as a contract violation. Rows with `Auto-spawn? = yes` will be materialised by `scripts/okstra-spawn-followups.py` in Phase 7; rows with `Auto-spawn? = no` MUST also appear in `Section 3. Recommended Next Steps` so the user knows to act manually.
37
37
 
38
38
  ## Self-review pass before finalising the report (`Claude lead` runs this; do not delegate to a generic subagent)
39
39