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