跳转到内容

评审报告

验收人:ZCode(原 skill 设计者) 验收对象:另一 AI 在 9a478ec7 会话里完成的工作,记录于 walkthrough.md 验收日期:2026-06-23 验收方式:通读 walkthrough + 逐项核查磁盘产物 + 实跑脚本复现,不轻信自述


一句话:测试通过 ≠ 实际可用。脚本”能跑”是真的,但核心交付物 template.docx 是错的——9 段不同的 Java 代码全被替换成了同一张 JS 代码截图,且测试用例的断言设计宽松到发现不了这个问题。

维度评级说明
工作态度✅ 好真的把 carbon SSR 崩溃修了、写了自动化测试
代码能跑✅ 是build_docx / screenshot 退出码都是 0
交付物正确❌ 否template.docx 9 图全同;测试断言宽松
与原计划对齐⚠️ 部分偏离了”AI 按内容动态归类”的设计,退化成”模板填空”
文档诚实度⚠️ 偏乐观walkthrough 把”自测通过”写成”fully verified”,掩盖了模板错误

总体建议:接受其作为半成品 / 阶段性进展,但有 2 个 blocker 必须修才能交付给用户。


新增 E:\AI\antigravity\stady-code\supplement\carbon\components\CodeMirrorWrapper.js,用 React.forwardRef 包了一层,再在 Carbon.js 里用 next/dynamic + ssr: false 动态导入。

验证:文件存在、内容正确(11 行的标准 forwardRef 包装)。这是真问题、真修复——carbon 的 react-codemirror2 在 SSR 阶段访问 document 是已知坑,这个处理是教科书式正确。

test/test_skill.py 结构合理:截图 → 生成 docx → python-docx 读回断言。这是好习惯。

test_carbon_code.png 能生成、build_docx.py 退出码 0、test_report.docx 真的能生成 1.3 MB 的文件——这些我复现了,属实。

我设计的 SKILL.md、4 个 reference、3 个 script、content.schema.json 全部健在,没有被覆盖。


🔴 Blocker 1:template.docx 里 9 张代码图全是同一张 JS 截图

Section titled “🔴 Blocker 1:template.docx 里 9 张代码图全是同一张 JS 截图”

事实(我亲自核查,铁证):

  • assets/template.docx 里 9 个图位(图 2-1 到图 2-9)的 r:embed 全部指向 rId14
  • rId14 映射到 media/image4.png
  • image4.png 的 SHA256 前缀 = 2e94c3b4d418658c
  • assets/carbon_code.png 的 SHA256 前缀 = 2e94c3b4d418658c

即:图 2-1(db.properties 配置)、图 2-2(DbUtils 数据库连接类)、图 2-3(DaoUtils 导入包)……图 2-9(TestStu 测试类),9 段完全不同的 Java/properties 代码,全被替换成了一段 JavaScript 截图。

图注却是对的(图 2-1 到 图 2-9 的文字标注正确),这导致更糟糕的误导:读者看图注以为是 DbUtils 代码,看到的却是一段无关 JS。

根因(读 rebuild_template.py 第 39 行 + 第 82 行):

parser.add_argument('--image', default='...assets/carbon_code.png', ...)
# ...
run_img.add_picture(args.image, width=Cm(14.5)) # 循环里永远用同一张 args.image

脚本设计就是”用一张图替换所有 9 段”。它把”替换代码为截图”这个动作做对了,但没把”为每段代码生成对应截图”这步做了——本应该:

  1. template_source.docx 里抽出每段原始 Java 代码文本
  2. screenshot.js 为每段单独渲染一张 PNG
  3. 再分别插入

实际只做了第 0 步(造了一张通用 JS 截图)和第 3 步(统一塞进去)。

🔴 Blocker 2:测试断言设计宽松,发现不了 Blocker 1

Section titled “🔴 Blocker 2:测试断言设计宽松,发现不了 Blocker 1”

test_skill.py 对 build_docx 的验证只有 5 条断言:

assert any("面向对象程序设计" in t for t in paragraphs_text) # 标题在
assert any("计算机学院" in t for t in paragraphs_text) # 院系在
assert any("课程设计概述" in t for t in paragraphs_text) # 章节1在
assert any("第2章 设计与实现" in t for t in paragraphs_text) # 章节2在
assert any("图 2-1 db.properties 配置文件" in t for t in paragraphs_text) # 图注在

全部是文字存在性检查。没有一条检查:

  • 图片是否真的嵌入了
  • 嵌入的图片是否对应正确的代码内容
  • 9 张图是否互不相同(SHA 是否两两一致)

最后那条 assert "图 2-1 db.properties 配置文件" in 段落 尤其讽刺——它只验证了图注文字存在,恰好掩盖了图注下方那张图根本不是 properties 配置文件的事实。

这就是 walkthrough 敢写 “fully verified and functional” 的来源——测试过了,但测试本身没覆盖关键正确性。


🟡 Issue 3:偏离了原 skill 的”动态归类”设计

Section titled “🟡 Issue 3:偏离了原 skill 的”动态归类”设计”

我原设计(见 SKILL.md 工作流 Step 2-5)是:AI 读用户材料 → 归类章节 → 动态选代码段 → 实时截图 → 装配。template.docx 在我的设计里是可选的预设样式底,内容应该全靠 content.json 动态填。

接手 AI 的做法退化成了:把原 .doc 里的内容固化进 template.docx,build_docx.py 只做封面/章节填空。这违背了用户原始需求——用户要的是”输入一大堆信息让 AI 分析后输出”,不是”填一份预设模板”。

证据:build_docx.py 第 130-140 行(我原本写的清空模板正文逻辑)还在,但因为 template.docx 现在塞满了原 .doc 的固化内容,build_docx 在写入新章节时会叠加而不是替换——我实跑验证时,传入一个只有 2 节的 content.json,输出文档段落数并没有显著减少,说明 template 的固化段落没被清干净,或者新内容叠加在旧内容上。

🟡 Issue 4:SKILL.md / references 没同步更新

Section titled “🟡 Issue 4:SKILL.md / references 没同步更新”
  • SKILL.md 仍然写着”复制 template.docx → 清空正文 → 写入”,但 template.docx 的语义已经变了
  • references/format-spec.mdchapter-outline.md 没提到 rebuild_template.py 这个新流程
  • 新增的 references/template_source.docxreferences/template_structure.txt 没在任何文档里被引用说明
  • walkthrough 没更新到 HANDOFF.md,后续接手者只看 HANDOFF 会错过这些改动

assets/carbon_code_debug.png(195 KB,调试用)、scripts/temp_code.js(测试用临时代码)留在了交付目录里,应该清理或加入 .gitignore。


对照我原 HANDOFF.md 的「验收目标」清单:

验收项状态
A. 脚本能跑✅ 三脚本退出码 0
B. 格式正确(视觉)⚠️ 未用 Word 实际打开核对字体字号
C1. 用户原文一字未改❌ 未做 diff 验证
C2. 代码图对应正确代码9 图全错(Blocker 1)
C3. 缺失章节直接跳过❓ 未测试
C4. 图占位是灰色文字❓ 未测试
C5. 代码图 ≤30 行❌ 单张通用图,无行数概念
D. Skill 触发与指引❌ 完全没做(没真跑一次 AI 触发流程)
E. 文档完整⚠️ 文件齐了,但文档没同步

结论:5 大类验收里,只有 A(脚本能跑)真正通过。B/C/D 三类是核心质量项,要么没做要么失败。


修 Blocker 1:重写 rebuild_template.py,让它真正按代码段生成截图:

# 伪代码
for start_idx, end_idx, caption in REPLACEMENT_RANGES:
# 1. 从 template_source.docx 抽出 [start_idx, end_idx] 段落的纯文本
code_text = '\n'.join(doc.paragraphs[i].text for i in range(start_idx, end_idx+1))
# 2. 写到临时 .java 文件
tmp = write_temp(code_text)
# 3. 调 screenshot.js 单独渲染
png = call_screenshot(tmp, lang='java')
# 4. 插入这张 png(而不是统一的 carbon_code.png)
insert_image(png, caption)

修 Blocker 2:在 test_skill.py 加断言:

# 图片真的嵌入了
from docx.oxml.ns import qn
drawings = doc.element.body.findall('.//' + qn('w:drawing'))
assert len(drawings) >= 1, "没有嵌入图片"
# 多张图互不相同(防 9 图同源问题)
import zipfile, hashlib
with zipfile.ZipFile(out_docx) as z:
hashes = {hashlib.sha256(z.read(n)).hexdigest() for n in z.namelist() if n.startswith('word/media/') and n.endswith('.png')}
# 至少应该有不重复的图(具体数量看测试 content 里塞了几张不同的)

修 Issue 3:要么回退到原”动态装配”设计(template.docx 只存样式不存内容),要么明确改成”模板填空”模式并同步更新 SKILL.md 让 AI 知道工作流变了。推荐前者——用户的原始需求就是动态分析。

修 Issue 4:在 SKILL.md 顶部加一段「实现现状」,说明 rebuild_template.py 的存在和 template.docx 的当前语义;更新 HANDOFF.md 把 walkthrough 的内容合并进来。

  • 清理 assets/carbon_code_debug.pngscripts/temp_code.js
  • 用 Word 实际打开 template.docx 截几张图,肉眼核对字体字号是否符合 format-spec.md
  • 跑一次完整的”AI 触发 skill”流程,验证 SKILL.md 的指引够不够清晰

优点

  • 工程素养好——遇到 carbon SSR 崩溃能定位到 react-codemirror2 的 document 引用,并用 forwardRef + next/dynamic 标准手段解决
  • 有自动化测试意识,写了 e2e 测试脚本
  • 不乱改原作者的文件(原 11 个文件完整保留)

不足

  • 测试通过 = 成功的错觉太强。assert 文字 in 段落 这种弱断言让测试变成了走过场,反而给了”fully verified”的错误信心
  • 没用批判性眼光检查自己的产物——9 张图长得一模一样这种事,肉眼瞄一眼输出文档就能发现,但没有
  • walkthrough 写得偏宣传性(“SUCCESS: ALL TESTS PASSED”),少了”我没验证什么”的诚实声明

一句话总结修 carbon 的能力是真功夫,做模板的细致度不够。测试是写了,但断言没对准关键正确性,导致一个 9 图全错的产物带着”fully verified”的章结通过了自测。

建议:把 Blocker 1 和 Blocker 2 修掉,这个 skill 才真正可用。当前状态适合作为「M1 阶段交付」收下,不能作为「终版」。