okstra 0.173.0 → 0.174.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 (62) hide show
  1. package/docs/architecture/storage-model.md +13 -3
  2. package/docs/architecture.md +5 -21
  3. package/docs/cli.md +3 -2
  4. package/docs/container.md +1 -1
  5. package/docs/contributor-change-matrix.md +1 -1
  6. package/docs/project-structure-overview.md +13 -13
  7. package/docs/task-process/README.md +1 -1
  8. package/docs/task-process/implementation-planning.md +1 -1
  9. package/package.json +1 -1
  10. package/runtime/BUILD.json +2 -2
  11. package/runtime/agents/workers/claude-worker.md +1 -1
  12. package/runtime/bin/lib/okstra/globals.sh +1 -1
  13. package/runtime/bin/okstra-provider-exec.py +29 -12
  14. package/runtime/bin/okstra-trace-cleanup.sh +58 -129
  15. package/runtime/prompts/lead/adapters/cmux.md +2 -0
  16. package/runtime/prompts/lead/okstra-lead-contract.md +1 -1
  17. package/runtime/prompts/lead/plan-body-verification.md +3 -3
  18. package/runtime/prompts/lead/report-writer.md +6 -6
  19. package/runtime/prompts/profiles/_common-contract.md +2 -2
  20. package/runtime/prompts/profiles/_implementation-executor.md +2 -0
  21. package/runtime/prompts/profiles/_implementation-verifier.md +2 -2
  22. package/runtime/prompts/profiles/error-analysis.md +1 -1
  23. package/runtime/prompts/profiles/implementation-planning.md +12 -9
  24. package/runtime/prompts/profiles/implementation.md +2 -1
  25. package/runtime/prompts/profiles/release-handoff.md +1 -1
  26. package/runtime/python/okstra_ctl/adapters/dispatch/__init__.py +1 -6
  27. package/runtime/python/okstra_ctl/adapters/hosts/external/relay.md +4 -4
  28. package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +5 -0
  29. package/runtime/python/okstra_ctl/conformance.py +68 -0
  30. package/runtime/python/okstra_ctl/dispatch_core.py +89 -39
  31. package/runtime/python/okstra_ctl/dispatch_state.py +142 -14
  32. package/runtime/python/okstra_ctl/doctor.py +2 -2
  33. package/runtime/python/okstra_ctl/domain/worker_exec.py +5 -0
  34. package/runtime/python/okstra_ctl/final_report_schema.py +5 -4
  35. package/runtime/python/okstra_ctl/pane_reclaim.py +13 -22
  36. package/runtime/python/okstra_ctl/render_final_report.py +15 -19
  37. package/runtime/python/okstra_ctl/report_contract.py +0 -1
  38. package/runtime/python/okstra_ctl/report_finalize.py +68 -9
  39. package/runtime/python/okstra_ctl/run.py +43 -2
  40. package/runtime/python/okstra_ctl/schema_excerpt.py +1 -1
  41. package/runtime/python/okstra_ctl/scope_provenance.py +1 -1
  42. package/runtime/python/okstra_ctl/session.py +69 -12
  43. package/runtime/python/okstra_ctl/team.py +51 -25
  44. package/runtime/python/okstra_ctl/tmux.py +19 -149
  45. package/runtime/python/okstra_ctl/worker_request.py +2 -0
  46. package/runtime/python/okstra_ctl/worktree.py +69 -3
  47. package/runtime/python/okstra_token_usage/cli.py +1 -1
  48. package/runtime/python/okstra_token_usage/collect.py +66 -6
  49. package/runtime/skills/okstra-setup/references/project-config.md +11 -0
  50. package/runtime/templates/reports/settings.template.json +0 -24
  51. package/runtime/validators/lib/fixtures.sh +49 -17
  52. package/runtime/validators/validate-implementation-plan-stages.py +63 -3
  53. package/runtime/validators/validate-run.py +14 -473
  54. package/runtime/validators/validate_session_conformance.py +1 -1
  55. package/src/cli-registry.mjs +8 -1
  56. package/src/commands/execute/team.mjs +3 -3
  57. package/src/commands/execute/worktree-status.mjs +109 -0
  58. package/src/commands/lifecycle/install.mjs +0 -2
  59. package/src/commands/report/finalize.mjs +13 -6
  60. package/runtime/bin/okstra-subagent-reclaim.sh +0 -26
  61. package/runtime/schemas/final-report-v1.0.schema.json +0 -6366
  62. package/runtime/templates/reports/final-report.template.md +0 -1258
@@ -1,1258 +0,0 @@
1
- {# OKSTRA Final Report — Jinja2 template (schemas/final-report-v1.0).
2
- Consumed by scripts/okstra-render-final-report.py against the JSON
3
- SSOT at runs/<task-type>/reports/final-report-<task-type>-<seq>.data.json.
4
- Custom filters: format_int, format_usd, format_duration_ms,
5
- yaml_scalar, yaml_inline_list, model_detail, mdcell (defined in
6
- render_final_report.py). Every data interpolation inside a table row
7
- carries `| mdcell` so a literal `|` in worker prose (e.g. "PASS|FAIL")
8
- cannot split the row — except t() labels and format_int/format_usd/
9
- format_duration_ms outputs, which cannot contain `|` by construction.
10
- Never apply mdcell outside table cells (code fences, headings, prose).
11
- Token Usage cells render as `--` while tokenUsage.*.totalTokens is
12
- null in Phase 6; Phase 7 mutates the data.json then re-renders. #}
13
- ---
14
- title: {{ frontmatter.title | yaml_scalar }}
15
- id: {{ frontmatter.id | yaml_scalar }}
16
- tags: {{ frontmatter.tags | yaml_inline_list }}
17
- status: {{ frontmatter.status }}
18
- aliases: {{ frontmatter.aliases | yaml_inline_list }}
19
- date: {{ frontmatter.date }}
20
- task-id: {{ frontmatter.taskId | yaml_scalar }}
21
- task-group: {{ frontmatter.taskGroup | yaml_scalar }}
22
- project-id: {{ frontmatter.projectId | yaml_scalar }}
23
- taskType: {{ frontmatter.taskType | yaml_scalar }}
24
- workerId: {{ frontmatter.workerId | yaml_scalar }}
25
- approved: {{ frontmatter.approved | yaml_scalar }}
26
- implementation-option: {{ frontmatter.implementationOption | yaml_scalar }}
27
- ---
28
-
29
- # {{ header.taskKey }} - Multi-Agent Cross Verification Final Report
30
-
31
- - Created at: {{ header.createdAt }}
32
- - Task Key: {{ header.taskKey }}
33
- - Task Type: {{ header.taskType }}
34
- - Report Owner: `{{ header.reportOwner }}` (model: `{{ header.leadModel | model_detail }}`)
35
- - Report Author: `{{ header.reportAuthor }}`
36
- - Lead Model: `{{ header.leadModel | model_detail }}`
37
- {% for row in followUpTasks if row.origin == 'phase-continuation' %}{% if loop.first %}- Next Step: run `/okstra-run`, select task `{{ header.taskKey }}`, choose task-type `{{ row.suggestedTaskType }}`
38
- {% endif %}{% endfor %}- Okstra Version: `{{ header.okstraVersion }}`
39
-
40
- {% if clarificationCarryIn and clarificationCarryIn.sourceFile %}
41
- ## 0. Clarification Response Carried In From Previous Run
42
-
43
- {{ t("sectionIntro.clarificationCarryIn") }}
44
-
45
- - Source file: `{{ clarificationCarryIn.sourceFile }}`
46
- {% if implementationPlanning and implementationPlanning.incrementalDecision %}
47
- {% set incrementalDecision = implementationPlanning.incrementalDecision %}
48
- ### 0.1 Incremental Re-Verification Scope
49
-
50
- - Decision mode: `{{ incrementalDecision.mode }}`
51
- - Reason: {{ incrementalDecision.reason }}
52
- {% if incrementalDecision.mode == 'incremental' %}
53
- - Re-verified stages: {% for s in incrementalDecision.reverifyStages %}`stage-{{ s }}`{% if not loop.last %}, {% endif %}{% else %}(none){% endfor +%}
54
- - Carried-forward stages: {% for s in incrementalDecision.carryStages %}`stage-{{ s }}` carried-forward (unchanged){% if not loop.last %}, {% endif %}{% else %}(none){% endfor +%}
55
-
56
- Carried-forward plan items retain their prior verdicts verbatim; each such item carries a `carriedForwardFromSeq` tag pointing at the run it was verified in.
57
- {% endif %}
58
- {% endif %}
59
-
60
- {% endif %}
61
- ## Summary of the Problem or Verification Target
62
-
63
- {{ t("sectionIntro.ticketCoverage") }}
64
-
65
- | {{ t("columns.recordMeta") }} | {{ t("columns.summary") }} |
66
- |--------|------------|
67
- {% for row in summary -%}
68
- | **{{ row.id | mdcell }}**<br>Ticket: `{{ row.ticketId | mdcell }}`<br>{{ t("columns.source") }}: {{ row.source | mdcell }} | {{ row.summary | mdcell }} |
69
- {% endfor %}
70
-
71
- ## Verdict Card
72
-
73
- {{ t("sectionIntro.verdictCard") }}
74
-
75
- | {{ t("verdictCard.tableHeaderLabel") }} | {{ t("verdictCard.tableHeaderValue") }} |
76
- |------|----|
77
- | Final Conclusion | {{ verdictCard.finalConclusion | mdcell }} |
78
- | Verdict Token | `{{ verdictCard.verdictToken | mdcell }}` |
79
- | Direction | `{{ verdictCard.direction | mdcell }}` |
80
- | Approval Required? | `{% if verdictCard.approvalRequired %}yes — {{ t("verdictCard.approvalRequiredSuffix") }}{% else %}no{% endif %}` |
81
- | Next Step | {{ verdictCard.nextStep | mdcell }} |
82
-
83
- {% if readerSummary %}
84
- ## {{ t("readerSummary.heading") }}
85
-
86
- {{ t("sectionIntro.readerSummary") }}
87
-
88
- | {{ t("readerSummary.tableHeaderItem") }} | {{ t("readerSummary.tableHeaderValue") }} |
89
- |------|----|
90
- | {{ t("readerSummary.decisionLabel") }} | {{ readerSummary.decision | mdcell }} |
91
- | {{ t("readerSummary.humanActionRequiredLabel") }} | {{ readerSummary.humanActionRequired | mdcell }} |
92
- | {{ t("readerSummary.blockingItemsLabel") }} | {{ readerSummary.blockingItems | mdcell }} |
93
- | {{ t("readerSummary.safeToSkipLabel") }} | {{ readerSummary.safeToSkip | mdcell }} |
94
- | {{ t("readerSummary.recommendedCommandLabel") }} | `{{ readerSummary.recommendedCommand | mdcell }}` |
95
-
96
- {% endif %}
97
- ## {{ t("rationale.heading") }}
98
-
99
- {{ t("rationale.intro") }}
100
-
101
- **{{ t("rationale.motivationLabel") }}** — {{ rationale.motivation }}
102
-
103
- **{{ t("rationale.problemLabel") }}** — {{ rationale.problem }}
104
-
105
- **{{ t("rationale.approachLabel") }}** — {{ rationale.approach }}
106
-
107
- **{{ t("rationale.justificationLabel") }}** — {{ rationale.justification }}
108
-
109
- ## 1. Clarification Items
110
-
111
- {{ t("sectionIntro.clarificationItems") }}
112
-
113
- {% if clarificationItems | length == 0 -%}
114
- {{ t("emptyState.noClarification") }}
115
- {%- else %}
116
- {{ t("clarification.fillAndRerun") }}
117
-
118
- - Claude Code: `/okstra-run resume-clarification task-key={{ header.taskKey }}`
119
- - {{ t("clarification.separateTerminalLabel") }}: `scripts/okstra.sh --resume-clarification --task-key {{ header.taskKey }}`
120
-
121
- | {{ t("columns.recordMeta") }} | Statement | Expected form | User input |
122
- |---|---|---|---|
123
- {% for row in clarificationItems -%}
124
- | **{{ row.id | mdcell }}**<br>Ticket: `{{ row.ticketId | mdcell }}`<br>Kind: `{{ row.kind | mdcell }}`<br>Blocks: `{{ row.blocks | mdcell }}`<br>Status: {{ row.status | mdcell }} | {{ row.statement | mdcell }} | {{ row.expectedForm | mdcell }} | {{ (row.userInput or '') | mdcell }} |
125
- {% endfor %}
126
- {%- endif %}
127
-
128
- ## 2. Evidence and Detailed Analysis
129
-
130
- ### 2.1 Primary Evidence
131
-
132
- {% if evidence.primary | length == 0 -%}
133
- {{ t("emptyState.primaryEvidence") }}
134
- {%- else %}
135
- | {{ t("columns.recordMeta") }} | Evidence |
136
- |--------|----------|
137
- {% for row in evidence.primary -%}
138
- | **{{ row.id | mdcell }}**<br>Ticket: `{{ row.ticketId | mdcell }}`<br>Source items: {{ row.sourceItems | join(', ') | mdcell }}<br>Source: {{ row.source | mdcell }} | {{ row.evidence | mdcell }} |
139
- {% endfor %}
140
- {%- endif %}
141
-
142
- {{ t("evidence.sourceItemsColumnNote") }}
143
-
144
- ### 2.2 Secondary Evidence or Alternate Interpretations
145
-
146
- {% if not evidence.secondary or evidence.secondary | length == 0 -%}
147
- {{ t("emptyState.secondaryEvidence") }}
148
- {%- else %}
149
- | {{ t("columns.recordMeta") }} | Hypothesis or supporting evidence | Source / confidence |
150
- |--------|-----------------------------------|---------------------|
151
- {% for row in evidence.secondary -%}
152
- | **{{ row.id | mdcell }}**<br>Ticket: `{{ row.ticketId | mdcell }}` | {{ row.hypothesis | mdcell }} | {{ row.confidence | mdcell }} |
153
- {% endfor %}
154
- {%- endif %}
155
-
156
- {% if header.taskType in ('requirements-discovery', 'error-analysis', 'implementation-planning') %}
157
-
158
- ### 2.3 End State Coverage{% if t("sectionAside.endStateCoverage") != "End State Coverage" %} ({{ t("sectionAside.endStateCoverage") }}){%- endif %}
159
-
160
- {% if endStateCoverage | length == 0 -%}
161
- {{ t("emptyState.endStateCoverage") }}
162
- {%- else %}
163
- {{ t("sectionIntro.endStateCoverage") }}
164
-
165
- | ID | {{ t("columns.disposition") }} | {{ t("columns.coveredBy") }} | {{ t("columns.evidence") }} | {{ t("columns.rationale") }} |
166
- |----|---------------|-----------|----------|-----------|
167
- {% for row in endStateCoverage -%}
168
- | {{ row.id | mdcell }} | `{{ row.disposition | mdcell }}` | {{ row.coveredBy | mdcell }} | {{ (row.evidence | join(", ")) | mdcell }} | {{ row.rationale | mdcell }} |
169
- {% endfor %}
170
- {%- endif %}
171
-
172
- {% endif %}
173
-
174
- {% if header.taskType == 'error-analysis' %}
175
- ### 2.4 Error Analysis Result{% if t("errorAnalysis.heading") != "Error Analysis Result" %} ({{ t("errorAnalysis.heading") }}){% endif %}
176
-
177
- - **{{ t("errorAnalysis.symptomVerbatim") }}:** {{ errorAnalysis.symptomVerbatim }}
178
- - **{{ t("errorAnalysis.observableFailure") }}:** {{ errorAnalysis.observableFailure }}
179
- - **{{ t("errorAnalysis.reproductionStatus") }}:** `{{ errorAnalysis.reproduction.status }}`
180
- - **{{ t("errorAnalysis.reproductionEvidence") }}:** {{ errorAnalysis.reproduction.evidence | join(", ") }}
181
- {% if errorAnalysis.reproduction.blockedReason %}- **{{ t("errorAnalysis.blockedReason") }}:** {{ errorAnalysis.reproduction.blockedReason }}
182
- {% endif %}
183
-
184
- {% if errorAnalysis.causeCandidates | length == 0 -%}
185
- {{ t("emptyState.errorAnalysisCauseCandidates") }}
186
- {%- else %}
187
- | ID | {{ t("errorAnalysis.candidate") }} | {{ t("errorAnalysis.supportingEvidence") }} | {{ t("errorAnalysis.falsifyingEvidence") }} | {{ t("errorAnalysis.confidence") }} | {{ t("errorAnalysis.disproveWith") }} |
188
- |---|---|---|---|---|---|
189
- {% for row in errorAnalysis.causeCandidates -%}
190
- | {{ row.id | mdcell }} | {{ row.statement | mdcell }} | {{ row.supportingEvidence | join(", ") | mdcell }} | {{ row.falsifyingEvidenceChecked | join(", ") | mdcell }} | `{{ row.confidence | mdcell }}` | {{ row.disproveWith | mdcell }} |
191
- {% endfor %}
192
- {%- endif %}
193
-
194
- - **{{ t("errorAnalysis.nextDiagnostic") }}:** {{ errorAnalysis.nextDiagnostic.action }}
195
- - **{{ t("errorAnalysis.confirmingSignal") }}:** {{ errorAnalysis.nextDiagnostic.confirmingSignal }}
196
- - **{{ t("errorAnalysis.rejectingSignal") }}:** {{ errorAnalysis.nextDiagnostic.rejectingSignal }}
197
- - **{{ t("errorAnalysis.route") }}:** `{{ errorAnalysis.routing.nextTaskType }}`{% if errorAnalysis.routing.leadingCauseId %} — `{{ errorAnalysis.routing.leadingCauseId }}`{% endif %} — {{ errorAnalysis.routing.rationale }}
198
- {% endif %}
199
-
200
- ## 3. Recommended Next Steps
201
-
202
- {% if recommendedNextSteps | length == 0 -%}
203
- - No further action required. Final verdict in section 7 stands.
204
- {%- else %}
205
- {% for step in recommendedNextSteps -%}
206
- {{ loop.index }}. {{ step.text }}
207
- {% if step.commands -%}
208
- {% for cmd in step.commands %}
209
- - {{ cmd.label }}:
210
- - Claude Code: `{{ cmd.claudeCode }}`
211
- - {{ t("clarification.separateTerminalLabel") }}: `{{ cmd.terminal }}`
212
- {% endfor -%}
213
- {%- endif %}
214
- {% endfor %}
215
- {%- endif %}
216
-
217
- ## 4. Follow-up Tasks{% if t("followUpTasks.headingAside") != "Follow-up Tasks" %} ({{ t("followUpTasks.headingAside") }}){% endif %}
218
-
219
- {% if followUpTasks | length == 0 -%}
220
- {{ t("emptyState.noFollowUp") }}
221
- {%- else %}
222
- | {{ t("columns.recordMeta") }} | Title | Scope (files/areas) | Reason / Why deferred |
223
- |--------|-------|---------------------|------------------------|
224
- {% for row in followUpTasks -%}
225
- | **{{ row.id | mdcell }}**<br>Ticket: `{{ row.ticketId | mdcell }}`<br>Origin: `{{ row.origin | mdcell }}`<br>New Task ID: `{{ row.newTaskId | mdcell }}`<br>Type: `{{ row.suggestedTaskType | mdcell }}`<br>Priority: `{{ row.priority | mdcell }}`<br>Auto-spawn: `{{ row.autoSpawn | mdcell }}` | {{ row.title | mdcell }} | {{ row.scope | mdcell }} | {{ row.reason | mdcell }} |
226
- {% endfor %}
227
- {%- endif %}
228
-
229
- ## 5. Missing Information and Risks
230
-
231
- {% if missingInformation | length == 0 -%}
232
- {{ t("emptyState.risks") }}
233
- {%- else %}
234
- | {{ t("columns.recordMeta") }} | Item | Risk if ignored | Mitigation Owner |
235
- |--------|------|-----------------|------------------|
236
- {% for row in missingInformation -%}
237
- | **{{ row.id | mdcell }}**<br>Ticket: `{{ row.ticketId | mdcell }}` | {{ row.item | mdcell }} | {{ row.risk | mdcell }} | {{ row.owner | mdcell }} |
238
- {% endfor %}
239
- {%- endif %}
240
-
241
- {% if header.taskType == 'implementation-planning' %}
242
- ## 5.4 Implementation Plan Deliverables
243
-
244
- ### Option Candidates{% if t("sectionAside.optionCandidates") != "Option Candidates" %} ({{ t("sectionAside.optionCandidates") }}){% endif %}
245
-
246
- {% for opt in implementationPlanning.optionCandidates %}
247
- **{{ opt.name }}**
248
-
249
- - File Structure:
250
-
251
- | {{ t("columns.recordMeta") }} | Path (and line-range) | Change summary |
252
- |------|------------------------|----------------|
253
- {% for fs in opt.fileStructure -%}
254
- | **{{ fs.id | mdcell }}**<br>Ticket: `{{ fs.ticketId | mdcell }}`<br>Action: {{ fs.action | mdcell }} | `{{ fs.path | mdcell }}` | {{ fs.summary | mdcell }}{% if fs.details %}<br><small>{{ fs.details | mdcell }}</small>{% endif %} |
255
- {% endfor %}
256
-
257
- - {{ t("implementationPlanning.optionInterfacesLabel") }}: {{ opt.interfaces }}
258
- - {{ t("implementationPlanning.optionBlastRadiusLabel") }}: {{ opt.blastRadius }}
259
-
260
- {% endfor %}
261
-
262
- ### Trade-off Matrix{% if t("sectionAside.tradeOffMatrix") != "Trade-off Matrix" %} ({{ t("sectionAside.tradeOffMatrix") }}){% endif %}
263
-
264
- | Option | Complexity | Risk | Reversibility | Test Coverage Cost | Rollout Cost |
265
- |--------|-----------|------|---------------|--------------------|--------------|
266
- {% for row in implementationPlanning.tradeoffMatrix -%}
267
- | {{ row.option | mdcell }} | {{ row.complexity | mdcell }} | {{ row.risk | mdcell }} | {{ row.reversibility | mdcell }} | {{ row.testCoverageCost | mdcell }} | {{ row.rolloutCost | mdcell }} |
268
- {% endfor %}
269
-
270
- ### Recommended Option{% if t("sectionAside.recommendedOption") != "Recommended Option" %} ({{ t("sectionAside.recommendedOption") }}){% endif %}
271
-
272
- | {{ t("implementationPlanning.recommendedTableHeaderLabel") }} | {{ t("implementationPlanning.recommendedTableHeaderValue") }} |
273
- |------|----|
274
- | Recommended Option | {{ implementationPlanning.recommendedOption.name | mdcell }} |
275
- | {{ t("implementationPlanning.coreReasonLabel") }} | {{ implementationPlanning.recommendedOption.coreReason | mdcell }} |
276
- | {{ t("implementationPlanning.rationaleLabel") }} | {{ implementationPlanning.recommendedOption.rationale | mdcell }} |
277
- | {{ t("implementationPlanning.rejectedSummaryLabel") }} | {{ implementationPlanning.recommendedOption.rejectedSummary | mdcell }} |
278
-
279
- ### Dependency / Migration Risk{% if t("sectionAside.dependencyRisk") != "Dependency / Migration Risk" %} ({{ t("sectionAside.dependencyRisk") }}){% endif %}
280
-
281
- {% if implementationPlanning.dependencyMigrationRisk | length == 0 -%}
282
- {{ t("emptyState.dependencyRisk") }}
283
- {%- else %}
284
- | ID | Kind | Item | {{ t("implementationPlanning.columnImpact") }} | {{ t("implementationPlanning.columnMitigation") }} |
285
- |----|------|------|------|------------------|
286
- {% for row in implementationPlanning.dependencyMigrationRisk -%}
287
- | {{ row.id | mdcell }} | {{ row.kind | mdcell }} | {{ row.item | mdcell }} | {{ row.impact | mdcell }} | {{ row.mitigation | mdcell }} |
288
- {% endfor %}
289
- {%- endif %}
290
-
291
- ### Cross-Project Dependencies{% if t("sectionAside.crossProjectDependencies") != "Cross-Project Dependencies" %} ({{ t("sectionAside.crossProjectDependencies") }}){% endif %}
292
-
293
- {% if implementationPlanning.crossProjectDependencies | length == 0 -%}
294
- {{ t("emptyState.crossProjectDependencies") }}
295
- {%- else %}
296
- {% for xp in implementationPlanning.crossProjectDependencies %}
297
- **{{ xp.id }} — [{{ xp.direction }}] {{ xp.project }}**
298
-
299
- - {{ t("implementationPlanning.crossProjectFields.requiredWork") }}: {{ xp.requiredWork }}
300
- - {{ t("implementationPlanning.crossProjectFields.verificationSignal") }}: {{ xp.verificationSignal }}
301
- - {{ t("implementationPlanning.crossProjectFields.linkedWork") }}: {{ xp.linkedWork }}
302
- - {{ t("implementationPlanning.crossProjectFields.howToStart") }}: {{ xp.howToStart }}
303
- {% endfor %}
304
- {{ t("implementationPlanning.crossProjectRecognitionNote") }}
305
- {%- endif %}
306
-
307
- ### Validation Checklist{% if t("sectionAside.validationChecklist") != "Validation Checklist" %} ({{ t("sectionAside.validationChecklist") }}){% endif %}
308
-
309
- | {{ t("columns.recordMeta") }} | Check | Command / Observation | Expected outcome |
310
- |--------|-------|------------------------|-------------------|
311
- {% for row in implementationPlanning.validationChecklist -%}
312
- | **{{ row.id | mdcell }}**<br>Ticket: `{{ row.ticketId | mdcell }}`<br>Phase: {{ row.phase | mdcell }} | {{ row.check | mdcell }} | `{{ row.commandOrObservation | mdcell }}` | {{ row.expectedOutcome | mdcell }} |
313
- {% endfor %}
314
-
315
- ### Rollback Strategy{% if t("sectionAside.rollbackStrategy") != "Rollback Strategy" %} ({{ t("sectionAside.rollbackStrategy") }}){% endif %}
316
-
317
- | ID | Step | Action | Trigger signal | {{ t("columns.checkMethod") }} |
318
- |----|------|--------|----------------|-----------|
319
- {% for row in implementationPlanning.rollbackStrategy -%}
320
- | {{ row.id | mdcell }} | {{ row.step | mdcell }} | `{{ row.action | mdcell }}` | {{ row.triggerSignal | mdcell }} | `{{ row.verificationMethod | mdcell }}` |
321
- {% endfor %}
322
-
323
- ### Requirement Coverage
324
-
325
- | ID | Source | Requirement | Covered by option / stage / step | Status |
326
- |----|--------|-------------|-----------------------------------|--------|
327
- {% for row in implementationPlanning.requirementCoverage -%}
328
- | {{ row.id | mdcell }} | `{{ row.source | mdcell }}` | {{ row.requirement | mdcell }} | {{ row.coveredBy | mdcell }} | `{% if row.status == "documented-deviation" %}documented-deviation — refs: {{ (row.decisionRefs | join(", ")) | mdcell }}; approval: {{ row.approvalDisposition | mdcell }}{% else %}{{ row.status | mdcell }}{% endif %}` |
329
- {% endfor %}
330
-
331
- ### Decision Drafts{% if t("sectionAside.decisionDrafts") != "Decision Drafts" %} ({{ t("sectionAside.decisionDrafts") }}){% endif %}
332
-
333
- {% if (implementationPlanning.decisionDrafts | length == 0) and (implementationPlanning.skippedAdrCandidates | length == 0) -%}
334
- {{ t("emptyState.decisionDrafts") }}
335
- {%- else %}
336
- {% for d in implementationPlanning.decisionDrafts %}
337
- #### {{ d.number }}-{{ d.slug }}
338
-
339
- - **{{ t("implementationPlanning.decisionDraftFields.status") }}:** {{ d.status }}
340
- - **{{ t("implementationPlanning.decisionDraftFields.context") }}:** {{ d.context }}
341
- - **{{ t("implementationPlanning.decisionDraftFields.decision") }}:** {{ d.decision }}
342
- - **{{ t("implementationPlanning.decisionDraftFields.consequences") }}:** {{ d.consequences }}
343
- - **{{ t("implementationPlanning.decisionDraftFields.alternativesConsidered") }}:** {{ d.alternativesConsidered }}
344
- {% endfor %}
345
- {% for s in implementationPlanning.skippedAdrCandidates %}
346
- - skipped adr-candidate: {{ s.topic }} — reason: {{ s.reason }}
347
- {% endfor %}
348
- {%- endif %}
349
-
350
- ## 5.5 Stage Map
351
-
352
- | stage | title | depends-on | step-count | exit-contract-summary |
353
- |-------|-------|------------|------------|-----------------------|
354
- {% for row in implementationPlanning.stageMap -%}
355
- | {{ row.stage | mdcell }} | {{ row.title | mdcell }} | {{ row.dependsOn | mdcell }} | {{ row.stepCount | mdcell }} | {{ row.exitContractSummary | mdcell }} |
356
- {% endfor %}
357
-
358
- {% for stage in implementationPlanning.stages %}
359
- ## 5.5.{{ stage.stage }} Stage {{ stage.stage }}: {{ stage.title }}
360
-
361
- - **Slice value:** {{ stage.sliceValue }}
362
- - **Acceptance:** {{ stage.acceptance }}
363
- {% if not stage.tddExemption %}
364
- - **Test case (success):** {{ stage.testCaseSuccess }}
365
- - **Test case (boundary):** {{ stage.testCaseBoundary }}
366
- - **Test case (failure):** {{ stage.testCaseFailure }}
367
- {% endif %}
368
- {% if stage.conformanceTests %}
369
- - **Conformance tests:** stage-{{ stage.stage }} — {{ stage.conformanceTests }}
370
- {% else %}
371
- - **Conformance exemption:** {{ stage.conformanceExemption }}
372
- {% endif %}
373
- {% if stage.tddExemption %}
374
- - **TDD exemption:** {{ stage.tddExemption }}
375
- {% endif %}
376
-
377
- ### Carry-In
378
-
379
- {{ stage.carryIn }}
380
-
381
- ### Stepwise Execution Order
382
-
383
- | step | action | files | command | outcome | expected |
384
- |------|--------|-------|---------|---------|----------|
385
- {% for row in stage.stepwiseExecution -%}
386
- | {{ row.step | mdcell }} | {{ row.action | mdcell }} | `{{ row.files | mdcell }}` | `{{ row.command | mdcell }}` | {{ row.outcome | mdcell }} | {{ row.expectedDetail | mdcell }} |
387
- {% endfor %}
388
-
389
- ### Stage Exit Contract
390
-
391
- {{ stage.exitContract }}
392
-
393
- ### Stage Validation
394
-
395
- {{ stage.stageValidation }}
396
-
397
- {% endfor %}
398
-
399
- ### 5.5.9 Plan Body Verification{% if t("sectionAside.planBodyVerification") != "Plan Body Verification" %} ({{ t("sectionAside.planBodyVerification") }}){% endif %}
400
-
401
- {{ t("sectionIntro.planBodyVerification") }}
402
-
403
- - **Round count**: `{{ implementationPlanning.planBodyVerification.roundCount }}`
404
- - **Gate result**: `{{ implementationPlanning.planBodyVerification.gateResult }}`
405
- {% if implementationPlanning.planBodyVerification.participatingAnalysers %}- **Participating analysers**: `{{ implementationPlanning.planBodyVerification.participatingAnalysers.voting }}` / `{{ implementationPlanning.planBodyVerification.participatingAnalysers.rostered }}`
406
- {% endif %}
407
- {% if implementationPlanning.planBodyVerification.gateBlockedBy %}- **Blocked by**: {% for cause in implementationPlanning.planBodyVerification.gateBlockedBy %}`{{ cause }}`{% if not loop.last %}, {% endif %}{% endfor %}
408
- {% endif %}
409
- {% if implementationPlanning.planBodyVerification.uniformVerifiers %}- **{{ t("implementationPlanning.planBodyUniformVerifierLabel") }}**: {% for u in implementationPlanning.planBodyVerification.uniformVerifiers %}`{{ u.worker }}` → `{{ u.verdict }}` ({{ u.itemCount }}){% if not loop.last %}, {% endif %}{% endfor %}
410
-
411
- > {{ t("implementationPlanning.planBodyUniformVerifierLegend") }}
412
- {% endif %}
413
- > {{ t("implementationPlanning.planBodyGateLegend") }}
414
- >
415
- > {{ t("implementationPlanning.planBodyBlockedByLegend") }}
416
-
417
- #### Verdict details
418
-
419
- {{ t("implementationPlanning.planBodyVerdictLegend") }}
420
-
421
- {{ t("implementationPlanning.planBodyBreakageLegend") }}
422
-
423
- {% for item in implementationPlanning.planBodyVerification.planItems %}
424
- **{{ item.id }} — {{ item.subject }}**{% if item.sourceSection %} ({{ t("implementationPlanning.planBodySourceLabel") }} {{ item.sourceSection }}){% endif %}{% if item.clarificationId %} — {{ t("implementationPlanning.planBodyBlockerLabel") }} {{ item.clarificationId }}{% endif %}{% if item.selfFixNote %} — {{ item.selfFixNote }}{% endif %}
425
-
426
-
427
- | Worker | Verdict | Breakage kind | Fixability | Note |
428
- |--------|---------|---------------|------------|------|
429
- {% for v in item.verdicts %}| {{ v.worker | mdcell }} | {{ v.verdict | mdcell }} | {{ (v.breakageKind or '--') | mdcell }} | {{ (v.fixability or '--') | mdcell }} | {{ (v.note or '') | mdcell }} |
430
- {% endfor %}
431
-
432
- {% endfor %}
433
- #### Dissent log
434
-
435
- {% if implementationPlanning.planBodyVerification.dissentLog | length == 0 -%}
436
- {{ t("emptyState.dissent") }}
437
- {%- else %}
438
- {% for row in implementationPlanning.planBodyVerification.dissentLog -%}
439
- - **{{ row.planItem }}**: `{{ row.workerRole }}` — {{ row.body }}
440
- {% endfor %}
441
- {%- endif %}
442
-
443
- ### 5.5.10 Implementation Design Preparation{% if t("implementationPlanning.designPreparation.heading") != "Implementation Design Preparation" %} ({{ t("implementationPlanning.designPreparation.heading") }}){% endif %}
444
-
445
- - **{{ t("implementationPlanning.designPreparation.mode") }}:** `{{ implementationPlanning.designPreparation.mode }}`
446
- - **{{ t("implementationPlanning.designPreparation.reason") }}:** {{ implementationPlanning.designPreparation.reason }}
447
-
448
- {% if implementationPlanning.designPreparation["items"] | length == 0 -%}
449
- {{ t("implementationPlanning.designPreparation.empty") }}
450
- {%- else %}
451
- {% for item in implementationPlanning.designPreparation["items"] %}
452
- #### {{ item.id }} — {{ item.title }}
453
-
454
- - **{{ t("implementationPlanning.designPreparation.kind") }}:** `{{ item.kind }}`
455
- - **{{ t("implementationPlanning.designPreparation.status") }}:** `{{ item.status }}`
456
- - **{{ t("implementationPlanning.designPreparation.stages") }}:** {{ item.stageRefs | join(", ") }}
457
- - **{{ t("implementationPlanning.designPreparation.need") }}:** {{ item.need }}
458
- {% if item.knownFacts %}
459
- - **{{ t("implementationPlanning.designPreparation.knownFacts") }}:**
460
- {% for fact in item.knownFacts %}
461
- - {{ fact.statement }} — {{ fact.evidence }}
462
- {% endfor %}
463
- {% endif %}
464
- {% if item.openQuestions %}
465
- - **{{ t("implementationPlanning.designPreparation.openQuestions") }}:** {{ item.openQuestions | join("; ") }}
466
- {% endif %}
467
- - **{{ t("implementationPlanning.designPreparation.aiProposal") }}:** {{ item.aiProposal.summary }}
468
- - **{{ t("implementationPlanning.designPreparation.proposalDetails") }}:** {{ item.aiProposal.details | join("; ") or t("implementationPlanning.designPreparation.none") }}
469
- - **{{ t("implementationPlanning.designPreparation.proposalAssumptions") }}:** {{ item.aiProposal.assumptions | join("; ") or t("implementationPlanning.designPreparation.none") }}
470
- - **{{ t("implementationPlanning.designPreparation.proposalEvidence") }}:** {{ item.aiProposal.evidence | join("; ") or t("implementationPlanning.designPreparation.none") }}
471
- - **{{ t("implementationPlanning.designPreparation.proposalConfidence") }}:** `{{ item.aiProposal.confidence }}`
472
- - **{{ t("implementationPlanning.designPreparation.humanConfirmation") }}:**
473
- - **{{ t("implementationPlanning.designPreparation.confirmationRequired") }}:** `{% if item.humanConfirmation.required %}yes{% else %}no{% endif %}`
474
- - **{{ t("implementationPlanning.designPreparation.confirmationReason") }}:** {{ item.humanConfirmation.reason }}
475
- - **{{ t("implementationPlanning.designPreparation.suggestedAction") }}:** {{ item.humanConfirmation.suggestedAction }}
476
- {% if item.replanTriggerFields %}
477
- - **{{ t("implementationPlanning.designPreparation.replanTriggerFields") }}:** `{{ item.replanTriggerFields | join("`, `") }}`
478
- {% endif %}
479
- {% if item.workingAssumption %}
480
- - **{{ t("implementationPlanning.designPreparation.workingAssumption") }}:** {{ item.workingAssumption }}
481
- {% endif %}
482
- {% if item.guardrails %}
483
- - **{{ t("implementationPlanning.designPreparation.guardrails") }}:** {{ item.guardrails | join("; ") }}
484
- {% endif %}
485
- {% if item.reviewAt %}
486
- {% if item.reviewAt.stage %}
487
- - **{{ t("implementationPlanning.designPreparation.reviewAt") }}:** {{ item.reviewAt.phase }} — stage {{ item.reviewAt.stage }}
488
- {% else %}
489
- - **{{ t("implementationPlanning.designPreparation.reviewAt") }}:** {{ item.reviewAt.phase }}
490
- {% endif %}
491
- {% endif %}
492
- {% if item.ifStillOpen %}
493
- - **{{ t("implementationPlanning.designPreparation.ifStillOpen") }}:** `{{ item.ifStillOpen }}`
494
- {% endif %}
495
- {% if item.requestPath %}
496
- - **{{ t("implementationPlanning.designPreparation.requestPath") }}:** `{{ item.requestPath }}`
497
- {% endif %}
498
- {% if item.blockReason %}
499
- - **{{ t("implementationPlanning.designPreparation.blockReason") }}:** {{ item.blockReason }}
500
- {% endif %}
501
- {% if item.requiredDecision %}
502
- - **{{ t("implementationPlanning.designPreparation.requiredDecision") }}:** {{ item.requiredDecision }}
503
- {% endif %}
504
- {% if item.notApplicableReason %}
505
- - **{{ t("implementationPlanning.designPreparation.notApplicableReason") }}:** {{ item.notApplicableReason }}
506
- {% endif %}
507
- {% endfor %}
508
- {%- endif %}
509
-
510
- ### 5.5.11 Variation-Point Analysis{% if t("implementationPlanning.variationPointAnalysis.heading") != "Variation-Point Analysis" %} ({{ t("implementationPlanning.variationPointAnalysis.heading") }}){% endif %}
511
-
512
- - **{{ t("implementationPlanning.variationPointAnalysis.hasMultiple") }}:** `{% if implementationPlanning.variationPointAnalysis.hasMultipleImplementations %}yes{% else %}no{% endif %}`
513
-
514
- {% if not implementationPlanning.variationPointAnalysis.hasMultipleImplementations -%}
515
- - **{{ t("implementationPlanning.variationPointAnalysis.rationale") }}:** {{ implementationPlanning.variationPointAnalysis.noVariationRationale }}
516
- {% else %}
517
- {% for point in implementationPlanning.variationPointAnalysis["points"] %}
518
- - **{{ t("implementationPlanning.variationPointAnalysis.behavior") }}:** {{ point.behavior }}
519
- - **{{ t("implementationPlanning.variationPointAnalysis.implementations") }}:** {{ point.implementations | join(", ") }}
520
- - **{{ t("implementationPlanning.variationPointAnalysis.evidence") }}:** {{ point.evidence }}
521
- - **{{ t("implementationPlanning.variationPointAnalysis.extract") }}:** `{% if point.extractionDecision.extract %}yes{% else %}no{% endif %}` — {{ point.extractionDecision.interfaceKind }} ({{ point.extractionDecision.coveredBy }}) — {{ point.extractionDecision.rationale }}
522
- {% endfor %}
523
- {% endif %}
524
-
525
- **{{ t("implementationPlanning.variationPointAnalysis.testSeams") }}:**
526
-
527
- {% if implementationPlanning.recommendedOption["testSeams"] | length == 0 -%}
528
- {{ t("implementationPlanning.variationPointAnalysis.seamEmpty") }}
529
- {% else %}
530
- {% for seam in implementationPlanning.recommendedOption["testSeams"] -%}
531
- - {{ seam.boundary }} — {{ seam.injectedAs }} → {{ seam.replacedInTest }}
532
- {% endfor %}
533
- {% endif %}
534
-
535
- {% endif %}
536
- {% if header.taskType == 'release-handoff' %}
537
- ## 5.6 Release Handoff Deliverables
538
-
539
- {{ t("releaseHandoff.auditNote") }}
540
-
541
- {% if releaseHandoff.handoffScope %}
542
- ### 5.6.0 Handoff Scope
543
-
544
- - Mode: `{{ releaseHandoff.handoffScope.mode | mdcell }}`
545
- {% if releaseHandoff.handoffScope.stages %}- Stages: {{ releaseHandoff.handoffScope.stages | join(', ') | mdcell }}
546
- {% endif %}{% if releaseHandoff.handoffScope.collectorBranch %}- Collector branch: `{{ releaseHandoff.handoffScope.collectorBranch | mdcell }}`
547
- {% endif %}{% if releaseHandoff.handoffScope.mergeCommits %}- Assemble merge commits: {{ releaseHandoff.handoffScope.mergeCommits | join(', ') | mdcell }}
548
- {% endif %}{% if releaseHandoff.handoffScope.dependencyClosureVerdict %}- Dependency closure: {{ releaseHandoff.handoffScope.dependencyClosureVerdict | mdcell }}
549
- {% endif %}
550
- {% endif %}
551
- ### 5.6.1 Source Verification Report
552
- {% if releaseHandoff.sourceVerificationReports %}
553
- | Stage | Report path (project-relative) | Quoted `Verdict Token` row |
554
- |-------|--------------------------------|----------------------------|
555
- {% for row in releaseHandoff.sourceVerificationReports -%}
556
- | {{ row.stage | mdcell }} | `{{ row.path | mdcell }}` | {{ row.verdictTokenQuote | mdcell }} |
557
- {% endfor %}
558
- {%- else %}
559
- - Path (project-relative): `{{ releaseHandoff.sourceVerificationReport.path }}`
560
- - Quoted `Verdict Token` row from that report's `## 7.` table:
561
- > {{ releaseHandoff.sourceVerificationReport.verdictTokenQuote | mdquote(2) }}
562
- {% endif %}
563
-
564
- ### 5.6.2 Feature Branch & Working-Tree State{% if t("releaseHandoff.branchStateAside") != "captured at run start" %} ({{ t("releaseHandoff.branchStateAside") }}){% endif %}
565
-
566
- - Feature branch: `{{ releaseHandoff.featureBranchState.branchName }}`
567
- - {{ t("releaseHandoff.gitStatusShortLabel") }}:
568
- ```
569
- {{ releaseHandoff.featureBranchState.gitStatusShort | indent(2) }}
570
- ```
571
- - {{ t("releaseHandoff.existingPrLabel") }}: `{{ releaseHandoff.featureBranchState.existingPrUrl or '(none)' }}`
572
-
573
- ### 5.6.3 User Selections{% if t("releaseHandoff.userSelectionsAside") != "menu response log" %} ({{ t("releaseHandoff.userSelectionsAside") }}){% endif %}
574
-
575
- | {{ t("releaseHandoff.questionsTableHeader.questionId") }} | {{ t("releaseHandoff.questionsTableHeader.questionBody") }} | {{ t("releaseHandoff.questionsTableHeader.userResponse") }} | {{ t("releaseHandoff.questionsTableHeader.allowedOptions") }} |
576
- |---------|-----------|--------------------|--------------------|
577
- | H1 | {{ t("releaseHandoff.h1Body") }} | `{{ releaseHandoff.userSelections.h1 | mdcell }}` | `local checkout` / `push + PR` / `skip` |
578
- {% if releaseHandoff.userSelections.h1c %}
579
- | H1c | Local checkout target | `{{ releaseHandoff.userSelections.h1c | mdcell }}` | `whole-task branch` / `stage <N> stack branch` |
580
- {% endif %}
581
- | H2 | {{ t("releaseHandoff.h2Body") }} | `{{ (releaseHandoff.userSelections.h2 or t("releaseHandoff.h2DefaultLabel")) | mdcell }}` | {{ t("releaseHandoff.h2OptionsLabel") }} |
582
- | H2b | Merge conflict probe | `{{ (releaseHandoff.userSelections.h2b or releaseHandoff.mergeConflictProbe.kind) | mdcell }}` | `not-run` / `clean` / `proceed anyway` / `change base branch` / `cancel` |
583
- | H3 | {{ t("releaseHandoff.h3Body") }} | `{{ releaseHandoff.userSelections.h3 | mdcell }}` | `not-run` / `use as-is` / `edit then proceed` / `cancel` |
584
-
585
- ### 5.6.4 Executed Commands
586
-
587
- {% if releaseHandoff.executedCommands | length == 0 -%}
588
- - {{ t("releaseHandoff.noMutationNote") }}
589
- {%- else %}
590
- | # | command (verbatim) | exit code | {{ t("releaseHandoff.commandsTableHeader.outputSummary") }} |
591
- |---|---------------------|-----------|--------------------|
592
- {% for row in releaseHandoff.executedCommands -%}
593
- | {{ row.number | mdcell }} | `{{ row.command | mdcell }}` | `{{ row.exitCode | mdcell }}` | {{ row.outputSummary | mdcell }} |
594
- {% endfor %}
595
- {%- endif %}
596
-
597
- ### 5.6.5 Commit List
598
-
599
- {% if releaseHandoff.commitList.empty -%}
600
- - No implementation commits found; release-handoff is blocked.
601
- {%- else %}
602
- | Short SHA | Full SHA | Subject | Files |
603
- |-----------|----------|---------|-------|
604
- {% for row in releaseHandoff.commitList -%}
605
- | `{{ row.shortSha | mdcell }}` | `{{ row.fullSha | mdcell }}` | {{ row.subject | mdcell }} | {{ row.files | mdcell }} |
606
- {% endfor %}
607
- {%- endif %}
608
-
609
- ### 5.6.6 Merge Conflict Probe
610
-
611
- {% if releaseHandoff.mergeConflictProbe.kind == 'not-run' -%}
612
- - Not run (user picked local checkout or skip).
613
- {%- elif releaseHandoff.mergeConflictProbe.kind == 'clean' -%}
614
- - Clean — no conflicts against {{ releaseHandoff.mergeConflictProbe.baseBranch }} at {{ releaseHandoff.mergeConflictProbe.baseSha }}.
615
- {%- else -%}
616
- - Conflicts detected against {{ releaseHandoff.mergeConflictProbe.baseBranch }} at {{ releaseHandoff.mergeConflictProbe.baseSha }}; user chose {{ releaseHandoff.mergeConflictProbe.userChoice }}. Conflicting paths: {{ releaseHandoff.mergeConflictProbe.conflictingPaths | join(', ') }}.
617
- {%- endif %}
618
-
619
- ### 5.6.7 Pull Request Outcome
620
-
621
- {% if releaseHandoff.pullRequestOutcome.kind == 'no-action' -%}
622
- - No PR action requested.
623
- {%- elif releaseHandoff.pullRequestOutcome.kind == 'created' -%}
624
- - PR created: {{ releaseHandoff.pullRequestOutcome.url }} — title: {{ releaseHandoff.pullRequestOutcome.title }} (base: {{ releaseHandoff.pullRequestOutcome.baseBranch }})
625
- {%- elif releaseHandoff.pullRequestOutcome.kind == 'reused' -%}
626
- - PR reused: {{ releaseHandoff.pullRequestOutcome.url }}
627
- {%- else -%}
628
- - PR creation skipped: {{ releaseHandoff.pullRequestOutcome.reason }}
629
- {%- endif %}
630
-
631
- ### 5.6.8 Routing Recommendation
632
-
633
- {{ releaseHandoff.routingRecommendation }}
634
-
635
- ### 5.6.9 Local Checkout Outcome
636
-
637
- - Status: `{{ releaseHandoff.localCheckoutOutcome.status | mdcell }}`
638
- {% if releaseHandoff.localCheckoutOutcome.status == 'checked-out' %}- Checked out `{{ releaseHandoff.localCheckoutOutcome.branch | mdcell }}` into `{{ releaseHandoff.localCheckoutOutcome.mainWorktreePath | mdcell }}`
639
- - okstra worktree: {% if releaseHandoff.localCheckoutOutcome.removedWorktree %}`{{ releaseHandoff.localCheckoutOutcome.removedWorktree | mdcell }}` removed{% else %}none removed — already torn down, so the branch survived{% endif %}
640
- {% endif %}
641
- {% endif %}
642
- {% if header.taskType == 'implementation' %}
643
- ## 5.7 Implementation Deliverables
644
-
645
- ### 5.7.1 Approved Plan Reference
646
-
647
- - Plan file (project-relative): `{{ implementation.approvedPlanReference.planFile }}`
648
- - Approval evidence:
649
- > {{ implementation.approvedPlanReference.approvalEvidence | mdquote(2) }}
650
- - {{ t("executionMeta.runExecutorWorktreePath") }}: `{{ implementation.approvedPlanReference.executorWorktreePath }}`
651
- - {{ t("executionMeta.runBaseRef") }}: `{{ implementation.approvedPlanReference.baseRefSha }}`
652
-
653
- ### 5.7.2 Commit List
654
-
655
- {% if implementation.commitList | length == 0 -%}
656
- - No implementation commits produced; routing recommendation must be back to implementation-planning.
657
- {%- else %}
658
- | # | Short SHA | Full SHA | Plan Step | Subject | Files |
659
- |---|-----------|----------|-----------|---------|-------|
660
- {% for row in implementation.commitList -%}
661
- | {{ row.number | mdcell }} | `{{ row.shortSha | mdcell }}` | `{{ row.fullSha | mdcell }}` | {{ row.planStep | mdcell }} | {{ row.subject | mdcell }} | {{ row.files | mdcell }} |
662
- {% endfor %}
663
- {%- endif %}
664
-
665
- ### 5.7.3 Diff Summary
666
-
667
- ```
668
- {{ implementation.diffSummary.rawStat }}
669
- ```
670
-
671
- | File | Action | Lines (+/-) | Plan step / Out-of-plan |
672
- |------|--------|-------------|--------------------------|
673
- {% for row in implementation.diffSummary.files -%}
674
- | `{{ row.file | mdcell }}` | {{ row.action | mdcell }} | `{{ row.lines | mdcell }}` | {{ row.planStep | mdcell }} |
675
- {% endfor %}
676
-
677
- ### 5.7.4 Out-of-plan Edits
678
-
679
- {% if implementation.outOfPlanEdits | length == 0 -%}
680
- {{ t("emptyState.outOfPlanEdits") }}
681
- {%- else %}
682
- | ID | File | Rationale | Trigger |
683
- |----|------|-----------|---------|
684
- {% for row in implementation.outOfPlanEdits -%}
685
- | {{ row.id | mdcell }} | `{{ row.file | mdcell }}` | {{ row.rationale | mdcell }} | {{ row.trigger | mdcell }} |
686
- {% endfor %}
687
- {%- endif %}
688
-
689
- ### 5.7.5 Stage Sidecar Evidence
690
-
691
- - Stage: `{{ implementation.stageSidecarEvidence.stageNumber }}` — {{ implementation.stageSidecarEvidence.stageTitle }}
692
- {% if implementation.stageSidecarEvidence.withheld -%}
693
- - Carry sidecar **withheld** — not written to `carry/stage-{{ implementation.stageSidecarEvidence.stageNumber }}.json`: {{ implementation.stageSidecarEvidence.withheld }}
694
- {% endif -%}
695
- - Carry sidecar JSON:
696
- ```json
697
- {{ implementation.stageSidecarEvidence.carryJson | indent(2) }}
698
- ```
699
- - Appended `consumers.jsonl` rows:
700
- {% for row in implementation.stageSidecarEvidence.consumerRows -%}
701
- > {{ row | mdquote(2) }}
702
- {% endfor %}
703
-
704
- ### 5.7.6 Validation Evidence
705
-
706
- | Phase | Command | Exit code | Output tail | TDD evidence |
707
- |-------|---------|-----------|-------------|--------------|
708
- {% for row in implementation.validationEvidence -%}
709
- | {{ row.phase | mdcell }} | `{{ row.command | mdcell }}` | `{{ row.exitCode | mdcell }}` | {{ row.outputTail | mdcell }} | {{ (row.tddEvidence or '--') | mdcell }} |
710
- {% endfor %}
711
-
712
- ### 5.7.7 Verifier Results
713
-
714
- {% for block in implementation.verifierResults %}
715
- - **{{ block.verifier }}** — Verdict: `{{ block.verdict }}`
716
- - Read-only command log: {{ block.readOnlyCommandLog }}
717
- - Independent validation re-run: {{ block.independentValidationRerun }}
718
- - Style / lint / type-check: {{ block.styleLintTypecheck or '--' }}
719
- - Declined fix recommendations: {{ block.declinedFixRecommendations or t("emptyState.declinedFixRecommendations") }}
720
- - Discrepancy: {{ block.discrepancy or t("emptyState.discrepancy") }}
721
- {% endfor %}
722
-
723
- ### 5.7.8 Rollback Verification
724
-
725
- | Category | Rollback command | Verification | Result |
726
- |----------|-------------------|---------------|--------|
727
- {% for row in implementation.rollbackVerification -%}
728
- | {{ row.category | mdcell }} | `{{ row.rollbackCommand | mdcell }}` | {{ row.verification | mdcell }} | `{{ row.result | mdcell }}` |
729
- {% endfor %}
730
-
731
- ### 5.7.9 Manual User Test (Draft)
732
-
733
- {% if implementation.manualUserTest.applicable -%}
734
- {% for item in implementation.manualUserTest.items %}
735
- - **{{ item.target }}**
736
- - {{ t("manualUserTest.environmentSetup") }}: {{ item.environmentSetup }}
737
- - {{ t("manualUserTest.steps") }}:
738
- {% for step in item.steps %} {{ loop.index }}. {{ step }}
739
- {% endfor %} - {{ t("manualUserTest.expectedResult") }}: {{ item.expectedResult }}
740
- {% endfor %}
741
- {%- else -%}
742
- - {{ t("manualUserTest.notApplicable") }}: {{ implementation.manualUserTest.exemptionReason }}
743
- {%- endif %}
744
-
745
- ### 5.7.10 Routing Recommendation
746
-
747
- {{ implementation.routingRecommendation }}
748
-
749
- {% endif %}
750
- {% if header.taskType == 'final-verification' %}
751
- ## 5.8 Final Verification Deliverables
752
-
753
- ### 5.8.1 Source Implementation Report
754
-
755
- - Path (project-relative): `{{ finalVerification.sourceImplementationReport.path }}`
756
- - {{ t("evidenceMeta.commitListSummary") }}:
757
- > {{ finalVerification.sourceImplementationReport.commitListQuote | mdquote(2) }}
758
- - {{ t("evidenceMeta.diffSummaryQuote") }}:
759
- > {{ finalVerification.sourceImplementationReport.diffSummaryQuote | mdquote(2) }}
760
- - {{ t("evidenceMeta.targetWorktreePath") }}: `{{ finalVerification.sourceImplementationReport.worktreePath }}`
761
- - {{ t("evidenceMeta.implementationBaseRef") }}: `{{ finalVerification.sourceImplementationReport.implementationBaseRef }}`
762
- - {{ t("evidenceMeta.capturedHeadSha") }}: `{{ finalVerification.sourceImplementationReport.capturedHeadSha }}`
763
- - {{ t("evidenceMeta.gitStatusAtRunStart") }}:
764
- ```
765
- {{ finalVerification.sourceImplementationReport.gitStatusShort | indent(2) }}
766
- ```
767
- - {{ t("evidenceMeta.gitDiffStatAtRunStart") }}:
768
- ```
769
- {{ finalVerification.sourceImplementationReport.gitDiffStat | indent(2) }}
770
- ```
771
- {% if verificationScope in ['whole-task', 'single-stage'] %}- {{ t("finalVerification.verificationScope") }}: `{{ verificationScope }}`
772
- {% endif %}{% if finalVerification.stageReports %}- {{ t("finalVerification.stageReportsLabel") }}:
773
- {% for row in finalVerification.stageReports %} - stage {{ row.stage }}: `{{ row.reportPath }}`
774
- {% endfor %}{% endif %}
775
-
776
- ### 5.8.2 Acceptance Blockers
777
-
778
- {% if finalVerification.acceptanceBlockers | length == 0 -%}
779
- - No acceptance blockers found.
780
- {%- else %}
781
- | ID | Severity | Statement | Evidence | Recommended follow-up phase |
782
- |----|----------|-----------|----------|------------------------------|
783
- {% for row in finalVerification.acceptanceBlockers -%}
784
- | {{ row.id | mdcell }} | `{{ row.severity | mdcell }}` | {{ row.statement | mdcell }} | {{ row.evidence | mdcell }} | `{{ row.followUpPhase | mdcell }}` |
785
- {% endfor %}
786
- {%- endif %}
787
-
788
- ### 5.8.3 Residual Risk
789
-
790
- {% if finalVerification.residualRisk | length == 0 -%}
791
- {{ t("emptyState.lingeringRisks") }}
792
- {%- else %}
793
- | ID | Item | Mitigation owner | Escalation trigger |
794
- |----|------|------------------|---------------------|
795
- {% for row in finalVerification.residualRisk -%}
796
- | {{ row.id | mdcell }} | {{ row.item | mdcell }} | {{ row.owner | mdcell }} | {{ row.escalationTrigger | mdcell }} |
797
- {% endfor %}
798
- {%- endif %}
799
-
800
- ### 5.8.4 Validation Evidence{% if t("finalVerification.validationEvidenceAside") != "requirements coverage" %} ({{ t("finalVerification.validationEvidenceAside") }}){% endif %}
801
-
802
- | ID | {{ t("finalVerification.columnRequirement") }} | Artifact | Status |
803
- |----|--------------------------------|----------|--------|
804
- {% for row in finalVerification.validationEvidence -%}
805
- | {{ row.id | mdcell }} | {{ row.requirement | mdcell }} | `{{ row.artifact | mdcell }}` | {{ row.status | mdcell }} |
806
- {% endfor %}
807
-
808
- ### 5.8.5 Read-only Command Log
809
-
810
- | # | Tier | Command (verbatim) | Status | Exit code | Output tail |
811
- |---|------|---------------------|--------|-----------|-------------|
812
- {% for row in finalVerification.readonlyCommandLog -%}
813
- | {{ row.number | mdcell }} | {{ row.tier | mdcell }} | `{{ row.command | mdcell }}` | `{{ row.status | mdcell }}` | {{ (row.exitCode if row.exitCode is not none else '—') | mdcell }} | {{ (row.statusReason if row.status in ['rejected', 'env-unavailable', 'advisory'] else row.outputTail) | mdcell }} |
814
- {% endfor %}
815
-
816
- ### 5.8.6 Conditional Acceptance Conditions
817
-
818
- {% if not finalVerdict.conditionalAcceptanceConditions -%}
819
- - Not applicable (verdict is not `conditional-accept`).
820
- {%- else %}
821
- | ID | Condition | Evidence required | Blocks release-handoff |
822
- |----|-----------|-------------------|------------------------|
823
- {% for row in finalVerdict.conditionalAcceptanceConditions -%}
824
- | {{ row.id | mdcell }} | {{ row.condition | mdcell }} | {{ row.evidenceRequired | mdcell }} | {{ row.blocksReleaseHandoff | mdcell }} |
825
- {% endfor %}
826
- {%- endif %}
827
-
828
- ### 5.8.7 Manual User Test Results
829
-
830
- {% if finalVerification.manualUserTest.applicable -%}
831
- | {{ t("manualUserTest.performed") }} | {{ t("manualUserTest.result") }} | {{ t("manualUserTest.observed") }} |
832
- |---|---|---|
833
- {% for row in finalVerification.manualUserTest.results -%}
834
- | {{ row.target | mdcell }} — {{ row.performed | mdcell }} | `{{ row.result | mdcell }}` | {{ row.observed | mdcell }} |
835
- {% endfor %}
836
- {%- else -%}
837
- - {{ t("manualUserTest.notApplicable") }}: {{ finalVerification.manualUserTest.exemptionReaffirm }}
838
- {%- endif %}
839
-
840
- ### 5.8.8 Routing Recommendation
841
-
842
- {{ finalVerification.routingRecommendation }}
843
-
844
- ### 5.8.9 Could-Not-Verify Roll-up
845
-
846
- Single scan of every agreed check that this run did NOT confirm — requirement gaps, commands not run (rejected / not-configured / env-unavailable), advisory commands, and blocked manual tests — aggregated from the sections above.
847
-
848
- {% for row in finalVerification.validationEvidence if row.status == 'gap' -%}
849
- - `{{ row.id | mdcell }}` requirement gap — {{ row.requirement | mdcell }}
850
- {% endfor -%}
851
- {% for row in finalVerification.readonlyCommandLog if row.status in ['rejected', 'not-configured', 'env-unavailable', 'advisory'] -%}
852
- - `{{ row.command | mdcell }}` — {{ row.status | mdcell }}: {{ row.statusReason | mdcell }}
853
- {% endfor -%}
854
- {% if finalVerification.manualUserTest.applicable -%}
855
- {% for row in finalVerification.manualUserTest.results if row.result == 'blocked' -%}
856
- - manual: {{ row.target | mdcell }} — {{ row.performed | mdcell }} (blocked): {{ row.observed | mdcell }}
857
- {% endfor -%}
858
- {% endif -%}
859
- {% if not (
860
- finalVerification.validationEvidence | selectattr('status', 'equalto', 'gap') | list
861
- or finalVerification.readonlyCommandLog | selectattr('status', 'in', ['rejected', 'not-configured', 'env-unavailable', 'advisory']) | list
862
- or (
863
- finalVerification.manualUserTest.applicable
864
- and finalVerification.manualUserTest.results | selectattr('result', 'equalto', 'blocked') | list
865
- )
866
- ) -%}
867
- - All agreed checks were executed or covered — nothing left unverified.
868
- {%- endif %}
869
-
870
- {% endif %}
871
- {% if analysisCommon %}
872
- ## 5.9 Analysis Basis
873
-
874
- {{ t("analysis.basisIntro") }}
875
-
876
- ### 5.9.1 Snapshot and Scope
877
-
878
- | Item | Value |
879
- |------|-------|
880
- | Run sequence | `{{ analysisCommon.runSeq | mdcell }}` |
881
- | Source commit | `{{ analysisCommon.sourceCommit | mdcell }}` |
882
- | Included paths | {{ analysisCommon.scope.includedPaths | join(', ') | mdcell }} |
883
- | Excluded paths | {{ analysisCommon.scope.excludedPaths | join(', ') | mdcell }} |
884
- | Unscanned paths | {{ (analysisCommon.scope.unscannedPaths | join(', ') or '--') | mdcell }} |
885
- | Resolved target mode | `{{ (analysisCommon.scope.resolvedTarget.inputMode or '--') | mdcell }}` |
886
- | Resolved target | {{ (analysisCommon.scope.resolvedTarget.requestedValue or '--') | mdcell }} |
887
-
888
- ### 5.9.2 Evidence Inputs
889
-
890
- {% if analysisCommon.evidenceInputs | length == 0 -%}
891
- {{ t("analysis.empty") }}
892
- {%- else %}
893
- | Task key | Task type | Report path | Run | Source commit | Relation | Freshness | Review status |
894
- |----------|-----------|-------------|-----|---------------|----------|-----------|---------------|
895
- {% for row in analysisCommon.evidenceInputs -%}
896
- | {{ row.taskKey | mdcell }} | `{{ row.taskType | mdcell }}` | `{{ row.reportPath | mdcell }}` | `{{ row.runSeq | mdcell }}` | `{{ row.sourceCommit | mdcell }}` | `{{ row.relation | mdcell }}` | `{{ row.freshness | mdcell }}` | `{{ row.reviewStatus | mdcell }}` |
897
- {% endfor %}
898
- {%- endif %}
899
-
900
- ### 5.9.3 Confirmed Facts
901
-
902
- {% if analysisCommon.confirmedFacts | length == 0 -%}
903
- {{ t("analysis.empty") }}
904
- {%- else %}
905
- | ID | Claim | Current code evidence | Confidence | Review resolution |
906
- |----|-------|-----------------------|------------|-------------------|
907
- {% for row in analysisCommon.confirmedFacts -%}
908
- {% set review = namespace(value=t("analysis.reviewNotRecorded")) -%}
909
- {% for resolution in analysisCommon.analysisReviewResolution if resolution.affectedId == row.id -%}
910
- {% set review.value = resolution.outcome ~ ': ' ~ resolution.resolution -%}
911
- {% endfor -%}
912
- | {{ row.id | mdcell }} | {{ row.statement | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} | confirmed | {{ review.value | mdcell }} |
913
- {% endfor %}
914
- {%- endif %}
915
-
916
- ### 5.9.4 Inferences and Unknowns
917
-
918
- {% if analysisCommon.inferences | length == 0 -%}
919
- {{ t("analysis.empty") }}
920
- {%- else %}
921
- | ID | Claim | Evidence IDs | Confidence |
922
- |----|-------|--------------|------------|
923
- {% for row in analysisCommon.inferences -%}
924
- | {{ row.id | mdcell }} | {{ row.statement | mdcell }} | {{ row.evidenceIds | join(', ') | mdcell }} | `{{ row.confidence | mdcell }}` |
925
- {% endfor %}
926
- {%- endif %}
927
-
928
- {% if analysisCommon.unknowns | length > 0 %}
929
- | ID | Question | Reason | Affects verdict |
930
- |----|----------|--------|-----------------|
931
- {% for row in analysisCommon.unknowns -%}
932
- | {{ row.id | mdcell }} | {{ row.question | mdcell }} | {{ row.reason | mdcell }} | `{{ row.affectsVerdict | mdcell }}` |
933
- {% endfor %}
934
- {% endif %}
935
-
936
- ### 5.9.5 Analysis Review Resolution
937
-
938
- {% if analysisCommon.analysisReviewResolution | length == 0 -%}
939
- {{ t("analysis.empty") }}
940
- {%- else %}
941
- | Affected ID | Outcome | Resolution | Evidence |
942
- |-------------|---------|------------|----------|
943
- {% for row in analysisCommon.analysisReviewResolution -%}
944
- | {{ row.affectedId | mdcell }} | `{{ row.outcome | mdcell }}` | {{ row.resolution | mdcell }} | {{ row.evidence | join('<br>') | mdcell }} |
945
- {% endfor %}
946
- {%- endif %}
947
-
948
- {% endif %}
949
- {% if projectAnalysis %}
950
- ## 5.10 Project Analysis
951
-
952
- {{ t("analysis.projectIntro") }}
953
-
954
- {% if projectAnalysis.techStack %}
955
- ### 5.10.0 Tech Stack
956
-
957
- | Language | Version | Version source | Files | Lines |
958
- |----------|---------|----------------|-------|-------|
959
- {% for row in projectAnalysis.techStack.languages -%}
960
- | {{ row.name | mdcell }} | {{ row.version | mdcell }} | {{ row.versionSource | mdcell }} | {{ row.fileCount | default('--') | mdcell }} | {{ row.lineCount | default('--') | mdcell }} |
961
- {% endfor %}
962
- {% if projectAnalysis.techStack.frameworks %}
963
- | Framework | Version | Version source | Role |
964
- |-----------|---------|----------------|------|
965
- {% for row in projectAnalysis.techStack.frameworks -%}
966
- | {{ row.name | mdcell }} | {{ row.version | mdcell }} | {{ row.versionSource | mdcell }} | {{ row.role | mdcell }} |
967
- {% endfor %}
968
- {% endif %}
969
- {% if projectAnalysis.techStack.toolchain %}
970
- | Tool kind | Name | Version | Command |
971
- |-----------|------|---------|---------|
972
- {% for row in projectAnalysis.techStack.toolchain -%}
973
- | {{ row.kind | mdcell }} | {{ row.name | mdcell }} | {{ row.version | default('--') | mdcell }} | {{ row.command | default('--') | mdcell }} |
974
- {% endfor %}
975
- {% endif %}
976
- {% endif %}
977
-
978
- ### 5.10.1 Components
979
-
980
- | ID | Name | Responsibility | Paths | Current code evidence |
981
- |----|------|----------------|-------|-----------------------|
982
- {% for row in projectAnalysis.components -%}
983
- | {{ row.id | mdcell }} | {{ row.name | mdcell }} | {{ row.responsibility | mdcell }} | {{ row.paths | join(', ') | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
984
- {% endfor %}
985
-
986
- ### 5.10.2 Dependencies and Boundaries
987
-
988
- | From | To | Direction | Current code evidence |
989
- |------|----|-----------|-----------------------|
990
- {% for row in projectAnalysis.dependencies -%}
991
- | {{ row.fromComponentId | mdcell }} | {{ row.toComponentId | mdcell }} | {{ row.direction | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
992
- {% endfor %}
993
-
994
- | Kind | Path | Symbol | Role | Current code evidence |
995
- |------|------|--------|------|-----------------------|
996
- {% for row in projectAnalysis.entryPoints -%}
997
- | {{ row.kind | mdcell }} | `{{ row.path | mdcell }}` | `{{ row.symbol | mdcell }}` | {{ row.role | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
998
- {% endfor %}
999
-
1000
- ### 5.10.3 Stores and External Systems
1001
-
1002
- | Store | Owner | Read boundary | Write boundary | Current code evidence |
1003
- |-------|-------|---------------|----------------|-----------------------|
1004
- {% for row in projectAnalysis.dataStores -%}
1005
- | {{ row.name | mdcell }} | {{ row.ownerComponentId | mdcell }} | {{ row.readBoundary | mdcell }} | {{ row.writeBoundary | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
1006
- {% endfor %}
1007
-
1008
- | External system | Adapter | Direction | Current code evidence |
1009
- |-----------------|---------|-----------|-----------------------|
1010
- {% for row in projectAnalysis.externalSystems -%}
1011
- | {{ row.name | mdcell }} | {{ row.adapter | mdcell }} | {{ row.direction | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
1012
- {% endfor %}
1013
-
1014
- {% if projectAnalysis.internalInterfaces %}
1015
- ### 5.10.3b Internal Interfaces
1016
-
1017
- | ID | Name | Kind | Owner | Signature | Consumers | Current code evidence |
1018
- |----|------|------|-------|-----------|-----------|-----------------------|
1019
- {% for row in projectAnalysis.internalInterfaces -%}
1020
- | {{ row.id | mdcell }} | {{ row.name | mdcell }} | {{ row.kind | mdcell }} | {{ row.ownerComponentId | mdcell }} | `{{ row.signature | mdcell }}` | {{ row.consumers | default([]) | join(', ') | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}`{% if not loop.last %}<br>{% endif %}{% endfor %} |
1021
- {% endfor %}
1022
- {% endif %}
1023
- {% if projectAnalysis.workflows %}
1024
- ### 5.10.3c Workflows
1025
-
1026
- {% for flow in projectAnalysis.workflows -%}
1027
- **{{ flow.id | mdcell }} — {{ flow.name | mdcell }}** (trigger: {{ flow.trigger | mdcell }}{% if flow.outcome %}; outcome: {{ flow.outcome | mdcell }}{% endif %})
1028
-
1029
- | Step | Action | Component | External system |
1030
- |------|--------|-----------|-----------------|
1031
- {% for step in flow.steps -%}
1032
- | {{ step.order | mdcell }} | {{ step.action | mdcell }} | {{ step.componentId | mdcell }} | {{ step.externalSystem | default('--') | mdcell }} |
1033
- {% endfor %}
1034
- {% endfor %}
1035
- {% endif %}
1036
-
1037
- ### 5.10.4 Feature Index
1038
-
1039
- | ID | Name | Description | Representative entry point | Related components | Current code evidence |
1040
- |----|------|-------------|----------------------------|--------------------|-----------------------|
1041
- {% for row in projectAnalysis.featureIndex -%}
1042
- | {{ row.id | mdcell }} | {{ row.name | mdcell }} | {{ row.description | mdcell }} | `{{ row.representativeEntryPoint.path | mdcell }}:{{ row.representativeEntryPoint.symbol | mdcell }}` | {{ row.componentIds | join(', ') | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
1043
- {% endfor %}
1044
-
1045
- - Scan coverage: `{{ projectAnalysis.scanCoverage.scannedPathCount }}` scanned / `{{ projectAnalysis.scanCoverage.unscannedPathCount }}` unscanned — {{ projectAnalysis.scanCoverage.reason }}
1046
-
1047
- {% endif %}
1048
- {% if featureAnalysis %}
1049
- ## 5.11 Feature Analysis
1050
-
1051
- {{ t("analysis.featureIntro") }}
1052
-
1053
- ### 5.11.1 Confirmed Target
1054
-
1055
- | Mode | Requested value | Feature ID | Entry points |
1056
- |------|-----------------|------------|--------------|
1057
- | `{{ featureAnalysis.target.inputMode | mdcell }}` | {{ featureAnalysis.target.requestedValue | mdcell }} | {{ (featureAnalysis.target.featureId or '--') | mdcell }} | {% for row in featureAnalysis.target.entryPoints %}`{{ row.path | mdcell }}:{{ row.symbol | mdcell }}`{% if not loop.last %}<br>{% endif %}{% endfor %} |
1058
-
1059
- ### 5.11.2 Flows, Rules, and State Changes
1060
-
1061
- | ID | Kind | Claim | Current code evidence | Source reports |
1062
- |----|------|-------|-----------------------|----------------|
1063
- {% for row in featureAnalysis.flows -%}
1064
- | {{ row.id | mdcell }} | `{{ row.kind | mdcell }}` | {% for step in row.steps %}{{ step.sequence | mdcell }}. {{ step.action | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} | {{ row.sourceReportRefs | join(', ') | mdcell }} |
1065
- {% endfor %}
1066
- {% for row in featureAnalysis.domainRules -%}
1067
- | {{ row.id | mdcell }} | `rule` | {{ row.condition | mdcell }} → {{ row.outcome | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} | {{ row.sourceReportRefs | join(', ') | mdcell }} |
1068
- {% endfor %}
1069
- {% for row in featureAnalysis.stateChanges -%}
1070
- | {{ row.id | mdcell }} | `state-change` | {{ row.dataStore | mdcell }}.{{ row.field | mdcell }} — {{ row.change | mdcell }}{% if row.sideEffects %}<br>Side effects: {{ row.sideEffects | join(', ') | mdcell }}{% endif %} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} | {{ row.sourceReportRefs | join(', ') | mdcell }} |
1071
- {% endfor %}
1072
-
1073
- ### 5.11.3 External Interactions and Tests
1074
-
1075
- | Target | Input | Output | Failure handling | Current code evidence |
1076
- |--------|-------|--------|------------------|-----------------------|
1077
- {% for row in featureAnalysis.externalInteractions -%}
1078
- | {{ row.target | mdcell }} | {{ row.input | mdcell }} | {{ row.output | mdcell }} | {{ row.failureHandling | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
1079
- {% endfor %}
1080
-
1081
- | ID | Target IDs | Test paths | Gaps |
1082
- |----|------------|------------|------|
1083
- {% for row in featureAnalysis.testCoverage -%}
1084
- | {{ row.id | mdcell }} | {{ row.targetIds | join(', ') | mdcell }} | {{ row.testPaths | join(', ') | mdcell }} | {{ (row.gaps | join(', ') or '--') | mdcell }} |
1085
- {% endfor %}
1086
-
1087
- {% endif %}
1088
- {% if changeImpactAnalysis %}
1089
- ## 5.12 Change Impact Analysis
1090
-
1091
- {{ t("analysis.changeImpactIntro") }}
1092
-
1093
- ### 5.12.1 Change and Preserved Behavior
1094
-
1095
- - Change request: {{ changeImpactAnalysis.changeRequest.summary }} — evidence: `{{ changeImpactAnalysis.changeRequest.briefEvidence }}`
1096
-
1097
- | Preserved behavior | Current code evidence |
1098
- |--------------------|-----------------------|
1099
- {% for row in changeImpactAnalysis.preservedBehaviors -%}
1100
- | {{ row.statement | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
1101
- {% endfor %}
1102
-
1103
- ### 5.12.2 Impact Items and Blast Radius
1104
-
1105
- | ID | Target | Impact kind | Level | Confidence | Source reports | Current code evidence |
1106
- |----|--------|-------------|-------|------------|----------------|-----------------------|
1107
- {% for row in changeImpactAnalysis.impactItems -%}
1108
- | {{ row.id | mdcell }} | {{ row.target | mdcell }} | {{ row.impactKind | mdcell }} | `{{ row.level | mdcell }}` | `{{ row.confidence | mdcell }}` | {{ row.sourceReportRefs | join(', ') | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
1109
- {% endfor %}
1110
-
1111
- | Source impact ID | Affected target | Direction | Current code evidence |
1112
- |------------------|-----------------|-----------|-----------------------|
1113
- {% for row in changeImpactAnalysis.dependencyBlastRadius -%}
1114
- | {{ row.sourceImpactId | mdcell }} | {{ row.affectedTarget | mdcell }} | {{ row.direction | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
1115
- {% endfor %}
1116
-
1117
- ### 5.12.3 Test, Operational, and Planning Inputs
1118
-
1119
- | Test scope | Action | Test paths | Current code evidence |
1120
- |------------|--------|------------|-----------------------|
1121
- {% for row in changeImpactAnalysis.testImpact -%}
1122
- | {{ row.scope | mdcell }} | `{{ row.action | mdcell }}` | {{ row.testPaths | join(', ') | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
1123
- {% endfor %}
1124
-
1125
- | Operational area | Impact | Current code evidence |
1126
- |------------------|--------|-----------------------|
1127
- {% for row in changeImpactAnalysis.operationalImpact -%}
1128
- | {{ row.area | mdcell }} | {{ row.impact | mdcell }} | {% for evidence in row.currentCodeEvidence %}`{{ evidence.path | mdcell }}:{{ evidence.line | mdcell }}` — {{ evidence.claim | mdcell }}{% if not loop.last %}<br>{% endif %}{% endfor %} |
1129
- {% endfor %}
1130
-
1131
- | Planning constraint | Unknown |
1132
- |---------------------|---------|
1133
- {% for row in changeImpactAnalysis.planningInputs -%}
1134
- | {{ row.constraint | mdcell }} | `{{ row.unknown | mdcell }}` |
1135
- {% endfor %}
1136
-
1137
- {% endif %}
1138
- {# `improvement-discovery` is not in the data.json TaskType enum — its
1139
- `## 5.9 Improvement Candidates` report is authored directly by the report
1140
- writer (report-writer-worker.md), never rendered through this template. #}
1141
- {% if fixCycle and fixCycle.cycle %}
1142
- ## 5.10 Fix History
1143
-
1144
- > This run belongs to a post-release bug-fix cycle registered in `history/fix-cycles.jsonl`.
1145
-
1146
- - Cycle: `{{ fixCycle.cycle }}` — {{ fixCycle.symptom }}
1147
- - Target report: `{{ fixCycle.targetReport }}`
1148
- {% if fixCycle.runs %}
1149
- - Runs in this cycle so far:
1150
- {% for r in fixCycle.runs %}
1151
- - {{ r.taskType }} seq {{ r.runSeq }}{% if r.runManifest %} (`{{ r.runManifest }}`){% endif %}
1152
- {% endfor %}
1153
- {% endif %}
1154
- {% endif %}
1155
- ## 6. Cross Verification Results
1156
-
1157
- {% if crossVerification.roundHistory and not crossVerification.roundHistory.disabled -%}
1158
- ### 6.0 Round History
1159
-
1160
- {% if crossVerification.roundHistory.rounds | length > 1 -%}
1161
- | Round | inputQueueSize | resolvedCount | carriedForwardCount | dispatches (worker:status:durationMs) | skippedWorkers (worker:reason) |
1162
- |-------|----------------|---------------|----------------------|----------------------------------------|---------------------------------|
1163
- {% for row in crossVerification.roundHistory.rounds -%}
1164
- | {{ row.round | mdcell }} | {{ row.inputQueueSize | mdcell }} | {{ row.resolvedCount | mdcell }} | {{ row.carriedForwardCount | mdcell }} | {{ row.dispatches | mdcell }} | {{ row.skippedWorkers | mdcell }} |
1165
- {% endfor %}
1166
-
1167
- - `round2SkippedReason`: `{{ crossVerification.roundHistory.round2SkippedReason }}` ← {{ t("roundHistory.round2SkippedReasonNote") }}
1168
- {% elif crossVerification.roundHistory.rounds | length == 1 -%}
1169
- {% set r = crossVerification.roundHistory.rounds[0] -%}
1170
- - {{ t("roundHistory.singleRoundPrefix") }} resolved={{ r.resolvedCount }}, carriedForward={{ r.carriedForwardCount }}, round2SkippedReason=`{{ crossVerification.roundHistory.round2SkippedReason }}`
1171
- {% else -%}
1172
- - {{ t("roundHistory.noRoundsNote") }} round2SkippedReason=`{{ crossVerification.roundHistory.round2SkippedReason }}`
1173
- {% endif %}
1174
-
1175
- {% endif %}
1176
- ### 6.1 Consensus
1177
-
1178
- {% if crossVerification.consensus | length == 0 -%}
1179
- {{ t("emptyState.consensusItems") }}
1180
- {%- else %}
1181
- | {{ t("columns.recordMeta") }} | Statement | Evidence (path:line / log / worker report) |
1182
- |--------|-----------|---------------------------------------------|
1183
- {% for row in crossVerification.consensus -%}
1184
- | **{{ row.id | mdcell }}**<br>Ticket: `{{ row.ticketId | mdcell }}`<br>Source items: {{ row.sourceItems | join(', ') | mdcell }} | {{ row.statement | mdcell }} | {{ row.evidence | mdcell }} |
1185
- {% endfor %}
1186
- {%- endif %}
1187
-
1188
- {{ t("sectionIntro.sourceItemsRule") }}
1189
-
1190
- ### 6.2 Differences
1191
-
1192
- {% if crossVerification.differences | length == 0 -%}
1193
- {{ t("emptyState.differences") }}
1194
- {%- else %}
1195
- | {{ t("columns.recordMeta") }} | Disagreement | Evidence |
1196
- |--------|--------------|----------|
1197
- {% for row in crossVerification.differences -%}
1198
- | **{{ row.id | mdcell }}**<br>Ticket: `{{ row.ticketId | mdcell }}`<br>Workers: {% for w in row.workersPosition %}{{ w.worker | mdcell }}:{{ w.itemId | mdcell }} ({{ w.position | mdcell }}){% if not loop.last %} / {% endif %}{% endfor %} | {{ row.disagreement | mdcell }} | {{ row.evidence | mdcell }} |
1199
- {% endfor %}
1200
- {%- endif %}
1201
-
1202
- ## 7. Final Verdict
1203
-
1204
- {{ t("finalVerdict.intro") }}
1205
-
1206
- | {{ t("verdictCard.tableHeaderLabel") }} | {{ t("verdictCard.tableHeaderValue") }} |
1207
- |------|----|
1208
- | Final Conclusion | {{ finalVerdict.finalConclusion | mdcell }} |
1209
- | Verdict Token | `{{ finalVerdict.verdictToken | mdcell }}` |
1210
- | Direction | `{{ finalVerdict.direction | mdcell }}` |
1211
- | {{ t("verdictCard.rationaleLabel") }} | {{ finalVerdict.rationaleRowIds | join(', ') | mdcell }} |
1212
- | {{ t("verdictCard.nextStepLabel") }} | {{ finalVerdict.nextStep | mdcell }} |
1213
-
1214
- {% if ticketCoverage.omit %}
1215
- {# Ticket Coverage omitted entirely — release-handoff / final-verification #}
1216
- {%- else %}
1217
- ## Ticket Coverage
1218
-
1219
- {{ t("ticketCoverage.intro") }}
1220
-
1221
- {% if ticketCoverage.singleTicket -%}
1222
- - Single ticket run: {{ ticketCoverage.singleTicket }}
1223
- {%- else %}
1224
- | Ticket ID | {{ t("ticketCoverage.columnSections") }} | {{ t("ticketCoverage.columnRelatedIds") }} |
1225
- |-----------|-----------|---------------|
1226
- {% for row in ticketCoverage.rows -%}
1227
- | `{{ row.ticketId | mdcell }}` | `{{ row.sections | mdcell }}` | `{{ row.relatedIds | mdcell }}` |
1228
- {% endfor %}
1229
- {%- endif %}
1230
-
1231
- {% endif %}
1232
- ## Execution Status by Agent
1233
-
1234
- {{ t("sectionIntro.executionStatus") }}
1235
-
1236
- | {{ t("columns.recordMeta") }} | Summary of Key Findings |
1237
- |--------|-------------------------|
1238
- {% for row in executionStatus -%}
1239
- | **{{ row.agent | mdcell }}**<br>Role: {{ row.role | mdcell }}<br>Model: {{ row.model | mdcell }}<br>Status: {{ row.status | mdcell }}<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 | mdcell }} |
1240
- {% endfor %}
1241
-
1242
- ## {{ t("tokenSummary.heading") }}
1243
-
1244
- | {{ t("tokenSummary.tableHeaderItem") }} | {{ t("columns.rawTokens") }} | {{ t("columns.billableTokensInputEquiv") }} | {{ t("columns.cost") }} |
1245
- |------|-----------|------------------------|------------|
1246
- | {{ t("tokenSummary.rowLead") }} | `{{ tokenUsage.lead.totalTokens | format_int }}` | `{{ tokenUsage.lead.billableTokens | format_int }}` | `{{ tokenUsage.lead.costUsd | format_usd }}` |
1247
- | {{ t("tokenSummary.rowWorkerTotal") }} | `{{ tokenUsage.worker.totalTokens | format_int }}` | `{{ tokenUsage.worker.billableTokens | format_int }}` | `{{ tokenUsage.worker.costUsd | format_usd }}` |
1248
- {% for row in tokenUsage.workerDetails or [] -%}
1249
- | - {{ row.label | mdcell }} | `{{ row.totalTokens | format_int }}`{% if row.cliTotalTokens is not none and row.cliTotalTokens > 0 %}<br>CLI: `{{ row.cliTotalTokens | format_int }}`{% endif %} | `{{ row.billableTokens | format_int }}` | `{{ row.costUsd | format_usd }}`{% if row.cliCostUsd is not none and row.cliCostUsd > 0 %}<br>+ CLI `{{ row.cliCostUsd | format_usd }}`{% endif %} |
1250
- {% endfor -%}
1251
- | {{ t("tokenSummary.rowGrandTotal") }} | **`{{ tokenUsage.grand.totalTokens | format_int }}`** | **`{{ tokenUsage.grand.billableTokens | format_int }}`** | **`{{ tokenUsage.grand.costUsd | format_usd }}`** |
1252
- {% if tokenUsage.cli and tokenUsage.cli.costUsd is not none and tokenUsage.cli.costUsd > 0 -%}
1253
- | {{ t("tokenSummary.rowCliExtra") }} | | | `{{ tokenUsage.cli.costUsd | format_usd }}` |
1254
- {% endif %}
1255
-
1256
- {# At Phase 6 numeric cells are null and render as `--`.
1257
- Phase 7's okstra-token-usage.py populates tokenUsage in data.json then
1258
- re-invokes this renderer to produce the final markdown. #}