Skip to content

fix(quota): resolve an explicit --todo-id from the Goal's own rows - #4837

Merged
huangruiteng merged 2 commits into
mainfrom
codex/steward-explicit-id-reachability-20260921
Sep 21, 2026
Merged

huangruiteng merged 2 commits into
mainfrom
codex/steward-explicit-id-reachability-20260921

Conversation

@huangruiteng

Copy link
Copy Markdown
Collaborator

动机

quota should-run --todo-id <id>本泳道自己刚做完的那一行会拒绝:decision=skip state=quota_action_selection_rejected reason=candidate_not_currently_eligible。行内已经记了三次真实复现(同一台机器、同一天,含 turn id),后果不是"少选一个动作",而是只能把结算挂到可选带内的另一行,账本因此长期存在归属偏移。

根因是 look-up 的种子:build_explicit_advancement_next_action 的候选集合来自 quota_runnable_action_candidates(...) + agent_todo_planning_source_items,两者的上游都是 status payload 里有界的展示 lane(primary + 2 alternatives ≈ first_executable_items/executable_backlog_items,以及 items/deferred/blocker/monitor)。于是"开放、已认领、typed advancement"的行只要落在展示预算之外就查不到,TS reducer 收到 candidate=null,只能给出 candidate_not_currently_eligible。PR #4512 已经把 look-up 从"仅展示 lane"扩到"规划清单",但那份清单本身仍是有界投影,缺口依旧。

改动思路

显式 --todo-id 是调用方已经做出的选择,不是从菜单里挑;因此按 id 解析时应当读 Goal 自己的状态行。新增 _authoritative_requested_agent_rows(...):用 loopx.materials.goal_state_path 取目标 Goal 的 state file,用 goal_todo_summaries(..., roles=["agent"], status="open", todo_id=<id>) 解析这一行,再并入既有 builder 的候选集合。所有 eligibility 谓词(actionable open / task_class / capability / claimed_by)仍在原 owner 里执行,所以这只扩大可达性,不扩大可选项

具体改动

  • loopx/control_plane/quota/should_run_prepare.py(+47/-10):新增 _authoritative_requested_agent_rows;显式选择分支的候选集合追加该来源;状态文件缺失/不可读或 id 不存在时返回空表并保持原有拒绝,不改变主路径。
  • tests/control_plane/test_explicit_todo_id_beyond_presented_lanes.py(+104/-0):3 条断言——展示 lane 之外的行可由 id 解析并被 builder 接受(同时先证明展示 lane 里确实没有它);未知 id / 缺失 state file 解析为空;别的 agent 的行与 blocked 行仍被谓词拒绝。

风险边界

  • 谓词未改:仅增加了"从哪里找到这一行",未放宽任何准入;非法/他人/阻塞行照旧不可选。
  • 只在显式 --todo-id 时读取一次 Goal state(缺失或不可读即跳过),不改变无选择时的热路径,也不新增持久化状态。
  • 未覆盖:不改变展示 lane 的预算策略;"提交前是否需要同时收敛展示"是产品选择,不在这一刀。

验证

  • 端到端(真实 Goal loopx-meta,本次唤醒 turn id):同一条此前三次被拒的命令现在返回 decision=run / qualification=qualified / selected=todo_431983a1e942,回执由 unbound 升级为绑定。
  • 反例:同一命令此前在同一 Goal 上返回 quota_action_selection_rejected / candidate_not_currently_eligible(本泳道 16:11Z、19:07Z、21:16Z 三个 turn,均已记录在案)。
  • 3 条新用例 + 相邻 45/158 条(quota settlement、slot accounting、blocked-priority notice、state refresh、canonical planning、turn envelope)通过;ruff 干净。

The presented planning lanes are a display budget, so an owned, open, typed
advancement Todo that sat outside them was unreachable by an explicit
--todo-id and the guard refused it as candidate_not_currently_eligible, even
though the caller had just worked on that row and had no other legal way to
bind its own settlement to it.

The by-id lookup now also resolves the requested row from the Goal's own state
rows. Every eligibility predicate still runs in the existing builder, so this
widens reachability of the lookup, not what may be selected.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Assert that a row absent from the presented lanes is reachable through the
Goal state while another agent's row and a blocked row still refuse.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

精确 head:4d537d82340c2545e314a80d5dedb957dcfed7c3(base main 09f10c4e3)。无阻断发现,建议合并;合并决定留给 maintainer。

动机

problem_contextquota should-run --todo-id <id>本泳道自己刚做完的那一行会拒绝——decision=skip state=quota_action_selection_rejected reason=candidate_not_currently_eligible。行 todo_414bf4c7a75c 里已记了三次真实复现(同一天、含 turn id),后果不是"少选一个动作",而是只能把结算挂到可选带内的另一行,账本因此长期归属偏移。

根因在 look-up 的种子:候选来自 quota_runnable_action_candidates(...) + agent_todo_planning_source_items,两者上游都是 status payload 里有界的展示 lane。于是"开放、已认领、typed advancement"的行只要落在展示预算之外就查不到,TS reducer 收到 candidate=null,只能给出 candidate_not_currently_eligible。PR #4512 已把 look-up 从展示 lane 扩到规划清单,但那份清单本身仍是有界投影,缺口仍在。

真实 Goal(loopx-meta)上的端到端对比:

base: decision=skip state=quota_action_selection_rejected reason=candidate_not_currently_eligible(16:11Z / 19:07Z / 21:16Z 三个 turn 记录在案)
head: decision=run   action_selection_qualification.state=qualified   selected todo_431983a1e942   回执 unbound → bound

改动思路

architecture_flow / repository_reuse / walkthroughs:显式 --todo-id 是调用方已经做出的选择,不是从菜单里挑,所以按 id 解析应当读 Goal 自己的状态行。新增 _authoritative_requested_agent_rows(...):用既有 loopx.materials.goal_state_path 取 state file、用既有 goal_todo_summaries(..., roles=["agent"], status="open", todo_id=<id>) 解析这一行,并入既有 builder 的候选集合。所有 eligibility 谓词仍在原 owner 执行,因此只扩大可达性,不扩大可选项

被否掉的替代方案:放宽谓词(扩大可选项)、给 reducer 加新 reason(行依旧不可达)、改从 status 的 rollout-event index 取行(那里的行文本是 todo add recorded for ... 占位、没有 task_class,builder 无法判定)。

具体改动

changed_line_classification / symbol_map:生产 1 个文件(should_run_prepare.py +47/-10),测试新增 1 个文件(+118/-0)。

关键代码讲解

  1. loopx/control_plane/quota/should_run_prepare.py:446 _authoritative_requested_agent_rows —— 只为显式请求解析一行;未知 id / 缺 state file / 读失败 / 投影非法一律返回空表(不抛错、不编造),保持原有拒绝形状。
  2. 同文件显式选择分支的候选并集:两个来源变三个(runnable candidates、planning inventory、authoritative row)。该并集只在 --todo-id 存在时构建,未选择的默认路径完全不变。

对主干的风险

failure_analysis / walkthroughs.negative / validation_matrix / scope_fit

  • 最强回归场景:显式请求会多解析一次 Goal state(仅在带 --todo-id 时),大 state 的解析成本未测量。
  • 触发到观测:同一 Goal 上"此前被拒、现在 qualified";展示 lane 里没有该行时仍能被 builder 接受;别的 agent 的行、blocked 行、未知 id、缺失 state 一律照旧拒绝。
  • 爆炸半径:显式选择路径;可选带、判定码、展示预算、调度与扣费路径未动。回滚即 revert 两个提交。
  • 生效调用点:任何带 --todo-idquota should-run 都会走该分支(非仅测试可达)。
  • 证据边界(诚实记录):TS reducer 是通过真实 CLI 走通的,没有单独重跑 TS 套件;反例来自同一天同一 Goal 的三个已记录 turn,而不是重跑一次 base;未跑全量仓库套件。

我的整体评价

observable_semantics / code_volume / change_proportionality / default_off_isolation / authority_semantics

  • 三条对比行分别是"真实 Goal 显式请求""展示 lane 缺失的行""他人/阻塞/未知/缺 state":第一条从 rejected 变 qualified;第二条证明可达;第三条证明可达性没有放宽资格。判定码与可选带一字未改,记为 intentional_change_validated
  • 规模与收益相称:一个只读 resolver + 一处并集成员 + 3 条断言;无新模块、依赖、配置、状态或 CLI 面。
  • 隔离性:只在显式 --todo-id 时激活,默认守卫路径不额外读文件、不扣费,default_off_isolationisolated
  • authority:没有放宽权限——谓词与 reducer 仍是唯一判定者,菜单也没多出这一行。
  • 类型/域中立/义务表述:按 todo_id 精确匹配、由 typed 字段判定资格,无子串或自然语言启发式;新增文案只提 quota、guard 与 Todo,不含 goal/产品/benchmark 措辞。
  • 结论:无阻断性 finding。残余风险三条:显式请求的额外解析成本未测量;TS reducer 未单独重跑;证据是有界集合(3 + 158 + 45 + 真实 CLI),未跑全量套件。

English verdict: APPROVE - reviewed head 4d537d8 makes the explicit by-id lookup read the Goal's own rows, keeps every eligibility predicate and the offered band unchanged, and is backed by a live command that flips from candidate_not_currently_eligible to qualified, three focused cases, a 158-case adjacent run, a clean-worktree rerun, and an explicit statement of the unmeasured parse cost and un-rerun TS suite.

@huangruiteng
huangruiteng merged commit 9218580 into main Sep 21, 2026
21 of 26 checks passed
@huangruiteng
huangruiteng deleted the codex/steward-explicit-id-reachability-20260921 branch September 21, 2026 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant