返回设计文档

EVIDENCE · 05/08

Five-Bucket Evidence

Core、engines、aiskills、memory、golden 的 active contract。

真相源
docs/DESIGN_五桶证据.md
读取方式
构建时本地读取
规模
532 行

Status: active Scope: nexrur substrate Evidence Traceability: GitHub issues #10, #26, #42, #95, #212, #223, #276 Updated: 2026-09-05

本文只定义底座通用 Evidence 能力。任何 App 名、产品名、业务阶段名、领域字段、 来源分类和模型供应商都不属于本文真相。

1. 定义

Evidence 把当前执行需要的事实整理成五桶:

桶内容读取原则
coreoutcome、manifest、core audit只读 App 合同声明的 core sources
enginesorchestrator、campaign、ToolLoop 运行事实只读允许的底座/核心账本
aiskills已投影的业务资产和显式 extra sources只执行 aiskills read plan
memory已登记 memory source 与选择结果backend 状态由运行 envelope 显式提供
golden已审核 Diagnosis 案例与显式历史事实只读登记的 Golden 资产

Evidence 不判断业务成败,不诊断根因,不选择 Campaign 路由,也不决定资产晋升。

2. 唯一公开入口与固定内部链

App 和 App orchestrator 只允许调用一个 Evidence 公开入口:

nexrur_evidence_obligations

nexrur_step6_evidence_obligations 只是同一入口在 Step 6 state 下的语义别名, 不是第二套 Evidence runner。Bundle、五个 Reader 和 Digest 是底座内部受审计 子链,不得暴露为 App phase,也不得要求 App 按顺序分别调用。

每次公开调用必须闭合以下内部链:

Obligations public facade
  -> Bundle
       -> read core
       -> read engines
       -> read aiskills / materialize required lanes
       -> read golden candidates
  -> Digest
       -> digest core / engines / aiskills
       -> read and digest memory
       -> select and digest golden
  -> deterministic obligation assembly
  -> handoff schema/identity validation
  -> Projection
  -> success | partial receipt

已有 Bundle/Digest 只有在 identity、state、trace/cycle、source hashes 和完整性 receipt 全部一致时才可幂等复用。缺 Bundle 必须补跑 Bundle;缺 Digest 必须补跑 Digest。不存在“没有 Digest 也继续组装 Obligations”的合法路径。

2.1 公开状态与 fail-closed

公开状态条件handoff是否可继续
success全部 required 子链完成,handoff 验证与 Projection 成功,且无降级或 warning必须存在、Schema 有效且已 Projection是
partialrequired 子链、覆盖、handoff validation 与 Projection 均闭合,仅存在 optional/advisory warning;零 errors、零 failed bucket、零 omitted content unit,represented 与 total 完全相等必须存在、Schema 有效且已 Projection,并保留 warnings/degraded facts是,由 ToolLoop control envelope 明确列入 continue statuses
failedrequired 缺失,或任一内部执行、Digest 完整性/覆盖、身份/状态、handoff validation、Projection 失败禁止产生可用 handoff否

Evidence 公开结果严格只有 success | partial | failed。Reader 内部可使用 empty、degraded、missing_required、error、blocked 等细分状态,但必须在 Obligations 公开出口归一。有可消费 handoff 且完整性闭合的有界缺口归为 partial;存在 errors、failed bucket、omission、required 缺失或 handoff 不可用归为 failed。partial 不得洗成 success;是否继续由显式 ToolLoop control envelope 声明。 Active 只验证并晋升已闭合的产物,不补跑 Bundle、Digest 或 Obligations。

3. 显式 Evidence envelope

底座只认以下通用身份:

current_scope:
  product: <opaque product key>
  asset_band: <optional opaque band>
  asset_id: <optional>
  canonical_id: <optional>
  subject_id: <optional>
  trace_id: <required when writing trace>
  run_id: <optional>
  step_run_id: <optional>
  target_subagent: <optional opaque owner>
  target_module: <optional opaque module>
  target_step: <optional opaque step>
  current_artifact_refs: []
  memory_backend_status:
    backend: <opaque backend>
    read_status: <opaque status>
    write_status: <opaque status>
    degraded: false
    degraded_reason: null
    source: engines

规则:

  • orchestrator/ToolLoop 在 Evidence 边界构造 current_scope;
  • reader 可以把顶层同名通用字段规范化进 current_scope;
  • 不允许从目录名、phase 名、结果字段名或历史文件内容推断 product、asset 或 step;
  • App 私有身份别名只能声明在 App 的 evidence.yml::identity_aliases;
  • 别名缺失时不猜;别名配置损坏时 fail closed;
  • 同时出现冲突状态或冲突身份时 fail closed。
  • subject_id、canonical_id 和 asset_id 是三个独立身份;除非 App 在 identity_aliases 显式声明,否则任何一个都不得冒充另一个。
  • identity_aliases 只把 App 原始字段名归到同一个通用身份,不允许把 subject_id、canonical_id、asset_id 三种通用身份互相匹配;任一同时存在的 身份或 trace/run 身份冲突都必须拒绝该记录。
  • LLM usage attribution 只写真实 asset_id;unbound 请求写 trace_id,不得把 subject/canonical 填进 asset_id 记账字段。
  • 包级公共 scope 编译接口只有 compile_current_scope(...);Evidence 不提供 runtime-object marshal、旧 payload adapter 或第二套 schema alias 翻译。

3.1 Artifact ref grammar

Bundle、core、engines 与 aiskills 共享同一显式引用解析规则:

Ref := 非空本地路径字符串 | Python Path | {path: 路径, ...metadata}
     | {ref: 路径, ...metadata}
Refs := Ref | [Refs, ...] | {逻辑名称: Refs, ...}

path / ref 对象是终止节点,只从明确 locator 寻址;存在 path 时它优先。 其余字段(包括来源路径、业务 ID、类型与 metadata)保留为元数据,不继续搜索路径。 named mapping/list 可嵌套并展开所有真实引用,禁止将 list/dict 的字符串表示传给 Path。非法 locator 类型、空值、循环引用、URI 和含 NUL/换行的值不作为本地引用。 已保存 read plan 的 {source, name, ref: Refs} 包装可以展开其明确 ref 容器, 不会递归包装上的其他元数据;path 字段仍必须是单个路径。active/reference 分流 只检查真实路径,不依据 source/name/metadata 中出现的 active 字样。 errors、warnings、diagnostics、diagnosis_result、projection_tool_calls 等 诊断/调用记录不是 ref 容器,里面即便出现 path 也不递归读取。App 应将这些记录 放在普通结果字段,业务身份仍可以随 typed ref 保留。 named mapping 的 metadata / content / summary 名称本身不排除文件:其值是 可辨识路径字符串、Path 或显式单路径 {path/ref: ...} 时作为正常引用消费;值是 原始对象树、列表或普通说明文字时不向内寻找路径。typed ref 对象上的同名字段仍只 是 metadata,不递归。诊断/errors/调用记录字段始终不是路径槽,不适用这个窄区分。

文件系统拒绝单个引用(包括 Linux ENAMETOOLONG)不得抛出到整个 Bundle 并丢弃 其他来源。core/engines 将不可读取的候选排除,required source 没有可读取文件时 仍按缺失失败;aiskills 保留该引用的 artifact_ref_unreadable 事实和其他已读取产物, required source 有这种显式引用读取错误时必须 missing_required,经公开出口归一为 failed;其他既有 advisory read warning 保持其来源合同的降级语义。 错误元数据被排除不表示业务成功;业务错误继续通过明确 failure facts 交接。

4. Evidence state

允许的通用状态只有:

evidence
step6_evidence
restart_evidence

provenance_lane 必须与 evidence state 相同。App 风格状态名、历史 phase 状态名和 隐式映射全部禁止。

通用 ToolLoop callable 可以通过其明确身份选择默认状态:

  • regular Evidence callable -> evidence;
  • Step 6 Evidence callable -> step6_evidence。

其他 callable 必须显式传 state。

5. App Evidence contract

Canonical path:

<app>/.gemini/skills/_shared/engines/evidence/evidence.yml

底座只解析通用结构:

version: 1

identity_aliases: {}

core:
  sources: []

engines:
  sources: []

aiskills:
  sources:
    - name: aiskills_projection_contract
      enabled: true
      required: true
      projection_contract_path: .gemini/skills/_shared/engines/projection/projection.yml
  summary_fields: []
  extra_sources:
    <current_product>:
      <source_id>:
        product: <explicit source product>
        target_steps: []
        root: <explicit template>
        files: []
        copy: true

memory:
  sources: []

golden:
  sources: []

obligation_targets: []

App 拥有:

  • source 名称、路径模板、业务字段和 source taxonomy;
  • identity aliases;
  • aiskills summary fields;
  • extra source 的 product、target steps、root、files、copy 策略;
  • obligation targets 与 declaration 内容;
  • memory backend 的实现与状态产生。

底座不得提供上述内容的 App 默认值。

纯 optional source 缺失进入 degraded_optional_sources,并允许把当前五桶结果 标为 partial;partial 本身不阻断,因此 fresh Product 在尚无历史 Core/Engines/AIskills/Memory 时不会被自己锁死。optional empty bucket 仍写 empty receipt 并继续,warning 与缺口必须进入最终 handoff;required source 不可用则归一 为 failed 并 fail closed。LLM profile/model 路由不属于 App,由 llm.yml 按稳定 caller role 统一声明。

6. core reader

core reader 只允许已登记的通用 artifact type:

  • outcome_json;
  • manifest_json;
  • core_audit_jsonl。

读取顺序:

  1. 显式 artifact/evidence refs;
  2. 当前 scope 约束下的合同路径;
  3. 无 scope 时 required source 不得靠全局扫描通过。

reader 输出 bounded content unit、artifact ref、source report 和 scope report。它不解释 业务字段,不根据字段名推断状态。

7. engines reader

engines reader 只读底座允许的运行账本根和 App 合同声明的 source。它按 trace_id/run_id/step_run_id 过滤当前执行,不读取历史目录补事实。

规则:

  • 模板越过允许根时 fail closed;
  • 超限文件只输出索引和明确 degraded 原因;
  • JSONL 先按 current scope 过滤,再生成 bounded unit;
  • 不从 runtime 记录推断 App 产品或业务 phase。

8. aiskills reader

aiskills reader 必须消费 aiskills_read_plan。没有 plan 直接 failed,不允许恢复 全局 glob 或旧 business/local reader。

read plan 至少包含:

state: evidence|step6_evidence|restart_evidence
scope:
  product: <explicit>
  asset_id: <explicit when bound>
  trace_id: <explicit when writing>
  target_step: <explicit when selectors need it>
upstream: []
reference: []
current:
  include_active: <true only when asset_id exists>
diagnosis: {}

额外规则:

  • projection product 由 App step/orchestrator 显式传入;
  • extra_sources 每项必须有 product;
  • 有 target_steps selector 时,current_scope.target_step 必须存在;
  • reader 不得把 phase 当 product,也不得从路径猜 product;
  • upstream/diagnosis raw lanes 通过 Projection trace 原子写入;
  • materialization receipt 可幂等复用,但损坏或半提交必须 fail closed;
  • reference 只作候选上下文,不冒充 active truth。

9. memory reader

memory reader 在具体 Memory backend 已显式启用时,消费 core/engines/aiskills 三个 primary bucket 的 digest context,再执行通用 program/LLM 选择链。它不探测 provider key、环境变量或 App 本地模型配置。

current_scope.memory_backend_status 缺失,或 backend 为 none / disabled / not_configured 时,表示 Memory 尚未配置。可选 Memory source 必须返回显式 not_configured 空桶,跳过 primary digest ref 门禁、store 查询和 Memory LLM;不得阻断 Evidence。只有 required source 缺少 backend 时才 fail closed。具体 backend 已启用后, primary digest 缺失、backend degraded、store 失败或内容损坏仍按真实失败/降级上报。

任何 LLM 选择器或仲裁器都必须使用稳定的 caller role;具体 profile、provider、 model 和 Flash/Pro 路由只由 llm.yml 声明。App payload 不得覆盖该路由。

Memory 只调用 evidence.yml::memory.sources 中显式启用的 store。每个 source 必须声明 artifact_type、root_type: memory_store、retrieval_mode: store_api、 config_path 和 store_path;不得探测默认目录,也不得在 backend unavailable 时先调用 store 再补一个 degraded 标签。LLM 输出 schema、候选 ID 或状态不合法时 fail closed,不能静默过滤坏 ID 后继续。

10. golden reader

Golden 只读已审核 Diagnosis 资产或 App 显式声明的历史 source:

  • positive case;
  • counterexample;
  • pattern。

Diagnosis assets root 必须由 payload 或 App contract 显式提供。底座不从目录布局猜根。 候选文件损坏、索引冲突、路径越界或 hash/span 不一致时 fail closed。

Golden ref 与普通 business evidence ref 必须分槽:

  • golden_artifact_refs:selector/audit;
  • artifact_refs/evidence_refs:production/diagnosis facts。

Golden 不能被当作当前业务事实。

11. digest

digest 只压缩 bounded reader units:

  • core 与 engines 互不依赖,可使用通用 Flash digest prompt 并行压缩;两路 计算完成后必须按 canonical bucket 顺序串行执行 Projection 原子写入;
  • aiskills upstream/diagnosis raw truth 不二次改写,只生成 reference digest;
  • memory 必须先执行程序 gate,再由 Flash 选择;只有 Flash 与程序结果冲突时 才进入 Pro 仲裁,最后用 Flash 生成 memory digest;
  • golden 只用 Flash 生成 selector digest,不做常驻 Pro 仲裁。

每个被请求的 bucket 都必须落一个 digest receipt;合法空桶写 deterministic empty receipt,不能因为没有 content unit 就消失。AIskills 空桶仍写 aiskills/reference.json,不得恢复同级 aiskills.json。Memory 的 Flash/Pro 选择结果必须把 program candidate pool 完整划分为 selected/rejected;Golden 同样必须把所有 eligible cards 完整划分,重复、交叉或遗漏均 fail closed。

Digest 汇总状态遵循公开三态:只有 warning、optional empty 或可审计降级时返回 partial 并继续;任一 requested bucket 失败、任一 error、unit 覆盖遗漏或 required 缺失必须返回 failed。Obligations 必须同时接受合法的 success 与 partial Digest, 完成 obligation assembly、handoff validation 与 Projection,并把 partial 原样传播 到 handoff 和最终 receipt;不得因 digest_status != success 直接制造失败。

具体 provider/profile 的能力声明与路由解析只能来自 llm.yml。Evidence Python 只提交稳定 caller role,不 hardcode provider、model 或 App 默认值;App 也不传 Evidence 专用 profile/model 覆盖底座路由。

11.1 普通摘要的一次 Pro 补救(nexrur #284)

core / engines / memory 的普通摘要首次使用 evidence_digest:<bucket>。 只有模型最终 JSON 不可解析、不是 object、缺少必填字段、字段类型/枚举不符, 或公开 LLM 已返回 llm_provider_empty_final_content 时,Evidence 调用方才允许 以相同 Prompt、相同 bounded source units 调用一次 evidence_digest_repair:<bucket> 完整再生成;该角色在 llm.yml 路由到 llm_pro。再次不合格即失败,不能继续 切模型、补造 status=success、删掉校验或重跑其他 bucket、Reader、APP/MCP。

这是底座检查自己的摘要合同,不读取或判断 APP 业务状态。合法 partial 不触发 补救;无 source units 仍走零 LLM 的 deterministic empty receipt。结构合法但仍 遗漏/重复/伪造 unit id 的回答保持严格 coverage 失败,不由程序补齐或伪装完成。 网络、鉴权、admission、权限、超时、截断或拒绝等执行失败不触发这层再生成。 既有 LLM provider 返空/transport 恢复不变,Golden 已有的 Pro 补救不再套一层。

每个 bucket 的 llm_call 保存顺序 attempts、caller、耗时、原始 reason code、 结构校验错误与失败回答哈希,以及 recovery_attempted / recovered。不保存原始 prompt/response,也不把第一次失败覆盖成从未发生。两次均无有效摘要时,coverage 中的零值表示零份通过校验的摘要,representation_basis=no_validated_llm_digest; 不得再由空占位结果制造“模型遗漏了所有输入”的次生错误。

Deadline 声明每个普通 bucket 的 Flash 与一次 Pro 为顺序上界;core 与 engines 两条链仍并发,memory 普通 digest 的上界排在既有 Memory 选择/仲裁之后。模型升级 不能仅增加执行代码而不增加 Deadline 拓扑。真实 token/费用继续由公开 LLM usage 记录,两次 caller 生成不等于只有两次 provider HTTP 尝试。

调用要求:

evidence_state: <explicit>
current_scope: <explicit>

禁止:

  • provider/model 默认值;
  • key/env 探测;
  • use_flash 之类 provider 选择旁路;
  • Evidence 专用 max_output_tokens、按 unit 数估算输出上限,或在 Evidence 中截断 LLM 输出;
  • 领域 claim/formula/operator/slot preservation 规则;
  • App source type 白名单;
  • 把 oversized 原文直接塞进 LLM。

LLM 的 provider 输出能力、续写/重试和统一输出策略归 LLM 底座。Evidence 不传 专用输出上限;它只在返回后验证每个 input unit 都有且只有一个对应输出。 如果底座最终返回不完整结果,Digest fail closed,不用 Python 补写或伪造覆盖。

输入“裁剪”只允许是可审计的去重、哈希、结构化索引、retrieval 或 chunking; 禁止字符串静默截断。oversized source 只能进入 App 声明的 memory/index 能力, 返回 bounded retrieval;无法安全路由时 fail closed。

12. obligations 与 Step 6

App 通过 obligation_targets 声明要携带的 obligation。底座只做机械 envelope:

obligations:
  <target without _obligations suffix>:
    source: app_obligation_declaration
    truth_source: app_manifest
    declaration: {}
    evidence_refs: []
    source_digest_refs: []

底座不得内置某一种业务 obligation。

obligation_targets 缺失或为空表示 App 本轮没有额外 obligation,合法结果是 obligations: {};底座不得强迫每个 App 伪造声明。只有 App 显式列出 target 后, 对应 declaration 缺失或非法才是编译失败。

Step 6 diagnosis packet 只从显式通用字段组装:

  • phase_failure_facts;
  • production_failure_facts;
  • validation_facts;
  • runtime_failure_facts;
  • phase_issue_facts;
  • schema_errors;
  • requires_diagnosis。

禁止扫描任意 *_result、按字段名猜 validation、从 phase history 找 reason,或读取 App 私有结果名。reason code 只能来自显式 failure facts。

builder 不得修改调用方 payload。多个显式 evidence state 冲突时 fail closed。 Diagnosis packet 的 source_phase 只能来自显式 current_scope.target_step 或 显式 source_phase;不得从 failed_phase 或目录名反推。

13. Projection 与 unbound trace

Evidence 不手写 ai-skills 目录。所有 trace/digest/handoff 写入通过通用 Projection:

  • 未出生资产写 <product>/<trace_id>/...;
  • 已绑定资产写 <product>/<asset_id>/<trace_id>/...;
  • bind 成功后才承认 asset id;
  • archive/bind 由授权动作执行;
  • Evidence 不决定何时 bind 或 archive。

Evidence handoff 和 digest 在资产未出生时立即写入 trace scope;不存在 deferred handoff,也不存在资产出生后由 Orchestrator 回头补写 Evidence 的 finalizer。 projection_identity 必须随 handoff 明确记录 scope/product/trace_id/cycle_no; 只有真实 asset_id 存在时才允许 scope: asset。

写入必须原子、幂等、冲突失败,禁止复制出双份真相。

14. 公开接口与内部模块

App-facing ToolLoop 公开接口只有 nexrur_evidence_obligations,以及指向同一 callable 的 Step 6 语义别名。下列 Python 模块可供底座内部组合、聚焦测试和 显式导入,但它们不是 App ToolLoop 的八个公开 phase:

build_evidence_bundle
build_evidence_digest
build_obligations
compile_current_scope
read_core_artifacts
read_engines_artifacts
read_aiskills_artifacts
read_memory_artifacts
read_golden_artifacts

内部子链可以使用各模块的 run(...),但必须由 Obligations facade 按本文 固定顺序编排,并保留每个子链的 deadline、audit 和 receipt。__init__.py 不保存 执行逻辑或 Evidence cache。重放、checkpoint、幂等和落盘 receipt 分别由 ToolLoop、Orchestrator 与 Projection 负责。

15. App-neutral 禁止项

nexrur Evidence Python、prompt 和 active substrate contract 禁止出现:

  • App/product/phase 名称及别名;
  • App source taxonomy;
  • 领域 ID、公式、operator、slot、claim 规则;
  • App validation count、业务状态或私有结果字段;
  • 目录名/phase/result 字段猜测;
  • provider 默认值、provider key/env 探测;
  • 旧 business/local/RAG compatibility 接口;
  • fallback success。

App 业务词只允许存在于 App DESIGN、prompt、schema、evidence.yml 和 production callable。

16. 验收

每次 Evidence 改动至少验证:

  1. Python compile;
  2. App evidence/projection/toolloop YAML parse;
  3. 五桶聚焦测试;
  4. 无 plan 的 aiskills reader fail closed;
  5. 缺 product/target step/backend status 或 caller route 未在 llm.yml 声明时按合同失败或 degraded;
  6. state 冲突 fail closed;
  7. materialization 重放幂等,半提交不产 success receipt;
  8. Golden 与普通 evidence ref 分槽;
  9. 代码和 prompt 不包含 App/provider 默认值;
  10. git diff --check 与凭据扫描通过。
  11. bound/unbound handoff 都直接投影,且 subject_id 不会生成假资产目录;
  12. 旧 private scope/asset-birth 标记只能用于 fail-closed 退场测试,active 路径不再 接受它们;不得存在 deferred handoff 或 Evidence 包级 cache。
  13. App 只登记 Obligations,Bundle/Digest/Reader 未出现在 App graph 或 App ToolLoop block;
  14. 合法 warning-only/optional-empty Digest partial 必须完成 Obligations、handoff validation 与 Projection,并以 partial 满足下游依赖;
  15. 缺 Digest、required missing、coverage omission、handoff validation 失败和 Projection 失败均归为 failed,不产 success、partial 或可用 handoff;
  16. resume/replay 只复用 identity/state/source hashes 完整一致的 durable receipt。
  17. typed/nested refs 保留真实路径与身份元数据,诊断/调用记录不参与路径查找;模拟 Linux stat 错误时其他产物仍可读取,required source 不得变成 success/partial。