okstra 0.149.0 → 0.151.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/architecture.md +1 -1
- package/docs/cli.md +2 -2
- package/docs/project-structure-overview.md +1 -1
- package/package.json +3 -2
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/report-writer-worker.md +8 -0
- package/runtime/agents/workers/translator-worker.md +67 -0
- package/runtime/bin/okstra-render-final-report.py +0 -11
- package/runtime/bin/okstra-report-translate.py +191 -0
- package/runtime/prompts/lead/adapters/claude-code.md +1 -1
- package/runtime/prompts/lead/okstra-lead-contract.md +1 -0
- package/runtime/prompts/lead/plan-body-verification.md +1 -1
- package/runtime/prompts/lead/report-writer.md +16 -15
- package/runtime/prompts/lead/team-contract.md +2 -2
- package/runtime/prompts/wizard/prompts.ko.json +17 -1
- package/runtime/python/okstra_ctl/analysis_inputs.py +24 -9
- package/runtime/python/okstra_ctl/analysis_packet.py +23 -1
- package/runtime/python/okstra_ctl/clarification_items.py +241 -44
- package/runtime/python/okstra_ctl/codex_dispatch.py +2 -1
- package/runtime/python/okstra_ctl/convergence.py +15 -1
- package/runtime/python/okstra_ctl/dispatch_core.py +2 -2
- package/runtime/python/okstra_ctl/dispatch_state.py +12 -1
- package/runtime/python/okstra_ctl/final_report_paths.py +22 -1
- package/runtime/python/okstra_ctl/i18n.py +12 -7
- package/runtime/python/okstra_ctl/render_final_report.py +18 -17
- package/runtime/python/okstra_ctl/report_finalize.py +18 -0
- package/runtime/python/okstra_ctl/report_html/filters.py +15 -77
- package/runtime/python/okstra_ctl/report_html/render.py +44 -2
- package/runtime/python/okstra_ctl/report_translation.py +469 -0
- package/runtime/python/okstra_ctl/report_views.py +23 -9
- package/runtime/python/okstra_ctl/run.py +1 -1
- package/runtime/python/okstra_ctl/user_response.py +11 -6
- package/runtime/python/okstra_ctl/wizard.py +100 -25
- package/runtime/python/okstra_ctl/worker_liveness.py +130 -36
- package/runtime/templates/reports/html/base.template.html +12 -12
- package/runtime/templates/reports/html/i18n/en.json +395 -0
- package/runtime/templates/reports/html/i18n/ko.json +395 -0
- package/runtime/templates/reports/html/macros/forms.html +16 -16
- package/runtime/templates/reports/html/macros/visualizations.html +2 -2
- package/runtime/templates/reports/html/tasks/change-impact-analysis.template.html +17 -17
- package/runtime/templates/reports/html/tasks/error-analysis.template.html +12 -12
- package/runtime/templates/reports/html/tasks/feature-analysis.template.html +16 -16
- package/runtime/templates/reports/html/tasks/final-verification.template.html +12 -12
- package/runtime/templates/reports/html/tasks/implementation-planning.template.html +37 -37
- package/runtime/templates/reports/html/tasks/implementation.template.html +18 -18
- package/runtime/templates/reports/html/tasks/improvement-discovery.template.html +7 -7
- package/runtime/templates/reports/html/tasks/project-analysis.template.html +29 -29
- package/runtime/templates/reports/html/tasks/release-handoff.template.html +13 -13
- package/runtime/templates/reports/html/tasks/requirements-discovery.template.html +14 -14
- package/runtime/templates/reports/report.js +8 -5
- package/runtime/validators/validate-report-views.py +1 -1
- package/runtime/validators/validate-run.py +59 -31
- package/src/cli-registry.mjs +11 -0
- package/src/commands/inspect/worker-liveness.mjs +9 -7
- package/src/commands/report/translate.mjs +31 -0
- package/src/lib/helper-scripts.mjs +1 -0
- 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>
|
|
8
|
+
<h2>{{ t('tasks.feature-analysis.feature-overview') }}</h2>
|
|
9
9
|
{{ render_narrative(narrative.userBehaviorExplanation, "featureAnalysis.userNarrative.userBehaviorExplanation") }}
|
|
10
|
-
<p><strong>
|
|
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>
|
|
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>
|
|
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>
|
|
25
|
-
<div data-report-field="featureAnalysis.stateChanges"><h3>
|
|
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>
|
|
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>
|
|
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>
|
|
41
|
-
<table><thead><tr><th>
|
|
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>
|
|
46
|
-
<table><thead><tr><th>
|
|
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>
|
|
51
|
-
<table><thead><tr><th>
|
|
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>
|
|
56
|
-
<table><thead><tr><th>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
36
|
-
<table><tbody><tr><th>
|
|
37
|
-
{% if final.get("stageReports") %}<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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
17
|
-
<table data-report-field="implementationPlanning.tradeoffMatrix"><thead><tr><th>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
45
|
+
<h2>{{ t('tasks.implementation-planning.where-implementations-diverge') }}</h2>
|
|
46
46
|
{% if planning.variationPointAnalysis.hasMultipleImplementations %}
|
|
47
|
-
<table><thead><tr><th>
|
|
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>
|
|
54
|
-
<table><thead><tr><th>#</th><th>
|
|
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>
|
|
59
|
+
<h2>{{ t('tasks.implementation-planning.verification-and-rollback') }}</h2>
|
|
60
60
|
{{ render_narrative(narrative.validationAndRollback, "implementationPlanning.userNarrative.validationAndRollback") }}
|
|
61
|
-
<h3>
|
|
62
|
-
<h3>
|
|
63
|
-
<h3>
|
|
64
|
-
<h3>
|
|
65
|
-
<h3>
|
|
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>
|
|
70
|
-
<p><strong>
|
|
71
|
-
{% if planning.planBodyVerification.get("gateBlockedBy") %}<p><strong>
|
|
72
|
-
<table><thead><tr><th>
|
|
73
|
-
{% if planning.planBodyVerification.get("dissentLog") %}<h3>
|
|
74
|
-
<table><thead><tr><th>
|
|
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>
|
|
80
|
-
<table><thead><tr><th>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
94
|
-
{% else %}<p>
|
|
95
|
-
{% if planning.get("skippedAdrCandidates") %}<h3>
|
|
96
|
-
<table data-report-field="implementationPlanning.skippedAdrCandidates"><thead><tr><th>
|
|
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>
|
|
101
|
-
<div class="summary-grid">{% for row in openDecisions %}{{ summary_card(row.id ~ " · " ~ row.kind, row.statement, "important", anchor=row.id) }}{% else %}<p>
|
|
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>
|
|
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>
|
|
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>
|
|
20
|
-
<table data-report-field="implementation.requirementCoverage"><thead><tr><th>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
38
|
-
{% if implementation.commitList is mapping %}<p>
|
|
39
|
-
<table><thead><tr><th>
|
|
40
|
-
<table data-report-field="implementation.approvedPlanReference"><tbody><tr><th>
|
|
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>
|
|
45
|
-
<table><thead><tr><th>
|
|
46
|
-
{% if implementation.stageSidecarEvidence %}<p data-report-field="implementation.stageSidecarEvidence"><strong>
|
|
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>
|
|
51
|
-
{% if implementation.manualUserTest.applicable %}{% for row in implementation.manualUserTest["items"] %}<article class="summary-card"><h3>{{ row.target | inline_code }}</h3><p><strong>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
24
|
+
<h2>{{ t('tasks.improvement-discovery.how-to-choose') }}</h2>
|
|
25
25
|
{{ render_narrative(narrative.selectionGuidance, "improvementDiscovery.userNarrative.selectionGuidance") }}
|
|
26
|
-
<p><strong>
|
|
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 %}
|