Skip to content

fix(chat): bind agents through source authority - #4950

Merged
huangruiteng merged 4 commits into
loopx-project:mainfrom
Duang777:codex/audit-chat-action-authority
Sep 23, 2026
Merged

huangruiteng merged 4 commits into
loopx-project:mainfrom
Duang777:codex/audit-chat-action-authority

Conversation

@Duang777

Copy link
Copy Markdown
Contributor

Goal And Delivered Outcome

  • Goal/source and gap: Chat `agent.bind` previewed and wrote the shared registry read model. It did not bind the source Goal peer set, so a later source-to-global sync could remove the binding and a concurrent source peer change did not invalidate the reviewed proposal.
  • Observable before -> after, with the validation row that proves it: Before, source resync removed a reported binding and source peer-set edits could pass the old confirmation. After, preview fingerprints the canonical source peer set, apply rechecks it under the source registry transaction, and success requires source plus global readback. The regression parity and unit rows cover both transitions.
  • Issue/task and intended base: Self-contained control-plane correctness fix against `main` at `eb16c5443`.

Scope And Continuation

  • Completed scope and remaining work: Complete within this scope for Chat `agent.bind`. The same-shape scan found Goal lifecycle already uses source CAS, while Todo and Monitor mutations use their canonical providers or state transactions. Goal creation has separate bootstrap semantics and is unchanged.
  • Slice boundary / successor: N/A. This patch changes only agent-binding authority, projection recovery, its regression tests, and the matching self-repair pattern.

Validation

  • Tested revision: `42748fc82931c4ece1aa930b1b01802275205a69`
  • Run state: finished
  • Input classes: synthetic, public_fixture
Check kind Result Public-safe evidence / limitation
`regression_parity` `passed` The source-resync and concurrent source peer-set cases reproduced as failing behavior before the fix; both pass at the tested revision.
`unit` `passed` `python -m pytest -q tests/control_plane/test_configure_source_authority.py`: 7 passed, including source resync persistence, zero-write stale rejection, receipt-loss recovery, and stale-mirror repair.
`static` `passed` Ruff passed for all changed Python files; changed-file compilation and diff checks passed.
`integration` `passed` Standard diff-selected premerge completed 18 of 18 checks with no failures or warnings, including configure-goal global sync and peer-agent runtime smokes.
`static` `passed` Repository hygiene and semantic vocabulary checks passed.
  • Coverage and gaps: The tests exercise the shared-registry entrypoint, canonical source write, source peer-set CAS, global projection readback, idempotent retry, and mirror repair. Full-repository mypy is not a usable changed-code gate on this base: it reports 4,096 existing errors across 496 files, with no report tied to the added symbols. The standalone docs-governance smoke also fails on the unchanged `docs/architecture/rfcs/automatic-execution-admission-v0.md` semantic-mirror requirement; the same failure is present on `upstream/main`. Neither baseline is changed here.

See validation disclosure guidance.

Frontend / Visual Evidence

  • UI impact: none
  • Before: N/A
  • After: N/A
  • States and viewports shown: N/A
  • Source data: none
  • Attention review: N/A. No user-visible layout or interaction changed.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring (no functional changes)
  • Documentation update
  • Test update

LoopX Area

  • Control plane (goals, todos, quota, scheduler, registry, runtime)
  • Benchmark boundary (adapters, runners, verifiers, scoring, evidence)
  • Capability or extension (providers, adapters, skills)
  • Public docs or presentation surface (README, protocols, dashboard)
  • Build, packaging, installer, or CI
  • Host or runtime integration

Technical Direction

  • Direction / acceptance reference, when applicable: Core control-plane hardening.

Shared-authority RFC fixture impact

N/A. This patch corrects an existing Python Chat action write path and does not claim TypeScript authority migration progress.

Boundary Checklist

  • Neither the diff nor this PR body/comments/attachments disclose private state, credentials, raw traces or verifier output, internal links, or local machine paths (including `.loopx/`, `.codex/goals/`, and live `ACTIVE_GOAL_STATE.md`).
  • I did not duplicate maintainer-owned benchmark work unless a maintainer split out a public issue for it.
  • I kept the change scoped to the linked issue/task.
  • I completed the visual evidence section for UI changes, or marked UI impact `none`.
  • Every commit includes a DCO `Signed-off-by` trailer (`git commit -s`).

Chat agent binding wrote only the shared registry, so source resync discarded it and source peer changes did not stale reviewed proposals.

Fingerprint the source peer set, merge under the source registry transaction, sync and verify the global projection, and let already-bound retries repair the mirror after response loss.

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

Copy link
Copy Markdown
Contributor Author

@huangruiteng Please review this source-authority fix when available. The PR is based on current main; focused regressions and standard premerge are green.

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

动机

Exact head: 42748fc82931c4ece1aa930b1b01802275205a69(base eb16c5443)。旧 Chat agent.bind 只写全局注册表的共享读模型,项目源再同步会抹掉绑定,且源 peer set 在确认后变化不会使预览失效。修复这一持久化/确认缺口有实际价值;当前 head 的正常路径已经改善,但仍未完整绑定被确认的源身份。

改动思路

新路径从 canonical source 读取已注册 Agent,以 peer-set revision 做预览依据;apply 在项目源注册表事务中检查修订、合并 Agent、调用既有 configure_goal/全局同步 owner,并在源及投影读回后才记 agent_bound。已绑定重试会重同步投影,保留响应丢失恢复。该设计复用了配置服务而非新造一个注册表写入器,Goal 创建与 Todo/Monitor 各自的 owner 未被改动。

具体改动

关键代码讲解

  • configure_goal_service.py 新增 goal_agent_binding_revisionread_goal_agent_binding_with_source_route,从源 peer 列表导出 revision;bind_goal_agent_with_global_sync 负责锁内 stale 判定、源合并、共享投影同步与读回。
  • chat_actions.pyagent.bind 预览和应用改调用上述源服务,失败时留在 stale/错误,成功时保存 agent_boundagent_already_bound receipt。
  • test_configure_source_authority.py 新增源重同步保持绑定、源 peer 并发变化零写入、响应丢失后的镜像修复;self-repair pattern 增加同一根因的公开可复用条目。新增代码有真实 Chat 调用点,不是孤立测试结构。

对主干的风险

P1 阻断:peer-set revision 没有源路由身份。 我以真实临时注册表复现:预览源 A(含 agent-a),复制同样内容到源 B,只把全局 source_registry 改指 B,然后确认绑定 agent-b。基线将 proposal 标为 stale 且 A/B 均无新绑定;本 head 把 agent-b 写进 B 和全局投影,并标为 applied,A 仍只有 agent-agoal_agent_binding_revisionconfigure_goal_service.py:105)只哈希 goal id 和 Agent 列表;apply 在 :693 重新解析到 B、在 :717 看到相同列表便放行。源/投影读回成功只证明新目标 B 一致,不证明 B 是用户确认时的 A。请把所预览 canonical source 的身份纳入修订,并在事务与同步路径保持路由一致;补等 peer-set 的 A→B 路由切换 stale/零写入测试。#4949 的生命周期确认有同类缺口,宜复用同一个窄的路由绑定规则。

语义与 CI 对齐

受影响的是现有 Goal Agent 绑定的权限与持久化契约;没有新增 peer actor 生命周期,也没有 default-off 开关。聚焦测试 26/26、Ruff/diff、补齐 Node 依赖后的 premerge 18/18 全通过;首次 premerge 因隔离 worktree 未安装 Node 依赖,仅 semantic-vocabulary smoke 失败,依赖安装后该 smoke 和完整 premerge 都通过。最新 main 可干净合并。Goal 配置 wait_for_ci=false,未轮询远端 CI。现有用例在基线复现正常绑定丢失,但未覆盖源路由切换反例。

我的整体评价

REQUEST_CHANGES。正常源写入、重放和投影恢复的设计合理,增量规模相称;但“确认绑定到所预览源”这个决定性语义仍可被同列表的路由切换绕过。修复后请在真实 Chat 入口重跑 A/B 反例、配置源权限套件与 premerge,再重审 exact head。未来演进上优先与 #4949 共享源身份/修订的有类型边界;其余宽泛重构没有必要。

English verdict: REQUEST_CHANGES - head 42748fc82931c4ece1aa930b1b01802275205a69 passes focused tests and premerge, but an equal-peer source-route switch registers the Agent on a different, unreviewed source; bind and recheck route identity.

Include the canonical source registry in agent binding revisions so equal peer sets cannot authorize writes after a route change. Restrict already-bound recovery to the exact same source and pre-bind peer set, and cover both route-switch cases.

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
…tion-authority

Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
Regenerate source line metadata after merging the latest main history changes.

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

Copy link
Copy Markdown
Contributor Author

Addressed the requested source-route binding fix in exact head 8a71f9525450986b65ad0d12ac9c5d77ac96aed3 (merged current main at a038ad8d3).

  • agent.bind revisions now include the normalized canonical source_registry identity as well as the source peer set.
  • The source selected at apply is carried through the source transaction and projection sync.
  • Already-bound recovery is accepted only when removing the target Agent reconstructs the confirmed revision for that same source, so a route switch cannot masquerade as receipt-loss recovery.
  • Added real Chat regressions for equal-peer A→B route replacement and for a replacement source that already contains the target Agent; both require stale and byte-for-byte zero writes across A, B, and the mirror.

Verification:

  • focused source/configuration suites: 44 passed
  • Ruff and registry I/O manifest checks: passed
  • standard premerge: 18/18 passed (10 catalog canaries, 8 risk-profile smokes)

Please re-review the new exact head.

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

动机

修复 chat agent.bind 只修改共享镜像、随后被 canonical source 重同步抹掉的非持久绑定;同时解决 preview 后源路由 A→B、即使两边 peer 集合相同也可能误执行的问题。本次评审固定在 8a71f95

改动思路

preview 从 canonical source 读取 peer 集合,将规范化 source 路径与 peer 集合一起纳入 revision。apply 在源 registry 事务锁内核对 revision,调用已有 configure-goal source/global sync owner,验证源与镜像。只有同一来源、同一 peer 变更的 receipt-loss 重试才允许识别为 already_bound 并修复镜像;换源或其他 peer 漂移返回 stale 且零写入。

具体改动

chat_actions 的 agent.bind 分支不再直接写共享镜像,改由 configure_goal_service 的 source-backed helper 完成 CAS、配置和回读;sync_if_unchanged 复用现有同步路径处理已写源但回执丢失的重试。IO manifest、自修复参考和针对源重同步、A→B 等集合换源、目标 Agent 已在 B、回执丢失的测试一并更新。相关前瞻性重构是把 chat 层的重复写入规则收归现有 source configure owner;没有新增第二个持久权威。

对主干的风险

跨 source/global 的同步仍不是分布式原子事务,镜像同步失败时源可能已写入;现有 partial-write/错误路径会暴露失败,原 proposal 可在同源条件下重试修复,不会伪造成功回执。旧的、未执行的镜像指纹 proposal 会安全地变为 stale,需要重新 preview。换源与 peer 漂移测试比较三个 registry 的前后字节,防止跨源误写。未按当前 review 契约查询远端 CI。

我的整体评价

APPROVE 此精确 head。28/28 本地 Python 用例、Ruff 与风险 canary 18/18 通过,未见阻断性发现;无新执行权限、迁移或无关 chat action 默认变化。相关重构已限于同一 source-sync 边界。此批准不等于合并授权:控制面行为变更仍由维护者按 exact-head 门槛合并。

English verdict: APPROVE - 8a71f95; source-backed binding and equal-peer A-to-B stale rejection verified; 28 Python tests, Ruff and 18 canaries passed. Maintainer merge required.

@huangruiteng
huangruiteng merged commit d2bae5a into loopx-project:main Sep 23, 2026
23 of 26 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