## 修复记录 - 21:56:记录 bug 修复:非成功 Agent 工具调用可能被商业账本误计量。 - Git 提交检查:已执行 `git fetch --all --prune`;`HEAD..origin/main` 无新增提交;本地 `main` ahead 17 个既有提交,分别为 `242d68c3` 审批任务流、`28b834ed` 不可变动作回放、`4940ebc4` 风险处置、`ee88a36b` 分层费用学习、`6bdf65bc` 权威预审、`ae3f02c3` 零录入票据关联、`54754b55` 个人申请记忆、`211f85d9` 统一申请流、`5b246307` 申请预览决策、`a662cfe6` 申请反馈台账、`5ed34c2b` 历史申请回填、`11275e4b` 迁移归属校验、`1347366b` 费用时间线与草稿事件、`22669a90` 统一费用事件时间线、`a616b30c` AI 申请事务、`653eda05` bearer 会话和 `661990b2` 费用案例事件;均非本次修复产生。 - 修改:`commercial_runtime_policy.py` 把工具调用状态明确分为可计量、采集中和不可计量;`commercial_runtime_metering.py` 只允许 `succeeded/success/ok/completed` 的真实终态调用进入用量与成本账本,`running/pending/queued` 保留待终态补偿语义,`blocked/failed/skipped/cancelled` 不再产生商业事实。同步用 `commercial_runtime_bridge.py` 将未配置租户兼容放行、显式配置后的执行前配额门禁、成功调用后的幂等追加和故障补偿接入真实 `AgentToolCall` 生命周期。 - 操作:在 `AgentRunService` 的创建与终态更新后触发桥接计量;在中央工具执行器调用真实 executor 前执行权益预检;将工具执行职责拆到 `orchestrator_tool_execution.py`,让核心编排文件回落到 762 行;所有命令均在 `local-x-financial-linux` 容器内运行并设置 60 秒超时。 - 验证:商业运行计量 17 项通过,商业模型/服务/接口/运行计量合计 28 项通过,AgentRun 与 Orchestrator 鉴权相关回归合计 34 项通过;范围内 Ruff、`compileall`、diff 检查和类级 800 行检查通过。全库 code-size 门禁仍被本次范围外的 `RiskRuleGenerationService` 817 行阻断,未在本修复中改动该类。 - 影响:未成功完成的工具调用不会再消耗客户配额或形成内部成本;未配置商业计量的既有租户继续执行;已配置租户在执行前受配额约束。计量系统故障时真实工具调用记录保持不变,返回 `requires_reconciliation` 并可按同一工具调用 ID 幂等重试,避免把计量失败伪装成已入账。 - 22:31:修复执行前只读配额在并发下可超卖、直接调用绕过预占及补偿误判问题。 - Git 提交检查:再次执行 `git fetch --all --prune`、`git status -sb`、`git log HEAD..@{u}` 和 `git log @{u}..HEAD`;上游无新增提交,本地仍 ahead 17 个既有提交:`242d68c3`、`28b834ed`、`4940ebc4`、`ee88a36b`、`6bdf65bc`、`ae3f02c3`、`54754b55`、`211f85d9`、`5b246307`、`a662cfe6`、`5ed34c2b`、`11275e4b`、`1347366b`、`22669a90`、`a616b30c`、`653eda05`、`661990b2`,均非本次修复产生。 - 修改:新增 `commercial_runtime_reservations` 运营占位及 `0019` 迁移;在订阅、权益行锁内按“已用量 + 有效预占 + 本次预占”原子校验硬配额。中央 Orchestrator 先生成稳定 tool call ID 并预占,再执行真实工具;成功且真实量不超过预占才追加用量/成本并提交,失败或阻断释放,变量基准没有执行器 hard max 时失败关闭。 - 修改:新增持久 `reconciliation_required` 和过期补偿器。缺少执行前预占的旧直接调用不再静默补写正常用量,而是冻结对应容量;补偿器仅在真实工具成功、失败或运行已终止且无调用时结算/释放,运行中或来源不确定继续保留。修复历史过期订阅/权益错误启用门禁、无租户旧运行错误进入补偿、相同预占重试被自身占位判定为额度耗尽三个边界。 - 操作:拆出运行时成本解析、周期键、标量校验、预占和补偿模块,相关核心类均低于 800 行;更新模型注册、迁移所有权、前置检查、商业配额投影、AgentRun/中央工具调用点和迁移/并发/补偿测试。所有 Python、Alembic 和 PostgreSQL 验证均在 `local-x-financial-linux` 容器内以 60 秒超时执行。 - 验证:运行时定向 25 项通过;商业、Agent、权限、迁移组合 140 项通过;一次性 PostgreSQL 17 商业并发 4 项通过,两个线程竞争一份硬配额时只有一个预占成功;全新 PostgreSQL 0019→0020 完整 Alembic 升降级循环 1 项通过;范围内 Ruff、`compileall`、`git diff --check` 和相关类 800 行检查通过。Orchestrator review 套件保持既有 5 项本体/申请流失败、11 项通过;全库 code-size 仍仅被范围外 `RiskRuleGenerationService` 817 行阻断。 - 影响:商业硬配额从“执行前提示”升级为数据库原子 permit,真实工具并发不能再穿透上限;成功事实可幂等结算,计量或成本故障保留可补偿状态且不伪造成功;未配置 runtime meter 的路径继续兼容,历史失效配置不会误拦截用户。 - 22:39:修复“用量已提交、成本写入失败”缺少持久补偿身份的问题。 - Git 提交检查:再次执行 `git fetch --all --prune`、`git status -sb`、`git log HEAD..@{u}` 和 `git log @{u}..HEAD`;上游仍无新增提交,本地仍 ahead 17 个既有提交:`242d68c3`、`28b834ed`、`4940ebc4`、`ee88a36b`、`6bdf65bc`、`ae3f02c3`、`54754b55`、`211f85d9`、`5b246307`、`a662cfe6`、`5ed34c2b`、`11275e4b`、`1347366b`、`22669a90`、`a616b30c`、`653eda05`、`661990b2`,均非本次修复产生。 - 修改:为运行时预占增加 `committed_reconciliation_required` 状态。真实用量已经追加但内部成本失败时,保留真实数量、结算时间和失败原因并进入补偿队列;按同一 tool call 重试只幂等补写成本,成功后恢复 committed。该状态不再计入有效预占,避免真实用量和冻结量重复消耗配额。 - 修改:直连调用发生后若当前唯一匹配合同已暂停,允许补偿记录绑定原订阅/权益快照并进入 `reconciliation_required`;正常执行前 reserve 仍严格要求 active/trialing 订阅和 active 权益,不放宽真实执行许可。 - 验证:容器内运行时定向 27 项、商业/Agent/权限/迁移组合 183 项通过,另 1 项因未显式配置外部迁移库跳过;全新 PostgreSQL 完整迁移循环 1 项、商业并发 4 项通过。成本故障用例验证 `used=1`、`reserved=0`,重试后用量仍为 1 且只新增 1 条成本;范围内 Ruff 通过。 - 影响:成本账本短暂故障不再只依赖日志发现,也不会让客户额度被重复扣减;暂停发生与工具终态竞态时,已发生业务仍有持久、租户隔离的补偿证据。