Skip to content

fix(turn): fence journal commits by GoalRef - #5324

Merged
huangruiteng merged 2 commits into
mainfrom
codex/goal-instance-turn-journal
Sep 30, 2026
Merged

huangruiteng merged 2 commits into
mainfrom
codex/goal-instance-turn-journal

Conversation

@Duang777

Copy link
Copy Markdown
Collaborator

Summary

  • classify Turn journals as legacy, exact GoalRef, or invalid without changing loopx_turn_journal_v0
  • hand the source alias guard from Python to the TypeScript journal owner so every source journal mutation validates the current exact GoalRef and writes atomically
  • preserve legacy RPC shape and bytes, add ABA/replay/expired-handoff coverage, and qualify only the turn_journal M3 inventory row

Verification

  • npm run -s typecheck:control-plane -- --pretty false
  • npm run -s test:control-plane (3,514 passed, 30 skipped)
  • focused TypeScript journal suite (17 passed)
  • focused Python Turn/journal/Host suites (97 passed and 50 passed)
  • architecture inventory and registry census (10 passed)
  • docs-governance-smoke.py and repository-hygiene-smoke.py
  • loopx canary premerge --from-git-diff (11 selected, 0 failures)

Mypy isolated output remains identical to the baseline: 28 existing errors in the same three touched modules, with no new-line diagnostics.

Scope

This qualifies only the Turn-journal owner. It does not remove the overall M3 activation hold or enable execution authority. PR #5278 remains open and overlaps the bilingual RFC/inventory, so those metadata edits may need conflict resolution if it lands first.

Refs #5206

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

Copy link
Copy Markdown
Collaborator Author

CI follow-up after merging current main@649826221 into this branch:

  • 25 checks passed, including all TypeScript shards, Stage 2C, Windows, dashboard acceptance, Ark 3.11/3.13, DCO, and the release build.
  • Frontstage Pages / build fails on the existing v1.2.3 Developer Book release-anchor mismatch. The same failure occurs on main run https://github.com/loopx-project/loopx/actions/runs/36610043069, and docs: synchronize 1.2.3 Developer Book release anchors #5318 contains the dedicated fix.
  • Python shards 2/3 report test_new_independent_twin_cannot_hide_behind_generated_pair plus both test_live_decision_adds_only_existing_required_read_channel cases. All three failures reproduce unchanged in a clean detached worktree at origin/main@649826221; none of their test or implementation files differ in this PR.

I have not folded these unrelated baseline repairs into #5324. The branch is clean and mergeable; review is still required. No merge was attempted.

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

结论:APPROVE。评审完整 base-to-head diff,exact head 9b3873f7e64b28d6c39871de19836d05e614d8d2;本次 journal 提交隔离已独立验证,没有发现阻塞问题。这是 #5206 的 M3 journal 增量,不是整个 source-session profile 已可启用的结论。

动机

同一个 Goal alias 被替换为新实例后,旧 Turn 的结果不应继续推进旧 journal,更不应拿旧身份结算。只在 Host 启动或返回时检查一次不够:验证、恢复和后续 checkpoint 期间仍可能切换实例。本 PR 将保护落实到每次实际 journal 写入,解决可复现的 A→B 期间旧 A 继续提交问题。

改动思路

复用既有 source alias guard 和 TypeScript require_current 决策,Python 只在持有 guard 时传递当前 authority 与锁见证,TS 写入 owner 验证后再获得 journal lock、执行原单调状态转换和原子写入。guard 持续覆盖提交,不把 plan 中的 GoalRef、锁 token 或 profile 名称当成新授权。全部 checkpoint 归入同一 persist_journal 回调,减少原先分散的特殊包装;legacy journal 保持原 wire 与只读历史检查能力。

具体改动

关键代码讲解

  • parseTurnJournalGoalBinding:将无引用、完整 exact 引用、不完整/不一致引用分为 typed legacy/exact/invalid。plan 和 transaction 的两份引用必须一致,不用文本包含规则推断实例身份。
  • source_journal_admission:在现有跨运行时 alias guard 中读取规范 authority,并交出一次内部锁见证。它不写入 journal、不授予 peer/session 权限,非 source 路径返回原 legacy 行为。
  • commitTurnJournal:exact journal 必须提供匹配的 admission、registry/GoalRef 和有效活锁见证,再调用已有 require_current。随后沿用 journal 的不可变 plan、checkpoint 顺序和原子提交规则;旧 A 或错误见证不能改写 A/B journal。
  • persist_journal:初始提交、Host 尝试、验证、失败、恢复和结算 checkpoint 共用此路径。source 拒绝转换为现有 runtime rejection,避免只保护 happy path 或另建 Python 决策源。

本人用同一脚本在 merge-base 649826221289cd4cb3dd8880d016e0afbbaca0fc 与本 head 执行实际 Turn executor→managed TS RPC→File journal/跨运行时锁。6 个场景涵盖 legacy/current-source 完成与重跑、Host 前/过程中/验证时换实例、source 缺少引用;完整归一化结果除目标修复场景外保持一致。关键反例中 base 在验证后错误提交旧 A 并结算;head 拒绝 stale A,原 journal 字节不变、旧 A 无 writeback/spend/scheduler,新 B 随后成功提交。Host 与业务结算回调使用合成实现;journal 提交和锁不是 mock,因此证据证明提交边界而非真实模型或外部业务效果。

对主干的风险

新增严格条件只服务已有 source-session 精确绑定:缺失/错误 GoalRef 或失效 guard 会拒绝;legacy 的完整执行、持久 JSON 与重复调用均做了 base/head 对照,未被迫升级。运行时 RPC 是同包边界,持久 loopx_turn_journal_v0 仍须保留兼容;新 admission 是瞬时提交输入,不能充当可重放授权。没有新增用户确认步骤、CLI 开关或 UI 编辑器;历史 inspect/恢复入口通过 companion 测试。

语义与 CI 对齐

本人本地验证:171 项 Python、48 项 TS、typecheck 通过,canary 全部选定检查及 5 项直接检查通过。包括真实 File/managed TS admission、单调 checkpoint、不可变 plan、失败恢复、历史读取和 CLI companion 路径。相关 #5278 的 handoff owner 已合并;本 PR 没有借此宣称其他 inventory 行或完整 M3/M4/M5 都已完成。未拉取或等待远端 CI;也未改预算、放松既有检查。此次不涉及 PostgreSQL authority store 重构,未以 mock 替代受影响的真实 journal 后端。

我的整体评价

增量边界合理:关闭一个完整的 journal commit/recovery 缺口,保留现有 RFC/issue 中整体激活仍待验证的阶段。未来维护性检查已应用在统一提交回调和复用 typed owner 上,下一次 checkpoint 规则修改无需再寻找分散的 admission 包装;更大的 executor 重构不属于这次必要范围。拒绝旧 A 之后已验证新 B 恢复有用推进,不只停留在 blocker 回执。批准本 exact head 的增量,整体 profile 启用及合并由各自 owner 判断,不自合并控制面代码。

English verdict: APPROVE — exact head 9b3873f. Real managed-TS/File journal counterexamples verify per-commit GoalRef fencing, legacy parity and recovery to a fresh instance. This qualifies the bounded M3 journal slice, not overall source-session activation.

@huangruiteng
huangruiteng merged commit 0731177 into main Sep 30, 2026
31 of 36 checks passed
@huangruiteng
huangruiteng deleted the codex/goal-instance-turn-journal branch September 30, 2026 03:12
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