1实现原理 · 为什么它能做到
两条流水线共享同一终点外观与同一哲学:脚本只干执行,agent 保留两个不可自动化的判断——按内容排序页面、整档验证。
**Division of labor**: scripts carry execution; you (the agent) carry the two judgment steps — content-based page ordering, and whole-document verification. Neither can be automated away: filenames lie about order, and per-page spot checks miss wrong-slot bugs.
透视矫正与白平衡用自研 OpenCV 脚本:photo_to_scan.py 找最大亮斑四边形 warp 到 A4(200dpi),--raw 模式只矫正;默认模式多做『除以纸色背景』白平衡给彩纸页预洗。EXIF 旋转由 PIL exif_transpose 先修(cv2.imread 忽略 EXIF)。
The script handles EXIF rotation internally (`cv2.imread` ignores EXIF; phone photos come rotated — this silently produces sideways pages if you rectify with raw OpenCV).
『扫描感』由 noteshrink(uvx 外部工具)量化调色板实现:白纸批量一次 -w -g -K 全局调色板统一墨/章色,-c "true" 跳过其内部 PDF 步骤由本 skill 自组装。
uvx noteshrink -w -g -K -q -b ns -c "true" page_03.jpg page_01.jpg page_07.jpg ...
A4 组装带边缘裁剪:assemble_pdf.py 每页先裁 24px 顶/12px 侧(200dpi)去除矫正拖入的桌面边条,img2pdf 直接嵌调色板 PNG 不重编码,输出 ~0.05MB/页。
Edge crop (default 24px top / 12px sides at 200 dpi) removes the sliver of desk surface that rectification drags in along page borders; document margins dwarf it.
验证纪律是『全档 contact sheet 必读』:make_contact_sheet.py 出一张总览图,agent 逐页核对顺序/色偏/印章签名,再抽查 1-2 页全分辨率锐度。
**"I verified the pages I changed" is not verification.**
数字签名分支(digital-signature-synthesis.md)用 synthesize_signature.py 五子命令完成:fonts/candidates/generate/locate/composite/scanify,字体必须经 candidates 页给用户挑(agent 不得自选),--seed 保证可复现。
**Send the candidates sheet to the user and get a number back — do not pick one yourself.** Which style reads as a plausible signature is a taste call, not something derivable from the document or the font's technical properties.
合成签名的定位靠 pdftotext -bbox 找签名行标签,并内建防错机制:标签与下划线被合并成一个 word 时会打 WARNING 并指导用像素扫描右缘,避免签名浮空。
This means `pdftotext` tokenized your label together with whatever sits right after it on the same line — most commonly a signature blank authored as underscores immediately following the label with no space (`簽名:_____`, an entirely ordinary way to type this in Word).
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| cli | uvx noteshrink(扫描感增强,PEP 723 首跑 ~30s 构建) |
| cli | poppler pdftoppm / pdftotext(contact sheet / -bbox 定位) |
| package | opencv-python-headless / numpy / pillow / img2pdf(PEP 723 内联依赖) |
| cli | LibreOffice soffice(签名分支把 docx 渲染成页图) |
| cli | fc-list(fontconfig,发现手写体字体) |
4风险提醒 风险提醒:黄色 · 留意使用
- 合成签名+扫描做旧可被用于伪造文件外观(核心风险) — 产出物与真实签署扫描件难以区分,用于合同/确认单/授权书可误导接收方。skill 不设用途闸门,宿主/用户需自担授权与告知义务;仅应在确有签署权或明确演示用途时使用。
- 判断步骤依赖 agent 眼力 — 内容排序、纸色判定、整档核查与合成效果目检都是人/模型判断;低质量模型可能跳过或走马观花,需宿主监督。
- 环境依赖面 — 需要 poppler/soffice/noteshrink(uvx 联网首装)/fc-list 与手写体 CJK 字体(macOS 有、Linux 需自装)。
- 无删除面但会覆盖输出 — 输出路径由用户给;assemble 的工作目录中间件 _pdfpage_*.png 会留在输入旁(--work-dir 可改)。
5第二遍独立确认
- [ok] 主流水线 rectify→noteshrink→assemble→contact sheet — 四个环节命令与脚本均在;photo_to_scan.py --raw 与默认白平衡模式分支存在。
- [ok] EXIF/quad/白平衡实现 — load_exif_corrected 用 ImageOps.exif_transpose;find_page_quad/warp_a4/flatten_whitebalance 函数在 photo_to_scan.py 源码可定位。
- [ok] 边缘裁剪默认值 24/12px — assemble_pdf.py argparse default crop_top=24/crop_side=12 与 SKILL 一致。
- [ok] noteshrink 参数 -w -g -K -c "true" — SKILL 命令与外部工具语义一致(noteshrink 为 uvx 外部包,未在本仓捆绑,命令调用方式可核)。
- [ok] 『只查改动页不算验证』纪律 — SKILL 原文 + 两个 shipped-bug 叙事(错槽覆盖邻页、调色板污染)在 Step 5。
- [ok] 签名分支六子命令 — synthesize_signature.py subparsers fonts/candidates/generate/locate/composite/scanify 均实现;candidates→用户挑选→generate 流程与 reference 一致。
- [ok] 候选人选门禁(agent 不自选字体) — reference 原文 'do not pick one yourself';脚本 generate 需 --font/--face/--ink 显式参数。
- [ok] 无网络/凭证/删除面 — 全脚本扫描零网络代码、零 env 密钥读取;无删除用户文件逻辑;子进程均列表参数。
6结论
0e8f936e0a123f3a…d5c4678cb5