context-infra 检查与复盘infra.guiming.net · 全内容自包含呈现 · 生成于 2026-07-21 16:28 UTC

Final Report · 工程走查(HTML)最佳实践

Z3 全文↑ Z2 条目

术-格式 · 术层 skill 全文

← 返回术层 skill 索引 · 返回方法论区

本页是 <code>rules/skills/bestpractice_final_report.md</code> 的逐字投影(仅隐私清洗,零改写)。

时点提示:本页是仓内文件 rules/skills/bestpractice_final_report.md 的逐字投影(仅做隐私清洗:仓库根绝对路径→相对路径、家目录→~/;除此零改写)。若源文件后续有修订,以仓内真源为准。

Final Report · 工程走查(HTML)最佳实践

元数据

在报告写作矩阵中的位置

本 skill 是报告写作矩阵里的「实现 / 走查报告 × HTML 格式」格:管 HTML 渲染(视觉、注释交互、图表、dark mode)和工程走查的内容结构(6 字段、测试 6 维、修改记录分图)。通用的易读性判断(完整记录变化、look-back 真实过程记录、降噪)以 bestpractice_report_readability 为准,本 skill 不重复,写报告时两者叠加。调研 / survey 报告的内容组织走 workflow_analytical_writing。矩阵全图见 workflow_report_writing_matrix

这个 skill 解决什么问题

用户反复反馈 agent 交付的工程报告有六类典型病:

  1. 写得"对"但读不懂——大段散文堆叠、没有视觉层次、关键数字埋在中段
  2. 假定读者已懂背景——专有名词不解释、缩写直接使用
  3. 测试章节过于简略——只说"通过 N 个 case",不讲怎么测、是不是「画靶射箭」
  4. 报喜不报忧——隐藏 oracle drift、修测试让 case 过、空转轮次等"难看真相"
  5. 注释/弹窗遮挡原文——center modal + backdrop blur 让阅读体验崩坏
  6. MD 交付——视觉表现力不够,关键对比和数据无法清晰可视化

目标

让一个完全不懂这个项目背景的人能在 5-20 分钟内:

  1. 看懂「这是什么、解决什么问题、怎么解决」(实现)
  2. 看懂「测试是怎么做的、结果如何、可信吗」(测试)
  3. 看到诚实的局限声明(不是营销文)
  4. 如果有修改/迭代历史:看懂改了什么、为什么改、谁推动改

作为 Loop 收束 Renderer

workflow_controller_loop 选择 task_looprecoverable_overlay 时,本 skill 负责把 Loop evidence 组织成可读 HTML;Controller 仍负责决定是否完成、是否转向、closure verdict 和 claim ceiling。

Loop 收束报告默认路径是:

<loop_home>/reports/FINAL_REPORT.html

报告必须覆盖:

本 skill 不反向裁决 Loop 是否完成;如果 HTML 报告内容与 CONTROL.mdPHASES.md 或 effect review 冲突,先回 Controller 修正状态,再重新生成报告。

收口注册义务:报告附 T-id 清单 + 注册回执(2026-07-06 W5-C / T1138 增)

Loop 收束报告同时是一次 run 的注册账本,不止写给读者看。收尾时报告必须额外覆盖两件事,否则 final_report phase 过不了 check_closeout_registration gate:

这条义务由确定层 gate 机械兜底:final_report phase 的 exit 加 gate_pass:check_closeout_registration:<报告路径>,gate(tools/rr4_capture/closeout_predicate.py)读 contexts/todo/logs/todo_events.jsonl 核对本 session 是否真有 todo_added 事件,bare 回执行不单独放行,防自报造假。规则真源在道层 workflow_phase_framework.md「收口义务」段(DP-TODO-4 / Q22 / R9-21)。

核心立场

「面向小白」≠「内容简单」。 用户原话:「面向小白,并不是说内容简单就好了……针对具体的实现方式和实现细节,你需要从简单的层面出发,并且精炼地给出一个完整的说明」(contexts/daily_records/claude/2026-05-17.md:6391)。

具体含义:不要回避细节、不要简化掉真实代码、不要把组件用一句话带过。精炼但完整、侧重内容而非形式。每个细节用「真实代码 + 输入输出 + 类比」三件套讲透。

验收标准

S1 · 实现说明的「6 字段」完整性

报告里描述的每个核心组件/模块必须含全部 6 个字段:

#字段检查方法
1一句话本质它到底是 class / function / JSON 文件 / 数据结构?一句话定性
2关键代码5-15 行真实代码(不是伪代码),带 path:line 引用
3输入 → 输出调用时传入什么、返回 / 写入什么
4调用关系谁调用它(caller),它调用谁(callee)。具体函数名
5没有它会怎样拆掉这个组件后系统会退化成什么。反向论证
6小白能秒懂的一句话去掉所有术语用日常类比讲清楚

第 6 项是用户最在意、agent 最容易忽略的字段。 自检方法:把组件名以外的所有英文/项目专有名词全去掉,剩下的中文能让一个外行点头吗?

S2 · 测试章节的 6 维度覆盖

测试章节必须包含全部 6 个维度,缺一不可:

S3 · 诚实自评章节存在且充实

独立成节描述"难看的真相"(如果存在):

报喜不报忧 = skill 验收失败。 用户原话:「他的测试很多时候还是在『画靶射箭』……如果你去检查,肯定会得到一个『AAU improved』的结果,这显然是不对的」(2026-05-17.md:20015-20019)。

S4 · 注释/术语交互的「不挡原文」硬约束

用户最严厉强调的硬要求:「不管用什么样的方式,都要让我能同时查看到原文以及注释」(2026-05-17.md:7467)。

满足以下全部条件:

可接受方案(按推荐顺序):

  1. 推挤式 panel(首选):panel 浮出时主区 width: calc(100% - 320px) 缩窄;panel 用 transform: translateX(0) 滑入右侧
  2. inline 展开(紧贴术语下方)
  3. hover popover 紧贴(不遮挡上下文)
  4. 底部信息条(mobile 友好)

反例(绝对禁止):center modal + 黑色 backdrop + backdrop-filter: blur(3px)

S5 · 卡点由「无上下文 LLM」识别,且不限于术语

作者不能自己挑要解释的术语——作者太懂了,会漏掉真正卡的地方。

派一个完全不懂项目背景的 sub-agent 通读初稿,按它真实卡住的地方挑出 20-30 个。sub-agent prompt 里明确禁止它

卡点不限于术语(用户原话:2026-05-17.md:6931-6934)。要覆盖四类:

Type含义例子
A术语没解释"AAU" "oracle" "evaluator"
B代词指代不明"它" "这个" "该 agent"
C概念介绍不充分第一次出现的概念只说了用法没说本质
D假定背景知识"类似 ReAct 那样" 但读者不懂 ReAct

每个卡点输出:quote / section / type / min_explain(一句话定义 + 一个日常类比,≤ 50 字)。

模板见 §附录 1。

S6 · 视觉密度

S7 · 交付形态

S8 · 修改记录章节(如果报告需要涵盖迭代历史)

如果报告需要讲"改了什么",必须满足:

S9 · 可访问性 + 移动端

输出规格

默认输出

<相关项目目录>/walkthrough_reports_<YYYYMMDD>/final_report.html

单文件、自包含、零外部依赖。约 50-120 KB。

交付 HTML 报告前必须跑 FR-15 hygiene gate:

python3 tools/report_scaffold/check_report_completeness.py --report <相关项目目录>/walkthrough_reports_<YYYYMMDD>/final_report.html --html-hygiene-only

该 gate 防三类失格:直接把 raw Markdown 塞进 HTML、Markdown 语法在 HTML 正文中未渲染、引用 Markdown-derived 材料时没有 excerpt/summary 上下文。

特例:如内容真的多到必须分维度讲(且每份内容相互独立 ≥ 70%),可用:

<相关项目目录>/walkthrough_reports_<YYYYMMDD>/
├── final_report.html            # 主入口(叙事版 + KPI + 详细报告卡片入口)
├── implementation_detail.html   # 详细实现
├── modifications_detail.html    # 详细修改记录
└── testing_detail.html          # 详细测试真实性

反例(用户曾否决):三份报告 70% 内容重叠 → 「读者无法快速区分『哪份回答什么问题』」。每份开头只放该报告独有的一句话答案 + KPI,背景说明只在 final_report.html 入口出现一次。

推荐技术栈(实战胜出方案)

零外部依赖单文件 HTML 为默认:双击即开、不依赖 CDN、无渲染失败风险、文件体积可控。

只在确有必要时引外部库

是否引入理由
Mermaid谨慎仅在 SVG/CSS 表达不了的复杂流程图时;否则 CSS Grid + arrow 够用
Chart.js / ECharts不引CSS flex 柱状图、SVG 饼图、CSS 时间线都能搞定
GSAP / SplitType不引拆字符 + background-clip:text 在 dark mode 会失败(见 §已知陷阱 T1)
Lenis可选浏览器原生 scroll-behavior:smooth 通常够用
tsParticles / Vanta不引喧宾夺主
backdrop-blur 弹窗框架绝对不引遮挡原文,违反 S4
文字流动 / 流光效果可选用户欢迎但不能为炫技牺牲可读性——尤其要避免 hero 渐变拆字组合

主题切换 = CSS variables + data-theme 属性 + matchMedia listener。

颜色按语义命名(不按色相):

:root[data-theme="dark"] {
  --bg-primary: #080810;
  --accent-aau: #f59e0b;            /* 主角色 */
  --accent-baseline: #22d3ee;       /* 对照色 */
  --accent-success: #4ade80;
  --accent-warning: #fbbf24;
  --accent-danger: #f87171;
}

推挤式注释面板

.page-wrapper.annotated {
  transform: translateX(-160px);
  width: calc(100% - 320px);
  transition: transform .3s, width .3s;
}
.anno-panel {
  position: fixed; right: 0; top: 0; bottom: 0;
  width: 320px;
  transform: translateX(100%);
  transition: transform .3s;
}
.anno-panel.active { transform: translateX(0); }

@media (max-width: 640px) {
  /* 移动端改为底部抽屉,禁推挤 */
  .page-wrapper.annotated { transform: none; width: 100%; }
  .anno-panel {
    top: auto; right: 0; left: 0; bottom: 0;
    width: 100%; height: 70vh;
    transform: translateY(100%);
  }
  .anno-panel.active { transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .page-wrapper, .anno-panel { transition: none; }
}

自动术语扫描autoTagTerms()):

参考实现:adhoc_jobs/atomic_agent_unit_20260509/second_generation_implementation_20260511/walkthrough_reports_20260516/kimi_version/index.html:1850-1910

内容生产流程(多 sub-agent 协作)

由主 agent(Opus)协调,sub-agent 分工:

关于 sub-agent 模型选择:见 bestpractice_multi_agent_analysis.md

已知陷阱(实战踩坑记录)

T1 · hero 渐变文字在 dark mode 黑屏

现象:用 splitType 或自写代码拆 hero 标题成字符 span 做 stagger 动画,配合 .accent-text { background: linear-gradient; -webkit-background-clip: text; -webkit-text-fill-color: transparent } 做流光。拆出来的子 .char span 不继承父元素 background,dark 背景下变透明黑块。

应对:要么不拆 .accent-text 整体保留一个 span 参与 stagger;要么给每个 char 都 inline 写一份 background-image。最稳:避免渐变拆字这种组合。

T2 · * universal selector 覆盖 padding

现象:* { padding: 0 } 经常压过后定义的 body.term-panel-open { padding-right: 320px },导致 body padding 推挤布局失效。

应对:用 width + transform 推挤法(Kimi 实测胜出方案)替代 body padding:给 .page-wrapper.annotatedwidth: calc(100% - 320px),更可靠。

T3 · JS 字符串内嵌中文引号 ASCII 闭合

现象:在中文 string literal 里写 "...就像"老师觉得你对"...",ASCII " 当作字符串结束符,syntax error。

应对:内嵌引用用中文「直角引号」「」『』,或转义 \"做完一定要 node --check 跑一遍

T4 · osascript Chrome 跨上下文 globals 不可读

现象:用 osascript execute javascript 验证页面状态时,读不到 inline <script> 设置的 window.someGlobal(osascript 在 isolated world,main world globals 不可见)。

应对:验证 JS 是否跑通时看 DOM 变化(.term 数量、body.className、computed style),不要依赖 window.* 自定义全局。

T5 · osascript Chrome 多 tab 时 active tab 错位

现象:用户切走了 tab,测试 javascript 跑在了错误的页面上。

应对:用 open file://... 命令强制目标网页拉到前台,或明确遍历 tabs 找到目标 URL 设 active tab index。

T6 · sub-agent 带太多背景挑卡点不准

现象:派的 sub-agent 如果不小心读了项目其他文件、用预训练知识"代入",挑出来的卡点跟作者自挑差不多——只有真正陌生的术语会被挑出来。

应对:sub-agent prompt 里明确禁止:「不要读其他项目文件补背景」/「不要用预训练知识脑补」/「假装你完全不懂,老实承认『我读到这里卡住了』」。模板见 §附录 1。

T7 · 分多份报告时 70% 重叠

现象:写"实现 / 修改 / 测试"三份时,每份开头都重述项目背景 + 总结,最后内容 70% 重叠。

应对:用户原话:「读者无法快速区分『哪个报告回答什么问题』」。每份开头只放该报告独有的一句话答案 + KPI,背景说明只在 final_report.html 入口出现一次。

T8 · 把 MD 原文直接塞进 HTML

现象:展示文档历史 / 变化时图省事,把整段 Markdown 源文本直接 inject 进 HTML,既不摘录也不转 HTML 结构。结果 MD 语法(#-、表格、代码围栏)在 HTML 里不渲染,显示成一坨带井号星号的纯文本,可读性崩坏。

应对:不直接塞 MD 原文。要么摘录关键片段再用 HTML 原生结构(<h><ul><table><pre>)重排,要么把要展示的 MD 片段先做一次 MD→HTML 转换(见 bestpractice_markdown_html_conversion)再嵌入。展示变化时只摘变化的关键行,不整段倾倒。

反例(绝对不要做的)

来自用户多次明确否决:

验收清单(完成后逐项打勾)

历史出处(用户原话证据)

参考实现

附录 1 · 「无上下文小白」sub-agent prompt 模板

## 你的角色
你是一个完全不了解 <项目名> 的工程师。今天第一次打开一个 HTML 网页阅读。你不知道项目背景、专有名词、内部缩写。

## 重要原则
**不要**读其他项目文件补背景。**不要**用预训练知识脑补"作者大概想说……"。
你要做的恰恰相反:假装自己一无所知,老实承认"我读到这里卡住了"。

## 任务
读 <HTML 文件路径>。只读 <body> 里 §1 到 §N 的内容,不读 CSS/JS。按顺序阅读,每次卡住就记一条:

- type: A=术语没解释 / B=代词指代不明 / C=概念介绍不充分 / D=假定背景知识
- quote: 原文短引(10-25 字,能让你定位回原文)
- section: 哪一节
- context_question: 你当时卡在哪里(一句话)
- min_explain: 一句话定义 + 一个日常类比(≤ 50 字)

## 重要原则
- 诚实:读着读着前文已经解释了就不要标记,只标真正读到尾还不明白的
- 不要完美主义:列 20-30 个最关键的就够
- 重复出现的同一术语只标第一次
- 输出 JSON 数组

附录 2 · 实现说明的 6 字段示例模板

### Component 1: Requirement Anchor

**1. 一句话本质**:一个 JSON 文件,存放任务最初的「需求单」,作为不可变参考点。

**2. 关键代码**(unit.py:13-19):

def create_requirement_anchor(path, data, ledger=None):
target = Path(path)
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(json.dumps(data, ensure_ascii=False, indent=2))
if ledger:
ledger.append(actor="aau", phase="intake",
event_type="anchor_created", object_ref=str(target))
return target


**3. 输入 → 输出**:dict(题目 + requirements + 约束)→ 写盘的 JSON + 在 ledger 记 anchor_created 事件

**4. 调用关系**:初始化脚本调用 → 调用 `EventLedger.append()`

**5. 没有它会怎样**:worker 会在执行中悄悄重述需求、丢字段;oracle 找不到「最初题目是什么」的不可变锚定

**6. 小白能秒懂**:就像考前先拍下来的「考卷照片」——保证没人偷改题目,所有人据此判分

← 返回术层 skill 索引 · 返回方法论区