feat(evidence): 统一 Source → Evidence ↔ Claim 证据契约 - #104
Theater-ahyeon wants to merge 1 commit into
Conversation
新增 folio-evidence-contract/v1 统一契约(core 类型 + shared 投影), 把 FinancialEvidenceEnvelope、EvidenceRef、NewsItem 三套并行证据抽象 投影到同一条 Source → Evidence ↔ Claim 关系链: - core/evidence-contract.ts: EvidenceSource / EvidenceItem / EvidenceClaim / EvidenceBundle 类型,全部 ID 确定性派生(sha256,键序无关), 组装 → 持久化 → 重载全程稳定 - shared/evidence/contract.ts: 四个投影函数(结构化金融事实 / 研究论点 / 新闻 / 通用文档备案)+ buildEvidenceBundle 多对多合并 + 序列化往返守卫 - 结构化金融来源不伪造 canonicalUrl;authority 元数据只在已知时填写; 投影只读输入,现有持久化记录无需迁移 - docs/evidence-contract.md: 身份与生命周期语义文档 对应 helsome#100(契约整合部分;claim verifier / Source Inspector 接入留作 后续增量 PR)
helsome
left a comment
There was a problem hiding this comment.
方向非常值得保留,而且 #100 需要的核心形状基本已经出来了;测试报告也满足要求。当前我只卡两个会进入长期证据契约的数据语义问题,建议在 v1 落地前修掉:
-
projectNewsItems目前把NewsItem.timestamp同时写进publishedAt和retrievedAt,且直接原值写入。现有 core 明确约定NewsItem.timestamp是 epoch seconds,而新契约把EvidenceSource.retrievedAt/publishedAt定义为 epoch ms;这里会产生 1000 倍时间偏差。同时NewsItem只有来源时间,并没有真实 retrieval time,不能用发布时间冒充抓取时间。请让调用方显式提供 retrieval timestamp(或把未知 retrieval 表达为 unknown/optional),并在投影处做统一单位转换,补一个能抓住 seconds↔ms 的测试。 -
projectFinancialEvidence中financial.asOf会优先使用value.asOf ?? envelope.asOf,但同一 EvidenceItem 的freshness.asOf只写envelope.asOf。当 metric 有更细粒度value.asOf时,同一条证据内部会出现两个不同的时间语义。请统一为同一个 resolved as-of,并补value.asOf存在、envelope asOf 缺失/不同的用例。
这两个点属于 #100 最核心的“不要让不同来源在统一层丢失/伪造时间语义”,不是要求扩大 scope。其余 Source/Evidence/Claim、确定性 ID、多对多、structured finance 不伪造 URL 的方向我认可。#105/#106 是 stacked 在本 PR 上,先把这里修正即可,不需要三个 PR 重复改。
改了什么
按 issue #100 的「版本化、增量式证据契约」方向,新增统一契约的第一个增量切片:契约类型 + 三条既有证据路径的确定性投影 + bundle 组装/序列化。不改动任何现有类型、持久化格式与生产路径。
新增文件
packages/core/src/evidence-contract.tsEvidenceSource/EvidenceItem/EvidenceClaim/EvidenceBundle契约类型与folio-evidence-contract/v1版本常量packages/shared/src/evidence/contract.tsbuildEvidenceBundle+ 序列化/守卫packages/shared/src/evidence/contract.test.tsdocs/evidence-contract.md修改文件(各 1 行导出接线)
packages/core/src/index.ts、packages/shared/src/evidence/index.ts为什么要改
当前存在三套并行演化的证据抽象:Copilot 的
FinancialEvidenceEnvelope(结构化金融事实)、Deep Research 的EvidenceRef(论点引用)、NewsItem(网页/新闻)。同一事实/来源因来自不同子系统而获得不同身份与元数据(语义碎片化)。本 PR 用一条 Source → Evidence ↔ Claim 关系链统一它们,且是投影整合而非新框架:现有类型仍是生产方的权威表示。对应 Issue
#100(契约整合部分)。claim verifier(#13)、Source Inspector UI(#30)、检索去重(#39)的接入留作后续增量 PR。
设计要点
sourceId/evidenceId/claimId全部由 sha256 确定性派生(截断 24 位,src_/ev_/claim_前缀,与现有fe_风格一致);哈希输入经键排序的stableJson序列化,身份永不依赖对象键序。sourceId不含检索时间:同一文档/查询被再次观察仍是同一来源evidenceId含检索时间:同一事实稍后再次观察是同源新 observation,保留各自 provenanceclaimId由表述 + instrument 作用域派生:不同 run 的相同论点在 bundle 中合并并并集 evidenceIds —— 多对多映射由此自然成立evidenceIds[],Evidence 不反向命名 Claim;一条证据可支撑多个论点。structured_finance来源无公开文档,canonicalUrl恒为空,身份由 publisher + dataset + query 承担;authority元数据只在实际已知时填写(如监管备案)。availability枚举值,不允许静默丢弃。验证
环境:Bun 1.4.2 / Windows 10 (10.0.26200)
验收标准覆盖情况:
evidence-contract.ts+docs/evidence-contract.md)projectFinancialEvidence/projectNewsItems/projectTextEvidence;研究论点路径projectEvidenceRefs覆盖 tool 证据)mixed-source integration用例在单个 bundle 同时携带结构化金融证据、tool 论点证据、新闻摘录、监管备案摘录并验证重载一致无可见 UI 变化
纯契约/共享层新增,不改任何 UI、IPC 或持久化行为。
已知未完成项(后续增量 PR)
verification/verifiedBy,契约不变)