# Application Reference Example 验收合同 > **受众**:业务应用团队与框架团队 > > **状态**:`[TARGET / CONTRACT]`,M1 只定义场景、目录和验收;本阶段不创建可运行代码 > > **未来位置**:`examples/application_reference/` ## 1. 为什么需要这个 example Application API 只有经过一条真实、跨停止恢复的业务链路验证,才能证明业务无需修改框架内核。这个 example 是 M2/M3 的 walking skeleton 和接入合规测试载体,不是脚本构建第三版,也不追求完整创作产品体验。 它选择一个“证据驱动的创作任务”,因为该场景同时需要: - 先验证事实,再产生表达,能检验 Context 和 Artifact 的分层。 - 同时保留两个候选,能检验归属、血缘和采用。 - 用确定性规则发现局部产物问题,能检验 Validator 的局部回退。 - 经父级审核决定下一步,能检验 ValidationResult 与 TaskReview 的权威边界。 - 停止、重启和回溯,能检验应用身份和版本化状态是否完整恢复。 本文依赖的业务接口仍是未实现草案,见 [Application API 0.1](./application-api-0.1-draft.md)。框架状态与业务边界见 [M1 设计基线](./application-framework-m1.md)。 ## 2. 场景定义 ### 2.1 输入 根目标收到一个主题和一组已登记资料,要求形成一份完整、可发布的短内容。输入固定包含: - 一个需要核实的事实概念。 - 两份可授权的来源资料,其中一份只允许事实核实 Task 使用。 - 一条创作要求:正文必须基于已验证 Finding,不能保留占位描述。 - 一条资源约束:只允许一个事实子 Task 和最多两个表达候选。 示例不使用脚本段落、账号人设、Pattern、脚本元素或 SQL branch。未来脚本构建应用可以替换这里的业务对象,但不能把这些概念加入框架公共模型。 ### 2.2 角色 | 角色 | 业务职责 | 框架约束 | |---|---|---| | `editor` | 持有根目标,委派事实核实,比较候选并提交最终内容 | 只能创建 `fact_checker` 和 `writer`;不能伪造验证结果 | | `fact_checker` | 提问、读取获授权资料、形成 Finding 和假设 | 只读资料工具;不能创建候选或写最终内容 | | `writer` | 使用已验证 Finding 生成两个候选表达 | 不能读取未转授的原始事实资料;候选必须进入 Repository | 角色名和提示词属于 example。框架只识别应用内角色身份、允许的子角色关系、工具能力和资源限制。 ### 2.3 可替换应用组件 example 必须分别实现并允许在测试中替换: - `TaskContextProvider`:枚举两份来源资料及其版本、hash、继承和授权元数据。 - 事实核实工具:读取当前 Task 已获授权的资料并产出 ArtifactRef。 - `ArtifactResolver`:按精确版本可信读取事实 Finding 和候选正文。 - `CandidateRepository`:保存候选内容、fork、修订、归属和采用写回。 - `QualityCheckProvider`:提供“正文不得含占位描述”的确定性规则。 - `RunEventProjector`:把 Task、候选、验证和采用事件投影到测试业务视图。 测试替身只能替换 Provider/工具实现,不得替换 Runner、TaskProtocol、TraceStore、Validator 或 ResourceBudgetController。 ## 3. 端到端流程 ### 步骤 1:创建根目标 `[M3A]` 业务入口使用固定 ApplicationRef 创建新 Run。框架解析 `editor` 根角色,固化应用版本、config hash、角色 hash、工具、质量规则和 RunLimits,并创建 RootTaskAnchor。 验收证据:Trace 的恢复合同能指出精确应用版本;根目标和根约束不可被子角色改写。 ### 步骤 2:事实核实子 Task `[M2 + M3A]` `editor` 委派一个 `fact_checker` Task。该 Task 通过框架命令记录: - 一个待回答 `Question`。 - 资料之间的一个 `Finding`,带 ContextRef/ArtifactRef。 - 一个仍待确认的 `Hypothesis` 或明确说明没有未决假设。 - 简短判断依据,不保存模型原始思维链。 TaskContextProvider 只枚举资料;框架决定授权,并阻止该 Task 读取另一个 root 或兄弟 Task 的引用。 验收证据:TaskProgress 绑定当前 TaskBrief revision;事实报告经 Validator 和父级 TaskReview 接受后形成可复用证据,不靠自由文本暗示“已验证”。 ### 步骤 3:生成两个候选 `[M2 + M3B]` `editor` 把已验证 Finding 转授给 `writer`,但不必重新转授原始事实资料。`writer` 生成候选 A 和候选 B: - 两者都保存为不可变内容版本,并获得 ArtifactRef 和 CandidateRef。 - CandidateRef 记录 application/root/trace/task 归属和血缘。 - 候选 A 内容完整;候选 B 故意包含 `{待补充事实}` 占位描述。 验收证据:两个 CandidateRef 均属于 writer Task;只凭候选 ID 不能从另一应用或另一 root 读取内容。 ### 步骤 4:确定性检查发现局部问题 `[M3A + M3B]` QualityCheckProvider 声明稳定、版本化的占位描述检查。框架把它编译进 ValidationPlan:候选 A 通过,候选 B 的 output scope 失败,结果仍覆盖该 scope 计划内的全部 check_id。 验收证据:规则 Provider 不直接写 ValidationResult、TaskProgress 或候选阶段;规则 ID/版本和解析配置已经进入本 Run 的恢复合同。 ### 步骤 5:只退回候选产物层 `[M2 + M3B]` Validator 对候选 B 给出 output/candidate 层的回退建议,不让 `fact_checker` 重新检索已经通过的事实。父级 TaskReview 决定让 `writer` 从 B fork 修订版 B2,或放弃 B。 验收证据:已接受的 Finding、事实 Artifact 和事实 TaskReport 保持原版本;只新增候选修订和对应验证历史,不覆盖旧 B。 ### 步骤 6:父级采用或继续修订 `[M2 + M3B]` `editor` 比较已通过的 A 与修订后的 B2,通过 TaskReview 选择: - 采用一个候选并返回根目标重新判断;或 - 要求 writer 继续修订;或 - 在根约束无法满足时失败上行。 只有采用动作可以调用 CandidateRepository 的幂等业务写回。ValidationResult 只表示验收,不能替父级选择候选。 验收证据:最终内容引用被采用的精确 CandidateRef/ArtifactRef;重复投递采用事件或重复写回不会产生两个业务结果。 ### 步骤 7:停止、重启和回溯 `[M2 + M3A + M3B]` 测试在三个位置执行恢复:事实 Task 完成后停止、人工确认等待期间重启、候选 B 失败后回溯。恢复后必须保持: - 相同 ApplicationRef、角色 hash、工具、规则和 RunLimits。 - 相同 TaskBrief/TaskProgress 历史和 sequence head。 - 相同 Context/Artifact 授权,不扩大跨 Task 访问。 - 相同候选内容、归属、血缘和验证结果。 - 相同业务投影 cursor;事件重放不产生重复数据。 应用版本缺失或 config hash 被修改时,恢复必须失败关闭,不能采用当前默认配置继续。 ## 4. 未来目录合同 M1 **不会**创建以下目录。M2/M3 实现期间按能力逐步增加,目录名称可在实现评审时小幅调整,但职责不能混合: ```text examples/application_reference/ ├── README.md # 运行方式、场景和里程碑状态 ├── application.py # AgentApplication 声明,不包含 Runner 分叉 ├── roles/ │ ├── editor.prompt │ ├── fact_checker.prompt │ └── writer.prompt ├── skills/ # example 专属业务技能 ├── tools/ │ ├── verify_fact.py # 事实核实工具 │ └── propose_candidates.py # 候选生成工具 ├── providers/ │ ├── context.py # TaskContextProvider │ ├── artifacts.py # ArtifactResolver │ ├── candidates.py # CandidateRepository │ ├── quality.py # QualityCheckProvider │ └── projector.py # RunEventProjector ├── fixtures/ # 小型、确定、无外网依赖的业务资料 └── tests/ ├── test_happy_path.py ├── test_context_authorization.py ├── test_candidate_ownership.py ├── test_local_retry.py ├── test_application_restore.py └── test_event_projection.py ``` `application.py` 只装配公共应用描述和 Provider,不创建自定义 loop。测试使用框架公开入口和可替换 Provider,不访问 TraceStore 的内部文件来伪造状态。 ## 5. 里程碑依赖 | 能力/步骤 | M2 | M3A | M3B | M1 后的可运行状态 | |---|---:|---:|---:|---| | Question/Finding/Hypothesis 和 TaskProgress revision | 必需 | | | M2 后可做协议级测试 | | 应用身份、Registry/Binding/Runtime、严格恢复 | | 必需 | | M3A 后可创建应用 Run | | AgentRole、ToolSet、TaskContextProvider | | 必需 | | M3A 后可替换角色、资料和工具 | | ArtifactResolver 应用绑定 | | 必需 | | M3A 后可从应用恢复 Resolver | | QualityCheckProvider 与规则版本固化 | | 必需 | 可随候选联调 | M3A 后可跑单 Artifact 规则 | | CandidateRef 和 CandidateRepository | | | 必需 | M3B 后可完成双候选链路 | | 规范事件和 RunEventProjector cursor | | | 必需 | M3B 后可验证业务投影 | | 完整七步 example | 必需 | 必需 | 必需 | 三个里程碑完成后才可运行 | 因此,任何文档或 README 都不能在 M2/M3B 完成前把此 example 标记为“可运行的应用模板”。 ## 6. 验收用例 ### AR-01 应用隔离 同一进程注册 `application_reference@1` 和一个同名角色/工具但不同应用 ID 的测试应用。两者的角色、工具、Context、Resolver、规则和候选完全隔离;全局 Preset 不参与解析。 ### AR-02 跨 Task Context 越权 writer 尝试读取只授权给 fact_checker 的原始资料,框架拒绝。父级合法转授已经验证的 Finding 后,writer 只能读取该新 ContextRef/ArtifactRef。 ### AR-03 应用恢复 hash 停止并重启进程后,相同应用版本和 hash 能恢复。修改 Prompt、工具 schema、规则版本或 RunLimits 后复用旧版本号,旧 Trace 恢复失败;修改 Provider 凭证但行为配置未变时 hash 不变,凭证缺失则装配失败。 ### AR-04 候选归属与血缘 候选只能由所属 application/root/task 读取或修订。B2 的 parent 指向 B;A 不因 B 的失败而被回退;另一 root 复用 candidate_id 时被拒绝。 ### AR-05 确定性规则完整性 占位规则只让 B 的 output scope 失败,ValidationResult 的 check_id 与计划严格相等。Provider 异常时也产生计划完整的失败关闭结果,不生成计划外 ID。 ### AR-06 局部回退 B 失败后只重新执行 writer 的候选修订,事实 Task 的工具调用次数、Artifact 版本和 ValidationResult 不变。父级 TaskReview 是是否修订的唯一决定来源。 ### AR-07 停止、重启、回溯 在事实完成、工具确认等待和候选失败三个位置分别恢复。应用身份、协议版本、候选、授权和预算一致;回溯形成新历史,不覆盖旧结果。 ### AR-08 事件幂等 Projector 在同一事件上故障并重放,业务视图只出现一个候选版本和一次采用动作。投影停机不改变 Trace 的 completed/failed 状态。 ### AR-09 内核零修改 example 的实现提交不得修改以下目录中的运行时代码: - `cyber_agent/core/runner.py` - `cyber_agent/core/task_protocol.py` - `cyber_agent/trace/store.py` - `cyber_agent/core/validation.py` 若 example 必须修改这些文件才能接入,应先判定为框架通用能力缺口,单独设计和测试,不能把业务特例塞入内核。 ## 7. 验收证据格式 最终 reference example 的 CI 必须输出或保存以下可审计证据: - 测试所用 ApplicationRef 和解析后 config hash。 - 根 Trace、事实 Task、writer Task 的 ID 和父子关系。 - TaskBrief/TaskProgress revision、ValidationResult 和 TaskReview 引用链。 - ContextRef、ArtifactRef、CandidateRef 的归属和内容 hash。 - 局部回退前后的工具调用计数和保留版本。 - Projector 起止 cursor、故障重放次数和最终业务记录数。 证据可由测试 fixture 和结构化断言形成,不要求保存模型原始推理文本,也不应在日志中输出凭证或完整敏感资料。 ## 8. 完成定义 只有同时满足以下条件,reference example 才能从合同升级为“可运行模板”: - 七步业务流程和 AR-01 至 AR-09 全部通过。 - 角色、资料 Provider、工具、候选 Repository 和质量规则可分别替换。 - 停止、进程重启和回溯均不改变应用身份、Task 合同、候选与验收结果。 - 业务代码没有直接修改协议 context、TraceStore 文件或 Validator 结果。 - example 中所有创作概念均留在 example;公共框架仍保持业务无关。 - 业务团队只阅读公开接入文档即可完成一次同类替换实现。 M1 到此只冻结验收问题,不宣称这些能力已经存在。