Commit babc58d36b57c5a0b82345836f7d6e4552d89422
1 parent
0d7a045a
graphlemon: brd artifact for task 773a7a08-b295-4ba3-b506-196a21403d8b
Showing
1 changed file
with
117 additions
and
0 deletions
.graphlemon/runs/773a7a08-b295-4ba3-b506-196a21403d8b/brd.md
0 → 100644
| 1 | +# BRD:修复"Planner 产出总览"面板文件/代码列表点击无反应的 Bug | |
| 2 | + | |
| 3 | +> 依据 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`。 | |
| 4 | + | |
| 5 | +## 0. 文档信息 | |
| 6 | + | |
| 7 | +- 触发来源:用户报告的可复现 UI Bug + 用户已给出的确认根因(本 BRD 对根因做了独立交叉验证,见 1.2)。 | |
| 8 | +- 覆盖实体/接口: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`,本次**不修改**。 | |
| 9 | +- 类型:Bug 修复(交互缺陷,根因单一),非新特性、非重新设计。 | |
| 10 | +- 风险等级:低(纯前端 `frontend/app.js` 改动,无权限/支付/数据不可逆变更;无需触碰后端 API 或数据库 schema)。 | |
| 11 | +- 状态机备注:本文档为 `task` 生命周期中 `planning_brd_prd_sdd` 阶段产出的 BRD Artifact,不代表任务已完成;状态流转由 `c_org_node_trigger`/`c_org_loop_route` 依据 BRD/PRD/SDD/Benchmark 判定。 | |
| 12 | + | |
| 13 | +## 1. 背景与问题陈述 | |
| 14 | + | |
| 15 | +### 1.1 用户可观察的症状 | |
| 16 | + | |
| 17 | +控制台 Graph 页面(`#/graph`)"Planner 产出总览"面板中,"文档列表(brd/prd/sdd/benchmark)"和"代码列表(code_diff/test_report)"两个子列表里的每一项,点击后没有任何反应——用户预期点击后能跳转到该 artifact 的详情/内容页面,实际什么都不发生。 | |
| 18 | + | |
| 19 | +### 1.2 根因(已通过直接读取生产代码交叉验证,非仅采信用户描述) | |
| 20 | + | |
| 21 | +- `renderArtifactSummaryList()`(`frontend/app.js:1344-1351`)目前渲染出的每个 `<li>` 只包含两个 `<span>` 文本节点,**没有任何 `data-*` 属性,也没有绑定任何点击行为**。已确认用户给出的根因描述准确无误。 | |
| 22 | +- 对照组:同一挂载函数 `mountArtifactsOverviewPanel()`(1359-1400 行)里的"Graph 运行历史"列表(`gc_runs_list`)已正确实现"数据带 id + 点击跳转"模式(`data-run-task-id` + `querySelectorAll`/`addEventListener` 绑定),证明面板内已有可复用实现模式,问题范围严格限定在 `renderArtifactSummaryList()` 及其调用方。 | |
| 23 | +- 数据侧确认:`list_artifacts()`(`src/artifact_query.py:22-46`)返回对象已带 `artifact_id`(不含 `/`,可安全嵌入 URL hash)。 | |
| 24 | +- 已有可复用跳转机制:`v_artifact_browser`(`#/artifacts`,`frontend/app.js:1560-1654`)已完整实现"选中 artifact → 拉取 `GET /api/artifacts/:artifact_id` → 展示血缘链 + 内容预览",工作正常,不应重建并行逻辑。 | |
| 25 | +- 路由层现状:`render()`(77-132 行)只支持精确匹配表和两个正则动态路由(`TASK_DETAIL_RE`/`SKILL_AUDIT_RE`),`#/artifacts` 目前没有携带具体 id 的动态子路由。 | |
| 26 | + | |
| 27 | +### 1.3 相关文档缺口(供 Validator 知悉,非本次修复范围) | |
| 28 | + | |
| 29 | +"Planner 产出总览"面板未被 `docs/sdd/02-V-界面与交互.md`/`docs/development-plan.md` 记录(与 CLAUDE.md "Status" 一节所述现象一致)。本 BRD 以代码本身为事实来源,不在本次范围内补写缺失文档。 | |
| 30 | + | |
| 31 | +## 2. 目标与非目标 | |
| 32 | + | |
| 33 | +### 2.1 目标 | |
| 34 | +- **G1**:文档/代码列表每项带真实 `artifact_id`,点击可跳转,视觉提示与"Graph 运行历史"一致。 | |
| 35 | +- **G2**:跳转后精确展示被点击 artifact 的真实内容(复用 `v_artifact_browser` 预览面板),不是空白/默认最新一条。 | |
| 36 | +- **G3**:两个"查看全部"链接继续跳到未过滤 `#/artifacts`,行为不变。 | |
| 37 | +- **G4**:不重新实现内容展示逻辑,只接入既有机制。 | |
| 38 | + | |
| 39 | +### 2.2 非目标 | |
| 40 | +不修改 `src/artifact_query.py`/后端 API;不修改 `showPreview()` 内部逻辑;不改变"查看全部"行为或补充过滤参数;不处理"任务列表"子块点击(范围外,记录为后续跟进项);不改动"Graph 运行历史"现有实现;不引入新依赖/构建步骤。 | |
| 41 | + | |
| 42 | +## 3. 事实 / 设计决策 / 假设 / 未知 | |
| 43 | + | |
| 44 | +### 3.1 已知事实 | |
| 45 | +- `renderArtifactSummaryList()` 无 `data-*`/事件绑定;`artifacts` 已含 `artifact_id`(UUID,`src/artifact_write.py:68`)。 | |
| 46 | +- `render()` 无查询字符串解析能力;`#/tasks/:id`、`#/skills/:id/audit` 是"列表+id 动态子路由"的两个成熟先例。 | |
| 47 | +- `mountArtifactBrowser()` 的 `refreshList()`(1638-1642 行)已有"若 `selectedArtifactId` 存在则 `showPreview()`,否则默认第一条"逻辑,可直接复用于"外部带初始 id 进入"场景。 | |
| 48 | +- `.artifact-list li` 已有 `cursor:pointer`/`:hover`/`.active` 样式;`.simple-list li` 没有。 | |
| 49 | +- `frontend/test_graph_console_smoke.js` 现有 fixture(116-120 行)不含 `artifact_id`,若不同步更新会造成"测试通过但未测到关键改动"的假阳性。 | |
| 50 | + | |
| 51 | +### 3.2 设计决策 | |
| 52 | +- **D1**:新增动态路由 `#/artifacts/:artifact_id`(沿用既有正则动态路由模式),不引入查询字符串解析。 | |
| 53 | +- **D2**:`mountArtifactBrowser()` 新增可选形参 `artifactId`,有值时预置 `selectedArtifactId`,复用既有"保持选中项"逻辑触发 `showPreview()`。 | |
| 54 | +- **D3**:`renderArtifactSummaryList()` 输出 `data-artifact-id` + 可点击视觉提示;事件绑定放在 `mountArtifactsOverviewPanel()` 里 `innerHTML` 赋值之后,与 `gc_runs_list` 现有模式一致(不用内联 `onclick`)。 | |
| 55 | +- **D4**:跳转 URL 对 `artifact_id` 做 `encodeURIComponent()`,与 `showPreview()` 现有写法一致。 | |
| 56 | + | |
| 57 | +### 3.3 待验证假设 | |
| 58 | +无实质性待验证假设,根因/数据/可复用机制/路由边界均已通过读代码确认。 | |
| 59 | + | |
| 60 | +### 3.4 阻塞性未知 | |
| 61 | +无。可直接进入开发。 | |
| 62 | + | |
| 63 | +## 4. 范围 | |
| 64 | + | |
| 65 | +### 4.1 范围内文件 | |
| 66 | +- `frontend/app.js`:`renderArtifactSummaryList()`、`mountArtifactsOverviewPanel()`、`routes`/动态路由区(新增 `ARTIFACT_DETAIL_RE`)、`mountArtifactBrowser()`(新增可选形参)。 | |
| 67 | +- `frontend/test_graph_console_smoke.js`:更新 fixture + 断言。 | |
| 68 | +- `frontend/style.css`(视实现选择,非必须)。 | |
| 69 | + | |
| 70 | +### 4.2 明确排除 | |
| 71 | +`src/artifact_query.py`、`src/backend_server.py`、`src/artifact_write.py`;`showPreview()` 内部逻辑;"查看全部"行为;"任务列表"点击;"Graph 运行历史"现有实现;后端测试套件(应保持全绿但无需新增用例)。 | |
| 72 | + | |
| 73 | +## 5. 验收标准 | |
| 74 | + | |
| 75 | +### 5.1 自动化测试证据 | |
| 76 | +- `node frontend/test_graph_console_smoke.js`:fixture 含 `artifact_id`,断言输出含精确匹配的 `data-artifact-id`;"查看全部"仍渲染为无 id/无查询参数的普通链接;现有断言全部继续通过。 | |
| 77 | +- `python3 -m unittest discover -s src` 全量通过(回归基线,未改后端代码)。 | |
| 78 | + | |
| 79 | +### 5.2 真实浏览器验证证据(人工,本仓库前端既有约定) | |
| 80 | +1. `#/graph` 面板列表项呈现可点击视觉提示。 | |
| 81 | +2. 点击文档列表项,hash 变为 `#/artifacts/<真实 artifact_id>`,切换到 Artifact 浏览器。 | |
| 82 | +3. 预览面板精确展示被点击 artifact 的真实内容,对应 `<li>` 呈现 `.active` 高亮。 | |
| 83 | +4. 代码列表(`code_diff`/`test_report`)重复验证。 | |
| 84 | +5. 两个"查看全部"仍跳到未过滤 `#/artifacts`。 | |
| 85 | +6. 直接在地址栏输入 `#/artifacts/<id>` 能独立正确加载(不依赖前置点击状态)。 | |
| 86 | + | |
| 87 | +### 5.3 边界场景证据 | |
| 88 | +磁盘文件缺失时预览面板展示"(文件不可用)"文案(既有逻辑),不崩溃。 | |
| 89 | + | |
| 90 | +## 6. 风险与依赖 | |
| 91 | +- R1(低):`mountArtifactBrowser` 新增可选形参需保证 `artifactId` 为 `undefined` 时默认行为逐字节不变。 | |
| 92 | +- R2(低):fixture 更新遗漏 `artifact_id` 会造成假阳性测试,需人工确认断言做了精确值匹配。 | |
| 93 | +- R3(可忽略):D4 已给出防御性 encode 写法。 | |
| 94 | +- 依赖:无外部依赖,无环;复用组件均已验证可工作。 | |
| 95 | + | |
| 96 | +## 7. 可追溯性矩阵 | |
| 97 | + | |
| 98 | +| 原始要求 | 责任范围 | 验收锚点 | | |
| 99 | +|---|---|---| | |
| 100 | +| 每项加真实 `artifact_id` + 点击跳转 | `renderArtifactSummaryList()` + `mountArtifactsOverviewPanel()` 绑定 | 5.1 + 5.2.1/5.2.2 | | |
| 101 | +| 跳转需定位到具体 artifact 详情视图 | 新增 `#/artifacts/:artifact_id` 路由(D1)+ 预置 `selectedArtifactId`(D2) | 5.2.2/5.2.6 | | |
| 102 | +| 跳转后展示真实内容,非空白/默认全量 | 复用既有 `showPreview`/`selectedArtifactId` 逻辑 | 5.2.3/5.2.4 + 5.3 | | |
| 103 | +| "查看全部"行为不变 | 不改动现有 `<a>` 标签 | 5.1 + 5.2.5 | | |
| 104 | +| 复用现有内容预览机制,不重建 | D1-D4 均基于复用 | 4.2 + 2.1 G4 | | |
| 105 | +| 不修改 `c_artifact_get`/`v_artifact_browser` 本身 | 4.2 排除后端与预览内部实现 | 4.2 | | |
| 106 | + | |
| 107 | +## 8. PL 自审 | |
| 108 | +- [x] 根因有明确代码来源(1.2) | |
| 109 | +- [x] 事实/决策/假设/未知已分列(第 3 节) | |
| 110 | +- [x] 范围清晰,显式排除相邻蔓延项(2.2、4.2) | |
| 111 | +- [x] 验收标准可测试、描述可观察结果(5.1/5.2) | |
| 112 | +- [x] 已识别"测试通不到真改动"的假阳性风险(3.1、R2) | |
| 113 | +- [x] 依赖无环(第 6 节) | |
| 114 | +- [x] 原始要求均在追溯矩阵中有责任方与验收锚点(第 7 节) | |
| 115 | +- [x] 无需更深调查,风险等级低,可直接进入开发 | |
| 116 | + | |
| 117 | +**判定:可以流转到开发(Code Agent)**,无阻塞性未知,范围与验收标准明确。后续 SDD 应给出 `ARTIFACT_DETAIL_RE` 具体正则、函数签名与 CSS class 命名,BRD 本身不预锁实现细节。 | |
| 0 | 118 | \ No newline at end of file | ... | ... |