fix(periodic-report): close canonical progress and approval retry consumers - #4867
Conversation
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
审阅 exact head:d1dcf38dd889a90b60e1652e90020ea9646ce795
动机
这个修复解决的是 promotion 之后仍存在的真实 authority 分裂:Todo 的 canonical provider 已经成为事实源,但 periodic-report 的进度快照、post-writeback frontier 和 approval retry 仍可能回读 Markdown display。于是 display 缺失、过期或损坏时,报告会漏掉已完成工作、重新带回已删除工作,或者找不到已经归档但仍应生效的 rejection/cancellation。
我按“promoted provider 与 display 冲突”这个最强反例审阅,而不是只接受 PR 的 happy path。结论是本 PR 确实关闭了一个完整的 report-consumer family,同时没有夸大成整个 shared-authority migration 已完成。
改动思路
核心边界是对的:read_report_todo_source 把 promotion fence 作为唯一模式开关。只有 canonical read 返回 None(尚未 promote)时才允许解析 Markdown;一旦已 promote,空 canonical state 仍然是权威空状态,provider unavailable 则直接传播,不能偷偷退回 display。
frontier 与 project-progress 共用同一次完整、已评估快照;report-specific 的 outcome/next-action 排序及 approval retry 选择进入 periodic_report_progress.ts。Python 保留 registry/runtime-root、provider IO、渲染和冻结 attempt 的 effect 边界,没有再建立第二套 Todo transition authority。这个拆分与仓库当前“typed decision、host effect adapter”的方向一致。
具体改动
todo_source.py复用read_canonical_todos_if_promoted与canonical_todo_summary_fields,显式传递 runtime root、rollout evidence 与 available capabilities;unpromoted legacy Goal 仍走原 Markdown adapter。project_progress_snapshot.py把完整 Todo snapshot 送入 TypeScript selector。selector 使用明确的 status/action/task-class/Agent 字段与 offset-aware microsecond timestamp,排除无 owner、future、monitor 和 report-maintenance 项,并保留 reporter-first 排序。post_writeback_hook.py让 frontier 与 progress 从同一 read 得到,避免两个观察时刻混合。pending_intent.py从共享 source 读取 retained User decisions,再由 typed selector 做 exact scope、exact Agent、reject/cancel 与真实时间排序;durable retry revision 仍使用原始todo_id:updated_at字节,没有迁移既有 attempt key。- 当前 exact head 上,本地运行了扩展 periodic-report Python 套件 280 项、TS selector 14 项和 provider conformance,全部通过;Ruff、
git diff --check、control-plane typecheck 与当前origin/mainmerge-tree 也通过。远端 CI 不作为本次 review 证据。
对主干的风险
我没有发现 blocking finding。重点负向路径均为 fail-closed:missing/stale/malformed display 不影响 promoted provider;空 authority 不复活 Markdown;provider unavailable 不被误判为空或 legacy;foreign scope/Agent、approval outcome、malformed time 和 duplicate Todo identity 不会触发 retry。
剩余风险有两个:第一,我本地没有重跑 PostgreSQL provider,当前独立证据覆盖 File/SQLite、public CLI 与 conformance;第二,该分支当前仍是 BEHIND,因此批准代码不等于 merge-ready,合并前仍要更新基线并重新执行 exact-head readiness。当前 main 的结构化 merge-tree 无冲突。
我的整体评价
这是一个比例合适、边界完整的 authority-consumer 修复。它删除了分散的 source resolution / Python sorting 知识,复用 canonical summary,并把 report-specific 决策放到一个 typed owner;没有借机增加 provider、subscription、permission、delivery 或新持久化状态。未来向前看的 refactor pass 已经体现在共享 source 与 selector 中,没有必要再为这一批引入更宽的框架。
结论:对 exact head d1dcf38dd889a90b60e1652e90020ea9646ce795 无阻塞问题,批准;merge readiness 仍由更新后的 head、required checks 与独立合并门禁决定。
English verdict: APPROVE - The exact head closes the promoted periodic-report authority gap with one canonical-first source and typed report selection; local positive and fail-closed evidence passed, while rebase/readiness and PostgreSQL-specific validation remain separate residual risks.
Goal And Delivered Outcome
After Goal promotion, periodic-report staging, live editorial fallback and approval retry still read Markdown. A missing or stale display could hide canonical completions, revive removed work or lose a retained rejection. These consumers now share a canonical-first read, and report selection/retry ordering lives in TypeScript.
Related to #4574 and the shared-authority T3/L5 consumer work. Base:
main. Missing/stale/malformed/empty display regressions reproduce against the immutable old implementation and pass on this branch.Scope And Continuation
Complete within the report consumer family:
periodic_reportcapability owns the typed selector. It reuses Todo resume/acceptance evaluation and timestamp decoding; Python retains IO, rendering and publication-history filtering.No provider-default, subscription, permission or publication-cursor change. Remaining caller/effect fences, full display recovery, contributor-owned SQLite durability (#4224), capture/whole-Goal migration and default onboarding remain in the existing RFC program. The conditional 5–8 further-package estimate is retained; this PR closes one consumer family, not that whole program. English/Chinese TS checkpoints and shared-authority checkpoint are updated.
The related refactor removes separate source resolution/parsing and Python selection/sorting loops. Runtime Python is approximately flat in net lines because the shared source adapter replaces duplicated rules; no bulk Python-retirement claim.
Validation
d1dcf38dd889a90b60e1652e90020ea9646ce795.npm run test:control-plane: 2,523 passed, zero failures; real isolated PostgreSQL 16 store enabled. One optional service integration skipped in that invocation passed separately against another isolated database before the unrelated rebase.154f71a6. Source and provider heads remain unchanged. No deployed PostgreSQL CLI-routing or promotion claim.canary premergepassed all 19 selected checks with zero failures.An earlier broad TS run failed the SQLite capacity child while source edits were concurrent. With source frozen, its standalone six checks and the final full suite passed. No budget or test was weakened. The private three-arm harness initially omitted a required File-store constructor argument; correcting that harness produced the passing comparison above.
Coverage is bounded to the changed report consumers and shared evaluation seam. Long-running SQLite soak, full default cutover and PostgreSQL deployment are not qualified by these checks.
Frontend / Visual Evidence
UI impact: none. Report templates, configuration editors, layouts and delivery actions are unchanged; this fixes their existing fact-source path. Actual CLI and editorial-request readback cover the affected interaction. No screenshot or packaged frontend rebuild is applicable.
Type of Change
LoopX Area
Technical Direction
Shared Goal Authority and TypeScript migration: existing T3/L5 acceptance, with
periodic_reportretaining capability ownership. No new capability/provider abstraction.Shared-authority RFC fixture impact
loopx_coordination_production_scale_fixture_v0; bounded conformance cases add mixed-offset completions and retained archived report rejection to native/imported graphs.Boundary Checklist