Files
ParkingRobot/docs/superpowers/plans/2026-08-03-daily-summary-job-domain-visualization-upgrade.md
T

916 lines
41 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Daily Summary Job Domain Visualization Upgrade Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use `subagent-driven-development` (recommended) or `executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Upgrade `daily-summary-job` so it understands the current task, renders the function or algorithm's real domain effect, and connects visible objects to the current problem, cause, consequence, correction, expected result, and task-matched verification evidence.
**Architecture:** Extend the normalized report facts with optional algorithm views and task-specific validation facts. Keep one diagnostic interaction shell, but render its central canvas through a declarative adapter registry selected from the current task's semantics. Split maintainable CSS and JavaScript assets during skill development, then inline them into the final self-contained HTML during rendering.
**Tech Stack:** Python 3.12 standard library, `unittest`, HTML5, CSS, vanilla JavaScript, SVG/DOM, Node syntax checks.
## Global Constraints
- Implement the approved design in `docs/superpowers/specs/2026-08-03-daily-summary-job-domain-visualization-upgrade-design.md`.
- Modify the personal skill at `C:\Users\admin\.codex\skills\daily-summary-job`; request filesystem approval when the execution environment requires it.
- Do not hard-code trajectory planning as the meaning of algorithm visualization. Select the view from the current task's purpose, observable business objects, inputs, outputs, and correctness constraints.
- A generic flow diagram may assist navigation, but it must not replace a domain effect view when spatial, numeric, temporal, state, search, or structured-data evidence exists.
- Distinguish actual observation, static reconstruction, conceptual preview, verified result, and conflicting evidence in both data and presentation.
- Build validation scenarios from the current task and its correctness constraints. Do not substitute an unrelated fixed test matrix.
- Preserve reports that omit the new optional fields.
- Final HTML must contain no external resource or network dependency.
- Do not modify business code, run expensive tests by default, stage changes, or create Git commits.
- Preserve the current UTF-8, date/module classification, checkpoint limits, stable issue IDs, and Markdown/HTML pairing behavior.
## User-Approved Scope Adjustment
This implementation ships only the generic declarative `composite-scene` renderer and the unified diagnosis shell. Do not implement dedicated `spatial-scene`, `cartesian-series`, `graph-network`, `state-machine`, or `data-flow` renderers in this round. Keep the adapter registry as an extension point, so future task-specific work can add those renderers without changing the report contract.
---
## File Structure
**Modify**
- `C:\Users\admin\.codex\skills\daily-summary-job\SKILL.md` — task understanding, visualization-brief generation, domain-view selection, and task-matched validation workflow.
- `C:\Users\admin\.codex\skills\daily-summary-job\references\report-schema.md` — optional algorithm-view, issue-target, solution-preview, verified-result, and task-validation contracts.
- `C:\Users\admin\.codex\skills\daily-summary-job\scripts\prepare_report.py` — validate new facts, render the Markdown algorithm section, bundle assets, and validate rendered links.
- `C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py` — schema, backward compatibility, Markdown, asset bundling, adapter, interaction, and CLI regression tests.
- `C:\Users\admin\.codex\skills\daily-summary-job\assets\interactive-report-template.html` — diagnostic-shell markup and asset placeholders.
- `C:\Users\admin\.codex\skills\daily-summary-job\agents\openai.yaml` — UI description and default prompt for task-matched domain visualization.
**Create**
- `C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-styles.css` — domain canvas, view modes, diagnostic drawer, evidence states, responsiveness, and reduced-motion styles.
- `C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-adapters.js` — declarative scene-object renderer registry and built-in layout strategies.
- `C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-runtime.js` — report state, selectors, view switching, target highlighting, diagnosis rendering, and keyboard interaction.
The three development assets are embedded into every rendered report. They must never remain as runtime `<link>` or `<script src>` dependencies.
---
### Task 1: Extend the normalized fact contract without breaking old reports
**Files:**
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py:152-365`
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\prepare_report.py:32-340`
**Interfaces:**
- Consumes: existing `validate_report_data(data: dict[str, Any]) -> None`.
- Produces: optional `algorithm_views: list[dict]`, optional `task_validation: dict`, optional issue visualization fields, and `visual_target_index(data) -> dict[str, set[str]]`.
- [ ] **Step 1: Add a complete task-matched visualization fixture**
Add this helper to `ReportRenderingTests` and use it only in new visualization tests so the existing `sample_data()` remains a legacy-format fixture:
```python
def visualization_data(self):
data = self.sample_data()
data["algorithm_views"] = [
{
"id": "local-g2-smoother",
"name": "Local G2 路径平滑",
"purpose": "把粗路径转换为满足连续性、曲率和安全约束的可执行路径。",
"domain": "geometry-smoothing",
"adapter": "spatial-scene",
"evidence_state": "actual",
"inputs": [
{"id": "coarse-path", "label": "粗路径", "detail": "离散位姿序列", "source_ref": "tests/input.json"}
],
"outputs": [
{"id": "smooth-path", "label": "平滑路径", "detail": "连续候选轨迹", "source_ref": "tests/output.json"}
],
"constraints": [
{"id": "curvature-limit", "label": "曲率上限", "detail": "abs(kappa) <= 0.2", "status": "失败", "source_ref": "tests/output.json"}
],
"stages": [
{
"id": "candidate-evaluation",
"label": "候选评价",
"detail": "比较连续性、曲率和碰撞约束。",
"function_refs": ["PathSmoothing/CandidateEvaluator.cs"],
"target_ids": ["current-path", "curvature-peak"],
}
],
"scene": {
"coordinate_system": "cartesian",
"objects": [
{
"id": "current-path",
"kind": "polyline",
"label": "当前路径",
"evidence_state": "actual",
"source_ref": "tests/output.json",
"data": {"points": [[0, 0], [1, 0.4], [2, 1.1]]},
},
{
"id": "curvature-peak",
"kind": "annotation",
"label": "曲率峰值",
"evidence_state": "actual",
"source_ref": "tests/output.json",
"data": {"x": 1, "y": 0.4, "value": 0.31},
},
{
"id": "preview-path",
"kind": "polyline",
"label": "候选修正路径",
"evidence_state": "conceptual",
"source_ref": "docs/solution.md",
"data": {"points": [[0, 0], [1, 0.3], [2, 1.1]]},
},
],
"layers": [
{"id": "baseline", "label": "正常机制", "mode": "baseline", "object_ids": ["current-path"]},
{"id": "current", "label": "当前问题", "mode": "current", "object_ids": ["current-path", "curvature-peak"]},
{"id": "proposed", "label": "修正预演", "mode": "proposed", "object_ids": ["preview-path"]},
],
},
"source_refs": ["tests/input.json", "tests/output.json"],
}
]
data["issues"][0].update(
{
"algorithm_view_id": "local-g2-smoother",
"target_ids": ["curvature-peak"],
"effect_target_ids": ["current-path"],
"solution_preview": {
"summary": "重新约束连接段导数。",
"expected_result": "曲率峰值回到上限内。",
"evidence_state": "conceptual",
"target_ids": ["preview-path"],
},
}
)
data["task_validation"] = {
"task": "验证 Local G2 平滑候选是否满足当前路径约束。",
"correctness_criteria": [
{"id": "criterion-curvature", "statement": "全路径曲率不超过 0.2。", "source_ref": "tests/output.json"}
],
"checks": [
{
"id": "check-curvature",
"name": "曲率扫描",
"status": "失败",
"criterion_ids": ["criterion-curvature"],
"command": "verify_path_smoothing.ps1",
"result": "max_abs_curvature=0.31",
"evidence_ref": "tests/output.json",
}
],
"missing_evidence": [
{
"criterion_id": "criterion-curvature",
"needed": "修正后的相同输入扫描结果",
"suggested_check": "对同一输入重新运行曲率扫描。",
}
],
}
return data
```
- [ ] **Step 2: Write failing contract and compatibility tests**
Add tests with these exact assertions:
```python
def test_accepts_legacy_report_without_algorithm_views(self):
self.require_target().validate_report_data(self.sample_data())
def test_accepts_linked_algorithm_view_and_task_validation(self):
target = self.require_target()
data = self.visualization_data()
target.validate_report_data(data)
self.assertEqual(
{"current-path", "curvature-peak", "preview-path", "candidate-evaluation"},
target.visual_target_index(data)["local-g2-smoother"],
)
def test_rejects_unknown_visual_target(self):
data = self.visualization_data()
data["issues"][0]["target_ids"] = ["missing-target"]
with self.assertRaisesRegex(ValueError, "unknown visual target"):
self.require_target().validate_report_data(data)
def test_verified_result_requires_verified_state_and_validation_reference(self):
data = self.visualization_data()
data["issues"][0]["verified_result"] = {
"summary": "看起来已经改善。",
"evidence_state": "conceptual",
"target_ids": ["preview-path"],
"validation_refs": [],
}
with self.assertRaisesRegex(ValueError, "verified_result"):
self.require_target().validate_report_data(data)
def test_task_validation_rejects_unknown_criterion(self):
data = self.visualization_data()
data["task_validation"]["checks"][0]["criterion_ids"] = ["criterion-missing"]
with self.assertRaisesRegex(ValueError, "unknown correctness criterion"):
self.require_target().validate_report_data(data)
```
- [ ] **Step 3: Run the focused tests and confirm RED**
Run:
```powershell
python -X utf8 C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py ReportRenderingTests
```
Expected: new tests fail because `visual_target_index` and visualization validation do not exist; existing legacy tests remain green.
- [ ] **Step 4: Add validation constants and helpers**
Add near the existing constants:
```python
VISUAL_EVIDENCE_STATES = {"actual", "static", "conceptual", "verified", "conflict"}
VIEW_MODES = {"baseline", "current", "proposed", "verified"}
VISUAL_ID = re.compile(r"[a-z0-9][a-z0-9-]{1,63}")
```
Add helpers before `validate_report_data`:
```python
def _require_visual_id(value: Any, field: str) -> str:
text = _require_text(value, field)
if not VISUAL_ID.fullmatch(text):
raise ValueError(f"invalid {field}: {text}")
return text
def _require_text_list(value: Any, field: str) -> list[str]:
return [_require_text(item, f"{field} item") for item in _require_list(value, field)]
def _validate_named_fact(item: Any, field: str, required: tuple[str, ...]) -> None:
if not isinstance(item, dict):
raise ValueError(f"{field} item must be an object")
for key in required:
_require_text(item.get(key), f"{field}.{key}")
def visual_target_index(data: dict[str, Any]) -> dict[str, set[str]]:
result: dict[str, set[str]] = {}
for view in data.get("algorithm_views", []):
targets = {stage["id"] for stage in view["stages"]}
targets.update(obj["id"] for obj in view["scene"]["objects"])
result[view["id"]] = targets
return result
```
- [ ] **Step 5: Validate algorithm views, issue links, and task criteria**
Implement `_validate_algorithm_views(data)` and `_validate_task_validation(data)` and call them from `validate_report_data` before issue-link validation. Require the exact fields used by `visualization_data()`, unique view/stage/object/layer IDs, valid evidence states, valid layer modes, stage target references, and layer object references. Require every scene object's `data` to be an object. Require `actual` and `verified` scene objects to carry a non-empty `source_ref`; `static` and `conceptual` objects may reference source or design evidence but must retain their explicit state. Permit any safe adapter slug so future tasks are not restricted to a fixed domain list.
For each issue, validate optional fields only when present:
```python
view_id = issue.get("algorithm_view_id")
if view_id is not None:
view_id = _require_visual_id(view_id, "issue.algorithm_view_id")
if view_id not in targets_by_view:
raise ValueError(f"unknown algorithm view: {view_id}")
for field in ("target_ids", "effect_target_ids"):
for target_id in _require_text_list(issue.get(field, []), f"issue.{field}"):
if target_id not in targets_by_view[view_id]:
raise ValueError(f"unknown visual target: {target_id}")
```
Require `solution_preview.evidence_state` to be `conceptual` or `static`. Require `verified_result.evidence_state == "verified"` and at least one non-empty `validation_refs` item.
- [ ] **Step 6: Run focused and full tests and confirm GREEN**
Run:
```powershell
python -X utf8 C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py ReportRenderingTests
python -X utf8 C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py
```
Expected: focused contract tests pass; the full suite retains all existing passes plus the new tests.
- [ ] **Step 7: Review the scoped diff without staging or committing**
Run:
```powershell
git diff --no-index -- NUL C:\Users\admin\.codex\skills\daily-summary-job\scripts\prepare_report.py
```
Expected: only the intended contract helpers and validation paths are present. Do not run `git add` or `git commit`.
---
### Task 2: Render algorithm purpose and task-matched validation in Markdown
**Files:**
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py:249-285`
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\prepare_report.py:342-452`
**Interfaces:**
- Consumes: validated `algorithm_views` and `task_validation` from Task 1.
- Produces: `_render_algorithm_markdown(data: dict[str, Any]) -> list[str]` and `_render_task_validation_markdown(data: dict[str, Any]) -> list[str]`.
- [ ] **Step 1: Write failing Markdown assertions**
```python
def test_renders_algorithm_function_domain_effect_and_task_validation(self):
markdown = self.require_target().render_markdown(self.visualization_data())
for expected in (
"## 2. 当前函数与算法功能",
"Local G2 路径平滑",
"把粗路径转换为满足连续性、曲率和安全约束的可执行路径",
"候选评价",
"PathSmoothing/CandidateEvaluator.cs",
"## 8. 当前任务匹配的验证",
"全路径曲率不超过 0.2",
"max_abs_curvature=0.31",
"修正后的相同输入扫描结果",
):
self.assertIn(expected, markdown)
def test_legacy_markdown_keeps_original_section_numbers(self):
markdown = self.require_target().render_markdown(self.sample_data())
self.assertIn("## 2. 今日完成的工作", markdown)
self.assertIn("## 7. 证据索引", markdown)
self.assertNotIn("当前函数与算法功能", markdown)
```
- [ ] **Step 2: Run the two tests and confirm RED**
Run:
```powershell
python -X utf8 C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py ReportRenderingTests.test_renders_algorithm_function_domain_effect_and_task_validation ReportRenderingTests.test_legacy_markdown_keeps_original_section_numbers
```
Expected: the visualization-aware test fails; the legacy numbering test passes.
- [ ] **Step 3: Add deterministic Markdown helpers**
Implement `_render_algorithm_markdown` so each view shows purpose, domain, evidence state, inputs, outputs, constraints, stages, function references, and source references. Implement `_render_task_validation_markdown` so criteria, executed checks, and missing evidence are separate lists. Do not infer pass/fail or substitute generic tests.
Use this section order only when `algorithm_views` is non-empty:
```text
1. 今日结论摘要
2. 当前函数与算法功能
3. 今日完成的工作
4. 今日发现的问题
5. 问题如何被发现及证据
6. 已采取的改善和验证结果
7. 尚未解决的风险与下一步
8. 当前任务匹配的验证
9. 证据索引
```
Keep the current seven-section output byte-compatible in structure when `algorithm_views` is absent.
- [ ] **Step 4: Run focused and full tests and confirm GREEN**
Run the commands from Step 2, then:
```powershell
python -X utf8 C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py
```
Expected: all Markdown and legacy tests pass.
- [ ] **Step 5: Inspect a rendered Markdown sample**
Run:
```powershell
python -X utf8 -c "import importlib.util; from pathlib import Path; p=Path(r'C:\Users\admin\.codex\skills\daily-summary-job\scripts\prepare_report.py'); s=importlib.util.spec_from_file_location('daily',p); m=importlib.util.module_from_spec(s); s.loader.exec_module(m); print(m.render_markdown(__import__('json').loads(Path('sample-visual-report.json').read_text(encoding='utf-8'))))"
```
Before running, create `sample-visual-report.json` in a temporary directory from `visualization_data()` through the test helper or CLI fixture, then remove only that temporary file. Expected: algorithm function, task-specific criteria, run checks, and missing evidence are visibly separated.
---
### Task 3: Split development assets and inline them into the final HTML
**Files:**
- Create: `C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-styles.css`
- Create: `C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-adapters.js`
- Create: `C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-runtime.js`
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\assets\interactive-report-template.html`
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\prepare_report.py:453-470,624-660`
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py:286-342`
**Interfaces:**
- Produces: `load_visual_assets(asset_dir: Path | None = None) -> dict[str, str]`.
- Changes: `render_html(data, template, visual_assets=None) -> str` while preserving existing two-argument callers.
- [ ] **Step 1: Write failing asset-bundling tests**
```python
def test_inlines_visual_assets_without_runtime_dependencies(self):
target = self.require_html_target()
html = target.render_html(
self.visualization_data(), TEMPLATE_PATH.read_text(encoding="utf-8")
)
self.assertNotIn("__VISUAL_STYLES__", html)
self.assertNotIn("__VISUAL_ADAPTERS__", html)
self.assertNotIn("__VISUAL_RUNTIME__", html)
self.assertIn("DailySummaryVisuals", html)
self.assertNotRegex(html, r"<link\b|<script[^>]+src=|https?://")
def test_rejects_missing_or_duplicate_asset_placeholder(self):
target = self.require_html_target()
template = TEMPLATE_PATH.read_text(encoding="utf-8").replace("__VISUAL_RUNTIME__", "")
with self.assertRaisesRegex(ValueError, "visual asset placeholder"):
target.render_html(self.visualization_data(), template)
```
- [ ] **Step 2: Run the focused tests and confirm RED**
Run:
```powershell
python -X utf8 C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py HtmlRenderingTests.test_inlines_visual_assets_without_runtime_dependencies HtmlRenderingTests.test_rejects_missing_or_duplicate_asset_placeholder
```
Expected: failures because the template and loader do not contain the new placeholders.
- [ ] **Step 3: Move styles and scripts into focused development files**
Move the current `<style>` content to `visualization-styles.css` and the current inline behavior to `visualization-runtime.js`. Initialize `visualization-adapters.js` with this stable public namespace:
```javascript
'use strict';
globalThis.DailySummaryVisuals = (() => {
const registry = new Map();
function register(name, renderer) {
if (!/^[a-z0-9][a-z0-9-]+$/.test(name) || typeof renderer !== 'function') {
throw new TypeError('invalid visualization adapter');
}
registry.set(name, renderer);
}
function select(name) {
return registry.get(name) || registry.get('composite-scene');
}
function render(view, root, context) {
const renderer = select(view.adapter);
if (!renderer) throw new Error('composite-scene adapter is not registered');
return renderer(view, root, context);
}
return { register, select, render };
})();
```
Replace template bodies with exact single placeholders:
```html
<style>__VISUAL_STYLES__</style>
...
<script id="report-data" type="application/json">__REPORT_DATA__</script>
<script>__VISUAL_ADAPTERS__</script>
<script>__VISUAL_RUNTIME__</script>
```
- [ ] **Step 4: Implement the asset loader and renderer replacement**
```python
VISUAL_ASSET_FILES = {
"__VISUAL_STYLES__": "visualization-styles.css",
"__VISUAL_ADAPTERS__": "visualization-adapters.js",
"__VISUAL_RUNTIME__": "visualization-runtime.js",
}
def load_visual_assets(asset_dir: Path | None = None) -> dict[str, str]:
root = Path(asset_dir or Path(__file__).parent.parent / "assets")
return {
placeholder: (root / filename).read_text(encoding="utf-8")
for placeholder, filename in VISUAL_ASSET_FILES.items()
}
def render_html(
data: dict[str, Any],
template: str,
visual_assets: dict[str, str] | None = None,
) -> str:
validate_report_data(data)
replacements = {
"__REPORT_DATA__": safe_json_for_html(data),
**(visual_assets or load_visual_assets()),
}
rendered = template
for placeholder, value in replacements.items():
if rendered.count(placeholder) != 1:
label = "report data placeholder" if placeholder == "__REPORT_DATA__" else "visual asset placeholder"
raise ValueError(f"template must contain exactly one {label}: {placeholder}")
rendered = rendered.replace(placeholder, value)
return rendered
```
When `--template` points to a custom template, continue loading the trusted bundled assets from the skill's `assets` directory unless a future explicit CLI option changes that contract.
- [ ] **Step 5: Run bundling tests, full tests, and syntax checks**
```powershell
python -X utf8 C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py
node --check C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-adapters.js
node --check C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-runtime.js
```
Expected: Python suite passes; both Node checks exit 0.
---
### Task 4: Implement the generic declarative domain-effect renderer
**Files:**
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-adapters.js`
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py`
**Interfaces:**
- Consumes: `algorithm_views[].scene.objects`, `scene.layers`, and the selected view mode.
- Produces: SVG/DOM elements carrying `data-target-id`, `data-evidence-state`, and accessible labels.
- Public JS API: `DailySummaryVisuals.register(name, renderer)`, `.select(name)`, and `.render(view, root, context)`.
- [ ] **Step 1: Add task-derived adapter assertions**
Use `visualization_data()` as the business fixture. Add static and generated-HTML assertions:
```python
def test_domain_adapter_renders_task_objects_not_fixed_demo_content(self):
html = self.require_html_target().render_html(
self.visualization_data(), TEMPLATE_PATH.read_text(encoding="utf-8")
)
for value in ("local-g2-smoother", "current-path", "curvature-peak", "preview-path"):
self.assertIn(value, html)
self.assertNotIn("固定轨迹示例", html)
def test_unknown_safe_adapter_has_composite_fallback(self):
data = self.visualization_data()
data["algorithm_views"][0]["adapter"] = "custom-business-domain"
html = self.require_html_target().render_html(
data, TEMPLATE_PATH.read_text(encoding="utf-8")
)
self.assertIn("custom-business-domain", html)
self.assertIn("composite-scene", html)
```
- [ ] **Step 2: Run the focused tests and confirm RED**
Expected: the fallback or declarative object hooks are missing.
- [ ] **Step 3: Add safe DOM/SVG construction helpers**
Implement helpers that assign text through `textContent` and SVG attributes through `setAttribute`; never concatenate untrusted labels into `innerHTML`:
```javascript
const SVG_NS = 'http://www.w3.org/2000/svg';
function element(name, attrs = {}, text = '') {
const node = document.createElement(name);
Object.entries(attrs).forEach(([key, value]) => node.setAttribute(key, String(value)));
if (text) node.textContent = text;
return node;
}
function svgElement(name, attrs = {}) {
const node = document.createElementNS(SVG_NS, name);
Object.entries(attrs).forEach(([key, value]) => node.setAttribute(key, String(value)));
return node;
}
function markTarget(node, object) {
node.dataset.targetId = object.id;
node.dataset.evidenceState = object.evidence_state;
node.setAttribute('tabindex', '0');
node.setAttribute('role', 'button');
node.setAttribute('aria-label', `${object.label}${object.evidence_state}`);
return node;
}
```
- [ ] **Step 4: Implement adapter strategies over shared primitives**
Register these layout strategies, while keeping their data task-driven:
- `composite-scene`: render supplied points, polylines, curves, regions, nodes, edges, state blocks, data items, annotations, and clear unsupported-kind cards for the remainder.
The generic renderer must filter visible objects from the selected `scene.layers[].object_ids`; it must not invent domain samples. Unknown adapter names must select `composite-scene`. Do not add dedicated renderer implementations in this task.
- [ ] **Step 5: Add evidence-state and target CSS**
In `visualization-styles.css`, use line style, icon/text, and color together:
```css
[data-evidence-state="actual"] { --state-color: var(--blue); }
[data-evidence-state="static"] { --state-color: var(--amber); }
[data-evidence-state="conceptual"] { --state-color: var(--amber); stroke-dasharray: 8 6; opacity: .82; }
[data-evidence-state="verified"] { --state-color: var(--green); }
[data-evidence-state="conflict"] { --state-color: var(--red); stroke-dasharray: 3 4; }
[data-target-id].is-highlighted { filter: drop-shadow(0 0 5px var(--state-color)); }
[data-target-id]:focus-visible { outline: 3px solid #e7a628; outline-offset: 3px; }
```
- [ ] **Step 6: Run Python tests and Node syntax checks**
Use the commands from Task 3 Step 5. Expected: all pass, and no test claims business correctness beyond the current fixture's actual evidence.
---
### Task 5: Build the four-mode interactive diagnosis shell
**Files:**
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\assets\interactive-report-template.html`
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-runtime.js`
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-styles.css`
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py`
**Interfaces:**
- State: `{ algorithmId, issueId, mode, solutionIndex }`.
- Modes: `baseline`, `current`, `proposed`, `verified`.
- Consumes: Task 1 issue links and Task 4 adapter API.
- [ ] **Step 1: Write failing interaction-hook tests**
```python
def test_renders_algorithm_selector_four_modes_domain_canvas_and_diagnosis_card(self):
html = self.require_html_target().render_html(
self.visualization_data(), TEMPLATE_PATH.read_text(encoding="utf-8")
)
for hook in (
'id="algorithm-selector"',
'data-view-mode="baseline"',
'data-view-mode="current"',
'data-view-mode="proposed"',
'data-view-mode="verified"',
'id="domain-canvas"',
'id="diagnosis-current"',
'id="diagnosis-cause"',
'id="diagnosis-impact"',
'id="diagnosis-solution"',
'id="diagnosis-expected"',
'id="task-validation"',
):
self.assertIn(hook, html)
def test_verified_mode_is_guarded_by_verified_result(self):
runtime = (TEMPLATE_PATH.parent / "visualization-runtime.js").read_text(encoding="utf-8")
self.assertIn("hasVerifiedResult", runtime)
self.assertIn("button.disabled", runtime)
self.assertIn("尚无修正后的匹配验证证据", runtime)
```
- [ ] **Step 2: Run the focused tests and confirm RED**
Expected: the new shell hooks and verified-result guard are absent.
- [ ] **Step 3: Replace the two-column issue workbench with the approved shell**
Add:
- algorithm and issue selectors;
- four mode buttons with `aria-pressed`;
- layer toggles;
- central `#domain-canvas`;
- algorithm-stage navigation;
- object diagnosis card;
- expandable source/test evidence;
- existing solution steps, validation gates, and roadmap below the canvas.
When `algorithm_views` is absent, hide the algorithm controls and retain the legacy text diagnosis behavior.
- [ ] **Step 4: Implement one state-driven render path**
In `visualization-runtime.js`, use one render function so selectors, modes, canvas, diagnosis, validation, and buttons never drift:
```javascript
const report = JSON.parse(document.getElementById('report-data').textContent);
const views = Array.isArray(report.algorithm_views) ? report.algorithm_views : [];
const issues = Array.isArray(report.issues) ? report.issues : [];
const state = {
algorithmId: views[0]?.id || '',
issueId: issues[0]?.id || '',
mode: views.length ? 'baseline' : 'current',
solutionIndex: 0,
};
function currentView() {
return views.find((view) => view.id === state.algorithmId) || null;
}
function currentIssue() {
return issues.find((issue) => issue.id === state.issueId) || null;
}
function hasVerifiedResult(issue) {
return Boolean(issue?.verified_result?.evidence_state === 'verified' && issue.verified_result.validation_refs?.length);
}
function renderApp() {
const view = currentView();
const issue = currentIssue();
renderSelectors(view, issue);
renderModeButtons(issue);
renderDomainCanvas(view, issue);
renderDiagnosis(issue);
renderTaskValidation(report.task_validation);
renderExistingReportSections(issue);
}
```
- [ ] **Step 5: Implement mode-to-layer and diagnosis behavior**
- `baseline`: show the normal algorithm layer and purpose/input/output/constraints.
- `current`: show current layer, highlight `target_ids`, then `effect_target_ids` in propagation order.
- `proposed`: show `solution_preview.target_ids`, expected result, and conceptual/static label.
- `verified`: enable only when `hasVerifiedResult(issue)`; show verified targets and validation references.
Clicking or pressing Enter/Space on a visual target must select the linked issue. Arrow keys change issues only when focus is not in a form control; mode buttons and targets retain visible focus.
- [ ] **Step 6: Add responsive and reduced-motion behavior**
At desktop width use mode rail + canvas + diagnosis drawer. Under 900px stack the drawer below the canvas. Under 560px use single-column selectors and controls. When `prefers-reduced-motion: reduce` is active, reveal the complete impact path immediately rather than animating it.
- [ ] **Step 7: Extend rendered-pair validation to cover algorithm facts**
Update `_validate_rendered_text` so every algorithm view ID, view evidence state, linked issue target ID, correctness criterion ID, and executed check ID exists in the generated HTML. Require the view name, purpose, criterion statement, and check result in Markdown. Keep the existing issue ID/evidence checks and external-resource rejection.
Add a negative test that removes `curvature-peak` from rendered HTML and expects `validate` to fail with `HTML is missing visual target: curvature-peak`.
- [ ] **Step 8: Run the full suite and generated-HTML validation**
```powershell
python -X utf8 C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py
node --check C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-adapters.js
node --check C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-runtime.js
```
Expected: all tests and syntax checks pass; generated HTML contains no external resource.
---
### Task 6: Teach the skill the task-understanding and dynamic-validation workflow
**Files:**
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\SKILL.md`
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\references\report-schema.md`
- Modify: `C:\Users\admin\.codex\skills\daily-summary-job\agents\openai.yaml`
**Interfaces:**
- Consumes: data contract and renderer from Tasks 1-5.
- Produces: repeatable Agent instructions that create task-matched views and validation facts without requiring the user to fill JSON manually.
- [ ] **Step 1: Add the mandatory understanding sequence to SKILL.md**
Insert a concise workflow before report JSON construction:
```markdown
## Build a task-matched algorithm view
When today's work changes, diagnoses, or discusses a function or algorithm:
1. Identify its business purpose, inputs, outputs, stages, observable objects, and correctness constraints from current evidence.
2. Decide what domain effect lets a reader see the algorithm working. Prefer spatial scenes, numeric plots, search/state structures, timelines, or transformed data over a generic flowchart when the evidence supports them.
3. Build one `algorithm_views` entry from actual run/test data when available. Label source reconstruction as `static` and solution prediction as `conceptual`.
4. Link every visual issue to existing stage/object IDs. Show current targets, effect propagation, candidate changes, and verified results as separate states.
5. If the evidence cannot support a credible domain view, list the missing evidence and omit the invented scene.
```
- [ ] **Step 2: Replace generic validation wording with task-matched validation**
```markdown
## Match validation to the current task
Derive correctness criteria from the selected function or algorithm, then locate only tests, commands, samples, and runtime evidence that directly evaluate those criteria. Record checks actually run, their exact results, and missing evidence separately. If no matching test exists, propose a task-specific check and keep the conclusion unverified. Never claim coverage from an unrelated fixed scenario.
```
Retain the existing safety rule against expensive tests by default.
- [ ] **Step 3: Document the complete schema and one non-prescriptive example**
In `references/report-schema.md`, document every Task 1 field, allowed evidence states, object/layer linking rules, task-validation shape, verified-result requirements, and legacy behavior. Use one example only to illustrate the contract, and state explicitly that its domain does not constrain adapter selection.
- [ ] **Step 4: Regenerate UI metadata from the updated skill**
Run:
```powershell
python -X utf8 C:\Users\admin\.codex\skills\.system\skill-creator\scripts\generate_openai_yaml.py C:\Users\admin\.codex\skills\daily-summary-job --interface 'display_name=Daily Summary Job' --interface 'short_description=按当前任务生成带领域算法诊断的交互日报' --interface 'default_prompt=使用 $daily-summary-job 理解当前任务和算法,以匹配的领域效果图展示正常机制、问题、影响、修正方案与验证结果,并更新今日日报。'
```
Expected: `agents/openai.yaml` contains only the interface block with the three supplied values and valid UTF-8 Chinese.
- [ ] **Step 5: Validate skill structure and concise loading behavior**
```powershell
python -X utf8 C:\Users\admin\.codex\skills\.system\skill-creator\scripts\quick_validate.py C:\Users\admin\.codex\skills\daily-summary-job
```
Expected: `Skill is valid!`. Confirm `SKILL.md` stays under 500 lines and keeps detailed field definitions in `references/report-schema.md`.
---
### Task 7: End-to-end verification on the current task and backward compatibility
**Files:**
- Test: all files under `C:\Users\admin\.codex\skills\daily-summary-job`
- Generate temporary outputs only under a verified temporary directory or this project's `dailywork_report` when explicitly updating the real report.
**Interfaces:**
- Consumes: completed skill from Tasks 1-6.
- Produces: fresh verification evidence for schema, rendering, interaction hooks, self-containment, task matching, and legacy reports.
- [ ] **Step 1: Run the complete automated suite**
```powershell
python -X utf8 C:\Users\admin\.codex\skills\daily-summary-job\scripts\test_prepare_report.py
```
Expected: every test passes with zero failures. Record the actual test count; do not reuse the previous count of 31.
- [ ] **Step 2: Run skill and JavaScript validation**
```powershell
python -X utf8 C:\Users\admin\.codex\skills\.system\skill-creator\scripts\quick_validate.py C:\Users\admin\.codex\skills\daily-summary-job
node --check C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-adapters.js
node --check C:\Users\admin\.codex\skills\daily-summary-job\assets\visualization-runtime.js
```
Expected: skill valid; both JavaScript files exit 0.
- [ ] **Step 3: Run a temporary legacy report round trip**
Use the existing `sample_data()` shape without `algorithm_views`. Run `render`, `validate`, and `render --update` in a new temporary project. Expected: Markdown and HTML are created, validate returns `valid: true`, and update reuses the same pair.
- [ ] **Step 4: Run a temporary current-task domain-view round trip**
Use the Task 1 `visualization_data()` facts, which match the current path-smoothing work rather than an unrelated generic test. Run `render`, then `validate`. Assert:
- `valid` is `true`;
- HTML contains the task's actual object IDs and values;
- current, proposed, and verified controls are present;
- verified mode is disabled because this fixture has no verified result;
- Markdown contains the task-specific criterion and missing evidence;
- no external URL, `<link>`, or `<script src>` exists.
- [ ] **Step 5: Verify failure gates with mutations**
Starting from the same task facts, independently mutate and reject:
- an unknown `target_id`;
- a proposed view marked `verified` without validation references;
- a check referencing an unknown correctness criterion;
- a layer referencing an unknown object;
- a rendered HTML file containing an external URL.
Expected: each mutation returns a non-zero CLI status and an error naming the violated contract.
- [ ] **Step 6: Perform live visual and interaction QA when a browser runtime is available**
Open the generated domain-view HTML and verify:
- algorithm and issue selection;
- all four mode controls;
- task-specific domain objects, not a fixed demo;
- click/keyboard target selection;
- cause and effect highlighting;
- solution-step preview;
- verified-mode guard;
- desktop and narrow-screen layout;
- reduced-motion behavior.
If the browser runtime is unavailable, record this exact check as `待验证风险`; source inspection and syntax checks do not replace visual QA.
- [ ] **Step 7: Review only skill and report artifacts; do not commit**
Run scoped file listings and diffs. Confirm no business source file, staging index, or Git commit was changed. Report created/modified skill files, verification commands, exact pass counts, and any remaining visual-QA risk.
---
## Plan Completion Criteria
- All seven tasks satisfy their focused tests before the next task begins.
- The full suite passes after each task that changes Python or JavaScript behavior.
- A legacy report and a task-matched domain report both pass CLI validation.
- The task-matched report visibly connects domain objects to problem, cause, consequence, solution preview, expected result, and available verification evidence.
- No fixed domain example is presented as a universal validation scenario.
- No external dependency, business-code edit, Git staging, or Git commit is introduced.