okstra 0.48.0 → 0.50.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 (60) hide show
  1. package/docs/kr/architecture.md +8 -8
  2. package/docs/kr/cli.md +2 -2
  3. package/docs/project-structure-overview.md +3 -3
  4. package/docs/superpowers/plans/2026-06-05-compact-markdown-report-tables.md +323 -0
  5. package/docs/superpowers/plans/2026-06-05-wizard-batch-prompts.md +559 -0
  6. package/docs/superpowers/specs/2026-06-05-compact-markdown-report-tables-design.md +87 -0
  7. package/docs/superpowers/specs/2026-06-05-wizard-batch-prompts-design.md +121 -0
  8. package/docs/task-process/error-analysis.md +1 -1
  9. package/docs/task-process/final-verification.md +1 -1
  10. package/docs/task-process/release-handoff.md +1 -1
  11. package/docs/task-process/requirements-discovery.md +1 -1
  12. package/package.json +1 -1
  13. package/runtime/BUILD.json +2 -2
  14. package/runtime/agents/SKILL.md +3 -3
  15. package/runtime/agents/workers/claude-worker.md +1 -1
  16. package/runtime/agents/workers/codex-worker.md +1 -1
  17. package/runtime/agents/workers/gemini-worker.md +1 -1
  18. package/runtime/agents/workers/report-writer-worker.md +3 -3
  19. package/runtime/bin/lib/okstra/tmux-pane.sh +40 -0
  20. package/runtime/bin/okstra-codex-exec.sh +17 -21
  21. package/runtime/bin/okstra-gemini-exec.sh +12 -15
  22. package/runtime/bin/okstra-render-report-views.py +1 -1
  23. package/runtime/bin/okstra-trace-cleanup.sh +13 -1
  24. package/runtime/prompts/launch.template.md +1 -1
  25. package/runtime/prompts/profiles/_common-contract.md +15 -15
  26. package/runtime/prompts/profiles/_implementation-deliverable.md +1 -1
  27. package/runtime/prompts/profiles/_implementation-executor.md +1 -1
  28. package/runtime/prompts/profiles/_implementation-verifier.md +1 -1
  29. package/runtime/prompts/profiles/error-analysis.md +1 -1
  30. package/runtime/prompts/profiles/final-verification.md +2 -2
  31. package/runtime/prompts/profiles/implementation-planning.md +9 -9
  32. package/runtime/prompts/profiles/improvement-discovery.md +5 -5
  33. package/runtime/prompts/profiles/release-handoff.md +2 -2
  34. package/runtime/prompts/profiles/requirements-discovery.md +2 -2
  35. package/runtime/python/okstra_ctl/clarification_items.py +11 -11
  36. package/runtime/python/okstra_ctl/render.py +1 -1
  37. package/runtime/python/okstra_ctl/render_final_report.py +1 -1
  38. package/runtime/python/okstra_ctl/report_views.py +26 -39
  39. package/runtime/python/okstra_ctl/run.py +3 -3
  40. package/runtime/python/okstra_ctl/wizard.py +90 -3
  41. package/runtime/python/okstra_ctl/workflow.py +1 -1
  42. package/runtime/skills/okstra-brief/SKILL.md +1 -1
  43. package/runtime/skills/okstra-convergence/SKILL.md +8 -8
  44. package/runtime/skills/okstra-report-writer/SKILL.md +22 -22
  45. package/runtime/skills/okstra-run/SKILL.md +2 -0
  46. package/runtime/skills/okstra-team-contract/SKILL.md +1 -1
  47. package/runtime/templates/project-docs/task-index.template.md +1 -8
  48. package/runtime/templates/reports/final-report.template.md +194 -198
  49. package/runtime/templates/reports/i18n/en.json +16 -17
  50. package/runtime/templates/reports/i18n/ko.json +16 -17
  51. package/runtime/templates/reports/implementation-planning-input.template.md +1 -1
  52. package/runtime/templates/reports/release-handoff-input.template.md +1 -1
  53. package/runtime/templates/reports/schedule.template.md +3 -7
  54. package/runtime/templates/reports/user-response.template.md +1 -1
  55. package/runtime/templates/worker-prompt-preamble.md +1 -1
  56. package/runtime/validators/lib/fixtures.sh +2 -2
  57. package/runtime/validators/validate-implementation-plan-stages.py +9 -9
  58. package/runtime/validators/validate-report-views.py +10 -10
  59. package/runtime/validators/validate-run.py +36 -36
  60. package/runtime/validators/validate_improvement_report.py +8 -8
@@ -42,171 +42,104 @@ approved: {{ frontmatter.approved | yaml_scalar }}
42
42
  | Approval Required? | `{% if verdictCard.approvalRequired %}yes — {{ t("verdictCard.approvalRequiredSuffix") }}{% else %}no{% endif %}` |
43
43
  | Next Step | {{ verdictCard.nextStep }} |
44
44
 
45
- {% if clarificationCarryIn and clarificationCarryIn.sourceFile %}
46
- ## 0. Clarification Response Carried In From Previous Run
47
-
48
- - Source file: `{{ clarificationCarryIn.sourceFile }}`
49
- - {{ t("sectionIntro.clarificationCarryIn") }}
50
-
51
- {% endif %}
52
- ## Summary of the Problem or Verification Target
45
+ ## 1. Clarification Items
53
46
 
54
- {{ t("sectionIntro.ticketCoverage") }}
55
-
56
- | ID | Ticket ID | {{ t("columns.summary") }} | {{ t("columns.source") }} |
57
- |----|-----------|------------|----------------------------|
58
- {% for row in summary -%}
59
- | {{ row.id }} | `{{ row.ticketId }}` | {{ row.summary }} | {{ row.source }} |
60
- {% endfor %}
61
-
62
- {% if ticketCoverage.omit %}
63
- {# Ticket Coverage omitted entirely — release-handoff / final-verification #}
64
- {%- else %}
65
- ## Ticket Coverage
66
-
67
- {{ t("ticketCoverage.intro") }}
47
+ {{ t("sectionIntro.clarificationItems") }}
68
48
 
69
- {% if ticketCoverage.singleTicket -%}
70
- - Single ticket run: {{ ticketCoverage.singleTicket }}
49
+ {% if clarificationItems | length == 0 -%}
50
+ {{ t("emptyState.noClarification") }}
71
51
  {%- else %}
72
- | Ticket ID | {{ t("ticketCoverage.columnSections") }} | {{ t("ticketCoverage.columnRelatedIds") }} |
73
- |-----------|-----------|---------------|
74
- {% for row in ticketCoverage.rows -%}
75
- | `{{ row.ticketId }}` | `{{ row.sections }}` | `{{ row.relatedIds }}` |
76
- {% endfor %}
77
- {%- endif %}
78
-
79
- {{ t("ticketCoverage.ruleNote") }}
80
-
81
- {% endif %}
82
- ## Execution Status by Agent
52
+ {{ t("clarification.fillAndRerun") }}
83
53
 
84
- {{ t("sectionIntro.executionStatus") }}
54
+ - Claude Code: `/okstra-run resume-clarification task-key={{ header.taskKey }}`
55
+ - {{ t("clarification.separateTerminalLabel") }}: `scripts/okstra.sh --resume-clarification --task-key {{ header.taskKey }}`
85
56
 
86
- | Agent | Role | Model | Status | {{ t("columns.rawTokens") }} | {{ t("columns.billableTokens") }} | {{ t("columns.cost") }} | Duration | Summary of Key Findings |
87
- |-------|------|-------|--------|-----------|-----------|------------|----------|-------------------------|
88
- {% for row in executionStatus -%}
89
- | {{ row.agent }} | {{ row.role }} | {{ row.model }} | {{ row.status }} | {{ row.totalTokens | format_int }}{% if row.cliTotalTokens %} (CLI: {{ row.cliTotalTokens | format_int }}){% endif %} | {{ row.billableTokens | format_int }} | {{ row.costUsd | format_usd }}{% if row.cliCostUsd %} (+ CLI {{ row.cliCostUsd | format_usd }}){% endif %} | {{ row.durationMs | format_duration_ms }} | {{ row.summary }} |
57
+ | ID | Ticket ID | Kind | Statement | Expected form | Blocks | Status | User input |
58
+ |----|-----------|------|-----------|---------------|--------|--------|-----------|
59
+ {% for row in clarificationItems -%}
60
+ | {{ row.id }} | `{{ row.ticketId }}` | `{{ row.kind }}` | {{ row.statement }} | {{ row.expectedForm }} | `{{ row.blocks }}` | {{ row.status }} | {{ row.userInput or '' }} |
90
61
  {% endfor %}
91
62
 
92
- ## {{ t("tokenSummary.heading") }}
93
-
94
- | {{ t("tokenSummary.tableHeaderItem") }} | {{ t("columns.rawTokens") }} | {{ t("columns.billableTokensInputEquiv") }} | {{ t("columns.cost") }} |
95
- |------|-----------|------------------------|------------|
96
- | {{ t("tokenSummary.rowLead") }} | `{{ tokenUsage.lead.totalTokens | format_int }}` | `{{ tokenUsage.lead.billableTokens | format_int }}` | `{{ tokenUsage.lead.costUsd | format_usd }}` |
97
- | {{ t("tokenSummary.rowWorkerTotal") }} | `{{ tokenUsage.worker.totalTokens | format_int }}` | `{{ tokenUsage.worker.billableTokens | format_int }}` | `{{ tokenUsage.worker.costUsd | format_usd }}` |
98
- | {{ t("tokenSummary.rowGrandTotal") }} | **`{{ tokenUsage.grand.totalTokens | format_int }}`** | **`{{ tokenUsage.grand.billableTokens | format_int }}`** | **`{{ tokenUsage.grand.costUsd | format_usd }}`** |
99
- {% if tokenUsage.cli and tokenUsage.cli.costUsd is not none and tokenUsage.cli.costUsd > 0 -%}
100
- | {{ t("tokenSummary.rowCliExtra") }} | | | `{{ tokenUsage.cli.costUsd | format_usd }}` |
101
- {% endif %}
102
-
103
- {# At Phase 6 numeric cells are null and render as `--`.
104
- Phase 7's okstra-token-usage.py populates tokenUsage in data.json then
105
- re-invokes this renderer to produce the final markdown. #}
106
-
107
- ## 1. Cross Verification Results
108
-
109
- {% if crossVerification.roundHistory and not crossVerification.roundHistory.disabled -%}
110
- ### 1.0 Round History
63
+ {{ t("clarification.columnGuide") }}
111
64
 
112
- {% if crossVerification.roundHistory.rounds | length > 1 -%}
113
- | Round | inputQueueSize | resolvedCount | carriedForwardCount | dispatches (worker:status:durationMs) | skippedWorkers (worker:reason) |
114
- |-------|----------------|---------------|----------------------|----------------------------------------|---------------------------------|
115
- {% for row in crossVerification.roundHistory.rounds -%}
116
- | {{ row.round }} | {{ row.inputQueueSize }} | {{ row.resolvedCount }} | {{ row.carriedForwardCount }} | {{ row.dispatches }} | {{ row.skippedWorkers }} |
117
- {% endfor %}
65
+ - **`Kind`** `{material, decision, data-point}`.
66
+ - **`Blocks`** `{approval, next-phase, none}`.
67
+ - **`Status`** ∈ `{open, answered, resolved, obsolete}`.
68
+ {%- endif %}
118
69
 
119
- - `round2SkippedReason`: `{{ crossVerification.roundHistory.round2SkippedReason }}` ← {{ t("roundHistory.round2SkippedReasonNote") }}
120
- {% elif crossVerification.roundHistory.rounds | length == 1 -%}
121
- {% set r = crossVerification.roundHistory.rounds[0] -%}
122
- - {{ t("roundHistory.singleRoundPrefix") }} resolved={{ r.resolvedCount }}, carriedForward={{ r.carriedForwardCount }}, round2SkippedReason=`{{ crossVerification.roundHistory.round2SkippedReason }}`
123
- {% else -%}
124
- - {{ t("roundHistory.noRoundsNote") }} round2SkippedReason=`{{ crossVerification.roundHistory.round2SkippedReason }}`
125
- {% endif %}
70
+ ## 2. Evidence and Detailed Analysis
126
71
 
127
- {% endif %}
128
- ### 1.1 Consensus
72
+ ### 2.1 Primary Evidence
129
73
 
130
- {% if crossVerification.consensus | length == 0 -%}
131
- {{ t("emptyState.consensusItems") }}
74
+ {% if evidence.primary | length == 0 -%}
75
+ {{ t("emptyState.primaryEvidence") }}
132
76
  {%- else %}
133
- | ID | Ticket ID | Statement | Source items (worker:item) | Evidence (path:line / log / worker report) |
134
- |----|-----------|-----------|----------------------------|---------------------------------------------|
135
- {% for row in crossVerification.consensus -%}
136
- | {{ row.id }} | `{{ row.ticketId }}` | {{ row.statement }} | {{ row.sourceItems | join(', ') }} | {{ row.evidence }} |
77
+ | {{ t("columns.recordMeta") }} | Evidence |
78
+ |--------|----------|
79
+ {% for row in evidence.primary -%}
80
+ | **{{ row.id }}**<br>Ticket: `{{ row.ticketId }}`<br>Source items: {{ row.sourceItems | join(', ') }}<br>Source: {{ row.source }} | {{ row.evidence }} |
137
81
  {% endfor %}
138
82
  {%- endif %}
139
83
 
140
- {{ t("sectionIntro.sourceItemsRule") }}
84
+ {{ t("evidence.sourceItemsColumnNote") }}
141
85
 
142
- ### 1.2 Differences
86
+ ### 2.2 Secondary Evidence or Alternate Interpretations
143
87
 
144
- {% if crossVerification.differences | length == 0 -%}
145
- {{ t("emptyState.differences") }}
88
+ {% if not evidence.secondary or evidence.secondary | length == 0 -%}
89
+ {{ t("emptyState.secondaryEvidence") }}
146
90
  {%- else %}
147
- | ID | Ticket ID | Disagreement | Workers (position + item) | Evidence |
148
- |----|-----------|--------------|---------------------------|----------|
149
- {% for row in crossVerification.differences -%}
150
- | {{ row.id }} | `{{ row.ticketId }}` | {{ row.disagreement }} | {% for w in row.workersPosition %}{{ w.worker }}:{{ w.itemId }} ({{ w.position }}){% if not loop.last %} / {% endif %}{% endfor %} | {{ row.evidence }} |
91
+ | {{ t("columns.recordMeta") }} | Hypothesis or supporting evidence | Source / confidence |
92
+ |--------|-----------------------------------|---------------------|
93
+ {% for row in evidence.secondary -%}
94
+ | **{{ row.id }}**<br>Ticket: `{{ row.ticketId }}` | {{ row.hypothesis }} | {{ row.confidence }} |
151
95
  {% endfor %}
152
96
  {%- endif %}
153
97
 
154
- ## 2. Final Verdict
155
-
156
- {{ t("finalVerdict.intro") }}
98
+ ## 3. Recommended Next Steps
157
99
 
158
- | {{ t("verdictCard.tableHeaderLabel") }} | {{ t("verdictCard.tableHeaderValue") }} |
159
- |------|----|
160
- | Final Conclusion | {{ finalVerdict.finalConclusion }} |
161
- | Verdict Token | `{{ finalVerdict.verdictToken }}` |
162
- | Direction | `{{ finalVerdict.direction }}` |
163
- | {{ t("verdictCard.rationaleLabel") }} | {{ finalVerdict.rationaleRowIds | join(', ') }} |
164
- | {{ t("verdictCard.nextStepLabel") }} | {{ finalVerdict.nextStep }} |
165
-
166
- ## 3. Evidence and Detailed Analysis
167
-
168
- ### 3.1 Primary Evidence
169
-
170
- {% if evidence.primary | length == 0 -%}
171
- {{ t("emptyState.primaryEvidence") }}
100
+ {% if recommendedNextSteps | length == 0 -%}
101
+ - No further action required. Final verdict in section 7 stands.
172
102
  {%- else %}
173
- | ID | Ticket ID | Evidence | Source items (worker:item) | Source (path:line / log) |
174
- |----|-----------|----------|----------------------------|---------------------------|
175
- {% for row in evidence.primary -%}
176
- | {{ row.id }} | `{{ row.ticketId }}` | {{ row.evidence }} | {{ row.sourceItems | join(', ') }} | {{ row.source }} |
103
+ {% for step in recommendedNextSteps -%}
104
+ {{ loop.index }}. {{ step.text }}
105
+ {% if step.commands -%}
106
+ {% for cmd in step.commands %}
107
+ - {{ cmd.label }}:
108
+ - Claude Code: `{{ cmd.claudeCode }}`
109
+ - {{ t("clarification.separateTerminalLabel") }}: `{{ cmd.terminal }}`
110
+ {% endfor -%}
111
+ {%- endif %}
177
112
  {% endfor %}
178
113
  {%- endif %}
179
114
 
180
- {{ t("evidence.sourceItemsColumnNote") }}
181
-
182
- ### 3.2 Secondary Evidence or Alternate Interpretations
115
+ ## 4. Follow-up Tasks{% if t("followUpTasks.headingAside") != "Follow-up Tasks" %} ({{ t("followUpTasks.headingAside") }}){% endif %}
183
116
 
184
- {% if not evidence.secondary or evidence.secondary | length == 0 -%}
185
- {{ t("emptyState.secondaryEvidence") }}
117
+ {% if followUpTasks | length == 0 -%}
118
+ {{ t("emptyState.noFollowUp") }}
186
119
  {%- else %}
187
- | ID | Ticket ID | Hypothesis or supporting evidence | Source / confidence |
188
- |----|-----------|-----------------------------------|---------------------|
189
- {% for row in evidence.secondary -%}
190
- | {{ row.id }} | `{{ row.ticketId }}` | {{ row.hypothesis }} | {{ row.confidence }} |
120
+ | {{ t("columns.recordMeta") }} | Title | Scope (files/areas) | Reason / Why deferred |
121
+ |--------|-------|---------------------|------------------------|
122
+ {% for row in followUpTasks -%}
123
+ | **{{ row.id }}**<br>Ticket: `{{ row.ticketId }}`<br>Origin: `{{ row.origin }}`<br>New Task ID: `{{ row.newTaskId }}`<br>Type: `{{ row.suggestedTaskType }}`<br>Priority: `{{ row.priority }}`<br>Auto-spawn: `{{ row.autoSpawn }}` | {{ row.title }} | {{ row.scope }} | {{ row.reason }} |
191
124
  {% endfor %}
192
125
  {%- endif %}
193
126
 
194
- ## 4. Missing Information and Risks
127
+ ## 5. Missing Information and Risks
195
128
 
196
129
  {% if missingInformation | length == 0 -%}
197
130
  {{ t("emptyState.risks") }}
198
131
  {%- else %}
199
- | ID | Ticket ID | Item | Risk if ignored | Mitigation Owner |
200
- |----|-----------|------|-----------------|------------------|
132
+ | {{ t("columns.recordMeta") }} | Item | Risk if ignored | Mitigation Owner |
133
+ |--------|------|-----------------|------------------|
201
134
  {% for row in missingInformation -%}
202
- | {{ row.id }} | `{{ row.ticketId }}` | {{ row.item }} | {{ row.risk }} | {{ row.owner }} |
135
+ | **{{ row.id }}**<br>Ticket: `{{ row.ticketId }}` | {{ row.item }} | {{ row.risk }} | {{ row.owner }} |
203
136
  {% endfor %}
204
137
  {%- endif %}
205
138
 
206
139
  {% if header.taskType == 'implementation-planning' %}
207
- ## 4.5 Implementation Plan Deliverables
140
+ ## 5.5 Implementation Plan Deliverables
208
141
 
209
- ### 4.5.1 Option Candidates{% if t("sectionAside.optionCandidates") != "Option Candidates" %} ({{ t("sectionAside.optionCandidates") }}){% endif %}
142
+ ### 5.5.1 Option Candidates{% if t("sectionAside.optionCandidates") != "Option Candidates" %} ({{ t("sectionAside.optionCandidates") }}){% endif %}
210
143
 
211
144
  {% for opt in implementationPlanning.optionCandidates %}
212
145
  **{{ opt.name }}**
@@ -224,7 +157,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
224
157
 
225
158
  {% endfor %}
226
159
 
227
- ### 4.5.2 Trade-off Matrix{% if t("sectionAside.tradeOffMatrix") != "Trade-off Matrix" %} ({{ t("sectionAside.tradeOffMatrix") }}){% endif %}
160
+ ### 5.5.2 Trade-off Matrix{% if t("sectionAside.tradeOffMatrix") != "Trade-off Matrix" %} ({{ t("sectionAside.tradeOffMatrix") }}){% endif %}
228
161
 
229
162
  | Option | Complexity | Risk | Reversibility | Test Coverage Cost | Rollout Cost |
230
163
  |--------|-----------|------|---------------|--------------------|--------------|
@@ -232,7 +165,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
232
165
  | {{ row.option }} | {{ row.complexity }} | {{ row.risk }} | {{ row.reversibility }} | {{ row.testCoverageCost }} | {{ row.rolloutCost }} |
233
166
  {% endfor %}
234
167
 
235
- ### 4.5.3 Recommended Option{% if t("sectionAside.recommendedOption") != "Recommended Option" %} ({{ t("sectionAside.recommendedOption") }}){% endif %}
168
+ ### 5.5.3 Recommended Option{% if t("sectionAside.recommendedOption") != "Recommended Option" %} ({{ t("sectionAside.recommendedOption") }}){% endif %}
236
169
 
237
170
  | {{ t("implementationPlanning.recommendedTableHeaderLabel") }} | {{ t("implementationPlanning.recommendedTableHeaderValue") }} |
238
171
  |------|----|
@@ -241,7 +174,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
241
174
  | {{ t("implementationPlanning.rationaleLabel") }} | {{ implementationPlanning.recommendedOption.rationale }} |
242
175
  | {{ t("implementationPlanning.rejectedSummaryLabel") }} | {{ implementationPlanning.recommendedOption.rejectedSummary }} |
243
176
 
244
- ### 4.5.4 Stepwise Execution Order{% if t("sectionAside.stepwiseExecutionOrder") != "Stepwise Execution Order" %} ({{ t("sectionAside.stepwiseExecutionOrder") }}){% endif %}
177
+ ### 5.5.4 Stepwise Execution Order{% if t("sectionAside.stepwiseExecutionOrder") != "Stepwise Execution Order" %} ({{ t("sectionAside.stepwiseExecutionOrder") }}){% endif %}
245
178
 
246
179
  | Step | Ticket ID | Action (≤ 5min) | Files | Command / Test | Expected outcome |
247
180
  |------|-----------|------------------|-------|----------------|-------------------|
@@ -249,9 +182,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
249
182
  | {{ row.step }} | `{{ row.ticketId }}` | {{ row.action }} | `{{ row.files }}` | `{{ row.commandOrTest }}` | {{ row.expectedOutcome }} |
250
183
  {% endfor %}
251
184
 
252
- {{ t("sectionIntro.stepRule") }}
253
-
254
- ### 4.5.5 Dependency / Migration Risk{% if t("sectionAside.dependencyRisk") != "Dependency / Migration Risk" %} ({{ t("sectionAside.dependencyRisk") }}){% endif %}
185
+ ### 5.5.5 Dependency / Migration Risk{% if t("sectionAside.dependencyRisk") != "Dependency / Migration Risk" %} ({{ t("sectionAside.dependencyRisk") }}){% endif %}
255
186
 
256
187
  {% if implementationPlanning.dependencyMigrationRisk | length == 0 -%}
257
188
  {{ t("emptyState.dependencyRisk") }}
@@ -263,7 +194,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
263
194
  {% endfor %}
264
195
  {%- endif %}
265
196
 
266
- ### 4.5.6 Validation Checklist{% if t("sectionAside.validationChecklist") != "Validation Checklist" %} ({{ t("sectionAside.validationChecklist") }}){% endif %}
197
+ ### 5.5.6 Validation Checklist{% if t("sectionAside.validationChecklist") != "Validation Checklist" %} ({{ t("sectionAside.validationChecklist") }}){% endif %}
267
198
 
268
199
  | Phase | Ticket ID | Check | Command / Observation | Expected outcome |
269
200
  |-------|-----------|-------|------------------------|-------------------|
@@ -271,7 +202,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
271
202
  | {{ row.phase }} | `{{ row.ticketId }}` | {{ row.check }} | `{{ row.commandOrObservation }}` | {{ row.expectedOutcome }} |
272
203
  {% endfor %}
273
204
 
274
- ### 4.5.7 Rollback Strategy{% if t("sectionAside.rollbackStrategy") != "Rollback Strategy" %} ({{ t("sectionAside.rollbackStrategy") }}){% endif %}
205
+ ### 5.5.7 Rollback Strategy{% if t("sectionAside.rollbackStrategy") != "Rollback Strategy" %} ({{ t("sectionAside.rollbackStrategy") }}){% endif %}
275
206
 
276
207
  | ID | Step | Action | Trigger signal | {{ t("columns.checkMethod") }} |
277
208
  |----|------|--------|----------------|-----------|
@@ -279,7 +210,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
279
210
  | {{ row.id }} | {{ row.step }} | `{{ row.action }}` | {{ row.triggerSignal }} | `{{ row.verificationMethod }}` |
280
211
  {% endfor %}
281
212
 
282
- ### 4.5.9 Plan Body Verification{% if t("sectionAside.planBodyVerification") != "Plan Body Verification" %} ({{ t("sectionAside.planBodyVerification") }}){% endif %}
213
+ ### 5.5.9 Plan Body Verification{% if t("sectionAside.planBodyVerification") != "Plan Body Verification" %} ({{ t("sectionAside.planBodyVerification") }}){% endif %}
283
214
 
284
215
  {{ t("sectionIntro.planBodyVerification") }}
285
216
 
@@ -306,17 +237,17 @@ approved: {{ frontmatter.approved | yaml_scalar }}
306
237
 
307
238
  {% endif %}
308
239
  {% if header.taskType == 'release-handoff' %}
309
- ## 4.6 Release Handoff Deliverables
240
+ ## 5.6 Release Handoff Deliverables
310
241
 
311
242
  {{ t("releaseHandoff.auditNote") }}
312
243
 
313
- ### 4.6.1 Source Verification Report
244
+ ### 5.6.1 Source Verification Report
314
245
 
315
246
  - Path (project-relative): `{{ releaseHandoff.sourceVerificationReport.path }}`
316
- - Quoted `Verdict Token` row from that report's `## 2.` table:
247
+ - Quoted `Verdict Token` row from that report's `## 7.` table:
317
248
  > {{ releaseHandoff.sourceVerificationReport.verdictTokenQuote }}
318
249
 
319
- ### 4.6.2 Feature Branch & Working-Tree State{% if t("releaseHandoff.branchStateAside") != "captured at run start" %} ({{ t("releaseHandoff.branchStateAside") }}){% endif %}
250
+ ### 5.6.2 Feature Branch & Working-Tree State{% if t("releaseHandoff.branchStateAside") != "captured at run start" %} ({{ t("releaseHandoff.branchStateAside") }}){% endif %}
320
251
 
321
252
  - Feature branch: `{{ releaseHandoff.featureBranchState.branchName }}`
322
253
  - {{ t("releaseHandoff.gitStatusShortLabel") }}:
@@ -325,7 +256,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
325
256
  ```
326
257
  - {{ t("releaseHandoff.existingPrLabel") }}: `{{ releaseHandoff.featureBranchState.existingPrUrl or '(none)' }}`
327
258
 
328
- ### 4.6.3 User Selections{% if t("releaseHandoff.userSelectionsAside") != "menu response log" %} ({{ t("releaseHandoff.userSelectionsAside") }}){% endif %}
259
+ ### 5.6.3 User Selections{% if t("releaseHandoff.userSelectionsAside") != "menu response log" %} ({{ t("releaseHandoff.userSelectionsAside") }}){% endif %}
329
260
 
330
261
  | {{ t("releaseHandoff.questionsTableHeader.questionId") }} | {{ t("releaseHandoff.questionsTableHeader.questionBody") }} | {{ t("releaseHandoff.questionsTableHeader.userResponse") }} | {{ t("releaseHandoff.questionsTableHeader.allowedOptions") }} |
331
262
  |---------|-----------|--------------------|--------------------|
@@ -333,7 +264,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
333
264
  | H2 | {{ t("releaseHandoff.h2Body") }} | `{{ releaseHandoff.userSelections.h2 or t("releaseHandoff.h2DefaultLabel") }}` | {{ t("releaseHandoff.h2OptionsLabel") }} |
334
265
  | H3 | {{ t("releaseHandoff.h3Body") }} | `{{ releaseHandoff.userSelections.h3 }}` | `use as-is` / `edit then proceed` / `cancel` |
335
266
 
336
- ### 4.6.4 Executed Commands
267
+ ### 5.6.4 Executed Commands
337
268
 
338
269
  {% if releaseHandoff.executedCommands | length == 0 -%}
339
270
  - {{ t("releaseHandoff.noMutationNote") }}
@@ -345,7 +276,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
345
276
  {% endfor %}
346
277
  {%- endif %}
347
278
 
348
- ### 4.6.5 Commit List
279
+ ### 5.6.5 Commit List
349
280
 
350
281
  {% if releaseHandoff.commitList.empty -%}
351
282
  - No implementation commits found; release-handoff is blocked.
@@ -357,7 +288,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
357
288
  {% endfor %}
358
289
  {%- endif %}
359
290
 
360
- ### 4.6.6 Merge Conflict Probe
291
+ ### 5.6.6 Merge Conflict Probe
361
292
 
362
293
  {% if releaseHandoff.mergeConflictProbe.kind == 'not-run' -%}
363
294
  - Not run (user picked local only or skip).
@@ -367,7 +298,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
367
298
  - Conflicts detected against {{ releaseHandoff.mergeConflictProbe.baseBranch }} at {{ releaseHandoff.mergeConflictProbe.baseSha }}; user chose {{ releaseHandoff.mergeConflictProbe.userChoice }}. Conflicting paths: {{ releaseHandoff.mergeConflictProbe.conflictingPaths | join(', ') }}.
368
299
  {%- endif %}
369
300
 
370
- ### 4.6.7 Pull Request Outcome
301
+ ### 5.6.7 Pull Request Outcome
371
302
 
372
303
  {% if releaseHandoff.pullRequestOutcome.kind == 'no-action' -%}
373
304
  - No PR action requested.
@@ -379,15 +310,15 @@ approved: {{ frontmatter.approved | yaml_scalar }}
379
310
  - PR creation skipped: {{ releaseHandoff.pullRequestOutcome.reason }}
380
311
  {%- endif %}
381
312
 
382
- ### 4.6.8 Routing Recommendation
313
+ ### 5.6.8 Routing Recommendation
383
314
 
384
315
  {{ releaseHandoff.routingRecommendation }}
385
316
 
386
317
  {% endif %}
387
318
  {% if header.taskType == 'implementation' %}
388
- ## 4.7 Implementation Deliverables
319
+ ## 5.7 Implementation Deliverables
389
320
 
390
- ### 4.7.1 Approved Plan Reference
321
+ ### 5.7.1 Approved Plan Reference
391
322
 
392
323
  - Plan file (project-relative): `{{ implementation.approvedPlanReference.planFile }}`
393
324
  - Approval evidence:
@@ -395,7 +326,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
395
326
  - {{ t("executionMeta.runExecutorWorktreePath") }}: `{{ implementation.approvedPlanReference.executorWorktreePath }}`
396
327
  - {{ t("executionMeta.runBaseRef") }}: `{{ implementation.approvedPlanReference.baseRefSha }}`
397
328
 
398
- ### 4.7.2 Commit List
329
+ ### 5.7.2 Commit List
399
330
 
400
331
  {% if implementation.commitList | length == 0 -%}
401
332
  - No implementation commits produced; routing recommendation must be back to implementation-planning.
@@ -407,7 +338,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
407
338
  {% endfor %}
408
339
  {%- endif %}
409
340
 
410
- ### 4.7.3 Diff Summary
341
+ ### 5.7.3 Diff Summary
411
342
 
412
343
  ```
413
344
  {{ implementation.diffSummary.rawStat }}
@@ -419,7 +350,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
419
350
  | `{{ row.file }}` | {{ row.action }} | `{{ row.lines }}` | {{ row.planStep }} |
420
351
  {% endfor %}
421
352
 
422
- ### 4.7.4 Out-of-plan Edits
353
+ ### 5.7.4 Out-of-plan Edits
423
354
 
424
355
  {% if implementation.outOfPlanEdits | length == 0 -%}
425
356
  {{ t("emptyState.outOfPlanEdits") }}
@@ -431,7 +362,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
431
362
  {% endfor %}
432
363
  {%- endif %}
433
364
 
434
- ### 4.7.5 Validation Evidence
365
+ ### 5.7.5 Validation Evidence
435
366
 
436
367
  | Phase | Command | Exit code | Output tail | TDD evidence |
437
368
  |-------|---------|-----------|-------------|--------------|
@@ -439,7 +370,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
439
370
  | {{ row.phase }} | `{{ row.command }}` | `{{ row.exitCode }}` | {{ row.outputTail }} | {{ row.tddEvidence or '--' }} |
440
371
  {% endfor %}
441
372
 
442
- ### 4.7.6 Verifier Results
373
+ ### 5.7.6 Verifier Results
443
374
 
444
375
  {% for block in implementation.verifierResults %}
445
376
  - **{{ block.verifier }}** — Verdict: `{{ block.verdict }}`
@@ -450,7 +381,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
450
381
  - Discrepancy: {{ block.discrepancy or t("emptyState.discrepancy") }}
451
382
  {% endfor %}
452
383
 
453
- ### 4.7.7 Rollback Verification
384
+ ### 5.7.7 Rollback Verification
454
385
 
455
386
  | Category | Rollback command | Verification | Result |
456
387
  |----------|-------------------|---------------|--------|
@@ -458,15 +389,15 @@ approved: {{ frontmatter.approved | yaml_scalar }}
458
389
  | {{ row.category }} | `{{ row.rollbackCommand }}` | {{ row.verification }} | `{{ row.result }}` |
459
390
  {% endfor %}
460
391
 
461
- ### 4.7.8 Routing Recommendation
392
+ ### 5.7.8 Routing Recommendation
462
393
 
463
394
  {{ implementation.routingRecommendation }}
464
395
 
465
396
  {% endif %}
466
397
  {% if header.taskType == 'final-verification' %}
467
- ## 4.8 Final Verification Deliverables
398
+ ## 5.8 Final Verification Deliverables
468
399
 
469
- ### 4.8.1 Source Implementation Report
400
+ ### 5.8.1 Source Implementation Report
470
401
 
471
402
  - Path (project-relative): `{{ finalVerification.sourceImplementationReport.path }}`
472
403
  - {{ t("evidenceMeta.commitListSummary") }}:
@@ -485,7 +416,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
485
416
  {{ finalVerification.sourceImplementationReport.gitDiffStat }}
486
417
  ```
487
418
 
488
- ### 4.8.2 Acceptance Blockers
419
+ ### 5.8.2 Acceptance Blockers
489
420
 
490
421
  {% if finalVerification.acceptanceBlockers | length == 0 -%}
491
422
  - No acceptance blockers found.
@@ -497,7 +428,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
497
428
  {% endfor %}
498
429
  {%- endif %}
499
430
 
500
- ### 4.8.3 Residual Risk
431
+ ### 5.8.3 Residual Risk
501
432
 
502
433
  {% if finalVerification.residualRisk | length == 0 -%}
503
434
  {{ t("emptyState.lingeringRisks") }}
@@ -509,7 +440,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
509
440
  {% endfor %}
510
441
  {%- endif %}
511
442
 
512
- ### 4.8.4 Validation Evidence{% if t("finalVerification.validationEvidenceAside") != "requirements coverage" %} ({{ t("finalVerification.validationEvidenceAside") }}){% endif %}
443
+ ### 5.8.4 Validation Evidence{% if t("finalVerification.validationEvidenceAside") != "requirements coverage" %} ({{ t("finalVerification.validationEvidenceAside") }}){% endif %}
513
444
 
514
445
  | ID | {{ t("finalVerification.columnRequirement") }} | Artifact | Status |
515
446
  |----|--------------------------------|----------|--------|
@@ -517,7 +448,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
517
448
  | {{ row.id }} | {{ row.requirement }} | `{{ row.artifact }}` | {{ row.status }} |
518
449
  {% endfor %}
519
450
 
520
- ### 4.8.5 Read-only Command Log
451
+ ### 5.8.5 Read-only Command Log
521
452
 
522
453
  | # | Tier | Command (verbatim) | Status | Exit code | Output tail |
523
454
  |---|------|---------------------|--------|-----------|-------------|
@@ -525,7 +456,7 @@ approved: {{ frontmatter.approved | yaml_scalar }}
525
456
  | {{ row.number }} | {{ row.tier }} | `{{ row.command }}` | `{{ row.status }}` | {{ row.exitCode if row.exitCode is not none else '—' }} | {{ row.rejectionReason if row.status == 'rejected' else row.outputTail }} |
526
457
  {% endfor %}
527
458
 
528
- ### 4.8.6 Conditional Acceptance Conditions
459
+ ### 5.8.6 Conditional Acceptance Conditions
529
460
 
530
461
  {% if not finalVerdict.conditionalAcceptanceConditions -%}
531
462
  - Not applicable (verdict is not `conditional-accept`).
@@ -537,13 +468,13 @@ approved: {{ frontmatter.approved | yaml_scalar }}
537
468
  {% endfor %}
538
469
  {%- endif %}
539
470
 
540
- ### 4.8.7 Routing Recommendation
471
+ ### 5.8.7 Routing Recommendation
541
472
 
542
473
  {{ finalVerification.routingRecommendation }}
543
474
 
544
475
  {% endif %}
545
476
  {% if header.taskType == 'improvement-discovery' %}
546
- ## 4.9 Improvement Candidates
477
+ ## 5.9 Improvement Candidates
547
478
 
548
479
  > Lens whitelist and column schema enforced by `validators/validate-improvement-report.py`. Row count is bounded by the brief's `candidate-cap` (default 8, absolute max 12).
549
480
 
@@ -551,56 +482,121 @@ approved: {{ frontmatter.approved | yaml_scalar }}
551
482
  |---------|------|-------|-------|----------|--------|-----------|----------------|------------------------|----------|
552
483
 
553
484
  {% endif %}
554
- ## 5. Clarification Items
555
-
556
- {{ t("sectionIntro.clarificationItems") }}
485
+ ## 6. Cross Verification Results
557
486
 
558
- {% if clarificationItems | length == 0 -%}
559
- {{ t("emptyState.noClarification") }}
560
- {%- else %}
561
- {{ t("clarification.fillAndRerun") }}
562
-
563
- - Claude Code: `/okstra-run resume-clarification task-key={{ header.taskKey }}`
564
- - {{ t("clarification.separateTerminalLabel") }}: `scripts/okstra.sh --resume-clarification --task-key {{ header.taskKey }}`
487
+ {% if crossVerification.roundHistory and not crossVerification.roundHistory.disabled -%}
488
+ ### 6.0 Round History
565
489
 
566
- | ID | Ticket ID | Kind | Statement | Expected form | Blocks | Status | User input |
567
- |----|-----------|------|-----------|---------------|--------|--------|-----------|
568
- {% for row in clarificationItems -%}
569
- | {{ row.id }} | `{{ row.ticketId }}` | `{{ row.kind }}` | {{ row.statement }} | {{ row.expectedForm }} | `{{ row.blocks }}` | {{ row.status }} | {{ row.userInput or '' }} |
490
+ {% if crossVerification.roundHistory.rounds | length > 1 -%}
491
+ | Round | inputQueueSize | resolvedCount | carriedForwardCount | dispatches (worker:status:durationMs) | skippedWorkers (worker:reason) |
492
+ |-------|----------------|---------------|----------------------|----------------------------------------|---------------------------------|
493
+ {% for row in crossVerification.roundHistory.rounds -%}
494
+ | {{ row.round }} | {{ row.inputQueueSize }} | {{ row.resolvedCount }} | {{ row.carriedForwardCount }} | {{ row.dispatches }} | {{ row.skippedWorkers }} |
570
495
  {% endfor %}
571
496
 
572
- {{ t("clarification.columnGuide") }}
497
+ - `round2SkippedReason`: `{{ crossVerification.roundHistory.round2SkippedReason }}` ← {{ t("roundHistory.round2SkippedReasonNote") }}
498
+ {% elif crossVerification.roundHistory.rounds | length == 1 -%}
499
+ {% set r = crossVerification.roundHistory.rounds[0] -%}
500
+ - {{ t("roundHistory.singleRoundPrefix") }} resolved={{ r.resolvedCount }}, carriedForward={{ r.carriedForwardCount }}, round2SkippedReason=`{{ crossVerification.roundHistory.round2SkippedReason }}`
501
+ {% else -%}
502
+ - {{ t("roundHistory.noRoundsNote") }} round2SkippedReason=`{{ crossVerification.roundHistory.round2SkippedReason }}`
503
+ {% endif %}
573
504
 
574
- - **`Kind`** ∈ `{material, decision, data-point}`.
575
- - **`Blocks`** ∈ `{approval, next-phase, none}`.
576
- - **`Status`** ∈ `{open, answered, resolved, obsolete}`.
505
+ {% endif %}
506
+ ### 6.1 Consensus
507
+
508
+ {% if crossVerification.consensus | length == 0 -%}
509
+ {{ t("emptyState.consensusItems") }}
510
+ {%- else %}
511
+ | {{ t("columns.recordMeta") }} | Statement | Evidence (path:line / log / worker report) |
512
+ |--------|-----------|---------------------------------------------|
513
+ {% for row in crossVerification.consensus -%}
514
+ | **{{ row.id }}**<br>Ticket: `{{ row.ticketId }}`<br>Source items: {{ row.sourceItems | join(', ') }} | {{ row.statement }} | {{ row.evidence }} |
515
+ {% endfor %}
577
516
  {%- endif %}
578
517
 
579
- ## 6. Recommended Next Steps
518
+ {{ t("sectionIntro.sourceItemsRule") }}
580
519
 
581
- {% if recommendedNextSteps | length == 0 -%}
582
- - No further action required. Final verdict in section 2 stands.
520
+ ### 6.2 Differences
521
+
522
+ {% if crossVerification.differences | length == 0 -%}
523
+ {{ t("emptyState.differences") }}
583
524
  {%- else %}
584
- {% for step in recommendedNextSteps -%}
585
- {{ loop.index }}. {{ step.text }}
586
- {% if step.commands -%}
587
- {% for cmd in step.commands %}
588
- - {{ cmd.label }}:
589
- - Claude Code: `{{ cmd.claudeCode }}`
590
- - {{ t("clarification.separateTerminalLabel") }}: `{{ cmd.terminal }}`
591
- {% endfor -%}
592
- {%- endif %}
525
+ | {{ t("columns.recordMeta") }} | Disagreement | Evidence |
526
+ |--------|--------------|----------|
527
+ {% for row in crossVerification.differences -%}
528
+ | **{{ row.id }}**<br>Ticket: `{{ row.ticketId }}`<br>Workers: {% for w in row.workersPosition %}{{ w.worker }}:{{ w.itemId }} ({{ w.position }}){% if not loop.last %} / {% endif %}{% endfor %} | {{ row.disagreement }} | {{ row.evidence }} |
593
529
  {% endfor %}
594
530
  {%- endif %}
595
531
 
596
- ## 7. Follow-up Tasks{% if t("followUpTasks.headingAside") != "Follow-up Tasks" %} ({{ t("followUpTasks.headingAside") }}){% endif %}
532
+ ## 7. Final Verdict
597
533
 
598
- {% if followUpTasks | length == 0 -%}
599
- {{ t("emptyState.noFollowUp") }}
534
+ {{ t("finalVerdict.intro") }}
535
+
536
+ | {{ t("verdictCard.tableHeaderLabel") }} | {{ t("verdictCard.tableHeaderValue") }} |
537
+ |------|----|
538
+ | Final Conclusion | {{ finalVerdict.finalConclusion }} |
539
+ | Verdict Token | `{{ finalVerdict.verdictToken }}` |
540
+ | Direction | `{{ finalVerdict.direction }}` |
541
+ | {{ t("verdictCard.rationaleLabel") }} | {{ finalVerdict.rationaleRowIds | join(', ') }} |
542
+ | {{ t("verdictCard.nextStepLabel") }} | {{ finalVerdict.nextStep }} |
543
+
544
+ {% if clarificationCarryIn and clarificationCarryIn.sourceFile %}
545
+ ## 0. Clarification Response Carried In From Previous Run
546
+
547
+ - Source file: `{{ clarificationCarryIn.sourceFile }}`
548
+ - {{ t("sectionIntro.clarificationCarryIn") }}
549
+
550
+ {% endif %}
551
+ ## Summary of the Problem or Verification Target
552
+
553
+ {{ t("sectionIntro.ticketCoverage") }}
554
+
555
+ | {{ t("columns.recordMeta") }} | {{ t("columns.summary") }} |
556
+ |--------|------------|
557
+ {% for row in summary -%}
558
+ | **{{ row.id }}**<br>Ticket: `{{ row.ticketId }}`<br>{{ t("columns.source") }}: {{ row.source }} | {{ row.summary }} |
559
+ {% endfor %}
560
+
561
+ {% if ticketCoverage.omit %}
562
+ {# Ticket Coverage omitted entirely — release-handoff / final-verification #}
600
563
  {%- else %}
601
- | ID | Ticket ID | Origin | New Task ID | Title | Suggested task-type | Scope (files/areas) | Reason / Why deferred | Priority (P0/P1/P2) | Auto-spawn? |
602
- |----|-----------|--------|-------------|-------|---------------------|---------------------|------------------------|---------------------|-------------|
603
- {% for row in followUpTasks -%}
604
- | {{ row.id }} | `{{ row.ticketId }}` | `{{ row.origin }}` | `{{ row.newTaskId }}` | {{ row.title }} | `{{ row.suggestedTaskType }}` | `{{ row.scope }}` | {{ row.reason }} | `{{ row.priority }}` | `{{ row.autoSpawn }}` |
564
+ ## Ticket Coverage
565
+
566
+ {{ t("ticketCoverage.intro") }}
567
+
568
+ {% if ticketCoverage.singleTicket -%}
569
+ - Single ticket run: {{ ticketCoverage.singleTicket }}
570
+ {%- else %}
571
+ | Ticket ID | {{ t("ticketCoverage.columnSections") }} | {{ t("ticketCoverage.columnRelatedIds") }} |
572
+ |-----------|-----------|---------------|
573
+ {% for row in ticketCoverage.rows -%}
574
+ | `{{ row.ticketId }}` | `{{ row.sections }}` | `{{ row.relatedIds }}` |
605
575
  {% endfor %}
606
576
  {%- endif %}
577
+
578
+ {% endif %}
579
+ ## Execution Status by Agent
580
+
581
+ {{ t("sectionIntro.executionStatus") }}
582
+
583
+ | {{ t("columns.recordMeta") }} | Summary of Key Findings |
584
+ |--------|-------------------------|
585
+ {% for row in executionStatus -%}
586
+ | **{{ row.agent }}**<br>Role: {{ row.role }}<br>Model: {{ row.model }}<br>Status: {{ row.status }}<br>{{ t("columns.rawTokens") }}: {{ row.totalTokens | format_int }}{% if row.cliTotalTokens %} (CLI: {{ row.cliTotalTokens | format_int }}){% endif %}<br>{{ t("columns.billableTokens") }}: {{ row.billableTokens | format_int }}<br>{{ t("columns.cost") }}: {{ row.costUsd | format_usd }}{% if row.cliCostUsd %} (+ CLI {{ row.cliCostUsd | format_usd }}){% endif %}<br>Duration: {{ row.durationMs | format_duration_ms }} | {{ row.summary }} |
587
+ {% endfor %}
588
+
589
+ ## {{ t("tokenSummary.heading") }}
590
+
591
+ | {{ t("tokenSummary.tableHeaderItem") }} | {{ t("columns.rawTokens") }} | {{ t("columns.billableTokensInputEquiv") }} | {{ t("columns.cost") }} |
592
+ |------|-----------|------------------------|------------|
593
+ | {{ t("tokenSummary.rowLead") }} | `{{ tokenUsage.lead.totalTokens | format_int }}` | `{{ tokenUsage.lead.billableTokens | format_int }}` | `{{ tokenUsage.lead.costUsd | format_usd }}` |
594
+ | {{ t("tokenSummary.rowWorkerTotal") }} | `{{ tokenUsage.worker.totalTokens | format_int }}` | `{{ tokenUsage.worker.billableTokens | format_int }}` | `{{ tokenUsage.worker.costUsd | format_usd }}` |
595
+ | {{ t("tokenSummary.rowGrandTotal") }} | **`{{ tokenUsage.grand.totalTokens | format_int }}`** | **`{{ tokenUsage.grand.billableTokens | format_int }}`** | **`{{ tokenUsage.grand.costUsd | format_usd }}`** |
596
+ {% if tokenUsage.cli and tokenUsage.cli.costUsd is not none and tokenUsage.cli.costUsd > 0 -%}
597
+ | {{ t("tokenSummary.rowCliExtra") }} | | | `{{ tokenUsage.cli.costUsd | format_usd }}` |
598
+ {% endif %}
599
+
600
+ {# At Phase 6 numeric cells are null and render as `--`.
601
+ Phase 7's okstra-token-usage.py populates tokenUsage in data.json then
602
+ re-invokes this renderer to produce the final markdown. #}