尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Maka Runtime Resume Phase 0 崩溃契约:基于已提交 RuntimeEvent 前缀的确定性回放安全

Maka Runtime Resume Phase 0 崩溃契约:基于已提交 RuntimeEvent 前缀的确定性回放安全 Maka Runtime Resume Phase 0 崩溃契约基于已提交 RuntimeEvent 前缀的确定性回放安全【免费下载链接】makaApache Maka (Incubating) is a high-performance agent workspace that keeps a complete record of everything it did.项目地址: https://gitcode.com/GitHub_Trending/mak/makaPhase 0 是 MakaApache Maka, Incubating崩溃恢复体系的第一道闸门它只回答一个问题——当进程在任意时刻被杀死后仅凭已经完整落盘的RuntimeEvent前缀系统能否安全地把这段历史重放给模型。本文以 docs/architecture/runtime-resume-phase0-crash-contract.md 为骨架结合 packages/runtime/src/runtime-resume.ts 与 packages/runtime/src/tests/runtime-resume-crash.test.ts 的源码实现完整解析 P0–P11 稳定故障注入点、四条已提交前缀的判定规则、真实子进程 SIGKILL 测试方法论以及 Phase 0 明确不承诺的能力边界。读完本文你将掌握 Maka 如何在崩溃后工具副作用状态未知这一最危险场景下做到确定性、可测试、fail-closed 的恢复决策。为什么需要 Phase 0崩溃后缺失结果至少有四种解释当一个 Agent 正在调用工具例如通过Bash执行touch marker时进程崩溃重启后系统面对一个缺失的工具结果至少有四种互斥的解释工具从未启动工具启动了但没有写入任何东西副作用已经完成文件已写入但结果事务未提交文件被写入后又被人或其他进程改掉了。盲目重试会重复第 3 种情况下的副作用盲目宣布成功则会给模型一个在第 1、2、4 种情况下完全虚假的历史。因此恢复必须基于不可变的事实而非猜测。Phase 0 的全部工作就是只读取已提交的RuntimeEvent前缀把它投影成ToolOperation再产出一个ResumePlan——要么safe_replay要么blocked。与完整恢复体系的关系Phase 0 不恢复执行、不调和工具副作用、也不引入未来的 SQLite 工具日志tool journal。这些属于后续阶段见 docs/architecture/runtime-resume-architecture.md 中 Phase 0–4 的阶段划分。生产 API一条纯函数链路Phase 0 的生产 API 是纯的pure即同样的输入永远得到同样的输出且投影过程不修改任何持久化数据committed RuntimeEvent prefix - ToolOperation projection - ResumePlan - safe_replay or blocked这条链路在源码中的落点非常清晰projectToolOperationsFromRuntimeEvents(events)先将事件交给resolveRuntimeRecovery得到恢复决策再投影出ToolOperation[]buildResumePlanFromRuntimeEvents(events, options)聚合投影、诊断、拒绝原因最终计算出disposition: safe_replay | blocked见 packages/runtime/src/runtime-resume.ts决策的底层依据来自RecoveryResolverresolveRuntimeRecovery见 packages/runtime/src/recovery-resolver.ts它把RuntimeEvent前缀解释为completed / parked / definitely_not_dispatched / indeterminate / corruption五类工具状态。ResumePlan的关键字段源码中定义于 packages/runtime/src/runtime-resume.ts字段含义dispositionsafe_replay或blockedoperations每个工具调用的投影结果succeeded/failed/indeterminate/not_dispatched/parked/corruptiondiagnostics人类可读的诊断码与消息rejectionReasons机器可读的拒绝原因如dangling_tool_state、runtime_offset_mismatchrequiresVerification是否存在未解决的工具副作用需要人工核验sourceRuntimeEventHighWater该计划覆盖的不可变日志水位replayRuntimeEvents重放给 provider 的合法事件子集稳定故障注入点P0–P11 目录RUNTIME_RESUME_FAILPOINTS是机器可读的权威事实来源其 TypeScript 常量定义于 packages/runtime/src/runtime-resume.ts。其中committedPrefix列表示崩溃后最后一个完整提交的RuntimeEvent前缀。它刻意不假装未来的 T1/T2 日志已经存在——崩溃发生在哪个阶段就只承认哪个阶段的事实。ID注入边界最后完整提交的 RuntimeEvent 前缀P0工具准备T1之前before_function_callP1function_call 已提交prepared journal 未提交after_function_callP2prepared journal 已提交实现未开始after_function_callP3工具实现进行中after_function_callP4副作用完成outcome 事务T2未提交after_function_callP5function_response 已提交outcome journal 未提交after_function_responseP6outcome 已提交结果未送达模型after_function_responseP7结果已送达下一步 provider 调用未开始after_function_responseP8terminal RuntimeEvent 提交after_function_responseP9terminal run-header 提交after_terminal_eventP10恢复决策提交after_terminal_eventP11continuation-run 创建after_terminal_event关于 P8 需要特别注意Phase 0 只对 terminal append之前的前缀做推理terminal 之后的合法前缀由 P9 表示。一条撕裂torn的 JSON 行属于存储损坏storage corruption不是合法的已提交前缀绝不能把它升级为恢复事实——这正是fail-closed的第一道体现。测试中对该目录的稳定性有专门断言runtime-resume.test.ts验证RUNTIME_RESUME_FAILPOINTS恰好包含 P0–P11 十二个 ID且去重后的 committedPrefix 恰好是before_function_call、after_function_call、after_function_response、after_terminal_event四种见 packages/runtime/src/tests/runtime-resume.test.ts。必选决策四种前缀如何判定Phase 0 对每种已提交前缀给出确定性的判定结果前缀期望结果before_function_callsafe_replay不存在任何工具操作after_function_callblocked操作状态为indeterminate拒绝原因为dangling_tool_state未解决的调用不出现在 provider 重放历史中after_function_responsesafe_replay操作状态为succeeded或failed调用与响应在 provider 重放中保持配对after_terminal_event工具判定与前缀相同terminal 事实保留在 canonical ledger 中此外若重新打开的已提交前缀与期望的 RuntimeEvent 高水位high-water不一致一律以runtime_offset_mismatch拒绝。源码中collectResumeDiagnostics会在expectedRuntimeEventHighWater ! events.length时产出该诊断见 packages/runtime/src/runtime-resume.ts。源码视角这些决策是如何算出来的buildResumePlanFromRuntimeEvents的判定逻辑见 packages/runtime/src/runtime-resume.ts可以概括为disposition safe_replay 当且仅当 rejectionReasons 为空 且 无 requiresVerification没有 indeterminate 操作 且 无 recovery.hasCorruption 否则 blocked拒绝原因dangling_tool_state由deriveRejectionReasons统一归并见 packages/runtime/src/runtime-resume.ts以下任何诊断都会映射到它——pending_tool_resultfunction_call 无匹配的已提交 function_response、tool_not_dispatched、tool_recovery_parked、tool_recovery_corruption、tool_ledger_corruption、duplicate_event_id、semantic_lane_conflict、protocol_marker_invalid、unmatched_tool_result、tool_name_mismatch。也就是说悬空工具状态不是单一情形而是一整类不确定状态的共同落点任何一类出现都会让重放被阻断。provider 重放历史如何构建buildResumeReplayRuntimeEvents见 packages/runtime/src/runtime-resume.ts按三条规则裁剪重放事件丢弃partial事件流式中间态丢弃modelVisibility hidden的事件如 T1 dispatch 等系统内部事实只保留已配对的function_call与function_response——未解决的调用绝不会被喂回 provider。这与契约表完全一致after_function_call前缀重放时只包含 user 事件调用被排除after_function_response前缀重放时 user/call/response 三者保持配对。进程级测试 Harness真实 SIGKILL 下的语义验证Phase 0 的崩溃测试必须使用真实文件后端的RuntimeEventStorecreateWorkspaceRuntimeStore而不是内存 mock。契约规定的九个步骤在 packages/runtime/src/tests/runtime-resume-crash.test.ts 中被完整实现创建临时工作区mkdtemp启动一个子 Node.js 进程spawn(process.execPath, ...)以环境变量MAKA_RUNTIME_RESUME_CRASH_CHILD1进入崩溃子进程模式通过RuntimeEventStore.appendRuntimeEvent写入该 failpoint 的完整前缀只有当所有 append promise resolve 之后子进程才向 stdout 输出READY通知父进程父进程用SIGKILL终止子进程Windows 下经terminateChildProcessTree处理进程树断言finally清理标记文件child-finally-ran未被写入——这证明 kill 发生在追加全部完成之后、任何清理之前正是已提交前缀的精确位置用新的RuntimeEventStore实例重新打开工作区读回事件并断言与提交前缀逐 ID 一致对重开的前缀投影两次要求两次的ResumePlan深度相等assert.deepEqual(second, first)验证确定性再次读取 ledger断言投影没有改动持久化数据assert.deepEqual(await reopened.readRuntimeEvents(...), recoveredEvents)。该 harness 在 Windows、macOS、Linux 三个平台上覆盖全部十二个稳定 failpoint ID。它验证的是进程崩溃恢复语义而不是断电持久性或文件系统fsync保证——后者需要单独的硬件与文件系统层测试。针对每种前缀assertResumePlanForPrefix见 packages/runtime/src/tests/runtime-resume-crash.test.ts还做了行为断言after_function_calldisposition blocked、操作status indeterminate、rejectionReasons [dangling_tool_state]、重放事件仅[user]before_function_callsafe_replay、无操作after_function_response/after_terminal_eventsafe_replay、操作status succeeded。Phase 边界Phase 0 不做什么Phase 0不改变任何工具执行行为。以下能力明确超出范围自动续跑automatic continuation工作区恢复workspace restorationT1/T2 事务化工具边界副作用对账side-effect reconciliation幂等工具重执行以 SQLite 作为 canonical 的 RuntimeEvent 与工具日志存储。这些能力依赖后续阶段。Phase 0 的定位是仅基于当前可得证据让恢复决策变得确定且 fail-closed。也就是说它在证据不足与证据充分之间的任何模糊地带一律选择阻断blocked/park而不是猜测应该没事。与后续阶段的关系从 docs/architecture/runtime-resume-architecture.md 可以看到Phase 0 是五阶段恢复路线的第一环Phase 0 解释已提交历史 → Phase 1 在完整安全边界上创建新执行RuntimeContinuationPlanner→ Phase 2 用 SQLite 的 T1/T2 收窄副作用窗口 → Phase 3A 原子化提交恢复事实 → 后续 Phase 3/4 做工具级证据与工作区检查点。Phase 2 不会取代 Phase 0/1它只是给这些闸门提供更精确的是否跨过工具派发边界的证据。相关延伸资料Runtime Resume 总体架构Phase 1 安全边界契约RecoveryResolver ADRRecoveryResolver 实现Phase 0 单元与契约测试Phase 0 进程崩溃 harness 测试小结Phase 0 一句话契约Phase 0 的价值不在于崩溃后能自动继续而在于让恢复决策本身变得可证明、可测试、可复现只承认完整提交的RuntimeEvent前缀撕裂行永远不算数只有四种合法前缀每种前缀的ResumePlan结果完全确定任何悬空工具状态一律blocked并给出稳定的机器可读原因dangling_tool_state等投影是纯函数重复投影结果一致且绝不改写持久化 ledger用真实子进程 SIGKILL 文件后端 store 在三大平台验证语义且明确不把进程崩溃与断电持久性混为一谈。这是整个 Maka 恢复体系fail-closed的基石先证明安全才允许重放。【免费下载链接】makaApache Maka (Incubating) is a high-performance agent workspace that keeps a complete record of everything it did.项目地址: https://gitcode.com/GitHub_Trending/mak/maka创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表