okstra 0.185.1 → 0.186.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/dist/commands/chat/chat.mjs +60 -14
- package/dist/commands/chat/chat.mjs.map +1 -1
- package/docs/cli.md +1 -1
- package/docs/for-ai/skills/okstra-chat.md +4 -4
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/prompts/lead/okstra-lead-contract.md +1 -1
- package/runtime/prompts/profiles/implementation-planning.md +1 -1
- package/runtime/python/okstra_ctl/cmux.py +63 -35
- package/runtime/python/okstra_ctl/report_html/common.py +86 -11
- package/runtime/python/okstra_ctl/report_html/filters.py +27 -10
- package/runtime/python/okstra_ctl/report_html/render.py +1 -0
- package/runtime/python/okstra_ctl/report_html/report_index.py +5 -1
- package/runtime/python/okstra_ctl/report_html/view_models/implementation_planning.py +1 -1
- package/runtime/skills/okstra-chat/SKILL.md +10 -2
- package/runtime/templates/reports/html/assets/base.css +48 -3
- package/runtime/templates/reports/html/base.template.html +7 -4
- package/runtime/templates/reports/html/i18n/en.json +86 -8
- package/runtime/templates/reports/html/i18n/ko.json +86 -8
- package/runtime/templates/reports/html/macros/forms.html +74 -55
- package/runtime/templates/reports/html/macros/layout.html +2 -2
- package/runtime/templates/reports/html/macros/visualizations.html +1 -1
- package/runtime/templates/reports/html/tasks/change-impact-analysis.template.html +2 -2
- package/runtime/templates/reports/html/tasks/error-analysis.template.html +3 -3
- package/runtime/templates/reports/html/tasks/feature-analysis.template.html +4 -4
- package/runtime/templates/reports/html/tasks/final-verification.template.html +3 -3
- package/runtime/templates/reports/html/tasks/implementation-option-selection.template.html +9 -9
- package/runtime/templates/reports/html/tasks/implementation-planning.template.html +20 -18
- package/runtime/templates/reports/html/tasks/implementation.template.html +3 -3
- package/runtime/templates/reports/html/tasks/improvement-discovery.template.html +3 -3
- package/runtime/templates/reports/html/tasks/project-analysis.template.html +10 -10
- package/runtime/templates/reports/html/tasks/release-handoff.template.html +2 -2
- package/runtime/templates/reports/html/tasks/requirements-discovery.template.html +4 -4
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
{% if state.show_option_selector %}<label for="approval-option">{{ t('macros.forms.implementation-option') }}</label>
|
|
32
32
|
<select id="approval-option"{% if state.disabled_reason %} disabled{% endif %}>
|
|
33
33
|
{% for name in state.option_names %}
|
|
34
|
-
{% if name == state.recommended_option %}<option data-recommended="true" selected value="{{ name }}">{{ name | inline_code }} (recommended)</option>{% else %}<option value="{{ name }}">{{ name | inline_code }}</option>{% endif %}
|
|
34
|
+
{% if name == state.recommended_option %}<option data-recommended="true" selected value="{{ name }}">{{ name | inline_code }} ({{ t('macros.forms.recommended') }})</option>{% else %}<option value="{{ name }}">{{ name | inline_code }}</option>{% endif %}
|
|
35
35
|
{% endfor %}
|
|
36
36
|
</select>{% endif %}
|
|
37
37
|
<label for="plan-decision-reason">{{ t('macros.forms.why-required-for-changes-or-rejection') }}</label>
|
|
@@ -43,69 +43,88 @@
|
|
|
43
43
|
|
|
44
44
|
{% macro direction_selection(state) -%}
|
|
45
45
|
<section id="direction-selection" data-report-section="direction-selection">
|
|
46
|
-
<h2>
|
|
47
|
-
<fieldset><legend>
|
|
46
|
+
<h2>{{ t('macros.forms.select-an-implementation-direction') }}</h2>
|
|
47
|
+
<fieldset><legend>{{ t('macros.forms.direction') }}</legend>
|
|
48
48
|
{% for option in state.rankedOptions %}
|
|
49
|
-
<input id="direction-selection-{{ option.id }}" type="radio" name="direction-selection-option" value="{{ option.id }}" data-option-name="{{ option.name }}" required><label for="direction-selection-{{ option.id }}">{{ option.id }} · {{ option.name | inline_code }}{% if option.id == state.recommendedOptionId %} (recommended){% endif %}</label>
|
|
49
|
+
<input id="direction-selection-{{ option.id }}" type="radio" name="direction-selection-option" value="{{ option.id }}" data-option-name="{{ option.name }}" required><label for="direction-selection-{{ option.id }}">{{ option.id | inline_code }} · {{ option.name | inline_code }}{% if option.id == state.recommendedOptionId %} ({{ t('macros.forms.recommended') }}){% endif %}</label>
|
|
50
50
|
{% endfor %}
|
|
51
51
|
</fieldset>
|
|
52
|
-
<input id="direction-selection-confirmed" type="checkbox" required><label for="direction-selection-confirmed">
|
|
53
|
-
<label for="direction-selection-note">
|
|
54
|
-
<label for="direction-selection-constraints">
|
|
52
|
+
<input id="direction-selection-confirmed" type="checkbox" required><label for="direction-selection-confirmed">{{ t('macros.forms.confirmed') }}</label>
|
|
53
|
+
<label for="direction-selection-note">{{ t('macros.forms.selection-note') }}</label><textarea id="direction-selection-note" rows="3"></textarea>
|
|
54
|
+
<label for="direction-selection-constraints">{{ t('macros.forms.constraints') }}</label><textarea id="direction-selection-constraints" rows="3"></textarea>
|
|
55
55
|
</section>
|
|
56
56
|
{%- endmacro %}
|
|
57
57
|
|
|
58
|
+
{% macro clarification_article(row, compact=false) -%}
|
|
59
|
+
{% set is_closed = row.status in ['resolved', 'obsolete'] %}
|
|
60
|
+
{% set approval_context = row.approvalContext | default(None) %}
|
|
61
|
+
{% set resolution = row.resolution | default(None) %}
|
|
62
|
+
{% set options = row.options | default([]) %}
|
|
63
|
+
<article class="clarification-item{% if compact %} is-closed{% endif %}" id="id-{{ row.id }}" data-response-id="{{ row.id }}" data-kind="{{ row.kind }}" data-status="{{ row.status }}">
|
|
64
|
+
{% if compact %}<details><summary>{{ row.id | inline_code }} · {{ row.status }}</summary>{% endif %}
|
|
65
|
+
<p class="eyebrow">{{ row.id | inline_code }} · {{ row.kind }}</p>
|
|
66
|
+
{{ row.statement | paragraphs }}
|
|
67
|
+
<dl class="clarification-expected"><dt>{{ t('macros.forms.answer-as') }}</dt><dd>{{ row.expectedForm | inline_code }}</dd></dl>
|
|
68
|
+
{% if approval_context %}
|
|
69
|
+
<div class="approval-context" data-approval-classification="{{ approval_context.classification }}">
|
|
70
|
+
<p class="eyebrow">{{ approval_context.classification }}</p>
|
|
71
|
+
<p><strong>{{ t('tasks.implementation-planning.unblock-condition') }}</strong> {{ approval_context.unblockCondition | inline_code }}</p>
|
|
72
|
+
{% set check_refs = resolution.checkRefs if resolution else approval_context.activityIds | default([]) %}
|
|
73
|
+
{% if check_refs %}<p><strong>{{ t('tasks.implementation-planning.agent-evidence') }}</strong>
|
|
74
|
+
{% for activity_id in check_refs %}<a href="#id-{{ activity_id }}">{{ activity_id }}</a>{% if not loop.last %}, {% endif %}{% endfor %}
|
|
75
|
+
</p>{% endif %}
|
|
76
|
+
</div>
|
|
77
|
+
{% endif %}
|
|
78
|
+
{% if options %}
|
|
79
|
+
<ol class="clarification-options">
|
|
80
|
+
{% for option in options %}
|
|
81
|
+
<li class="clarification-option{% if option.role == 'recommended' %} is-recommended{% endif %}">
|
|
82
|
+
<p class="clarification-option-answer">{{ option.answer }}{% if option.role == 'recommended' %} <span class="badge">{{ t('macros.forms.recommended') }}</span>{% endif %}</p>
|
|
83
|
+
{% if option.disposition | default(None) %}<p class="clarification-option-disposition"><code>{{ option.disposition }}</code></p>{% endif %}
|
|
84
|
+
<p class="clarification-option-rationale">{{ option.rationale }}</p>
|
|
85
|
+
<dl class="clarification-option-impact">
|
|
86
|
+
<dt>{{ t('macros.forms.scope-impact') }}</dt><dd>{% if option.reach | default(None) %}{{ option.reach }}{% if option.scopeEffects | default([]) %}, {{ option.scopeEffects | join(', ') }}{% endif %}{% else %}{{ option.scopeImpact | join(', ') }}{% endif %}</dd>
|
|
87
|
+
<dt>{{ t('macros.forms.added-work') }}</dt><dd>{{ option.addedWork }}</dd>
|
|
88
|
+
<dt>{{ t('macros.forms.direction-change') }}</dt><dd>{{ option.directionChange }}</dd>
|
|
89
|
+
</dl>
|
|
90
|
+
</li>
|
|
91
|
+
{% endfor %}
|
|
92
|
+
</ol>
|
|
93
|
+
{% endif %}
|
|
94
|
+
<label for="response-{{ row.id }}">{{ t('macros.forms.your-answer-to-id') | replace('{id}', row.id) }}</label>
|
|
95
|
+
{% if row.kind == 'decision' and approval_context and options %}
|
|
96
|
+
<select id="response-{{ row.id }}" data-response-id="{{ row.id }}"{% if is_closed %} disabled{% endif %}>
|
|
97
|
+
<option value="">{{ t('macros.forms.choose-one') }}</option>
|
|
98
|
+
{% for option in options %}<option value="{{ option.answer }}" data-disposition="{{ option.disposition | default('') }}"{% if option.role == 'recommended' %} data-recommended="true"{% endif %}{% if row.userInput | default('') == option.answer %} selected{% endif %}>{{ option.answer }}</option>{% endfor %}
|
|
99
|
+
</select>
|
|
100
|
+
{% else %}
|
|
101
|
+
<textarea id="response-{{ row.id }}" data-response-id="{{ row.id }}" rows="4"{% if is_closed %} disabled{% endif %}>{{ row.userInput | default('') }}</textarea>
|
|
102
|
+
{% endif %}
|
|
103
|
+
{% if compact %}</details>{% endif %}
|
|
104
|
+
</article>
|
|
105
|
+
{%- endmacro %}
|
|
106
|
+
|
|
58
107
|
{% macro clarification_responses(items) -%}
|
|
59
108
|
{% if items %}
|
|
60
|
-
|
|
61
|
-
|
|
109
|
+
{% set ns = namespace(open=[], closed=[]) %}
|
|
110
|
+
{% for row in items %}
|
|
111
|
+
{% if row.status in ['open', 'answered'] %}
|
|
112
|
+
{% set ns.open = ns.open + [row] %}
|
|
113
|
+
{% else %}
|
|
114
|
+
{% set ns.closed = ns.closed + [row] %}
|
|
115
|
+
{% endif %}
|
|
116
|
+
{% endfor %}
|
|
117
|
+
<section class="clarification-responses" data-report-section="clarification-responses" aria-label="{{ t('macros.forms.questions-waiting-on-you') if ns.open else t('macros.forms.answered-questions') }}">
|
|
118
|
+
{% if ns.open %}
|
|
119
|
+
<h2>{{ t('macros.forms.count-questions-waiting-on-you') | replace('{count}', ns.open | length) }}</h2>
|
|
62
120
|
<p class="clarification-lede">{{ t('macros.forms.the-code-alone-could-not-settle-these-fill-i') }} <strong>{{ t('macros.forms.export-my-answers') }}</strong> {{ t('macros.forms.at-the-foot-of-the-page') }}</p>
|
|
63
|
-
{% for row in
|
|
64
|
-
{%
|
|
65
|
-
{%
|
|
66
|
-
{%
|
|
67
|
-
{%
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
{{ row.statement | paragraphs }}
|
|
71
|
-
<dl class="clarification-expected"><dt>{{ t('macros.forms.answer-as') }}</dt><dd>{{ row.expectedForm | inline_code }}</dd></dl>
|
|
72
|
-
{% if approval_context %}
|
|
73
|
-
<div class="approval-context" data-approval-classification="{{ approval_context.classification }}">
|
|
74
|
-
<p class="eyebrow">{{ approval_context.classification }}</p>
|
|
75
|
-
<p><strong>{{ t('tasks.implementation-planning.unblock-condition') }}</strong> {{ approval_context.unblockCondition | inline_code }}</p>
|
|
76
|
-
{% set check_refs = resolution.checkRefs if resolution else approval_context.activityIds | default([]) %}
|
|
77
|
-
{% if check_refs %}<p><strong>{{ t('tasks.implementation-planning.agent-evidence') }}</strong>
|
|
78
|
-
{% for activity_id in check_refs %}<a href="#id-{{ activity_id }}">{{ activity_id }}</a>{% if not loop.last %}, {% endif %}{% endfor %}
|
|
79
|
-
</p>{% endif %}
|
|
80
|
-
</div>
|
|
81
|
-
{% endif %}
|
|
82
|
-
{% if options %}
|
|
83
|
-
<ol class="clarification-options">
|
|
84
|
-
{% for option in options %}
|
|
85
|
-
<li class="clarification-option{% if option.role == 'recommended' %} is-recommended{% endif %}">
|
|
86
|
-
<p class="clarification-option-answer">{{ option.answer }}{% if option.role == 'recommended' %} <span class="badge">{{ t('macros.forms.recommended') }}</span>{% endif %}</p>
|
|
87
|
-
{% if option.disposition | default(None) %}<p class="clarification-option-disposition"><code>{{ option.disposition }}</code></p>{% endif %}
|
|
88
|
-
<p class="clarification-option-rationale">{{ option.rationale }}</p>
|
|
89
|
-
<dl class="clarification-option-impact">
|
|
90
|
-
<dt>{{ t('macros.forms.scope-impact') }}</dt><dd>{% if option.reach | default(None) %}{{ option.reach }}{% if option.scopeEffects | default([]) %}, {{ option.scopeEffects | join(', ') }}{% endif %}{% else %}{{ option.scopeImpact | join(', ') }}{% endif %}</dd>
|
|
91
|
-
<dt>{{ t('macros.forms.added-work') }}</dt><dd>{{ option.addedWork }}</dd>
|
|
92
|
-
<dt>{{ t('macros.forms.direction-change') }}</dt><dd>{{ option.directionChange }}</dd>
|
|
93
|
-
</dl>
|
|
94
|
-
</li>
|
|
95
|
-
{% endfor %}
|
|
96
|
-
</ol>
|
|
97
|
-
{% endif %}
|
|
98
|
-
<label for="response-{{ row.id }}">{{ t('macros.forms.your-answer-to-id') | replace('{id}', row.id) }}</label>
|
|
99
|
-
{% if row.kind == 'decision' and approval_context and options %}
|
|
100
|
-
<select id="response-{{ row.id }}" data-response-id="{{ row.id }}"{% if is_closed %} disabled{% endif %}>
|
|
101
|
-
<option value="">{{ t('macros.forms.choose-one') }}</option>
|
|
102
|
-
{% for option in options %}<option value="{{ option.answer }}" data-disposition="{{ option.disposition | default('') }}"{% if option.role == 'recommended' %} data-recommended="true"{% endif %}{% if row.userInput | default('') == option.answer %} selected{% endif %}>{{ option.answer }}</option>{% endfor %}
|
|
103
|
-
</select>
|
|
104
|
-
{% else %}
|
|
105
|
-
<textarea id="response-{{ row.id }}" data-response-id="{{ row.id }}" rows="4"{% if is_closed %} disabled{% endif %}>{{ row.userInput | default('') }}</textarea>
|
|
106
|
-
{% endif %}
|
|
107
|
-
</article>
|
|
108
|
-
{% endfor %}
|
|
121
|
+
{% for row in ns.open %}{{ clarification_article(row) }}{% endfor %}
|
|
122
|
+
{% endif %}
|
|
123
|
+
{% if ns.closed %}
|
|
124
|
+
{% if ns.open %}<h3>{{ t('macros.forms.count-answered-questions') | replace('{count}', ns.closed | length) }}</h3>
|
|
125
|
+
{% else %}<h2>{{ t('macros.forms.count-answered-questions') | replace('{count}', ns.closed | length) }}</h2>{% endif %}
|
|
126
|
+
{% for row in ns.closed %}{{ clarification_article(row, compact=true) }}{% endfor %}
|
|
127
|
+
{% endif %}
|
|
109
128
|
</section>
|
|
110
129
|
{% endif %}
|
|
111
130
|
{%- endmacro %}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{% macro narrative(value, field_name) -%}
|
|
2
2
|
<div class="narrative" data-report-field="{{ field_name }}">
|
|
3
3
|
{{ value.text | paragraphs }}
|
|
4
|
-
<p class="evidence-refs">
|
|
4
|
+
<p class="evidence-refs">{{ t('macros.layout.evidence') }} {{ value.evidenceRefs | evidence_refs }}</p>
|
|
5
5
|
</div>
|
|
6
6
|
{%- endmacro %}
|
|
7
7
|
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
{% macro summary_card(title, body, tone='neutral', anchor='') -%}
|
|
28
28
|
<article class="summary-card tone-{{ tone }}"{% if anchor %} id="id-{{ anchor }}"{% endif %}>
|
|
29
|
-
{% if title %}<h3>{{ title }}</h3>{% endif %}
|
|
29
|
+
{% if title %}<h3>{{ title | inline_code }}</h3>{% endif %}
|
|
30
30
|
<p>{{ body | inline_code }}</p>
|
|
31
31
|
</article>
|
|
32
32
|
{%- endmacro %}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<thead><tr><th>{{ t('macros.visualizations.component') }}</th>{% if show_detail %}<th>{{ t('macros.visualizations.what-it-does') }}</th>{% endif %}{% if show_paths %}<th>{{ t('macros.visualizations.paths') }}</th>{% endif %}</tr></thead>
|
|
13
13
|
<tbody>
|
|
14
14
|
{% for node in model.nodes %}
|
|
15
|
-
<tr{% if anchor_nodes %} id="id-{{ node.id }}"{% endif %} data-fallback-id="{{ node.id }}">{{ row_key(pairs=[(
|
|
15
|
+
<tr{% if anchor_nodes %} id="id-{{ node.id }}"{% endif %} data-fallback-id="{{ node.id }}">{{ row_key(pairs=[(t('macros.layout.id'), node.id), (t('macros.layout.name'), node.label), (t('macros.layout.kind'), node.note)]) }}{% if show_detail %}<td>{{ node.detail | inline_code }}</td>{% endif %}{% if show_paths %}<td>{% for path in node.paths %}<code>{{ path }}</code>{% if not loop.last %} {% endif %}{% endfor %}</td>{% endif %}</tr>
|
|
16
16
|
{% endfor %}
|
|
17
17
|
</tbody>
|
|
18
18
|
</table>
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<section data-report-section="affected-and-unaffected">
|
|
14
14
|
<h2>{{ t('tasks.change-impact-analysis.what-the-change-touches-and-where-it-stops') }}</h2>
|
|
15
15
|
{{ render_narrative(narrative.impactExplanation, "changeImpactAnalysis.userNarrative.impactExplanation") }}
|
|
16
|
-
<div data-report-field="changeImpactAnalysis.impactItems"><h3>{{ t('tasks.change-impact-analysis.what-it-touches') }}</h3>{% for row in change.impactItems %}{{ summary_card(row.id ~ " · " ~
|
|
16
|
+
<div data-report-field="changeImpactAnalysis.impactItems"><h3>{{ t('tasks.change-impact-analysis.what-it-touches') }}</h3>{% for row in change.impactItems %}{{ summary_card(row.id ~ " · " ~ row.target, row.impactKind ~ " / " ~ t('macros.layout.impact') ~ " " ~ row.level ~ " / " ~ t('macros.layout.confidence') ~ " " ~ row.confidence, anchor=row.id) }}{% endfor %}</div>
|
|
17
17
|
<div data-report-field="changeImpactAnalysis.unaffectedBoundaries"><h3>{{ t('tasks.change-impact-analysis.where-the-change-stops') }}</h3>{{ render_narrative(narrative.unaffectedExplanation, "changeImpactAnalysis.userNarrative.unaffectedExplanation") }}<ul>{% for row in change.unaffectedBoundaries %}<li>{{ row.summary | inline_code }}</li>{% endfor %}</ul></div>
|
|
18
18
|
</section>
|
|
19
19
|
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
<section data-report-section="planning-readiness" data-report-field="changeImpactAnalysis.planningInputs">
|
|
34
34
|
<h2>{{ t('tasks.change-impact-analysis.plan-readiness') }}</h2>
|
|
35
35
|
{{ render_narrative(narrative.planningReadiness, "changeImpactAnalysis.userNarrative.planningReadiness") }}
|
|
36
|
-
<ul>{% for row in change.planningInputs %}<li>{{ row.constraint | inline_code }}{% if row.unknown %} —
|
|
36
|
+
<ul>{% for row in change.planningInputs %}<li>{{ row.constraint | inline_code }}{% if row.unknown %} — {{ t('tasks.change-impact-analysis.unsettled') }}{% endif %}</li>{% endfor %}</ul>
|
|
37
37
|
</section>
|
|
38
38
|
|
|
39
39
|
<section data-report-section="preserved-behaviors" data-report-field="changeImpactAnalysis.preservedBehaviors">
|
|
@@ -21,19 +21,19 @@
|
|
|
21
21
|
<h2>{{ t('tasks.error-analysis.cause-candidates') }}</h2>
|
|
22
22
|
{{ render_narrative(narrative.causeExplanation, "errorAnalysis.userNarrative.causeExplanation") }}
|
|
23
23
|
{{ figure(causeFigure) }}
|
|
24
|
-
<div class="summary-grid">{% for row in error.causeCandidates %}<article class="summary-card tone-{{ row.confidence }}" id="id-{{ row.id }}"><p class="eyebrow">{{ row.id }} ·
|
|
24
|
+
<div class="summary-grid">{% for row in error.causeCandidates %}<article class="summary-card tone-{{ row.confidence }}" id="id-{{ row.id }}"><p class="eyebrow">{{ row.id | inline_code }} · {{ t('macros.layout.confidence') }} {{ row.confidence }}</p><h3>{{ row.statement | inline_code }}</h3><p class="evidence-refs">{{ t('macros.layout.supporting-evidence') }} {{ row.supportingEvidence | evidence_refs }}</p></article>{% else %}<p>{{ t('tasks.error-analysis.no-cause-candidate-has-been-established-yet') }}</p>{% endfor %}</div>
|
|
25
25
|
</section>
|
|
26
26
|
|
|
27
27
|
<section data-report-section="uncertainty">
|
|
28
28
|
<h2>{{ t('tasks.error-analysis.what-cannot-be-settled-yet') }}</h2>
|
|
29
29
|
{{ render_narrative(narrative.uncertaintyExplanation, "errorAnalysis.userNarrative.uncertaintyExplanation") }}
|
|
30
|
-
{% for row in error.causeCandidates %}<article class="summary-card" id="id-{{ row.id }}-detail"><h3>{{ row.id }}</h3><p data-report-field="errorAnalysis.causeCandidates.confidence"><strong>{{ t('tasks.error-analysis.confidence-now') }}</strong> {{ row.confidence }}</p><p data-report-field="errorAnalysis.causeCandidates.falsifyingEvidenceChecked"><strong>{{ t('tasks.error-analysis.disproof-attempted') }}</strong> {{ row.falsifyingEvidenceChecked | join(', ') | inline_code }}</p><p data-report-field="errorAnalysis.causeCandidates.disproveWith"><strong>{{ t('tasks.error-analysis.how-to-disprove-this') }}</strong> {{ row.disproveWith | inline_code }}</p></article>{% endfor %}
|
|
30
|
+
{% for row in error.causeCandidates %}<article class="summary-card" id="id-{{ row.id }}-detail"><h3>{{ row.id | inline_code }}</h3><p data-report-field="errorAnalysis.causeCandidates.confidence"><strong>{{ t('tasks.error-analysis.confidence-now') }}</strong> {{ row.confidence }}</p><p data-report-field="errorAnalysis.causeCandidates.falsifyingEvidenceChecked"><strong>{{ t('tasks.error-analysis.disproof-attempted') }}</strong> {{ row.falsifyingEvidenceChecked | join(', ') | inline_code }}</p><p data-report-field="errorAnalysis.causeCandidates.disproveWith"><strong>{{ t('tasks.error-analysis.how-to-disprove-this') }}</strong> {{ row.disproveWith | inline_code }}</p></article>{% endfor %}
|
|
31
31
|
</section>
|
|
32
32
|
|
|
33
33
|
<section data-report-section="next-diagnostic">
|
|
34
34
|
<h2>{{ t('tasks.error-analysis.the-one-diagnostic-to-run-next') }}</h2>
|
|
35
35
|
{{ render_narrative(narrative.diagnosticGuidance, "errorAnalysis.userNarrative.diagnosticGuidance") }}
|
|
36
|
-
{{ summary_card(
|
|
36
|
+
{{ summary_card(t('tasks.error-analysis.run'), error.nextDiagnostic.action, "important") }}
|
|
37
37
|
<p><strong>{{ t('tasks.error-analysis.signal-to-check') }}</strong> {{ error.nextDiagnostic.confirmingSignal | inline_code }}</p>
|
|
38
38
|
<p><strong>{{ t('tasks.error-analysis.signal-that-rejects-it') }}</strong> {{ error.nextDiagnostic.rejectingSignal | inline_code }}</p>
|
|
39
39
|
</section>
|
|
@@ -15,25 +15,25 @@
|
|
|
15
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
|
-
<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>
|
|
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 | inline_code }} · {{ 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
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>{{ t('tasks.feature-analysis.domain-rules') }}</h3>{% for row in feature.domainRules %}{{ summary_card(row.id ~ " · " ~
|
|
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, row.outcome, anchor=row.id) }}{% endfor %}</div>
|
|
25
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
29
|
<h2>{{ t('tasks.feature-analysis.external-interactions') }}</h2>
|
|
30
|
-
{% for row in feature.externalInteractions %}{{ summary_card(row.target
|
|
30
|
+
{% for row in feature.externalInteractions %}{{ summary_card(row.target, row.input ~ " → " ~ row.output ~ ". " ~ t('tasks.feature-analysis.on-failure') ~ " " ~ row.failureHandling) }}{% endfor %}
|
|
31
31
|
</section>
|
|
32
32
|
|
|
33
33
|
<section data-report-section="test-gaps" data-report-field="featureAnalysis.testCoverage">
|
|
34
34
|
<h2>{{ t('tasks.feature-analysis.tests-and-gaps') }}</h2>
|
|
35
35
|
{{ render_narrative(narrative.testGapExplanation, "featureAnalysis.userNarrative.testGapExplanation") }}
|
|
36
|
-
{% for row in feature.testCoverage %}{{ summary_card(row.id, "
|
|
36
|
+
{% for row in feature.testCoverage %}{{ summary_card(row.id, t('tasks.feature-analysis.tests') ~ " " ~ (row.testPaths | join(', ')) ~ "; " ~ t('tasks.feature-analysis.gaps') ~ " " ~ ((row.gaps | join(', ')) or t('macros.layout.none')), anchor=row.id) }}{% endfor %}
|
|
37
37
|
</section>
|
|
38
38
|
|
|
39
39
|
<section data-report-section="preconditions" data-report-field="featureAnalysis.preconditions">
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
|
|
18
18
|
<section data-report-section="added-surface" data-report-field="finalVerification.addedSurfaceAudit">
|
|
19
19
|
<h2>{{ t('tasks.final-verification.what-the-change-added') }}</h2>
|
|
20
|
-
<div class="table-scroll"><table><thead><tr><th>
|
|
21
|
-
<tbody>{% for row in final.addedSurfaceAudit %}<tr id="id-{{ row.id }}"><td>{{ row.id }}</td><td>{{ row.surface | inline_code }}</td><td>{{ row.callers | inline_code }}</td><td>{{ row.requirement | inline_code }}</td><td><span class="status status-{{ row.disposition }}">{{ row.disposition }}</span> {{ row.note | inline_code }}</td></tr>{% else %}<tr><td colspan="5">{{ t('tasks.final-verification.the-change-added-no-new-surface') }}</td></tr>{% endfor %}</tbody></table></div>
|
|
20
|
+
<div class="table-scroll"><table><thead><tr><th>{{ t('macros.layout.id') }}</th><th>{{ t('tasks.final-verification.what-the-change-added') }}</th><th>{{ t('tasks.final-verification.callers') }}</th><th>{{ t('tasks.final-verification.traced-to') }}</th><th>{{ t('tasks.final-verification.result-per-requirement') }}</th></tr></thead>
|
|
21
|
+
<tbody>{% for row in final.addedSurfaceAudit %}<tr id="id-{{ row.id }}"><td>{{ row.id | inline_code }}</td><td>{{ row.surface | inline_code }}</td><td>{{ row.callers | inline_code }}</td><td>{{ row.requirement | inline_code }}</td><td><span class="status status-{{ row.disposition }}">{{ row.disposition }}</span> {{ row.note | inline_code }}</td></tr>{% else %}<tr><td colspan="5">{{ t('tasks.final-verification.the-change-added-no-new-surface') }}</td></tr>{% endfor %}</tbody></table></div>
|
|
22
22
|
</section>
|
|
23
23
|
|
|
24
24
|
<section data-report-section="blockers" data-report-field="finalVerification.acceptanceBlockers">
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
<section data-report-section="residual-risk" data-report-field="finalVerification.residualRisk">
|
|
31
31
|
<h2>{{ t('tasks.final-verification.residual-risk') }}</h2>
|
|
32
|
-
<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>
|
|
32
|
+
<div class="summary-grid">{% for row in final.residualRisk %}<article class="summary-card" id="id-{{ row.id }}"><h3>{{ row.id | inline_code }}</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>
|
|
33
33
|
</section>
|
|
34
34
|
|
|
35
35
|
<section data-report-section="manual-results" data-report-field="finalVerification.manualUserTest">
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
{% block human_content %}
|
|
6
6
|
<section data-report-section="selection-status">
|
|
7
|
-
<h2>
|
|
8
|
-
<dl><dt>
|
|
7
|
+
<h2>{{ t('tasks.implementation-option-selection.selection-status') }}</h2>
|
|
8
|
+
<dl><dt>{{ t('tasks.implementation-option-selection.mode') }}</dt><dd>{{ selection.mode }}</dd><dt>{{ t('tasks.implementation-option-selection.routing') }}</dt><dd>{{ selection.routing }}</dd></dl>
|
|
9
9
|
{{ render_narrative(narrative.selectionGuidance, "implementationOptionSelection.userNarrative.selectionGuidance") }}
|
|
10
10
|
{% if selection.mode == "preselected-validation" %}
|
|
11
|
-
<h3>
|
|
12
|
-
<dl><dt>
|
|
11
|
+
<h3>{{ t('tasks.implementation-option-selection.preselected-direction') }}</h3>
|
|
12
|
+
<dl><dt>{{ t('tasks.implementation-option-selection.option-id') }}</dt><dd>{{ selection.preselectedDirection.optionId | inline_code }}</dd><dt>{{ t('tasks.implementation-option-selection.direction') }}</dt><dd>{{ selection.preselectedDirection.direction | inline_code }}</dd><dt>{{ t('tasks.implementation-option-selection.confirmation-evidence') }}</dt><dd>{{ selection.preselectedDirection.confirmationEvidence | inline_code }}</dd><dt>{{ t('tasks.implementation-option-selection.citation') }}</dt><dd>{{ selection.preselectedDirection.citation | inline_code }}</dd></dl>
|
|
13
13
|
{% endif %}
|
|
14
14
|
</section>
|
|
15
15
|
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
<h2>{{ t('tasks.implementation-option-selection.ranked-options') }}</h2>
|
|
28
28
|
{{ render_narrative(narrative.rankingExplanation, "implementationOptionSelection.userNarrative.rankingExplanation") }}
|
|
29
29
|
<div class="summary-grid">{% for row in selection.rankedOptions %}<article class="summary-card" id="id-{{ row.id }}">
|
|
30
|
-
<p class="eyebrow">#{{ loop.index }} · {{ row.id }}</p>
|
|
30
|
+
<p class="eyebrow">#{{ loop.index }} · {{ row.id | inline_code }}</p>
|
|
31
31
|
<h3>{{ row.name | inline_code }}</h3>
|
|
32
32
|
<p>{{ row.goal | inline_code }}</p>
|
|
33
|
-
<div data-report-field="implementationOptionSelection.rankedOptions.coverageSummary"><p><strong>
|
|
34
|
-
<p><strong>
|
|
33
|
+
<div data-report-field="implementationOptionSelection.rankedOptions.coverageSummary"><p><strong>{{ t('macros.layout.coverage-percent') }}</strong> <span data-report-metric="coveragePercent">{{ row.coverageSummary.coveragePercent }}</span></p>
|
|
34
|
+
<p><strong>{{ t('macros.layout.scope-precision-percent') }}</strong> <span data-report-metric="scopePrecisionPercent">{{ row.coverageSummary.scopePrecisionPercent }}</span></p></div>
|
|
35
35
|
<p><strong>{{ t('tasks.implementation-option-selection.weighted-score') }}</strong> {{ row.weightedScore }}</p>
|
|
36
|
-
<table data-report-field="implementationOptionSelection.rankedOptions.requirementCoverage"><thead><tr><th>{{ t('tasks.implementation-option-selection.requirement') }}</th><th>{{ t('tasks.implementation-option-selection.satisfaction') }}</th><th>{{ t('tasks.implementation-option-selection.verification') }}</th></tr></thead><tbody>{% for coverage in row.requirementCoverage %}<tr>{{ row_key(pairs=[(
|
|
36
|
+
<table data-report-field="implementationOptionSelection.rankedOptions.requirementCoverage"><thead><tr><th>{{ t('tasks.implementation-option-selection.requirement') }}</th><th>{{ t('tasks.implementation-option-selection.satisfaction') }}</th><th>{{ t('tasks.implementation-option-selection.verification') }}</th></tr></thead><tbody>{% for coverage in row.requirementCoverage %}<tr>{{ row_key(pairs=[(t('macros.layout.id'), coverage.requirementId), (t('macros.layout.status'), coverage.status)]) }}<td>{{ coverage.satisfaction | inline_code }}</td><td>{{ coverage.expectedVerification | inline_code }}</td></tr>{% endfor %}</tbody></table>
|
|
37
37
|
</article>{% else %}<p>{{ t('tasks.implementation-option-selection.no-valid-options') }}</p>{% endfor %}</div>
|
|
38
38
|
</section>
|
|
39
39
|
|
|
@@ -44,6 +44,6 @@
|
|
|
44
44
|
|
|
45
45
|
<section data-report-section="candidate-audit" data-report-field="implementationOptionSelection.candidateAudit">
|
|
46
46
|
<h2>{{ t('tasks.implementation-option-selection.candidate-audit') }}</h2>
|
|
47
|
-
<table><thead><tr><th>{{ t('tasks.implementation-option-selection.candidate') }}</th><th>{{ t('tasks.implementation-option-selection.disposition') }}</th><th>{{ t('tasks.implementation-option-selection.reason') }}</th><th>
|
|
47
|
+
<table><thead><tr><th>{{ t('tasks.implementation-option-selection.candidate') }}</th><th>{{ t('tasks.implementation-option-selection.disposition') }}</th><th>{{ t('tasks.implementation-option-selection.reason') }}</th><th>{{ t('macros.layout.coverage-percent') }}</th><th>{{ t('macros.layout.scope-precision-percent') }}</th></tr></thead><tbody>{% for row in selection.candidateAudit %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[(t('macros.layout.id'), row.id), (t('macros.layout.proposed-by'), row.proposedBy)]) }}<td>{{ row.disposition }}</td><td>{{ row.reason | inline_code }}</td><td>{{ row.coverageSummary.coveragePercent }}</td><td>{{ row.coverageSummary.scopePrecisionPercent }}</td></tr>{% else %}<tr><td colspan="6">{{ t('tasks.implementation-option-selection.no-audit-entries') }}</td></tr>{% endfor %}</tbody></table>
|
|
48
48
|
</section>
|
|
49
49
|
{% endblock %}
|
|
@@ -12,26 +12,26 @@
|
|
|
12
12
|
|
|
13
13
|
{% if planning.get("planningContract") == "selected-direction" %}
|
|
14
14
|
<section data-report-section="selected-direction" data-report-field="implementationPlanning.selectedDirectionRef">
|
|
15
|
-
<h2>
|
|
16
|
-
<article class="summary-card tone-important"><h3>{{ planning.selectedDirectionRef.optionId | inline_code }}</h3><p><strong>
|
|
15
|
+
<h2>{{ t('tasks.implementation-planning.selected-direction') }}</h2>
|
|
16
|
+
<article class="summary-card tone-important"><h3>{{ planning.selectedDirectionRef.optionId | inline_code }}</h3><p><strong>{{ t('tasks.implementation-planning.source-report') }}</strong> {{ planning.selectedDirectionRef.sourceReport | inline_code }}</p><p><strong>{{ t('tasks.implementation-planning.snapshot') }}</strong> {{ planning.selectedDirectionRef.snapshotPath | inline_code }}</p></article>
|
|
17
17
|
</section>
|
|
18
18
|
{% if planning.outcome == "plan-ready" %}
|
|
19
19
|
<section data-report-section="direction-realization" data-report-field="implementationPlanning.directionRealization">
|
|
20
|
-
<h2>
|
|
21
|
-
<article class="summary-card"><h3>{{ planning.directionRealization.goal | inline_code }}</h3><p><strong>
|
|
20
|
+
<h2>{{ t('tasks.implementation-planning.direction-realization') }}</h2>
|
|
21
|
+
<article class="summary-card"><h3>{{ planning.directionRealization.goal | inline_code }}</h3><p><strong>{{ t('tasks.implementation-planning.core-mechanism') }}</strong> {{ planning.directionRealization.coreMechanism | inline_code }}</p><p><strong>{{ t('tasks.implementation-planning.interfaces') }}</strong> {{ planning.directionRealization.interfaces | inline_code }}</p><p><strong>{{ t('tasks.implementation-planning.blast-radius') }}</strong> {{ planning.directionRealization.blastRadius | inline_code }}</p><ul>{% for file in planning.directionRealization.fileStructure %}<li id="id-{{ file.id }}">{{ file.action }} <code>{{ file.path }}</code> — {{ file.summary | inline_code }}</li>{% endfor %}</ul></article>
|
|
22
22
|
</section>
|
|
23
23
|
<section data-report-section="plan-coverage" data-report-field="implementationPlanning.coverageSummary">
|
|
24
|
-
<h2>
|
|
25
|
-
<p><strong>
|
|
26
|
-
<p><strong>
|
|
24
|
+
<h2>{{ t('tasks.implementation-planning.plan-coverage') }}</h2>
|
|
25
|
+
<p><strong>{{ t('tasks.implementation-planning.coverage-percent') }}</strong> <span data-report-metric="coveragePercent">{{ planning.coverageSummary.coveragePercent }}</span></p>
|
|
26
|
+
<p><strong>{{ t('tasks.implementation-planning.scope-precision-percent') }}</strong> <span data-report-metric="scopePrecisionPercent">{{ planning.coverageSummary.scopePrecisionPercent }}</span></p>
|
|
27
27
|
</section>
|
|
28
28
|
{% else %}
|
|
29
29
|
<section data-report-section="direction-invalidation" data-report-field="implementationPlanning.directionInvalidation">
|
|
30
|
-
<h2>
|
|
30
|
+
<h2>{{ t('tasks.implementation-planning.direction-invalidated') }}</h2>
|
|
31
31
|
<ul>{% for reason in planning.directionInvalidation.reasons %}<li>{{ reason | inline_code }}</li>{% endfor %}</ul>
|
|
32
|
-
<p><strong>
|
|
32
|
+
<p><strong>{{ t('tasks.implementation-planning.code-evidence') }}</strong></p>
|
|
33
33
|
<ul>{% for evidence in planning.directionInvalidation.codeEvidence %}<li>{{ evidence | inline_code }}</li>{% endfor %}</ul>
|
|
34
|
-
<p data-report-field="implementationPlanning.routing"><strong>
|
|
34
|
+
<p data-report-field="implementationPlanning.routing"><strong>{{ t('tasks.implementation-planning.re-entry-route') }}</strong> {{ planning.routing | inline_code }}</p>
|
|
35
35
|
</section>
|
|
36
36
|
{% endif %}
|
|
37
37
|
{% else %}
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
{{ render_narrative(narrative.stageStrategy, "implementationPlanning.userNarrative.stageStrategy") }}
|
|
57
57
|
{% endif %}
|
|
58
58
|
{{ figure(stageFigure) }}
|
|
59
|
-
<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
|
|
59
|
+
<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></article>{% endfor %}</div>
|
|
60
60
|
</section>
|
|
61
61
|
|
|
62
62
|
{% if planning.get("designPreparation") %}
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
{% if planning.designPreparation.mode == "no-design-inputs" %}
|
|
66
66
|
<p>{{ planning.designPreparation.reason | inline_code }}</p>
|
|
67
67
|
{% else %}
|
|
68
|
-
<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=[(
|
|
68
|
+
<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=[(t('macros.layout.id'), row.id), (t('macros.layout.subject'), row.title), (t('macros.layout.kind'), row.kind)], status_name=t('macros.layout.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>
|
|
69
69
|
{% endif %}
|
|
70
70
|
</section>
|
|
71
71
|
{% endif %}
|
|
@@ -73,14 +73,14 @@
|
|
|
73
73
|
<section data-report-section="variation-points" data-report-field="implementationPlanning.variationPointAnalysis">
|
|
74
74
|
<h2>{{ t('tasks.implementation-planning.where-implementations-diverge') }}</h2>
|
|
75
75
|
{% if planning.variationPointAnalysis.hasMultipleImplementations %}
|
|
76
|
-
<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>{{
|
|
76
|
+
<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 %}{% set decision = row.extractionDecision %}<tr><td>{{ row.behavior | inline_code }}</td><td>{{ row.implementations | default([]) | join(" · ") | inline_code }}</td><td>{% if decision is mapping %}{{ t('tasks.implementation-planning.extract') if decision.extract else t('tasks.implementation-planning.keep') }} · {{ decision.interfaceKind | enum_label('interfaceKind') }} · {{ decision.coveredBy | inline_code }} — {{ decision.rationale | inline_code }}{% else %}{{ decision | inline_code }}{% endif %}</td><td>{{ row.evidence | inline_code }}</td></tr>{% endfor %}</tbody></table>
|
|
77
77
|
{% else %}<p>{{ planning.variationPointAnalysis.noVariationRationale | inline_code }}</p>{% endif %}
|
|
78
78
|
</section>
|
|
79
79
|
|
|
80
80
|
{% if planning.get("stepwiseExecution") %}
|
|
81
81
|
<section data-report-section="stepwise-execution" data-report-field="implementationPlanning.stepwiseExecution">
|
|
82
82
|
<h2>{{ t('tasks.implementation-planning.step-by-step-execution') }}</h2>
|
|
83
|
-
<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>{
|
|
83
|
+
<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><code>{{ row.files if row.files is string else row.files | join(" ") }}</code></td><td><code>{{ row.commandOrTest }}</code></td><td>{{ row.expectedOutcome | inline_code }}</td></tr>{% endfor %}</tbody></table>
|
|
84
84
|
</section>
|
|
85
85
|
{% endif %}
|
|
86
86
|
|
|
@@ -94,9 +94,9 @@
|
|
|
94
94
|
<section data-report-section="requirement-coverage" data-report-field="implementationPlanning.requirementCoverage">
|
|
95
95
|
<h2>{{ t('tasks.implementation-planning.how-each-requirement-gets-met') }}</h2>
|
|
96
96
|
{% if planning.get("planningContract") == "selected-direction" %}
|
|
97
|
-
<table><thead><tr><th>
|
|
97
|
+
<table><thead><tr><th>{{ t('tasks.implementation-planning.original-requirement') }}</th><th>{{ t('tasks.implementation-planning.stages') }}</th><th>{{ t('tasks.implementation-planning.status') }}</th></tr></thead><tbody>{% for row in planning.requirementCoverage %}<tr><td>{{ row.originalRequirementId | inline_code }}</td><td>{{ row.stageRefs | join(", ") | inline_code }}</td><td>{{ row.status | inline_code }}</td></tr>{% endfor %}</tbody></table>
|
|
98
98
|
{% else %}
|
|
99
|
-
<table><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=[(
|
|
99
|
+
<table><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=[(t('macros.layout.id'), row.id), (t('macros.layout.source'), row.source)], status_name=t('macros.layout.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>
|
|
100
100
|
{% endif %}
|
|
101
101
|
</section>
|
|
102
102
|
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
`no-dependent-statement` row legitimately carries neither. Referencing them
|
|
109
109
|
unconditionally under StrictUndefined meant a schema-valid report killed the
|
|
110
110
|
renderer. #}
|
|
111
|
-
<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=[(
|
|
111
|
+
<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>{% set answered_ids = clarificationItems | map(attribute='id') | list %}{% for row in planning.supersessionLedger %}<tr{% if row.clarificationId not in answered_ids %} id="id-{{ row.clarificationId }}"{% endif %}>{{ row_key(pairs=[(t('macros.layout.answer'), row.clarificationId), (t('macros.layout.disposition'), row.disposition)]) }}<td>{{ row.get("supersededStatement") | inline_code }}</td><td>{{ row.get("replacedWith") | inline_code }}</td></tr>{% else %}<tr><td colspan="4">{{ t('tasks.implementation-planning.no-answer-overturned-anything') }}</td></tr>{% endfor %}</tbody></table>
|
|
112
112
|
</section>
|
|
113
113
|
{% endif %}
|
|
114
114
|
|
|
@@ -121,6 +121,7 @@
|
|
|
121
121
|
{% endif %}
|
|
122
122
|
</section>{% endif %}
|
|
123
123
|
|
|
124
|
+
{% if planning.get("decisionDrafts") or planning.get("skippedAdrCandidates") %}
|
|
124
125
|
<section data-report-section="decision-drafts" data-report-field="implementationPlanning.decisionDrafts">
|
|
125
126
|
<h2>{{ t('tasks.implementation-planning.decision-record-draft') }}</h2>
|
|
126
127
|
{% for row in planning.get("decisionDrafts", []) %}
|
|
@@ -130,6 +131,7 @@
|
|
|
130
131
|
<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 %}
|
|
131
132
|
</section>
|
|
132
133
|
{% endif %}
|
|
134
|
+
{% endif %}
|
|
133
135
|
|
|
134
136
|
{% if agentActivities %}
|
|
135
137
|
<section data-report-section="agent-activity">
|
|
@@ -137,7 +139,7 @@
|
|
|
137
139
|
<div class="activity-list">
|
|
138
140
|
{% for row in agentActivities %}
|
|
139
141
|
<article class="activity-card" id="id-{{ row.activityId }}">
|
|
140
|
-
<p class="eyebrow">{{ row.activityId }} · {{ row.agent }}</p>
|
|
142
|
+
<p class="eyebrow">{{ row.activityId | inline_code }} · {{ row.agent }}</p>
|
|
141
143
|
<h3>{{ row.summary | inline_code }}</h3>
|
|
142
144
|
<p>{{ t('tasks.implementation-planning.result') }}: {{ row.outcome | inline_code }}</p>
|
|
143
145
|
<details>
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
|
|
18
18
|
<section data-report-section="requirement-coverage">
|
|
19
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=[(
|
|
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=[(t('macros.layout.id'), row.id)], status_name=t('macros.layout.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
24
|
<h2>{{ t('tasks.implementation.verification-result') }}</h2>
|
|
25
25
|
{{ render_narrative(narrative.validationExplanation, "implementation.userNarrative.validationExplanation") }}
|
|
26
|
-
<div class="summary-grid">{% for row in implementation.validationEvidence %}{{ summary_card(row.phase ~ " · exit
|
|
26
|
+
<div class="summary-grid">{% for row in implementation.validationEvidence %}{{ summary_card(row.phase ~ " · " ~ t('tasks.implementation.exit-code') ~ " " ~ row.exitCode, row.outputTail, "important" if row.exitCode else "neutral") }}{% endfor %}</div>
|
|
27
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
|
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<section data-report-section="shipped-commits" data-report-field="implementation.commitList">
|
|
37
37
|
<h2>{{ t('tasks.implementation.commits-delivered') }}</h2>
|
|
38
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=[(
|
|
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=[(t('macros.layout.sha'), row.shortSha), (t('macros.layout.order'), row.number), (t('macros.layout.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
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
|
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
<section data-report-section="opportunities">
|
|
7
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>{{ 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=[(
|
|
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=[(t('macros.layout.lens'), row.lens), (t('macros.layout.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
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 }} ·
|
|
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 | inline_code }} · {{ t('macros.layout.impact') }} {{ row.severity }} · {{ t('macros.layout.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">{{ t('macros.layout.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">
|
|
@@ -24,6 +24,6 @@
|
|
|
24
24
|
<h2>{{ t('tasks.improvement-discovery.how-to-choose') }}</h2>
|
|
25
25
|
{{ render_narrative(narrative.selectionGuidance, "improvementDiscovery.userNarrative.selectionGuidance") }}
|
|
26
26
|
<p><strong>{{ t('tasks.improvement-discovery.selection-cap') }}</strong> at most {{ improvement.selectionLimit }}</p>
|
|
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>
|
|
27
|
+
<ul>{% for row in improvement.candidates %}<li><label><input type="checkbox" name="improvement-candidate" value="{{ row.id }}"> {{ row.id | inline_code }} · {{ row.title | inline_code }}</label></li>{% endfor %}</ul>
|
|
28
28
|
</section>
|
|
29
29
|
{% endblock %}
|