免费

线索板

把项目笔记钉成一块离线线索板:每条说法都追到原文那一行,没有来源的一律盖上“未核实”。

安装

把“线索板”技能安装到 ~/.claude/skills/evidence-board。
下载下面每个文件,保存到这个文件夹:
https://skilllift.pages.dev/packs/evidence-board/SKILL.zh.md → SKILL.md
https://skilllift.pages.dev/packs/evidence-board/references/style.md → references/style.md
https://skilllift.pages.dev/packs/evidence-board/assets/template.html → assets/template.html
https://skilllift.pages.dev/packs/evidence-board/assets/strings.json → assets/strings.json
https://skilllift.pages.dev/packs/evidence-board/scripts/lib.mjs → scripts/lib.mjs
https://skilllift.pages.dev/packs/evidence-board/scripts/index.mjs → scripts/index.mjs
https://skilllift.pages.dev/packs/evidence-board/scripts/verify.mjs → scripts/verify.mjs
https://skilllift.pages.dev/packs/evidence-board/scripts/hints.mjs → scripts/hints.mjs
https://skilllift.pages.dev/packs/evidence-board/scripts/layout.mjs → scripts/layout.mjs
https://skilllift.pages.dev/packs/evidence-board/scripts/build.mjs → scripts/build.mjs
https://skilllift.pages.dev/packs/evidence-board/scripts/check.mjs → scripts/check.mjs
https://skilllift.pages.dev/packs/evidence-board/scripts/drive.mjs → scripts/drive.mjs
然后读一遍 SKILL.md,告诉我它是做什么的,并提醒我开一个新会话。

解压到 ~/.claude/skills

同一个技能,不同的需求

左边是预览。右边由另一个 Agent 按不同需求制作,它只有安装好的技能,没看过预览。

预览
预览
新需求,由另一个 Agent 制作
新需求,由另一个 Agent 制作

这是按虚构需求做的一次测试。系统字体不同时,字形可能略有差异。

把项目笔记变成一个离线知识图谱,整个就是一个 HTML 文件,画成侦探的线索板。可以读 Markdown 文件夹、JSON 或 CSV 记录,或一份目录清单:由 Agent 读笔记、写下每条说法及来源行,再由脚本逐条对照文件核对。页面能搜索、按类型筛选、打开案卷抽屉查看来源行、带日期的生命周期状态、相邻线索和反向链接,能追查两点间的路径,一眼回答谁负责什么、什么阻塞什么、还有什么不知道,并明确显示图规模规则。没有来源的内容一律盖上“未核实”。数据集同时交付一份纯 JSON。当用户想看清项目里的人、任务、决定和风险怎么连在一起、每条说法从哪来时使用。

交付前必须通过

  • 我读完整个索引,亲自写了 hand.json;reviewed 如实说明读了什么。
  • 我重读了 verify.mjs 列出的未引用行。
  • 负责人、阻塞、未知三个按钮都能从页面上回答各自的问题。
  • 改变状态的新笔记都作为新状态加入,结束的阻塞都标了 resolved。
  • node scripts/check.mjs 退出码为 0 且运行了渲染检查,否则我已说明没有运行。
  • node scripts/drive.mjs 退出码为 0。
  • 我看过 1280 和 390 下线索板、抽屉、负责人、阻塞、未知、追查、路径、规模规则的截图。
  • 每条事实都写在引用行上;更弱的都标为推断并写了 note,或标为未核实。
  • 没有编造任何内容。虚构内容带有说明。
  • 页面界面、标题和说明只用一种语言。
  • graph.json 和 index.html 放在一起。
阅读完整 SKILL.md
---
name: evidence-board
description: 把项目笔记变成一个离线知识图谱,整个就是一个 HTML 文件,画成侦探的线索板。可以读 Markdown 文件夹、JSON 或 CSV 记录,或一份目录清单:由 Agent 读笔记、写下每条说法及来源行,再由脚本逐条对照文件核对。页面能搜索、按类型筛选、打开案卷抽屉查看来源行、带日期的生命周期状态、相邻线索和反向链接,能追查两点间的路径,一眼回答谁负责什么、什么阻塞什么、还有什么不知道,并明确显示图规模规则。没有来源的内容一律盖上“未核实”。数据集同时交付一份纯 JSON。当用户想看清项目里的人、任务、决定和风险怎么连在一起、每条说法从哪来时使用。
version: 1.0.0
---

# 线索板

**你就是提取器。** 由你读笔记,写下每个实体、关系和状态,并逐条写明出处。脚本做不到这一点:在一个真实的小项目上,模式匹配只找到 22 个实体中的 4 个、26 条关系中的 2 条,还漏掉了两个最明显的负责人。外观和行为都在 `assets/template.html` 里,布局由数据决定,不要手动摆放。令牌和规则见 `references/style.md`。

每一步实际做什么:

| 步骤 | 做什么 | 不做什么 |
|---|---|---|
| `index.mjs` | 列出每一行、每个 CSV 行及其引用位置 | 不做任何判断 |
| 你 | 读完,写 `hand.json`:所有说法 | |
| `verify.mjs` | 核对每条引用确实存在且支持所标的依据;列出每个名称出现的行;报告没人引用的行 | 不增加说法,也不知道你的理解对不对 |
| `hints.mjs`(可选) | 按模式猜名称和关系,供你对照 | 不会上板,`build.mjs` 会拒绝它的输出 |
| `build.mjs` | 布局并画出线索板 | 不改说法 |
| `check.mjs`、`drive.mjs` | 测试观看者看到和操作到的东西 | 不判断说法是否完整 |

## 需要问用户的信息

简报里没有的,一次问完,放在同一条消息里。

必需:
1. 笔记:一个文件夹路径(Markdown、`.json`、`.csv`),或存成 `.txt` 的目录清单(`find`、`ls -R`、`tree` 的输出)。
2. 项目名称。

可选:
3. 一句话说明这些笔记是什么。
4. 页面语言,英文或中文。默认跟随笔记的主要语言。
5. 内容是否虚构或只是示例。

## 步骤

以下命令都在这个技能的文件夹里运行;`notes.index.txt`、`hand.json`、`work.json` 要放在技能文件夹之外的工作文件夹,不要放进技能里。脚本各约一秒,检查几秒,驱动测试最多一分钟。真正花时间的是写 `hand.json`,大约等于读完笔记的时间。

1. 建立证据索引:
   `node scripts/index.mjs <笔记> --out notes.index.txt`
2. **全部读完,然后写 `hand.json`**(见下):重要的人、机构、任务、决定和风险,谁负责什么,什么阻塞什么,状态,以及笔记说不知道的事。每条都引用来源行。
3. 可选,写完初稿后:`node scripts/hints.mjs <笔记> --out hints.json`,看看有没有漏掉什么。它经常出错。面对很长的目录清单或大型记录文件时,`--draft hand.draft.json` 会把猜测写成 `hand.json` 的格式供你修改,因为这种结构是机械的。采用之前要逐行读。
4. 核对:
   `node scripts/verify.mjs <笔记> --hand hand.json --out work.json`
   它一次报告所有问题,全部通过才写出文件。请改正引用或降低依据;除非这条说法确实没有依据,否则不要靠删除来消除报错。之后它会列出没被引用的行:**再读一遍**,补上漏掉的内容。
5. 生成:
   `node scripts/build.mjs work.json --out <文件夹>/index.html --root <笔记> --title "..." [--subtitle "..."] [--notice "..."] [--fictional] [--lang en|zh]`
   会在同一处写出 `index.html` 和 `graph.json`。
6. 检查,并修好它报告的所有问题:
   `node scripts/check.mjs <文件夹>/index.html`
   页面离开笔记所在位置后,加上 `--root <笔记>`。以下情况都会判为失败:1280x800 适配时标签小于 11 px、卡片重叠、标签被遮住、标题、说明、副标题、按钮或筛选项被截断、线从无关图钉下或无关卡片背后穿过、没有来源的说法被当成事实显示、状态与自身最新证据不符、引用的行与真实文件不符、手机上的点击区域小于 44 px。
7. 驱动所有交互,然后亲眼看:
   `node scripts/drive.mjs <文件夹>/index.html --shots <临时文件夹>`
   会在 1280 和 390 两个宽度、开启和减弱动效下运行,并模拟触屏。**打开截图看:线索板、抽屉、负责人、阻塞、未知、追查、路径、规模规则,两个宽度都要看。** 脚本通过不等于看过。

## 你要填写的字段:含义、上限、简报太少时怎么办

| 字段 | 含义 | 上限 | 简报太少时 |
|---|---|---|---|
| `--title` | 项目自己的名称,用页面语言 | 60 字符;过长会换行,不会被截断 | 用简报里的名称。没有的话,从笔记自己的用词里取,并列为假设。文件夹名只有读起来就是页面语言的名称时才能用;检查器会拒绝 `repro-notes` 这样的名称。 |
| `--subtitle` | 这些笔记是什么,用用户自己的话 | 120 字符 | 不填。绝不编造说明。 |
| `--notice` | 说明内容是虚构或示例 | 80 字符,可换行 | 不是虚构就不填。用了 `--fictional` 就必须填,且要包含“虚构”、fictional 或 invented。 |
| `reviewed` | 你实际读过、核对过什么 | 最多 120 字符,至少 12 字符 | 如实写读了什么。确实没能读笔记时,一字不改地写 `未复核:机器首次读取,可能有错` 或 `Not reviewed: first machine read, claims may be wrong`。这两句能通过检查,页面会显示警告横幅。绝不能声称做过没做的复核。 |
| `note` | 你的理解:这一行没有直接写明,为什么仍然支持这条说法 | 120 字符。推断的状态必填,引用行没写到名称的说法也必填 | 写清这一行说了什么、你得出什么结论。写不出来,就不要这条说法。 |
| `dates` | 属于某个事项的排期日期 | `value` 16 字符自由文本,`label` 8 字符 | 见下文。笔记没写就不填。 |
| `date` | 状态或解除从何时成立 | `YYYY`、`YYYY-MM` 或 `YYYY-MM-DD` | 笔记没有日期就不填,并按从早到晚列出状态:顺序就跟随你的列表,页面会说明这一点。 |
| `unverified_reason` | 这条说法为什么没有来源 | 120 字符,没有 `source` 时必填 | 写明它从哪来,比如 `只在对话中提到,没有笔记记录。` 如果连这个都不知道,就不要写这条说法。 |
| `label` | 线上的文字,用于 `kind` 为 `related_to` 时 | 24 字符,与页面语言一致 | 不填,使用默认词。不要重复两端的名称。 |

### 手填文件

这就是你对笔记的理解。只有写在这里的内容才会上板。

```json
{
  "reviewed": "逐行读完 8 篇笔记,并写下这些说法。",
  "aliases": { "恒温系统": "恒温恒湿系统" },
  "entities": [
    { "name": "演出页面", "type": "task", "source": { "file": "design.md", "line": 2 },
      "states": [
        { "state": "blocked", "date": "2026-03", "source": { "file": "design.md", "line": 2 } },
        { "state": "active", "date": "2026-04", "source": { "file": "april.md", "line": 1 },
          "note": "原来要等照片,这一行说照片已送到。" }
      ] },
    { "name": "域名登录", "type": "risk", "source": { "file": "risks.md", "line": 2 },
      "states": [ { "state": "unknown", "source": { "file": "risks.md", "line": 2 } } ] },
    { "name": "只有口头提过的事", "type": "org", "unverified_reason": "只在对话中提到,没有笔记记录。" }
  ],
  "relations": [
    { "from": "王敏", "to": "网站改版", "kind": "owns", "basis": "fact", "source": { "file": "kickoff.md", "line": 2 } },
    { "from": "甲", "to": "丙", "kind": "owns", "basis": "fact", "source": { "file": "notes.md", "line": 14 }, "context": 12 },
    { "from": "照片", "to": "演出页面", "kind": "blocks", "basis": "inferred", "source": { "file": "design.md", "line": 2 },
      "resolved": { "source": { "file": "april.md", "line": 1 }, "note": "照片已送到。", "date": "2026-04" } },
    { "from": "甲", "to": "戊", "kind": "related_to", "label": "需要批准", "unverified_reason": "只在对话中提到,没有笔记记录。" }
  ]
}
```

类型:`person org place asset task event decision risk document other`。关系:`depends_on blocks owns approved rejected replaces supplies funds inspected reviewed reported located_at part_of contains works_for affects operates related_to`。`owns` 进入“负责人”,`blocks` 和 `depends_on` 进入“阻塞”,笔记是这个意思时就用这些关系,不要用自定义标签。

状态:`proposed active blocked done rejected superseded unknown`。
- 最后一条状态生效,所以**后来的证据可以取代之前的**:新增一条,不要改旧的。两条都留着,各带引用。每条都有日期时按日期排序,否则按你列出的顺序。
- **`unknown` 表示笔记提出了问题但没有答案。** 引用提出问题的那一行。笔记只是没提时,不要写 `states`,页面显示为无状态。
- 未解决的问题单独写成实体,状态设为 `unknown` 并引用那一行。不要编造占位的人;如果要为没人点名的人加卡片,必须标为未核实并写明原因。
- 状态只表示生命周期。“排在 10 月 12 日”不是 `active`;不要写状态,改用 `dates`。
- **算作写明状态的词:** proposed:proposed、draft、planned、todo、pending、will、next、`[ ]`、待定、计划、未开始、还没开始、待办、提议、草案、待确认。active:active、in progress、ongoing、underway、started、resumed、handling、open、进行中、在做、正在、推进中、施工中、开始了。blocked:blocked、on hold、paused、stalled、stuck、delayed、waiting、moved、受阻、卡住、卡着、卡在、暂停、搁置、停滞、延期、阻塞、等待。done:done、complete、completed、closed、finished、resolved、approved、delivered、shipped、picked、`[x]`、已完成、完成、修好、好了、到货、搞定、做完、结束、已解决、关闭、已交付、已上线、通过。rejected:rejected、cancelled、dropped、abandoned、declined、否决、驳回、取消、放弃、砍掉、不做了。superseded:superseded、retired、obsolete、replaced、作废、废弃、被取代。unknown:unknown、not sure、unsure、unclear、nobody knows、tbc、tbd、`?`、不清楚、不知道、未知、没人知道、不确定、待查。其他说法都算你的理解,要写 `note`。
- **不好归类时:** 项目用 `task`,钱用 `asset`,会议或有日期的场合用 `event`,未解决的问题用 `risk`。
- 阻塞结束后,在关系上加 `resolved`。它会移到“已不再阻塞”,线也会变淡。

### 日期变了怎么写

不要一个日期一张卡。把 `dates` 写在事项上,从早到晚列出。最后一条是当前值,显示在卡片上;旧的留在案卷里,标为已取代,各带引用。`value` 照笔记原样写,没有年份也可以。引用行里没有这个值时,要写 `note`。

```json
{ "name": "秋播", "type": "task", "source": { "file": "排期.csv", "line": 3 },
  "dates": [
    { "value": "2026-10-05", "source": { "file": "排期.csv", "line": 3 } },
    { "value": "10 月 12 日", "source": { "file": "十月例会.md", "line": 1 } }
  ] }
```

`states` 和 `resolved` 里的 `date` 不一样:它说明何时成立,只能写 `YYYY`、`YYYY-MM` 或 `YYYY-MM-DD`,只用来排列证据。笔记没写年份时不填,并按从早到晚列出。

### 怎么选事实、推断、未核实

- **事实(fact)**:只读引用的那一行,最多再加一行 `context`(通常是上方的标题),读者不用补充任何东西就能说出这条说法。关系必须在这些行里写明两端。状态必须写到实体名称,并用上表示该状态的词(`受阻`、`已完成`、`不清楚`、`[x]` 等)。
- **推断(inferred)**:这一行支持这条说法,但读者得自己联系:省略的主语、代词、隐含的因果、事情的先后。状态必须写 `note`。关系如果两端都没写到,也必须写 `note`。
- **未核实(unverified)**:没有任何一行支持它。必须填 `unverified_reason`,卡片会画上斜纹,线变成虚点,并显示警告。
- 标得更弱不会把它藏起来。追查路径按段数最少来走,也会列出其他路线,不管依据强弱,每条都标明。
- 拿不准时选更弱的那个。正确的说法标成推断,损失很小;错误的说法标成事实,会误导人。`verify.mjs` 能发现引用行缺字的事实,但发现不了理解错误,那只能靠你自己认真。

## 为什么线索提示只是提示

`hints.mjs` 的测试用的是两个故意写得很乱的中文笔记文件夹,由另一个从没见过它的 Agent 撰写,并附上它手工做的答案。`library` 用来调整;`tea` 在冻结后只跑一次,粗体就是那次的结果。另一个小型英文项目上,新 Agent 自己的答案显示:22 个实体找到 4 个,26 条关系找到 2 条。评分很严:答案里没列的真实事物也算错。

| 对照答案评分 | `library` 首次盲测 | `library` 交付版 | `tea` 冻结盲测 | `tea` 交付版 |
|---|---|---|---|---|
| 实体精确率 | 0.22 | 0.50 | **0.42** | 0.46 |
| 实体召回率 | 0.54 | 0.88 | **0.54** | 0.54 |
| 事实关系精确率 | 10 条对 2 条 | 13 条对 6 条 | **7 条对 2 条** | 6 条对 2 条 |
| 关系召回率 | 0.14 | 0.29 | **0.08** | 0.08 |
| 引用行与文件不符 | 201 条中 0 条 | 195 条中 0 条 | **167 条中 0 条** | 164 条中 0 条 |

它的行号引用是可靠的,读懂内容的能力则不可靠。笔记、答案和评分脚本都在 `example/messy-zh/`。你作为读者的准确度没有分数:`verify.mjs` 只核对引用,不核对判断。

**模式读不出,只能靠你:** 省略的主语(“Maya 看过”)、没有明显形态的名称、跨句或靠代词的关系、动词表以外的动词、两个名称是同一个东西、文字里的改口、否定和不确定的说法,以及后来的笔记是否结束了之前的状态。

## 遇到不顺的情况

- **简报太少:** 复述用户给的事实,绝不编造,并在报告里列出每一条推断。线索板只能说笔记说过的话。
- **没人能回答:** 按上面表格的规则继续,并在报告里列出你的假设。
- **卡片比预期多或少:** 一张板最多 60 张卡片,这是固定上限,用来保证标签不小于 11 px。超出的按排名下板,在规模规则里逐个列出,并且仍能搜索到。想改变板上内容,就调整你写下的实体,不要改上限。
- **来源没有真实链接:** 来源是文件路径和行号,不是链接,因为页面要离线可用。不要加网址。
- **笔记里有机密或个人信息:** 引文会嵌入页面。分享前先告诉用户。
- **页面被移动过:** 检查时要加 `--root <笔记>`。页面本身带着引文,放在哪里都能用。

## 交付物

- `index.html`:线索板,一个文件,没有外部请求。
- `graph.json`:实体关系数据集,含来源和规模规则。
- `hand.json`:你写下的说法,留着以便重新生成。
- 报告里写明:数量、你加的每条推断或未核实说法、规模规则去掉了什么、渲染检查有没有运行。

## 交付前检查

- [ ] 我读完整个索引,亲自写了 `hand.json`;`reviewed` 如实说明读了什么。
- [ ] 我重读了 `verify.mjs` 列出的未引用行。
- [ ] 负责人、阻塞、未知三个按钮都能从页面上回答各自的问题。
- [ ] 改变状态的新笔记都作为新状态加入,结束的阻塞都标了 `resolved`。
- [ ] `node scripts/check.mjs` 退出码为 0 且运行了渲染检查,否则我已说明没有运行。
- [ ] `node scripts/drive.mjs` 退出码为 0。
- [ ] 我看过 1280 和 390 下线索板、抽屉、负责人、阻塞、未知、追查、路径、规模规则的截图。
- [ ] 每条事实都写在引用行上;更弱的都标为推断并写了 note,或标为未核实。
- [ ] 没有编造任何内容。虚构内容带有说明。
- [ ] 页面界面、标题和说明只用一种语言。
- [ ] `graph.json` 和 `index.html` 放在一起。

## 什么时候不要用

- 要一张已经定好关系、讲究美观的示意图。这张板展示证据,不讲既定故事。
- 实体超过几百个,或者要接实时数据库。它只是一份快照。
- 只有一篇文档,这时摘要更合适。
- 用户想手动摆放位置。布局由数据决定。

## 环境要求

- Node 18 或更新版本。脚本不依赖任何包。
- 渲染检查和 `drive.mjs` 需要:`npm install playwright` 和 `npx playwright install chromium`。Playwright 装在别处时,把 `NODE_PATH` 设为它的 `node_modules`。没有 Playwright 时 `check.mjs` 以退出码 3 结束。`--static` 可跳过渲染检查;用了就要在报告里说明。

用在这些流程里

相似技能