Skip to content

fix(authority): recover canonical Todo projection during refresh - #4961

Merged
huangruiteng merged 6 commits into
mainfrom
codex/authority-projection-delivery-0924
Sep 24, 2026
Merged

huangruiteng merged 6 commits into
mainfrom
codex/authority-projection-delivery-0924

Conversation

@huangruiteng

Copy link
Copy Markdown
Collaborator

Problem and behavior

A promoted Goal can have committed canonical Todos but stale or missing Markdown. Ordinary refresh-state and same-Turn replay did not recover that display. Refresh planning read canonical Todos, but the missing-work diagnostic read Markdown again, producing either a false expansion request or a hidden empty frontier.

This closes the refresh caller's recovery gap under #4574 and the shared-authority L5/D1 / TypeScript T3 checkpoints:

  • Committed refresh and same-Turn replay reuse existing journal-backed Todo projection recovery. Display failure remains pending alongside successful refresh; recovery does not repeat Todo mutations, quota settlement or replayed run history.
  • Planning, gap diagnosis and initial rendering share a complete canonical snapshot. Durable publication still requires a fresh provider confirmation; concurrent advances are retried from the returned complete snapshot.
  • TypeScript owns latest-versus-pinned intent and the three-attempt bound through a typed confirmation. Python retains locking, rendering and durable publication. Pinned requests never silently retarget.
  • Behavior change: committed promoted refresh now repairs Todo sections. Legacy and dry-run behavior remain unchanged. Existing non-Todo narrative is preserved; missing documents recover Todo sections only.

The existing Todo projection owner is sufficient: no new capability, provider, persisted ACK, RPC method or schema version. The adjacent refactor removes Python retry policy and duplicate Markdown-based Todo diagnosis. CLI JSON/Markdown and Turn use the same boundary; no settings or packaged frontend assets change, and external-delivery authorization remains unchanged.

Validation

  • Full TypeScript control-plane suite: 2,874 passed, 24 skipped (integration opt-ins tested separately where applicable); typecheck passed.
  • Focused Python production-entrypoint, refresh/replay, planning, concurrency and projection suites: 223 passed.
  • Real isolated PostgreSQL 16.15, Node 24.21.0: authority suite 285 passed, zero skipped. An earlier run used an incompatible subprocess Python; after selecting the checkout environment, one run hit a 90-second child timeout. The isolated complete rerun passed; the earlier failures are not counted as passes.
  • Disposable File/SQLite rehearsals from an authorized read-only source snapshot verified ordinary refresh, actual CLI replay, publication failure, missing-display recovery and unchanged canonical readback. Active source state was not migrated or modified; private snapshots and logs are excluded.
  • Extended the existing 464-Todo production-scale fixture; all-provider confirmation conformance checks pinned/latest overlap and bounded retry.
  • Risk-based premerge canary: 10 selected checks passed out of 15 matched candidates; compile, maintainability and diff checks passed, no manual holds. Ruff and public-boundary scan passed.

Remaining boundary

This is the refresh recovery slice, not full L5 consumer qualification, a background drainer or a provider-default switch. Successful confirmation is a point-in-time observation; another writer may advance immediately afterward. Recovery adds durable display work and confirmation IO, with no latency-improvement claim.

Updated English/Chinese RFCs retain an estimated 5–8 cohesive delivery packages for remaining caller/executor fences, consumer qualification, SQLite D2, whole-Goal migration and default/retirement. They reconcile merged #4870/#4888/#4920 and still-open #4922/#4931, including the failing and missing D2 evidence in #4224. PostgreSQL deployment qualification remains separate. Rendering and validated import/export are not slated for indiscriminate Python deletion.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
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.

Request changes conclusion (author-owned PR; GitHub blocks formal self-review)

Reviewed exact head: fa245069c60cb10e95a615d0e7a9543e0e5faece

动机

已提升到 canonical Todo authority 的 Goal,普通 refresh-state 或同一 Turn 重放可能在业务提交成功后仍留下缺失/过期的 Markdown Todo 区。继续从 Markdown 诊断缺口会误报待办扩展,或隐藏可执行前沿。该 PR 要让刷新顺手恢复显示,而不重做 Todo 写入、quota 结算或历史事件。

改动思路

方案复用现有 provider 快照、journal-backed projection outbox 和机器区渲染,不增加第二个队列/ACK。规划阶段携带完整 canonical 快照,持久发布前重新确认 provider revision;TS 决定 pinned/latest 与三次尝试上限,Python 保留锁、渲染和发布。这个归属方向合理,pinned 不追新 head,失败保持 pending

具体改动

关键代码讲解

  • refresh_state_run 在已提交刷新和 replay 返回处调用 recover_refresh_todo_projection,并将 canonical Todo 字段传给缺口诊断;空 canonical 分组不会退回旧 Markdown。
  • project_current_canonical_todos 可复用规划快照渲染,但仍通过新的 provider readback 确认是否需要重试;旧业务提交不重放。
  • confirmProjectionReadback 给出 finish/retry 的 typed 决策;文档和 268 行 refresh 回归测试覆盖恢复、失败与重叠。

本地聚焦验证:41 个 Python 测试、7 个 TS 测试及 git diff --check 通过。没有在这些路径上复现新的代码缺陷。

对主干的风险

当前 exact head 的必需集成检查仍为红:Frontstage Pages 的 showcase catalog smoke 因 README 语句断言失败;此后 main 的 #4969 已修该 smoke,说明本分支需要吸收主干后重测。minimum-Node 检查另有 4 个 SQLite deferred-lease 用例失败(不在本 PR 改动路径),merge-gate 也失败。不能把这些失败直接归因于本补丁,但也不能把局部通过当作可合并证据。请先同步当前 main,对新 exact head 重跑必需检查;若 minimum-Node 仍红,定位并修复/隔离该 lane 后再复审。保持本 PR 的刷新、重放和 revision-overlap 回归覆盖。

我的整体评价

实现边界和已有局部证据支持这个恢复方向;本次结论仅因当前 head 的必需集成验证未闭合而请求修改,不要求增加新的恢复机制。相邻重构审视:现有 outbox 已足够,无需再抽象。新 head 与检查读回后可复审。

English verdict: REQUEST_CHANGES - At fa24506 the focused 41 Python/7 TS tests pass, but required Frontstage and minimum-Node checks remain red; sync current main and revalidate the exact head before merge.

…ction-delivery-0924

The only conflicts were the shared-authority RFC's cadence paragraphs in
English and Chinese: main replaced the older five-package estimate with the
2026-09-23 seven-boundary decomposition, while this branch recorded its own
2026-09-24 baseline reconciliation. Resolution keeps main's current
decomposition and keeps this slice's checkpoint, updated to name boundary 4
and the now-merged snapshot pagination, so neither statement is lost and the
superseded count is not restored.

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

The refreshed main's canonical snapshot conformance still built the request
readback as `{provider_revision, changed}`, while the adjusted contract decodes
`provider_revision`, `changed`, `attempt` and `target`, so the two cases that
exercise the projection confirmation failed on a decode error instead of the
expected `canonical_snapshot_changed` rejection. The shipped producer and both
TypeScript entrypoints already send the typed shape, so the conformance request
is updated to it and the pagination reference names the typed fields.

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)

Reviewed exact head bb940c3fcd8991c5ffb273fc81817333cbf74a6f against base ed2fa2ee24c612144dfea50d5e4373eb672aed89.

动机

上一轮评审在 fa245069c 上的结论不是新的代码缺陷,而是必需集成验证未闭合:当前 head 的 Frontstage Pages showcase catalog smoke 为红(main 的 #4969 已修该 smoke),minimum-Node lane 另有 4 个 SQLite deferred-lease 用例失败,merge-gate 随之失败。本轮要做的就是把分支同步到当前 main、对新 exact head 重跑必需检查,并在同步后处理真实的集成差异。PR 的目标不变:已提交的普通 refresh-state 与同 Turn 重放要顺手恢复缺失/过期的 Markdown Todo 区,而不重做 Todo 写入、quota 结算或历史事件。

改动思路

本轮没有新增恢复机制,只做「同步 + 集成对齐」。同步后的唯一真实差异是跨 PR 契约:main 的 canonical snapshot conformance(来自已合并的一致性分页工作)仍用两字段 {provider_revision, changed} 构造 projection_readback,而本 PR 已把该读回收紧为带 attempt / target 的 typed confirmation;产品侧 Python producer 与两个 TypeScript 入口都已经是四字段形状,因此把 conformance 请求对齐到 typed 形状,而不是放宽解码器去猜调用方意图(默认 latest 会静默重定向一个 pinned 请求)。

具体改动

  • 合入当前 main(69 个提交)。冲突只有双语 RFC 的「节奏/边界」段落:保留 main 的 2026-09-23「七个明确 PR 边界」分解,同时保留本 PR 的 2026-09-24 基线核对,改写为指向表中第 4 项(投影恢复与客户端闭合)、并把已合并的 #4922 记为已合并,不再恢复被取代的「5–8 个包」表述。
  • 集成修复:tests/control_plane_ts/canonical_snapshot_conformance.ts 的两处请求补上 typed 读回(attempt: 1, target: "latest"),使「continuation 绑定 query/Goal/incarnation/revision」与「projection confirmation 属于同一 snapshot」两个用例重新走到预期的 canonical_snapshot_changed 判定,而不是在解码处抛错。
  • 文档:docs/reference/canonical-snapshot-pagination.md 说明 projection_readback 的四个 typed 字段及其 pinned/latest 意图与尝试预算含义。
  • 未改动任何产品语义、持久格式、CLI/Lark 入口或打包前端资源;本 PR 的 Python/TS 产品代码与上一轮 head 相同。

对主干的风险

上一轮的两条红都可解释且已在本机闭合:Frontstage showcase catalog smoke 随 main #4969 合并后通过;minimum-Node lane 在精确匹配 CI 的 pinned Node 22.22.3(LOOPX_TEST_REQUIRE_SQLITE_QUALIFIED=1)下 14/14 通过,说明 main 抬高 Node 下限到 WAL-fixed SQLite runtime 后该 lane 已恢复。真实隔离 PostgreSQL 16.15 上:provider conformance 292/292、ladder 行 s2b.postgresql_conformance_live pass=1 fail=0、service admission 10/10(全新 service 数据库,含要求的 authorized-tenant/restored-incarnation 断言)。

完整 TypeScript 套件在本机为 3264/3277,13 项失败均已逐条归因,无一项指向本 diff:11 项来自 todo_continuation.test.ts 写死 python3(本机是 Python 3.9,CI 会准备 3.11),1 项来自复用旧 PostgreSQL service 数据库(重建数据库后 10/10),1 项 sqlite_capacity 的 capacity rehearsal 在未修改的 origin/main 上以相同方式失败。本轮仍按本 Goal 的 wait_for_ci=false 未等待远端 CI。change-quality receipt:cqr_aaf211d3e1a02f88dffddecision=pass)。

语义与边界

行为变更范围与上一轮一致:只有已提交的 promoted refresh 会修复 Todo 区,legacy 与 dry-run 不变,非 Todo 叙述保留,缺失文档只恢复 Todo 区;展示失败保持 pending 与成功刷新并存,恢复不重放业务提交。相邻重构审视:现有 projection outbox 已足够,本轮不需要新的抽象。

我的整体评价

APPROVE:请求修改的唯一原因是同步与必需验证未闭合,本 head 合入当前 main 后,两条红分别由上游修复与同步后的重跑闭合,并顺带修掉了同步暴露出的真实跨 PR 契约差异(conformance 仍用旧的两字段读回)。改动仍是单主题、可回滚,未扩大 PR 声明的交付边界。

English verdict: APPROVE - exact head bb940c3fcd8991c5ffb273fc81817333cbf74a6f merges current main, resolves the bilingual RFC cadence conflict without restoring the superseded estimate, aligns the canonical snapshot conformance request with the typed projection_readback the shipped producer already sends, and closes the previously red required checks: Frontstage showcase smoke passes, the pinned minimum-Node lane is 14/14, real isolated PostgreSQL 16.15 gives 292/292 conformance, ladder pass=1/fail=0 and 10/10 service admission; the 13 local full-suite failures are attributed to host Python 3.9, a reused service database and one pre-existing origin/main capacity rehearsal failure. Receipt cqr_aaf211d3e1a02f88dffd.

@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)

Reviewed exact head 80b7f6bf8de37e5286f1f189dcc9c59814b4c482 against base b2ddbd5f6fe7318de756a3a10d428168a116251f.

动机

上一轮评审在 fa245069c 上请求修改的原因不是新的代码缺陷,而是必需集成验证未闭合:Frontstage Pages showcase catalog smoke 为红(main 的 #4969 已修),minimum-Node lane 另有 4 个 SQLite deferred-lease 用例失败。本轮把分支同步到当前 main 并对新 exact head 重跑必需检查,同时处理同步暴露出的真实跨 PR 契约差异。PR 目标不变:已提交的普通 refresh-state 与同 Turn 重放恢复缺失/过期的 Markdown Todo 区,而不重做 Todo 写入、quota 结算或历史事件。

改动思路

不新增恢复机制,只做「同步 + 集成对齐」。同步后的唯一真实差异是跨 PR 契约:main 的一致性分页 conformance 仍用两字段 {provider_revision, changed} 构造 projection_readback,而本 PR 已把它收紧为带 attempt / target 的 typed confirmation,产品侧 Python producer 与两个 TypeScript 入口都已是四字段形状。因此对齐 conformance 请求,而不是放宽解码器去猜调用方意图——把缺失的 target 默认成 latest 会静默重定向一个 pinned 请求。

具体改动

  • 合入当前 main 两次(先 69 个提交到一致性分页与 Node 下限抬升之后的 head,再 b2ddbd5f6#4898 shadow-management 与 #4944 goal-instance M2)。第二次为无冲突自动合并。
  • 唯一冲突在双语 RFC 的「节奏/边界」段落:保留 main 的 2026-09-23「七个明确 PR 边界」分解,同时保留本 PR 的 2026-09-24 基线核对,改写为指向表中第 4 项(投影恢复与客户端闭合),并把已合并的 #4922 记为已合并,不恢复被取代的「5–8 个包」表述。
  • 集成修复:tests/control_plane_ts/canonical_snapshot_conformance.ts 的两处请求补上 typed 读回(attempt: 1, target: "latest"),使「continuation 绑定 query/Goal/incarnation/revision」与「projection confirmation 属于同一 snapshot」回到预期的 canonical_snapshot_changed 判定,而不是在解码处抛错。
  • 文档:docs/reference/canonical-snapshot-pagination.md 说明 projection_readback 的四个 typed 字段及其 pinned/latest 意图与尝试预算。
  • 未改动产品语义、持久格式、CLI/Lark 入口或打包前端资源;本 PR 的 Python/TS 产品代码与上一轮 head 相同。

对主干的风险

上一轮的两条红都已在同步后的 head 上闭合:Frontstage showcase catalog smoke 通过;minimum-Node lane 在精确匹配 CI 的 pinned Node 22.22.3(LOOPX_TEST_REQUIRE_SQLITE_QUALIFIED=1)下 14/14 通过,说明 main 抬高 Node 下限到 WAL-fixed SQLite runtime 后该 lane 已恢复;merge-gate 依赖的其余必需分片在本轮重跑中亦无失败。

真实隔离 PostgreSQL 16.15:provider conformance 292/292、ladder 行 s2b.postgresql_conformance_live pass=1 fail=0、service admission 10/10(全新 service 数据库,含要求的 authorized-tenant/restored-incarnation 断言)。本 head 另行通过:typecheck:control-plane;刷新/投影相关 Python 聚焦套件 114 用例;docs-governance-smokeloopx canary premerge 19 项全通过。

本轮早先 head 的完整 TypeScript 套件为 3264/3277,13 项失败已逐条归因且无一项指向本 diff:11 项来自 todo_continuation.test.ts 写死 python3(本机是 Python 3.9,CI 准备 3.11),1 项来自复用旧 PostgreSQL service 数据库(重建后 10/10),1 项 sqlite_capacity rehearsal 在未修改的 origin/main 上以相同方式失败。仍按本 Goal 的 wait_for_ci=false 未等待远端 CI。change-quality receipt:cqr_1c40e5d096de870a6b4adecision=pass)。

语义与边界

行为变更范围未变:只有已提交的 promoted refresh 修复 Todo 区,legacy 与 dry-run 不变,非 Todo 叙述保留,缺失文档只恢复 Todo 区;展示失败保持 pending 与成功刷新并存,恢复不重放业务提交。相邻重构审视:现有 projection outbox 已足够,本轮不需要新抽象。

我的整体评价

APPROVE:请求修改的唯一原因是同步与必需验证未闭合;本 head 合入当前 main 后两条红分别由上游修复与重跑闭合,并修掉了同步暴露的真实跨 PR 契约差异(conformance 仍用两字段读回)。改动单主题、可回滚,未扩大 PR 声明的交付边界。

English verdict: APPROVE - exact head 80b7f6bf8de37e5286f1f189dcc9c59814b4c482 merges current main (including #4898/#4944), resolves the bilingual RFC cadence conflict without restoring the superseded estimate, aligns the canonical snapshot conformance request with the typed projection_readback the shipped producer sends, and closes the previously red required checks: Frontstage showcase smoke passes, the pinned minimum-Node lane is 14/14, real isolated PostgreSQL 16.15 gives 292/292 conformance, ladder pass=1/fail=0 and 10/10 service admission, with typecheck, 114 focused Python cases, docs governance and the 19-check canary green. Receipt cqr_1c40e5d096de870a6b4a.

@huangruiteng
huangruiteng merged commit 0fd40cd into main Sep 24, 2026
5 checks passed
@huangruiteng
huangruiteng deleted the codex/authority-projection-delivery-0924 branch September 24, 2026 06:19
@huangruiteng

Copy link
Copy Markdown
Collaborator Author

Self-repair and merged decision record (admin-bypass merge, maintainer-authorized).

  • Requested change addressed: the review on fa245069c did not find a new code defect; it blocked because the head's required integration checks were red (Frontstage Pages showcase catalog smoke, and a minimum-Node lane with four SQLite deferred-lease failures, which also failed the merge gate). This head syncs current main and revalidates it, and repairs the one real cross-PR contract difference the sync exposed.
  • Exact head reviewed and merged: 80b7f6bf8de37e5286f1f189dcc9c59814b4c482; merge commit on main: 0fd40cd759163c78b71b32eb959db2163bb75d8c.
  • Before the merge, loopx pr-review --check-merge-readiness 4961@80b7f6bf8... returned ready=true with no blocking reasons, using the author-owned exact-head review published above.
  • git diff 80b7f6bf8... 0fd40cd75 is empty: the merged main tree is byte-identical to the head that was validated.

Repair content:

  • Merged current main twice: first the 69-commit advance (which already carried the showcase-smoke repair from test: remove stale README copy checks from showcase catalog smoke #4969 and the Node minimum reach WAL-fixed SQLite runtime from fix: raise Node minimum to the WAL-fixed SQLite runtime #4960), then b2ddbd5f6 (test(coordination): pin the aliased-root contract across both readers and the ladder #4898 shadow-management, feat(goals): add source-session lifetime transaction #4944 goal-instance M2), which merged without conflicts.
  • The only conflict was the shared-authority RFC's cadence paragraph in both languages. Resolution keeps main's 2026-09-23 seven-boundary decomposition and keeps this branch's 2026-09-24 baseline reconciliation, rewritten to point at table row 4 (projection recovery and client closure) and to record the now-merged snapshot pagination, so the superseded "5-8 packages" estimate is not restored.
  • Integration repair: main's canonical snapshot conformance still built projection_readback as the older two-field {provider_revision, changed}, while this branch tightened the typed confirmation to provider_revision, changed, attempt, target — a shape the shipped Python producer and both TypeScript entrypoints already send. The conformance request now uses the typed shape, so those two cases reach the expected canonical_snapshot_changed rejection instead of failing in the decoder. The pagination reference now names the typed fields and their pinned/latest intent.
  • No product semantics, persisted format, CLI/Lark entry point or packaged frontend asset changed in this round.

Validation at the merged head:

  • Passed: the previously red Frontstage showcase-catalog-smoke; the exact required minimum-Node lane on pinned Node 22.22.3 (LOOPX_TEST_REQUIRE_SQLITE_QUALIFIED=1) at 14/14; npm run typecheck:control-plane; 114 focused Python refresh/projection cases; docs-governance-smoke; and the 19-check loopx canary premerge set with zero failures.
  • Real isolated PostgreSQL 16.15: provider conformance 292/292, ladder row s2b.postgresql_conformance_live pass=1/fail=0, and the service admission suite 10/10 on a freshly created service database (including the required authorized-tenant/restored-incarnation assertion).
  • Attributed, not caused by this diff: on this turn's earlier head the full TypeScript suite was 3264/3277; 11 failures came from todo_continuation.test.ts spawning the host's Python 3.9, one from reusing an existing PostgreSQL service database (fresh rerun 10/10), and sqlite_capacity's rehearsal fails identically on unmodified origin/main on this host.
  • Not awaited: remote CI, per this Goal's wait_for_ci=false and the maintainer's instruction for this run.
  • Change-quality receipt: cqr_1c40e5d096de870a6b4a (decision=pass).
  • Carried limits: the delivered behavior change is limited to committed promoted refresh repairing Todo sections (legacy and dry-run unchanged); consumers that relied on refresh leaving a stale Todo section alone must treat that as changed. Native Windows lifecycle and signed desktop release lanes remain CI/release qualifications and were not executed here.

huangruiteng added a commit that referenced this pull request Sep 24, 2026
…readmodel-0924

Two conflicts. The effect-runtime handler registry conflicted on imports
only, so both sides keep their handlers. The shared-authority RFC conflicted
on the delivery-count checkpoint: main carries the 2026-09-23 seven-boundary
decomposition while this branch recorded its own dependency reconciliation.
Resolution keeps main's decomposition, updates the reconciliation with the
now-merged #4922/#4960/#4961 and the still-in-review #4931, and states that the
estimate is updated after the combined head is accepted instead of restoring
the superseded five-to-eight package range.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
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