N1c 子窗口完成报告:采集演示(窗口 N · 3/5)
窗口:N-c(execution-plan §六.十八 8-10)|日期:2026-08-19 依据:demo-redesign-design v0.3(§3.3/§6/§12)+ demo-n-window-ledger §10.1(冻结验收清单 7 项)+ handoff-design-hub §六.7(推送纪律) 验收方式:demo 设计中枢独立验收(不轻信自检:实跑 + 数字独立重算 + git 检查)
1. 交付总览
| 项 | 内容 |
|—|—|
| 新增文件 | demo/capture_chain.py(63.7 复现链路共享模块——现象/机制单一事实源)、
tests/test_demo_smoke.py(AppTest 冒烟 + golden 守卫 + 63.7 断言) |
| 重写文件 | demo/pages/02_capture.py(采集演示页:四类判定对齐表 + verdict 状态位
流转时间线 + expected_types 机制交互 + declared 高级折叠区) |
| 修改文件 | demo/pages/01_workshop.py(_golden_b_chain 收敛为
capture_chain.run_chain() 缓存包装——现象层与机制层共用同一链路)、
demo/theme.css(N-c 样式增量:四色对齐表/流转时间线/补入卡/徽章)、
.github/workflows/ci.yml(install 加装 demo extra——台账 §2.2 收口)、
docs/migration/index.md(N1c 登记) |
| 零改动 | src/、tests/(test_demo_smoke.py 除外)、ui/、demo/data/
(git diff 确认) |
| 数据真实性 | 63.7 复现全链路基于 demo/data 提炼副本(verdicts_10X_B.jsonl +
golden_agent_10X_B_executed.py + windowL_10X_B_expected.json),
零读仓库外 cellvoyager-outputs;交互重算与工坊页现象层共用
capture_chain,两处数字一致 |
| 验证 | pytest 274 passed(269 + 新增 5)/ golden 0 差异 / ruff 0 错误 /
AppTest 冒烟 5 项全过 / Playwright 双宽度 0 溢出 / 视觉抽查 |
2. execution-plan §六.十八 打勾
- N-c 8 四类判定可视化(一致/虚报/漏报/未验证四色)+ verdict 状态位 流转时间线(verdicts jsonl 三态 11 provisional + 13 final + 1 revoked)
- N-c 9 expected_types 机制交互:勾选清单 → 实时重算 → 63.7 blocked 复现(M1 从 verdicts 重建 + M3 解析 executed.py + expected_types_for, 见设计 §6;断言基准 windowL_10X_B_expected.json);declared 注入 降级为高级折叠区
- N-c 10 tests/test_demo_smoke.py:AppTest 冒烟 + golden 0 差异守卫 + 63.7 断言读 demo/data 副本(provenance 保留 source=windowL_10X_B_expected.json);CI 依赖同步(ci.yml 加装 demo extra)→ CI 云上绿(见 §8.1)
3. 台账 §10.1 冻结验收清单逐项核对
| # | 验收项 | 结果 | 证据 |
|---|---|---|---|
| 1 | 四类判定可视化:四色 + 对齐表(10X-B 真实交叉验证 consistent 10 / false_positive 1 / expected_added 1)+ verdict 三态流转(11/13/1) | ✅ | §5.1-5.2(DOM 实测:11 对齐行 / 14 流转行 / 虚报行红调样式生效) |
| 2 | expected_types 机制交互:勾选清单(读 expected_types.yaml)→ 实时重算 → 补入 → 63.7 blocked 完整复现;与工坊页现象层数字一致;交互/快照双模式 | ✅ | §5.3 + §6.1(共享 capture_chain;独立重算 5/5 断言;取消勾选 → 80.0 pass 对照) |
| 3 | declared 注入:高级折叠区(expandable)+ 工具提示 | ✅ | §5.4(折叠区 + 两级作用说明 + 三级可信源语义) |
| 4 | tests/test_demo_smoke.py:AppTest 冒烟 + golden 守卫 + 63.7 断言读 demo/data 副本;CI 依赖同步 → CI 云上绿 | ✅ | §6 + §8.1(smoke 5 项:四页冒烟 + 采集页勾选交互 + 63.7 断言 + 交互对照 + golden 守卫) |
| 5 | 工程纪律:pytest 全绿 + golden 0 差异 + 零改动 + 推送纪律 | ✅ | §8 |
| 6 | skill:design-taste-frontend + web-design-guidelines 走查(🔴=0,报告落盘)+ code-review 双轴(报告落盘) | ✅ | §4 + §7 |
| 7 | 报告 + execution-plan 打勾 | ✅ | 本文件 |
4. 设计走查(web-design-guidelines,🔴=0)
完整走查报告见 §4.1(本报告内落盘)。结论:🔴 严重问题 0 项;🟡 1 项 (接受,理由见下);🟢 其余全部通过。走查方式 = Playwright 真实浏览器 程序化验证(双宽度 0 溢出、元素计数、计算样式、交互往返)+ 视觉模型 抽查(横幅/标题/对齐表/流转行/分数卡/补入卡逐状态确认)。
4.1 走查明细(按 web-design-guidelines 五维)
| 维度 | 结论 | 备注 |
|---|---|---|
| 字体与排版 | ✅ 层级延续工坊页(页标题 1.75rem / 分区标题 0.82rem 大写 / 正文 0.86-0.92rem / 徽章 0.66-0.78rem 等宽);判定徽章/流转标签全部等宽 + tabular-nums;中文混排行高 1.6 + word-break;detail 列超长省略 + title 悬停全文 | — |
| 间距与节奏 | ✅ 8px 网格延续(统计行 8px 间距 / 流转行 8px 内距 / 表内 8px padding);四分区节奏 = 表 → 流转卡 → 交互舞台 → 折叠区,主焦点(交互)篇幅最大 | — |
| 交互与反馈 | ✅ 勾选即时重算(cache_data 按清单哈希);「恢复默认(全选)」1 次点击回全选;断言徽章 ✓/✗ 双态即时反馈;hover:徽章/说明列 title 悬停全文;disabled 无适用场景;focus 保留 Streamlit 默认环 | — |
| 色彩与对比 | ✅ 四类判定四色语义严格绑定(一致绿/虚报红/漏报黄/未验证灰)+ 补入青,图例常驻;正文 #e5e7eb on #0f1115(≈14:1);次要 #9ca3af(≈5.5:1);虚报行 5% 红调底 + 红色左边条(唯一红色行,一眼定位);流转终态色 = verdict 语义色复用 | — |
| 布局与层级 | ✅ 第一眼锚点 = 对齐表统计行(四色计数);机制说明列限宽 380px 防长行;1024px 下对齐表/流转行纵向堆叠(media query),实测 0 溢出 | — |
🟡 接受项(1):对齐表 detail 列文字截断 120 字符(title 悬停全文)—— 表格行高约束下的主动取舍,与工坊页对比表 choice 省略号同策略。
视觉抽查记录(真实浏览器 + 视觉模型逐状态):
- 默认态(全选):横幅 BIO-AUDIT + 三元组徽章 ✓、标题「采集演示」✓、 大分数卡 63.7 红 + blocked + 红点 ✓、三维度进度条 ✓、绿色断言徽章 「与断言基准一致 ✓」✓、青色上下文 chips(n_cells=59399 等)✓;
- 取消勾选态:红调「与断言基准不一致 ✗」提示 ✓、「静默跳过在预期清单外 不可见」蓝卡 ✓(DOM 确认 80.0 · pass 渲染);
- 两档宽度(1440/1024)document 横向溢出均为 0。
4.2 design-taste-frontend 自查(Spec #F4 闭环)
页面生成沿用 N-a/N-b 定稿的深色审计台设计语言(design-taste-frontend 执行), N-c 增量自查(对照 skill 的 AI 模板感特征清单):
- 无深紫/靛蓝渐变、无彩虹文字、无 emoji 堆砌、无对称三卡复制;
- 布局不对称:四分区节奏 = 对齐表(信息密)→ 流转卡(叙事)→ 交互舞台 (主焦点,篇幅最大)→ 折叠区(辅助);
- 色彩有语义:四类判定四色严格绑定判定类别 + 图例常驻,无装饰色;
- 克制动效:仅 hover 边框/背景过渡 150ms ease-out + prefers-reduced-motion;
- 等宽字体(Consolas 回退栈)用于一切数字/决策 id/徽章,tabular-nums 对齐;
- 中文混排行高 1.6 + word-break;圆角 8-10px 克制。 (全站最终复查归 N-e。)
5. 关键实现说明
5.1 声明 vs 事实对齐表(四类判定,N-c1)
- 数据 =
capture_chain.run_chain()的 alignments(10X-B 真实交叉验证: consistent 10 / false_positive 1 / false_negative 0 / unverified 0 / expected_added 1 现成分布); - 行序 = 本体阶段顺序(复用
result_view.ontology_decision_order,与工坊页 对比表同一对齐纪律);列 = 决策点 / 判定(四色徽章)/ M1 声明 / M3 事实(operative 工具签名 + 实例数)/ 机制说明(title 悬停全文); - 虚报行(doublet_detection)红调底 + 红色左边条 + 「补入 expected」青徽章 并存——一眼定位「声明了但没做 → 撤销 → 补入」的完整语义;
- 四类判定图例常驻(漏报/未验证计数 0 也不隐藏——机制说明「不凑数」, 与设计 §3.3「四类判定可视化」字面一致)。
5.2 verdict 状态位流转时间线(N-c1)
- 数据 = verdicts_10X_B.jsonl 25 行原始记录(按 verdict_id 聚合,末条为 终态):11 provisional + 13 final + 1 revoked;
- 三态计数条(provisional → final / revoked)+ 图例(一致 / 虚报 / expected 补入三流转语义);
- 逐 verdict 流转行(14 行):M1 声明行 = provisional → final(绿)或 revoked(红,skip_doublet「虚报」流转高亮红调行);expected 补入行 = final 青徽章(直接终态);reason 取 history 末条真实原因(title 悬停);
- 诚实说明:历史含 1 条 expected api_data_integrity(窗口 M 早期清单), 现行 expected_types.yaml 已不含该类型(M3 无确定性签名,L1 §4.3.1)—— 时间线展示原始记录,交互重算用现行配置,口径分列不混写。
5.3 expected_types 机制交互(63.7 复现,N-c2)
- 勾选清单 =
capture_chain.default_expected()(读 expected_types.yaml scrna_10x 11 决策,B7 豁免已应用);st.checkbox2 列网格 + session_state 持久化(刷新不丢)+「恢复默认(全选)」1 次点击复位; - 实时重算 =
st.cache_data按勾选清单哈希缓存(控件交互不重算一切); - 链路中间产物全展示:① M1 重建 11 条 → ② M3 解析 79 候选(未定 7)→
③ 交叉验证四类统计 → ④ 补入过程卡(doublet_detection / skip_doublet /
provenance=expected / context chips = M1 事实)→ ⑤ final N 决策 → 大分数卡
- 断言徽章(与 windowL_10X_B_expected.json 实时比对);
- 机制对照(取消勾选 doublet_detection):无补入 → 80.0 · pass——静默跳过 在预期清单外不可见;恰与黄金对照 A(10X,双联体真实执行)同分 (A 版分数从 golden_summary 动态读取,不硬编码);
- 只有缺失的预期决策点受勾选影响(本案例唯一缺失 = doublet_detection), 页面 caption 明示,防观众误操作困惑。
5.4 declared 注入(高级折叠区 + 工具提示,N-c2)
st.expander("高级:declared 注入(评测者 / 数据事实声明)")默认折叠;- 内容:三级可信源(调用参数 > 数据元数据 > declared)语义、与 Agent
自证 M1 的严格区分(G-2 纪律:Agent 上报的键永远不进 declared)、
实际注入的 declared dict(
{"sequencing": "10X_scRNA_seq"})、 两处作用(平台解析 → scrna_10x → 11 决策清单;补入上下文优先取 M1 事实); - 普通观众不细看,想懂的人能展开(Spec 轴建议落地)。
5.5 capture_chain.py(单一事实源)
- 工坊页
_golden_b_chain(现象层)与采集页勾选重算(机制层)共用capture_chain.run_chain(expected=None)——expected 可注入(勾选子集); 返回键与 N1b 现象层原实现完全一致(n_m1/m3_n_candidates/stats/added/ final_n/state/generated_at/benchmark + alignments/m3_n_uncertain 新增); - 输入路径 = 模块相对 demo/data(自包含,不依赖 cwd/sys.path);
chain_matches_benchmark四元断言(分数/verdict/决策数/补入类型)供 页面徽章与 smoke 测试共用。
6. tests/test_demo_smoke.py(N-c3)
| 测试 | 断言 |
|---|---|
test_golden_zero_diff_guard |
20 轨迹分数 + verdict + 决策数 vs 冻结基线 0 差异(紧凑版;全量逐决策明细守卫在 test_golden.py,不重复) |
test_63_7_chain_matches_benchmark |
完整链路数字断言:provenance.source == windowL_10X_B_expected.json / M1 11 条含 skip_doublet / M3 79 候选 / expected 11 决策 / stats{10,1,0,0,1} / 补入 doublet_detection·skip_doublet / final 11 / 63.7·blocked / dims{0.6375,0.8,0.85} / 与断言基准一致 |
test_63_7_interaction_contrast_unchecked_doublet |
取消勾选 → 无补入 → final 10 → 80.0·pass(机制对照) |
test_apptest_four_pages_smoke |
AppTest 四页路由(工坊/采集/评测/关于)无异常 + 采集页默认态「与断言基准一致」+ 63.7 呈现 |
test_apptest_capture_interaction |
勾选交互往返:取消 doublet → 与断言基准不一致 + 80.0;勾回 → 一致 + 63.7·blocked |
- streamlit 缺失语义:AppTest 组
pytest.importorskip——golden/63.7 断言不依赖 streamlit 恒跑;CI 已加装 demo extra,AppTest 组云上真跑; - 63.7 断言读 demo/data 副本:capture_chain 路径锚定 demo/data,provenance 保留 source=windowL_10X_B_expected.json(断言在测试内显式核验)。
7. 双轴代码审查(code-review skill,两轴独立子代理并行)
审查员 A(Standards 轴,构建质量)与审查员 B(Spec 轴,是否做了该做的) 独立运行、分开展示、不合并裁决;意见闭环如下(采纳/驳回逐条记录)。
7.1 Standards 轴 findings 与闭环
审查员 A 结论:无阻塞项;13 项重点复核全部无误(HTML 转义主体、Streamlit API 时序、capture 公共类签名、M1 去重/final-only 消费、workshop 重构等价性、 importorskip 语义、AppTest 用法、断言基准结构、数据事实、CSS、ci.yml 可行性、 chain_matches_benchmark 语义);4 建议 + 8 吹毛求疵。
| # | 严重度 | finding | 闭环决议 |
|---|---|---|---|
| S1 | 建议 | eval_verdict 三处未转义直插 unsafe_allow_html(链路⑤/断言徽章 ok 卡/取消勾选 note 卡),破坏页面「插值一律 _esc」纪律 | 采纳:三处补 _esc(...) |
| S2 | 建议 | STATUS_META 兜底分支 _label 未转义(防御路径恰是未转义路径) |
采纳:badge 插值补 _esc(_label) |
| S3 | 建议 | verdict 流转计数按终态统计 → provisional 恒显 0,与「11 provisional」叙事矛盾 | 采纳:_verdict_count 改为按 25 行原始记录 status 计数(11/13/1,与冻结锚点一致);caption 明示「计数=记录分布,逐行=终态流转」 |
| S4 | 建议 | demo/data 路径双源:data_index 两函数成死代码 + capture_chain 自持常量 | 部分采纳:capture_chain 公开 VERDICTS_PATH/EXECUTED_PATH/BENCHMARK_PATH 为链路路径单一事实源,页面 _verdict_raw_records 改走该常量;data_index 两公开函数保留(N1a 交付接口契约,N-d/N-e 可能使用),加注释说明不再被链路调用 |
| S5 | 建议 | CI demo extra 未锁定(~40 包未锁版本,未来发版可静默改变 AppTest 行为) | 部分采纳:不加 demo.lock——台账 §2.2 明示「streamlit 依赖树较大,勿并入 CI 锁」(requirements-dev.lock 注释即此理由);golden 门兜住评分漂移;ci.yml 注释已如实说明「extra 未精确锁版本,上限 <2 防 2.x 破坏 data-testid CSS 注入」;N-e 打磨期可再评估 |
| S6 | 吹毛求疵 | 恢复默认按钮 st.rerun() 冗余 |
驳回(附理由):checked 在按钮 handler 之前已计算,去掉 rerun 本轮仍渲染旧清单;rerun 必需 |
| S7 | 吹毛求疵 | CI ruff 未覆盖 demo/(且 \|\| true 吞失败) |
采纳:ci.yml ruff 行加 demo(pyproject extend-exclude 仅排除 demo/data) |
| S8 | 吹毛求疵 | golden 守卫与 test_golden 重复(紧凑版) | 说明:docstring 已注明「紧凑版,全量明细在 test_golden.py」,有意为之 |
| S9 | 吹毛求疵 | caption 硬编码「25 行原始记录(2026-08-16)」 | 采纳:行数改 len(raw_records) 动态、会话名从首条 session_id 取 |
| S10 | 吹毛求疵 | doublet_detection expected 出现 2 条(23:04 初跑 + 23:05 基准时刻),流转区 3 行未解释 | 采纳:caption 注明「窗口 M 重跑两次留 2 条记录,逐行忠实呈现」 |
| S11 | 吹毛求疵 | DECLARED: dict 注解过宽 |
采纳:改 dict[str, str] |
| S12 | 吹毛求疵 | use_container_width 新版弃用(width=”stretch” 取代) |
说明:沿用工坊页既有模式(全站一致);1.60 实测无警告;N-e 打磨期统一迁移 |
| S13 | 吹毛求疵 | 黄金对照 A 查找失败静默显示 “?” | 说明:防御路径;当前数据必有 A(80.0 pass 已核实) |
7.2 Spec 轴 findings 与闭环
审查员 B 结论:关键数字独立重算 7/7 一致(M1 11 / M3 79 / expected 11 / stats{10,1,0,0,1} / final 11 / 63.7·blocked / 80.0 对照);验收项 1-3 通过, 4-7 部分通过(推前时点 CI 未验 + 报告占位)——以下闭环后全部落实。
| # | 严重度 | finding | 闭环决议 |
|---|---|---|---|
| F1 | 高 | CI 云上绿未达成且报告虚标 ✅(run ID 占位、变更未推送) | 采纳:push 后回填真实 run ID(双矩阵 + Pages),云上绿后再定稿(见 §8.1) |
| F2 | 中 | verdict 流转统计条 provisional 显 0,与冻结锚点 11 矛盾 | 采纳:同 Standards S3(记录级计数 11/13/1) |
| F3 | 中 | code-review 双轴审查未落盘(报告占位) | 采纳:本节(7.1/7.2)即闭环记录,随报告提交 |
| F4 | 低 | design-taste-frontend 应用证据缺失 | 采纳:报告补 §4.2 design-taste 自查 |
| F5 | 低 | 「三页冒烟」vs 实现四页 | 说明:四页 ⊇ 三页(超集),execution-plan 亦记「四页冒烟」;验收记录以此为准 |
| F6 | 低 | M1 报告「未验证 1」与断言基准「unverified 0」冲突 | 说明:M1 §3.2 的「未验证 1」为中间态(当时清单含 api_data_integrity,后移除);N-c 链路与断言基准一致(unverified 0)。M 窗口报告勘误已提示,不属本窗口变更面 |
| F7 | 吹毛求疵 | .vis_shot/ 空目录残留 | 采纳:已删除(git 不跟踪空目录) |
| F8 | 吹毛求疵 | ci.yml 注释「效果等同锁定上限 <2」措辞过强 | 采纳:改述为「未精确锁版本,上限 <2 防 2.x」 |
7.3 闭环后最终验证
- ruff check demo/ tests/test_demo_smoke.py → 0 错误
- pytest 274 passed(含 smoke 5 项)
- AppTest 全量回归(四页冒烟 + 采集页勾选交互往返)
- Playwright 最终浏览器验证:统计条 provisional 11 / final 13 / revoked 1 (与冻结锚点一致)、对齐表 11 行 / 流转 14 行 / 勾选框 11、取消 → 80.0 + 不一致徽章、恢复 → 63.7 + 一致徽章、双宽度 0 溢出
8. 工程纪律核对
- golden 0 差异:
bio-audit golden --json→n_diffs = 0(137 决策) - pytest 全绿:274 passed(134.9s,269 存量 + 5 新增 smoke)
- ruff:demo/ + tests/test_demo_smoke.py 0 错误
- 零改动:src/、tests/(test_demo_smoke.py 除外)、ui/、demo/data/ 未触碰(git status 仅上述交付文件)
- 推送纪律:只 add demo/(capture_chain.py + 02_capture.py + 01_workshop.py + theme.css)+ tests/test_demo_smoke.py + ci.yml + docs/migration/(N1c 报告 + index.md),严禁 git add -A; push 前三查见 §8.2
- CI 云上绿:见 §8.1
8.1 CI 云上结果
- run
32265897647(push 361c262)success:双矩阵pytest+golden (Python 3.12, 4m8s)+pytest+golden (Python 3.10, 4m46s)均绿——含新增 test_demo_smoke 5 项(demo extra 加装后 streamlit 云上可用;3.12 job 实测 274 passed, 与本地同数 = smoke 真跑未 skip);golden replay 137 决策 0 diff; 本体/规则/benchmark/reward 闸门 + scrna_r0 锚定不变;ruff 含 demo/(非门禁) - Pages build
32265895283随 push 触发 success(22s;docs 站重建, index.md 登记 N1c)
8.2 push 前三查
git status干净(无预期外文件;.vis_shot 等临时文件已清理)git log origin/main..HEAD仅 1 commitgit ls-files demo/ tests/无大文件(demo/data 未变,最大仍 38.8KB verdicts)
9. 遗留与说明(给后续子窗口)
- 63.7 复现数字(本窗口实测锁定):M1 重建 11 条 / M3 解析 79 候选 (未定 7)/ expected 11 决策 / stats{consistent 10, false_positive 1, false_negative 0, unverified 0, expected_added 1} / final 11 → 63.7 · blocked(dims:data_handling 0.6375 / method_selection 0.8 / statistical_rigor 0.85)== 断言基准;取消勾选 doublet_detection → 80.0 · pass(与黄金对照 A 同分,机制对照)。
- 交互重算 vs 快照一致性:交互重算(勾选全选)与 demo/data 提炼快照 (windowL_10X_B_expected.json)数字完全一致——两者同源(同一 demo/data 副本 + 同一 capture 公共类链路),页面实时比对徽章 ✓;快照模式 (设计 §6 注「演示现场可用提炼快照直接展示」)由断言基准副本承担, 交互模式 = 增强展示,两模式数字一致(验收会独立重算)。
- 现象层/机制层分工:工坊页 = 现象(点按钮看结果);本页 = 机制 (勾选清单实时重算、看中间产物)。两处共用 capture_chain 单一事实源, 数字一致(smoke 测试与独立重算双重守卫)。
- execution-plan 打勾:§六.十八 N-c 8-10 已勾(仓库外文档,不随仓库 push)。
- 台账状态表(demo-n-window-ledger.md §1):N-c ⏳ → ✅ 由 demo 设计 中枢验收后更新。
- CI streamlit 依赖收口:ci.yml install 步骤加装
pip install -e ".[demo]"(streamlit>=1.33,<2 由 pyproject 锁定);streamlit 依赖树较大不并入 requirements 锁(requirements-dev.lock 注释同款理由),以 extra 加装。 - 「三页冒烟」口径:台账 §10.1 写「AppTest 三页冒烟」,实现为四页 (工坊/采集/评测/关于)——超集满足(execution-plan N-c 10 亦记「四页冒烟」), 验收记录以四页为准。
- M1 报告「未验证 1」口径提示:M1 §3.2 的「未验证 1」为窗口 M 中间态 (当时 expected 清单含 api_data_integrity,后移除,L1 §4.3.1);N-c 链路 与断言基准一致(unverified 0)。M 窗口报告如需勘误由审计中枢裁定,不属 本窗口变更面。
- use_container_width 弃用:沿用工坊页既有模式(全站一致),1.60 实测 无警告;N-e 打磨期可统一迁移 width=”stretch”。