obsidian-llm-wiki · diff
git:20260908.c87ff41 to git:20260908.3c320a5
13 added, 2 removed. Audit B to B.
---
name: obsidian-llm-wiki
- description: "LLM Wiki 模式:用 LLM 持续维护 Obsidian 知识库(raw/wiki 双层 + AGENTS.md/CLAUDE.md schema + index.md + log.md)。支持 ingest、query、query-image、optimize、extract-thinking-frameworks、lint、index、migrate、delete;强制维护遍历(Mandatory Maintenance Pass)自动检查并修复 frontmatter/index/schema 结构缺口;index.md 统一三权威变量(indexed_page_count/wiki_file_count/registered_domain_count)+ 三健康变量(missing_count/broken_count/duplicate_count)+ 索引健康行;双入口 schema 字节一致并验 SHA-256。支持用 Claude Code Agent 工具派发只读 subagent 以波次并行分析图片密集资料(截图课程、PPT、扫描件,支持 100–300 张多 Agents 并行读图),用项目 .venv 做 PDF/DOCX/PPTX/XLSX 预处理与 image manifest。触发词:wiki、知识库维护、ingest、preprocess、batch-analyze images、subagent、波次并行、manifest、venv、optimize、lint、index、索引健康、六变量统计、双入口 schema、补录、漂移修正、知识管理、Obsidian 笔记整理、读图降级、视觉通道探测、视觉 MCP、zai-mcp-server、GLM-4.6V、GLM/MiniMax 网关、log.md 大文件追加、固定只读日志预检(log-preflight.ps1,2 MiB 阈值与跨年判定)、日志分卷轮转、log status、log query、log rotate、固定 PDF 预处理(preprocess_pdf.py)、任务临时目录清理(tmp/obsidian-llm-wiki、created_files.json、temp-cleanup)、query-image、图片查询、截图检索。"
+ description: "LLM Wiki 模式:用 LLM 持续维护 Obsidian 知识库(raw/wiki 双层 + AGENTS.md/CLAUDE.md schema + index.md + log.md)。支持 ingest、query、query-image、optimize、extract-thinking-frameworks、lint、index、migrate、update-raw-reference、delete;强制维护遍历(Mandatory Maintenance Pass)自动检查并修复 frontmatter/index/schema 结构缺口;index.md 统一三权威变量(indexed_page_count/wiki_file_count/registered_domain_count)+ 三健康变量(missing_count/broken_count/duplicate_count)+ 索引健康行;双入口 schema 字节一致并验 SHA-256。支持用 Claude Code Agent 工具派发只读 subagent 以波次并行分析图片密集资料(截图课程、PPT、扫描件,支持 100–300 张多 Agents 并行读图),用项目 .venv 做 PDF/DOCX/PPTX/XLSX 预处理与 image manifest。触发词:wiki、知识库维护、ingest、preprocess、batch-analyze images、subagent、波次并行、manifest、venv、optimize、lint、index、索引健康、六变量统计、双入口 schema、补录、漂移修正、知识管理、Obsidian 笔记整理、读图降级、视觉通道探测、视觉 MCP、zai-mcp-server、GLM-4.6V、GLM/MiniMax 网关、log.md 大文件追加、固定只读日志预检(log-preflight.ps1,2 MiB 阈值与跨年判定)、日志分卷轮转、log status、log query、log rotate、固定 PDF 预处理(preprocess_pdf.py)、任务临时目录清理(tmp/obsidian-llm-wiki、created_files.json、temp-cleanup)、query-image、图片查询、截图检索、update-raw-reference、媒体引用修复、嵌入改写。"
---
# Obsidian LLM Wiki Skill
用 LLM 持续维护 Obsidian 知识库。基于 raw / wiki / schema 三层架构:`raw/` 不可变源资料(只读),`wiki/` LLM 维护的知识层(可写),`CLAUDE.md` / `AGENTS.md` 为 schema。LLM 是维护者,人类负责策划原始资料、提问、引导方向。
本 Skill 是**通用方法论层**:subagent 批量分析、image manifest、文档预处理运行时、强制维护遍历、安全规则等跨 vault 复用的机制都在这里。项目特定的配置(领域、raw 目录树、运行环境)由项目根的 `CLAUDE.md` / `AGENTS.md` 承载,本 Skill 不重复。
## Grounding(schema 优先级与读取顺序)
每次进入一个 vault,按优先级读取 schema,确立架构、领域、路径、规则:
1. **`CLAUDE.md` / `AGENTS.md`**(schema 入口)— 见下方三情形
2. **`index.md`** — 现有内容目录,了解已有页面
3. **`log.md`**(尾部)— 近期操作,了解最新变更
**schema 双入口三情形**(关键:按 vault 声明的契约处理两份 schema):
1. **声明双入口字节契约**(两文件内容完全相同,典型如 Lester 知识库):两份文件必须字节一致;结构变更时**同一次编辑同步两个文件**,并验证 SHA-256 相等;运行时只应用与当前运行时匹配的适配章节(Claude Code 侧用 Claude Code 适配章节)。这是项目契约,不是建议。
2. **未声明契约且两文件冲突**:Claude Code 侧以 `CLAUDE.md` 为准,并在结果中记录任务相关的冲突,提示用户裁定。
3. **仅存在一个 schema 文件**:直接使用之(Claude Code 单文件通常是 `CLAUDE.md`,Codex 单文件通常是 `AGENTS.md`,均为合法配置)。
> 所有路径、领域、frontmatter 规范从 schema 读取,**不硬编码**。发现双入口契约下两文件不一致时,必须报告,不擅自改写。
## 强制维护遍历(Mandatory Maintenance Pass)
**每次使用本 Skill 都包含一次强制维护遍历**。用户无需显式要求"更新 index.md / 修复 frontmatter / 同步 schema"——自动检查并在发现结构缺口时修复。
**用户显式边界仍优先**:若用户声明只读 / 审计 / 查询 / "不改任何文件",则执行同样的检查,但**只报告 gaps,不写入**。
在每次任务收尾前运行这七步:
1. 读 `AGENTS.md` / `CLAUDE.md`(在时)与 `index.md`。
2. 识别任务作用域内的 wiki 页面:ingest / optimize / migrate / delete / extract-thinking 任务 = 所有新建、修改、移动、删除或被直接引用为产出的页面;query 任务 = 为回答而读的页面;lint / audit / index 任务 = 用户指定作用域,未指定则全库。
3. 检查作用域页面的 YAML frontmatter 七字段(`title` / `created` / `updated` / `domain` / `tags` / `sources` / `status`)。frontmatter 是**结构性维护例外**:缺失或错位时默认修复到文件第一行,**不受** "append-only / 保留正文 / 放最后" 约束(这些约束只针对正文、图片与章节顺序)。只有显式 "不改任何文件" 才不写。缺失值按文件名 / schema 路径 / 今日 / 声明 sources / 当前页面状态保守推断;`domain` 或 `source` 推断不确定才问用户。
4. 检查 `index.md` 任务作用域相关条目(新增 / 移除 / 迁移 / 改名 / 缺条 / 路径过期 / 摘要过期 / 标签变化 / 统计漂移 / 重复 / 断链)。改 `index.md` 前先扫 `wiki/**/*.md` + 读现有 index + 按 §Index Metadata And Statistics 重算六个变量;改 index 时**同一次编辑**刷新顶部维护说明 + 底部统计行 + 索引健康行。
5. 检查 `AGENTS.md` / `CLAUDE.md` 中与任务相关的领域注册、raw/wiki 路径、工作流、安全、标签、图片/文档规则是否过期;按 vault 双入口契约处理(同步两文件 + 验 SHA-256)。
6. 若有文件变更,向 `log.md` 追加**一条**最终记录,含 `AGENTS.md` / `CLAUDE.md` / `index.md` / frontmatter 四项检查结果(含 "已检查,无需更新");若 `index.md` 变更,记录三个权威变量 + 三个健康计数 + `indexed_page_count` 变化类型(变化 / 不变 / 统计漂移修正)。无维护变更但其他文件变更时,仍为每个检查项记 `已检查,无需更新`。(`log.md` 变大时按 §运行时与网关适配 的 EOF 直追法追加,勿整读。)
7. 维护遍历**只动结构与元数据**:不因发现元数据或索引缺口就扩写、改写或重新诠释源资料正文。
> 本节取代旧版"Schema 与 Index 新鲜度检查"章节——那节的"只读默认不改、写操作必检查并记录"分工已并入本遍历。主 Claude agent 拥有此遍历与所有写入;subagent 只辅助分析。
## 安全规则
- **绝不修改、移动、删除 `raw/` 下任何文件**(不可变层)。
- **`log.md` 条目 append-only**,不删除、不改写已有条目,只追加。
- **覆盖已有 wiki 内容前须用户确认**;优化页面时**绝不删除已有的 `![[图片.png]]` 嵌入**。
- **删除 wiki 页面**用精确路径,禁通配符/递归/管道批量/循环/目录删除:
```powershell
Remove-Item -LiteralPath "<绝对路径>"
```
单文件单命令;中文路径与带空格路径必须用 `-LiteralPath` 或被正确引用的显式参数。唯一目录删除例外:Skill 任务目录(`<vault-root>/tmp/obsidian-llm-wiki/<task-id>/`)内已清空、已确认为空的目录,按 [references/temp-cleanup.md](references/temp-cleanup.md) 逐个用非递归 `Remove-Item -LiteralPath` 删除。
- **双入口 schema 字节一致性**:声明双入口契约时,`AGENTS.md` 与 `CLAUDE.md` 必须字节相同;结构变更**同步编辑两文件并验证 SHA-256**;不得泄露密钥或本地敏感配置。
- **subagent 只读红线**:派出的 subagent 绝不修改 `raw/`、`wiki/`、`index.md`、`log.md`、schema 文件或 `.claude/` 下任何文件。
- 不确定时**提问,不猜测**;图片重名/缺失/无法唯一定位一律先报告。
- **不虚构**来源、数据、引用或验证结果。
- 不修改 Windows 系统 PATH,不自动安装/卸载/重装 Python,不调用用户目录下的 Python;不通过 PowerShell 管道向 Python 传递中文路径。
- - 图片嵌入用短文件名 `![[文件名.png]]`,不写完整路径(Obsidian 全库自动解析)。
+ - 图片嵌入默认短文件名 `![[文件名.png]]`(Obsidian 全库自动解析);通用易重名文件名(如 `image-001.png`)或 vault schema 明确要求时用全路径 `![[raw/…]]`,防跨目录误解析。
- **图片视觉未识别时必须如实标注**(视觉未识别 / 基于正文非图像识别),绝不依文件名或上下文虚构图中文字、人物、数字、颜色。
- **`log.md` 大文件(超 `Read` 上限)追加用 EOF 直追**(bash heredoc / `Add-Content -LiteralPath`),不为追加而整读。
- **任务临时文件自动清理**:杂项中转/对账临时文件只放系统临时目录(Git Bash `/tmp`,即 Windows `%TEMP%`,如 `C:/Users/<用户名>/AppData/Local/Temp/`);Skill 管理的任务产物(如 PDF 预处理中间产物)统一放任务目录 `<vault-root>/tmp/obsidian-llm-wiki/<task-id>/`;两者均禁止写入 `raw/`、`wiki/` 或 vault 其他位置。优先用命令内变量、命令替换与进程替换(如 `diff <(...) <(...)`)内联完成,不落盘;确需落盘时,任务收尾按 [references/temp-cleanup.md](references/temp-cleanup.md) 自动清理,无需用户确认(若运行时配置了命令守卫,tmp/temp 类目录下的单文件 `rm` 与单路径非递归删除可配置为免审批放行——后者是空任务目录窄例外的唯一删除方式;目录级与递归删除仍应直接拦截);系统临时目录与任务目录均不得残留任务临时文件。
## 前置条件(初始化)
使用前,项目根目录必须有 schema 文件(本地默认与推荐:单个 `CLAUDE.md`,Claude Code 原生自动加载)。如果不存在,引导用户初始化:
1. 询问用户的知识库有哪些领域(如"读书笔记"、"AI"、"投资")
2. 使用 [references/schema.md](references/schema.md) 作为模板,按你用的运行时落盘 schema:Claude Code 生成 `CLAUDE.md`,Codex / 其他 agent 生成 `AGENTS.md`;多运行时并存则两份都存(字节完全相同,保留双入口契约)。单文件即合法配置,不强制双入口。
3. 创建 `raw/` 和 `wiki/` 目录结构
4. 创建空的 `index.md` 和 `log.md`
5. 在 Obsidian 设置中将 `attachmentFolderPath` 设为 `raw`(新图片暂存 raw/ 根目录,ingest 时按领域整理到对应子目录)
## 模板
本 Skill 自带通用模板,位于 `assets/` 目录:
- `assets/wiki-page.md` — 通用 wiki 页面
- `assets/book-note.md` — 读书笔记
- `assets/meeting-note.md` — 会议记录
- `assets/tool-page.md` — 工具页面
- `assets/log-active.md` — 新活动日志模板(仅在一次成功分卷轮转后创建新 `log.md` 时使用,见「log.md 追加(大文件安全)」与 [references/log-rotation.md](references/log-rotation.md))
**优先级**:如果项目根目录有 `templates/` 目录,优先使用项目模板;否则使用 Skill 自带的 `assets/` 模板。模板中的 `{{domain}}`、`{{date}}`、`{{title}}` 等占位符由主 agent 根据项目 schema 填写。
## Frontmatter 与 Tag 规范化
每个 wiki 页面必须以 YAML frontmatter 开头(文件第一行,`---` 起始),必需七字段:
```yaml
---
title: "页面标题"
created: YYYY-MM-DD
updated: YYYY-MM-DD
domain: <领域名>
tags: [type/book, AI/编程]
sources: []
status: draft | active | archived
---
```
- `title` 与文件名一致;`sources` 指向 raw 来源目录(以 `/` 结尾)或文件路径,多个用 YAML 数组;`updated` 在正文、标签或来源元数据实质变化时刷新。
- `tags` 是权威来源;inline `#tag` 如存在必须与 frontmatter 匹配。
- **Tag 规范化**:只在 frontmatter `tags` 与 inline `#tag` 中规范化,**不自动改** domain、sources、raw/wiki 路径、目录名、文件名、页面标题、wiki 链接、图片嵌入或正文普通文本。标签片段中如有空白,统一用 `_` 连接(如 `AI Live` → `AI_Live`)。
- **结构性维护例外**:frontmatter 缺失或错位时,即使用户说 "append-only / 不改现有内容 / 放最后",仍默认把 frontmatter 修复到第一行——这不计入"改动正文或顺序"。只有显式 "只读 / 不改任何文件" 才阻止写入。
## Windows 与 Python
文档预处理优先用项目 Python 虚拟环境,**不依赖系统** `python` / `py` / `python3`。文件发现优先用 `rg`。解释器优先级链:
1. `.venv\Scripts\python.exe`(项目本地,首选)
2. `.claude-python\python.exe`(可选项目目录)
3. `.runtime\python\python.exe`(可选)
脚本必须用 `pathlib.Path` 处理路径(跨平台、Windows 中文路径友好)。**中文路径与内容必须作为 PowerShell 显式参数传递,不通过管道喂给 Python**。不修改 PATH、不安装/卸载/重装 Python、不调用户目录 Python。调用约定见下文「文档预处理运行时」。
## 文档预处理运行时(Document Preprocessing Runtime)
PDF/DOCX/PPTX/XLSX 等文档的确定性预处理,与只读 subagent 视觉分析分工协作。
**调用格式**(项目脚本就位后):
```powershell
& ".\.venv\Scripts\python.exe" ".\scripts\<script>.py" "<input-path>" "<output-path>"
```
**PDF 固定脚本(强制,禁止临时另写)**:处理 PDF 前必须先读 [references/pdf-preprocessing.md](references/pdf-preprocessing.md),再运行 Skill 自带 `scripts/preprocess_pdf.py`(pypdf 优先中文文本、PyMuPDF 负责页数/图片/整页渲染,逐页乱码质量判定,固定产出 pages/manifest/`created_files.json`)。Git Bash 调用:
```bash
PYTHONUTF8=1 PYTHONIOENCODING=utf-8 \
"<vault-root>/.venv/Scripts/python.exe" \
"<skill_base>/scripts/preprocess_pdf.py" \
--input "<PDF 绝对路径>" --vault-root "<知识库绝对路径>" --task-id "<时间戳-安全任务标识>"
```
- 产物只进任务目录 `<vault-root>/tmp/obsidian-llm-wiki/<task-id>/`;`task-id` 运行前必须不存在(脚本拒绝覆盖);`requires_visual` 页按「运行时与网关适配」三级视觉通道读图。
- **清理触发**:成功与可控失败的任务,都要在构建最终日志与最终回复前按 [references/temp-cleanup.md](references/temp-cleanup.md) 清理:先逐个单文件删除登记产物,再按 `created_directories` 最深优先删除空任务目录(窄例外单路径非递归 `Remove-Item -LiteralPath`),工作容器空则条件删除;最终汇报生成数/删除数/文件残留数/目录残留数/任务根状态/容器状态。
**`.venv` 职责**(确定性、可重复):
- 从 DOCX / PDF / PPTX / XLSX 提取文本与元数据
- 提取或枚举内嵌图片、slide/page 顺序、文件名、尺寸、源文档引用
- 仅在用户明确要求生成新源资产时,才把 PDF 页面或 PPTX 幻灯片渲染为图片文件
- 为后续只读 subagent 视觉分析建立有序 manifest
- **中间产物默认不写入 `raw/`**,除非用户明确要求
**`.venv` 与 subagent 分工**:
- `.venv` 负责可重复的解析、排序、抽取、manifest 建立
- 只读 subagent 负责 OCR-like 图片阅读、截图理解、图表/UI 细节、概念洞见合成
- **不默认假设** Tesseract、OpenCV、PaddleOCR、RapidOCR 等传统 OCR 引擎可用,除非用户明确安装或要求
> PDF 依赖(`pypdf`、`PyMuPDF`)以项目 `.venv` 为准;缺依赖且用户未授权安装时,PDF 用 Read 的 `pages` 参数直读降级。DOCX/PPTX/XLSX 项目脚本是否就位、依赖是否安装,仍以项目 schema(CLAUDE.md 的「运行环境」章节)为准。
## 图片密集资料分析(Image-Heavy Source Analysis)
适用范围:raw 图片目录、截图课程、PPT 截图导出、wiki 页面中以 `![[...]]` 引用 raw 图片的页面、以及从 PDF/DOCX/PPTX 中抽取出页面或图片的资料。
1. **先建 image manifest,再分析**:
- 对 wiki 页面:按**文档顺序**提取每个 `![[...]]` 嵌入,解析短文件名时优先用页面 `sources` 声明的 raw 目录。
- 对 raw-only 图片目录:按自然文件名顺序处理。
- 对 PDF/DOCX/PPTX 源:先用 `.venv` 检查文本、内嵌媒体、page/slide 顺序与文档元数据,再决定如何把图片分配到批次。
- 若 `sources` 为空或不完整:按精确文件名全库搜索,报告未解析或歧义匹配。
- **双向对账**:除嵌入→文件(唯一性/缺失/重名)外,还须做**文件→嵌入反查**——sources 目录中未被页面嵌入的文件逐张定性:先 MD5 比对时间近邻判断是否同图重复保存,再读图判定是 同题另拍 / 解析续页 / 独立题目;结论写入页面边界说明并留用户处置(raw 只读,不代移动/删除)。未嵌入 ≠ 可删,也可能藏着归属错目录的嵌入图。
- **视觉通道探测**:建 manifest 后、派发读图前,先按 §运行时与网关适配 做视觉通道顺序探测(`Read` 单图 → 视觉理解 MCP(如 zai-mcp-server)单图);两条通道都不可用才走降级(manifest 照建,视觉字段标"视觉未识别",基于已有文字提炼)。
2. **保留顺序**:已有 wiki 嵌入顺序是权威顺序;raw-only 图片集用自然文件名顺序;优化时不擅自重排嵌入,除非用户明确要求。
3. **覆盖风险检测(报告而不猜测)**:检测重名文件、缺失文件、非图片嵌入、位于 declared `sources` 之外的图片;**不要猜测**哪个重名图是意图所指——报告出来让用户/主 agent 决定。嵌入唯一命中其他 raw 目录(跨目录图片/同图双存)时:短文件名全库唯一即可正常解析、不算断链,按 vault 先例在 frontmatter `sources` **登记多个目录**,**不移动 raw 文件**。
4. **分析可追溯**:中间笔记放工作上下文或最终回复,**不写 `raw/`**;写 wiki 内容时用文件名 + manifest index 标识每张图。
## Subagent 批量分析(Claude Code 适配)
当用户明确要求 subagent / 并行 agent / 批量图片分析时,主 agent 用 Claude Code 的 **`Agent`(Task)工具**派发只读 subagent。
> 术语映射:Codex 侧现行接口是 `collaboration.spawn_agent(agent_type: "default")`;在 Claude Code 对应 `Agent` 工具调用,`subagent_type` 用项目自定义只读 subagent(如 `image-reader`)或内置 **`Explore`** 类型(同样只读)。**ZCode 运行时不加载项目 `.claude/agents/`**,可用类型为 general-purpose / Explore / judge,读图批次直接用 **Explore**(只读,且其 `Read` 与主线程一样可直接读图)。两侧职责划分一致。
**派发前类型解析(fallback 规则)**:
1. 优先项目自定义只读类型(如 `image-reader`,其角色定义、只读红线与视觉 MCP 工具授权由 agent 定义自动注入)。
2. 项目自定义类型不可用,或派发返回 `Agent type '...' not found`(错误消息会列出该运行时实际可用的类型清单)→ **不重试原类型**,同一批次立即改用内置 `Explore` 重发。
3. **契约自带要求**:用 `Explore` 等未注入项目 agent 定义的类型时,调用 prompt 必须完整自带 ①只读红线(只允许 `ls`/`Read` 读图,不编辑任何文件)②九字段输出契约 ③批次四件套——这些内容不会自动注入,漏写会导致输出格式不齐或红线缺失。
**主 agent 独占四件事**:manifest 建立、分批/分波、最终合成、所有写文件。subagent 只读图返回分析。
**分批与波次机制(支持 100–300 张大批量多 Agents 并行读图)**:
| 图片数 | 策略 |
|---|---|
| 1–10 | 主 agent 本地直接读取分析,除非委派更有利 |
| 11–30 | 拆成 2–3 个只读 subagent 批次 |
| 31+ | 拆成 ≤6 个只读 subagent 批次(单波并发上限 ≤6) |
**波次(waves)推进大批量**:
- **单批容量**:每个 subagent 单批控制在合理大小(默认每批 ≤30 张,沿用 11–30 档经验,避免单 subagent 上下文过载)。
- **单波并发**:每波同时派发 ≤6 个只读 subagent(单条消息内多个 `Agent` tool use 即并发)。Claude Code 动态 Workflow 理论并发上限为 16,但**第三方网关可用性未经验证**,保守取 ≤6。注意:网关并发与"读图视觉通道"是两个独立问题——某些网关下 `Read` 图片仅返回 CDN 上传回执而无视觉内容(见 §运行时与网关适配),需先做视觉通道顺序探测再决定读图方式:`Read` 可用则照常派发 Read 批次;`Read` 不可用但视觉 MCP 可用(见 §视觉理解 MCP 通道)时,subagent 已被授予视觉 MCP 工具则照常派发批次(subagent 用 MCP 工具替代 `Read` 读图),未授予则由主线程分批逐张调用 MCP 工具并按 manifest 对账。
- **多波推进**:当总量超过单波容量(如 100–300 张)时,以**波次**持续推进——主 agent 每波派发 ≤6 个 subagent 并行读图,每波返回后按 manifest 序号对账,再派发下一波,直到 manifest 全部图片处理完。波次数不限(300 张 ÷ 约 90 张/波 ≈ 2–4 波)。运行时并发低于批数时也以波次执行这同一批数目,**不增加批次总数、不削弱大批量能力**。
- **并发受限降级链**:派发报并发上限错误(如 `user concurrency limit exceeded` / `model concurrency limit exceeded`,多会话并行时常见)→ 降为**同批串行**逐个派发(批数与每批规模不变,串行批次每批约 130–250K subagent tokens 属正常水位);串行仍失败 → 主线程按批次自行读图。跨批 coverage 拼接(如题号连续性核对、跨页同题互证)由主线程归并,不依赖单个 subagent 的全局视野。
- **整卷/错题集类页面**:题库截图流手写合集页(整卷页、错题本)的双向对账表、作答统计、错题清单与跨页互证模板见 [references/exam-collection-playbook.md](references/exam-collection-playbook.md)。
> 这是对旧版"100+ 首轮 6 批后追加"粗糙表述的规范化:大批量(100–300 张)多 Agents 并行读图能力**保留并增强**为一等能力,对齐 Codex 版 `execute in waves` 思想。
**派发约定**:
- 给每个 subagent 一段 **bounded manifest slice**:绝对图片路径 + 稳定 manifest index(Claude Code 侧通过 Agent 工具 prompt 传入;Codex 侧用 `items` 的 `local_image` 条目)。
- **同一张图不派给多个 subagent**,除非在校验某个不确定读数。
- subagent 调用 prompt 模板——项目自定义类型(如 `image-reader`)契约已注入,可用简模板:
```
分析这批图片用于 Obsidian LLM Wiki 更新。只读,不编辑文件。
每张图按九字段输出契约返回一个 section,然后给批次总结。
严格保留 manifest index 与文件名。
```
`Explore` 等契约未注入的类型必须用**完整模板**(按序包含,全部为必备段):
```
① 角色与红线:只读图片分析助手,只允许 ls/Read 读图,不编辑任何文件。
② 目录:raw 图片目录的绝对路径。
③ 本批 manifest slice:manifest index 范围 + 确切文件名规则(默认扩展名 + 例外清单),
并要求 subagent 先 ls 核对文件名再逐张 Read。
④ 资料背景:来源与预期内容一段(帮助 subagent 定位主题、标注低置信读数)。
⑤ 逐张输出:九字段契约(字段名与含义逐项列出)。
⑥ 批次输出:四件套(batch_summary / repeated_ideas / contradictions_or_low_confidence /
wiki_section_candidates,候选章节六选)。
⑦ 转录要求:数据类截图(人数/金额/榜单/表格)务必精确转录数字;
装饰图、表情包、氛围图可简写。
```
**每张图输出契约(九字段)**:`manifest_index` / `filename` / `visible_text`(可见文字)/ `page_topic`(主题)/ `key_points`(关键要点)/ `diagrams_flows_ui`(图表/流程/UI 元素)/ `insights`(可提炼洞见)/ `confidence`(高/中/低)/ `unreadable_areas`(无法识别或不确定区域)。
**每批次输出(四件套)**:`batch_summary`(批次总结)/ `repeated_ideas`(跨图重复观点)/ `contradictions_or_low_confidence`(矛盾或低置信读数)/ `wiki_section_candidates`(建议归入章节:`图片内容解析` / `资料总结` / `洞见` / `方法论提炼` / `最佳实践` / `金句精选`)。
**归并对账**:subagent(含跨波次)返回后,**先比对 filename 与 manifest index** 再合成,防止张冠李戴、缺页或重复解析。
## 运行时与网关适配(视觉通道 + 读图降级 + 大文件日志)
本 Skill 默认假设主 agent 与只读 subagent 的 `Read` 能正常解析图片像素。但**第三方网关(如智谱 GLM、MiniMax 等兼容 Anthropic 协议的网关)的多模态下推链路未必启用**:实测在某些网关下,`Read` 图片只返回"文件已上传至 CDN"的文本回执(含一个 URL),**不向模型返回视觉内容**——主 agent 与 subagent 都"看不见"图。此时**视觉理解 MCP**(如智谱 `zai-mcp-server`,接入 GLM-4.6V)可作为独立于网关的视觉通道。本节规定三级视觉通道(`Read` → 视觉 MCP → 降级)的探测与降级流程,避免空转、避免虚构。
### 视觉理解 MCP 通道(zai-mcp-server)
第三方网关 `Read` 失效时的首选兜底视觉通道:智谱官方 Local MCP Server `zai-mcp-server`(npm 包 `@z_ai/mcp-server`,接入 GLM-4.6V;官方文档 https://docs.bigmodel.cn/cn/coding-plan/mcp/vision-mcp-server ),配置于 `~/.claude.json` 顶层 `mcpServers`。安装步骤与 API Key 配置说明见本 skill README 的「视觉 MCP 配置(可选)」一节;**配置示例中的 API Key 一律用占位符,绝不把真实密钥写进任何文件或日志**。
**工具清单与 wiki 九字段映射**(以实际安装的工具名为准;智谱文档中的 `image_analysis` / `video_analysis` 对应实际安装名 `analyze_image` / `analyze_video`):
| 实际工具名(`mcp__zai-mcp-server__` 前缀) | 用途 | 映射到九字段输出契约 |
|---|---|---|
| `analyze_image` | 通用图像理解(兜底);`image_source` 支持本地绝对路径与远程 URL | 全字段 |
| `extract_text_from_screenshot` | OCR 文字提取(可指定 programming_language) | `visible_text` |
| `understand_technical_diagram` | 架构/流程/UML/ER 图结构化解读 | `diagrams_flows_ui` |
| `analyze_data_visualization` | 图表/仪表盘数据提炼 | `diagrams_flows_ui` + `key_points` |
| `diagnose_error_screenshot` | 错误弹窗/堆栈/日志截图诊断 | wiki 场景少用 |
| `ui_to_artifact` | UI 截图转代码/提示词/设计规范 | wiki 场景少用 |
| `ui_diff_check` | 对比两张 UI 截图差异 | 校验场景 |
| `analyze_video` | 视频解析;本地文件 ≤8MB,MP4/MOV/M4V | 拓展能力(如视频类领域) |
**调用约定**:
- `image_source` 传**本地绝对路径**(中文与空格路径直接传,不走 PowerShell 管道);单图单工具调用,逐张按 manifest index 对账。
- 按图型选工具:常规截图/扫描件用 `analyze_image` 兜底;文字密集图优先 `extract_text_from_screenshot`;架构/流程图优先 `understand_technical_diagram`;统计图表优先 `analyze_data_visualization`。
- **隐私边界**:视觉 MCP 是云端通道,图片内容会上送智谱服务器处理;涉及敏感资料时先经用户确认再走此通道。
- **subagent 授权**:要让只读 subagent(如 `image-reader`)在此通道下读图,项目需在其 agent 定义的 `tools` 中显式授予对应 `mcp__zai-mcp-server__*` 工具;未授予时由主线程分批逐张调用。改用 `Explore` 等未授予 MCP 工具的类型时同样回退主线程逐张调用,并按 manifest index 对账。
### 图片读取能力探测(读图前必做一次)
- **顺序探测**(用同一张代表性图,优先概念图、含文字最多的图,如"X VS Y"对比图):
1. **`Read` 单图探测**:返回内容含图片视觉信息 → **Read 视觉通道可用**,走正常 subagent 批量分析(§Subagent 批量分析)。
2. **视觉 MCP 单图探测**:`Read` 仅返回 `... has been uploaded to CDN and is available at: https://...` 文本回执时,调 `mcp__zai-mcp-server__analyze_image` 并把该图**本地绝对路径**传入 `image_source`:返回真实视觉内容 → **视觉 MCP 通道可用**,按 §视觉理解 MCP 通道 的调用约定读图。
3. 两级探测都失败(MCP 未配置 / 调用报错 / 无视觉内容)→ 进入降级流程。
- **通道能力矩阵**(集中维护,验证后更新;顺序探测机制使其自纠正,矩阵过期也不影响判断)。`Read` 视觉可用性由**运行时 × 网关/模型**两维共同决定,不单看网关:探测失败多为该组合的多模态下推链路未启用,而非模型能力问题(GLM 本身是多模态模型)——同一模型在不同运行时可能结论相反:
- 官方 Anthropic API:`Read` 视觉可用(默认)。
- Claude Code + 智谱 GLM 网关:`Read` **已验证不可用**(仅返回 CDN URL 回执,无视觉内容;主线程与 subagent 同失效);`zai-mcp-server` 视觉 MCP **已验证可用**(2026-08-19 本地实测:`analyze_image` 以含中文与空格的本地绝对路径成功返回完整视觉描述与文字转录)。
- ZCode 运行时(GLM 模型):`Read` 视觉**已验证可用**(2026-09-05 实测,主线程与 Explore subagent 一致,可直接读本地中文路径图片);与上一行不矛盾——可用性按"运行时 × 网关"组合记录。
- `4_5v_mcp`(GLM Coding Plan 服务端内置的 image_analysis 通道):仅支持远程 URL,本地 raw 图片不适用。
- MiniMax 网关:**未验证**(待测;若在此网关下,先做顺序探测,把结果回写本节)。
- 探测结果写入当次 `log.md` 条目(视觉通道:Read 可用 / 视觉 MCP 可用 / 均不可用 + 运行时名 + 网关/模型名)。
### 视觉不可用时的降级流程
**两条视觉通道(`Read` 与视觉 MCP)都不可用时**才进入降级。降级**不等于放弃**:image manifest 的建立、文件名/顺序/来源匹配、缺失与重名检测都是**文件系统层**操作,不需要视觉。降级按六步:
1. **照常建 image manifest**(§图片密集资料分析):按文档顺序提取 `![[...]]`、解析短文件名、与 raw 目录对账、检测重名/缺失/越界。manifest 完整性与视觉无关。
2. **视觉识别字段全部标"视觉未识别"**:`visible_text` / `key_points` / `diagrams_flows_ui` / `insights` 等"需要看图"的字段不填、不猜,统一标注"视觉未识别(当前网关多模态通道与视觉 MCP 均不可用)"。
3. **基于已有文字做高维度提炼**:页面已有逐字稿/正文/结构表/金句等文字(典型如飞书 doc 抓取页)时,完全可基于这些文字完成"资料总结/洞见/方法论提炼/最佳实践/金句精选"——它们不依赖图片视觉。
4. **概念图概念补充须标注来源**:某张概念图(如"平等 VS 公正"对比图)承载的概念若在正文已有文字阐释,可引用正文作补充,但必须明确写"基于正文,非图像识别"。
5. **不重复空转**:视觉不可用时**不再**派发读图 subagent、也不再逐张调用视觉 MCP(派了也是空回执或报错);把"图片视觉内容待多模态通道或视觉 MCP 恢复后补录精确转写"记为**未决项**,写进 `log.md` 与页面"图片内容解析"节。
6. **不虚构**:绝不依据文件名或上下文猜测图中具体文字、人物、数字、颜色并当作识别结果写入。
> 项目侧若已声明视觉通道与降级路径(如项目 `CLAUDE.md` 的 Claude Code 适配章节),以项目声明为准;本节是通用兜底。
### log.md 追加(大文件安全)
`log.md` 随维护累积会变得很大(实测单个 vault 的 `log.md` 可达数百 KB)。`Read` 工具有大小上限(约 256KB),大 `log.md` **整文件读不了**,也就无法用"读末尾 → Edit 锚点"的方式追加。
#### 第 0 步:追加前固定预检(写入型任务必跑)
适用:`ingest` / `optimize` / `migrate` / `index` / 删除、归档、改名 / 实施修复的 lint / 其他产生了文件变更并要写最终日志的工作流。`query`、只读 lint/audit、`log status`、`log query` 与无文件变化的任务**不跑预检、不轮转**。
先构造完整待追加文本(含前置分隔换行与末尾换行;一个任务只对应一条最终条目),再调用本 Skill 自带的固定只读脚本 `scripts/log-preflight.ps1`(默认阈值 2 MiB;投影超阈值或活动日志跨年即 `rotation_due=true`):
- Git Bash / Claude Code——多行中文文本必须走 Base64 通道,规避命令行换行/引号/编码风险:
```bash
PENDING_B64=$(printf '%s' "$PENDING" | base64 -w0)
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "<skill_base>/scripts/log-preflight.ps1" \
-VaultRoot "<vault_root>" -PendingAppendB64 "$PENDING_B64" -ThresholdMiB 2 -Json
```
`PENDING` 与 `PENDING_B64` 全程用命令内变量构造(heredoc / 命令替换),**禁止为预检或追加在 vault 或项目目录落盘中转文件**;对账类中间产物(嵌入清单、文件清单对比等)优先用进程替换内联(如 `diff <(cmd1) <(cmd2)`);确需临时文件时放系统临时目录并在任务收尾自动删除(见「安全规则」的任务临时文件自动清理条目)。
- 原生 PowerShell(Codex 或 pwsh 会话)——可直接传明文参数:
```powershell
& "<skill_base>\scripts\log-preflight.ps1" -VaultRoot "<vault_root>" -PendingAppend "<完整待追加文本>" -ThresholdMiB 2 -Json
```
`rotation_due=false` → 按下方方式追加并做完整性验证。`rotation_due=true` → 读 [references/log-rotation.md](references/log-rotation.md) 执行轮转,轮转完成后把本任务条目追加到新的 `log.md`。预检脚本**只读**:不创建/修改/移动/删除文件、不写临时文件、不输出日志正文;**不得**用临时生成的 Python/PowerShell/bash 代码替代,也不为常规检查创建状态或缓存文件。
#### 追加方式(append-only,无需整读)
- **首选:直接追加到文件末尾(append-only,无需锚点)**。`log.md` 是 append-only,新条目永远加在 EOF,不需要读旧内容:
- bash(Git Bash / WSL)——用引号封闭定界符的 heredoc,防变量展开,内部反引号/代码栏安全:
```bash
cat >> "路径/log.md" <<'LOGEOF'
## [YYYY-MM-DD] <操作> | <标题>
- <条目内容>
LOGEOF
```
- PowerShell——`Add-Content` 默认追加,中文/带空格路径用 `-LiteralPath`,UTF-8 编码,不走管道(与既有"不通过管道喂 Python"安全规则一致):
```powershell
Add-Content -LiteralPath "路径\log.md" -Encoding UTF8 -Value @"
## [YYYY-MM-DD] <操作> | <标题>
- <条目内容>
"@
```
- **次选:Edit + tail 锚点**(文件仍可被 `Read` 时):`tail -n 5` 取末尾几行作 Edit 的 `old_string`(取含独特上下文的行保证全文唯一,必要时多取几行),再 Edit 追加。
- **禁止**:为追加条目而 `Read` 整个大 `log.md`(触发大小上限失败并浪费上下文)。
- **抽查**:追加后用 `tail -n 3` 或 `grep` 确认新条目落位正确即可,不必整读。
#### 追加前后完整性验证(低 Token)
追加前:`wc -c` + `sha256sum` 记录原字节长度与整文件哈希;内部用 `tail -n 80`(必要时至多 200 行)核对精确任务标题是否已存在(已存在则不重复追加),只把末尾唯一 2–4 行与判定结果带回上下文,**不回传整个尾部**。
追加后:
- 长度增量 == 待追加文本的 UTF-8 字节数(即预检返回的 `pending_bytes`);
- `tail -n 80` 内精确任务标题恰好出现 1 次,且新条目是最后一条;
- `tail -c 1` 确认文件仍以换行结束;
- `head -c <原字节长度> "<log.md>" | sha256sum` == 追加前整文件 SHA-256,证明既有字节未被改动。
任一项不满足:如实报告失败,不宣称 append-only 成功。同一任务只追加一条最终记录,不为中间步骤重复写日志。
> 说明:用户直觉里的"用 tail 做新增"映射为"shell 文件末操作"——`tail` 用于取锚点/抽查,实际写入用 `>>` / `Add-Content`(tail 本身只读不写)。
## Index Metadata And Statistics
`index.md` 是知识库的内容目录,**LLM 维护**。它有固定的**顶部维护块**、**底部统计行**与**索引健康行**,本节规定其精确格式、字段语义、六变量计数口径、同步契约与校验规则。所有写命令(ingest / optimize / extract-thinking-frameworks / index / migrate / delete / query-归档)以及 lint 校验都必须遵守本节。
> **不在 `index.md` 上引入 YAML frontmatter**。日期、计数、操作摘要都由正文/斜体/引用块承载;变更历史由 `log.md` 承担。
>
> 本节使用**六个变量**(与项目 schema、实际 vault 页脚一致):三权威变量 `indexed_page_count` / `wiki_file_count` / `registered_domain_count`,三健康变量 `missing_count` / `broken_count` / `duplicate_count`。**不得用 `wiki_file_count` 代替 `indexed_page_count`**——两者必须独立验证。
### Index 文件结构总览
`index.md` 由四部分组成,按出现顺序固定:
1. **顶部维护块**(2 个 `>` 引用行 + 1 个 `---` 分隔线)— 见 §Index 顶部维护块
2. **章节主体**(一个或多个 `## <领域路径>` 章节;每个章节下 1 张三列表,列头固定为 `| 页面 | 摘要 | 标签 |`、分隔行 `|---|---|`)— 见 §Index 章节与表格规范
3. **底部统计行**(倒数第二行的 `>` 索引健康行 + 最后一行的斜体统计行)— 见 §Index 底部统计与索引健康行
各部分之间**必须**用 `---` 分隔线隔开;不允许出现其他段落、HTML 注释、或 H1 之外的标题(H2 章节允许)。
### Index 顶部维护块
#### 字面模板
```markdown
# 知识库索引
> 由 LLM 维护。上次更新:<YYYY-MM-DD>(<简洁动作摘要>)。
> 格式:`[[页面标题]]` — 一句话摘要
---
```
#### 字段语义
- `<YYYY-MM-DD>`:本次更新本地日期(4 位年 - 2 位月 - 2 位日,零填充)。**不变量**:必须与底部统计行的日期、`log.md` 本次条目日期、今天本地日期**字面一致**。
- `<简洁动作摘要>`:本次动作的动词短语;可含命令名、涉及页面/Schema 名;涉及多文件时可缩为 `A.md、B.md 等 N 个 wiki 页面`。**不再强求文件列表**(如本次仅刷 Schema,摘要可只写一句)。
- 第 2 行 `> 格式:...` 是**只读脚注**,永远不修改(除非全文件结构改版)。
**操作摘要建议用语**(非字面契约,仅供措辞参考):
| 场景 | 建议摘要 |
|---|---|
| `ingest` / `query-归档` | `同步索引:新增 1 个页面(<页面名>)` |
| `optimize`(摘要未变) | `同步索引:刷新 1 个页面(<页面名>)` |
| `optimize`(摘要已变) | `同步索引:更新 1 个页面(<页面名> 摘要变)` |
| `extract-thinking-frameworks` | `同步索引:新增 1 个页面(<框架名>,归入 提炼思维)` |
| `index`(全量重建) | `同步索引:补登 X 个页面、修正 Y 个链接、去重 Z 个重复条目`(X/Y/Z 为本次 diff;必要时附 `统计漂移修正`) |
| `migrate` | `同步索引:迁移 N 个页面至 wiki/<领域>/` |
| `delete` | `同步索引:移除 1 个页面(<页面名>)` |
| 补录既有页面 | `同步索引:补录既有页面 <页面名>` |
| Schema 同步(非 wiki 变更) | `同步 AGENTS.md 与 CLAUDE.md Schema,并统一索引统计口径` |
| 完全不写 index 的只读操作(`query` 未归档、`lint` 不写) | 顶部维护块**整体不更新**,日期保持上一次;但 `log.md` 必须有 "index.md:已检查,无需本次修改" |
### Index 章节与表格规范
- 一律用 `## <领域路径>` 二级标题;领域路径用 ` / ` 分段(半角斜杠 + 两侧空格)。
- 顶级段必须与 schema `## 领域注册表` 的"领域"列**语义一致**(不强制字面相等,因为 schema 可能有"一堂/创业者修炼"而 index 有"一堂")。
- 同级章节按顶级段 → 二级段字典序排列;用户手动调整顺序时**尊重用户**,但**禁止出现空章节**(只有标题无表格)。
- 表格列头**必须**固定为 `| 页面 | 摘要 | 标签 |`,分隔行**必须**为 `|---|---|`。
- 数据行**必须**形如 `| [[<页面标题>]] | <一句话摘要> | <inline tags> |`。
- 一行 = 一个 wiki 页面。**禁止同一行两个 `[[]]`**。
- 同一 `##` 章节下**禁止出现重复行**(按 `[[<页面标题>]]` 字段去重)。
- 摘要列**只放摘要**,不写正文片段、不放链接(链接在 `## 相关` 章节正文里)。
### Index 底部统计与索引健康行
文件**最后两行**固定为:倒数第二行 `>` 索引健康行,最后一行斜体统计行。
#### 字面模板
```markdown
_统计:{indexed_page_count} 个已索引页面 | {wiki_file_count} 个 Wiki 文件 | {registered_domain_count} 个注册领域 | 上次更新于 YYYY-MM-DD_
> 索引健康:未收录 {missing_count} | Markdown 断链 {broken_count} | 重复条目 {duplicate_count};`.canvas`、示例占位和 `raw/...` 链接不计入页面数。
```
#### 字段语义
- **统计行**(斜体,前后各 1 `_`,文件最后一行):三个权威变量 + 日期。
- **索引健康行**(`>` 引用块,倒数第二行,永远在统计行之前一行):三个健康变量 + 尾部说明。尾部说明文字(`.canvas`、示例占位、`raw/...` 不计入页面数)是只读脚注,不修改。
- `<YYYY-MM-DD>`:与顶部维护块**字面一致**。
### Index 六变量计数口径
#### 三权威变量
| 变量 | 定义 | 计数口径 |
|---|---|---|
| `indexed_page_count` | 可解析到真实 `wiki/**/*.md` 且**去重后**的索引条目数 | 抽取 index 所有 `\| [[<target>]] \|` 数据行的 target → 按**三形式**在 `wiki/**/*.md` 查找:① `[[wiki/路径/标题]]` 全路径、② `[[子路径/标题]]` 相对路径、③ `[[标题]]` 裸 stem(①②按路径 + `.md` 精确匹配,③按 stem 兜底)→ 命中且唯一则计入;同一 wiki 文件多次出现只计 1 次。**带 `wiki/` 前缀的全路径条目是合法索引形式**,不得按裸 stem 口径误报为断链/未收录 |
| `wiki_file_count` | 实际 `wiki/**/*.md` 文件数 | glob 扫描,排除 `index.md` / `log.md` / `*.canvas` / `templates/` / `assets/` |
| `registered_domain_count` | 领域注册表数据行数 | 读 schema `## 领域注册表` 表,去表头与分隔行后的数据行数 |
#### 三健康变量
| 变量 | 定义 | 含义 |
|---|---|---|
| `missing_count` | 有 wiki 文件但无唯一可解析索引条目覆盖 | 应补录;>0 报告或补录 |
| `broken_count` | 无法唯一解析且不属于排除项的 index 链接 | title 未命中、或命中华歧义;应修正或摘除 |
| `duplicate_count` | 同一真实 wiki 页面在 index 中的额外重复条目 | 同 path 被 ≥2 条目解析 → +(出现数 − 1);首次出现不计 |
**机检**:
- **快校(lint 用,上限预警)**:保留旧 awk 一行版,重命名为 "raw entry count"(仅数 `| [[` 候选行,不去重、不解析),作为漂移预警的快检上限——**不是** `indexed_page_count` 的精确值。awk 状态机实现有漏计风险(多表连续等场景可能漏数),精确对照以全文件 `grep -c '^| \[\['` 或精校脚本为准。
- **精校(所有写命令用)**:**直接运行 Skill 自带固定脚本 [references/index_stat.py](references/index_stat.py)**,不要每次临时新写脚本。脚本实现与本条口径一致:扫 `wiki/**/*.md` 建路径表与 stem 索引 → 解析 index 数据行 target → 按三形式解析(见 `indexed_page_count` 口径)→ 命中(dedupe by path,记 `indexed_page_count`)/ 未命中或歧义(`broken_count`)/ 未被命中(`missing_count`)/ 同 path 重复(`duplicate_count`);`wiki_file_count` = 文件表 size;`registered_domain_count` = schema 注册表数据行数。脚本额外输出未收录/断链/重复明细、双入口注册表行数对照、**页脚旧值 vs 扫描值漂移报告**(供『统计漂移修正』,`footer_match=true` 即页脚无漂移);`--json` 为机读模式(`broken` 明细为 `{"target", "reason"}` 对象数组,后处理时勿整串 `str()` 后再做字符串匹配)。脚本不可用时按本条算法降级手工执行。
```bash
# 快校 awk 一行版(raw entry count 上限,非精确 indexed_page_count)
awk '/^\| 页面 \| 摘要 \| 标签 \|/{t=1;next} t==1 && /^\|---/{t=2;next} t==2 && /^\| \[\[/ {c++} t==2 && /^## /{t=0} END{print c+0}' index.md
# 精校固定脚本:<skill_base> 为本 Skill 基目录(Skill 加载时给定),<vault> 为知识库根目录;
# Python 按 §文档预处理与运行环境 优先级取(项目 .venv 首选);输出六变量 + 明细 + 页脚漂移对照
"<python>" "<skill_base>/references/index_stat.py" "<vault>" # 人类可读
"<python>" "<skill_base>/references/index_stat.py" "<vault>" --json # 机读
```
**排除项**(不计入页面数):`.canvas` 文件、图片、附件、`raw/...` 源链接、生成产物、外部链接、schema 文件、`[[页面标题]]` 这类示例占位、`templates/` 与 `assets/` 下的模板。
#### 计数漂移处置
- **首次补录**(`补录既有页面` / first-time index backfill):wiki 文件存在但 index 无条目 → 加条目,`indexed_page_count` +1,log 标 `补录既有页面`。
- **统计漂移修正**(`统计漂移修正`):旧 footer 与实际扫描结果不符 → 用新扫描值覆盖全部六个变量,log 标 `统计漂移修正`;**绝不**在旧值上递增。
- **仅摘要/标签/路径文字变化**(链接解析与去重未变):`indexed_page_count` 不变。
- **创建/删除/迁移/改名/归档/去索引/补录**:六变量全部重算。
### 同步契约 / 增量与全量分工
**同步契约不变量**:
```
顶部 <YYYY-MM-DD> == 底部统计行 <YYYY-MM-DD> == log.md 本次条目日期 == 今天(本地)
indexed_page_count == 当次扫描去重后解析的 index 条目数(不沿用旧值)
wiki_file_count == 当次 wiki/**/*.md 文件数
registered_domain_count == schema 领域注册表数据行数
missing_count / broken_count / duplicate_count == 当次扫描结果
统计行与索引健康行各只出现 1 次
```
**写命令的标准操作流程**(落盘 index.md 前必走):
1. 完成 wiki 页面变更(创建/修改/删除)
2. 决定 `<简洁动作摘要>`(按 §Index 顶部维护块 建议用语表,允许简洁版)
3. 在 `index.md` 上做增量修改
4. 运行 §六变量计数口径 精校 → 得六变量新值(精校前先快查 `wiki/**/*.md` 文件数与上轮差异,防并行投放污染计数,见 §并行会话干扰防护)
5. 顶部维护块 + 底部统计行 + 索引健康行 **同一次编辑**同步替换(三处日期字面一致)
6. **页脚写后复验**:三处同步完成后**必须重跑精校**,扫描值与页脚一致(`footer_match=true`)方可收尾;若复验发现精校期间出现并行投放/新条目导致漂移,**按最终扫描值二次覆盖页脚**并再次复验
7. 若涉及双入口 schema 变更(如新领域),同步编辑 `AGENTS.md` + `CLAUDE.md` + 验 SHA-256
8. `log.md` 追加一条最终记录(含 `AGENTS.md` / `CLAUDE.md` / `index.md` / frontmatter 四项 + 六变量 + `indexed_page_count` 变化/不变/漂移修正 标识)
9. 写后自检(快校 awk + 精校固定脚本 [references/index_stat.py](references/index_stat.py);统计行与健康行各只出现 1 次)
### 并行会话干扰防护(多会话同时维护同一 vault 时)
并行会话会同时改 `index.md`、`log.md`、新建页面,统计与锚点因此漂移。写型任务全程遵循:
1. **精校前快查漂移**:对比 `wiki/**/*.md` 文件数与上轮已知值;发现新投放文件 → 只报告并留给对应会话/用户,不代补录(missing 明细只是快照)。
2. **页脚以最终扫描值为准**:校验期间每次发现文件数/条目变化,页脚按当次扫描值重新覆盖,绝不沿用上轮手算值递增。
3. **modified-since-read 重读协议**:Edit/Write 报 "File has been modified since read" → 重读该文件相关段落,确认锚点仍有效后重试;同步盘触碰 mtime 但内容未变时(可用 `wc -c` + 时间戳佐证)重读即过,勿当冲突硬改。
4. **log-preflight 结论沿用前先验状态**:预检与追加之间存在窗口,沿用早前预检结论前先 `wc -c` + `sha256sum` 确认 `log.md` 未被并行会话动过;不一致则重跑预检。
5. **PENDING 文本不跨命令持久**:shell 变量不跨工具调用存活,待追加文本必须在追加命令内重建;两次构造须逐字一致(字节增量对账就是抓"两次粘贴不一致"的探测器)。
6. **验证链防退出码截断**:`grep -c` 计数为 0 时退出码 1,会截断 `&&` 链——预期可能为 0 的计数校验一律加 `|| true`;控制台中文回显乱码(GBK/UTF-8)时改用 Read 工具或脚本 `--json` 输出核验,不以终端回显为准。
**增量 vs 全量分工**:
| 命令 | 模式 | 落盘动作 |
|---|---|---|
| `ingest` / `optimize` / `extract-thinking-frameworks` / `migrate` / `delete` / `query-归档` | **增量** | 在对应 `## <领域>` 章节追加/修改/删除一行;刷新顶部维护块 + 底部统计行 + 索引健康行 |
| `/index` | **全量** | 完整扫描 `wiki/**/*.md`,重算后整文件重写;与增量互为补集 |
| `/lint` | **不动 index**,只校验 | 见 §Index lint 校验规则 |
**何时必须走全量(`/index`)**(增量无法修复时):
- 顶部日期 ≠ 底部统计行日期
- `indexed_page_count` ≠ 扫描结果
- `wiki_file_count` ≠ 扫描结果
- `registered_domain_count` ≠ schema 注册表行数
- 任一健康变量 ≠ 扫描结果
- 同一 `##` 章节下出现重复行
- 顶级段集合 vs schema 领域注册表集合差集非空
- 用户显式要求"重建索引"
### Index lint 校验规则
`/obsidian-llm-wiki lint` 在原有步骤之上**追加 index.md 专项校验**:
1. 解析 `index.md` 抽取顶部维护块、底部统计行、索引健康行、全部 H2 章节。
2. 顶部维护块字面合规(正则 `^> 由 LLM 维护\.上次更新:(\d{4}-\d{2}-\d{2})(.+)\n> 格式:.+`)。
3. **底部统计行**字面合规(正则三变量版):`^_统计:(\d+) 个已索引页面 \| (\d+) 个 Wiki 文件 \| (\d+) 个注册领域 \| 上次更新于 (\d{4}-\d{2}-\d{2})_$`。
4. **索引健康行**字面合规(正则):`^> 索引健康:未收录 (\d+) \| Markdown 断链 (\d+) \| 重复条目 (\d+);.+。$`。
5. 顶部日期 = 底部统计行日期 = 今天。
6. **快校**:awk 数候选行数 ≥ `indexed_page_count`(上限校验)。
7. **精校**:运行 [references/index_stat.py](references/index_stat.py)(或按 §六变量计数口径 手工扫描)得六变量;分别与统计行三数 + 健康行三数核对(脚本自带页脚对照与漂移报告)。
8. 校验统计行与索引健康行**各只出现 1 次**(grep 计数 = 1)。
9. 校验每个 `## <领域>` 章节下有且仅有一张表,表头/分隔行/数据行格式合规。
10. 校验同一章节内数据行不重复(按 `[[<页面标题>]]` 去重)。
11. 校验顶级段集合与 schema `## 领域注册表` 集合的差集,报告。
12. **双入口 schema 字节一致**:存在 `AGENTS.md` + `CLAUDE.md` 时校验两文件字节相同(或按 vault 声明的契约);不一致则报告。
13. 报告格式:每条不通过一项给出一行"`index lint 失败:<原因> + 建议动作(增量修复 / 走 `/index` 全量重建 / 双入口同步并验 SHA-256)`"。
14. **lint 不自动修改 `index.md`**;但若全量重建条件成立,提示用户"建议运行 `/obsidian-llm-wiki index`"。
### Index 反例 / 常见错误
- **A**:顶部维护块只有 1 个 `>` 引用行(漏了"格式:..."脚注)→ lint 报"顶部维护块缺格式说明行"。
- **B**:底部统计行用了粗体 `**统计:...**` → grep 难定位;lint 报"底部统计行非斜体"。
- **B'**:底部统计行用旧两变量模板 `_统计:421 个页面 | 18 个领域 | ..._` → lint 报"底部统计行非三变量模板,疑似旧版残留"。
- **C**:日期写成 `2026/6/23`(斜杠、无零填充)→ 不符合契约;lint 报"日期格式不符 YYYY-MM-DD"。
- **D**:`indexed_page_count` 与扫描结果差 N → lint 报"`indexed_page_count` 漂移",建议走 `/index` 全量重建。
- **E**:`## 一堂 / 创业者修炼` 与 `## 一堂/创业者修炼`(" / "两侧少空格)混用 → 顶级段解析不一致;lint 报"领域路径格式不一致"。
- **F**:在 `index.md` 中插入 H1 之外的 H2/H3 章节(如 `### 索引说明`)→ 不在契约内;lint 报"未声明的 H3 章节"。
- **G**:在表格行里写两个 `[[]]`(如 `| [[A]] 与 [[B]] | ... | ... |`)→ 一个数据行被当两个页面;lint 报"数据行多 wiki 链接"。
- **H**:`optimize` 改了页面摘要但忘了刷 `index.md` 的摘要列 → 摘要与 index 不一致;`/lint` 应同时校验"页面 frontmatter 一句话摘要"与"`index.md` 同行的摘要列"内容一致。
- **I**:缺少索引健康行 → lint 报"缺索引健康行;按 §Index 底部统计与索引健康行 补齐"。
- **J**:双入口 schema SHA-256 不等 → lint 报"AGENTS.md 与 CLAUDE.md 字节不一致;按 vault 契约同步两文件并验 SHA-256"。
- **K**:用 `wiki_file_count` 代替 `indexed_page_count` 填入统计行 → lint 报"不得用 `wiki_file_count` 替 `indexed_page_count`;两者必须独立验证"。
## 命令
### /obsidian-llm-wiki ingest \<source\>
处理 `raw/` 中的新来源,集成到 wiki。
1. 确认来源文件在 `raw/` 对应目录中
2. **文档预处理**(条件性):PDF 必须走 Skill 固定脚本 `scripts/preprocess_pdf.py`(先读 references/pdf-preprocessing.md,见「文档预处理运行时」),收尾按 temp-cleanup.md 清理任务目录;DOCX/PPTX/XLSX 或大量图片在 `scripts/` 就位时用 `.venv` 预处理并建立 manifest;PDF 依赖未就位时用 Read 的 `pages` 参数直读
3. **图片密集分析**:图片密集资料按 image manifest 分析;先做视觉通道顺序探测(`Read` → 视觉 MCP,见「运行时与网关适配」),超过 10 张派只读 subagent 并行分析,100–300 张以波次推进(见「Subagent 批量分析」)
4. **核对 manifest**:阅读/分析时核对覆盖率、顺序、缺失、重名,异常先报告
5. 与用户讨论关键要点
6. 在 `wiki/` 对应目录创建摘要页面:
- 读项目 schema 确定领域和路径映射
- 选合适模板(项目 `templates/` 或 Skill `assets/`)
- 加 YAML frontmatter(七字段,按 schema 规范)
- 加 inline tags(与 frontmatter 匹配)
- 含一句话摘要
- 图片分析结果整理进 `图片内容解析` / `资料总结` / `洞见` / `方法论提炼` / `最佳实践` / `金句精选` 六节
- 加「相关」和「来源」部分
7. 更新与新内容相关的已有 wiki 页面
8. **运行强制维护遍历**。若 `index.md` 改变(新页面 → `indexed_page_count` +1;补录既有页面 → +1 且 log 标 `补录既有页面`;仅摘要/标签变 → 不变),按 §Index Metadata And Statistics 重算六变量,**同一次编辑**刷新顶部维护块 + 底部统计行 + 索引健康行;追加 `log.md` 条目 `## [YYYY-MM-DD] ingest | <标题>`,日期与 index 顶部/底部字面一致,含 AGENTS/CLAUDE/index/frontmatter 四项 + 六变量 + `indexed_page_count` 变化标识。
### /obsidian-llm-wiki query \<问题\>
使用 wiki 回答问题。
1. 读项目 schema 了解架构
2. 读 `index.md` 了解可用内容
3. 从索引定位相关 wiki 页面
4. 读相关页面
5. 综合答案,引用页面 `[[标题]]`
6. **运行强制维护遍历**(query 默认只读 → **只报告** schema/index gaps,不自动修改)
7. 询问用户是否将答案归档为新 wiki 页面;若是,创建页面并更新 index.md(按 §Index Metadata And Statistics 重算六变量)和 log.md
### /obsidian-llm-wiki query-image \<图片…\> [问题]
以图片为主输入、可搭配文字问题查询 wiki(试题截图、图表、扫描件等找相似页面)。**视觉能力是硬性前提**。
1. **视觉通道预检**:按 §运行时与网关适配 的「图片读取能力探测」顺序探测(`Read` 单图 → 视觉 MCP 单图);两条通道都不可用 → 报告当前运行时/模型不支持视觉、无法执行本命令并终止,可提示改用纯文字 `query`;本命令不降级空跑
2. **读图提取查询要素(自动并行)**:按输入图片数量自动套用 §Subagent 批量分析 的分批与波次机制:1–10 张主线程直读;11–30 张拆 2–3 个只读 subagent 批次;31 张以上 ≤6 批次、单波并发 ≤6 波次推进;批次随图片数量自动增减
3. **轻量查询要素契约(每张图)**:可见文字(题干/正文)、代码片段、关键实体与检索关键词、无法辨认区域(显式标「存疑」);本命令以检索为目的,不要求 ingest 的九字段全量契约
4. 合并图片要素与用户文字问题,形成检索关键词集合
5. **按 query 流程作答**:执行 `/obsidian-llm-wiki query` 步骤 2–5;答案须区分「图片识别内容 / 库内事实 / 推论」,图片模糊或无法辨认处显式标注存疑,不得虚构图片内容
6. **运行强制维护遍历**(query-image 默认只读 → **只报告** schema/index gaps,不自动修改)
7. 询问用户是否将答案归档为新 wiki 页面;输入图片默认不入 `raw/`(归档页为纯文字,来源说明标注「查询输入截图」);用户明确要求图片入库时才按 ingest 流程补 image manifest
### /obsidian-llm-wiki optimize \<page\>
优化已有 wiki 页面(结构、表达、交叉引用),**不删除已有图片嵌入**,不破坏已有 wiki 链接。
1. 读目标页面,读其 `sources` 对应的 raw 资料
2. 页面图片 ≤10 张:读全部图片后优化;>10 张:先确认用户是否读全部,或仅基于已有文字优化
3. 优化 frontmatter(补缺失字段、更新 `updated`;frontmatter 修复是结构例外,append-only 体优化时仍可置正文前)、结构、表达
4. 追加内容(如需)插在 `## 相关` 之前;图片分析结果整理进六节
5. 检查并补充缺失的交叉引用
6. **运行强制维护遍历**。若 `index.md` 改变:摘要未变 → 顶部维护块摘要 = `同步索引:刷新 1 个页面(<页面名>)`;摘要已变 → `同步索引:更新 1 个页面(<页面名> 摘要变)`;**`indexed_page_count` 不变**(除非链接解析或去重变化)。按 §Index Metadata And Statistics 重算六变量并同步三处;追加 `log.md` 条目 `## [YYYY-MM-DD] optimize | <标题>`,日期字面一致。
### /obsidian-llm-wiki extract-thinking-frameworks
从 wiki 内容中提炼通用方法论与思维模型,归入 `wiki/提炼思维/`(无 raw 层)。
1. 扫描 `wiki/` 找反复出现的方法论、框架、模型
2. 与用户讨论提炼方向
3. 在 `wiki/提炼思维/` 创建独立页面(frontmatter `domain: 提炼思维`)
4. 在源页面添加 `[[提炼出的框架]]` 交叉引用
5. **运行强制维护遍历**。若 `index.md` 改变:在 `## 提炼思维` 章节追加一行;重算六变量;`registered_domain_count` 按 schema 注册表行数取("提炼思维"若首次进注册表则 +1);追加 `log.md` 条目 `## [YYYY-MM-DD] extract-thinking-frameworks | <标题>`,日期字面一致。
### /obsidian-llm-wiki lint
健康检查 wiki。
1. 读 `index.md`,验证每个列出的页面存在
2. 读每个 wiki 页面,检查:YAML frontmatter 存在且七字段齐全;frontmatter tags 与 inline tags 一致;页面至少 2 个出站 wiki 链接;无断裂链接;同主题页面间无矛盾
3. 找孤立页面(无入链)
4. 找值得拥有独立页面的内联提及
5. 检查过期内容(30+ 天未更新)
6. 向用户报告发现
7. 追加 lint 报告到 `log.md`
8. **`index.md` 专项校验**(详见 §Index Metadata And Statistics §Index lint 校验规则,六变量口径):顶部维护块正则、底部统计行三变量正则、索引健康行正则、三处日期一致、六变量精校、统计行与健康行各只 1 次、表格格式、同章节去重、顶级段 vs 注册表差集、双入口 schema 字节一致。**不自动修改 `index.md`**;全量重建条件成立时提示 `/index`。
### /obsidian-llm-wiki index
从当前 wiki 状态**全量重建** `index.md`。与各写命令的"增量更新"互为补集;本命令是兜底 / 一致性修复入口。
1. 扫描 `wiki/**/*.md`,跳过 `index.md` / `log.md` / `*.canvas` / `templates/` / `assets/`
2. 对每个 .md 读 YAML frontmatter 抽 `title` / `domain` / `created` / `updated`;读正文第一段非空行作"一句话摘要";读 `tags` 作 inline tags
3. 按 `domain` 分到 `## <domain>` 顶级段;二级段从文件相对路径 `wiki/<domain>/...` 推断(如 `wiki/AI/编程出海/技术/上线/落地页/X.md` → `## AI / 编程出海 / 技术 / 上线 / 落地页`)。推断失败时归入 `## <domain> / 其他`
4. 按 §Index 章节与表格规范 排序并写入三列表
5. 按 §六变量计数口径 重算六个变量
6. 按 §Index 顶部维护块 / §Index 底部统计与索引健康行 模板写入三处,操作摘要 = `同步索引:补登 X 个页面、修正 Y 个链接、去重 Z 个重复条目`(X/Y/Z 为本次 diff;必要时附 `统计漂移修正`)
7. **运行强制维护遍历**;校验三权威变量 + 三健康变量、统计行与健康行各只 1 次、三处日期字面一致;将本次 index 重建条目追加到 `log.md`,记录 `indexed_page_count` 变化/不变/漂移修正标识
**不变量**:本命令产物必须通过 §Index lint 校验规则 的所有检查。
### /obsidian-llm-wiki migrate
一次性迁移助手,把已有 Obsidian 笔记迁到 LLM Wiki 模式。
1. 扫描项目目录,找不在 `raw/` 和 `wiki/` 中的 .md 文件
2. 与用户确认每个文件属于哪个领域
3. 对每个文件:读内容 → 提取 inline tags → 生成 frontmatter(按 schema 规范)→ 确定目标(raw/ 或 wiki/)→ 写入新位置 → **同步 `index.md`**(按 §Index Metadata And Statistics,操作摘要 = `同步索引:迁移 N 个页面至 wiki/<领域>/`,N = 本次累计的 wiki 写入数;重算六变量)→ 记录迁移日志
4. 若迁移引入新领域导致双入口 schema 变更,**同步编辑 `AGENTS.md` + `CLAUDE.md` + 验 SHA-256**
5. 所有文件迁移完成后,**建议运行 `/obsidian-llm-wiki index` 全量重建**(增量可能因目录拓扑变化漂移),并把"全量重建"作为迁移日志的最后一条
+
+ ### /obsidian-llm-wiki update-raw-reference \<wiki页面.md\> \<raw目录\>
+
+ 媒体引用修复:来源图片/视频目录迁移后,把指定 Wiki 页面的媒体嵌入一站式改写到指定 raw 目录的 Obsidian 全路径嵌入格式 `![[raw/…]]`,并顺带补缺 frontmatter 与补录索引(**缺才补、有则只验证**)。
+
+ 1. **参数校验(硬门槛,不合法立即报错、零写入)**:参数 1 必须是 `wiki/` 下真实存在的 `.md` 文件;参数 2 必须是 `raw/` 下真实存在的目录;两参数必填。两个名称通常相同(页面 stem ↔ raw 目录名)但**不强制**;不一致时照常执行,仅在报告中提示。
+ 2. **嵌入清点(只读)**:提取页面全部 `![[...]]` 嵌入,按扩展名区分媒体嵌入(图片 png/jpg/jpeg/webp/gif/svg/bmp,视频 mp4/mov/webm/m4v,音频 mp3/wav/m4a/ogg 等)与其他嵌入;已有嵌入顺序是权威顺序,不重排。
+ 3. **改写规则**:仅当 `raw/<参数2目录>/<原文件名>` 真实存在时,才把该媒体嵌入改写为 `![[raw/<目录>/<文件名>]]`;通用易重名文件名(如 `image-001.png`)必须用全路径,防跨目录误解析。目标文件不存在、原名解析歧义、或嵌入已有效指向其他 raw 目录时**不改写**,列入未决报告。绝不移动/修改/删除 `raw/` 文件,绝不删除既有嵌入,不改 wiki 链接与正文。
+ 4. **frontmatter(缺才补、有则只验证)**:页面无 frontmatter 时按 §Frontmatter 与 Tag 规范化 补齐七字段(结构性例外,可置于正文前);已存在则只校验,不改动。`updated` 仅在发生实质变化时刷新。
+ 5. **补录索引(缺才补、有则只验证)**:页面在 `index.md` 对应分区无条目时,按 §Index Metadata And Statistics 补录(`indexed_page_count` +1,操作摘要 = `同步索引:补录既有页面 <页面名>`),顶部维护块 + 底部统计行 + 索引健康行同一次编辑,重跑精校确认 `footer_match=true`;已有条目则只验证链接可解析,跳过。
+ 6. **收尾**:运行强制维护遍历;`log.md` 按「log.md 追加(大文件安全)」预检后追加一条最终记录(含参数校验结果、改写/未改写清单、六变量与变化类型)。
### /obsidian-llm-wiki delete \<page\>
删除 wiki 页面(**不动 raw/**)。删除前:确认无其他页面的入链,或有则提示用户处理断链。删除动作:用 `Remove-Item -LiteralPath "<绝对路径>"`,禁通配符/`-Recurse`/批量/目录删除(唯一例外:Skill 任务临时目录的空目录窄例外,见 [references/temp-cleanup.md](references/temp-cleanup.md))。删除后**运行强制维护遍历**:在对应 `## <领域>` 章节删除该行;检查相关链接/反向链接/index 是否需要更新;`indexed_page_count` 变化则重算六变量;顶部维护块摘要 = `同步索引:移除 1 个页面(<页面名>)`;追加 `log.md` 条目 `## [YYYY-MM-DD] delete | <标题>`,日期与 index 顶部/底部字面一致。
### /obsidian-llm-wiki log \<mode\>
日志工作流:`status` / `query "<条件>"` / `rotate now|year|size|auto`;同时是所有写入型任务追加最终日志条目的路由(预检与追加验证见「log.md 追加(大文件安全)」)。
1. `log status`:只读运行 `scripts/log-preflight.ps1 -Detailed -Json`(Git Bash 经 `powershell.exe -NoProfile -ExecutionPolicy Bypass -File` 调用),展示当前字节数、投影、阈值与活动日志起始日期,绝不轮转。
2. `log query "<条件>"`:用 `rg` 检索活动 `log.md` 与 `logs/archive/*.md`,只读取命中处有界上下文(如 `rg -n -C 2 "<条件>"`)。
3. `log rotate now` / `year` / `size` / `auto`:按 [references/log-rotation.md](references/log-rotation.md) 的十步流程执行整文件移动轮转。
4. 永不把轮转当备份;永不改写历史分卷;`logs/` 永不计入 `index.md` 页面统计。
## 排版规范
所有 wiki 页面应遵循以下排版标准。
### 标题层级
- 页面不使用 H1(`#`),标题由 frontmatter `title` 定义
- 正文从 H2(`##`)开始,层级严格递进不跳级
- 同一页面中 H2 之间保持语义平行
### 列表格式
- 无序列表统一使用 `-`(不混用 `*` 和 `+`)
- 嵌套缩进 2 个空格
- 任务列表使用 `- [ ]` 和 `- [x]`
### 表格
- 必须包含表头行和分隔行
- 仅在数据对比或多维度信息时使用,简单列表不转为表格
### Callout
使用 Obsidian callout 替代普通引用表达特殊语义:`> [!note]`、`> [!tip]`、`> [!warning]`、`> [!info]`、`> [!quote]`。一句话摘要仍用普通引用(`> 摘要`),不使用 callout。
### 代码块
- 行内代码用反引号包裹命令、文件名
- 代码块指定语言标识(如 ` ```python `、` ```bash `)
### 图片
- 默认不指定尺寸(`![[图.png]]`),让 Obsidian 自适应
- 信息密度高的图表可限宽:`![[图.png|400]]`
- 不指定高度(保持纵横比)
## 页面要求
**必需结构元数据**(缺失即视为结构缺口,由强制维护遍历修复):
1. YAML frontmatter 作为文件第一行/块,`---` 起始,含七字段:`title` / `created` / `updated` / `domain` / `tags` / `sources` / `status`
2. Inline tags(如使用)与 frontmatter tags 一致
3. Tags 规范化:标签片段内空格用 `_`(如 `一堂/AI_Live`)
**推荐内容**(服从资料类型、已有页面结构与用户作用域;**不**为 query-only 或轻量维护任务强制扩写):
1. 一句话摘要(以 `>` 引用格式)
2. 正文内容
3. `## 相关` — wiki 链接到相关页面(每页至少 2 个可解析出链)
4. `## 来源` — 引用 raw 来源(schema 定义的无 raw 领域如 `提炼思维` 可省)
> frontmatter 是结构例外:append-only / 保留正文约束不阻止把缺失 frontmatter 修复到第一行(见 §Frontmatter 与 Tag 规范化)。
## 守则
- 绝不修改 `raw/` 下的文件
- 覆盖已有 wiki 内容前须确认;优化时不删除已有 `![[]]` 图片嵌入
- `log.md` 条目 append-only
- 保持中文为主要内容语言
- 不确定时询问用户
- 所有路径和领域从项目 schema(`AGENTS.md` / `CLAUDE.md`)读取,不硬编码
- **双入口 schema 字节一致**:声明契约时 `AGENTS.md` 与 `CLAUDE.md` 必须字节相同;结构变更同步两文件并验 SHA-256
- 派出的 subagent 只读,不修改 raw/wiki/index/log/schema/.claude
- 图片重名/缺失/无法定位一律先报告,不猜测
- **不虚构**来源、数据、引用或验证结果
- 中文路径与带空格路径用 `-LiteralPath` 或显式参数,不走 PowerShell 管道;不修改 PATH、不重装 Python、不调用户目录 Python
- `log.md` 条目至少含:日期与任务名 / 增改删文件 / 是否检查 `AGENTS.md` + `CLAUDE.md` / 是否检查 frontmatter + 图片嵌入 + `index.md` + 统计 / 关键验证结果与未决项;同一任务只追加一条最终记录;新条目用标准紧凑格式(必需:范围、变更、维护、验证;按需:资料、未决,见 [references/log-rotation.md](references/log-rotation.md))
- **写入型任务追加 `log.md` 前必跑固定只读预检** `scripts/log-preflight.ps1`(见「log.md 追加(大文件安全)」);`logs/` 不计入 `index.md` 页面统计;历史分卷(`logs/archive/`)永久只读,不删除、不改写、不继续追加