Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8e0cbd1
feat(cite-check): 引用语义正确性保障体系(确定性核对 + 回验协议 + 审计台账)
Qinbf Jul 2, 2026
32cb384
feat(cite-check): 盲填复核 + 查询侧核对 + 跨模型二审 + pre-commit 机械闸门
Qinbf Jul 2, 2026
ed55e80
feat(cite-check): 原子分解 + 检索凭证链 + 统计保证 + 对抗评测集
Qinbf Jul 2, 2026
e2c3175
chore: P0 修复 + 引用体系用户文档 + 性能/维护收尾
Qinbf Jul 2, 2026
f42d252
feat(web): 引用审计裁决页 + 仪表盘接入引用体系指标
Qinbf Jul 2, 2026
6c006aa
fix(cite-check): arXiv 数字重复瑕疵 + list 块锚点尾巴泄漏两个真实 bug
Qinbf Jul 2, 2026
c5232c2
feat(search-raw): raw 原文块级全文检索——长文档细节的可发现性补全
Qinbf Jul 3, 2026
98eb8fd
feat(corpus-map): raw 层全库文档地图——LLM 浏览式检索的第一跳
Qinbf Jul 3, 2026
2bae2e9
fix(corpus-map): 补全 title-only 唯一性闸门 + broken-outline 上报
Qinbf Jul 3, 2026
a1216ea
docs: 移除双仓库同步约定——收敛为单仓维护
Qinbf Jul 3, 2026
cfc6954
docs: 新增「构建自己的本地知识库」指南——引擎在此、数据在别处
Qinbf Jul 3, 2026
534f374
fix(web): 外置 KB_ROOT 下 k.py 脚本路径解析错误
Qinbf Jul 3, 2026
330079a
feat(skill): kb-edit-source——来源内容变更后同步 wiki 引用的工作流
Qinbf Jul 3, 2026
f720492
fix(skill): kb-edit-source 移除硬编码私人路径,改用 $SRC_ROOT 占位
Qinbf Jul 3, 2026
aaee3b9
fix(web): k.py 子进程默认解释器 python → python3
Qinbf Jul 4, 2026
acdcf6c
docs: design evidence-first citation accuracy v2
Qinbf Jul 10, 2026
e302e44
feat: harden citation verification fail-closed
Qinbf Jul 10, 2026
a934eeb
feat: add long-document evidence atlas
Qinbf Jul 11, 2026
1acd13a
feat: add stage2 citation accuracy gates
Qinbf Jul 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions .agents/skills/kb-cite-audit/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
name: kb-cite-audit
description: 知识库引用语义审计工作流——确定性枚举(论断, 引用)审计对,逐条以 fresh-context 判定被引原文是否真的支撑论断,判定入验证台账,未通过的落 CAUTION 标注交人裁决。当用户提到"审计引用"、"核对引用"、"引用是否正确"、"cite audit"、"验证来源"、"检查论断与原文一致性"时使用此 skill。
---

# 知识库引用语义审计工作流(kb-cite-audit)

你现在是知识库的 **引用审计员**。任务:验证 wiki 论断的块级引用在**语义上**成立——被引的那个块是否真的支撑该论断。结构 lint(broken-refs / bare-claims / coarse-citations)只保证「锚点存在、有引用、粒度够细」;本流程补上「引的内容对不对」。

> **Workspace 前提(必读)**:数据层按主题隔离在 `workspaces/<name>/` 下。本文所有 `wiki/`、`raw/`、`log.md` 路径均相对当前 workspace;`k.py` 命令加 `--workspace <name>`;`Read` / `Edit` / `git add` 用带 workspace 的全路径。

> **raw 不在场即降级(必读)**:本仓的 demo 库不分发 `raw/`(版权),协作者浅 clone 同理。`extract-claims` 会把这类引用标为 `raw-not-distributed`——**直接跳过、勿烧 token 强行判定**;语义审计只在 raw 在场的环境(dev 仓 / 用户自己的库)实际执行。

**核心原则**:

- **KB 出数据、agent 出判断**:`extract-claims` / `cite-audit-log` 是确定性工具;「支撑与否」的判定由你(外部 agent)做,这是全流程唯一需要智能的一步。
- **fresh-context 判定**:只依据 `claim_text` + 现场取回的被引原文下判断。**禁止**凭「我 ingest 时读过这篇」的记忆判定——上下文污染正是错引的成因,不能再用它做裁判。
- **不默默修正**:发现错引不改论断本身,落 CAUTION 标注 + `citation-suspect` 标签,让人在工作台裁决(与 kb-lint 的冲突处理铁律一致)。
- **台账是 memoization,不是真相**:`.cache/citation_audit.jsonl` 只记「谁在何时核验过什么」,删了重审即重建;「这条引用有问题」这一知识状态**只以 markdown 标注为准**(`list-suspect-citations` 扫 markdown,不读台账)。

---

## 第 1 步:枚举待审对

```bash
# 增量模式(周检 / 例行):只审从未审过 + 内容已漂移的对,配额抽样
python scripts/k.py --workspace <name> extract-claims --unaudited-only --sample 20 --seed <YYYY-WW> --json

# 全量首审(一次性存量清偿):去掉 --sample;量大时分多轮
python scripts/k.py --workspace <name> extract-claims --unaudited-only --json
```

- `--seed` 用当周周号(如 `2026-W27`):同周重跑取样一致(可复现),跨周覆盖累积。
- 「已审」判定是双 hash pin:claim 内容变 → pair_id 变;被引块内容变(含 ^h- 节**正文**重写而标题不变)→ `target_content_hash` 漂移——任一侧变化都自动回到未审,无需人为盯。

## 第 2 步:分诊

按 `target_status` 分流,只对 `ok` 的对做语义判定:

| target_status | 处置 |
|---|---|
| `ok` | 进入第 3 步判定 |
| `raw-not-distributed` | `cite-audit-log --verdict UNVERIFIABLE` 批量入账(不烧 token;k.py 校验:只有目标确实不可得才接受 UNVERIFIABLE) |
| `file-missing` / `anchor-missing` | 归 broken-refs 流程修复,本流程跳过(不双报) |

## 第 3 步:逐条 fresh-context 判定

对每对(建议 20-30 条一批,批间不携带前批内容):

1. 取回被引原文(**必须现场取,不用记忆**):
```bash
python scripts/k.py --workspace <name> read-block <target> <anchor> # ^p-/^t-/^c-/^f-
python scripts/k.py --workspace <name> read-section <target> <anchor> # ^h-
```
2. 判定三问:
- ① **关键事实在场**:论断中的数字 / 日期 / 主体是否出现在被引原文?
- ② **直接支撑**:论断是否被原文直接支撑(不需要额外推理 / 拼接其他来源)?
- ③ **语义 drift**:有无过度概括("多数"写成"所有")、加了原文没有的限定词 / 程度词、因果错置(correlation 写成 causation)?
3. 映射 verdict:三问全过 → `SUPPORTED`;部分支撑 / 措辞偏移 → `PARTIAL`;被引块与论断无关或关键事实不在 → `UNSUPPORTED`;论断与被引证据**相反** → `CONTRADICTED`。
4. **盲填复核(含数字的对必做)**:`extract-claims --unaudited-only --cloze` 输出挖空论断(数字→⟦N1⟧);核验时**只看「挖空论断 + 被引原文」**填空(不看期望值),`python scripts/k.py cloze-check --batch <fills.jsonl>` 机器判分(块级 union:一块多引用时数字由块内任一引用的原文填出即可)。判分未过按 UNSUPPORTED 处置——盲填从原理上消灭判定式审核的附和偏差,并抓「数字巧合在场但归属错误」。
5. **跨模型二审(推荐)**:`python tools/cite-audit/audit.py --workspace <name> [--unaudited-only|--all --sample N --seed <YYYY-WW>]`——外部客户端(tools/ 例外区)调 DeepSeek 自动跑双通道并入台账;`--all --sample` 模式可对已 SUPPORTED 记录换模型交叉复查(防橡皮图章与同源盲区)。问答 / 导出草稿可用 `--draft /tmp/answer.md`,判定会通过草稿专属 pair 受控入账。需 `DEEPSEEK_API_KEY`;无 key 时以 fresh-context 子 agent 反驳式抽查替代。

审计器的结果协议是 fail-closed:exit `0` = 所有实际判定对通过,exit `1` = 完成判定且发现语义未通过,exit `2` = 网络 / 协议 / 核验包 / quote / skipped 等导致审计未完成。`2` 不是「没发现问题」,禁止当作通过;截断 claim/evidence/cloze 和多来源盲填冲突都进 incomplete,不冒充 UNSUPPORTED 或语义查全命中。

**防误伤细则**(判定前先过一遍):

- **多来源合成论断**(`multi_source: true`,多见于 analysis / comparison 页):一块多引用时,引用只对其**紧邻的前方分句**负责;单个被引块只支撑论断的一部分是**正常形态** → `PARTIAL` 且**不落标注**。只有「被引块与归属分句无关或矛盾」才 `UNSUPPORTED`。
- **合法转述白名单**(按 `SUPPORTED` 处理,note 记明):约数舍入(约 40% ↔ 39.2%)、跨语言日期 / 数字格式转写(August 29 ↔ 2025-08-29)、已标 `[KB 推算: ^锚]` 且现场验算成立的派生算术(差值 / 倍数 / 单位换算——验算不成立则 `UNSUPPORTED`)。
- **^h- 大节引用**:支撑句埋在整节多处(分布式支撑)属正常 → `PARTIAL` 不落标注,建议 note 记「宜降 ^p- 级锚」。

## 第 4 步:判定入台账

```bash
# 单条(agent 记 SUPPORTED 必须附 --evidence:被引块原文的一段字面子串,k.py 会校验——
# 证明确实取回过原文,杜绝橡皮图章)
python scripts/k.py --workspace <name> cite-audit-log --pair <pair_id> --verdict SUPPORTED \
--evidence "<从 read-block 返回内容里复制的一段>" --note "三问全过"

# 批量:JSONL 文件每行 {"pair_id": "...", "verdict": "...", "note": "...", "evidence": "..."}
python scripts/k.py --workspace <name> cite-audit-log --batch /tmp/verdicts.jsonl
```

k.py 的确定性校验(被拒说明流程有问题,不要绕):pair 过期(内容已变)拒绝;目标可解析时记 UNVERIFIABLE 拒绝;SUPPORTED 无 / 假 evidence 拒绝。

## 第 5 步:UNSUPPORTED 落 CAUTION 标注

对 `UNSUPPORTED` / `CONTRADICTED`(以及**实质事实错**的 PARTIAL),`Edit` 在论断块**正下方**追加审计标注(格式固定,`list-suspect-citations` 靠它扫描):

```markdown
> [!CAUTION] 引用审计未通过 — YYYY-MM-DD
> **论断**:<论断句摘录>(块 ^p-4-34d5b1)
> **被引块**:[[<target>#^<anchor>]]
> **审计判定**:UNSUPPORTED — <一句差异说明,如"被引表格中数字为 65.9 非 66.9">
> **建议**:<改引 [[<target>#^<正确锚>]] / 修正论断数字 / 删除论断>
> **状态**:⏳ 待人类判别
```

同时该页 frontmatter `tags` 追加 `citation-suspect`。**不改论断原文**——修复由人裁决(或人授权后走正规修复 + 删标注,claim 变化会自动触发重审)。

## 第 6 步:收尾对账 + 汇报 + commit

```bash
python scripts/k.py --workspace <name> list-suspect-citations --check-ledger
```

- `ledger-unsupported-without-marker` 必须为空——有 = CAUTION 标注被删而论断未改(「删标注蒸发」),恢复标注。
- log.md 追加 `lint` 类条目:`- 引用审计:<N> 对(S/P/U = x/y/z),UNSUPPORTED 已标注 z 条`。
- git commit(只含 `wiki/**` 标注改动 + log.md;**.cache 台账不入库**):`git commit -m "lint: 引用审计 <N> 对"`。

---

## 完成检查清单

- [ ] `extract-claims --unaudited-only` 本批返回的 `ok` 对已全部判定并入账
- [ ] 核验包的 claim / evidence / cloze 未截断,审计器没有 incomplete / skipped / ledger error
- [ ] `raw-not-distributed` 的对已批量记 UNVERIFIABLE(没有烧 token 强判)
- [ ] 每条 SUPPORTED 都带真实 `--evidence`(k.py 校验通过)
- [ ] UNSUPPORTED / CONTRADICTED 已落 CAUTION 标注 + `citation-suspect` 标签,**没有默默修正论断**
- [ ] `list-suspect-citations --check-ledger` 对账一致
- [ ] log.md 记账、git commit 完成(.cache 不入库)

## 反例(绝对不要做)

- ❌ 凭「我 ingest 时读过」的记忆判定,不现场 `read-block` 取回原文——上下文污染不能当裁判
- ❌ 对可解析的目标记 UNVERIFIABLE 跳过劳动(k.py 会拒绝;被拒就老实取原文)
- ❌ 把多来源合成论断的正常 PARTIAL 当错引落标注(误伤会让人对审计失去信任)
- ❌ 发现错引直接改论断数字(默默修正)——必须落标注走人裁
- ❌ 删 CAUTION 标注但不修论断(对账会报 ledger-unsupported-without-marker)
- ❌ 把台账 jsonl 提交进 git(它是派生层缓存,删了重审即重建)
Loading
Loading