BRD:修复"Planner 产出总览"面板文件/代码列表点击无反应的 Bug
依据 SOUL.md §16,本 Agent 不直接改写
task.status,仅产出本 BRD Artifact 供c_org_node_trigger/c_org_loop_route判定流转。以下事实均来自对当前代码(非文档)的直接读取:frontend/app.js、frontend/style.css、frontend/test_graph_console_smoke.js、src/artifact_query.py、src/artifact_write.py、src/backend_server.py、docs/sdd/02-V-界面与交互.md。
0. 文档信息
- 触发来源:用户报告的可复现 UI Bug + 用户已给出的确认根因(本 BRD 对根因做了独立交叉验证,见 1.2)。
- 覆盖实体/接口:V=
v_graph_console(#/graph,"Planner 产出总览"面板,2026-08-03 加入,无独立 SDD 文档条目,docs/sdd/02-V-界面与交互.md未记录此面板——见 1.3 的文档缺口说明)复用 V=v_artifact_browser(docs/sdd/02-V-界面与交互.md§2.8);C=c_artifact_get(GET /api/artifacts/:artifact_id,src/artifact_query.py:49-71,本次不修改。 - 类型:Bug 修复(交互缺陷,根因单一),非新特性、非重新设计。
- 风险等级:低(纯前端
frontend/app.js改动,无权限/支付/数据不可逆变更;无需触碰后端 API 或数据库 schema)。 - 状态机备注:本文档为
task生命周期中planning_brd_prd_sdd阶段产出的 BRD Artifact,不代表任务已完成;状态流转由c_org_node_trigger/c_org_loop_route依据 BRD/PRD/SDD/Benchmark 判定。
1. 背景与问题陈述
1.1 用户可观察的症状
控制台 Graph 页面(#/graph)"Planner 产出总览"面板中,"文档列表(brd/prd/sdd/benchmark)"和"代码列表(code_diff/test_report)"两个子列表里的每一项,点击后没有任何反应——用户预期点击后能跳转到该 artifact 的详情/内容页面,实际什么都不发生。
1.2 根因(已通过直接读取生产代码交叉验证,非仅采信用户描述)
renderArtifactSummaryList()(frontend/app.js:1344-1351)目前渲染出的每个<li>只包含两个<span>文本节点,没有任何data-*属性,也没有绑定任何点击行为。已确认用户给出的根因描述准确无误。- 对照组:同一挂载函数
mountArtifactsOverviewPanel()(1359-1400 行)里的"Graph 运行历史"列表(gc_runs_list)已正确实现"数据带 id + 点击跳转"模式(data-run-task-id+querySelectorAll/addEventListener绑定),证明面板内已有可复用实现模式,问题范围严格限定在renderArtifactSummaryList()及其调用方。 - 数据侧确认:
list_artifacts()(src/artifact_query.py:22-46)返回对象已带artifact_id(不含/,可安全嵌入 URL hash)。 - 已有可复用跳转机制:
v_artifact_browser(#/artifacts,frontend/app.js:1560-1654)已完整实现"选中 artifact → 拉取GET /api/artifacts/:artifact_id→ 展示血缘链 + 内容预览",工作正常,不应重建并行逻辑。 - 路由层现状:
render()(77-132 行)只支持精确匹配表和两个正则动态路由(TASK_DETAIL_RE/SKILL_AUDIT_RE),#/artifacts目前没有携带具体 id 的动态子路由。
1.3 相关文档缺口(供 Validator 知悉,非本次修复范围)
"Planner 产出总览"面板未被 docs/sdd/02-V-界面与交互.md/docs/development-plan.md 记录(与 CLAUDE.md "Status" 一节所述现象一致)。本 BRD 以代码本身为事实来源,不在本次范围内补写缺失文档。
2. 目标与非目标
2.1 目标
- G1:文档/代码列表每项带真实
artifact_id,点击可跳转,视觉提示与"Graph 运行历史"一致。 - G2:跳转后精确展示被点击 artifact 的真实内容(复用
v_artifact_browser预览面板),不是空白/默认最新一条。 - G3:两个"查看全部"链接继续跳到未过滤
#/artifacts,行为不变。 - G4:不重新实现内容展示逻辑,只接入既有机制。
2.2 非目标
不修改 src/artifact_query.py/后端 API;不修改 showPreview() 内部逻辑;不改变"查看全部"行为或补充过滤参数;不处理"任务列表"子块点击(范围外,记录为后续跟进项);不改动"Graph 运行历史"现有实现;不引入新依赖/构建步骤。
3. 事实 / 设计决策 / 假设 / 未知
3.1 已知事实
renderArtifactSummaryList()无data-*/事件绑定;artifacts已含artifact_id(UUID,src/artifact_write.py:68)。render()无查询字符串解析能力;#/tasks/:id、#/skills/:id/audit是"列表+id 动态子路由"的两个成熟先例。mountArtifactBrowser()的refreshList()(1638-1642 行)已有"若selectedArtifactId存在则showPreview(),否则默认第一条"逻辑,可直接复用于"外部带初始 id 进入"场景。.artifact-list li已有cursor:pointer/:hover/.active样式;.simple-list li没有。frontend/test_graph_console_smoke.js现有 fixture(116-120 行)不含artifact_id,若不同步更新会造成"测试通过但未测到关键改动"的假阳性。
3.2 设计决策
- D1:新增动态路由
#/artifacts/:artifact_id(沿用既有正则动态路由模式),不引入查询字符串解析。 - D2:
mountArtifactBrowser()新增可选形参artifactId,有值时预置selectedArtifactId,复用既有"保持选中项"逻辑触发showPreview()。 - D3:
renderArtifactSummaryList()输出data-artifact-id+ 可点击视觉提示;事件绑定放在mountArtifactsOverviewPanel()里innerHTML赋值之后,与gc_runs_list现有模式一致(不用内联onclick)。 - D4:跳转 URL 对
artifact_id做encodeURIComponent(),与showPreview()现有写法一致。
3.3 待验证假设
无实质性待验证假设,根因/数据/可复用机制/路由边界均已通过读代码确认。
3.4 阻塞性未知
无。可直接进入开发。
4. 范围
4.1 范围内文件
frontend/app.js:renderArtifactSummaryList()、mountArtifactsOverviewPanel()、routes/动态路由区(新增ARTIFACT_DETAIL_RE)、mountArtifactBrowser()(新增可选形参)。frontend/test_graph_console_smoke.js:更新 fixture + 断言。frontend/style.css(视实现选择,非必须)。
4.2 明确排除
src/artifact_query.py、src/backend_server.py、src/artifact_write.py;showPreview() 内部逻辑;"查看全部"行为;"任务列表"点击;"Graph 运行历史"现有实现;后端测试套件(应保持全绿但无需新增用例)。
5. 验收标准
5.1 自动化测试证据
node frontend/test_graph_console_smoke.js:fixture 含artifact_id,断言输出含精确匹配的data-artifact-id;"查看全部"仍渲染为无 id/无查询参数的普通链接;现有断言全部继续通过。python3 -m unittest discover -s src全量通过(回归基线,未改后端代码)。
5.2 真实浏览器验证证据(人工,本仓库前端既有约定)
#/graph面板列表项呈现可点击视觉提示。- 点击文档列表项,hash 变为
#/artifacts/<真实 artifact_id>,切换到 Artifact 浏览器。 - 预览面板精确展示被点击 artifact 的真实内容,对应
<li>呈现.active高亮。 - 代码列表(
code_diff/test_report)重复验证。 - 两个"查看全部"仍跳到未过滤
#/artifacts。 - 直接在地址栏输入
#/artifacts/<id>能独立正确加载(不依赖前置点击状态)。
5.3 边界场景证据
磁盘文件缺失时预览面板展示"(文件不可用)"文案(既有逻辑),不崩溃。
6. 风险与依赖
- R1(低):
mountArtifactBrowser新增可选形参需保证artifactId为undefined时默认行为逐字节不变。 - R2(低):fixture 更新遗漏
artifact_id会造成假阳性测试,需人工确认断言做了精确值匹配。 - R3(可忽略):D4 已给出防御性 encode 写法。
- 依赖:无外部依赖,无环;复用组件均已验证可工作。
7. 可追溯性矩阵
| 原始要求 | 责任范围 | 验收锚点 |
|---|---|---|
每项加真实 artifact_id + 点击跳转 |
renderArtifactSummaryList() + mountArtifactsOverviewPanel() 绑定 |
5.1 + 5.2.1/5.2.2 |
| 跳转需定位到具体 artifact 详情视图 | 新增 #/artifacts/:artifact_id 路由(D1)+ 预置 selectedArtifactId(D2) |
5.2.2/5.2.6 |
| 跳转后展示真实内容,非空白/默认全量 | 复用既有 showPreview/selectedArtifactId 逻辑 |
5.2.3/5.2.4 + 5.3 |
| "查看全部"行为不变 | 不改动现有 <a> 标签 |
5.1 + 5.2.5 |
| 复用现有内容预览机制,不重建 | D1-D4 均基于复用 | 4.2 + 2.1 G4 |
不修改 c_artifact_get/v_artifact_browser 本身 |
4.2 排除后端与预览内部实现 | 4.2 |
8. PL 自审
- [x] 根因有明确代码来源(1.2)
- [x] 事实/决策/假设/未知已分列(第 3 节)
- [x] 范围清晰,显式排除相邻蔓延项(2.2、4.2)
- [x] 验收标准可测试、描述可观察结果(5.1/5.2)
- [x] 已识别"测试通不到真改动"的假阳性风险(3.1、R2)
- [x] 依赖无环(第 6 节)
- [x] 原始要求均在追溯矩阵中有责任方与验收锚点(第 7 节)
- [x] 无需更深调查,风险等级低,可直接进入开发
判定:可以流转到开发(Code Agent),无阻塞性未知,范围与验收标准明确。后续 SDD 应给出 ARTIFACT_DETAIL_RE 具体正则、函数签名与 CSS class 命名,BRD 本身不预锁实现细节。