Skip to content

fix(todos): scope Monitor completion replay by cycle - #4916

Merged
huangruiteng merged 5 commits into
loopx-project:mainfrom
Duang777:codex/core-correctness-20260923-b
Sep 23, 2026
Merged

huangruiteng merged 5 commits into
loopx-project:mainfrom
Duang777:codex/core-correctness-20260923-b

Conversation

@Duang777

@Duang777 Duang777 commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Problem and result

An unkeyed continuous_monitor completion reused one permanent Goal/Todo operation id. After the Monitor reopened, a new completion could replay an earlier success while leaving the current Todo open. The TypeScript terminal authority now derives that operation id from the authoritative material_change_generation, so retries within one cycle replay and later cycles complete independently.

Implementation

  • Use one terminal request schema (v3) for complete and supersede. operation_identity is a discriminated union: {kind: "explicit", operation_id: "..."} or {kind: "current_monitor_cycle"}. The latter is valid only for unkeyed Monitor completion.
  • Retire the v0/v1/v2 terminal request decoders and nullable top-level operation id convention. Python and the managed TypeScript runtime ship together; mismatched requests fail before provider access. Existing stored Chat proposals continue through their existing public action adapters.
  • Keep operation ids, persisted receipt schemas and request fingerprints stable for named operations. Historical recovery does not require preserving old request decoders.
  • Read the Monitor generation from canonical authority and recheck it around receipt recovery. Never infer cycle membership from an old unscoped receipt. If a named operation already completed this cycle, create a generation-scoped no_change receipt.
  • Reuse one TypeScript terminal transaction and one intent decoder, including the combined User edit/completion caller. Migrate callers and conformance fixtures; update the English and Chinese contract docs.

The protocol simplification removes a net 40 production lines relative to the earlier PR implementation. No provider defaults, storage formats, promotion or permissions change. No frontend configuration or UI change is required: CLI and Chat still use the same public completion actions; the changed envelope is internal to the packaged adapter/runtime.

Validation

  • File/SQLite authority and affected runtime tests: 405 cases covered; after correcting a test registry witness, the 44 runtime/decoder cases passed on rerun. The final strict-identity decoder suite passed all 9 cases.
  • Real isolated PostgreSQL 16.15 authority integration: 285 passed, zero skips; disposable server stopped afterward.
  • Python authority, reviewed Chat terminal actions, User completion and combined update coverage: 93 passed in the initial run; the one test-instrumentation failure was corrected and passed alongside 4 new File/SQLite identity-mode cases (5 passed). Coverage includes packaged Chat HTTP recovery.
  • Cross-version real-store rehearsal: receipts generated by 3ac56718f for complete/supersede were recovered unchanged by the new implementation on both File and SQLite, without changing the authority head.
  • TypeScript typecheck, focused Ruff, repository hygiene and diff checks passed.
  • Docs governance remains failing on an unchanged main baseline: automatic-execution-admission-v0.md lacks the checker-required semantic mirror text. Confirmed the same failure condition in origin/main; this PR does not modify that RFC.

Fresh CI and maintainer review apply to the updated head. This PR is not merged.

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
@Duang777
Duang777 force-pushed the codex/core-correctness-20260923-b branch from 87a7580 to 3a6af7b Compare September 23, 2026 02:17
@huangruiteng

Copy link
Copy Markdown
Collaborator

在 exact head 3a6af7b79ed76bd0cdaaa721a000955a212f770b 上复现一个跨周期 legacy replay 问题(先发布可操作发现;全 PR 结论仍待完整审查):

  1. 在 File/SQLite 实存储中,用既有 production-scale Monitor fixture:重开到 generation 5,以旧版 unscoped operation ID 完成;再重开到 generation 6,以显式 operation ID 完成。
  2. 当前 Todo 已经是 generation 6 的 done。此时用 v3/null operation ID 隐式重试,observeImplicitMonitorCompletion 在当前周期没有 v1 receipt 时继续查永久的 legacy unscoped receipt;只验证当前 Todo 仍为 done 且 generation 未在两次读之间变化,就返回 generation 5 的 receipt。
  3. 我在现有 conformance 中临时添加同一反例并分别以 node --no-warnings --experimental-sqlite --experimental-strip-types --test --test-name-pattern="implicit retry after a later explicit cycle" tests/control_plane_ts/authority_store.test.ts... tests/control_plane_ts/sqlite_authority_store.test.ts 运行,两者均失败:实际 original_receipt.operation_id 等于旧周期 ID todo-terminal:71e47944f1eae53cea6c90c751a88dbd

这不是旧周期未重开时的合法恢复;新周期已经通过另一具名请求完成。请把 legacy fallback 绑定到它所属的周期/可验证的完成 lineage,或在无法证明时停止恢复旧 receipt;补上 File/SQLite 的“旧 legacy → 新周期显式完成 → v3 隐式重试”负例。现有测试只覆盖旧周期刚完成时的恢复,以及新周期继续由 v3 完成的路径,因此没有击中这个交叉路径。

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
@Duang777

Copy link
Copy Markdown
Contributor Author

已在 3ac56718f 修复。这里选择在无法证明 lineage 时停止 v3 的 legacy 恢复:

  • 删除 v3/null 对永久 legacy unscoped operation ID 的 fallback;v3 只查询当前 material_change_generation 推导出的 receipt。
  • 当前 generation 已被显式 operation 完成、但没有 generation receipt 时,v3 写入该 generation 的 no_change receipt;后续 v3 重试只 replay 这张 receipt。
  • v2 仍可携带原 operation ID 恢复 legacy receipt,兼容边界未删除。

已补 File 和 SQLite 同一反例:旧 legacy 完成 -> 重开新 generation -> 显式完成 -> v3/null 重试。修复前两者都 replay 旧 receipt;修复后均返回 generation-scoped no_change,再次重试 replay 新 receipt,且 operation ID 与 legacy、显式 receipt 都不同。

验证结果:聚焦 File/SQLite reviewer + lifecycle 用例 6 passed,受影响 TypeScript authority/runtime 套件在 uv run --extra test581 passed,Python facade 83 passed,聚焦 Python 10 passed,typecheck、Ruff 和 premerge 19 项检查均通过。

huangruiteng
huangruiteng previously approved these changes Sep 23, 2026

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

动机

评审精确 head 3ac56718f7b4e32f2e3d42216b422f76028bf7cd。原有未指定 completion identity 的 continuous_monitor 总用 Goal/Todo 对应的永久 operation ID;Monitor 在新 material-change generation 重开后,再次完成可能重放上一周期的 receipt,返回成功但 canonical Todo 仍为 open。维护者给出的更强反例是:旧周期 legacy 完成,新周期由显式 operation 完成,再执行 v3 隐式重试。

改动思路

Python 仅为未指定 identity 的连续 Monitor 发送 v3/null operation 请求;显式 identity 和非 Monitor 仍走 v2。TypeScript terminal authority 读取 canonical material_change_generation 后推导周期 operation ID,只重放同周期 receipt;没有可证明 lineage 时不猜测旧 legacy receipt。若当前周期已由显式 operation 完成,v3 写入该周期的 no_change receipt,再次重试只重放它。v2 携带原 operation ID 的历史恢复保留。

具体改动

provider_terminal_lifecycle.py 选择版本与 nullable identity;local_authority_runtime.ts 拒绝 v3 非 null ID、supersede 和带 completion turn key 的请求;todo_terminal_lifecycle.ts 以 typed union、generation 校验、两次权威读和现有 receipt/commit 边界完成周期绑定。中英文 canonical-terminal 文档说明兼容与回滚边界;File/SQLite conformance 覆盖旧 legacy、跨周期重开、显式完成后 v3 的 no_change、race 与非 Monitor 拒绝;Python facade 覆盖真实 complete_goal_todo 和 canonical readback。

对主干的风险

新增一个 wire 版本和约 691 行净增量,主要在聚焦测试,核心语义仍留在既有 TypeScript terminal owner,没有第二个 Python 决策源。周期编号取自 canonical Todo,不依赖显示投影;v2 的具名 receipt 仍可按原 ID 恢复。当前 head 上 8 个 File/SQLite 相关实存储测试、10 个 Python facade 测试、12 个 runtime 请求测试、TypeScript typecheck 与 diff 检查通过。本评审未独立运行 PostgreSQL 服务或轮询远端 CI;这不是主干合并许可,maintainer 仍需按合并门槛确认。

我的整体评价

APPROVE(代码评审)。 上轮指出的“旧 legacy → 新周期显式完成 → v3 重试”反例得到精确修复,v3 不再把无 generation lineage 的旧 receipt 当作当前周期证明;同周期重试与 v2 历史恢复仍有回归覆盖。相关未来重构可留在 terminal owner 内,当前不需要扩出新抽象。

English verdict: APPROVE - exact head 3ac5671 scopes implicit Monitor receipts to canonical generations and no longer infers legacy lineage; focused File/SQLite, Python and request tests plus typecheck passed. Merge qualification remains separate.

@huangruiteng

Copy link
Copy Markdown
Collaborator

Exact-head readiness update for 3ac56718f7b4e32f2e3d42216b422f76028bf7cd: the existing APPROVED review is valid and there are no unresolved review threads, but loopx pr-review --check-merge-readiness reports ready=false because GitHub merge state is BEHIND (merge_state_requires_update). CI was not consulted by this readiness check.

Please update the branch against main; that will create a new head requiring a fresh exact-head review and readiness check. No merge is recommended on this head. The related future-facing pass found no additional bounded refactor needed before the branch update.

…request-4916

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

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
@huangruiteng
huangruiteng merged commit bd37525 into loopx-project:main Sep 23, 2026
8 checks passed
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.

2 participants