Repository navigation
fix(status): fail closed on truncated legacy Todo sections - #6921
JasonBuildAI wants to merge 2 commits into
Conversation
Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
songoow
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; OpenAI GPT-6 Astra; provider OpenAI; self_reported.
Reviewed head: fa29f297e50e3066376ef0d77516947a33240723
动机
这是对 #6870 所述 legacy ACTIVE_GOAL_STATE 截断问题的定向修复。原有读回把“文件可读、但在 Agent Todo 标题前已经截断”解释为 agent todo 数量为零,contract/status 也可能给出健康结果和首次只读 tick 的行动建议。受影响的是仍以 Markdown 为 Todo authority 的 Goal 及依赖 status、todo list、quota 决定是否推进的调用者;错误健康结果会把未知工作状态传递给后续执行判断。
预期前后变化是:缺少必要 Agent Todo 来源区段时,返回可见的 state_incomplete 和修复动作;确实存在、但没有条目的 Agent Todo 区段继续代表合法空集合。已经 promoted 到 canonical provider 的 Goal 仍只按 provider 判定完整性,展示副本的缺损不改变权威状态。此 PR 的非目标是恢复被截掉的条目、证明标题之后的正文没有丢失,或维护一份新的 last-good Todo 权威副本。
改动思路
实现沿已有 Todo parser 建立一个缺失区段诊断,再复用 contract、read model、attention queue 和 quota 已有的健康判断路径。这个实现比增加持久化健康开关或第二套 Todo inventory 更符合当前责任划分:缺失与否从本次实际读取的来源派生;修复原文件后,下次读取自然恢复,不需要同步另一份状态。
最关键的边界是 authority 优先级。代码在 canonical 路径确定之后才进入 legacy Markdown 完整性判断,避免把一个过时展示副本升级成否定 canonical 状态的依据。现有 parser 的标题别名与可见 Markdown 处理被继续使用,新增检查不通过裸字符串匹配另造语法规则。该局部诊断足以覆盖报告的问题;不能据此宣称能检测所有可能的截断位置。
具体改动
关键代码讲解
active_state_incomplete_warning(loopx/control_plane/todos/active_state_todo_parser.py:27)复用visible_markdown_lines与find_todo_source_regions,把缺少 agent 来源区域转为结构化诊断。Agent Todo、Codex Todo和Project Agent Todo仍沿已有别名解析;front matter、注释和代码块中的伪标题不会仅凭字面匹配构成来源。存在但为空的区段不触发诊断。_todo_contract_diagnostics(loopx/contract.py:463)在 canonical authority 分支之后读取 legacy 来源并消费同一诊断,产生 error 级state_incomplete。读取或 Todo 区域解析失败仍交给现有错误路径,不把异常变成空集合。list_goal_todos(loopx/control_plane/todos/list_readback.py:56)在 legacy 路径返回ok=false、error_code=state_incomplete和缺失原因。即使兼容 payload 仍有todo_count=0,状态明确告诉调用者该数字不能当成已证实的无工作结论。active_state_todo_fields与active_state_todo_attention_item(loopx/control_plane/todos/active_state_todos.py、todo_summary.py)把缺失诊断传给高优先级 attention;其修复建议先于首次 tick 等常规建议。project_asset同步携带相同诊断,避免页面内两个读回对同一损坏来源给出互相冲突的解释。
正向路径是完整且空的合法标题经 parser/list/contract 保持健康;负向路径是文件恰在 Agent Todo 前截断,经同一来源检查让 list 和 status 明确失败,再让已有 quota 健康门返回 blocked_health。修复来源的 owner 是用户或 controller,而不是 parser 自动重建丢失 Todo。
本次已阅读所有 11 个改动文件、调用处及现有 review 讨论;新增测试覆盖 legacy 截断的 API/CLI/status/attention/quota、三个空标题别名、解析失败,并把 canonical 展示副本的 truncated 情况加入现有 provider/readback 测试矩阵。git diff --check 在当前 head 通过。测试文件的覆盖范围是源码检查结论,不能等同于我重新跑过全部测试。
对主干的风险
没有发现需要阻塞的代码问题。最大的兼容变化是:历史上没有任何 Agent Todo 区段、但曾被当作健康空集合的 legacy 文件,现在需要恢复合法标题。这个行为是本次修复的主要效果,已在 status contract 和 attention queue 文档写清,不是一个隐藏的可选模式。state_incomplete 属于来源诊断和健康状态,不新增工作分类、授权主体或调度责任。
较强的回归反例是 canonical Goal 的展示 Markdown 损坏后误触发阻塞。我检查了 canonical 分支先返回的顺序、相关 provider 读取和新增 truncated 展示矩阵,未发现从展示副本回退或反向覆盖 canonical authority 的新路径。另一个剩余边界是 Agent Todo 标题存在、但标题之后内容被截断:当前检查不能证明该内容完整;这是明确保留的范围限制,不应把此 PR 的成功描述扩大成通用文件完整性保证。
此前尝试执行涉及真实 Effect runtime 的本地测试时,环境的 host permission/运行资源限制使整批结果不能形成有效的通过凭证。本次按要求优先发表源码 review,不依据 CI,也不把本地环境限制列为 PR 缺陷。尚缺我在当前 head 上独立完成的全链路 CLI 重放,尤其是 canonical file/SQLite 展示损坏与修复前后的行为对照。
我的整体评价
本次源码 review 未发现 blocking finding。改动使用已有 parser 和健康 owner,把“未知来源”与“合法空集合”分开,并保留 canonical authority 的优先级,范围与报告的问题相称。建议采用这份代码结论;本评论不声称已完成全套运行验证或合并资格认证。剩余验证边界如上,不构成凭空提出的代码缺陷。
English verdict: COMMENT — no blocking code finding at fa29f297e50e3066376ef0d77516947a33240723. The legacy completeness diagnostic is derived at the existing parser/readback boundary, remains separate from a valid empty section, and is bypassed by canonical authority. This is a source-review conclusion; CI was not used as a prerequisite, and a complete independent live CLI/base-head validation is not claimed.
Goal And Delivered Outcome
Outcome basis / optional anchor:
Closes #6870.Goal/source and gap: A readable legacy
ACTIVE_GOAL_STATE.mdthat ends before## Agent Todois currently classified as a healthy goal with zero Todos. This turns an unknown projection into "no open work" and letsquota should-runauthorize a turn.Observable before → after, with the validation row that proves it: On the same synthetic fixture,
statuschanges from exit0/ok:true/connected_without_run/ generic first-tick advice to exit1/state_incomplete/ explicit restore guidance;todo listchanges from exit0/ok:true/todo_count:0to exit1/error_code:state_incomplete. Restoring the section returns the fixture to exit0with one Todo.Issue/task and intended base:
Closes #6870; base isloopx-project/loopx:main.Author Declaration
AI disclosure: this change was drafted with AI assistance at my request, under my direction and review.
Implemented against
242821068; the status/Todo contract indocs/status-data-contract.mdat the final base.loopx/contract.py,loopx/control_plane/todos/todo_summary.pytests/control_plane/test_truncated_active_state_todos.py; syntheticstatuscomparisontodo listmust not present the missing projection as a valid empty listloopx/control_plane/todos/list_readback.pytodo listcomparisonquota should-runon the wounded fixture returnsshould_run:false,state:blocked_healthloopx/control_plane/todos/active_state_todo_parser.pyloopx/control_plane/todos/active_state_todos.pytests/control_plane/test_canonical_status_todos.pyScope And Continuation
Validation
fa29f297e, rebased onto upstreame4190c30d. The focused regression and direct CLI reproduction were rerun on the final head; the canonical status/Todo suite reports 156 passed and four unchanged Windows GBK subprocess-decoding failures, which pass when rerun withPYTHONUTF8=1.regression_paritypassed242821068and the change: status exit0/ok:truevs1/state_incomplete; Todo list exit0/ok:truevs1/error_code:state_incomplete; restored section returns exit0with one Todo.unitpassedtests/control_plane/test_truncated_active_state_todos.py: 6 passed at final headfa29f297e, including directstatus,todo list, andquota should-runCLI regressions. Covers truncation, three accepted aliases, project-asset propagation, contract diagnostics, status attention, and malformed-region handling.integrationpassedtests/control_plane/test_canonical_status_todos.py: 156 passed and four environment-only Windows GBK subprocess-decoding failures; the four failures pass withPYTHONUTF8=1. Includes truncated display cases proving canonical/provider authority is unaffected.real_entrypointpassedloopx status --format json,loopx todo list --format json, andloopx quota should-run --goal-id ...on wounded and restored fixtures. Wounded: exit 1 andstate_incomplete; restored: exit 0 with one Todo. Quota reportsshould_run:false,state:blocked_health, and the restore action.staticpassedpy_compile;git diff --check; semantic inventory reports 7 changed sources and zero supported new vocabulary carriers.manualfailedloopx canary premerge --from-git-diff --git-diff-base upstream/main: 17/19 selected checks passed, including risk-profile smokes and public-boundary. The two failures reproduce on the same upstream baseline: hot-path extension doctorentrypoint_missing, and CLI output budget differential Windows temp-directory cleanupPermissionError/WinError 32.staticnot_runno-any-returndiagnostics in the touched modules. No mypy pass is claimed.real_backendnot_applicablestatus,todo list, andquota should-runCLI paths. The canary limitations are the two baseline-reproduced Windows/extension-environment failures above. A section cut after the## Agent Todoheading but before its items remains indistinguishable from an intentionally empty section; that is the explicit boundary of the heading-presence strategy.Frontend / Visual Evidence
Independent Review
fa29f297e: the contract now distinguishes an emptyagent_todosfield from a required legacy heading, and the primary acceptance path has an automated CLI regression forstatus,todo list, andquota should-run.## Agent Todoheading but before its items still reads as an intentionally empty section. This patch deliberately checks heading presence, not last-known-good section inventory.Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
state_incompletestatus/error classification only to the legacy Markdown fallback; canonical authority is unchanged.Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).python3 scripts/check_rfc_bilingual.py --base origin/main --head HEADpasses, or no paired RFC changed.none.Signed-off-bytrailer (git commit -s).