Skip to content

fix(chat): amortize historical recovery discovery reads - #7989

Merged
huangruiteng merged 2 commits into
mainfrom
codex/inventory-rpc-20261103-085944
Nov 4, 2026
Merged

huangruiteng merged 2 commits into
mainfrom
codex/inventory-rpc-20261103-085944

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

Lark 的后台投递扫描会检查历史请求能否恢复。同一 Session 的多个历史失败,每次检查都重新解析整个 Turn 目录、读取会话历史和扫描来源控制记录。历史增长后,这些重复 IO 会拖慢队列发现。

本 PR 在一次 pending_delivery_paths() 扫描内创建一个惰性本地读取器,复用同一 Session 的队列、用户历史及来源控制记录;下一次扫描重新读取。请求、Turn 和 binding 仍逐项读取,实际恢复仍执行原有的完整、实时准入检查。

可观察结果是一次扫描中的 Session 级只读事实从“每个候选各读一次”降为该扫描每类一次;候选与副作用不变。该结论不冒充生产 App、真实 WebView、手机或长期延迟收益。

Current repair · 2026-11-04

Head: 8ed84e740bed68d9148435125c054bb9ddf6c28a. Base: main
0c4f6075c6a8f3edcea08b9a21d705dc4e01f8d0.

  • Rebased the two PR commits onto current main.
  • Resolved the external_conversations._context_recovery_plan conflict by preserving both
    main's metadata-capacity/executor-configuration path and this PR's discovery_reads.
  • Retained current main's _original_native_session and metadata-review/executor ownership;
    the scan-local reader changes only the three repeated Session-level reads.
  • The current-main registry smoke was missing anti-entropy-governance; the second commit
    updates that exact builtin inventory and the registry tests/smoke pass.

Changes

  • _RecoveryDiscoveryReads lazily caches one scanner pass's queued-turn state, user messages,
    and source controls. Failed reads are not cached as empty results.
  • context_recovery_observer() supplies one local reader to every request in the scan;
    pending_delivery_paths() creates a fresh reader for the next scan and pins one
    effect-runtime request scope.
  • _context_recovery_plan(..., discovery_reads=...) is explicitly discovery-only. Normal
    recovery/admission rejects a discovery reader, re-reads current authority and remains the
    owner of submission and provider effects.
  • Tests cover same-pass reuse, next-pass reread, cross-Session isolation, failed-read recovery,
    queued input, revoked binding, lost owner authority, forbidden discovery authorization,
    and the real scanner's one-pass/per-request authority behavior.

Validation

  • pytest tests/test_context_recovery_discovery.py tests/test_native_steward_private.py tests/test_lark_private_conversations.py -q --tb=short: 412 passed on the rebase against f818165f5f. The later base advance to 0c4f6075c6 changed only benchmark files, none intersecting this PR's paths; the exact final head then reran the 8 discovery tests, registry tests/smoke and premerge below.
  • pytest tests/test_context_recovery_discovery.py -q --tb=short on final head: 8 passed.
  • pytest tests/capabilities/test_capability_extension_registry.py -q: 22 passed.
  • python examples/capability-extension-registry-smoke.py: passed.
  • Ruff, changed-Python compilation and git diff --check: passed.
  • Standard premerge: passed, including 6 direct checks, 2 catalog canaries, 8 extension-runtime risk smokes and 1 public-boundary scan; zero failures and zero manual holds.

Remaining gaps

No installed App, native WebView, mobile or live provider acceptance was run. The PR establishes
read-count amortization and regression parity, not installed-state latency or long-term benefit.
No persistent cache, retry protocol, scoring, permission or storage-format change is introduced.

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewer: actor_kind=model_agent; model=gpt-6.1-sol; provider=OpenAI; reasoning_effort=max; declaration_source=runtime_reported

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

动机 / Motivation

精确审查 #7989@9ac5fad30829541d7956c80788acbb54b4b5093a,对照 immutable merge-base 1dc98eb8739777a65102e18553658dc70e0f0044,核验 target main 44337e3cb5cbe3e1621550e1fe741853ba5b5a45。同一 Session 的多个失败投递逐条重复读取 queue/history/control 与 runtime code identity。

受影响调用方:Lark private delivery recovery scanner over multiple failed requests in one Session.

同一轮两个失败请求保持候选结果不变,queue/control/runtime identity 从各2次降为各1次;准备失败的 user history 同样2→1,下一轮重新读取。

非目标:不改变恢复准入、不持久化快照、不安装或证明真实模型效果、生产 p95 或长期效用。

剩余缺口:真实模型、生产负载与安装态长程效用尚未验证;全量 premerge 的既有 registry smoke 失败仍保留,合并就绪另判。

改动思路 / Approach

保留现有 TypeScript 决策 owner;Python helper 仅在既有 provider/transport IO 边界复用事实,不创建第二套恢复策略或共享状态协议。

本 PR 只交付发现阶段按轮次复用读取;发现提示不能授权恢复。

复用了现有 caller、typed owner 和错误/重试边界;没有新增持久状态、scope/config owner 或迁移。局部重构已包含于同一边界;跨进程缓存、实时状态修复和独立 UI 都不属于本次交付。

具体改动 / Changes

_RecoveryDiscoveryReads; context_recovery_observer; pending_delivery_paths。

没有独立书面 discovery IO 验收规范;先读 immutable base 的既有 correlation/admission owner 和 TypeScript 准备恢复优先级,未编造 roadmap 验收。

独立验证:当前 exact head 三模块391通过;当前 immutable base 两模块383通过。 独立真实 ChatSessionStore/Core/Lark 扫描探针 base/head 各2通过。普通上下文失败保留两个候选,准备失败因后续等价用户输入只保留最新候选;每轮各类读取2→1,第二轮累计4→2。malformed JSON/null 与非用户无效时间不改变结果,源记录、provider capture 不变,新增 provider 调用0。

负例:新增8项模块覆盖单轮/跨轮/跨 Session、临时 IO 错误不缓存为空、queued input、revoked binding、owner unavailable 的实时拒绝与禁止把 discovery object 用作实际恢复;这些8项已包含在当前完整回归中,不相加。

对主干的风险 / Risks

本地 standard premerge FAIL:registry smoke 在 base/head 同样于第62行失败,期待24个 builtin,实际包含第25个 anti-entropy-governance;完整规范化 traceback 相同,smoke/catalog/registry/entry 源 blob 相同。它在 scanner 前即失败,因此独立归因为 unchanged pre-existing,未改写为通过。其余7项 risk smoke、直接 diff/RFC/compile 和 semantic 检查通过。

当前完整 CI Ruff 范围通过;两个 F811 抑制只标注既有 pytest fixture 参数,未删测试正文。

两边 raw maintainability ratchet 也都 FAIL,完整输出与 formatter blob 相同:render_canonical_todo_sections oversized、magnitude_regressions=0;native gate 将其列为 inherited advisory,未将单项 smoke 标成通过。没有把一次成功、作者计时或测试数量当成生产性能、安装态 adoption 或真实模型效果。

CI 未查询、轮询或等待,状态未知。未知 CI 不单独阻塞有独立证据的 approve;当前回归、必要覆盖、合并就绪与权限仍分开判断。

我的整体评价 / Verdict

当前 exact head 没有验证出的 blocking finding,交付边界完整且可回滚,结论 APPROVE。本条是 author-owned 的 COMMENTED approval conclusion;合并需另取该 head 的 readiness,且本次没有合并授权或执行。

English verdict: APPROVE — the bounded caller fix is independently validated; unchanged baseline failures and merge-readiness holds remain explicit.

@mergify

mergify Bot commented Nov 3, 2026

Copy link
Copy Markdown

This pull request has merge conflicts with main and cannot be merged
until they are resolved. Please rebase or merge the base branch, @loopx-agent.

Choose the remote for the base repository, not an out-of-date fork.
For a fork clone, first inspect git remote -v; upstream must point
to https://github.com/loopx-project/loopx.git. If it is absent, add it
with git remote add upstream https://github.com/loopx-project/loopx.git.
Then run:

git fetch upstream
git rebase upstream/main
# Resolve each conflict, git add the resolved files, then git rebase --continue.
git push --force-with-lease origin HEAD

For a same-repository clone whose origin points to
https://github.com/loopx-project/loopx.git, use origin instead of
upstream for fetch/rebase. If you prefer merging the base, use
git merge <base-remote>/main and push normally.

Keep the DCO Signed-off-by trailer on every commit when you rebase.
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Nov 3, 2026
@huangruiteng
huangruiteng force-pushed the codex/inventory-rpc-20261103-085944 branch from 9ac5fad to ea1154b Compare November 3, 2026 15:27
@mergify mergify Bot removed the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Nov 3, 2026
huangruiteng
huangruiteng previously approved these changes Nov 3, 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.

Reviewer: model_agent · GPT-5 · OpenAI · self_reported

Approval conclusion

动机 / Motivation

Lark 后台扫描与维护恢复的 Agent。

同一 Session 的多个历史失败请求,每次发现检查都会重新读取相同 queue、用户历史和 source-control 记录;历史越长,单次 pending_delivery_paths() 越慢,并可能拖住后续队列发现。

本 head 在一次扫描内惰性复用这些只读事实,下一次扫描重新读取。候选结果、请求/Turn/binding 的逐项读取、实际恢复的实时准入和副作用保持不变。

不新增持久缓存、重试协议、恢复权限或配置;不宣称已安装 App、真实 provider、生产 p95 或长期收益已达标。

改动思路 / Approach

入口仍是 LarkPrivateConversations.pending_delivery_paths();权威事实仍是 File ChatSessionStore 中的 Session、Turn、消息和 private source journal。新的 _RecoveryDiscoveryReads 只是一次扫描内的局部读取器:按 Session 缓存 queued_turns 与 user messages,并缓存一次 source controls。context_recovery_observer() 把同一个局部读取器交给该轮每个请求,下一轮重新创建。本 PR 的边界是修正 discovery IO 复用并覆盖真实权限负例,不增加持久缓存或第二套恢复决策。

发现与准入继续分离。_context_recovery_plan(discovery_only=True) 可使用该读取器;非 discovery 调用若收到它直接报错。实际 recover_failed_request() 仍逐条回读 binding、原请求/Turn、当前 queue、source authority 和 native observation,因此 cache 不能成为恢复许可。pending_delivery_paths() 复用既有 effect-runtime request scope,让一轮扫描固定同一 runtime code identity;没有新增通用 cache 或 decision owner。该判断应保留局部读取器这一最小边界。

具体改动 / Changes

相对 34cc6883fb7c9ca374e652dc900d5caf4fc924e2,本 PR 修改 4 个文件(+218/-7):两个现有发现/读取 owner、一个新增的 discovery regression 模块,以及一个当前 main 的 builtin registry smoke 清单修正。没有新增公共协议、持久字段或 CLI。

本 PR 没有独立书面 discovery IO 规范;不可变 base 中的 external_conversations.py 已定义 discovery/admission 分离,private_conversations.py 已定义 private delivery 队列。实现和测试按这两个既有 owner 的真实边界验收。

关键代码讲解

  • external_conversations.py:41 的 _RecoveryDiscoveryReads 只保存一次扫描内的 queue/history/control hints;读取失败不会写入缓存,下一轮是全新实例。
  • external_conversations.py:80 的 _context_recovery_plan 接受可选的 scan-local reads,但拒绝在 discovery_only=False 时使用它,从代码边界上阻止 discovery hint 成为恢复授权。
  • external_conversations.py:207 的 context_recovery_observer 为一次扫描创建读取器,并把同一个 observer 传给后续请求;实际 request、Turn 和 binding 仍逐个读取。
  • external_conversations.py:212 的 context_recovery_candidate 继续返回“可能是候选”的布尔提示,不执行正常恢复或写入 provider。
  • private_conversations.py:1294 的 pending_delivery_paths 在同一 request scope 内使用该 observer;下一轮扫描重新建 observer,并保留既有 60 秒 probe 间隔。

对主干的风险 / Risks

最强风险是把发现阶段的缓存误解为保证候选可恢复。当前实现把风险限制在提示层:同一扫描中若 queue 新变化,真实 recover_failed_request 仍读当前状态并拒绝;binding 撤销或 owner authority 丢失也在恢复前重新检查。新测试分别覆盖 queued input、revoked binding、owner unavailable,且都断言 capture、Turn 和原始 state bytes 未改变。

另一个风险是失败读取被缓存成“无输入”。_RecoveryDiscoveryReads 只有在读取成功返回后才赋值缓存;测试让 queued_turns 第一次抛错、第二次成功,证明 reader 会重试而不是保留空结果。跨 Session 测试也确认 key 按 session_id 隔离,不会复用另一会话的输入。

当前验证结果:

  • pytest tests/test_context_recovery_discovery.py -q: 8 PASS。
  • pytest tests/test_context_recovery_discovery.py tests/test_native_steward_private.py tests/test_lark_private_conversations.py -q: 405 PASS。
  • 当前 base 的同命令 registry smoke 因 main 新增 anti-entropy-governance 而失败;本 head 将其加入 builtin inventory 后 smoke:PASS,对应 registry tests 22 PASS。
  • ruff、Python compile、diff check、semantic-vocabulary smoke、bilingual RFC check:PASS。
  • 标准 premerge:6 direct、2 catalog(一个继承 maintainability advisory)、8 extension-runtime smokes、1 public-boundary scan,PASS;manual holds 0。

没有查询、轮询或等待 GitHub CI,因为 managed packet 的 wait_for_ci=false。未运行已安装 App、原生 WebView、手机或真实 provider;这些仍是独立的采用/端到端证据缺口,不能用合成 fixture 替代。

语义与 CI 对齐

复用既有 context_recovery_candidate、recover_failed_request、pending_delivery_paths 和 effect-runtime request scope,没有新增共享词汇。本轮改动只改变读取次数,不改变候选判定、准入、发送、存储或权限;registry smoke 的改动只是补齐当前 main 的 builtin inventory。

我的整体评价 / Verdict

APPROVE。 当前精确 head 没有发现阻塞项。长期任务维度改善:历史失败较多时,同一个扫描不再重复读取 Session 级事实,队列发现成本不再随失败请求数线性叠加同一份历史 IO。用户体验维度改善:后台恢复扫描更快,且错误、撤销和权限丢失仍产生安全拒绝;没有新增人工确认或配置。

视觉评审不适用:变更只涉及 Python 后台发现、内存局部读取器和测试清单;没有渲染界面或首屏变化。代码体量以真实回归覆盖为主,生产逻辑集中在两个现有 owner;没有需要在本 PR 新增的第二套缓存/恢复框架。先前的约 5.8× 墙钟数据属于旧候选的合成测量;当前 exact head 只声明读取次数和回归覆盖,仍需独立安装态观测才能声称生产延迟收益。

English verdict: APPROVE — head ea1154b7729da1eeec934cddd849705388d64e20 reuses Session-level discovery reads only within one scanner pass, preserves recovery authority and current main registry behavior, and passes 405 related tests, semantic checks and standard premerge. No blocking finding remains.

@mergify

mergify Bot commented Nov 3, 2026

Copy link
Copy Markdown

This pull request has merge conflicts with main and cannot be merged
until they are resolved. Please rebase or merge the base branch, @loopx-agent.

Choose the remote for the base repository, not an out-of-date fork.
For a fork clone, first inspect git remote -v; upstream must point
to https://github.com/loopx-project/loopx.git. If it is absent, add it
with git remote add upstream https://github.com/loopx-project/loopx.git.
Then run:

git fetch upstream
git rebase upstream/main
# Resolve each conflict, git add the resolved files, then git rebase --continue.
git push --force-with-lease origin HEAD

For a same-repository clone whose origin points to
https://github.com/loopx-project/loopx.git, use origin instead of
upstream for fetch/rebase. If you prefer merging the base, use
git merge <base-remote>/main and push normally.

Keep the DCO Signed-off-by trailer on every commit when you rebase.
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Nov 3, 2026
@huangruiteng
huangruiteng force-pushed the codex/inventory-rpc-20261103-085944 branch from ea1154b to 410d292 Compare November 4, 2026 02:53
loopx-agent and others added 2 commits November 4, 2026 10:53
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
@mergify mergify Bot removed the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Nov 4, 2026
@huangruiteng
huangruiteng force-pushed the codex/inventory-rpc-20261103-085944 branch from 410d292 to 8ed84e7 Compare November 4, 2026 02:55

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

Reviewer: model_agent · GPT-5 · OpenAI · self_reported

Approval conclusion

动机 / Motivation

Lark 后台扫描与维护恢复的 Agent。

同一 Session 的多个历史失败请求,每次发现检查都会重新读取相同 queue、用户历史和 source-control 记录;历史越长,单次 pending_delivery_paths() 越慢,并可能拖住后续队列发现。

本 head 在一次扫描内惰性复用这些只读事实,下一次扫描重新读取。候选结果、请求/Turn/binding 的逐项读取、实际恢复的实时准入和副作用保持不变。

不新增持久缓存、重试协议、恢复权限或配置;不宣称已安装 App、真实 provider、生产 p95 或长期收益已达标。

改动思路 / Approach

入口仍是 LarkPrivateConversations.pending_delivery_paths();权威事实仍是 File ChatSessionStore 中的 Session、Turn、消息和 private source journal。新的 _RecoveryDiscoveryReads 只是一次扫描内的局部读取器:按 Session 缓存 queued_turns 与 user messages,并缓存一次 source controls。context_recovery_observer() 把同一个局部读取器交给该轮每个请求,下一轮重新创建。本 PR 的边界是修正 discovery IO 复用并覆盖真实权限负例,不增加持久缓存或第二套恢复决策。

发现与准入继续分离。_context_recovery_plan(discovery_only=True) 可使用该读取器;非 discovery 调用若收到它直接报错。实际 recover_failed_request() 仍逐条回读 binding、原请求/Turn、当前 queue、source authority 和 native observation,因此 cache 不能成为恢复许可。pending_delivery_paths() 复用既有 effect-runtime request scope,让一轮扫描固定同一 runtime code identity;没有新增通用 cache 或 decision owner。该判断应保留局部读取器这一最小边界。

具体改动 / Changes

相对当前 base 0c4f6075c6a8f3edcea08b9a21d705dc4e01f8d0,本 PR 修改 4 个文件(+218/-7):两个现有发现/读取 owner、一个新增的 discovery regression 模块,以及一个当前 main 的 builtin registry smoke 清单修正。没有新增公共协议、持久字段或 CLI。

本 PR 没有独立书面 discovery IO 规范;当前 base 中的 external_conversations.py 已定义 discovery/admission 分离,private_conversations.py 已定义 private delivery 队列。实现和测试按这两个既有 owner 的真实边界验收。rebase 保留了新 main 的 metadata_capacity、executor configuration、native-session 与 metadata-review ownership,只把原来的 Session history 读取替换为 scan-local reader。

关键代码讲解

  • external_conversations.py:41 的 _RecoveryDiscoveryReads 只保存一次扫描内的 queue/history/control hints;读取失败不会写入缓存,下一轮是全新实例。
  • external_conversations.py:80 的 _context_recovery_plan 接受可选的 scan-local reads,但拒绝在 discovery_only=False 时使用它,从代码边界上阻止 discovery hint 成为恢复授权。
  • external_conversations.py:207 的 context_recovery_observer 为一次扫描创建读取器,并把同一个 observer 传给后续请求;实际 request、Turn 和 binding 仍逐个读取。
  • external_conversations.py:212 的 context_recovery_candidate 继续返回“可能是候选”的布尔提示,不执行正常恢复或写入 provider。
  • private_conversations.py:1294 的 pending_delivery_paths 在同一 request scope 内使用该 observer;下一轮扫描重新建 observer,并保留既有 60 秒 probe 间隔。

对主干的风险 / Risks

最强风险是把发现阶段的缓存误解为保证候选可恢复。当前实现把风险限制在提示层:同一扫描中若 queue 新变化,真实 recover_failed_request 仍读当前状态并拒绝;binding 撤销或 owner authority 丢失也在恢复前重新检查。新测试分别覆盖 queued input、revoked binding、owner unavailable,且都断言 capture、Turn 和原始 state bytes 未改变。

另一个风险是失败读取被缓存成“无输入”。_RecoveryDiscoveryReads 只有在读取成功返回后才赋值缓存;测试让 queued_turns 第一次抛错、第二次成功,证明 reader 会重试而不是保留空结果。跨 Session 测试也确认 key 按 session_id 隔离,不会复用另一会话的输入。

当前验证结果:

  • pytest tests/test_context_recovery_discovery.py -q: 8 PASS。
  • pytest tests/test_context_recovery_discovery.py tests/test_native_steward_private.py tests/test_lark_private_conversations.py -q: 在前一 rebase f818165f5f 上 412 PASS。随后 main 前进到 0c4f6075c6 的 diff 只涉及 benchmark 文件,与本 PR 路径无交集;最终 head 另行重跑了下面 8 项 discovery、registry 与 premerge。
  • 当前 base 的同命令 registry smoke 因 main 新增 anti-entropy-governance 而失败;本 head 将其加入 builtin inventory 后 smoke:PASS,对应 registry tests 22 PASS。
  • ruff、Python compile、diff check、semantic-vocabulary smoke、bilingual RFC check:PASS。
  • 最终 head 标准 premerge:6 direct、2 catalog、8 extension-runtime smokes、1 public-boundary scan,PASS;zero failures、manual holds 0。

没有查询、轮询或等待 GitHub CI,因为 managed packet 的 wait_for_ci=false。未运行已安装 App、原生 WebView、手机或真实 provider;这些仍是独立的采用/端到端证据缺口,不能用合成 fixture 替代。

语义与 CI 对齐

复用既有 context_recovery_candidate、recover_failed_request、pending_delivery_paths 和 effect-runtime request scope,没有新增共享词汇。本轮改动只改变读取次数,不改变候选判定、准入、发送、存储或权限;registry smoke 的改动只是补齐当前 main 的 builtin inventory。

我的整体评价 / Verdict

APPROVE。 当前精确 head 没有发现阻塞项。长期任务维度改善:历史失败较多时,同一个扫描不再重复读取 Session 级事实,队列发现成本不再随失败请求数线性叠加同一份历史 IO。用户体验维度改善:后台恢复扫描更快,且错误、撤销和权限丢失仍产生安全拒绝;没有新增人工确认或配置。

视觉评审不适用:变更只涉及 Python 后台发现、内存局部读取器和测试清单;没有渲染界面或首屏变化。代码体量以真实回归覆盖为主,生产逻辑集中在两个现有 owner;没有需要在本 PR 新增的第二套缓存/恢复框架。先前的约 5.8× 墙钟数据属于旧候选的合成测量;当前 exact head 只声明读取次数和回归覆盖,仍需独立安装态观测才能声称生产延迟收益。

English verdict: APPROVE at 8ed84e740bed68d9148435125c054bb9ddf6c28a. The rebased head reuses Session-level discovery reads only within one scanner pass, preserves current-main recovery and registry semantics, and passes 8 exact-head discovery tests, 22 registry tests, the registry smoke, static checks and all 11 local premerge checks. No blocking finding remains.

@huangruiteng
huangruiteng merged commit 79b7818 into main Nov 4, 2026
8 of 9 checks passed
@huangruiteng
huangruiteng deleted the codex/inventory-rpc-20261103-085944 branch November 4, 2026 02:56
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