06:结果可信:模型生成产物以后为什么还要继续验证
从模型 final answer 之后的 validating 阶段出发,介绍 RunLens 怎样用产物契约、Stop Hook 和证据索引检查文件结构、内容格式与引用真实性。
06:结果可信:模型生成产物以后为什么还要继续验证
上一篇介绍了 RunLens 怎样控制循环和失败恢复。模型最终返回 final answer 后,AgentLoop 会停下来,Runtime 随即进入 validating。
这个阶段决定了一次 Run 能否交付。
模型可以生成结构完整、语言流畅的内容,也可能遗漏文件、写错枚举、缺少报告章节,或者引用一条源 CSV 中从未出现过的反馈。
RunLens 把“模型结束”和“业务完成”分成两个判断。
Final answer 负责结束模型循环,Artifact Validation 负责确认交付结果。

模型结束之后,文件还要接受检查
Feedback Analysis 要交付三个文件:
artifacts/feedback_analysis.json
artifacts/product_backlog.json
artifacts/insight_report.md
模型结束时可能出现几种情况:
- 只写了两个文件。
- JSON 可以解析,但缺少必需字段。
- priority 写成
high,而业务契约要求P0–P3。 - Markdown 报告缺少风险章节。
- analysis 和 backlog 引用了同一个虚构 feedback_id。
- feedback_id 真实,evidence_text 却是模型改写后的内容。
这些结果仍然可以读,业务可信度已经发生变化。
我希望 Run Status 能准确表达这次结果是否满足交付条件,因此验证逻辑放在 Runtime 的最终阶段统一执行。
ArtifactContract 先定义什么叫交付结果
Plugin 使用 ArtifactContract 声明每个最终产物。
主要字段包括:
| 字段 | 作用 |
|---|---|
name | 工作区相对路径 |
description | 产物用途 |
label | 前端展示名称 |
audience | user 或 developer |
sensitivity | 敏感级别 |
required | 是否属于必需交付 |
schema | JSON 轻量校验规则 |
required_headings | Markdown 必需标题 |
evidence_fields | 证据 ID 在 JSON 中的路径 |
Feedback Analysis 的三个 ArtifactContract 分别定义:
Feedback Analysis JSON
- 必需文件。
- 包含
items和failed_batches。 - sentiment 使用四类枚举。
- severity 使用四类枚举。
items.feedback_id需要回溯到 Evidence Index。
Product Backlog JSON
- 必需文件。
- 包含
items。 - priority 使用
P0–P3。 items.evidence_feedback_ids需要回溯。
Insight Report Markdown
- 必需文件。
- audience 为 user。
- 包含七个规定标题。
ArtifactContract 同时服务验证、Manifest 和前端元数据,避免三处分别维护产物规则。
Stop Hook 负责最后一道质量门
Runtime 初始化时,register_builtin_hooks() 会根据 ArtifactContract 自动注册 Stop Validators。
模型循环结束后,HookManager 触发 Stop 事件。
Stop 属于 Blocking Hook。任意 Validator 返回 blocked,最终 Run 会进入 failed。
与 PreToolUse 不同,Stop 会执行全部 Validator,再汇总失败原因。这样一次 Run 可以同时暴露缺失文件、JSON 枚举和证据引用问题。
当前主要有四类 Validator。
第一道门:必需文件是否存在
RequiredOutputValidationHook 检查每个 required artifact 的真实路径。
如果模型只创建了两个 JSON,报告缺失,Hook 会记录:
missing required files: artifacts/insight_report.md
Plan 的报告步骤也会因为 artifact success criteria 未满足而保留 failed 状态。
这一层解决的是最基础的交付完整性。
模型在 final answer 中写“报告已生成”只能结束循环,Runtime 会继续检查工作区中的真实文件。
第二道门:JSON 字段和枚举是否正确
JsonOutputValidationHook 会读取 ArtifactContract 中的 schema。
当前项目使用轻量规则:
{
"required_fields": ["items", "failed_batches"],
"enum_fields": {
"items.sentiment": ["positive", "neutral", "negative", "mixed"],
"items.severity": ["low", "medium", "high", "critical"]
}
}
Validator 会检查:
- 文件能否解析为 JSON。
- 顶层必需字段是否存在。
- 指定路径中的枚举值是否位于允许集合。
例如:
{
"priority": "urgent"
}
Backlog Validator 会返回 invalid priority,因为业务契约只接受 P0、P1、P2 和 P3。
当前规则聚焦最关键结构,后续可以升级为完整 JSON Schema 或 Pydantic 产物模型。
第三道门:Markdown 结构是否完整
MarkdownSectionValidationHook 检查报告是否包含规定标题。
Feedback Analysis 报告需要:
# FeedbackLens Insight Report
## Product Context
## Executive Summary
## Top Pain Points
## Evidence
## Recommended Actions
## Risks And Unknowns
这些标题对应产品负责人阅读报告时最关心的结构:背景、摘要、痛点、证据、行动和风险。
模型遗漏 ## Risks And Unknowns 时,报告仍然可读,交付契约却缺少风险说明。Stop Hook 会把这次 Run 标记为 failed。
当前实现使用字符串包含检查,适合固定标题契约。更复杂的文档结构可以在后续接入 Markdown AST。
第四道门:证据是否来自原始 CSV
前三道门检查格式和结构,Evidence Validation 检查事实来源。
Feedback Analysis 的业务要求是:
- 每条分析引用真实 feedback_id。
- 每个 Backlog Item 引用真实证据 ID。
- analysis 中的 evidence_text 来自对应反馈原文。
只检查两个产物是否互相一致还不够。它们可能共同引用一个模型虚构的 ID。
因此 RunLens 在读取 CSV 时建立独立 Evidence Index。
Evidence Index 怎样建立回溯关系
read_feedback_csv 完成读取和列校验后,会写入:
runtime/evidence_index.json
结构大致是:
{
"source": "sample_feedback.csv",
"source_hash": "...",
"items": {
"fb_001": {
"row_hash": "...",
"text": "导出周报太慢了……"
}
}
}
Source Hash
对整份 CSV 原始字节计算 SHA-256,记录本次运行使用的源文件版本。
Row Hash
每条反馈先规范化为排序后的 JSON,再计算 SHA-256。它可以标识某个 feedback_id 对应的完整行内容。
Original Text
保存原始反馈文本,用于验证 evidence_text。
Evidence Index 由确定性工具创建,Stop Hook 读取它完成最终回查。
自洽的虚构证据为什么仍然失败
假设模型生成:
// feedback_analysis.json
{
"items": [
{
"feedback_id": "fb_999",
"pain_point": "导出速度慢"
}
],
"failed_batches": []
}
Backlog 同时引用:
{
"evidence_feedback_ids": ["fb_999"]
}
两个文件内部关系完全一致。EvidenceCitationValidationHook 读取 Evidence Index 后,会发现 fb_999 查无对应源行。
验证路径是:
Stop
→ 读取 evidence_index.json
→ 收集 analysis 和 backlog 引用 ID
→ 对照真实 ID 集合
→ missing evidence ids: fb_999
→ Hook blocked
→ Run failed
这种检查聚焦来源真实性,文件内部一致性只覆盖其中一部分。
ID 真实,原文片段也要匹配
模型可能引用真实 fb_001,同时写入一段更顺畅的概括:
每周导出报告需要等待很长时间,影响团队协作效率。
源文本可能是:
导出周报太慢了,我们团队每周五都要导出,等三分钟很影响效率。
RunLens 要求 evidence_text 是源文本中的非空片段。
如果模型写的是改写句,Evidence Validation 会记录 text mismatch。
这种规则让“分析结论”和“原始证据引用”保持分离:
- pain_point 和 suggested_action 可以归纳。
- evidence_text 保留可直接核对的源片段。
验证失败后 Run 会发生什么
Stop Hook blocked 后,Runtime 会:
- 把最终 status 改为 failed。
- 写入 error_message。
- 将相关 Plan Step 标记为 failed。
- 发布 hook.blocked。
- 发布 artifact.rejected 或 artifact.validated。
- 发布 run.failed。
- 聚合失败 Metrics。
已经生成的文件会保留在工作区。开发者可以直接查看错误内容,前端也能通过 Plan 和 Events 确认失败发生在最终验证阶段。
Artifact 事件当前带有一部分路径匹配逻辑。跨产物证据错误有时仍会让已存在 Artifact 显示 validated,因此最终可交付性以 Run Status 和 Stop Hook 结果为准。
Prompt 和验证共同组成质量边界
Feedback Analysis 的 Evidence 要求同时出现在:
- Skill 指令。
- Business Prompt Fragments。
- ArtifactContract evidence fields。
- Evidence Index。
- Stop Validation。
这些位置分工明确:
| 层次 | 作用 |
|---|---|
| Skill | 提供正确任务方法 |
| Prompt | 让模型知道输出要求 |
| Tool | 创建真实证据索引和文件 |
| Contract | 声明可交付结构 |
| Stop Hook | 执行最终确定性检查 |
模型在生成阶段拥有清楚指导,Runtime 在交付阶段拥有独立判断。
当前校验还可以怎样增强
这一版已经覆盖文件、关键字段、枚举、标题和源证据。后续可以继续增加:
- 完整 JSON Schema。
- Pydantic 产物模型。
- Markdown 标题顺序和唯一性。
- Backlog acceptance criteria 和 metric 的字段约束。
- Source Hash 与外部数据版本管理。
- 产物签名和审核状态。
- 业务 Validator 插件接口。
增强方向仍然围绕同一目标:让 completed 表达真实交付条件。
小结
RunLens 使用 ArtifactContract 定义产物,Stop Hook 执行最终质量门,Evidence Index 把模型引用回溯到原始 CSV。
文件存在、JSON 结构、Markdown 章节和 Evidence 来源共同决定 Run 能否 completed。模型可以完成内容生成,Runtime 负责确认这些内容达到了业务交付条件。
下一篇继续看验证结果怎样进入运行证据:Events、Trace、Metrics 和 Manifest 如何把一次 Run 的因果链展示出来。