Repository navigation
Reuse exact Todo context projections within one request - #8106
loopx-agent wants to merge 2 commits into
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
动机 / Motivation
运行任务准入或状态汇总的 CLI 用户和 Agent。同一次命令多次读取相同 Todo 摘要和交接内容时,旧实现反复跨进程计算同一纯投影;新实现只在当前请求内复用完全相同的输入。这里的“投影”是把已有记录转成摘要或交接内容,不是重新读取或修改任务权威。重复跨进程调用会累积传输和计算开销,保留现状会继续付出这部分已经复现的成本。
真实 File、SQLite 普通 CLI 都保持准入结果;相同 18 次投影的完整 JSON 回放一致,实际投影 RPC 从 18 次减至 10 次。不改变任务权威、准入条件、排程或结算,也不证明宿主原生上下文交付、模型采纳或端到端总成本已经改善。必需 mypy 在当前提交新增一处 union-attr 错误;宿主原生上下文传输及实际模型后续行为尚未完成资格验证。因此这是有用且可单独回滚的增量,但当前提交还不能通过必要验证。
改动思路 / Approach
本次评审覆盖原始 base 12803354ab13a003de8620ab496250617224ff37 到 head f99e22236f81d6ba57d9854cd8e709ea1f481eb6 的全部两个文件。既有 CLI dispatcher 打开 request_scope,摘要与交接调用 effect_runtime_result,最终仍由 TypeScript 的 todo.context.page 生成内容。补丁把缓存放进既有 _RequestRuntimeRevision,只保留本次请求里已经成功返回的纯投影字节,不把权威读取或结算结果放进去。
完整参数和 timeout、retry_safe、large_local_snapshot 共同组成键,保留 JSON 顺序、标量类型和有符号零;命中后重新解码,避免调用方修改后污染下一次读取。scope 最后一次退出会清空缓存。编码失败、不同输入、错误返回或超过保留预算时,继续原调用或校验路径。
架构判断是保留这个现有请求 owner:不改动会留下真实重复,逐个摘要/交接调用者去重会分散生命周期规则,全局缓存则增加失效与权威风险。语义仍由 TypeScript 持有,Python 适配器负责 IO 复用,没有第二套任务决策器。当前 PR 的必要修复仅是缓存写入处的显式类型收窄,无需新配置、协议或全局服务。
具体改动 / Changes
没有找到专门为这项瞬时 memoization 接受的书面规格;评审依据是既有 request-scope 生命周期、纯投影 owner、真实调用者和必要仓库检查,不把一般缓存文档或补丁自己的断言改写成新 RFC 验收。两文件共 +120/-1:生产适配器 +43/-1,请求 scope 测试 +77/0,没有生成文件、持久化字段或公开 CLI 选项。
关键代码讲解
_RequestRuntimeRevision复用已有锁和请求计数,在最终leave()时关闭并清空缓存;复制出来的已关闭 context 不能继续命中,独立请求也不共享该缓存。remember_todo_context把键与结果的字节一起计入MAX_REQUEST_BYTES,保留上限是 8 MiB。真实 snapshot RPC 的完整大文本读取验证了超过保留预算时仍返回全部内容,第二次继续实际 RPC。effect_runtime_result只匹配已有精确方法todo.context.page,完整键命中后返回新解码对象;其他方法仍走effect_runtime_request。第 1631 行调用处缺少可被 mypy 确认的state非空收窄,是本次阻塞点。
独立验证
实际运行了隔离的 File、SQLite 普通公开 quota should-run CLI,基线和当前提交共四次,都返回预期任务且 normal_delivery_allowed=true。只在这些新建的普通调用夹具使用 --context-delivery off;源状态字节不变,synthetic spend 为零。每种后端所有非 Todo RPC 的方法计数逐项一致,权威 snapshot 仍实际读取两次。
再取每种基线 CLI 产生的同一组 18 次有序投影输入及完整预期 JSON,在两个不可变提交上通过真实 TypeScript RPC 回放;36 对完整输出全部一致,没有归一化字段或删掉诊断:
| 相同工作负载,每种后端 | 基线 | 当前提交 |
|---|---|---|
| 逻辑 Todo 投影调用 | 18 | 18 |
| 实际 Todo 投影 RPC | 18 | 10 |
| RPC 参数与结果序列化字节 | 32,284 | 22,723 |
这里的字节只覆盖参数和结果,不含传输 framing、其他方法、键编码、解码或全进程 CPU/内存;没有据此声称更低的完整运行成本。相同夹具指纹在同后端 base/head 一致,完整观察指纹均为 84c46f6f6ccbae22f02df088d2cf65abf3580507a030dc4d9987491706bc09d0。
负例通过真实 RPC 检查了返回对象修改、输入正文变化、传输选项、对象顺序、bool/int/float 与有符号零、大整数、两次非法输入、未缓存的 runtime.ping 和实际 authority snapshot、嵌套/独立/复制后关闭的 scope,以及 8 MiB 键加结果的保留拒绝;File/SQLite 的 base/head 四组均 PASS。额外把缓存键故意改成常量,仍运行真实 SQLite 公开 CLI,独立预期的正常准入变成 blocked_health/exit 1;未修改 head 的同路径 exit 0,说明 oracle 能检出错误复用。
对主干的风险 / Risks
[P2] Narrow the request state before inserting a memoized result — effect_runtime.py:1631。当前仓库配置的 uv run --extra test mypy 在基线通过 17 个文件,在 head 新增:Item "None" of "_RequestRuntimeRevision | None" has no attribute "remember_todo_context" [union-attr]。key is not None 在运行逻辑上来自前面的非空分支,但 mypy 不会沿这个变量关系收窄后面的 state。这是已引入的必需检查失败;没有复现运行时 None 异常,也没有据此声称必然崩溃。
最小修复是在插入 guard 中显式检查 state is not None,或采用等价的显式收窄;应保持完整键、预算、错误和重试语义。修复后重跑配置内 mypy、请求 scope/交接套件和必要真实路径,不应关闭检查或用 ignore 掩盖。
验证边界如下:26 个 Python 请求 scope/交接测试、13 个 TypeScript 纯投影测试和改动路径 Ruff 均 PASS。quick premerge 的六项直接检查与语义词汇检查通过,但整体 exit 1,原生 gate 为 quality_invalid_receipt;对应精确范围 CQR 已写为 FAIL,阻塞项是 validator:mypy。raw maintainability ratchet 也返回失败,原生 runner 标为 advisory_inherited_failure;本评审没有做它的独立完整 base/head 归因,不把这一项报成通过或豁免。
早期原生上下文捕获尝试在 base/head 都已产生正确的保存准入决策,随后在 context/capture 传输阶段 CLI exit 1。保留并只读回原决策,没有重复准入或记账;其根因未确认。随后独立普通夹具的成功只能证明上面明确列出的较窄路径,不能宣称这个旧失败已修复或已安装宿主全路径通过。相关 #7430 的更宽上下文/枚举评审问题也没有被这两个文件自动解决。
默认行为变化是请求内自动复用成功纯投影,没有新 opt-in。关闭/未进入 scope、不同输入和其他方法已做双版本反例;不新增 schema、提示、任务义务或调度权限。对纯投影缓存本身未发现第二个已验证阻塞缺陷,但完整宿主交付、实际模型采纳、全平台行为和端到端成本仍未验证。
我的整体评价 / Verdict
从完整 PR 看,机制与已证实的重复工作相称,沿用现有 owner 的边界合理,当前 scope 内没有应当改成另一个持久化权威或新抽象的理由。长期执行路径在已验证范围保留完整内容、独立请求寿命和权威读取;普通 CLI 用户流程保持可用。局部 RPC 减少是已证实收益,长期成果或总成本收益未证实。代码量不是通过理由,26/13 个测试通过也不能覆盖新增的必需类型检查失败。
视觉检查不适用:只改变内部请求复用和测试,检查了 summary/handoff 既有消费者,没有渲染页面或可见文案变化。未验证范围仍包括已安装 App 原生上下文传输和模型后续采纳,不宣称其视觉或端到端收益。共享语义复用已有 todo.context.page 词汇;没有新增 Enum/Literal、字符串分类器或把建议变成强制义务。
结论为 REQUEST_CHANGES。请先修复第 1631 行类型收窄并让必要本地检查通过,再对新的精确 head 复核;本结论不授予合并、安装或发布权限。
English verdict: REQUEST_CHANGES — the request-local design and bounded real-path parity are supported, but the exact head introduces a required mypy failure at line 1631.
| except (TypeError, ValueError, OverflowError, UnicodeError, RecursionError): | ||
| pass | ||
| else: | ||
| state.remember_todo_context(key, encoded) |
There was a problem hiding this comment.
[P2] Narrow the request state before inserting a memoized result
配置内的 uv run --extra test mypy 在不可变基线通过 17 个文件,在这个提交新增 union-attr:state 仍是 _RequestRuntimeRevision | None。前面 key is not None 的逻辑关联不能为这里提供类型收窄,因此必需检查失败;这不等于已复现运行时 None 异常。请在写入 guard 显式检查 state is not None 或作等价收窄,保留完整键、预算与重试语义,并重跑配置内 mypy 及受影响套件。
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
A single quota decision can ask for the same Todo summary several times. Reuse the successful TypeScript projection when the full request and transport options match inside the same revision-pinned Python request. Each caller receives its own decoded result. The reuse budget is 8 MiB of serialized keys and results per request; closing the scope discards them. Authority reads, failures and settlement are outside this path.
Extracted from #7430 as an independently reviewable and reversible slice. Cache insertion now explicitly narrows the request owner to its non-null state, satisfying the configured static type check.
Matched measurement. Collected the ordered calls from a real selected-Todo CLI guard against isolated SQLite and File stores. Replayed each store’s original 17 requests through the real handler on base and head. All 34 returned JSON bodies matched the originals, including order. On each backend:
The byte count excludes transport framing and other methods. This does not measure model context savings, wall time or a whole benchmark. Consecutive live guards take different reentry paths; those totals were not used for this comparison.
Validation. The configured mypy check initially reproduced the reported union-attr failure. With the explicit non-null guard, it passes all 17 configured source files. Request-scope and capture handoff suites pass 33 cases, including mutable caller results, changed data, numeric types, failed calls, authority operations and teardown. Explicit-off File and SQLite CLI acceptance checks pass both cases. Ruff and the public-boundary scan pass for the changed source.
The previously recorded default native-navigation fixture failures remain open. The explicit-off checks qualify that entrypoint only. Installed behavior, model adoption and complete task costs retain their earlier evidence limits. The matched projection measurement above is unchanged by this type-narrowing fix.