Suspension / Resume / Continuation 审查
基线状态:Historical fixed-target dossier。 本文按
b6458b41...审查 suspension/resume owner;本科生 guide 当前 target 为94fab78...,当前导航见implementation/source-map.md。
1. 范围与基线
- Current / 本单范围:只审
suspension、resume、continuation的 source owners 与直接 tests;不审 workspace、COW 全链、benchmark 或 campaign。 - Current / 固定基线:
b6458b41f0fa32085fdd4cad0a528d98602569d2。 - 基线校验:该 commit object记录的tree是
5e8154fc26527181c66e612584d79dd4e620649d,以下按该精确对象审查。 - 历史审查关系:较早的综合审查使用
b94c989.../6b8bb6...;本单明确审查后续最小修复后的当前实现。 - Status vocabulary:
Current/Observed是该 pin 的代码或测试事实;Historical/Deferred/Unsupported不升级为实现承诺;Framing只表示解释模型。
2. 何时允许“暂停”
| 边界 | Current 触发条件 | 继续方式 |
|---|---|---|
| Approval suspension | Current:Plan 的 capability 带 ApprovalLease;lease >0 且 ≤24h、PlaybackLiveOnly、无 PreDispatch;Broker 同时有 ApprovalSuspension 与 Controller | 同一个 Guest 的 pending ABI call 被放行或拒绝 |
| Workflow wait | Current / bounded:合法 Graph 必须有恰好一个 Wait 和一个 Terminal;Start 执行到 Wait 即生成 Suspended State | Resume 校验 State 后新建 Guest,继续 Wait 之后的节点 |
| Cold I/O continuation | Current / Experimental:Host 选择 ColdIOContinuation,且机制依赖 PreparedRuntime + MemoryCOW 满足;Cold/PageOut 阈值位于 Run timeout 内 | 同一 module/slot 的 Host call 返回;可在等待期间 MADV_COLD/MADV_PAGEOUT |
| 普通 cancel/timeout | context.Done() 到达但没有上述协议 | Abort,不是可恢复 suspend;本 pin 没有通用 resume token |
3. Approval suspension:同一执行的热等待
- Source owner:
runtime/approval/controller.go:Authorize, resolve, BeginDispatch, Complete, AbortApproved;runtime/capability/broker.go:NewBroker, call, completeApproval。 - 数据路径:Guest ABI
hostCall(runtime/engine/wazero/engine.go:1220-1257)先从 Guest linear memory 复制 request;Broker 校验 call identity、Plan、schema,再调用Controller.Authorize。 Authorize建立RequestID、RunID/PlanSHA256/CallID/ParentCallID/Capability、参数 SHA-256、CreatedAt/ExpiresAt;只存 digest,不存 arguments body。Authorize等待Approve、Reject、lease timer 或ctx.Done();Broker 将 reject/expiry/cancel 映射为 denied response,handler 尚未调用。- Dispatch gate:
BeginDispatch在 mutex 内同时检查 status、lease 和ctx.Err();成功写入DispatchCommittedAt,这是 handler 可以开始的线性化点。 - commit 之前取消/过期:不执行、不能补发;
AbortApproved只接受精确的cancelled_before_dispatch,并使后续Complete失败。 - commit 之后取消:不产生重放授权;handler 的真实结果仍须经
Complete(ok|error|ambiguous)审计,审计失败返回 ambiguous,而不是假装未执行。 - Terminal semantics:决定终结后 status 不再可改;成功路径是
StatusApproved + DispatchCommittedAt + Executed + CompletedAt,不是另一个terminalstatus。 - Token semantics:
Permit{RequestID}是审计关联句柄,不是新 capability grant、bearer token 或可跨进程恢复的 continuation token。
4. Workflow resume:显式逻辑状态 + fresh Guest
- Source owner:
runtime/workflow/evaluator.go:Graph.Validate, State.Validate, Start, Resume, evaluate, refreshObservations。 Start建立StateSchemaVersion=v2:Graph digest、ContinuationInput(必须 canonical JSON)、nodeRecords、WaitNodeID、immutable roots、AuthorityEnvelope;到 Wait 后finalize。evaluate的 defer 一定Guest.Close;因此第一次到 Wait 的 Guest 被销毁,State 不含 frame、heap、globals、file descriptor 或 WASM memory。Resume只接受ResumeEnabled、合法且Suspended的 State、匹配 Workflow/Graph/roots、非空 WaitNodeID;随后检查当前 evaluator 的 authority 可用性及 privacy partition。- authority 可变时,
invalidateAuthorityDependent删除 observation 及其传递后代;refreshObservations只刷新明确标记RefreshOnResume的 observation。 - Resume 的
evaluate每次都newExecutionIdentity,并通过Guests.NewGuest(ctx)创建新 Guest;未失效记录走 lookup,失效或被Evict的记录才 recompute。 - 回答“resume 是否 fresh”:是,Guest/execution fresh;不是从 Python/WASM hidden continuation 恢复,而是用显式记录重建后续计算。
- State 有
Completeddisposition;Completed State 不能再次 Resume。Suspended State 没有 consumed/one-shot 标记,调用方仍需自行防止重复 Resume。 - Expiry/cancel:AuthorityEnvelope 有
NotAfterUnixMS/Revoked,Resume 阻断于新 Guest 创建前;没有持久 cancel 字段,当前context取消只中止这次 evaluation。
5. Cold I/O continuation:同一 slot 的内存降温
- Source owner:
runtime/engine/wazero/cold_io.go:ColdIOEvidence, coldIOContinuation;Linux 实现为cold_io_linux.go:newColdIOContinuation, wait, advise, resume, finish。 engine.go:1023-1025将 continuation 放进当前 run context;hostCall发现它后,以复制过的 request 调continuation.wait(ctx, call)。wait将状态置为 Waiting;ColdAfter 后尝试MADV_COLD,可选 PageOutAfter 后尝试MADV_PAGEOUT;handler 返回或 cancel 时resume并回到 Running。- Current boundary:这里保留的是当前 module/slot 的 Guest memory 与执行调用关系,不是新 Guest,也不是序列化 State;page advice 失败只进入 bounded evidence blocker。
- context cancel 会立即返回
ctx.Err();注释明确 late Host result 被丢弃,不能 resume/replay 本次 execution,但不能声称能撤销一个无视 cancel 的外部副作用。 finish把 evidence 置为ColdIOTerminal;ColdIOEvidence.Validate约束 waits、attempts、successes、resumes、advised bytes 与 blocker 集合的计数关系。- Freshness 对照:直接测试还验证 fresh mapping 不泄漏 parked slot 的 dirty state;这只证明该 continuation 的 private boundary,不展开 COW/workspace 实现链。
6. Host / Guest 边界
- Host-owned:Run timeout、MechanismSet、ColdIOPolicy、Plan/Grant/handler、approval Controller 与时钟、AuthorityEnvelope、Graph/GuestFactory、State 持久化载体、dispatch/terminal evidence。
- Guest-owned:热 approval 时的 Python/WASM frames、locals、heap、linear memory;cold wait 时当前 module 的 private memory;workflow 节点的 Compute/Observe 代码只产生值,不产生 authority。
- Shared contract:canonical JSON request/response、CallID/Plan digest、workflow Record 的 value+digest、Freshness/Policy digest、WaitNodeID 与显式 continuation input。
- Private/non-shared:approval audit 只保存参数 digest;cold continuation 绑定当前 slot/context;workflow State 是显式数据,不等于可被别的 Run 直接复用的 interpreter 对象。
- Broker 代码注释明确:Guest 只能提交 JSON arguments,authority/schema selection 留在 Host;approval waiting 本身不扩大 capability authority。
7. Continuation、checkpoint 与 token 的区别
| 名称 | Current 语义 | 不应声称 |
|---|---|---|
| Approval suspension | pending ABI call + Host lease/decision;热等待后同一 Guest 返回 | durable continuation、跨进程恢复、自动重放 |
| Workflow State | 可 canonicalize 的逻辑 progress record;销毁 Guest 后 fresh re-evaluation | Python heap/frame checkpoint |
| ColdIOContinuation | 当前 slot 的内存 tiering + 同一次 Host call resume | dirty-page checkpoint、完整执行栈保存 |
| Checkpoint/restore | 本 pin 没有通用 Guest heap/stack restore owner | 可任意恢复 arbitrary Python |
| RequestID/Permit | body-safe audit correlation | capability token 或恢复凭证 |
8. 直接测试与证据
runtime/approval/controller_test.go:exactly-once、body-safe audit、lease 过期、dispatch gate cancel、AbortApproved、capacity fail-closed、late decision。runtime/capability/approval_test.go:approval 前 handler 调用数为 0;approve 后为 1;reject/expiry/cancel 均不 dispatch;receipt 与 approval/Plan identity 绑定。runtime/workflow/evaluator_test.go:TestWaitDestroysGuestAndResumeUsesFreshGuestWithLocalLookup、authority invalidation、Evict recompute、ResumeDisabled、expiry/revocation/privacy/tamper 在建 Guest 前失败。runtime/engine/wazero/cold_io_linux_test.go:same-slot cold/pageout、private dirty state、cancel 后 state 保持、late result 不作为 replay;cold_io_test.go校验证据计数拒绝矛盾值。runtime/mechanisms_test.go与runtime/cold_io_policy_test.go:默认全 off、依赖 fail-closed、Host policy 必须显式且阈值有界;integration/e2e/composable_test.go另观察真实 Guest cold marker 保持与 fresh run clean。- Observed / 执行纪律:本审查只读列举 pinned tests 与可机读 evidence schema;未运行测试,也未跑 campaign,不能把测试源码当成本轮运行结果。
9. Trade-off、Deferred 与 non-claims
- Trade-off:hot approval 保留 Guest,低恢复成本但占用内存;workflow fresh resume 释放 hidden state、边界清楚但要新建 Guest/lookup/recompute;cold tier 释放部分驻留页但依赖平台 advice,可能失败且有 fault latency。
- Rejected/Deferred:dirty-page checkpoint/restore、任意 Python frame/heap snapshot、跨进程或 crash-safe hot continuation、indefinite retention、通用多 Wait DAG scheduler,均不由本 pin 建立。
docs/research/approval-continuation-and-programmatic-tool-calling.md中“cold continuation proposed”属于 Historical/Deferred framing;本 pin 的cold_io_*source/test 只实现选定的 cold-I/O 同 slot 机制,不兑现该文的完整 approval continuation tier。docs/wait-suspension-and-reuse-tradeoffs.md的历史测量、吞吐/延迟比例不是本审查的 Current 运行结果;没有生产级 latency 或 arbitrary Python 支持结论。- Unsupported:通用网络断线恢复、把 State 当签名 token、把参数 digest 当外部世界真相、把 cancel 当副作用回滚,均不可从这些 owners/tests 推出。
10. 答辩一句话
Pysolate 只有在明确的 approval、Wait 或 cold-I/O 边界暂停:approval/cold 保留同一次受约束的 Guest call,workflow resume 则销毁旧 Guest、用显式且受 authority 校验的 State 创建 fresh Guest;它没有把任意 Python 执行栈伪装成 checkpoint 或 durable token。