feat(authority): add local post-commit observation capture - #3818
Conversation
huangruiteng
left a comment
There was a problem hiding this comment.
动机
这个方向本身贴合 RFC:Stage 2C 的前半段确实需要一个默认关闭的本地 shadow,把 legacy Markdown/task-lease 的提交结果投影到 FileAuthorityStore,同时保持 legacy writer 为唯一 authority,候选失败也不能反向推翻主写。
改动思路
实现采用 post-commit observer:各 Todo/lease/handoff/migration 写路径完成后,重新读取完整本地 projection,计算 digest,再通过 TypeScript AuthorityStore 写入 file candidate;candidate 永不参与执行决策。这个边界和 default-off/failure-isolation 原则是对的。
具体改动
- 增加显式的
--local-authority-shadow-file配置与关闭入口; - 为 Todo、follow-up、task lease lifecycle、handoff mode、state migration 接入提交后观察;
- 用
operation_id + source_digest在FileAuthorityStore中保留 observation receipt; - 增加冲突重试、迁移新 lineage、provider failure 不影响主写等测试。
对主干的风险
当前实现能证明的是“某次主写之后采样到的一份完整快照,被候选持久化了”,还不能称为 parity evidence 或 Stage 2C qualification:
- observer 在主写提交后重新采样整个 source,和原事务之间没有 durable outbox/锁内 receipt 绑定。并发写可能让
source_operation=A对应到已经包含 B 的快照;进程在 commit 与 observer 之间崩溃也会丢失该 observation。RFC 文档承认了 crash gap,但 catalog 和 PR 描述仍把结果称作 parity evidence / exact durable receipt,容易让后续 promotion 错用这份证据。 - 当前没有 source-vs-candidate readback compare,也没有 parity verdict。候选返回
advanced只证明 candidate commit 成功,不证明两个 authority view 相等。 - default-off 时执行语义基本隔离,但
configure-goalsummary 与 capability catalog 仍新增了字段,因此“默认模式零可观察变化”也应收窄为“默认关闭时不执行 shadow、不改变 lifecycle 决策”。
请在合入前完成至少一种收敛:
- 若本 PR 只交付 plumbing:把标题、PR body、catalog display/consider_when 和 evidence 说明统一改成 “post-commit shadow observation/capture”,明确它不是 parity verdict,也不能单独作为 promotion evidence;最好把
source_operation改成不暗示精确事务绑定的observation_trigger,或同等清晰的语义。 - 若要保留 parity/transaction evidence 的声明:必须把 observation 绑定到主写的 durable transaction identity(outbox 或等价机制),并增加 candidate readback compare/typed parity result。
我的整体评价
架构方向正确,作为 Stage 2C 前半段的 observation foundation 有价值;但当前命名和资格声明高于实际保证,会污染后续 authority promotion 的证据链,因此先 Request changes。调整声明边界后,不要求这个 PR 一次完成 durable outbox 和完整 promotion gate。
English verdict: Request changes. The default-off post-commit observation plumbing aligns with the first half of Stage 2C, but it does not yet provide transaction-correlated shadow delivery or a source/candidate parity verdict. Reframe the contract and UI as observation capture, or add durable transaction binding plus explicit parity readback before claiming qualification evidence.
80764e8 to
422757d
Compare
|
@huangruiteng Addressed the change request:
The RFC now also disambiguates #3669's historical Stage 3 label from the current stage map. Please re-review exact head after the force-push. |
|
@huangruiteng One addition to the PR body only, no code change on head 422757d: a new section "Known Debt Carried Into the Second Half of Stage 2C" lists three measured limits of this observation slice so the parity/promotion review does not inherit them silently: full-snapshot rewrite growth (100 Todos + 200 renewals grew one candidate file to 2.79 MB and renewal latency from 0.18 s to 0.54 s), the 1.0 s observation lock on the primary write path (1 of 24 observations dropped as typed |
huangruiteng
left a comment
There was a problem hiding this comment.
Findings
[P1] --runtime-root 会把同一 Goal 的成功 observation 分裂成两个 store lineage
触发条件是 registry 的 common_runtime_root 与本次 CLI 的 --runtime-root override 不同。Todo/follow-up 路径在 local_authority_shadow_adapter.py:447-450 固定传入 runtime_root=None,因此回退到 registry root;task-lease 路径在 task_lease_acquire_adapter.py:54-57 传入调用方的 override。两边都会返回 outcome=captured,但实际写入两个不同的 store_identity:Todo store 的 head 没有刚 acquire 的 lease,lease store 又是另一条 authority history。这样一来,当前 opt-in capture 自身就无法形成一份 Goal 级完整观察;这不只是后续 parity/promotion 阶段的性能债务,而是成功证据与实际 lineage 不一致。
最小修复是让所有 post-commit writer hook 消费同一个已解析的 effective runtime root(不能一部分重新从 registry 推导、一部分沿用 CLI override),并增加真实 subprocess E2E:令 common_runtime_root != --runtime-root,依次执行 Todo add 与 task-lease acquire,断言只产生一个 store identity,且同一个 head 同时包含 Todo 和 lease。当前 head 上我独立复现到:两个调用均返回 captured,但生成两个不同 identity,Todo-side head 的 lease 数为 0、override-side head 的 lease 数为 1。
动机
这个 PR 试图补齐 Shared Goal Authority Stage 2C 的第一段产品路径:现有 Markdown Todo、handoff mode 与本地 task-lease writer 仍是唯一 canonical authority;在主写提交后,把当前完整本地 projection 以默认关闭、显式 opt-in 的方式交给 FileAuthorityStore 保存。旧行为没有可从真实 CLI writer 进入的 observation seam,因而即使 file provider 已有 conformance contract,也无法观察 Todo/lease 的实际组合状态。单独给某一个 writer 加 hook 不足以覆盖 Goal coordination 的真实写面,所以覆盖 Todo、follow-up、handoff、lease lifecycle 与 migration 是合理的最小产品边界;本 PR明确不承担 durable outbox、source/candidate compare、parity verdict、legacy writer fencing 或 authority promotion。
改动思路
入口由 configure-goal --local-authority-shadow-file 控制。Python adapter 读取闭合的 file_one_way 配置,在 primary commit 之后连续采样本地 Todo、handoff mode 与 lease projection,计算稳定 digest 和 observation id,再调用 TypeScript effect handler。TypeScript 侧只负责把 snapshot、event 与 receipt 通过 FileAuthorityStore 的 revision/CAS 合同写入 candidate;candidate 永不回流到 lifecycle 决策。正向路径是“enable -> legacy writer commit -> sample -> candidate commit -> typed captured evidence”;负向路径是 provider construction/read/commit、lock timeout 或 protocol mismatch 均降级为 failed/unavailable 等 observation evidence,已完成的 primary write不回滚。迁移路径刻意不复制旧 candidate identity,而在目标 runtime 从迁移后的 canonical state 建立新 lineage。
原 review 关于 authority 语义的 blocker 已基本解决:source_operation/operation_id 已收窄为 observation_trigger/observation_id,所有 evidence 都明确声明 source_transaction_correlated=false、durable_source_outbox=false、source_candidate_compared=false、parity_verdict=not_evaluated;RFC、CLI help 与 catalog 也不再把它称为 parity/promotion evidence。
具体改动
Exact head 422757dd9f56f2543708a35ff44c04445ad96068 相对 PR base 共 23 个文件、+2796/-34:production +1151/-27,tests +1565/-0,docs +77/-7,build/config +3/-0。生产面包括配置归一化与 catalog、Python observation adapter、TypeScript store handler、Todo/follow-up/handoff/task-lease hooks、migration seed,以及 wheel/tsconfig 打包入口;测试面覆盖配置、真实 CLI、runtime failure/retry、migration 新 lineage 和 TypeScript receipt/CAS;中英文 RFC 同步收窄了 observation 的能力边界。
关键代码讲解
observe_local_authority_commit:以 registry config 为 gate,采样并 canonicalize Goal projection,生成 digest/observation id,在 provider revision conflict 后重新采样;异常只生成 typed evidence。当前 runtime-root 分裂也发生在这个 symbol 的调用参数边界。recordLocalAuthorityShadow:TypeScript-owned candidate commit seam;校验闭合 request/projection schema,通过FileAuthorityStore做 CAS,并仅在可读回同一 observation receipt 时把 ambiguous/replay 判为已捕获。_attach_local_authority_shadow:把真实 task-lease acquire/renew/transfer/release 的 committed result 接到 observer;它传入 caller runtime root,与 Todo hook 的 registry-root 选择不一致,是本次 blocker 的另一半。seed_migrated_authority_shadows:迁移完成后从目标 canonical files 生成 fresh candidate lineage,避免复制旧 store identity/revision;失败被压缩为 public-safe migration evidence,不推翻已经完成的迁移。apply_local_authority_shadow_change/local_authority_shadow_summary:用闭合 schema 管理 enable/disable 与 readback,默认不配置时不进入 TypeScript candidate runtime。
对主干的风险
最强回归场景是用户通过受支持的全局 --runtime-root 隔离运行时:Todo 与 task-lease 都表面成功,candidate 却被拆成两个互不相干的 store。它的 blast radius 限于显式启用该实验功能的 Goal,不改变 legacy primary authority,但会让 observation consumer、后续 parity 工作或人工排障读到不完整 head;现有 evidence 没有暴露 lineage split,因此可观察性不足。修复后应以上述不同-root E2E作为回归门禁。
其余边界验证较扎实:默认关闭时没有 candidate effect 或目录,provider failure 不反转主写,SIGKILL 测试诚实展示 commit-to-observer loss window,迁移不复制旧 lineage。仍需保留的 residual risk 包括 full-snapshot history 的二次增长、1 秒 observation lock 对 opt-in 主写响应时间的影响,以及无 durable outbox 导致的单次漏采;这些已经在 PR body/RFC 中披露,可留给 Stage 2C 后半段,但不能用来豁免当前的双-lineage 正确性问题。配置 catalog/readback 在 feature disabled 时仍有加法式 schema 可见变化,因此这里证明的是 lifecycle/decision isolation,而不是整个 CLI 输出逐字节不变。
验证结果:focused Python 20 passed;TypeScript control plane 394 passed, 1 PostgreSQL integration skipped;npm run typecheck:control-plane 通过;Ruff 与 git diff --check 通过;风险型 premerge gate 18/18 通过;public-boundary scan 24 files clean。GitHub pytest/DCO/build 等通过,但 SonarCloud Quality Gate 仍为 ERROR(new reliability rating D;当前公开 API 返回 5 个 open issues),远端 merge state 仍是 BLOCKED。合入前还需要把该 check 处理到绿色或给出仓库策略认可的等价处置。
我的整体评价
这个 exact head 已正确修复上一轮最关键的“把 observation 冒充 parity/transaction evidence”问题,TypeScript/Python ownership、failure isolation、migration lineage 与文档非目标也比旧 head 清晰。代码量虽然大,但大部分来自真实 writer 覆盖和系统级负向测试,修复 single-runtime-root 以后整体 scope 可以保持在本 PR 内,不需要为了形式拆散。不过当前支持的 CLI override 会制造两个都声称 captured 的 store,因而 change proportionality 与 authority observation 的完整性尚不能通过 completion gate;结论为 Request changes。请统一 effective runtime root、补上不同-root E2E,并清理失败的 SonarCloud gate 后再复审;无需在本 PR 扩展 durable outbox 或实现 parity promotion。
English verdict: Request changes on exact head 422757dd9f56f2543708a35ff44c04445ad96068. The earlier parity/transaction overclaim is now correctly resolved, and the focused/runtime/premerge validation is strong. However, a supported --runtime-root override makes Todo and task-lease hooks write two distinct FileAuthorityStore lineages while both report captured; route every writer through one effective runtime root, add a mismatched-root subprocess E2E, and clear the failing SonarCloud quality gate before re-review.
Signed-off-by: wchwawa <wch19961116@gmail.com>
Signed-off-by: wchwawa <wch19961116@gmail.com>
Signed-off-by: wchwawa <wch19961116@gmail.com>
Signed-off-by: wchwawa <wch19961116@gmail.com>
Signed-off-by: wchwawa <wch19961116@gmail.com>
Signed-off-by: wchwawa <wch19961116@gmail.com>
loopx/todos.py sits exactly at its maintainability ceiling (2285 lines), so threading one effective runtime root through the writer hooks cannot land there without growing the module. Move the todo list projection block (filtered summaries, the Markdown/event merge, and goal_todo_summaries) into loopx/control_plane/todos/goal_todo_projection.py; list_goal_todos keeps its behaviour and delegates to the new module. Pure move: no call site outside loopx/todos.py used the moved helpers, and the todo list, thin/explicit-limit, and agent-lane projection suites are unchanged. Signed-off-by: wchwawa <wch19961116@gmail.com>
…ntime root Review finding on the previous head: with `common_runtime_root` different from the CLI `--runtime-root` override, Todo and follow-up hooks resolved the registry root while task-lease hooks used the override, so one goal produced two FileAuthorityStore lineages that both reported `captured`. The Todo-side head had no lease and the lease-side head had no Todo. - local_authority_shadow_adapter.effective_runtime_root resolves the one root of a CLI call: the override when given, else `common_runtime_root`, with a relative value anchored at the registry's project root instead of the caller's working directory. runtime_root_from_registry now anchors the same way, so lease files and observations of one goal share one root. - Todo add/update/complete/supersede/archive, follow-up capture, and handoff-mode set accept `runtime_root_arg`; the CLI passes its override through, and each writer hands the resolved root to its ownership gate, lease fence, and post-commit observation. Non-CLI callers keep the registry-root default. - E2E: a subprocess run with `common_runtime_root != --runtime-root` drives todo add, task-lease acquire, todo update, capture-followups, and a leased completion; exactly one store identity exists, the head holds both the todos and the released lease, and the registry root gains no lineage and no lease directory. A second test pins the relative-root anchoring for every hook from a foreign working directory. - SonarCloud: replace the default sort in local_authority_shadow.ts with an explicit comparator; split set_goal_handoff_mode and execute_native_task_lease_acquire into smaller helpers to bring their cognitive complexity under the limit; hoist the fixture out of the configure-goal exception test so only one call can raise. Signed-off-by: wchwawa <wch19961116@gmail.com>
422757d to
ea15267
Compare
|
@huangruiteng Round 3 on exact head
|
|
Note on the |
huangruiteng
left a comment
There was a problem hiding this comment.
详细中文评审
Exact head: ea15267fed1b0f37274931aaacc2d32be60c17a6
动机
这份 PR 补的是 Shared Goal Authority Stage 2C 的前半段:现有 Markdown Todo、handoff mode 和本地 task lease writer 仍是唯一权威,但系统需要从真实产品写路径采集一份默认关闭、显式 opt-in 的 file candidate observation,才能在后续独立阶段验证 parity、设计 durable outbox,并最终讨论 promotion。此前只有 AuthorityStore/provider 基础合同,没有覆盖 Todo、follow-up、lease lifecycle、handoff 与 migration 的真实入口;仅给一个 writer 加 hook 会得到不完整的 Goal coordination 视图,因此覆盖这些相邻写面是合理的最小产品切片。
这次复审的原始 blocker 是:--runtime-root override 与 registry common_runtime_root 不一致时,不同 writer 会把同一个 Goal 投影到两个 store lineage,同时都声称 captured。最新 head 把 effective runtime root 统一向所有 hook 传递,并用跨进程 E2E 固化了单 lineage。更早一轮关于语义过度声明的问题也保持修复:公开合同明确这是 post-commit snapshot capture,不是 source transaction receipt、parity verdict 或 promotion evidence。
改动思路
配置入口是 configure-goal --local-authority-shadow-file。Python adapter 先读取闭合的 file_one_way 配置;未配置时直接返回且不创建 lock/provider 目录。启用后,各 legacy writer 在主提交完成后使用同一个 effective runtime root,连续采样 Todo、handoff mode 与 lease,直到得到稳定的完整 projection;随后以 observation_trigger + source_digest 生成 observation identity,调用 TypeScript effect handler。TypeScript 只通过 FileAuthorityStore 做 candidate-side CAS、receipt readback 和 ambiguous outcome reconciliation,candidate 不进入任何 Todo/lease/调度决策。
正向路径是:显式启用 → legacy Todo/lease/handoff 写入成功 → 从同一 runtime root 采样完整快照 → candidate commit → 返回 typed captured/replayed evidence。负向路径是:配置非法、provider construction/read/commit 失败、1 秒 observation lock 超时、协议不匹配或进程在 source commit 后、observer 前被杀死;这些情况只返回 failed/unavailable/ambiguous_unproved 等 observation evidence,不回滚已经完成的 primary write。迁移也不会复制旧 provider identity,而是从目标端 canonical state 建立 fresh lineage。
具体改动
- 配置与公开面:
configuration_catalog.py、configure_goal.py和 registry-admin CLI 增加闭合、默认关闭的 observation 配置、preview/execute/clear 与 readback;中英文 RFC 同步声明 crash gap、无 durable outbox、无 source/candidate compare、无 promotion authority。 - Python observation owner:
local_authority_shadow_adapter.py负责配置 gate、紧凑 Todo/lease projection、稳定采样、digest/observation identity、冲突后重采样和 typed failure isolation。 - TypeScript candidate owner:
local_authority_shadow.ts通过统一 AuthorityStore contract 持久化 projection/event/receipt;operation replay 和 response-loss ambiguity 必须由 exact receipt readback 证明,不能仅凭异常猜测成功。 - 产品接线:Todo add/update/complete/supersede/archive、follow-up capture、handoff mode、task-lease acquire/renew/transfer/release 与 state migration 都在成功提交后调用 observer。
goal_todo_projection.py是从todos.py纯移动出的确定性读模型,用来守住原文件 maintainability ceiling。 - runtime-root 修复:CLI 将
runtime_root_arg传入每个 Todo/follow-up/handoff 路径;effective_runtime_root()让显式 override 优先,否则将相对common_runtime_root锚定到 registry project root。lease fence、quiescence scan 与 observation 因而共享一条 root。
关键代码讲解
effective_runtime_root()是这次复审最关键的身份边界:同一 CLI 调用的 writer、lease fence 和 observer 都消费同一个已解析 Path,避免再次从 cwd 或 registry 产生第二 lineage。observe_local_authority_commit()只在 opt-in 后采样;observation_trigger被明确标为诊断上下文,快照可以包含 trigger 后并发落地的提交。它在 revision conflict 后重新采样,不用旧 projection 重试,也始终输出source_transaction_correlated=false、durable_source_outbox=false、parity_verdict=not_evaluated。recordLocalAuthorityShadow()是唯一 candidate commit seam:先验证 request/projection/goal identity,再用 store revision CAS 提交;operation_id_exists与 ambiguous result 都要读回匹配 receipt,缺失或不匹配则 fail closed。set_goal_handoff_mode()与 Todo/task-lease 调用链把同一 effective root同时用于 quiescence/lease 检查和 post-commit capture;因此 snapshot 中的 Todo 与 lease 不再来自不同运行目录。seed_migrated_authority_shadows()在迁移完成后从目标 canonical state 重建 observation,旧 candidate directory/store identity 不会被复制到新 runtime root。
对主干的风险
我没有发现最新 exact head 上仍然存在的代码 blocker。上轮双-lineage 问题已由真实 subprocess E2E覆盖:common_runtime_root != --runtime-root 时依次执行 Todo add、lease acquire、Todo update、follow-up capture 和带 lease completion,五个结果拥有同一 store_identity,同一 head 同时包含两个 Todo 与 released lease,registry root 不产生 shadow 或 lease 目录。相对路径从 foreign cwd 运行时也固定锚定 registry project root。
default-off counterfactual 已验证:相同 legacy writer 在未配置时不调用 Effect runtime、不创建 candidate/lock,Todo/lease lifecycle 结果保持原权威;启用后的 candidate failure 也不改变 primary commit。SIGKILL E2E 诚实证明 commit-to-observer loss window,后续一次完整 snapshot 能恢复当前 head,但不能补造丢失的 source transaction receipt。命名与实际 authority 对齐:这是本地 observation candidate,不是 peer agent、shared authority 或 parity owner;typed evidence 也明确区分 advisory observation 与未来 machine-enforced promotion gate。
残余风险仍包括 PR 已披露的 full-snapshot/history 二次增长、1 秒 observation lock 对 opt-in writer latency 的影响,以及没有 durable outbox 时的单次漏采。这些会阻止后续 parity/promotion,但不否定当前明确限定为 best-effort observation foundation 的价值。规模为 28 files、+3489/-344,其中 production +1673/-337、tests +1736、docs +77/-7;测试量与跨多个真实 writer/failure seam 相称,且没有在当前 PR 引入 read authority、promotion CLI 或第二套语义 reducer,整体 proportionality 可接受。
独立验证:focused Python/真实 CLI/migration suite 22 passed;TypeScript control plane 463 passed, 1 个显式 PostgreSQL live integration skipped;npm run typecheck:control-plane、changed-file Ruff、git diff --check 通过。远端 exact head 的 DCO、dependency review、pytest、Windows、release build 与 SonarCloud Code Analysis 均成功。直接对文件运行 mypy 会递归进入当前主干并报告数千条既有错误,不是可归因的本 PR 信号;我没有把它计作通过或回归。当前 GitHub mergeStateStatus=DIRTY,合并前仍需基于最新 main 解冲突并保持 head 上述验证,但这不是当前 diff 的行为 blocker。
我的整体评价
结论是 APPROVE。最新 head 同时解决了两轮核心问题:observation 不再冒充 transaction/parity evidence;所有产品 writer 也不再因为 runtime-root 解析分裂 candidate lineage。默认关闭、失败隔离、response-loss readback、迁移新 lineage 和 crash gap 都有明确合同与实测,future-facing work 被克制地留在 durable outbox、parity compare 和 separately reviewed promotion 阶段。请在合并前解决与最新 main 的冲突并重跑相应门禁;若冲突修改上述 authority/runtime-root 边界,需要按新 head 重新审查。
English verdict: APPROVE
Exact head ea15267fed1b0f37274931aaacc2d32be60c17a6. The previous split-lineage blocker is fixed by routing Todo, follow-up, handoff, lease, and observation paths through one effective runtime root, with a real mismatched-root CLI E2E proving one store identity and complete Todo/lease head. The contract also remains honestly bounded to default-off best-effort post-commit capture: no durable source outbox, parity verdict, decision read, or promotion authority is claimed. Focused Python (22 passed), TypeScript (463 passed, 1 gated skip), typecheck, Ruff, diff checks, and remote required checks pass. The branch is currently conflict-dirty against latest main and must be refreshed before merge; re-review is required if conflict resolution changes these boundaries.
Signed-off-by: huangruiteng <huangrt01@163.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Findings
没有发现新 blocker。复审绑定 exact head b6d493ac26900473817f65e60611d663a2767e8f。该 head 将最新 main 合入贡献分支;唯一人工冲突位于 tsconfig.control-plane.json,解决方式是保留 PR 的 local_authority_shadow.test.ts,同时保留主干新增的 coordination runtime/projection/local-authority tests,未改动 PR 的 runtime、配置、writer hook 或 authority 语义。
动机
本 PR 为 Shared Goal Authority Stage 2C 增加默认关闭、显式 opt-in 的 post-commit observation:现有 Markdown Todo、handoff 与本地 task lease 继续是 canonical authority,而 FileAuthorityStore 只保存从真实 writer 路径采集的 candidate snapshot。这样后续可以验证 parity 和设计 durable outbox,又不会让 observation 提前成为 read authority、settlement owner 或 promotion verdict。
此前 blocker 是 common_runtime_root 与 CLI --runtime-root 不同时,各 writer 会形成两个都声称 captured 的 store lineage。贡献者已用统一的 effective runtime root 修复,并补了跨进程 E2E;本次 main 合并没有改变这个边界。
改动思路
配置通过 configure-goal --local-authority-shadow-file 显式开启。Python adapter 在 primary commit 后从同一 effective runtime root 稳定采样 Todo、handoff 和 lease projection,生成 observation identity;TypeScript effect handler 使用 FileAuthorityStore revision/CAS 写 candidate 并做 receipt readback。provider 失败、lock timeout、协议错误或 response loss 都只产生 typed observation evidence,不回滚主写,也不把 candidate 回流到 lifecycle decision。
正向路径是 opt-in → legacy writer commit → 同 root 完整快照 → candidate CAS → captured/replayed receipt。负向路径保持 fail-isolated;迁移从目标 canonical state 建立新 lineage,不复制旧 provider identity。Todo completion、lease、调度和 settlement authority 始终留在既有 owner。
具体改动
local_authority_shadow_adapter.py与effective_runtime_root()统一 Todo、follow-up、handoff、lease fence 和 observation 的 runtime-root 解析;显式 override 优先,相对 registry root 稳定锚定 project root。local_authority_shadow.ts是唯一 candidate commit seam,以 store revision/CAS 和 exact receipt readback处理 replay/ambiguous outcome。- Todo add/update/complete/supersede/archive、follow-up capture、handoff mode、task-lease lifecycle 和 migration 都在成功主提交后接入 observer;失败不反转 canonical write。
- 配置 catalog、CLI/RFC 和 tests 明确
source_transaction_correlated=false、无 durable outbox、无 parity verdict、无 promotion authority。 - 本次冲突解决仅更新
tsconfig.control-plane.json的 include 集合:PR 自有 test 与最新 main 的三组 coordination tests 全部保留,使 typecheck/test runner继续覆盖两侧代码。
对主干的风险
残余风险是 opt-in full-snapshot/history 增长、1 秒 observation lock 的延迟,以及无 durable outbox 时 source commit 到 observer 之间可能漏采一次;PR 已明确披露,并且这些风险不会改变 primary authority。最新 main 带来的 coordination runtime/promotion代码与本 PR 的 observation-only seam 在同一 TypeScript编译/测试集合中通过,没有发现双 owner 或旧 writer fallback 被意外放宽。
合并后独立验证:focused Python suite 22 passed;control-plane TypeScript typecheck通过;TypeScript suite 492 passed, 1 个需要 LOOPX_TEST_POSTGRES_URL 的显式 live integration skipped;risk-based premerge 18/18 passed,包括 Python compile、diff hygiene、control-plane canaries、risk-profile smokes和 27-file public-boundary scan。GitHub 新 head checks 已触发,最终 merge 仍等待这些 required checks 通过。
我的整体评价
整体结论为 APPROVE。PR 的 observation contract 保持 default-off、best-effort、candidate-only,统一 runtime-root 的修复有真实多 writer E2E保护;冲突解决没有扩大产品 scope,只让 TypeScript验证清单保留两侧新增测试。future-facing 工作仍克制地留在 durable outbox、parity compare 和独立 promotion 阶段。待 GitHub exact-head required checks 全绿后可以合并。
English verdict: APPROVE
Exact head b6d493ac26900473817f65e60611d663a2767e8f. The conflict resolution merges current main and preserves the union of the PR's local-authority-shadow test with main's new coordination tests; it does not alter runtime or authority behavior. The prior split-lineage fix remains intact. Validation: 22 focused Python tests, TypeScript typecheck, 492 TypeScript tests with one explicitly gated PostgreSQL live skip, and all 18 risk-based premerge checks passed. Merge only after the new exact-head required checks are green.
Summary
@huangruiteng This PR is the first half of Stage 2C, not Stage 3 remote parity or Stage 4 canary work.
Issue Or Task
stage-2c-local-post-commit-observationValidation
npm run typecheck:control-planeloopx canary premerge --from-git-diff --git-diff-base origin/main(18/18, no warnings or holds)Type of Change
LoopX Area
Technical Direction
Shared Goal Authority and cross-host coordination
Target base branch:
mainDirection tracker or promotion unit: Stage 2C local observation foundation
observation_triggeris diagnostic context, not source transaction identity. Every result statessource_transaction_correlated=false,durable_source_outbox=false,source_candidate_compared=false, andparity_verdict=not_evaluated.This PR does not add an outbox, compare source and candidate, issue a parity verdict, fence legacy writers, or promote
FileAuthorityStore. The RFC also records that #3669's historical “Stage 3” name maps to the current RFC Stage 0 foundation, not current Stage 3 remote shadow parity.Known Debt Carried Into the Second Half of Stage 2C
These are measured on this head and are deliberately not fixed here. Each one blocks the parity and promotion half of Stage 2C, not this observation slice, and each is listed so the promotion review does not inherit it silently.
FileAuthorityStoretransaction, and the file provider rewrites the whole document. Observed on a fixture with 100 Todos: 200 lease renewals grew one candidate file to 2.79 MB (+10.9 KB per renewal) and raised renewal latency from 0.18 s to 0.54 s. Cumulative cost is quadratic in the number of observations until compaction or delta capture exists.exclusive_file_lock. Under contention a primary write waits up to that full second, and an observation that cannot take the lock is dropped and reported asunavailable; with four concurrent writers, 1 of 24 observations was dropped. The evidence stays typed, but capture is best-effort by construction.--runtime-root. Fixed in round 3 (see below): every hook now consumes one effective runtime root, and a subprocess E2E pins the single lineage.Round 3 (exact head
ea15267fe)Rebased onto
mainatfe80aecd7. The only conflict was thetsconfig.control-plane.jsoninclude list shared with #3819 and #3832; it is resolved as the union.Fix for the P1 on
422757dd9:local_authority_shadow_adapter.effective_runtime_rootis the one resolver every observation hook consumes: the CLI--runtime-rootoverride when given, otherwise the registrycommon_runtime_root, with a relative value anchored at the registry's project root instead of the caller's working directory.runtime_root_from_registryanchors the same way, so lease files and observations of one goal share one root.capture_followup_todos, andset_goal_handoff_modeacceptruntime_root_arg; the CLI passes its override through, and each writer hands the resolved root to its ownership gate, lease fence, and post-commit observation. Non-CLI callers keep the registry-root default.test_product_cli_runtime_root_override_keeps_one_candidate_lineage: withcommon_runtime_root != --runtime-root, todo add, task-lease acquire, todo update, capture-followups, and a leased completion produce exactly one store identity; the head holds both todos and the released lease; the registry root gains neitherauthority-shadow/nor a lease directory.test_relative_common_runtime_root_resolves_against_the_project_root_for_every_hookpins the anchoring from a foreign working directory.sort()inlocal_authority_shadow.ts;set_goal_handoff_modeandexecute_native_task_lease_acquiresplit into helpers below the cognitive-complexity limit; the configure-goal exception test has exactly one raising call.loopx/todos.pysits exactly at its maintainability ceiling, so a separate pure-move commit relocates the todo list projection intoloopx/control_plane/todos/goal_todo_projection.pybefore the threading lands. No caller outsideloopx/todos.pyused the moved helpers.Behavior disclosure: a relative
common_runtime_rootnow resolves against the registry's project root for the task-lease verbs and every observation hook; previously the lease verbs resolved it against the caller's working directory. Absolute roots and the default (no override) path are unchanged.Validation on this head:
pytest -n 4: 5161 passed, 12 skipped; the 12 failures in this environment are the same git-hook install, doctor runtime-readiness, and pydantic/fastmcp-dependent MCP tests that fail identically onmainhere.npm run typecheck:control-planeclean.loopx canary premerge --from-git-diff --git-diff-base origin/main: standard tier, 4/4 direct checks, 18/18 catalog canaries executed with 0 failures and 0 warnings,full-publicrisk profile ok,premerge-public-boundaryclean, 0 manual holds.Still not in this PR, per the previous verdict: durable outbox, source/candidate compare, parity verdict, legacy writer fencing, promotion. Those follow in the Stage 2C second-half PRs stacked on this branch.
Boundary Checklist
.loopx/,.codex/goals/, liveACTIVE_GOAL_STATE.md, credentials, private benchmark traces, verifier output, raw agent sessions, internal document links, or local machine paths.Signed-off-bytrailer (git commit -s).