okstra 0.149.0 → 0.150.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 (53) hide show
  1. package/docs/architecture.md +1 -1
  2. package/docs/cli.md +1 -1
  3. package/docs/project-structure-overview.md +1 -1
  4. package/package.json +1 -1
  5. package/runtime/BUILD.json +2 -2
  6. package/runtime/agents/workers/translator-worker.md +67 -0
  7. package/runtime/bin/okstra-render-final-report.py +0 -11
  8. package/runtime/bin/okstra-report-translate.py +158 -0
  9. package/runtime/prompts/lead/adapters/claude-code.md +1 -1
  10. package/runtime/prompts/lead/okstra-lead-contract.md +1 -0
  11. package/runtime/prompts/lead/report-writer.md +14 -13
  12. package/runtime/prompts/lead/team-contract.md +2 -2
  13. package/runtime/prompts/wizard/prompts.ko.json +17 -1
  14. package/runtime/python/okstra_ctl/analysis_inputs.py +24 -9
  15. package/runtime/python/okstra_ctl/analysis_packet.py +23 -1
  16. package/runtime/python/okstra_ctl/clarification_items.py +241 -44
  17. package/runtime/python/okstra_ctl/codex_dispatch.py +2 -1
  18. package/runtime/python/okstra_ctl/dispatch_core.py +2 -2
  19. package/runtime/python/okstra_ctl/dispatch_state.py +12 -1
  20. package/runtime/python/okstra_ctl/final_report_paths.py +22 -1
  21. package/runtime/python/okstra_ctl/i18n.py +12 -7
  22. package/runtime/python/okstra_ctl/render_final_report.py +18 -17
  23. package/runtime/python/okstra_ctl/report_html/filters.py +15 -77
  24. package/runtime/python/okstra_ctl/report_html/render.py +44 -2
  25. package/runtime/python/okstra_ctl/report_translation.py +440 -0
  26. package/runtime/python/okstra_ctl/report_views.py +23 -9
  27. package/runtime/python/okstra_ctl/run.py +1 -1
  28. package/runtime/python/okstra_ctl/user_response.py +11 -6
  29. package/runtime/python/okstra_ctl/wizard.py +100 -25
  30. package/runtime/python/okstra_ctl/worker_liveness.py +130 -36
  31. package/runtime/templates/reports/html/base.template.html +12 -12
  32. package/runtime/templates/reports/html/i18n/en.json +395 -0
  33. package/runtime/templates/reports/html/i18n/ko.json +395 -0
  34. package/runtime/templates/reports/html/macros/forms.html +16 -16
  35. package/runtime/templates/reports/html/macros/visualizations.html +2 -2
  36. package/runtime/templates/reports/html/tasks/change-impact-analysis.template.html +17 -17
  37. package/runtime/templates/reports/html/tasks/error-analysis.template.html +12 -12
  38. package/runtime/templates/reports/html/tasks/feature-analysis.template.html +16 -16
  39. package/runtime/templates/reports/html/tasks/final-verification.template.html +12 -12
  40. package/runtime/templates/reports/html/tasks/implementation-planning.template.html +37 -37
  41. package/runtime/templates/reports/html/tasks/implementation.template.html +18 -18
  42. package/runtime/templates/reports/html/tasks/improvement-discovery.template.html +7 -7
  43. package/runtime/templates/reports/html/tasks/project-analysis.template.html +29 -29
  44. package/runtime/templates/reports/html/tasks/release-handoff.template.html +13 -13
  45. package/runtime/templates/reports/html/tasks/requirements-discovery.template.html +14 -14
  46. package/runtime/templates/reports/report.js +8 -5
  47. package/runtime/validators/validate-report-views.py +1 -1
  48. package/runtime/validators/validate-run.py +28 -31
  49. package/src/cli-registry.mjs +11 -0
  50. package/src/commands/inspect/worker-liveness.mjs +9 -7
  51. package/src/commands/report/translate.mjs +31 -0
  52. package/src/lib/helper-scripts.mjs +1 -0
  53. package/runtime/templates/reports/i18n/ko.json +0 -273
@@ -5,55 +5,55 @@
5
5
 
6
6
  {% block human_content %}
7
7
  <section data-report-section="feature-overview">
8
- <h2>Feature overview</h2>
8
+ <h2>{{ t('tasks.feature-analysis.feature-overview') }}</h2>
9
9
  {{ render_narrative(narrative.userBehaviorExplanation, "featureAnalysis.userNarrative.userBehaviorExplanation") }}
10
- <p><strong>Subject:</strong> {{ feature.target.requestedValue | inline_code }}</p>
10
+ <p><strong>{{ t('tasks.feature-analysis.subject') }}</strong> {{ feature.target.requestedValue | inline_code }}</p>
11
11
  <ul>{% for row in feature.actors %}<li>{{ row.description | inline_code }}</li>{% endfor %}</ul>
12
12
  </section>
13
13
 
14
14
  <section data-report-section="behavior-flow" data-report-field="featureAnalysis.flows">
15
- <h2>How a user moves through it</h2>
15
+ <h2>{{ t('tasks.feature-analysis.how-a-user-moves-through-it') }}</h2>
16
16
  {{ render_narrative(narrative.flowExplanation, "featureAnalysis.userNarrative.flowExplanation") }}
17
17
  {{ figure(flowFigure) }}
18
18
  <div class="summary-grid">{% for row in feature.flows %}<article class="summary-card" id="id-{{ row.id }}" data-flow-kind="{{ 'alternate' if row.kind == 'alternative' else row.kind }}"><p class="eyebrow">{{ row.id }} · {{ row.kind }}</p><ol>{% for step in row.steps %}<li>{{ step.action | inline_code }}</li>{% endfor %}</ol></article>{% endfor %}</div>
19
19
  </section>
20
20
 
21
21
  <section data-report-section="rules-and-state">
22
- <h2>Rules and state changes</h2>
22
+ <h2>{{ t('tasks.feature-analysis.rules-and-state-changes') }}</h2>
23
23
  {{ render_narrative(narrative.rulesAndStateExplanation, "featureAnalysis.userNarrative.rulesAndStateExplanation") }}
24
- <div data-report-field="featureAnalysis.domainRules"><h3>Domain rules</h3>{% for row in feature.domainRules %}{{ summary_card(row.id ~ " · " ~ (row.condition | inline_code), row.outcome, anchor=row.id) }}{% endfor %}</div>
25
- <div data-report-field="featureAnalysis.stateChanges"><h3>State change</h3>{% for row in feature.stateChanges %}{{ summary_card(row.id ~ " · " ~ row.field, row.change, anchor=row.id) }}{% endfor %}</div>
24
+ <div data-report-field="featureAnalysis.domainRules"><h3>{{ t('tasks.feature-analysis.domain-rules') }}</h3>{% for row in feature.domainRules %}{{ summary_card(row.id ~ " · " ~ (row.condition | inline_code), row.outcome, anchor=row.id) }}{% endfor %}</div>
25
+ <div data-report-field="featureAnalysis.stateChanges"><h3>{{ t('tasks.feature-analysis.state-change') }}</h3>{% for row in feature.stateChanges %}{{ summary_card(row.id ~ " · " ~ row.field, row.change, anchor=row.id) }}{% endfor %}</div>
26
26
  </section>
27
27
 
28
28
  <section data-report-section="external-interactions" data-report-field="featureAnalysis.externalInteractions">
29
- <h2>External interactions</h2>
29
+ <h2>{{ t('tasks.feature-analysis.external-interactions') }}</h2>
30
30
  {% for row in feature.externalInteractions %}{{ summary_card(row.target | inline_code, row.input ~ " → " ~ row.output ~ ". On failure: " ~ row.failureHandling) }}{% endfor %}
31
31
  </section>
32
32
 
33
33
  <section data-report-section="test-gaps" data-report-field="featureAnalysis.testCoverage">
34
- <h2>Tests and gaps</h2>
34
+ <h2>{{ t('tasks.feature-analysis.tests-and-gaps') }}</h2>
35
35
  {{ render_narrative(narrative.testGapExplanation, "featureAnalysis.userNarrative.testGapExplanation") }}
36
36
  {% for row in feature.testCoverage %}{{ summary_card(row.id, "Tests: " ~ (row.testPaths | join(', ')) ~ "; Gaps: " ~ ((row.gaps | join(', ')) or 'none'), anchor=row.id) }}{% endfor %}
37
37
  </section>
38
38
 
39
39
  <section data-report-section="preconditions" data-report-field="featureAnalysis.preconditions">
40
- <h2>Precondition</h2>
41
- <table><thead><tr><th>Body</th><th>Evidence</th></tr></thead><tbody>{% for row in feature.preconditions %}<tr><td>{{ row.description | inline_code }}</td><td>{{ row.currentCodeEvidence | code_evidence }}</td></tr>{% else %}<tr><td colspan="2">Nothing was recorded.</td></tr>{% endfor %}</tbody></table>
40
+ <h2>{{ t('tasks.feature-analysis.precondition') }}</h2>
41
+ <table><thead><tr><th>{{ t('tasks.feature-analysis.body') }}</th><th>{{ t('tasks.feature-analysis.evidence') }}</th></tr></thead><tbody>{% for row in feature.preconditions %}<tr><td>{{ row.description | inline_code }}</td><td>{{ row.currentCodeEvidence | code_evidence }}</td></tr>{% else %}<tr><td colspan="2">{{ t('tasks.feature-analysis.nothing-was-recorded') }}</td></tr>{% endfor %}</tbody></table>
42
42
  </section>
43
43
 
44
44
  <section data-report-section="postconditions" data-report-field="featureAnalysis.postconditions">
45
- <h2>State once it is done</h2>
46
- <table><thead><tr><th>Body</th><th>Evidence</th></tr></thead><tbody>{% for row in feature.postconditions %}<tr><td>{{ row.description | inline_code }}</td><td>{{ row.currentCodeEvidence | code_evidence }}</td></tr>{% else %}<tr><td colspan="2">Nothing was recorded.</td></tr>{% endfor %}</tbody></table>
45
+ <h2>{{ t('tasks.feature-analysis.state-once-it-is-done') }}</h2>
46
+ <table><thead><tr><th>{{ t('tasks.feature-analysis.body') }}</th><th>{{ t('tasks.feature-analysis.evidence') }}</th></tr></thead><tbody>{% for row in feature.postconditions %}<tr><td>{{ row.description | inline_code }}</td><td>{{ row.currentCodeEvidence | code_evidence }}</td></tr>{% else %}<tr><td colspan="2">{{ t('tasks.feature-analysis.nothing-was-recorded') }}</td></tr>{% endfor %}</tbody></table>
47
47
  </section>
48
48
 
49
49
  <section data-report-section="permissions-and-flags" data-report-field="featureAnalysis.permissionsAndFlags">
50
- <h2>Permissions and flags</h2>
51
- <table><thead><tr><th>Body</th><th>Evidence</th></tr></thead><tbody>{% for row in feature.permissionsAndFlags %}<tr><td>{{ row.description | inline_code }}</td><td>{{ row.currentCodeEvidence | code_evidence }}</td></tr>{% else %}<tr><td colspan="2">Nothing was recorded.</td></tr>{% endfor %}</tbody></table>
50
+ <h2>{{ t('tasks.feature-analysis.permissions-and-flags') }}</h2>
51
+ <table><thead><tr><th>{{ t('tasks.feature-analysis.body') }}</th><th>{{ t('tasks.feature-analysis.evidence') }}</th></tr></thead><tbody>{% for row in feature.permissionsAndFlags %}<tr><td>{{ row.description | inline_code }}</td><td>{{ row.currentCodeEvidence | code_evidence }}</td></tr>{% else %}<tr><td colspan="2">{{ t('tasks.feature-analysis.nothing-was-recorded') }}</td></tr>{% endfor %}</tbody></table>
52
52
  </section>
53
53
 
54
54
  <section data-report-section="non-functional" data-report-field="featureAnalysis.nonFunctionalConcerns">
55
- <h2>Non-functional concerns</h2>
56
- <table><thead><tr><th>Body</th><th>Evidence</th></tr></thead><tbody>{% for row in feature.nonFunctionalConcerns %}<tr><td>{{ row.description | inline_code }}</td><td>{{ row.currentCodeEvidence | code_evidence }}</td></tr>{% else %}<tr><td colspan="2">Nothing was recorded.</td></tr>{% endfor %}</tbody></table>
55
+ <h2>{{ t('tasks.feature-analysis.non-functional-concerns') }}</h2>
56
+ <table><thead><tr><th>{{ t('tasks.feature-analysis.body') }}</th><th>{{ t('tasks.feature-analysis.evidence') }}</th></tr></thead><tbody>{% for row in feature.nonFunctionalConcerns %}<tr><td>{{ row.description | inline_code }}</td><td>{{ row.currentCodeEvidence | code_evidence }}</td></tr>{% else %}<tr><td colspan="2">{{ t('tasks.feature-analysis.nothing-was-recorded') }}</td></tr>{% endfor %}</tbody></table>
57
57
  </section>
58
58
 
59
59
  {{ analysis_review(analysisReviewIds) }}
@@ -4,43 +4,43 @@
4
4
 
5
5
  {% block human_content %}
6
6
  <section data-report-section="verification-verdict">
7
- <h2>Verification verdict</h2>
7
+ <h2>{{ t('tasks.final-verification.verification-verdict') }}</h2>
8
8
  <p><span class="status status-{{ verdict.verdictToken }}">{{ verdict.verdictToken }}</span></p>
9
9
  {{ render_narrative(narrative.verdictExplanation, "finalVerification.userNarrative.verdictExplanation") }}
10
10
  </section>
11
11
 
12
12
  <section data-report-section="requirement-results" data-report-field="finalVerification.validationEvidence">
13
- <h2>Result per requirement</h2>
13
+ <h2>{{ t('tasks.final-verification.result-per-requirement') }}</h2>
14
14
  {{ render_narrative(narrative.coverageExplanation, "finalVerification.userNarrative.coverageExplanation") }}
15
15
  {{ figure(coverageFigure, anchor_nodes=true) }}
16
16
  </section>
17
17
 
18
18
  <section data-report-section="blockers" data-report-field="finalVerification.acceptanceBlockers">
19
- <h2>What blocks acceptance</h2>
19
+ <h2>{{ t('tasks.final-verification.what-blocks-acceptance') }}</h2>
20
20
  {{ render_narrative(narrative.blockerExplanation, "finalVerification.userNarrative.blockerExplanation") }}
21
- <div class="summary-grid">{% for row in final.acceptanceBlockers %}{{ summary_card(row.id ~ " · " ~ row.severity, row.statement, "important", anchor=row.id) }}{% else %}<p>Nothing is holding acceptance.</p>{% endfor %}</div>
21
+ <div class="summary-grid">{% for row in final.acceptanceBlockers %}{{ summary_card(row.id ~ " · " ~ row.severity, row.statement, "important", anchor=row.id) }}{% else %}<p>{{ t('tasks.final-verification.nothing-is-holding-acceptance') }}</p>{% endfor %}</div>
22
22
  </section>
23
23
 
24
24
  <section data-report-section="residual-risk" data-report-field="finalVerification.residualRisk">
25
- <h2>Residual risk</h2>
26
- <div class="summary-grid">{% for row in final.residualRisk %}<article class="summary-card" id="id-{{ row.id }}"><h3>{{ row.id }}</h3><p>{{ row.item | inline_code }}</p><p><strong>Owner:</strong> {{ row.owner | inline_code }}</p><p><strong>Escalation condition:</strong> {{ row.escalationTrigger | inline_code }}</p></article>{% else %}<p>No residual risk was recorded.</p>{% endfor %}</div>
25
+ <h2>{{ t('tasks.final-verification.residual-risk') }}</h2>
26
+ <div class="summary-grid">{% for row in final.residualRisk %}<article class="summary-card" id="id-{{ row.id }}"><h3>{{ row.id }}</h3><p>{{ row.item | inline_code }}</p><p><strong>{{ t('tasks.final-verification.owner') }}</strong> {{ row.owner | inline_code }}</p><p><strong>{{ t('tasks.final-verification.escalation-condition') }}</strong> {{ row.escalationTrigger | inline_code }}</p></article>{% else %}<p>{{ t('tasks.final-verification.no-residual-risk-was-recorded') }}</p>{% endfor %}</div>
27
27
  </section>
28
28
 
29
29
  <section data-report-section="manual-results" data-report-field="finalVerification.manualUserTest">
30
- <h2>Manual user test results</h2>
30
+ <h2>{{ t('tasks.final-verification.manual-user-test-results') }}</h2>
31
31
  {% if final.manualUserTest.applicable %}{% for row in final.manualUserTest.results %}<article class="summary-card tone-{{ row.result }}"><h3>{{ row.target | inline_code }} · {{ row.result }}</h3><p>{{ row.performed | inline_code }}</p><p>{{ row.observed | inline_code }}</p></article>{% endfor %}{% else %}<p>{{ final.manualUserTest.exemptionReaffirm | inline_code }}</p>{% endif %}
32
32
  </section>
33
33
 
34
34
  <section data-report-section="verified-source" data-report-field="finalVerification.sourceImplementationReport">
35
- <h2>What was verified</h2>
36
- <table><tbody><tr><th>Implementation report</th><td><code>{{ final.sourceImplementationReport.path }}</code></td></tr><tr><th>Worktree</th><td><code>{{ final.sourceImplementationReport.worktreePath }}</code></td></tr><tr><th>Base commit</th><td><code>{{ final.sourceImplementationReport.implementationBaseRef }}</code> → <code>{{ final.sourceImplementationReport.capturedHeadSha }}</code></td></tr><tr><th>Diff summary</th><td>{{ final.sourceImplementationReport.diffSummaryQuote | inline_code }}</td></tr><tr><th>Uncommitted state</th><td>{{ final.sourceImplementationReport.gitStatusShort | inline_code }}</td></tr></tbody></table>
37
- {% if final.get("stageReports") %}<h3>Per-stage reports</h3>
35
+ <h2>{{ t('tasks.final-verification.what-was-verified') }}</h2>
36
+ <table><tbody><tr><th>{{ t('tasks.final-verification.implementation-report') }}</th><td><code>{{ final.sourceImplementationReport.path }}</code></td></tr><tr><th>{{ t('tasks.final-verification.worktree') }}</th><td><code>{{ final.sourceImplementationReport.worktreePath }}</code></td></tr><tr><th>{{ t('tasks.final-verification.base-commit') }}</th><td><code>{{ final.sourceImplementationReport.implementationBaseRef }}</code> → <code>{{ final.sourceImplementationReport.capturedHeadSha }}</code></td></tr><tr><th>{{ t('tasks.final-verification.diff-summary') }}</th><td>{{ final.sourceImplementationReport.diffSummaryQuote | inline_code }}</td></tr><tr><th>{{ t('tasks.final-verification.uncommitted-state') }}</th><td>{{ final.sourceImplementationReport.gitStatusShort | inline_code }}</td></tr></tbody></table>
37
+ {% if final.get("stageReports") %}<h3>{{ t('tasks.final-verification.per-stage-reports') }}</h3>
38
38
  <ul data-report-field="finalVerification.stageReports">{% for row in final.stageReports %}<li>Stage {{ row.stage }} — <code>{{ row.reportPath }}</code></li>{% endfor %}</ul>{% endif %}
39
39
  </section>
40
40
 
41
41
  <section data-report-section="release-route">
42
- <h2>Release path</h2>
42
+ <h2>{{ t('tasks.final-verification.release-path') }}</h2>
43
43
  {{ render_narrative(narrative.releaseReadiness, "finalVerification.userNarrative.releaseReadiness") }}
44
- {% if releaseAllowed %}<p>{{ final.routingRecommendation | inline_code }}</p>{% else %}<p>The current verdict does not allow release-handoff to start. Clear the blocker or the condition first.</p>{% endif %}
44
+ {% if releaseAllowed %}<p>{{ final.routingRecommendation | inline_code }}</p>{% else %}<p>{{ t('tasks.final-verification.the-current-verdict-does-not-allow-release-h') }}</p>{% endif %}
45
45
  </section>
46
46
  {% endblock %}
@@ -5,100 +5,100 @@
5
5
 
6
6
  {% block human_content %}
7
7
  <section data-report-section="planning-goal">
8
- <h2>What the plan is for</h2>
8
+ <h2>{{ t('tasks.implementation-planning.what-the-plan-is-for') }}</h2>
9
9
  <p>{{ humanSummary.outcome | inline_code }}</p>
10
10
  <div class="summary-grid">{% for reason in humanSummary.whyItMatters %}{{ summary_card("", reason, "important") }}{% endfor %}</div>
11
11
  </section>
12
12
 
13
13
  <section data-report-section="option-comparison">
14
- <h2>Implementation options compared</h2>
14
+ <h2>{{ t('tasks.implementation-planning.implementation-options-compared') }}</h2>
15
15
  {{ render_narrative(narrative.optionExplanation, "implementationPlanning.userNarrative.optionExplanation") }}
16
- <div class="summary-grid" data-report-field="implementationPlanning.optionCandidates">{% for row in planning.optionCandidates %}<article class="summary-card"><h3>{{ row.name | inline_code }}</h3><p><strong>Interface:</strong> {{ row.interfaces | inline_code }}</p><p><strong>Blast radius:</strong> {{ row.blastRadius | inline_code }}</p><ul>{% for file in row.fileStructure %}<li id="id-{{ file.id }}">{{ file.action }} <code>{{ file.path }}</code> — {{ file.summary | inline_code }}</li>{% endfor %}</ul></article>{% endfor %}</div>
17
- <table data-report-field="implementationPlanning.tradeoffMatrix"><thead><tr><th>Option</th><th>Complexity</th><th>Risk</th><th>Reversibility</th><th>Test cost</th><th>Rollout cost</th></tr></thead><tbody>{% for row in planning.tradeoffMatrix %}<tr><td>{{ row.option | inline_code }}</td><td>{{ row.complexity | inline_code }}</td><td>{{ row.risk | inline_code }}</td><td>{{ row.reversibility | inline_code }}</td><td>{{ row.testCoverageCost | inline_code }}</td><td>{{ row.rolloutCost | inline_code }}</td></tr>{% endfor %}</tbody></table>
16
+ <div class="summary-grid" data-report-field="implementationPlanning.optionCandidates">{% for row in planning.optionCandidates %}<article class="summary-card"><h3>{{ row.name | inline_code }}</h3><p><strong>{{ t('tasks.implementation-planning.interface') }}</strong> {{ row.interfaces | inline_code }}</p><p><strong>{{ t('tasks.implementation-planning.blast-radius') }}</strong> {{ row.blastRadius | inline_code }}</p><ul>{% for file in row.fileStructure %}<li id="id-{{ file.id }}">{{ file.action }} <code>{{ file.path }}</code> — {{ file.summary | inline_code }}</li>{% endfor %}</ul></article>{% endfor %}</div>
17
+ <table data-report-field="implementationPlanning.tradeoffMatrix"><thead><tr><th>{{ t('tasks.implementation-planning.option') }}</th><th>{{ t('tasks.implementation-planning.complexity') }}</th><th>{{ t('tasks.implementation-planning.risk') }}</th><th>{{ t('tasks.implementation-planning.reversibility') }}</th><th>{{ t('tasks.implementation-planning.test-cost') }}</th><th>{{ t('tasks.implementation-planning.rollout-cost') }}</th></tr></thead><tbody>{% for row in planning.tradeoffMatrix %}<tr><td>{{ row.option | inline_code }}</td><td>{{ row.complexity | inline_code }}</td><td>{{ row.risk | inline_code }}</td><td>{{ row.reversibility | inline_code }}</td><td>{{ row.testCoverageCost | inline_code }}</td><td>{{ row.rolloutCost | inline_code }}</td></tr>{% endfor %}</tbody></table>
18
18
  </section>
19
19
 
20
20
  <section data-report-section="recommendation" data-report-field="implementationPlanning.recommendedOption">
21
- <h2>Recommended</h2>
21
+ <h2>{{ t('tasks.implementation-planning.recommended') }}</h2>
22
22
  {{ render_narrative(narrative.recommendationExplanation, "implementationPlanning.userNarrative.recommendationExplanation") }}
23
- <article class="summary-card tone-important"><h3>{{ planning.recommendedOption.name | inline_code }}</h3><p>{{ planning.recommendedOption.coreReason | inline_code }}</p><p>{{ planning.recommendedOption.rationale | inline_code }}</p><p><strong>Options not taken:</strong> {{ planning.recommendedOption.rejectedSummary | inline_code }}</p></article>
23
+ <article class="summary-card tone-important"><h3>{{ planning.recommendedOption.name | inline_code }}</h3><p>{{ planning.recommendedOption.coreReason | inline_code }}</p><p>{{ planning.recommendedOption.rationale | inline_code }}</p><p><strong>{{ t('tasks.implementation-planning.options-not-taken') }}</strong> {{ planning.recommendedOption.rejectedSummary | inline_code }}</p></article>
24
24
  </section>
25
25
 
26
26
  <section data-report-section="stage-map" data-report-field="implementationPlanning.stageMap">
27
- <h2>Stage map</h2>
27
+ <h2>{{ t('tasks.implementation-planning.stage-map') }}</h2>
28
28
  {{ render_narrative(narrative.stageStrategy, "implementationPlanning.userNarrative.stageStrategy") }}
29
29
  {{ figure(stageFigure) }}
30
- <div class="summary-grid">{% for row in planning.stages %}<article class="summary-card"><h3>Stage {{ row.stage }} · {{ row.title | inline_code }}</h3><p>{{ row.sliceValue | inline_code }}</p><p><strong>Exit contract:</strong> {{ row.acceptance | inline_code }}</p><p><strong>Verification:</strong> {{ row.stageValidation | inline_code }}</p></article>{% endfor %}</div>
30
+ <div class="summary-grid">{% for row in planning.stages %}<article class="summary-card"><h3>Stage {{ row.stage }} · {{ row.title | inline_code }}</h3><p>{{ row.sliceValue | inline_code }}</p><p><strong>{{ t('tasks.implementation-planning.exit-contract') }}</strong> {{ row.acceptance | inline_code }}</p><p><strong>{{ t('tasks.implementation-planning.verification') }}</strong> {{ row.stageValidation | inline_code }}</p></article>{% endfor %}</div>
31
31
  </section>
32
32
 
33
33
  {% if planning.get("designPreparation") %}
34
34
  <section data-report-section="design-preparation" data-report-field="implementationPlanning.designPreparation">
35
- <h2>Design preparation</h2>
35
+ <h2>{{ t('tasks.implementation-planning.design-preparation') }}</h2>
36
36
  {% if planning.designPreparation.mode == "no-design-inputs" %}
37
37
  <p>{{ planning.designPreparation.reason | inline_code }}</p>
38
38
  {% else %}
39
- <table><thead><tr><th>Design item</th><th>What it needs</th><th>Open questions</th></tr></thead><tbody>{% for row in planning.designPreparation["items"] %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Subject", row.title), ("Kind", row.kind)], status_name="Status", status_raw=row.status, status_text=row.status) }}<td>{{ row.need | inline_code }}</td><td>{{ row.openQuestions | default([]) | join(" · ") | inline_code }}</td></tr>{% endfor %}</tbody></table>
39
+ <table><thead><tr><th>{{ t('tasks.implementation-planning.design-item') }}</th><th>{{ t('tasks.implementation-planning.what-it-needs') }}</th><th>{{ t('tasks.implementation-planning.open-questions') }}</th></tr></thead><tbody>{% for row in planning.designPreparation["items"] %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Subject", row.title), ("Kind", row.kind)], status_name="Status", status_raw=row.status, status_text=row.status) }}<td>{{ row.need | inline_code }}</td><td>{{ row.openQuestions | default([]) | join(" · ") | inline_code }}</td></tr>{% endfor %}</tbody></table>
40
40
  {% endif %}
41
41
  </section>
42
42
  {% endif %}
43
43
 
44
44
  <section data-report-section="variation-points" data-report-field="implementationPlanning.variationPointAnalysis">
45
- <h2>Where implementations diverge</h2>
45
+ <h2>{{ t('tasks.implementation-planning.where-implementations-diverge') }}</h2>
46
46
  {% if planning.variationPointAnalysis.hasMultipleImplementations %}
47
- <table><thead><tr><th>Action</th><th>Implementations</th><th>Extraction call</th><th>Evidence</th></tr></thead><tbody>{% for row in planning.variationPointAnalysis.points %}<tr><td>{{ row.behavior | inline_code }}</td><td>{{ row.implementations | default([]) | join(" · ") | inline_code }}</td><td>{{ row.extractionDecision | inline_code }}</td><td>{{ row.evidence | inline_code }}</td></tr>{% endfor %}</tbody></table>
47
+ <table><thead><tr><th>{{ t('tasks.implementation-planning.action') }}</th><th>{{ t('tasks.implementation-planning.implementations') }}</th><th>{{ t('tasks.implementation-planning.extraction-call') }}</th><th>{{ t('tasks.implementation-planning.evidence') }}</th></tr></thead><tbody>{% for row in planning.variationPointAnalysis.points %}<tr><td>{{ row.behavior | inline_code }}</td><td>{{ row.implementations | default([]) | join(" · ") | inline_code }}</td><td>{{ row.extractionDecision | inline_code }}</td><td>{{ row.evidence | inline_code }}</td></tr>{% endfor %}</tbody></table>
48
48
  {% else %}<p>{{ planning.variationPointAnalysis.noVariationRationale | inline_code }}</p>{% endif %}
49
49
  </section>
50
50
 
51
51
  {% if planning.get("stepwiseExecution") %}
52
52
  <section data-report-section="stepwise-execution" data-report-field="implementationPlanning.stepwiseExecution">
53
- <h2>Step-by-step execution</h2>
54
- <table><thead><tr><th>#</th><th>Action</th><th>Files</th><th>Command / test</th><th>Expected</th></tr></thead><tbody>{% for row in planning.stepwiseExecution %}<tr><td>{{ row.step }}</td><td>{{ row.action | inline_code }}</td><td>{% for file in row.files %}<code>{{ file }}</code>{% if not loop.last %} {% endif %}{% endfor %}</td><td><code>{{ row.commandOrTest }}</code></td><td>{{ row.expectedOutcome | inline_code }}</td></tr>{% endfor %}</tbody></table>
53
+ <h2>{{ t('tasks.implementation-planning.step-by-step-execution') }}</h2>
54
+ <table><thead><tr><th>#</th><th>{{ t('tasks.implementation-planning.action') }}</th><th>{{ t('tasks.implementation-planning.files') }}</th><th>{{ t('tasks.implementation-planning.command-test') }}</th><th>{{ t('tasks.implementation-planning.expected') }}</th></tr></thead><tbody>{% for row in planning.stepwiseExecution %}<tr><td>{{ row.step }}</td><td>{{ row.action | inline_code }}</td><td>{% for file in row.files %}<code>{{ file }}</code>{% if not loop.last %} {% endif %}{% endfor %}</td><td><code>{{ row.commandOrTest }}</code></td><td>{{ row.expectedOutcome | inline_code }}</td></tr>{% endfor %}</tbody></table>
55
55
  </section>
56
56
  {% endif %}
57
57
 
58
58
  <section data-report-section="validation-and-rollback">
59
- <h2>Verification and rollback</h2>
59
+ <h2>{{ t('tasks.implementation-planning.verification-and-rollback') }}</h2>
60
60
  {{ render_narrative(narrative.validationAndRollback, "implementationPlanning.userNarrative.validationAndRollback") }}
61
- <h3>Validation checklist</h3><table data-report-field="implementationPlanning.validationChecklist"><thead><tr><th>Check</th><th>Check</th><th>Command</th><th>Expected</th></tr></thead><tbody>{% for row in planning.validationChecklist %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Phase", row.phase)]) }}<td>{{ row.check | inline_code }}</td><td><code>{{ row.commandOrObservation }}</code></td><td>{{ row.expectedOutcome | inline_code }}</td></tr>{% endfor %}</tbody></table>
62
- <h3>How each requirement gets met</h3><table data-report-field="implementationPlanning.requirementCoverage"><thead><tr><th>Requirement</th><th>Body</th><th>Covered by</th></tr></thead><tbody>{% for row in planning.requirementCoverage %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Source", row.source)], status_name="Status", status_raw=row.status, status_text=row.status) }}<td>{{ row.requirement | inline_code }}</td><td>{{ row.coveredBy | inline_code }}</td></tr>{% endfor %}</tbody></table>
63
- <h3>Cross-project dependencies</h3><table data-report-field="implementationPlanning.crossProjectDependencies"><thead><tr><th>Dependency</th><th>Work needed</th><th>Signal to check</th><th>How to start</th></tr></thead><tbody>{% for row in planning.crossProjectDependencies %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Project", row.project), ("Direction", row.direction)]) }}<td>{{ row.requiredWork | inline_code }}</td><td>{{ row.verificationSignal | inline_code }}</td><td>{{ row.howToStart | inline_code }}</td></tr>{% endfor %}</tbody></table>
64
- <h3>Dependency and migration risk</h3><table data-report-field="implementationPlanning.dependencyMigrationRisk"><thead><tr><th>Item</th><th>Impact</th><th>Mitigation</th></tr></thead><tbody>{% for row in planning.dependencyMigrationRisk %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Item", row.item), ("Kind", row.kind)]) }}<td>{{ row.impact | inline_code }}</td><td>{{ row.mitigation | inline_code }}</td></tr>{% endfor %}</tbody></table>
65
- <h3>Rollback strategy</h3><div class="summary-grid" data-report-field="implementationPlanning.rollbackStrategy">{% for row in planning.rollbackStrategy %}{{ summary_card(row.id ~ " · " ~ (row.triggerSignal | inline_code), row.action, "important", anchor=row.id) }}{% endfor %}</div>
61
+ <h3>{{ t('tasks.implementation-planning.validation-checklist') }}</h3><table data-report-field="implementationPlanning.validationChecklist"><thead><tr><th>{{ t('tasks.implementation-planning.check') }}</th><th>{{ t('tasks.implementation-planning.check') }}</th><th>{{ t('tasks.implementation-planning.command') }}</th><th>{{ t('tasks.implementation-planning.expected') }}</th></tr></thead><tbody>{% for row in planning.validationChecklist %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Phase", row.phase)]) }}<td>{{ row.check | inline_code }}</td><td><code>{{ row.commandOrObservation }}</code></td><td>{{ row.expectedOutcome | inline_code }}</td></tr>{% endfor %}</tbody></table>
62
+ <h3>{{ t('tasks.implementation-planning.how-each-requirement-gets-met') }}</h3><table data-report-field="implementationPlanning.requirementCoverage"><thead><tr><th>{{ t('tasks.implementation-planning.requirement') }}</th><th>{{ t('tasks.implementation-planning.body') }}</th><th>{{ t('tasks.implementation-planning.covered-by') }}</th></tr></thead><tbody>{% for row in planning.requirementCoverage %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Source", row.source)], status_name="Status", status_raw=row.status, status_text=row.status) }}<td>{{ row.requirement | inline_code }}</td><td>{{ row.coveredBy | inline_code }}</td></tr>{% endfor %}</tbody></table>
63
+ <h3>{{ t('tasks.implementation-planning.cross-project-dependencies') }}</h3><table data-report-field="implementationPlanning.crossProjectDependencies"><thead><tr><th>{{ t('tasks.implementation-planning.dependency') }}</th><th>{{ t('tasks.implementation-planning.work-needed') }}</th><th>{{ t('tasks.implementation-planning.signal-to-check') }}</th><th>{{ t('tasks.implementation-planning.how-to-start') }}</th></tr></thead><tbody>{% for row in planning.crossProjectDependencies %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Project", row.project), ("Direction", row.direction)]) }}<td>{{ row.requiredWork | inline_code }}</td><td>{{ row.verificationSignal | inline_code }}</td><td>{{ row.howToStart | inline_code }}</td></tr>{% endfor %}</tbody></table>
64
+ <h3>{{ t('tasks.implementation-planning.dependency-and-migration-risk') }}</h3><table data-report-field="implementationPlanning.dependencyMigrationRisk"><thead><tr><th>{{ t('tasks.implementation-planning.item') }}</th><th>{{ t('tasks.implementation-planning.impact') }}</th><th>{{ t('tasks.implementation-planning.mitigation') }}</th></tr></thead><tbody>{% for row in planning.dependencyMigrationRisk %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Item", row.item), ("Kind", row.kind)]) }}<td>{{ row.impact | inline_code }}</td><td>{{ row.mitigation | inline_code }}</td></tr>{% endfor %}</tbody></table>
65
+ <h3>{{ t('tasks.implementation-planning.rollback-strategy') }}</h3><div class="summary-grid" data-report-field="implementationPlanning.rollbackStrategy">{% for row in planning.rollbackStrategy %}{{ summary_card(row.id ~ " · " ~ (row.triggerSignal | inline_code), row.action, "important", anchor=row.id) }}{% endfor %}</div>
66
66
  </section>
67
67
 
68
68
  <section data-report-section="plan-verification" data-report-field="implementationPlanning.planBodyVerification">
69
- <h2>Plan body verification</h2>
70
- <p><strong>Verdict</strong> — {{ planning.planBodyVerification.gateResult | inline_code }} ({{ planning.planBodyVerification.roundCount }} rounds{% if planning.planBodyVerification.get("selfFixRoundsApplied") is not none %}, {{ planning.planBodyVerification.selfFixRoundsApplied }} self-fix rounds{% if planning.planBodyVerification.get("selfFixStopReason") %} · {{ planning.planBodyVerification.selfFixStopReason | inline_code }}{% endif %}{% endif %})</p>
71
- {% if planning.planBodyVerification.get("gateBlockedBy") %}<p><strong>What it blocked</strong> — {{ planning.planBodyVerification.gateBlockedBy | join(", ") | inline_code }}</p>{% endif %}
72
- <table><thead><tr><th>Plan item</th><th>Subject</th></tr></thead><tbody>{% for row in planning.planBodyVerification.planItems %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Source section", row.sourceSection)]) }}<td>{{ row.subject | inline_code }}</td></tr>{% endfor %}</tbody></table>
73
- {% if planning.planBodyVerification.get("dissentLog") %}<h3>Dissent left standing</h3>
74
- <table><thead><tr><th>Subject</th><th>Body</th></tr></thead><tbody>{% for row in planning.planBodyVerification.dissentLog %}<tr>{{ row_key(pairs=[("Subject", row.planItem), ("Worker", row.workerRole)]) }}<td>{{ row.body | inline_code }}</td></tr>{% endfor %}</tbody></table>{% endif %}
69
+ <h2>{{ t('tasks.implementation-planning.plan-body-verification') }}</h2>
70
+ <p><strong>{{ t('tasks.implementation-planning.verdict') }}</strong> — {{ planning.planBodyVerification.gateResult | inline_code }} ({{ planning.planBodyVerification.roundCount }} rounds{% if planning.planBodyVerification.get("selfFixRoundsApplied") is not none %}, {{ planning.planBodyVerification.selfFixRoundsApplied }} self-fix rounds{% if planning.planBodyVerification.get("selfFixStopReason") %} · {{ planning.planBodyVerification.selfFixStopReason | inline_code }}{% endif %}{% endif %})</p>
71
+ {% if planning.planBodyVerification.get("gateBlockedBy") %}<p><strong>{{ t('tasks.implementation-planning.what-it-blocked') }}</strong> — {{ planning.planBodyVerification.gateBlockedBy | join(", ") | inline_code }}</p>{% endif %}
72
+ <table><thead><tr><th>{{ t('tasks.implementation-planning.plan-item') }}</th><th>{{ t('tasks.implementation-planning.subject') }}</th></tr></thead><tbody>{% for row in planning.planBodyVerification.planItems %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Source section", row.sourceSection)]) }}<td>{{ row.subject | inline_code }}</td></tr>{% endfor %}</tbody></table>
73
+ {% if planning.planBodyVerification.get("dissentLog") %}<h3>{{ t('tasks.implementation-planning.dissent-left-standing') }}</h3>
74
+ <table><thead><tr><th>{{ t('tasks.implementation-planning.subject') }}</th><th>{{ t('tasks.implementation-planning.body') }}</th></tr></thead><tbody>{% for row in planning.planBodyVerification.dissentLog %}<tr>{{ row_key(pairs=[("Subject", row.planItem), ("Worker", row.workerRole)]) }}<td>{{ row.body | inline_code }}</td></tr>{% endfor %}</tbody></table>{% endif %}
75
75
  </section>
76
76
 
77
77
  {% if planning.get("supersessionLedger") is not none %}
78
78
  <section data-report-section="superseded" data-report-field="implementationPlanning.supersessionLedger">
79
- <h2>What your answers overturned</h2>
80
- <table><thead><tr><th>Answer</th><th>Statement overturned</th><th>Replaced with</th></tr></thead><tbody>{% for row in planning.supersessionLedger %}<tr>{{ row_key(pairs=[("Answer", row.clarificationId), ("Disposition", row.disposition)]) }}<td>{{ row.supersededStatement | inline_code }}</td><td>{{ row.replacedWith | inline_code }}</td></tr>{% else %}<tr><td colspan="4">No answer overturned anything.</td></tr>{% endfor %}</tbody></table>
79
+ <h2>{{ t('tasks.implementation-planning.what-your-answers-overturned') }}</h2>
80
+ <table><thead><tr><th>{{ t('tasks.implementation-planning.answer') }}</th><th>{{ t('tasks.implementation-planning.statement-overturned') }}</th><th>{{ t('tasks.implementation-planning.replaced-with') }}</th></tr></thead><tbody>{% for row in planning.supersessionLedger %}<tr>{{ row_key(pairs=[("Answer", row.clarificationId), ("Disposition", row.disposition)]) }}<td>{{ row.supersededStatement | inline_code }}</td><td>{{ row.replacedWith | inline_code }}</td></tr>{% else %}<tr><td colspan="4">{{ t('tasks.implementation-planning.no-answer-overturned-anything') }}</td></tr>{% endfor %}</tbody></table>
81
81
  </section>
82
82
  {% endif %}
83
83
 
84
84
  {% if planning.get("incrementalDecision") %}<section data-report-section="replan-scope" data-report-field="implementationPlanning.incrementalDecision">
85
- <h2>Scope, restated</h2>
85
+ <h2>{{ t('tasks.implementation-planning.scope-restated') }}</h2>
86
86
  <p><strong>{{ planning.incrementalDecision.mode | inline_code }}</strong> — {{ planning.incrementalDecision.reason | inline_code }}</p>
87
- <p><strong>Stages verified again</strong> — {{ planning.incrementalDecision.reverifyStages | default([]) | join(", ") | inline_code }} · <strong>Stages carried over as they were</strong> — {{ planning.incrementalDecision.carryStages | default([]) | join(", ") | inline_code }}</p>
87
+ <p><strong>{{ t('tasks.implementation-planning.stages-verified-again') }}</strong> — {{ planning.incrementalDecision.reverifyStages | default([]) | join(", ") | inline_code }} · <strong>{{ t('tasks.implementation-planning.stages-carried-over-as-they-were') }}</strong> — {{ planning.incrementalDecision.carryStages | default([]) | join(", ") | inline_code }}</p>
88
88
  </section>{% endif %}
89
89
 
90
90
  <section data-report-section="decision-drafts" data-report-field="implementationPlanning.decisionDrafts">
91
- <h2>Decision record draft</h2>
91
+ <h2>{{ t('tasks.implementation-planning.decision-record-draft') }}</h2>
92
92
  {% for row in planning.decisionDrafts %}
93
- <article class="summary-card"><h3>{{ row.number }} · {{ row.slug | inline_code }} ({{ row.status | inline_code }})</h3><p><strong>Context</strong> — {{ row.context | inline_code }}</p><p><strong>Decision</strong> — {{ row.decision | inline_code }}</p><p><strong>Result</strong> — {{ row.consequences | inline_code }}</p></article>
94
- {% else %}<p>There is no decision draft to record.</p>{% endfor %}
95
- {% if planning.get("skippedAdrCandidates") %}<h3>What was deliberately not recorded</h3>
96
- <table data-report-field="implementationPlanning.skippedAdrCandidates"><thead><tr><th>Topic</th><th>Why</th></tr></thead><tbody>{% for row in planning.skippedAdrCandidates %}<tr><td>{{ row.topic | inline_code }}</td><td>{{ row.reason | inline_code }}</td></tr>{% endfor %}</tbody></table>{% endif %}
93
+ <article class="summary-card"><h3>{{ row.number }} · {{ row.slug | inline_code }} ({{ row.status | inline_code }})</h3><p><strong>{{ t('tasks.implementation-planning.context') }}</strong> — {{ row.context | inline_code }}</p><p><strong>{{ t('tasks.implementation-planning.decision') }}</strong> — {{ row.decision | inline_code }}</p><p><strong>{{ t('tasks.implementation-planning.result') }}</strong> — {{ row.consequences | inline_code }}</p></article>
94
+ {% else %}<p>{{ t('tasks.implementation-planning.there-is-no-decision-draft-to-record') }}</p>{% endfor %}
95
+ {% if planning.get("skippedAdrCandidates") %}<h3>{{ t('tasks.implementation-planning.what-was-deliberately-not-recorded') }}</h3>
96
+ <table data-report-field="implementationPlanning.skippedAdrCandidates"><thead><tr><th>{{ t('tasks.implementation-planning.topic') }}</th><th>{{ t('tasks.implementation-planning.why') }}</th></tr></thead><tbody>{% for row in planning.skippedAdrCandidates %}<tr><td>{{ row.topic | inline_code }}</td><td>{{ row.reason | inline_code }}</td></tr>{% endfor %}</tbody></table>{% endif %}
97
97
  </section>
98
98
 
99
99
  <section data-report-section="open-decisions">
100
- <h2>Open decisions before approval</h2>
101
- <div class="summary-grid">{% for row in openDecisions %}{{ summary_card(row.id ~ " · " ~ row.kind, row.statement, "important", anchor=row.id) }}{% else %}<p>No open decision is holding approval.</p>{% endfor %}</div>
100
+ <h2>{{ t('tasks.implementation-planning.open-decisions-before-approval') }}</h2>
101
+ <div class="summary-grid">{% for row in openDecisions %}{{ summary_card(row.id ~ " · " ~ row.kind, row.statement, "important", anchor=row.id) }}{% else %}<p>{{ t('tasks.implementation-planning.no-open-decision-is-holding-approval') }}</p>{% endfor %}</div>
102
102
  {{ action_list(humanSummary.actions) }}
103
103
  </section>
104
104
 
@@ -4,55 +4,55 @@
4
4
 
5
5
  {% block human_content %}
6
6
  <section data-report-section="delivered-outcome">
7
- <h2>What was delivered</h2>
7
+ <h2>{{ t('tasks.implementation.what-was-delivered') }}</h2>
8
8
  {{ render_narrative(narrative.deliveredOutcome, "implementation.userNarrative.deliveredOutcome") }}
9
9
  <p>{{ humanSummary.outcome | inline_code }}</p>
10
10
  </section>
11
11
 
12
12
  <section data-report-section="change-map" data-report-field="implementation.diffSummary">
13
- <h2>What changed</h2>
13
+ <h2>{{ t('tasks.implementation.what-changed') }}</h2>
14
14
  {{ render_narrative(narrative.changeExplanation, "implementation.userNarrative.changeExplanation") }}
15
15
  {{ figure(changeFigure) }}
16
16
  </section>
17
17
 
18
18
  <section data-report-section="requirement-coverage">
19
- <h2>Requirement coverage</h2>
20
- <table data-report-field="implementation.requirementCoverage"><thead><tr><th>Requirement</th><th>Body</th><th>Implemented by</th></tr></thead><tbody>{% for row in implementation.requirementCoverage %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id)], status_name="Status", status_raw=row.status, status_text=row.status) }}<td>{{ row.requirement | inline_code }}</td><td>{{ row.coveredBy | inline_code }}</td></tr>{% endfor %}</tbody></table>
19
+ <h2>{{ t('tasks.implementation.requirement-coverage') }}</h2>
20
+ <table data-report-field="implementation.requirementCoverage"><thead><tr><th>{{ t('tasks.implementation.requirement') }}</th><th>{{ t('tasks.implementation.body') }}</th><th>{{ t('tasks.implementation.implemented-by') }}</th></tr></thead><tbody>{% for row in implementation.requirementCoverage %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id)], status_name="Status", status_raw=row.status, status_text=row.status) }}<td>{{ row.requirement | inline_code }}</td><td>{{ row.coveredBy | inline_code }}</td></tr>{% endfor %}</tbody></table>
21
21
  </section>
22
22
 
23
23
  <section data-report-section="validation" data-report-field="implementation.validationEvidence">
24
- <h2>Verification result</h2>
24
+ <h2>{{ t('tasks.implementation.verification-result') }}</h2>
25
25
  {{ render_narrative(narrative.validationExplanation, "implementation.userNarrative.validationExplanation") }}
26
26
  <div class="summary-grid">{% for row in implementation.validationEvidence %}{{ summary_card(row.phase ~ " · exit code " ~ row.exitCode, row.outputTail, "important" if row.exitCode else "neutral") }}{% endfor %}</div>
27
- <p><strong>Independent check:</strong> {% for row in implementation.verifierResults %}<span class="status status-{{ row.verdict | lower }}">{{ row.verdict }}</span>{% if not loop.last %}, {% endif %}{% endfor %}</p>
27
+ <p><strong>{{ t('tasks.implementation.independent-check') }}</strong> {% for row in implementation.verifierResults %}<span class="status status-{{ row.verdict | lower }}">{{ row.verdict }}</span>{% if not loop.last %}, {% endif %}{% endfor %}</p>
28
28
  </section>
29
29
 
30
30
  <section data-report-section="remaining-issues">
31
- <h2>What is left</h2>
31
+ <h2>{{ t('tasks.implementation.what-is-left') }}</h2>
32
32
  {{ render_narrative(narrative.remainingIssues, "implementation.userNarrative.remainingIssues") }}
33
- <div class="summary-grid">{% for row in implementation.outOfPlanEdits %}{{ summary_card(row.id ~ " · " ~ row.file, row.rationale, "important", anchor=row.id) }}{% else %}<p>Nothing was changed outside the plan.</p>{% endfor %}</div>
33
+ <div class="summary-grid">{% for row in implementation.outOfPlanEdits %}{{ summary_card(row.id ~ " · " ~ row.file, row.rationale, "important", anchor=row.id) }}{% else %}<p>{{ t('tasks.implementation.nothing-was-changed-outside-the-plan') }}</p>{% endfor %}</div>
34
34
  </section>
35
35
 
36
36
  <section data-report-section="shipped-commits" data-report-field="implementation.commitList">
37
- <h2>Commits delivered</h2>
38
- {% if implementation.commitList is mapping %}<p>There are no commits.</p>{% else %}
39
- <table><thead><tr><th>Commit</th><th>Subject</th><th>Files</th></tr></thead><tbody>{% for row in implementation.commitList %}<tr>{{ row_key(pairs=[("SHA", row.shortSha), ("Order", row.number), ("Plan step", row.planStep)]) }}<td>{{ row.subject | inline_code }}</td><td>{% for file in row.files %}<code>{{ file }}</code>{% if not loop.last %} {% endif %}{% endfor %}</td></tr>{% endfor %}</tbody></table>{% endif %}
40
- <table data-report-field="implementation.approvedPlanReference"><tbody><tr><th>Approved plan</th><td><code>{{ implementation.approvedPlanReference.planFile }}</code></td></tr><tr><th>Approval evidence</th><td>{{ implementation.approvedPlanReference.approvalEvidence | inline_code }}</td></tr><tr><th>Worktree</th><td><code>{{ implementation.approvedPlanReference.executorWorktreePath }}</code> @ <code>{{ implementation.approvedPlanReference.baseRefSha }}</code></td></tr></tbody></table>
37
+ <h2>{{ t('tasks.implementation.commits-delivered') }}</h2>
38
+ {% if implementation.commitList is mapping %}<p>{{ t('tasks.implementation.there-are-no-commits') }}</p>{% else %}
39
+ <table><thead><tr><th>{{ t('tasks.implementation.commit') }}</th><th>{{ t('tasks.implementation.subject') }}</th><th>{{ t('tasks.implementation.files') }}</th></tr></thead><tbody>{% for row in implementation.commitList %}<tr>{{ row_key(pairs=[("SHA", row.shortSha), ("Order", row.number), ("Plan step", row.planStep)]) }}<td>{{ row.subject | inline_code }}</td><td>{% for file in row.files %}<code>{{ file }}</code>{% if not loop.last %} {% endif %}{% endfor %}</td></tr>{% endfor %}</tbody></table>{% endif %}
40
+ <table data-report-field="implementation.approvedPlanReference"><tbody><tr><th>{{ t('tasks.implementation.approved-plan') }}</th><td><code>{{ implementation.approvedPlanReference.planFile }}</code></td></tr><tr><th>{{ t('tasks.implementation.approval-evidence') }}</th><td>{{ implementation.approvedPlanReference.approvalEvidence | inline_code }}</td></tr><tr><th>{{ t('tasks.implementation.worktree') }}</th><td><code>{{ implementation.approvedPlanReference.executorWorktreePath }}</code> @ <code>{{ implementation.approvedPlanReference.baseRefSha }}</code></td></tr></tbody></table>
41
41
  </section>
42
42
 
43
43
  <section data-report-section="rollback" data-report-field="implementation.rollbackVerification">
44
- <h2>Can this be rolled back</h2>
45
- <table><thead><tr><th>Subject</th><th>Rollback command</th><th>How to verify</th><th>Result</th></tr></thead><tbody>{% for row in implementation.rollbackVerification %}<tr><td>{{ row.category | inline_code }}</td><td><code>{{ row.rollbackCommand }}</code></td><td>{{ row.verification | inline_code }}</td><td>{{ row.result | inline_code }}</td></tr>{% else %}<tr><td colspan="4">No rollback check was recorded.</td></tr>{% endfor %}</tbody></table>
46
- {% if implementation.stageSidecarEvidence %}<p data-report-field="implementation.stageSidecarEvidence"><strong>Stage carry-over</strong> — Stage {{ implementation.stageSidecarEvidence.stageNumber }} {{ implementation.stageSidecarEvidence.stageTitle | inline_code }} · <code>{{ implementation.stageSidecarEvidence.carryJson }}</code></p>{% endif %}
44
+ <h2>{{ t('tasks.implementation.can-this-be-rolled-back') }}</h2>
45
+ <table><thead><tr><th>{{ t('tasks.implementation.subject') }}</th><th>{{ t('tasks.implementation.rollback-command') }}</th><th>{{ t('tasks.implementation.how-to-verify') }}</th><th>{{ t('tasks.implementation.result') }}</th></tr></thead><tbody>{% for row in implementation.rollbackVerification %}<tr><td>{{ row.category | inline_code }}</td><td><code>{{ row.rollbackCommand }}</code></td><td>{{ row.verification | inline_code }}</td><td>{{ row.result | inline_code }}</td></tr>{% else %}<tr><td colspan="4">{{ t('tasks.implementation.no-rollback-check-was-recorded') }}</td></tr>{% endfor %}</tbody></table>
46
+ {% if implementation.stageSidecarEvidence %}<p data-report-field="implementation.stageSidecarEvidence"><strong>{{ t('tasks.implementation.stage-carry-over') }}</strong> — Stage {{ implementation.stageSidecarEvidence.stageNumber }} {{ implementation.stageSidecarEvidence.stageTitle | inline_code }} · <code>{{ implementation.stageSidecarEvidence.carryJson }}</code></p>{% endif %}
47
47
  </section>
48
48
 
49
49
  <section data-report-section="manual-test" data-report-field="implementation.manualUserTest">
50
- <h2>Manual user test</h2>
51
- {% if implementation.manualUserTest.applicable %}{% for row in implementation.manualUserTest["items"] %}<article class="summary-card"><h3>{{ row.target | inline_code }}</h3><p><strong>Environment:</strong> {{ row.environmentSetup | inline_code }}</p><ol>{% for step in row.steps %}<li>{{ step | inline_code }}</li>{% endfor %}</ol><p><strong>Expected:</strong> {{ row.expectedResult | inline_code }}</p></article>{% endfor %}{% else %}<p>{{ implementation.manualUserTest.exemptionReason | inline_code }}</p>{% endif %}
50
+ <h2>{{ t('tasks.implementation.manual-user-test') }}</h2>
51
+ {% if implementation.manualUserTest.applicable %}{% for row in implementation.manualUserTest["items"] %}<article class="summary-card"><h3>{{ row.target | inline_code }}</h3><p><strong>{{ t('tasks.implementation.environment') }}</strong> {{ row.environmentSetup | inline_code }}</p><ol>{% for step in row.steps %}<li>{{ step | inline_code }}</li>{% endfor %}</ol><p><strong>{{ t('tasks.implementation.expected') }}</strong> {{ row.expectedResult | inline_code }}</p></article>{% endfor %}{% else %}<p>{{ implementation.manualUserTest.exemptionReason | inline_code }}</p>{% endif %}
52
52
  </section>
53
53
 
54
54
  <section data-report-section="next-step" data-report-field="implementation.routingRecommendation">
55
- <h2>Next step</h2>
55
+ <h2>{{ t('tasks.implementation.next-step') }}</h2>
56
56
  <p>{{ implementation.routingRecommendation | inline_code }}</p>
57
57
  </section>
58
58
  {% endblock %}
@@ -4,26 +4,26 @@
4
4
 
5
5
  {% block human_content %}
6
6
  <section data-report-section="opportunities">
7
- <h2>Improvements found</h2>
7
+ <h2>{{ t('tasks.improvement-discovery.improvements-found') }}</h2>
8
8
  {{ render_narrative(narrative.opportunityOverview, "improvementDiscovery.userNarrative.opportunityOverview") }}
9
- <table data-report-field="improvementDiscovery.lensCoverage"><thead><tr><th>Lens</th><th>Detail</th><th>Evidence</th></tr></thead><tbody>{% for row in improvement.lensCoverage %}<tr>{{ row_key(pairs=[("Lens", row.lens), ("Result", row.status | enum_label("lens"))]) }}<td>{{ row.rationale | inline_code }}</td><td>{{ row.evidence | evidence_refs }}</td></tr>{% endfor %}</tbody></table>
9
+ <table data-report-field="improvementDiscovery.lensCoverage"><thead><tr><th>{{ t('tasks.improvement-discovery.lens') }}</th><th>{{ t('tasks.improvement-discovery.detail') }}</th><th>{{ t('tasks.improvement-discovery.evidence') }}</th></tr></thead><tbody>{% for row in improvement.lensCoverage %}<tr>{{ row_key(pairs=[("Lens", row.lens), ("Result", row.status | enum_label("lens"))]) }}<td>{{ row.rationale | inline_code }}</td><td>{{ row.evidence | evidence_refs }}</td></tr>{% endfor %}</tbody></table>
10
10
  </section>
11
11
 
12
12
  <section data-report-section="ranked-candidates">
13
- <h2>Ranked candidates</h2>
13
+ <h2>{{ t('tasks.improvement-discovery.ranked-candidates') }}</h2>
14
14
  {{ render_narrative(narrative.prioritizationExplanation, "improvementDiscovery.userNarrative.prioritizationExplanation") }}
15
- <div class="summary-grid" data-report-field="improvementDiscovery.candidates">{% for row in improvement.candidates %}<article class="summary-card tone-{{ row.severity }}" id="id-{{ row.id }}"><p class="eyebrow">#{{ loop.index }} · {{ row.id }} · Impact {{ row.severity }} · Effort {{ row.effort | enum_label("effort") }}</p><h3>{{ row.title | inline_code }}</h3><p>{{ row.expectedBehaviorAfter | inline_code }}</p><p><strong>Next step:</strong> {{ row.recommendedNextPhase }}</p><p class="evidence-refs">Evidence: {{ row.evidence | evidence_refs }}</p></article>{% else %}<p>There is no improvement candidate to pick.</p>{% endfor %}</div>
15
+ <div class="summary-grid" data-report-field="improvementDiscovery.candidates">{% for row in improvement.candidates %}<article class="summary-card tone-{{ row.severity }}" id="id-{{ row.id }}"><p class="eyebrow">#{{ loop.index }} · {{ row.id }} · Impact {{ row.severity }} · Effort {{ row.effort | enum_label("effort") }}</p><h3>{{ row.title | inline_code }}</h3><p>{{ row.expectedBehaviorAfter | inline_code }}</p><p><strong>{{ t('tasks.improvement-discovery.next-step') }}</strong> {{ row.recommendedNextPhase }}</p><p class="evidence-refs">Evidence: {{ row.evidence | evidence_refs }}</p></article>{% else %}<p>{{ t('tasks.improvement-discovery.there-is-no-improvement-candidate-to-pick') }}</p>{% endfor %}</div>
16
16
  </section>
17
17
 
18
18
  <section data-report-section="impact-effort">
19
- <h2>Impact and effort</h2>
19
+ <h2>{{ t('tasks.improvement-discovery.impact-and-effort') }}</h2>
20
20
  {{ figure(matrixFigure) }}
21
21
  </section>
22
22
 
23
23
  <section data-report-section="selection">
24
- <h2>How to choose</h2>
24
+ <h2>{{ t('tasks.improvement-discovery.how-to-choose') }}</h2>
25
25
  {{ render_narrative(narrative.selectionGuidance, "improvementDiscovery.userNarrative.selectionGuidance") }}
26
- <p><strong>Selection cap:</strong> at most {{ improvement.selectionLimit }}</p>
26
+ <p><strong>{{ t('tasks.improvement-discovery.selection-cap') }}</strong> at most {{ improvement.selectionLimit }}</p>
27
27
  <ul>{% for row in improvement.candidates %}<li><label><input type="checkbox" name="improvement-candidate" value="{{ row.id }}"> {{ row.id }} · {{ row.title | inline_code }}</label></li>{% endfor %}</ul>
28
28
  </section>
29
29
  {% endblock %}