用 build-evidence-map 构建可审计证据图谱:让 GitHub Copilot 的争议性技术决策有据可查
2026/9/12 2:51:13 网站建设 项目流程

用 build-evidence-map 构建可审计证据图谱:让 GitHub Copilot 的争议性技术决策有据可查

【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot

awesome-copilot 仓库的build-evidence-mapSkill 提供了一套可复用的工程化方法:把一个有争议的技术问题转化为一份机器可验证的"证据图谱"(evidence map)JSON 工件,精确记录支持、反驳、限定与缺失的证据,而不是把分歧揉进一段流畅的散文里。读完本文,你将掌握四类节点与四种边的建模规则、证据分级与源区域判定方法、.doubt.json的完整 schema 与不变量,以及如何使用仓库内置的零依赖验证器对图谱进行失败即关闭(fail-closed)的确定性校验并取得 64 字符收据。

这个 Skill 解决什么问题

在技术评审、研究综合、提案审查或重大决策场景中,最容易出问题的地方不是"我们倾向哪个结论",而是推理链不可见:某条证据到底支撑了什么?哪条证据与结论冲突却被悄悄略过?哪些关键事实我们其实并不知道?

build-evidence-map的核心主张非常明确:不要用一张"图"去装饰一个未经溯源的回答。它要求先把立场(position)、中间命题(claim)、证据(evidence)和未知(unknown)原子化地拆开,再用带注释的有向边表达它们之间的推理关系,最终产出以.doubt.json为后缀的 UTF-8 JSON 文件——一份"可移植的决策工件",任何人都能沿着边追溯每个结论的证据来源。

该 Skill 的定位边界在 SKILL.md 中写得很清楚:对于简单的事实性断言或一般性事实核查,应改用doublecheck之类的验证工作流;只有当证据与中间命题、权衡和缺失事实之间的关系本身才是重点时,才使用本 Skill。也就是说,它的适用对象不是"这个说法对不对",而是"围绕这个决策,哪些证据支持、哪些反对、哪些限定、哪些缺失,以及它们如何影响最终裁决"。

核心模型一:四类节点

整个图谱只允许四种节点类型,这是 map-schema.md 定义并在 contract.mjs 中硬编码的白名单:

节点类型语义使用要点
position唯一的当前裁决(verdict)全图恰好一个,且必须有至少一条入边支撑
claim中间命题连接证据与最终裁决的推理步骤
evidence对某一源区域的忠实陈述必须带sourceId,且必须作为至少一条边的from参与推理
unknown可能改变裁决的特定缺失事实用于结构化地表达不确定性,而不是"泛泛的还需更多研究"

从源码结构看,validate.mjs 通过NODE_TYPES集合(positionclaimevidenceunknown)逐节点校验类型,任何图外类型都会被标记为node-type违规;而confidence字段则被明确拒绝(false-precision规则),因为验证器认为"置信度百分比"是虚假的精确性——表达不确定性只能用unknown节点或收窄/限定立场。

核心模型二:四种边

节点之间的推理关系也只有四种,RELATIONS集合同样定义在 contract.mjs。evidence-ladder.md 给出了每类边"何时使用"与"最常见的冒牌货"对照表:

关系何时使用常见冒牌货
supports源增强了接受目标的理由主题相似
contradicts在同一范围与条件下两者不能同时成立日期或人群不同
qualifies源收窄了目标的范围、强度或适用性隐藏不利证据
missing某个具体缺失的事实阻碍或可能推翻目标泛泛的"还需更多研究"

Skill 特别警告两点:主题相似不是支持(topical similarity is not support);范围、日期或人群不同并不自动构成矛盾——这些差异应该用qualifies边表达,而不是粗暴地标成contradicts。每条边还必须附带一句通俗语言注释(plain-language note),说明为什么源节点与目标节点相关。

证据分级:从直接观察到无支撑断言

在动手采集证据之前,evidence-ladder.md 要求优先使用实际可行的最强证据,共六级,由高到低:

  1. 直接当前观察——可复现的行为、命令输出、检视过的工件或测量结果;
  2. 权威一手来源——官方规范、数据集、法律、文档、一方仓库或原创研究;
  3. 独立佐证——底层证据各不相同的可靠来源;
  4. 显式推断——前提与假设在图谱中可见的结论;
  5. 弱代理指标——与确切断言不直接吻合的相关指标、基准、轶事或测试;
  6. 无支撑断言——没有证据支撑的自信、重复或粉饰性语言。

注意一个重要的限定:更高级别的证据仍然可能过时、不相关或相对当前命题过宽——等级只衡量证据强度,不自动等于适用性。

源区域测试:创建证据节点前的五个自问

每条证据都必须锚定到一个有界的具体源区域。创建evidence节点前,evidence-ladder.md 要求回答:

  • 我依赖的确切句子、表格、命令输出、页面、章节或行区间是什么?
  • 它是否蕴含节点文本,还是仅仅讨论了同一主题?
  • 它的日期和版本是否适合该断言?
  • 该证据是独立的,还是从另一份被引来源复制而来?
  • 什么上下文会反转或收窄当前解释?

如果无法定位到确切区域,规则是:创建unknown节点,而不是证据节点。这一条直接约束了证据质量的下限,也解释了为什么后面会看到验证器对locatorexcerpt施加严格的格式约束。

十步工作流

SKILL.md 给出完整工作流,共十步:

第 1 步:框定单一决策。写出一个可证伪的问题和一个暂定立场,不断收窄问题,直到读者能识别图谱在检验哪个行动或信念。

第 2 步:收集有界源区域。优先直接观察与一手来源。为每个源记录:URL 或绝对本地路径、发布者、发布日期、检索日期、章节/页/行/时间戳定位符,以及一小段可核查的摘录。当源质量有争议时,阅读 evidence-ladder.md。

第 3 步:原子化推理。只创建前述四类节点。

第 4 步:为每条边定类型。使用supportscontradictsqualifiesmissing之一,并附通俗语言注释说明源节点为何作用于目标。

第 5 步:保留反证。即使暂定裁决在反证下仍然成立,也不得删除不利证据;范围差异用qualifies边表示。

第 6 步:结构化地表达不确定性。不要编造置信度百分比——添加unknown节点、收窄立场或限定某个命题。

第 7 步:写 UTF-8 JSON。文件使用.doubt.json后缀,遵循 map-schema.md;ID 保持简短、稳定、语义化。

第 8 步:失败即关闭地验证。以本SKILL.md为基准解析scripts/validate.mjs的相对路径,然后用 Node.js 18 或更新版本运行:

node <skill-directory>/scripts/validate.mjs decision.doubt.json

验证器只使用 Node.js 内置模块,不需要 npm 或网络访问。修复所有发现项后才能报告成功;只有命令退出码为0且打印出VALID加 64 字符收据时,才能说图谱是有效的。文件哈希、节点计数、JSON 解析成功或人工 schema 检查都不是Doubt 收据。如果确定性验证无法运行,必须报告阻塞而不是虚构成功。

随后,只有在用户已经安装doubt-ai@0.8.0时才能渲染已验证的图谱;不得隐式安装或执行远程包:

doubt map decision.doubt.json --out decision.html

第 9 步:仅在明确网络许可下验证源快照。下面的命令会逐一检索记录的 HTTP(S) 源,若摘录无法匹配则失败关闭:

doubt verify decision.doubt.json \ --out decision.verified.doubt.json

绝不隐式运行该命令。本地文件验证不走网络。不得手工编写verification对象,也不得掩盖不匹配。

第 10 步:检查交付物。确认问题、裁决、反证、未知项、边注释与精确源区域仍然可读。JSON 是规范的、可编辑的工件;HTML 只是可分享的视图。

.doubt.json规范:完整示例

map-schema.md 给出了规范的 JSON 结构。规范工件是 UTF-8 JSON,实用时使用.doubt.json后缀:

{ "title": "Short artifact title", "question": "One decision-changing question?", "updatedAt": "YYYY-MM-DD", "verdict": "A provisional, evidence-bounded answer.", "nodes": [ { "id": "current-position", "type": "position", "label": "Current position", "text": "The proposition represented by this node." }, { "id": "primary-observation", "type": "evidence", "label": "Observed result", "text": "A faithful statement of the source region.", "sourceId": "source-1" }, { "id": "missing-baseline", "type": "unknown", "label": "Missing baseline", "text": "The exact absent fact and why it matters." } ], "edges": [ { "from": "primary-observation", "to": "current-position", "relation": "supports", "note": "Why the observation increases reason to accept the position." }, { "from": "missing-baseline", "to": "current-position", "relation": "missing", "note": "Why this missing baseline could reverse the position." } ], "sources": [ { "id": "source-1", "title": "Source title", "url": "https://example.com/source", "publisher": "Publisher", "date": "YYYY-MM-DD", "retrievedAt": "YYYY-MM-DD", "locator": "Section: Results, p. 7, § 2.1, L12-L18, or 00:04:31", "excerpt": "A short, checkable excerpt or bounded source-region description." } ] }

注意verdict的定位是"暂定的、受证据约束的答案"——图谱的裁决永远不应比证据更宽(见后文质量门禁)。

不变量:验证器强制执行的契约

contract.mjs 中的inspectMapContract实现了完整的契约检查,validate.mjs通过validateMapFile把它包装成命令行工具。逐条对应 schema 的不变量如下:

顶层字段。titlequestionverdictupdatedAt必须是非空字符串;updatedAt必须是真实存在的日历日期(YYYY-MM-DDparseIsoDate会校验月份天数等合法性);nodes必须是非空数组,edgessources必须是数组(可为空)。

节点约束。每个节点必须有唯一字符串id、合法的type、非空的labeltextconfidence字段一旦出现即报false-precision。证据节点必须有sourceId且引用已存在的源;每个证据节点必须至少作为一条边的from参与推理(否则报unused-evidence)。

源约束。每个源必须拥有全部七个非空字段(titlepublisherdateretrievedAturllocatorexcerpt):

  • url必须是http(s)://file://、相对路径或绝对本地路径(sourceLocation正则);
  • locator必须匹配有界定位符模式(contract.mjs),支持如p. 7§ 2.1L12-L18lines 12-18、时间戳00:04:31以及Section: ...形式;
  • excerpt长度必须落在40–500 字符之间,且包含至少 6 个不同的字母数字符号(substantiveExcerpt去重检查),重复填充词会报low-information-excerpt
  • 日期链不变量:source.date不得晚于updatedAtretrievedAt不得晚于updatedAtretrievedAt不得早于source.date

边约束。from/to必须引用已存在的节点,禁止自指;from/to/relation三元组不得重复(duplicate-edge);relation必须属于四类白名单;note必须是非空字符串。

图结构约束。图谱必须恰好一个position节点,且该节点至少有一条入边(unsupported-position);每个非 position 节点必须存在一条有向推理路径通向 position(reaches深度优先遍历,否则报disconnected-node);图中不得存在有向环(三色标记 DFS 检测,报reasoning-cycle);每个源必须被至少一个证据节点引用(unused-source)。

验证器运行原理:收据是怎么算出来的

validate.mjs 的主流程清晰且刻意保持最小化:

  • validateMapFile(file)读取并JSON.parse文件;解析失败返回带invalid-json发现的失败结果,绝不崩溃后继续;
  • inspectOfflineMap(map)inspectMapContract基础上,仅当图谱有效时计算收据;
  • receiptFor(map)对每个源取其idretrievedAt与摘录的 SHA-256,拼进receiptPayload(其契约标记为doubt-evidence-receipt-v1),再对整包做规范序列化canonicalJson按键排序)后计算整体 SHA-256,得到 64 个十六进制字符的收据。

这就是为什么"JSON 解析成功"不等于"有效图谱":收据覆盖的是源的检索日期与摘录摘要,而不是 URL 当前服务的可变字节——这也是源码里Receipts cover that value and the recorded excerpt, not the mutable bytes currently served by the URL一语的由来。

命令行用法(见 validate.mjs 的帮助文本):

node <skill-dir>/scripts/validate.mjs <map.doubt.json> [--json]
  • 不带--json时输出人类可读结果:无效则打印INVALID <n> finding(s)及逐条path [rule] message;有效则打印VALID <receipt>,并附带一行指标:claim 数、evidence 数、source 数、contradiction 数与显式 unknown 数;
  • --json时输出完整结果对象(含findingsmetricsreceiptvalid);
  • 图谱无效时进程退出码设为1,便于接入 CI 或脚本门禁。

整个验证器只依赖 Node.js 内置模块(node:cryptonode:fs/promisesnode:pathnode:url),无需 npm install、无需网络,这正是它适合作为"确定性门禁"嵌入工作流的原因。

可选验证记录:只有命令才能写

verification对象只能由一次成功的显式源验证命令添加,且必须逐字段满足校验(map-schema.md、contract.mjs):

{ "verification": { "status": "verified", "method": "normalized-excerpt-match", "checkedAt": "YYYY-MM-DDTHH:mm:ss.sssZ", "contentSha256": "64 lowercase hexadecimal characters", "excerptSha256": "64 lowercase hexadecimal characters", "finalUrl": "The checked URL or absolute local path", "locatorStatus": "matched" } }

约束要点:status必须恰为verifiedmethod必须恰为normalized-excerpt-matchcheckedAt必须是带Z的 ISO UTC 时间戳,且其日期部分必须等于该源的retrievedAt;两个 SHA-256 字段必须是 64 位小写十六进制;locatorStatus只能是matchednot-machine-checkedfinalUrl必须是合法源位置。

特别提醒:对于页面、章节、时间戳类定位符,locatorStatus允许取not-machine-checked——但这不代表该区域被人工确认过,不要把它当作人工核实完成的证据。

质量门禁:交付前的九项检查

一份完成的图谱必须全部满足 SKILL.md 列出的九条质量门禁:

  • 恰好一个position具有传入推理;
  • 每个evidence节点命名一个源并参与某条边;
  • 每个源都被使用,且具备日期、有界定位符与实质性摘录;
  • 每个非 position 节点都有通向 position 的有向路径;
  • 推理图无重复边、无有向环;
  • 当源集合确实包含反证或限定性证据时,图谱中必须呈现它们;
  • 每个可能改变裁决的缺口都是显式的unknown节点;
  • 每条边注释都解释了支持、矛盾、限定或缺失;
  • 裁决不比证据更宽。

前六条是验证器可机械执行的图结构与溯源约束,后三条是内容质量要求——提醒作者:反证不能因为裁决存活就被删除,不确定性必须落在图谱里,裁决措辞不能超出证据覆盖范围。

交付结果报告

完成验证后,向用户报告 SKILL.md 规定的五项内容:

  • 用一句话陈述当前立场;
  • 最强的反证或限定是什么;
  • 最重要的未解决未知项;
  • 规范 JSON 与任何渲染 HTML 的路径;
  • 确定性验证与显式源验证是否已经运行。

同时必须遵守一条诚实性红线:绝不把结构上有效的图谱描述为"已被证明为真"。验证只确立了可追溯性与图结构完整性;源质量和推理质量仍然需要人工审查。

在 awesome-copilot 中获取并使用该 Skill

该 Skill 已在仓库的 docs/README.skills.md 中登记,可用 GitHub CLI 安装:

gh skills install github/awesome-copilot build-evidence-map

也可以把整个文件夹手动复制到本地 skills 目录。Skill 目录结构如下,全部资源随 Skill 一起分发:

  • SKILL.md —— 主指令(工作流、质量门禁、交付要求);
  • references/evidence-ladder.md —— 证据分级、源区域测试、边测试;
  • references/map-schema.md —— JSON schema 示例与不变量、可选验证记录;
  • scripts/contract.mjs —— 契约校验与收据计算的底层实现;
  • scripts/validate.mjs —— 零依赖命令行验证器入口。

使用时的最小闭环是:框定问题 → 按 schema 手写(或由 Copilot 辅助生成)decision.doubt.json→ 运行node <skill-dir>/scripts/validate.mjs decision.doubt.json直至输出VALID与收据 → 必要时在明确许可下用doubt verify做源快照核验 → 按五项要求交付报告。整个过程把"结论可信"从依赖模型自信,迁移到了可复核的图结构与源锚点之上。

【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询