Repository navigation
fix(quota): bound model-facing settlement diagnostics - #7913
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.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
当前 exact head 6808cd33adbb4ed42e4f21e1a2557bb5063f5cc7 有两项 P2:输出捕获失败会抹掉原始拒绝与结算字段;新增自动路径使用 Unix-only API,缺失时未转成结构化恢复。以下结论来自独立源码与本地反例,CI 未查询。
动机
调用已验证交付结算命令的 Agent 和读取 JSON 结果的自动化调用者。
一次结算因工作区不匹配被拒绝时,原先会打印包含完整 before 快照的大 JSON;候选把快照放入私有 capture,正常路径只展示控制字段和按需读取入口。
正常路径保留原始控制字段、完整诊断和同一 Turn 的幂等恢复;但 capture 失败会丢失原始拒绝,缺少 Unix API 时会异常退出,因此失败恢复尚未达到交付要求。
本 PR 不改变准入、扣额规则或合并权限,也不证明安装采用、模型保留、完整成本下降或长程收益。
接受依据为 docs/reference/required-work-context.md,不可变 revision 8d314af4955c86ea389b0916eda5f1a51f30b966;同时检查同 revision 的 docs/quota-allocation.md。映射其既有小节:Selected capture details 的完整值、摘要和分页在正常路径满足;Receipt-backed settlement progress 的原操作读回在错误投影丢失关键字段;Saved context cache 的私有捕获与同身份恢复尚缺平台安全处理。新增文档不能自己证明上述承诺。
改动思路
原路径把完整结果直接打印;新路径先由既有 TypeScript owner 执行与读回,再由 Python IO 保存完整结果,最后展示短控制字段。超大的未知控制字段通过同一 capture 的 mandatory selected read 完整恢复。这里用下表说明实际分支,未另作未经渲染验证的图。
| 分支 | 正常结果 | 需要修复的边界 |
|---|---|---|
| 省略 budget | 保留原 full JSON API | 无新捕获 |
| 生成的 bound JSON 命令 | 自动追加 64000;仅诊断延后 | 不受 native context off 控制 |
| capture IO 失败 | 原操作已经评估,可能已经提交 | 现在只保留部分字段,丢掉原始拒绝/回执 |
| 缺少 Unix 用户 API | 本应平台适配或预先拒绝 | 现在可能在扣额后抛出 AttributeError |
具体改动
-
[P2] 保留捕获失败前的原始拒绝与结算结果 —
_emit_quota_result的新异常分支。在隔离真实 CLI fixture 中,从 canonical checkout 执行本应拒绝的命令,再令 capture 目录权限不安全,结果仍是appended=false、扣额数 0,但原workspace_guard.action=return_to_delivery_worktree和具体原因全部消失,只剩“读取原 settlement receipt”的通用指引;这次拒绝并没有生成 spend receipt。实际提交后遇到相同 IO 错误时,canonical owner 有 validation/writeback/spend 三份 committed receipts,显示结果却没有settlement_result与settlement_identity。第 351 行复制的是不存在于正常此结果的settlement。请把原评估结果与 transport error 分开保留;至少保持原始 stop/action、身份、真实回执和可执行恢复路径。补测拒绝+捕获失败的 0 次扣额,以及提交后失败仍可读回真实 receipt、同 Turn 重试总共 1 次扣额。现有证据没有观察到重复扣额。 -
[P2] 在提交前处理不可用的 Unix API —
budgeted_settlement_result第 777 行。os.getuid()按 Python 官方接口文档 只在 Unix 提供,而本仓库支持原生 Windows。新生成命令默认带 budget,完整结果超限便在操作评估后进入这里;当前只捕获OSError/ValueError,缺少该 API 的AttributeError会绕过 JSON 错误结果。模块局部模拟 API 缺失已直接复现该异常;这不是原生 Windows 实测。请复用平台适配的私有目录/ACL 校验,或在 effect 前明确拒绝不支持的配置,并保证 effect 后仍提供原结果的结构化恢复。补上缺少该 API 的反例,再以受支持 Windows 的大结果路径验证;不能只忽略隐私校验。
正常实现复用了 write_decision_capture、reader descriptor、现有双摘要分页及 typed settlement readback,未建立第二套记账状态。七个文件的 +282/-11 包含默认 argv、异常投影、帮助/双语说明和聚焦测试;未知键、字段冲突、大整数、完整尾部控制、capture 损坏/缺失等已有正常与负向覆盖。相邻重构评估认为不需要新增框架;修复同一 IO owner 的错误字段投影即可。
对主干的风险
独立运行两个完整模块:test_quota_result_budget.py 与 test_quota_settlement_cli.py,173 passed。不可变 base 8d314af4955c86ea389b0916eda5f1a51f30b966 的既有 File/SQLite 工作区与结算用例 2 passed;base 没有新 budget API,未把它伪称为新功能的通过证据。新增真实 CLI 反例完整执行后因原 workspace guard 缺失失败;同身份 uncapped 恢复成功且总扣额保持 1。另一反例在缺少 getuid 时直接失败。首版评审探针曾把 dict 当对象调用 as_dict,那是探针错误;修正后仍复现产品字段丢失,未把探针错误计为产品缺陷。
提交带 DCO sign-off,committed RFC bilingual diff check 通过;diff-scoped semantic advisory 在四个生产源码变更中未发现受支持 vocabulary carrier,但其扫描不覆盖动态语义。未运行完整 premerge、Stage 2C 或原生 Windows,也没有查询、轮询或等待 CI。上述缺陷来自当前新增错误分支;不以 CI 未知作为拒绝依据,合并检查、readiness 与授权继续单独处理。
默认行为必须明确:手工省略 budget 仍保留旧 API,生成的 Turn-bound JSON 命令默认已变为 64000,即使 native context delivery off 也会进入新分支。捕获/分页不产生准入、权限、模型保留或完成证明;同 Turn 恢复不得换身份或重新准入。
我的整体评价
现有 Python 输出 IO 边界足以承担完整 capture 和投影,TypeScript 结算 owner 继续独占决策;两个反例可在此边界局部修复,无需增加状态 owner 或通用框架。
当前 PR 应交付同一结算结果的有界展示和完整失败恢复,保留原始操作身份、拒绝原因、回执与跨平台可用性。
检查了七个改动文件及现有 CLI 调用链;没有渲染页面、布局或产品文案界面变化,截图验收不适用。
未运行安装版 App、原生 Windows 或真实模型;本次仅资格化源码 CLI 与隔离故障注入。
方向有实际正常路径收益,范围也集中;当前两项恢复缺陷仍阻止 approve。请在本 PR 的既有 owner 修复并保留原反例,无需增加人工确认轮次或扩大到无关长程资格测试。该评审不授予合并、安装或升级权限。
English verdict: REQUEST_CHANGES for 6808cd3: preserve the evaluated result on capture failure and handle unavailable Unix APIs before effectful delivery; CI was not consulted.
Reviewer: actor_kind=model_agent; model=gpt-6.1-sol; provider=OpenAI; declaration_source=runtime_reported; reasoning_effort=max
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: actor_kind=model_agent; model=gpt-6-astra; provider=OpenAI; declaration_source=runtime_reported; reasoning_effort=high
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
未发现当前 head 257b45585f908b1a9ec7d7d27b294a7cf8389217 的阻塞性问题。两项 P2 已通过原反例复核;这次结论同时覆盖原始八文件 PR 与最近修复,不继承旧评审结论。此复审由本 PR 作者执行。
动机 / Motivation
执行 Turn 结算并读取 JSON 的 Agent 与自动化调用者。
原先超大诊断淹没恢复信息,捕获失败又丢失拒绝或回执;现在正常读取有界,故障时保全原控制字段并指向同身份恢复。
真实 CLI 已验证拒绝零扣额、提交后故障仍保留回执、恢复后总计一次扣额。
不改变记账 owner、准入、工作区权限或原实验预算,不证明模型保留或总成本收益。
验收依据是 docs/reference/required-work-context.md,不可变 revision 8d314af4955c86ea389b0916eda5f1a51f30b966:Selected capture details 要求原始选中值完整且按摘要读取,正常及未知大控制字段路径通过;Saved context cache 要求保留原捕获和原身份恢复,拒绝、提交后故障与恢复路径均通过。补充依据为本 PR 两条 P2 原评审线程;新增文档本身不是通过证明。
最大反对理由是:输出优化若掩盖已经提交的效果,会让调用者错误重做工作。本次先复现这个风险,再证明修复沿原身份恢复且没有第二次扣额;不以字节减少或测试数量代替这个结论。
改动思路 / Approach
复用既有不可变捕获与 TypeScript 结算 owner,在 Python 输出边界修复错误投影与平台前置校验,无需新增状态机或 ACL 框架。
本 PR 交付 POSIX 有界结算及结构化失败恢复;Windows 不验证私有 ACL,因而在效果前拒绝此输出选项并保留完整结果 API。
| 调用分支 | 当前行为 | 证据边界 |
|---|---|---|
| 手工省略输出预算 | 原完整 JSON API | File/SQLite 原分支通过 |
| 生成的 Turn-bound JSON 命令 | 默认 64000,超大快照进入不可变 capture | 明确的默认改变,与 native context off 无关 |
| 捕获失败 | 保留原 ok、拒绝、身份、回执,另附投递错误并非零退出 | 故障兜底允许超过展示预算,优先不丢控制信息 |
| 无 POSIX 身份接口 | 扣额前结构化拒绝有界输出,原无预算 API 可用 | 未宣称原生 Windows ACL 或成功捕获验证 |
上表描述精确 head 的源代码分支;没有把图表当执行证据。做更小的直接截断会丢失可恢复信息,保留全部原始输出则无法解决正常路径的大量重复诊断。复用既有 reader 是合适边界,建立独立结算状态或通用 ACL 框架都不需要。
具体改动 / Changes
_emit_quota_result在 typed owner 评估之后只负责投递。异常分支复制原始控制字段,仅移除 before/after,并单独返回 result_delivery_error。原 ok 描述已评估操作,非零进程退出描述投递失败;不会用投递失败覆盖 workspace_guard、settlement_result、settlement_identity 或未知控制字段。原来错误地复制 settlement 的遗漏已消除。budgeted_settlement_result保持完整私有 JSON、摘要和原 reader,必要时对全部控制字段提供强制选读。缺少 getuid 时通过同一 IO helper 明确拒绝,CLI 在准备效果之前校验;reader reference 及要求私有的 capture 读取也安全失败,不把 Windows mode bits 当 ACL。effect_program.py继续只组装原 Turn 命令,TS settlement owner 仍唯一负责准入、工作区拒绝、写回与扣额。quota_registration.py和中英说明公开默认 64000、无预算 API、失败兜底及平台边界。- 扩展既有 File/SQLite CLI 测试,覆盖错误工作区加不安全目录、提交后 IO 失败、完整回执读回及同 Turn 重试。独立缺失接口测试覆盖普通及 Windows 形态路径,并证明效果准备不会被调用。没有把本地模拟描述为原生 Windows 实测。
复用搜索覆盖捕获 writer、reference reader、native continuity projection、private_json 及 receipt owner。native continuity 与本次结算输出激活条件不同,不能用其开关冒充隔离。保留的 full-result API 是现实调用者兼容契约,非第二套业务规则。相邻改进采用一个共享私有捕获平台校验 helper;未扩大到无关 Windows 平台迁移。
对主干的风险 / Risks
真实 CLI 同组反例:旧 head 6808cd33adbb4ed42e4f21e1a2557bb5063f5cc7 的两个有界 File/SQLite 用例均因 workspace_guard 丢失失败,两个无预算用例通过;当前 head 四项均通过。拒绝时实际扣额为零,已提交后错误仍携带完整结算回执,重试后实际总扣额为一。缺失 OS API 的四项反例在修复前失败,修复后通过,完整 budget 模块 10 项通过。
精确 head 完整相关模块 177 passed,四个 reader/capture 模块 119 passed;这些运行使用当前已提交源码。
标准 managed premerge PASS:4 项直接检查、Python 编译及 19 项选中检查通过;committed RFC bilingual gate、public-boundary scan 通过。公开扫描有一处既有非字面 credential 测试说明告警,原样保留,未发现真实凭据。CI checks 对应本地 Ruff 范围通过,依赖锁与顶层模块预算 7 项通过。更宽的 ruff check . 曾报告118项非该 CI 范围问题,未声称修复;不能把不同范围混写成全仓 lint 通过。
第一版新增测试误以为 settlement_result 内嵌 identity,导致两个测试断言失败;实际 schema 将 identity 独立保存。修正断言检查真实 receipts 与 settlement_identity 后四项通过,未改产品语义或放宽验证。保留此前失败记录,未归因到 CI。
根据该 Goal 的配置未查询、轮询或等待 CI。委派中提及的旧 checks 失败原因仍未知,当前对应本地检查通过不等于证明其历史原因已解决。原生 Windows、安装版 App、真实模型保留和长程总成本仍未实测;此 PR 在缺少私有权限验证时选择前置拒绝,有界输出可移除,未宣称该平台的私有捕获成功。
我的整体评价 / Verdict
复用既有不可变捕获与 TypeScript 结算 owner,在 Python 输出边界修复错误投影与平台前置校验,无需新增状态机或 ACL 框架。
本 PR 交付 POSIX 有界结算及结构化失败恢复;Windows 不验证私有 ACL,因而在效果前拒绝此输出选项并保留完整结果 API。
已检查 CLI 输出及说明文档,未改变渲染页面;截图不适用。
原生 Windows、安装版 App 和真实模型未实测。
核心结果是让捕获故障后仍能按原身份辨明拒绝或提交并继续恢复,而非只生成更短的包。输出错误不授予新的执行权限、不重建旧 receipt、不改变实验账本。本次没有新的 prose classifier、状态词汇 owner 或手工同步字段;diff-scoped advisory 未发现支持范围内的新 vocabulary carrier,这仅是有界分析,不是全部语义自动证明。
Approve 仅针对当前源码交付;合并 readiness、当前 head 检查及授权单独执行。Windows ACL 扩展需独立平台资格,不能为了消除异常而跳过隐私验证。没有剩余已验证阻塞发现。
English verdict: APPROVE for 257b455: evaluated refusal and settlement controls survive capture failure, unsupported private capture is rejected before effects, and File/SQLite recovery remains idempotent. Native Windows and reported historical CI causes remain unverified; merge readiness is separate.
Oversized
quota spend-slotrefusals currently print the completebeforesnapshot, obscuring the error and recovery. Generated Turn-bound JSON settlement commands now use the existing 64,000-byte output budget. Larger results retain their full JSON in a private immutable capture; other controls remain visible, or are delivered through a mandatory selected read when they also exceed the budget.The existing reader verifies the complete digest and preserves the requested page budget. Calls without the option retain the full-result API. This does not enable native context continuity or change workspace validation, operation identity, accounting or replay. A post-evaluation capture failure still reports the actual append and settlement outcome.
Validation: 10 focused cases passed, including real File/SQLite refusal, invalid input before effects, delivery failure after a committed spend, same-receipt replay, and complete/missing/replaced capture reads. Ruff, the bilingual diff gate and the public-boundary scan passed. All seven complete related Python modules passed (258 tests); managed standard premerge passed its direct and selected local checks, with no manual hold. Existing quota CLI and context-read are the caller journey; no rendered product surface changed. Installed use, model retention and total cost savings remain unverified.