fix(reward-memory): reconcile live configuration and guide requalification - #4866
Conversation
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
审阅 exact head:606105d0174c10ba378faaaf9af3ea2bde4089fd
动机
这个 PR 修复的是一个容易误导操作者的状态分裂:私有 Reward Memory config 一旦被编辑,runtime admission 已会因 digest/receipt 不匹配而拒绝使用;但 settings catalog 仍可能把历史 receipt 显示成“已验证”,显式 recall 又把所有 unavailable 情况统一叫作 disabled。结果是运行时在正确 fail-closed,操作面却看不出 drift 的真实原因和安全恢复方式。
我重点验证了两个反例:缓存 receipt 是否还能让 automatic recall/ingest 看起来有效;repair command 是否可能漏掉 invoked registry、泄漏私有 pointer,或在只读查看时产生 provider/registry effect。两者在当前 head 都被正确封住。
改动思路
resolve_goal_reward_memory_experiment 是共享的只读 admission owner:catalog 不再复制一套简化 receipt 规则,而是复用与 runtime 相同的 config digest、Goal/Agent、provider、isolation、writability 和 exact-readback 校验。投影明确分开 desired/historical 与 effective/current:配置意图可以继续显示,但 drift/unverified 时 effective availability 和 effective automation 必须为 false。
恢复不新增 authority。_enablement_repair 只生成 configure-goal 的 preview/apply/verify 模板,保留完整 Agent allowlist,且每条命令都把 --registry <invoked-registry> 放在 command 前并声明 required binding。真正的 provider canary write、exact readback 与 registry synchronization 仍只在既有 configure-goal --execute owner 中发生。
具体改动
- experiment resolver 增加 already-loaded Goal 入口,使 runtime 与 catalog 共用完整 admission 规则;stale/unverified 返回 typed reason 与 public-safe repair plan。
- repair payload 明确
commands_are_templates=true、automatic_apply=false,不包含 registry 实际路径、config pointer、provider URI 或 credential;disabled 状态不返回 repair。 reward_memory_goal_policy_summary增加binding_status、effective_available、desired_automation与历史/有效 verified Agent 的区分。只有当前至少一个 Agent 真正 available 时 effective automatic flags 才能为 true。- agent-turn-recall 保留真实 unavailable status/reason;quota boundary、status projection 与 Markdown 传递同一 repair plan。现有 configuration catalog/frontend summary 消费新增 current fields,不引入新的 editor 或配置权威。
- exact head 上运行了 89 项相关测试(experiment、turn recall、outcome lifecycle、capability UI、chat configuration),全部通过;Ruff、
git diff --check与当前origin/mainmerge-tree 通过。测试覆盖逐项篡改 Goal、Agent、provider、isolation、digest、receipt,以及 missing/disabled config 和 explicit registry template parsing。
对主干的风险
我没有发现 blocking finding。default-off 边界仍成立:未同时满足 enabled + experimental + exact Agent 时不会触碰 provider;explicit disabled 不提供 repair;只读取 catalog/status/repair 不会写 registry、花 quota 或产生 external effect。配置存在、历史 receipt 存在或 repair template 可见都不等于 capability 已启用。
剩余风险主要是我没有在本地对真实外部 OpenViking 服务重新做一次 qualification;独立证据覆盖了生产 CLI、真实本地文件 binding、test provider、exact readback contract 与 no-effect branches。该分支同样处于 BEHIND;虽然与当前 main(包括较新的 Reward Memory 改动)merge-tree 无冲突,批准不替代更新基线后的 exact-head readiness。
我的整体评价
这不是单纯换文案,而是把“期望配置 / 历史证明 / 当前可用性”重新对齐到一个 admission owner,并把恢复留在原有配置 owner。新增字段都是 derived projection,没有第二份可编辑状态,也没有让 guidance 冒充授权。代码量与故障成本匹配;未来向前看的最佳简化——移除 catalog 的缓存 receipt 真值——已经在本 PR 内完成,不需要再建新的 provider 或 recovery framework。
结论:对 exact head 606105d0174c10ba378faaaf9af3ea2bde4089fd 无阻塞问题,批准;合并前仍需更新 head 并重新走 readiness。
English verdict: APPROVE - The exact head makes live config and receipt admission authoritative across recall, catalog, and status while keeping recovery template-only and explicitly registry-bound; focused negative evidence passed, with live external-provider qualification and post-rebase readiness left as residual risks.
|
已将分支同步到当前 本地重新验证:
PR 保持未合并,等待 exact-head review 与 CI。 |
huangruiteng
left a comment
There was a problem hiding this comment.
+Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
+
+Exact head reviewed: 97ff03aa3183f1737255e4ef0c09d72b081de1cf
+
+## 动机
+
+这个 PR 处理的是一个真实且容易误导操作者的状态分裂:私有 Reward Memory 配置发生变化后,runtime admission 已经会因 digest 或 qualification receipt 不匹配而 fail closed;但 configuration catalog 仍可能把历史回执显示为“已验证”,显式 recall 又把所有 unavailable 情况统一写成 disabled。因此,运行面虽然安全拒绝,设置页、Agent 和操作者却无法区分“明确停用”“配置漂移”“回执未验证”,也得不到一条保留既有 scope 的恢复路径。
+
+我用同一个合成 Goal/配置夹具分别执行了当前 origin/main 与本 exact head 的公开 CLI。仅改变私有配置字节时,基线 catalog 仍给出 automatic_recall=true 和缓存的 verified Agent,而 runtime 已返回 enablement_stale;当前 head 则保留 desired automation 和 recorded receipt,同时将 binding_status 置为 drifted、effective_available=false、有效自动化关闭,并附带只读的恢复模板。两边 registry 都保持字节不变。
+
+从目标边界看,这是一个完整而非碎片化的切片:只改 recall 文案会留下 catalog 的第二套真值,只加 catalog digest 检查又会漏掉 Goal/Agent/provider/isolation/write-readback 等完整 admission。当前做法复用现有 runtime resolver 与 configure-goal owner,没有引入新的配置权威、provider 权限或自动修复。
+
+## 改动思路
+
+权威关系收敛得合理:
+
+- Goal policy 与 repo-relative 私有配置仍是输入,resolve_goal_reward_memory_experiment 复用完整 runtime admission,校验注册 Agent、配置 schema/scope、当前 digest 和完整 enablement receipt;
+- reward_memory_goal_policy_summary 不再直接把历史 receipt 当作当前可用性,而是分离 desired/historical 与 effective/current,并让有效自动化依赖实时 admission;
+- stale/unverified 只生成 reward_memory_enablement_repair_v0 guidance:命令明确是 template、必须绑定本次 invoked registry、保留完整 Agent allowlist、automatic_apply=false;
+- 真正的 provider write、exact readback、receipt replacement 与 registry mutation 仍只发生在显式执行的 configure-goal --execute;
+- recall、quota/status 与 Markdown 只是消费者。配置存在、历史 receipt、repair 可见或 provider 可发现,都不会激活 capability。
+
+最强的“不应该合入”反例不是功能架构本身,而是当前 head 的仓库完整性:它通过一个未签署的 merge commit 同步 main。这个提交会被仓库自己的 DCO gate 拒绝,功能测试全绿也不能替代该门禁。
+
+## 具体改动
+
+### 关键代码讲解
+
+1. loopx/capabilities/reward_memory/experiment.py::_enablement_repair
+
- 从 canonical Goal id、完整 enabled-Agent 列表和当前 Agent 构造 preview/apply/verify 模板。模板不携带真实 registry 路径、私有 config pointer、provider URI 或凭据;每条命令都显式要求
<invoked-registry>绑定,且不会自动执行。
+2. loopx/capabilities/reward_memory/experiment.py::resolve_goal_reward_memory_experiment
+
- 把原来“先读 registry 再做校验”的逻辑拆成可接收已加载 Goal 的共享只读 owner。disabled、agent-not-enabled、config missing/invalid、digest drift、receipt unverified 与 available 仍是精确分支;只有 digest、Goal/Agent/provider/isolation、writability 和 exact-readback 全部对齐才返回 available。
+3. loopx/control_plane/reward_memory.py::reward_memory_goal_policy_summary
+
- 增加
binding_status、effective_available、desired_automation、recorded_verified_agents,并逐个通过共享 resolver 得到 effective Agent。这样 cached receipt 仍可作为历史事实展示,但不再直接打开automatic_recall或automatic_ingest。
+4. loopx/capabilities/agent_turn_recall/cli.py::handle_agent_turn_recall_command
+
- unavailable 分支保留 resolver 的真实
status与reason_code,同时继续保证 provider 调用数为 0、不花 quota、不授予新 action authority、无外部写入。
+其余改动把 reason_code/repair 透传到 Goal boundary、status 与 Markdown,把 live-derived 字段放进现有 configuration catalog;英文/中文文档说明 inspect → preview → authorized apply → verify 的恢复流程。完整 diff 为 10 个文件、+399/-11,其中 213 行是回归测试、46 行是双语文档;没有新增持久状态或命令。
+
+## 对主干的风险
+
+### [P1] 当前 exact head 的 merge commit 缺少 DCO 签署
+
+97ff03aa3183f1737255e4ef0c09d72b081de1cf 的 commit body 没有有效的 Signed-off-by trailer。仓库 .github/workflows/dco.yml 会枚举 origin/main..HEAD 的每个提交并逐一校验;我在当前 head 运行同一条本地规则,明确得到:
+
+MISSING 97ff03aa3183f1737255e4ef0c09d72b081de1cf,退出码 1。
+
+这不是可忽略的远端 CI 波动,而是当前 head 确定违反仓库提交策略。最小修复是重新创建或 amend 该 merge commit 并加入合法签署(也可以把两个已签署 feature commit rebase 到当前 main),推送新 head 后重新做 exact-head review。请不要只重跑检查;head 改变后本结论不会继承。
+
+除这个 blocker 外,没有发现新的功能性 blocking finding。验证结果:
+
+- Reward Memory experiment、turn recall、outcome lifecycle、capability UI contract 与 chat configuration API:89 passed;
+- 改动 Python 文件 Ruff:passed;
+- git diff --check origin/main...HEAD:passed;
+- 相同 drifted fixture 的 base/head 公开 CLI 对比:基线误报 cached effective automation;head 正确关闭 effective automation、保留 desired/historical 状态并给出 registry-bound template,且两边 registry 均无变化;
+- 当前 Goal 的 source CLI default-off 读回:status=disabled、available=false、automatic recall/ingest false、无 external write;
+- 当前 head 的 feature runtime 文件与上一 reviewed feature commit 一致;合入的新 main 没有产生文本冲突,相关 application/recall receipt 语义仍由现有 owner 保持。
+
+### 语义与 CI 对齐
+
+这个 PR 是对既有 Reward Memory vocabulary 的扩展:enablement_stale / enablement_unverified 没有改写成新的权威,新增 repair schema 与 catalog 字段都是 derived projection。代码、双语文档和 focused tests 对 desired/historical/effective、guidance/obligation、availability/activation 的区分是一致的。按本 Goal 配置,本轮没有读取或等待远端 CI;但本地 required DCO gate 已经失败,足以阻塞当前 exact head。
+
+剩余非阻塞风险是本轮没有重复真实外部 provider requalification,也没有做浏览器视觉验收;它们分别属于部署 qualification 与未改 renderer 的 UX 读回,不改变当前功能路径判断。修复 DCO 后仍需重新跑 89 项 focused suite、DCO rule、result gate 和 remote head freshness。
+
+## 我的整体评价
+
+功能设计本身是扎实且比例合理的:它删除 catalog 的缓存 receipt 真值,复用 runtime admission,并把恢复留给已有 configure-goal owner;没有复制 provider logic、自动接受私有配置变化或增加新的前端/Lark state owner。paired base/head CLI 也证明它修复了实际 operator-visible drift,而不只是让新单测变绿。
+
+但仓库门禁对每个 PR-only commit 的签署是明确的,当前 merge commit 未满足这一点,因此我不能批准这个 exact head。请先修复提交历史并推送新 head;届时需要完整 fresh exact-head review,而不是沿用旧 approval。
+
+English verdict: REQUEST_CHANGES - head 97ff03a functionally reconciles live Reward Memory state and passes 89 focused tests, Ruff, diff hygiene, paired base/head CLI and default-off readback, but its unsigned merge commit deterministically fails the repository DCO gate; sign or replace that commit and request a fresh review.
+
huangruiteng
left a comment
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
Exact head reviewed: 97ff03aa3183f1737255e4ef0c09d72b081de1cf
动机
这个 PR 处理的是一个真实且容易误导操作者的状态分裂:私有 Reward Memory 配置发生变化后,runtime admission 已经会因 digest 或 qualification receipt 不匹配而 fail closed;但 configuration catalog 仍可能把历史回执显示为“已验证”,显式 recall 又把所有 unavailable 情况统一写成 disabled。因此,运行面虽然安全拒绝,设置页、Agent 和操作者却无法区分“明确停用”“配置漂移”“回执未验证”,也得不到一条保留既有 scope 的恢复路径。
我用同一个合成 Goal/配置夹具分别执行了当前 origin/main 与本 exact head 的公开 CLI。仅改变私有配置字节时,基线 catalog 仍给出 automatic_recall=true 和缓存的 verified Agent,而 runtime 已返回 enablement_stale;当前 head 则保留 desired automation 和 recorded receipt,同时将 binding_status 置为 drifted、effective_available=false、有效自动化关闭,并附带只读的恢复模板。两边 registry 都保持字节不变。
从目标边界看,这是一个完整而非碎片化的切片:只改 recall 文案会留下 catalog 的第二套真值,只加 catalog digest 检查又会漏掉 Goal/Agent/provider/isolation/write-readback 等完整 admission。当前做法复用现有 runtime resolver 与 configure-goal owner,没有引入新的配置权威、provider 权限或自动修复。
改动思路
权威关系收敛得合理:
- Goal policy 与 repo-relative 私有配置仍是输入,
resolve_goal_reward_memory_experiment复用完整 runtime admission,校验注册 Agent、配置 schema/scope、当前 digest 和完整 enablement receipt; reward_memory_goal_policy_summary不再直接把历史 receipt 当作当前可用性,而是分离 desired/historical 与 effective/current,并让有效自动化依赖实时 admission;- stale/unverified 只生成
reward_memory_enablement_repair_v0guidance:命令明确是 template、必须绑定本次 invoked registry、保留完整 Agent allowlist、automatic_apply=false; - 真正的 provider write、exact readback、receipt replacement 与 registry mutation 仍只发生在显式执行的
configure-goal --execute; - recall、quota/status 与 Markdown 只是消费者。配置存在、历史 receipt、repair 可见或 provider 可发现,都不会激活 capability。
最强的“不应该合入”反例不是功能架构本身,而是当前 head 的仓库完整性:它通过一个未签署的 merge commit 同步 main。这个提交会被仓库自己的 DCO gate 拒绝,功能测试全绿也不能替代该门禁。
具体改动
关键代码讲解
-
loopx/capabilities/reward_memory/experiment.py::_enablement_repair从 canonical Goal id、完整 enabled-Agent 列表和当前 Agent 构造 preview/apply/verify 模板。模板不携带真实 registry 路径、私有 config pointer、provider URI 或凭据;每条命令都显式要求
<invoked-registry>绑定,且不会自动执行。 -
loopx/capabilities/reward_memory/experiment.py::resolve_goal_reward_memory_experiment把原来“先读 registry 再做校验”的逻辑拆成可接收已加载 Goal 的共享只读 owner。disabled、agent-not-enabled、config missing/invalid、digest drift、receipt unverified 与 available 仍是精确分支;只有 digest、Goal/Agent/provider/isolation、writability 和 exact-readback 全部对齐才返回 available。
-
loopx/control_plane/reward_memory.py::reward_memory_goal_policy_summary增加
binding_status、effective_available、desired_automation、recorded_verified_agents,并逐个通过共享 resolver 得到 effective Agent。这样 cached receipt 仍可作为历史事实展示,但不再直接打开automatic_recall或automatic_ingest。 -
loopx/capabilities/agent_turn_recall/cli.py::handle_agent_turn_recall_commandunavailable 分支保留 resolver 的真实
status与reason_code,同时继续保证 provider 调用数为 0、不花 quota、不授予新 action authority、无外部写入。
其余改动把 reason_code/repair 透传到 Goal boundary、status 与 Markdown,把 live-derived 字段放进现有 configuration catalog;英文/中文文档说明 inspect → preview → authorized apply → verify 的恢复流程。完整 diff 为 10 个文件、+399/-11,其中 213 行是回归测试、46 行是双语文档;没有新增持久状态或命令。
对主干的风险
[P1] 当前 exact head 的 merge commit 缺少 DCO 签署
97ff03aa3183f1737255e4ef0c09d72b081de1cf 的 commit body 没有有效的 Signed-off-by trailer。仓库 .github/workflows/dco.yml 会枚举 origin/main..HEAD 的每个提交并逐一校验;我在当前 head 运行同一条本地规则,明确得到:
MISSING 97ff03aa3183f1737255e4ef0c09d72b081de1cf,退出码 1。
这不是可忽略的远端 CI 波动,而是当前 head 确定违反仓库提交策略。最小修复是重新创建或 amend 该 merge commit 并加入合法签署(也可以把两个已签署 feature commit rebase 到当前 main),推送新 head 后重新做 exact-head review。请不要只重跑检查;head 改变后本结论不会继承。
除这个 blocker 外,没有发现新的功能性 blocking finding。验证结果:
- Reward Memory experiment、turn recall、outcome lifecycle、capability UI contract 与 chat configuration API:89 passed;
- 改动 Python 文件 Ruff:passed;
git diff --check origin/main...HEAD:passed;- 相同 drifted fixture 的 base/head 公开 CLI 对比:基线误报 cached effective automation;head 正确关闭 effective automation、保留 desired/historical 状态并给出 registry-bound template,且两边 registry 均无变化;
- 当前 Goal 的 source CLI default-off 读回:
status=disabled、available=false、automatic recall/ingest false、无 external write; - 当前 head 的 feature runtime 文件与上一 reviewed feature commit 一致;合入的新 main 没有产生文本冲突,相关 application/recall receipt 语义仍由现有 owner 保持。
语义与 CI 对齐
这个 PR 是对既有 Reward Memory vocabulary 的扩展:enablement_stale / enablement_unverified 没有改写成新的权威,新增 repair schema 与 catalog 字段都是 derived projection。代码、双语文档和 focused tests 对 desired/historical/effective、guidance/obligation、availability/activation 的区分是一致的。按本 Goal 配置,本轮没有读取或等待远端 CI;但本地 required DCO gate 已经失败,足以阻塞当前 exact head。
剩余非阻塞风险是本轮没有重复真实外部 provider requalification,也没有做浏览器视觉验收;它们分别属于部署 qualification 与未改 renderer 的 UX 读回,不改变当前功能路径判断。修复 DCO 后仍需重新跑 89 项 focused suite、DCO rule、result gate 和 remote head freshness。
我的整体评价
功能设计本身是扎实且比例合理的:它删除 catalog 的缓存 receipt 真值,复用 runtime admission,并把恢复留给已有 configure-goal owner;没有复制 provider logic、自动接受私有配置变化或增加新的前端/Lark state owner。paired base/head CLI 也证明它修复了实际 operator-visible drift,而不只是让新单测变绿。
但仓库门禁对每个 PR-only commit 的签署是明确的,当前 merge commit 未满足这一点,因此我不能批准这个 exact head。请先修复提交历史并推送新 head;届时需要完整 fresh exact-head review,而不是沿用旧 approval。
English verdict: REQUEST_CHANGES - head 97ff03a functionally reconciles live Reward Memory state and passes 89 focused tests, Ruff, diff hygiene, paired base/head CLI and default-off readback, but its unsigned merge commit deterministically fails the repository DCO gate; sign or replace that commit and request a fresh review.
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
…the capability The configuration catalog projection reused runtime admission to stop showing a cached receipt as current verification, but it did so with a function-local import from the control plane into the capability layer. That edge is rejected by the control-plane import boundary and reported as unreviewed dependency debt by the maintainability ratchet. Move the reconciled summary to the reward-memory capability, which already owns goal configuration and may depend on the control plane. The control plane keeps the provider-neutral policy projection only. Behavior is unchanged: the catalog and settings summary still separate desired automation and historical receipts from the effective binding. Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
97ff03a to
adea926
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Exact head reviewed: adea926c0cba3c3f5b3125ad62e9e605e283ddd3
动机
这个 PR 处理的是一个真实且容易误导操作者的状态分裂:私有 Reward Memory 配置发生变化后,runtime admission 已经因 digest 或 qualification receipt 不匹配而 fail closed;但 configuration catalog 仍把历史回执当作“当前已验证”展示,显式 recall 又把所有 unavailable 情况统一写成 disabled。运行面虽然安全拒绝,设置页、Agent 和操作者却无法区分“明确停用”“配置漂移”“回执未验证”,也得不到一条保留既有 scope 的恢复路径。
我用同一套合成 Goal/配置夹具分别在 pre-PR 基线(3a419abdf,其全部相关模块与 origin/main@8f5675101 逐字节一致)和本 exact head 上运行了真实投影函数与真实 CLI。仅追加一个字节修改私有配置时:基线 summary 仍返回 automatic_recall: true,基线 CLI 返回 status: "disabled" 且没有 reason code;head 则返回 binding_status: "drifted"、effective_available: false、automatic_recall: false,同时保留 desired_automation.automatic_recall: true 与 recorded_verified_agents: ["pilot"],CLI 给出 status: "enablement_stale"、reason_code: "config_digest_missing_or_drifted" 与带 registry 绑定的恢复模板。两边 registry 字节与 provider 调用数都没有变化。
从目标边界看这是完整的切片而不是碎片:只改 recall 文案会留下 catalog 的第二套真值,只在 catalog 里加 digest 检查又会漏掉 Goal/Agent/provider/isolation/receipt 的完整 admission。当前做法复用既有 runtime resolver 与 configure-goal owner,没有引入新的配置权威、provider 权限或自动修复。
这也是对上一次评审的收口。上次唯一的 blocker 是 97ff03aa3 是未签署的 merge commit,必然触发 DCO 门禁;该提交已通过把两个 feature commit rebase 到当前 origin/main 而消失,本 head 每个 commit 都带 Signed-off-by,远端 Sign-off 检查已 pass。
改动思路
权威关系收敛得合理:
- Goal policy 与 repo-relative 私有配置仍是输入;
resolve_goal_reward_memory_experiment复用完整 runtime admission,校验注册 Agent、配置 schema/scope、当前 digest 和完整 enablement receipt; - 新增的
reward_memory_goal_configuration_summary把 desired/historical 与 effective/current 分开,并让有效自动化依赖实时 admission; - stale/unverified 只生成
reward_memory_enablement_repair_v0guidance:命令明确是 template、必须绑定本次 invoked registry、保留完整 Agent allowlist、automatic_apply=false; - 真正的 provider write、exact readback、receipt replacement 与 registry mutation 仍只发生在显式执行的
configure-goal --execute; - recall、quota/status 与 Markdown 只是消费者。配置存在、历史 receipt、repair 可见或 provider 可发现,都不会激活 capability。
rebase 同时暴露了两个真实回归,都在本 head 修复:control plane 通过函数内 import 越界依赖 capability(tests/architecture/test_control_plane_import_boundaries.py 报 unexpected edges: [('loopx.control_plane.reward_memory', 'loopx.capabilities.reward_memory.experiment')]),以及同一根因导致的 maintainability ratchet 未审阅依赖债。修法是把 reconcile 投影移到它本该归属的 capability(loopx/capabilities/reward_memory/configuration.py,该模块本就拥有 goal configuration,且 configure_goal.py 已有导入同一 capability 其他函数的先例),control plane 只保留 provider-neutral 的 reward_memory_goal_policy。这不是新增抽象:reward_memory_goal_policy_summary 在 control plane 被整体删除,仓库内唯一调用方 configure_goal.py 已改为导入 capability 版本。
具体改动
12 个文件、+447/-41:生产代码 +76/-40(含 control plane 的 32 行删除)、双语文档 +46、测试 +222。没有新增持久状态、命令或 schema 版本。
关键代码讲解
-
loopx/capabilities/reward_memory/configuration.py::reward_memory_goal_configuration_summary(新增,第 24 行)这是 catalog 与设置页共用的唯一 reconcile 投影。
automatic_ingest/automatic_recall只有在effective_available为真时才为真,而binding_status、desired_automation、recorded_verified_agents始终上报,使历史事实仍然可见。逐个 agent 调用共享 resolver,单个 agent 的ValueError只跳过该 agent,不会清空整个投影。 -
loopx/capabilities/reward_memory/experiment.py::resolve_goal_reward_memory_experiment(第 867 行)把原来“先读 registry 再做校验”的逻辑拆成可接收已加载 Goal 的共享只读 owner。disabled、agent-not-enabled、config missing/invalid、digest drift、receipt unverified 与 available 仍是精确分支;只有 digest、Goal/Agent/provider/isolation、writability 与 exact-readback 全部对齐才返回 available。catalog 因此不需要第二套 receipt 规则。
-
loopx/capabilities/reward_memory/experiment.py::_enablement_repair(第 791 行)从 canonical Goal id、完整 enabled-Agent 列表与当前 Agent 构造 preview/apply/verify 模板。模板不携带真实 registry 路径、私有 config pointer、provider URI 或凭据;每条命令显式要求
<invoked-registry>绑定,registry_context=reuse_invoked_registry、automatic_apply=false,且不会自动执行。 -
loopx/capabilities/agent_turn_recall/cli.py::handle_agent_turn_recall_command(第 196 行)unavailable 分支保留 resolver 的真实
status(缺省not_available)与reason_code,同时继续保证 provider 调用数为 0、不花 quota、不授予新 action authority、suppress_external_sinks为 true。这是本 PR 唯一对外可见的显示语义变化,已在 PR 正文与双语文档中披露。
其余改动把 reason_code/repair 透传到 Goal boundary、status 与 Markdown,把 live-derived 字段放进现有 configuration catalog,并在英文/中文 README 说明 inspect → preview → authorized apply → verify 的恢复流程。
对主干的风险
loopx canary premerge --from-git-diff --git-diff-base origin/main:passed(19 checks,0 failures,含 maintainability ratchet smoke、semantic-vocabulary drift smoke 与 public-boundary smoke)。
- 79 passed:
tests/capabilities/test_reward_memory_experiment.py、tests/architecture/test_control_plane_import_boundaries.py、tests/canary/test_maintainability_ratchet.py、tests/cli_commands/test_project_lifecycle_goal_channel.py; - 更宽的本地运行
pytest tests/capabilities tests/presentation tests/cli_commands:1710 passed、21 skipped,1 个失败(test_reward_memory_feedback_hint.py::test_generated_command_previews_reviewed_event_and_rejects_scope_expansion)在基线 commit 上同样复现,与本 diff 无关,已如实列出而未隐藏; python -m ruff check tests loopx/canary loopx/control_plane loopx/domain_packs loopx/presentation:passed;python -m mypy:Success: no issues found in 22 source files;git diff --check origin/main...HEAD:clean;- 修复提交的行为保持性:同一夹具在上一 head(
97ff03aa3,control plane owner)与本 head(capability owner)上的 CLEAN/DRIFT 投影 JSON 逐字节一致,diff只差 owner 名称与 checkout 路径; - 独立 CLI 探针:default-off 情况在基线与 head 均为
disabled、available: false、无 repair、无写入;drifted 情况 head 返回enablement_stale+ registry 绑定模板,provider_call_count: 0、external_writes_performed: false、registry 字节不变; - 负例覆盖 drift、unverified/disabled、缺配置与 receipt 的 Goal/Agent/provider/isolation 字段错配;读取恢复指引不产生任何 provider 写入或 registry mutation。
语义与 CI 对齐
本 PR 扩展的是既有 Reward Memory vocabulary:enablement_stale / enablement_unverified 未被改写成新的权威,新增的 reward_memory_enablement_repair_v0 是派生 guidance,catalog 新字段都是 derived projection。代码、双语文档与 focused tests 对 desired/historical/effective、guidance/obligation、availability/activation 的区分一致;automatic_apply=false 与 commands_are_templates=true 使“指引”与“机器强制”在契约里显式可辨。
剩余非阻塞风险:(1)外部若按字面 status == "disabled" 分支消费 recall CLI,现在需要处理 enablement_stale/enablement_unverified/not_available;envelope 仍保留稳定的 available 与内嵌 experiment,loopx turn/quota 使用的进程内 API 未受影响。(2)本机未重复真实外部 provider 的 requalification,apply 路径仍是既有 configure-goal --execute 的 provider write/exact-readback 流程,本 PR 未宣称部署。(3)上述 1 个 main 既有失败与本 diff 无关。(4)examples/semantic-vocabulary-drift-smoke.py 需要 worktree 内有 node_modules,缺失时它以 TypeScript parser 失败退出;建立符号链接后通过,这不是本 diff 引入的问题。
我的整体评价
功能设计本身扎实且比例合理:它删除 catalog 的缓存 receipt 真值,复用 runtime admission,把恢复留给已有 configure-goal owner,并把 reconcile 投影放回它的正确所有者;没有复制 provider logic、自动接受私有配置变化或增加新的前端/Lark state owner。paired base/head 投影与 CLI 探针证明它修复了实际 operator-visible drift,而不只是让新单测变绿;修复提交的迁移被证明是行为保持的。
上一次评审唯一的阻塞项是仓库完整性(未签署的 merge commit),它已通过 rebase 消失并且远端 Sign-off 已通过;由此暴露的 import-boundary 与 ratchet 回归也已按所有权修正。因此我对本 exact head 给出通过结论,并据此执行 owner 授权的自合并。
English verdict: APPROVE - head adea926 reconciles live Reward Memory configuration with the settings catalog and recall CLI, deletes the control-plane copy of the projection to remove an outward capability dependency, and carries a registry-bound requalification template; the previous DCO blocker is gone (rebased, all commits signed), and validation passed (79 focused tests, 1710 passed wider run with 1 pre-existing main failure named, Ruff, mypy, git diff --check, canary premerge 19/19, byte-identical base/head projection payloads, default-off parity via real CLI probes).
Changing a private Reward Memory configuration invalidates its enablement receipt, but the settings catalog could still show cached verification and the recall CLI called the failure
disabled. Operators and agents received no actionable recovery plan.This change keeps the drift guard, makes the catalog reuse runtime admission validation, and separates desired automation/historical verification from effective availability. Stale or unverified bindings expose a shared
configure-goalpreview/apply/verify plan that retains the existing configuration pointer and complete Agent allowlist. Each command template requires an explicit invocation-registry binding, so copying it cannot silently fall back to the default registry. Applying still performs provider write/exact-readback qualification and registry synchronization; it does not automatically trust a changed configuration.User entry points: CLI recall, quota/managed-Turn projection, status/Markdown, and the existing frontend capability configuration summary share these results. The existing editor already supports preview/reapply with the retained pointer and Agent list. No new frontend controls or bundle changes are needed: the existing summary renders the updated
currentprojection. Lark continues to consume shared status; no new chat state owner is introduced.Changes since the previous review
The previous review blocked only on repository integrity:
97ff03aa3was an unsigned merge commit that deterministically fails the DCO gate. That commit no longer exists — the two feature commits were rebased onto currentorigin/main, so every commit in the PR range now carriesSigned-off-by.That rebase also surfaced two real regressions from the first head, both now fixed in the head under review:
tests/architecture/test_control_plane_import_boundaries.pyand the maintainability ratchet both rejected a function-local import fromloopx/control_plane/reward_memory.pyintoloopx/capabilities/reward_memory/experiment.py. The reconciled projection now lives in its owning capability (reward_memory_goal_configuration_summaryinloopx/capabilities/reward_memory/configuration.py, which already owns goal configuration and may depend on the control plane). The control plane keeps only the provider-neutral policy projection, so there is no new outward dependency edge and no duplicate receipt rule.Validation:
tests/capabilities tests/presentation tests/cli_commands: 1710 passed, 21 skipped, 1 pre-existing failure onmain(test_reward_memory_feedback_hint.py::test_generated_command_previews_reviewed_event_and_rejects_scope_expansion, reproducible on the base commit and unrelated to this diff).python -m ruff check tests loopx/canary loopx/control_plane loopx/domain_packs loopx/presentation,python -m mypyandgit diff --checkpassed.中文:私有配置变化后旧启用回执失效,但设置页仍可能误报已验证,召回 CLI 又将故障统一标为 disabled。本修改保留漂移保护,设置页复用运行时准入校验,区分期望配置、历史回执与当前可用性;失配时提供沿用原指针及完整 Agent 名单的共享 owner 恢复计划。CLI、managed Turn、状态与现有设置页共用投影,不引入新配置权威。
上次评审唯一的阻塞项是仓库完整性:
97ff03aa3是未签署的 merge commit,必然触发 DCO 门禁;该提交已通过把两个 feature commit rebase 到当前origin/main而消失,PR 范围内每个提交都带有Signed-off-by。rebase 同时暴露并修复了两个真实回归:control plane 越界导入 capability(tests/architecture/test_control_plane_import_boundaries.py)以及由此引起的 maintainability ratchet 未审阅依赖债——现在由 capability 自己持有 reconcile 投影(reward_memory_goal_configuration_summary),control plane 只保留 provider-neutral policy。79 项 focused 测试、Ruff、mypy、git diff --check通过;本机已完成现有 owner 恢复、真实经验写入、精确读回和独立业务召回,私有材料不进入仓库。代码提交审阅,尚未宣称已部署。