| name | doc-atlas |
| description | Turn one or more documents (PDF / Word / PPT / Excel / HTML / EPUB / Markdown…) into a single, polished, offline, self-contained HTML dashboard — a left fixed table-of-contents tree and right-side modular content (executive summary, big key-metric cards, logic/relationship diagrams, data charts, conflict comparison, chapter details). Use when the user has document files and wants to "distill / merge / visualize / make sense of / lay out / build a panel from" them. It highly distills the key points so the reader need not open the source, keeps every claim traceable back to file + page, and foregrounds the logic/relationship diagram as the centerpiece. |
多格式文档 → 可视化信息面板(doc-atlas)
把一份或多份文档(PDF / Word / PPT / Excel / HTML / EPUB / Markdown…)归一化为 Markdown 中间层 → 跨文件梳理合并成一个统一知识结构(model.json)→ 渲染成一个离线可开的单文件 dashboard.html:左侧固定目录树,右侧按需出现的模块化内容(关键指标卡、核心要点、逻辑/关系图、数据图表、冲突对照、章节详情)。
三条核心价值(一切取舍围绕它们):
- 高度炼化——读者看面板就够了,不必再翻原文;若做得杂乱无章,那还不如直接看 PDF。
- 准确可溯——零幻觉、每个数字/结论都能指回「哪个文件第几页」,不确定就诚实标注。
- 逻辑图是主角——把文档的核心逻辑/因果/关系做成醒目的大图,这是本工具最大的卖点。
路径模型(重要):命令在用户的文档文件夹里运行(即当前工作目录 cwd,里面放着用户的 PDF/文档),不要 cd 进 skill 目录。脚本一律用绝对路径 "$SKILL_DIR/scripts/..." 调用;所有产物写到用户文件夹下的 ./doc-atlas-out/。SKILL_DIR = 本 skill 的安装目录(即本 SKILL.md 所在目录),开工前设一次:
SKILL_DIR="$HOME/.claude/skills/doc-atlas"
OUT="./doc-atlas-out"
何时用本 skill
- 用户给了文档文件,并希望「梳理内容 / 生成面板 / 可视化总结 / 理清逻辑 / 多文件合并梳理」。
- 单文件也可用(跳过跨文件去重部分);多文件时跨文件合并是核心价值。
输出放哪:默认建在用户当前文件夹下的 ./doc-atlas-out/(里面含 workspace/、model.json、dashboard.html);若用户指定了目录就沿用。
工作流总览(六步)
- 扫描 + 一次性确认:先扫描当前文件夹(只读无害),再用一次 AskUserQuestion 同屏问两件事——输出语言 + 纳入哪些文件。
- 归一化:每个被确认的文件 →
workspace/<name>/{content.md, assets/, meta.json}(PDF 逐页文本带页锚、表格走结构化抽取保数值列;源未变自动跳过)。
- 梳理合并(核心):通读、去重 / 识冲突 / 互补 / 判关系,重组成
model.json;写完做完整性批判第二遍并填 distillation_report(含数值字段)自检。
- 事实核查(对抗式):对对外/高风险文档,派 subagent 回原件证伪,修正
❌/➖ 后再渲染(低风险单文件可内联自查)。
- 渲染:
model.json (+workspace) → dashboard.html(单文件、零外链、断网可开;渲染前自动跑 validate_model.py 机器校验)。
- 自检交付:无头校验无报错、抽查溯源,并把炼化体检/核查结论讲给用户。
阶段零:扫描 + 一次性确认(语言与文件同屏问,减少往返)
0.1 先扫描目标文件夹(只读,无副作用)
python3 "$SKILL_DIR/scripts/scan_docs.py" .
scan_docs.py 递归列出当前文件夹里所有候选文档(pdf / word / ppt / excel / html / epub / md / txt…),自动跳过隐藏目录、.venv、node_modules、doc-atlas-out 以及含 SKILL.md 的 skill 包目录。
0.2 一次 AskUserQuestion 同屏确认三件事(不要拆成多轮)
拿到清单后必须与用户确认,不要擅自全量开跑。把编号清单(文件名 / 类型 / 大小)呈现给用户,然后用一次 AskUserQuestion 同时问:
- 输出语言:「你想要哪种语言的信息面板? ① 中文 ② English ③ 跟随文档原语言 ④ 其他」
- 文件取舍:「以上文件是否都纳入梳理整合?要去掉哪些?有没有遗漏(比如埋在子目录里的)?」
- 阅读目标:「你最想从这批文档得到什么? ① 决策参考(要做判断/取舍) ② 学习理解(搞懂讲了什么) ③ 风险审查(找坑/找问题) ④ 数据核对(提取关键数字) ⑤ 其他(自填)」
多文件时可在同一表单里追加第四问:它们大概什么关系(同主题不同版本 / 时间序列 / 总分 / 互相引用),有助于阶段二定合并策略。
阅读目标记为 READING_GOAL,写进 meta.reading_goal,是整条流水线的"问题意识":
- 重要性分级(high/medium/low)按"对这个目标的重要性"打,不是按篇幅。
highlights 选"回答这个目标最需要的 4–6 个数字"。
meta.one_liner(定论)直接回答这个目标,不是泛泛总结。
- 用户跳过不答时缺省视为「学习理解」,不追问。
语言选择记为 UI_LANG,贯穿全程:
meta.ui_lang = 用户选择;meta.content_lang = 文档主要语言(二者可不同)。
- 所有 AI 撰写的叙述性文案一律用
UI_LANG(哪怕原文是另一种语言,也要在炼化时翻译/转写成 UI_LANG)。
- 事实保真不受影响:数字、专有名词、逐字引用(quotes)保留原文,可在
UI_LANG 里补一句释义;溯源角标(文件名/页码)原样。
- 用户没明确表态时,缺省 = 跟随文档主要语言。
等用户确认后,用确认过的文件清单进入阶段一。
阶段一:归一化为 Markdown 中间层
1.0 环境检查与按需安装(首次使用,必须先征得用户同意)
归一化需要 markitdown + pymupdf(装在 .venv 里,约 290MB)。先静默检查是否已就绪:
VENV_PY="$SKILL_DIR/.venv/bin/python"
if [ -x "$VENV_PY" ] && "$VENV_PY" -c "import markitdown, fitz" 2>/dev/null; then
echo READY
else
echo NEED_INSTALL
fi
- 输出
READY → 环境已装好,直接进入 1.1,不要重复安装。
- 输出
NEED_INSTALL → 停下来,向用户说明并征求同意,绝不擅自安装:
首次使用需要安装文档解析依赖(markitdown + PyMuPDF,约 290MB,1–2 分钟,装到 $SKILL_DIR/.venv)。是否现在安装?
- 用户同意 → 跑
bash "$SKILL_DIR/scripts/bootstrap.sh",装完再继续 1.1。
- 用户拒绝 → 不安装、也不继续。明确告诉用户:没有这些依赖就无法解析文档,本次到此为止,等愿意安装时再来。不要尝试绕过或用系统 python 硬跑(markitdown 装不进系统 3.9)。
1.1 逐个文件归一化
对每个被确认的输入文件跑归一化(脚本用绝对路径调,人留在用户文件夹里)。必须按确认清单顺序传 --file-id f1/f2/...——阶段二 model.json 的 files[].id 要与之一致,validate_model.py 靠这条链做页码越界核查:
"$VENV_PY" "$SKILL_DIR/scripts/normalize.py" "输入文件.pdf" --out "$OUT/workspace/" --file-id f1
三件套各司其职,缺一不可:
content.md — 阶段二的唯一阅读对象。PDF 走 PyMuPDF 逐页文本,每页前有页锚 <!-- [doc-atlas] p.N -->——写 SourceRef.page 时直接读锚,不许猜;表格另按行×列结构化抽取,追加在文末「结构化抽取的表格」一节(保住数值列)。非 PDF 由 markitdown 转换(无页码概念,用 loc 定位)。
assets/ — 用 PyMuPDF 等额外提取的有信息量图片(图表 / 流程图 / 示意图),供 model 的 image block 引用。
meta.json — page_map(页→偏移/首行)、标题索引、文件名、页数、字数、文档类型、日期(date_source 标注来源:content 可信 / mtime 兜底不可作权威性依据)、tables(表格登记:页码+行列数+置信度)、table_extraction(整体表格抽取状态),是 SourceRef 程序侧核查的依据。
表格保真很关键:很多"看似原文没写"的数值,其实是 markitdown 把表格列打乱/丢列造成的。normalize.py 用 page.find_tables() 把表格重抽成二维 Markdown 表并登记置信度——阶段二据此判断「原文确实没有」还是「我们没抽好、要回看 PDF 原图」(见阶段二纪律)。
扫描版 PDF 的 OCR 回退:当 PDF 是扫描件、markitdown 提不出文字层时,normalize.py 会自动走 OCR 回退把图片页转成文本(OCR 结果置信度较低,阶段二引用时倾向标注「(待核实)」)。
用 $VENV_PY 做归一化(markitdown/pymupdf 只装在 venv 里);render / validate / selfcheck 用系统 python3(stdlib only,见阶段三、四、五)。两者不要混用。
阶段二:信息梳理与多文件整合(核心,AI 亲自做)
通读 $OUT/workspace/*/content.md 与各自 meta.json,重新组织内容,而不是逐文件摘要。详细方法见 references/merge-and-structure.md,要点:
- 去重:同一概念/事实在多个文件出现 → 合并为一个节点,
sources 标注所有出处。
- 识冲突:同一事实说法不一致(数字/日期/结论)→ 不要静默选一个,写进
conflicts[],列出各方 positions 与出处,给 resolution 和 confidence。
- 互补:A 讲概述、B 讲细节 → 组织成同一章节的不同层级,而非两个并列章节。
- 判文件关系:同主题不同版本?时间序列?总分?互相引用?据此定合并策略;多文件时填
file_relations.mermaid。
把合并结果写成唯一中间产物 $OUT/model.json(顶层 IR)。字段语义、调色板与完整示例见 references/model-schema.md,机器约束见 schema/model.schema.json:
- 必填:
meta、files、outline、chapters;其余(highlights/conflicts/keypoints/diagrams/charts/quotes/file_relations/distillation_report)按需出现——给了才渲染,这就是右侧模块化的自由度。
outline 是合并后的统一主题树(1 / 1.1 / 1.2.1),不是按文件罗列;每个一级 outline 节点对应一个 chapters[]。
chapters[].blocks 从调色板自由编排:paragraph / callout / keypoints / metric / quote / diagram(Mermaid) / chart(Chart.js) / table / image / subsections。某章节有没有逻辑图/图表,全看它含不含对应 block。
- 每个
SourceRef 至少给 page 或 loc 之一,file_id 必须匹配某个 files[].id。
2.1 三层阅读模型(炼化 = 让人一眼看懂)
让每份 model.json 天然分三层,模板按层级默认展开/折叠,这样读者「10 秒抓主线、细节按需展开」:
| 层级 | 内容 | model.json 落点 | 默认呈现 |
|---|
| L1 概览 | 一句话定论 + ≤5 句执行摘要 + 4–6 个核心数字 | meta.one_liner + meta.executive_summary + highlights[] | 首屏直接显示 |
| L2 要点 | high/medium 要点、核心逻辑图、核心图表 | keypoints[] / diagrams[] / charts[] | 默认显示 |
| L3 细节 | 章节正文、参数表、工况表、质保表 | chapters[].blocks | 章节体默认折叠,点开才看 |
-
meta.one_liner(定论,强烈建议给):面板首屏的 The Bottom Line 大字条。写法:直接回答
reading_goal,把核心结论 + 最关键数字 + 转折压进一句话。缺省时面板回退用 executive_summary[0]。
-
highlights[](顶层,强烈建议给):把全篇 4–6 个最关键数字做成首屏大号指标卡(如「8 小时 / 纯电驻车」「<3% / 占整车重」「22 万 / 10 年累计节省」)。这是"极少内容获取主要"的最直接实现。
-
章节内也可用 metric block 给局部关键数字一个大字号出口。
-
关键数字不要只埋在段落里——能抽成 highlights / metric / chart 的就抽出来。
2.2 逻辑/关系图是主角(核心卖点,务必做足)
- 通读后先问自己:这份文档集的核心逻辑是什么?(因果链 / 流程 / 决策树 / 组织关系 / 价值传导)把它做成
diagrams[] 里一张主图——清晰、信息量足、能讲清主线。宁可一张扎实的大图,也别堆十张零碎小图。
- 模板会把
diagrams[] / file_relations 整行大尺寸渲染并支持点击放大,所以图要经得起放大看:节点命名清楚、箭头有动词标签、层次分明。
- 凡内容里出现关系或顺序就考虑画图(
flowchart 流程/因果、mindmap 概念分解、sequenceDiagram 时序);只是几条并列事实则用 keypoints,别硬画。
- 多文件时
file_relations.mermaid 画文件之间的关系(版本迭代/引用/互补);内容主题关系进 diagrams[]。
2.3 图表语义不要丢
- 区间数据用区间表达:如噪音「≥70 / <50」别画成定值 70/50(会误导);用区间/堆叠,或在标签标「≥ / <」。
- 不同口径的并列柱要标清:如「一次性投资 vs 10 年累计」并列时,标题/坐标轴/caption 必须醒目标注口径,避免被误读为同期可比。
2.4 炼化纪律(让"高度炼化"看得见、靠得住)
"高度炼化" ≠ "变短",它要同时满足:①跨文件/跨章去重;②升维归纳(从"原文怎么说"升到"结论/因果/对比");③关键信息(数字/标准号/参数/前置条件)零丢失且溯源;④重要性分级反映"对 reading_goal 的重要性"。
-
概念清单要落盘($OUT/workspace/_concepts.jsonl):阶段二边读边维护的"概念→出处"表不要只留在草稿里,写成 JSONL 正式中间产物,每行一条:
{"concept": "...", "statement": "...", "file_id": "f1", "page": 3, "loc": null, "disposition": "kept|merged|dropped", "target": "1.2"}
(disposition 记收/并/弃,target 记落到哪个 outline 节点/keypoint;弃收的写明原因。)
好处:claims_total 等体检数字从清单数出来而不是拍出来;核查 agent 可审计"收了什么、弃了什么";超长文档分批读可断点续作。多文件/长文任务必做,单短文件可省。
-
完整性批判第二遍(必做):第一遍写完 model.json 后,重读 source 自问:"哪个重要数字 / 前置条件 / 结论原文有、model 却没有?" 把找到的补回去,循环到"再读一遍也挑不出新的"。
-
填 distillation_report 并自检阈值(顶层可选字段,强烈建议给,交付时讲给用户)。数值字段必须给全(sections_total/sections_mapped、claims_total/claims_with_source_count、todo_count/data_points、compression_ratio_x),validate_model.py 据此机器执行纪律,展示文案字段可另给:
- 章节覆盖 必须 = 100%(
sections_mapped == sections_total),缺章回去补。
- 待核实占比
todo_count/data_points > 10% → 先别交付(校验器直接拦):多半是表格数值列没抽好(看 meta.tables / table_extraction),回查 PDF 原图能补的补回来。
- 溯源率
claims_with_source_count < claims_total → 有无源声明,要么补源要么删。
compression_ratio_x 落在 ~3 到 ~10 才算"既炼又不漏";接近 1 = 只是搬运。
-
"待核实" 只用于「原文确实没写」,严禁用于「本工具没抽出来」。后者要回查原件(meta.json 的页码 / assets/ 原图 / 用 Read 工具 pages 参数读原 PDF)补回真值;分不清就当成"要回查",不要默默标"待核实"后被当成"原文没有"。
纪律:一切结论溯源、不编造;PDF 的 SourceRef.page 必须来自 content.md 里的页锚(<!-- [doc-atlas] p.N -->),不许凭印象写;超长文档分批读再汇总,别漏后半部分。写完必须跑机器校验(结构 / 交叉引用 / 页码越界 / 炼化阈值),全绿再进入阶段三:
python3 "$SKILL_DIR/scripts/validate_model.py" "$OUT/model.json" --workspace "$OUT/workspace/"
阶段二·五:事实核查(对抗式,回原件证伪)
draft 出 model.json 后、渲染之前,加一道独立核查闸——目标是找错,不是确认。按风险/规模分档,别对所有任务都开多 agent:
| 场景 | 核查方式 |
|---|
| 单文件、< ~15 页、低风险 | 主 AI 内联自查(完整性批判第二遍即可,省 token) |
| 单文件、销售/合同/对外/高风险材料 | 1 个 subagent 专职核查 |
| 多文件 / 长文 / 有冲突表 | 按章节 fan-out 多个 subagent 并行核查 + 1 个汇总,重点查 conflicts[] 完整性、跨文件数字一致性 |
给核查 agent 的指令要点:
- 对抗框架:"逐条挑 model.json 里的数字/事实/结论,默认它可能错,去原文找反证。"
- 核查清单:每条 high/medium 的数字与结论,判定
✅准确 / ⚠️偏差 / ❌错误或幻觉 / ➖遗漏,并附原文出处。重点查三类:① 幻觉(原文没有却写了)② 遗漏(原文有却没收/误标待核实)③ 派生数字验算(亲手重算节省额/CO₂/续航小时等,核口径自洽)。
- 关键纪律:核查 agent 必须能读原始文件(Read 工具 pages 参数 / 原图),不能只读
content.md——因为 content.md 可能本身丢了表格数值列,只读它会和阶段二犯同样的盲区。
核查结果落盘(产物契约):核查记录写成 $OUT/factcheck.json——一个数组,每条
{"claim": "...", "verdict": "ok|deviation|error|missing", "source": {"file_id": "f2", "page": 12}, "note": "怎么处理的"}
(与 distillation_report.fact_check_items 同构,verdict 对应 ✅/⚠️/❌/➖)。
核查结果回流:
❌ 错误 / 幻觉 → 必须改,改完重渲染。
➖ 遗漏(原文确有) → 补进 model.json。
⚠️ 偏差 / 口径问题 → 修正,或在文案/callout 里显式标注口径。
- 把核查摘要写进
distillation_report.fact_check(如"已核 23 条、修正 3 条、补回 2 条遗漏"),
并把 factcheck.json 内容抄进 distillation_report.fact_check_items——面板附录会渲染成可展开的核查明细表,是"为什么可以信这份简报"的证据;阶段五讲给用户。
阶段三:渲染单文件面板
用系统 python3(stdlib only)渲染:
python3 "$SKILL_DIR/scripts/render_dashboard.py" "$OUT/model.json" "$OUT/dashboard.html" \
--workspace "$OUT/workspace/" --self-check
- 渲染前自动调用
validate_model.py(结构/交叉引用/页码越界/炼化阈值),不过关直接退出码 2——先修 model.json,别用 --skip-validate 绕。
- 输出是单文件
dashboard.html,完全自包含、零外链、断网可开:CSS/JS 内联,图片替换为 data: URI 内嵌,Chart.js 与 Mermaid 也整体内联(体积约 +3.5MB,是"离线可用 > 体积小"的既定取舍;确需外链瘦身可加 --cdn,但断网时图与图表只剩降级显示)。
- 图片
src 先按绝对路径找,找不到再按 workspace/src 找;缺图不报错,渲染占位并在 stderr 警告。
- 退出码 0 = 成功;非 0 = 失败并在 stderr 说明。加了
--self-check 会渲染后自动调用 selfcheck(即可省略阶段四的手动调用)。
- 默认
--template = scripts/../templates/dashboard.html,默认 --workspace = model.json 所在目录;上面显式写 --workspace 更稳。
阶段四 / 五:自检与交付
若阶段三没带 --self-check,单独跑:
python3 "$SKILL_DIR/scripts/selfcheck.py" "$OUT/dashboard.html"
- playwright 无头加载,捕获 console error / pageerror,统计 Mermaid 渲染出的 svg 数与 Chart canvas 数,校验注入 JSON 可解析、关键 section 存在;有错误则退出码非 0。
- 当前 python 缺 playwright 时,脚本会自动切换到 skill
.venv 的 python 重跑(bootstrap 用 --with-selfcheck 装过即可用)。
- 浏览器获取顺序:先
chromium.launch(),失败再 channel="chrome",再失败降级为静态解析检查并 warn。
人工抽查(自检脚本不能替代):树节点引用的来源页码在 meta.json 里真实存在;要点里的数字与原文一致;去重没把不同概念误合并。
交付:把 $OUT/dashboard.html 给用户,并用 3–5 句话说明:讲了什么、几个文件、最关键的结论/冲突,以及炼化体检与核查结论(章节覆盖率、待核实占比、已核/修正了几条)——让用户看得见"为什么可以信这份面板、而不必回去翻 PDF"。
约束
- 不编造:所有结论必须能溯源到某个文件的页码/位置;做不到就别写。
- "待核实" 严格界定:只用于「原文确实未写 / 来自 OCR / 多源冲突未定」;不得用于「本工具没抽出来」——后者必须回查原件补回真值。
- 分批:单文件 ~100 页以上或
content.md 超长时分批读取再汇总,避免遗漏后半部分。
- 语言策略:
meta.ui_lang(界面 + AI 撰写文案)跟随用户在阶段零选定的语言;meta.content_lang 跟随文档主要语言;逐字 quotes 保留原文。
- 禁用 localStorage;输出面板零外链、零网络请求(Chart.js / Mermaid 已内联;仅
--cdn 模式例外,且须明示用户断网后果)。
- 界面风格固定为「纸本简报」皮肤:暖米纸 + 蓝色强调(重点/风险保留朱红)+ 无衬线正文 + 日读;信息结构固定为一条主线——定论(one_liner) → 编号简报区(指标/摘要/逻辑图/图表/要点/冲突)→ 章节详情(折叠)→ 附录(源文件/关系/体检,降调)。由
templates/dashboard.html 决定;AI 不改皮肤、不提供外观切换面板。
参考文件索引
references/merge-and-structure.md — 阶段二跨文件去重/冲突/互补/文件关系判定、三层阅读模型、逻辑图主角化、炼化体检与核查的操作指南。
references/model-schema.md — model.json 的人类可读说明与完整示例(含 Block 调色板、highlights、metric、distillation_report 用法)。
schema/model.schema.json — model.json 的 JSON Schema(draft-07)。
scripts/scan_docs.py — 阶段零:扫描目标文件夹列出候选文档(stdlib only,供与用户确认)。
scripts/bootstrap.sh — 建 .venv 并安装 markitdown + pymupdf(优先 uv,无 uv 回退 python3 -m venv;--with-selfcheck 顺带装 playwright + chromium)。
scripts/normalize.py — 阶段一:单文件 → workspace/<name>/{content.md, assets/, meta.json}(PDF 逐页页锚 + 表格结构化抽取 + 扫描件 OCR 回退;增量跳过)。
scripts/validate_model.py — 阶段二末尾 / 渲染前的机器校验闸:结构、交叉引用、页码越界、炼化阈值(stdlib only)。
scripts/render_dashboard.py — 阶段三:model.json (+workspace) → 单文件 dashboard.html(stdlib only,图片 base64 内嵌,Chart.js/Mermaid 内联)。
scripts/selfcheck.py — 阶段五:playwright 无头校验 dashboard.html(缺 playwright 自动切 .venv python,再不行降级静态检查)。
templates/dashboard.html — 固定单文件前端模板(内联 CSS/JS + __DASHBOARD_DATA__ / __VENDOR_JS__ 注入位)。
templates/vendor/ — 内联用的 Chart.js / Mermaid 副本(版本与许可见其 README)。