Skip to content

fix(responses,claude): detect deferred V1 collaboration tools and bound the picker upload drain - #7010

Merged
lidge-jun merged 3 commits into
devfrom
codex/rt284-issues-proxy
Oct 12, 2026
Merged

lidge-jun merged 3 commits into
devfrom
codex/rt284-issues-proxy

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Summary

Two proxy fixes stacked on the owner bundle.

Verification

  • Lane: deferred collab surface 34 pass with mutation checks red per rule; collaboration set 366 pass on Bun 1.4.3 and 1.4.0; picker upload plus the new deterministic linger test 24 pass on Bun 1.4.2 and 1.4.3. Independent gpt-6.1-sol reviews PASS at each final head.
  • Union gates at the final stack head 3441130ea8 (Bun 1.4.3 test runner, external checkout): bun run typecheck, structure:check, privacy:scan, skill:surface:check exit 0; guards (test-layout, layout tooling with the pinned runner, file-size ratchet, repo hygiene, skill-ocx, structure-ssot) 110 pass / 0 fail; GUI locale parity 27 pass; lint:gui and build:gui exit 0; scripts/test-layout/layout.json 1999 lines.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • New Features
    • Codex Desktop requests that identify multi_agent_v1 as a deferred tool can now receive proactive collaboration guidance, when the request also confirms support.
  • Bug Fixes
    • When a Claude picker request is refused while the client is still uploading, the remaining input is discarded and the connection closes after the reply finishes sending, with a maximum 30-second delay. Closing the client connection cancels the pending close.
  • Documentation
    • Updated guidance explains when deferred-tool evidence is recognized and how long the picker connection may remain open after a refusal.

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner October 12, 2026 17:27
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T17:32:37.359206Z d9ce24c PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

📝 Walkthrough

Walkthrough

The change adds deferred V1 collaboration evidence from developer tool-state fragments and combines it with existing collaboration-surface evidence. It also bounds the picker’s post-reply handling of abandoned client input with a delayed drop.

Changes

Deferred V1 collaboration evidence

Layer / File(s) Summary
Deferred namespace parsing and replay
src/server/responses/deferred-collab-surface.ts:39–158, devlog/_plan/261013_deferred_v1_collab_surface/000_plan.md:20–37, devlog/_plan/261013_deferred_v1_collab_surface/010_deferred_v1_evidence.md:17–61
The parser reads standalone <tools> fragments from developer messages and replays snapshots and diffs. Malformed fragments and specified omissions clear carried state. Deferred evidence requires an eligible host and the multi_agent_v1 namespace.
Collaboration-surface analysis
src/server/responses/code-mode-collab-surface.ts:28–37,176–204, src/server/responses/collaboration.ts:12–13,322–330, devlog/_plan/261013_deferred_v1_collab_surface/010_deferred_v1_evidence.md:63–77
analyzeCodeModeExec reports genuine exec, rendered V1, and foreign-claim evidence. collabSurface combines rendered and deferred V1 evidence with direct surface evidence; foreign claims can produce a null result.
Guidance validation and documentation
tests/codex-integration/deferred-collab-surface.test.ts:82–292, docs-site/src/content/docs/guides/sub-agent-surface.md:131–135, structure/subagents.md:452–469, scripts/test-layout/layout.json:1247, tests/fixtures/test-layout-expected.json:790
Integration tests cover host qualification, fragment replay, malformed and omitted data, surface conflicts, continuations, and guidance conditions. Documentation describes the deferred-tool evidence and its limits. The test-layout files register the new integration test.

Picker abandoned-input drain

Layer / File(s) Summary
Schedule and cancel the delayed drop
src/claude/intercept/picker-listener.ts:37–64,166–169,485–500, structure/clients/claude-desktop.md:234–248, devlog/_plan/261013_deferred_v1_collab_surface/020_6984_verification.md:24–45
The listener schedules a 30-second client drop after the reply finishes flushing and cancels it if the client closes first. The documentation records that a client that stops reading may lose unread reply bytes when the timer expires.
Picker regression tests and registration
tests/claude-integration/claude-picker-linger.test.ts:18–120, scripts/test-layout/layout.json:23, tests/fixtures/test-layout-expected.json:32, devlog/_plan/261013_deferred_v1_collab_surface/020_6984_verification.md:46–78
Tests check the refusal response, the armed delay, continued upload before the drop, zero upstream relays, and timer cancellation on disconnect. The verification record notes that the combined changed-test run was not green, while affected suites passed in isolated reruns.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant collabSurface
  participant analyzeCodeModeExec
  participant deferredV1Evidence
  collabSurface->>analyzeCodeModeExec: Analyze tool declarations
  analyzeCodeModeExec-->>collabSurface: Return host, rendered V1, and foreign-claim flags
  collabSurface->>deferredV1Evidence: Check developer history using host analysis
  deferredV1Evidence-->>collabSurface: Return deferred V1 evidence
Loading

Merge Risk: ⚪ Minimal · up to ed2e4

The stale plan example does not affect the implemented behavior. The change is mergeable after normal checks.

Pre-merge checks · Passed 4 · Failed 1

Failed Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 40.91% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 6 files. (8 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely identifies both primary changes: deferred V1 collaboration-tool detection and the bounded picker upload drain.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.

Full details: Docstring Coverage

Explanation

Docstring coverage is 40.91% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 6 files. (8 skipped: 8 unsupported.)


  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR

🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Oct 12, 2026
@lidge-jun
lidge-jun force-pushed the codex/rt284-issues-proxy branch 2 times, most recently from 80f886c to dce81dc Compare October 12, 2026 20:17
@lidge-jun
lidge-jun force-pushed the codex/rt284-owner-bundle branch from e831e86 to fe6768c Compare October 12, 2026 20:34
…tools> fragment

Codex defers the V1 collaboration tools whenever the model supports tool
search, which every OpenCodex catalog row does. The code-mode exec
description then lists none of them (#6977 reads only the rendered case),
so collabSurface() stayed null and V1 Max/Ultra turns never received the
proactive delegation guidance.

When its deferred_tool_world_state feature is on (Codex Desktop sessions
receive it), codex-rs sends a developer <tools> fragment listing the
deferred namespaces, then Added/Removed diffs on later turns.
deferred-collab-surface.ts replays those fragments in input order from
developer messages only and treats a current multi_agent_v1 row as V1
evidence, beside a genuine code-mode exec or a structured tool_search
host. Omitted rows never establish a namespace; omitted removals and
malformed fragments clear what was carried. The evidence combines with
the direct and rendered surfaces exactly like #6977: it never yields v2
and yields to any contradicting surface.

Clients without the feature still carry no V1 evidence, and the row
cannot show whether an embedder's allowlist dropped spawn_agent alone;
both limits are documented in structure/subagents.md.

Refs #6844
#6986 made the picker's TCP front keep reading and discarding client
ciphertext after the backend ends a connection, so an HTTP/1.1 refusal,
generated 502 or early reply sent with Connection: close is not reset
before the client reads it. That discard had no end: a client that keeps
trickling an abandoned upload held the connection until listener
shutdown.

Once the backend has ended and the reply has flushed to the client
socket (finish), the front now arms a drop after
PICKER_ABANDONED_INPUT_LINGER_MS (30 s); a connection that closes first
cancels it. Arming after the flush keeps the reply and its
Connection: close behaviour intact. The timer is injected through a test
seam, so claude-picker-linger.test.ts fires it deterministically with a
half-open TLS client that never stops uploading; the existing
claude-picker-upload cases are unchanged.

Refs #6984
@lidge-jun
lidge-jun force-pushed the codex/rt284-issues-proxy branch from dce81dc to ed2e435 Compare October 12, 2026 20:37
Base automatically changed from codex/rt284-owner-bundle to dev October 12, 2026 21:11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔇 Additional comments (15)
src/claude/intercept/picker-listener.ts (2)

490-500: Guard the linger against a timer that arms after the connection is already closing.

At Line 494, the guard checks only client.destroyed. A close event can fire after that check and before finish. In that case, client.once("close", cancel) at Line 496 never runs, because close has already been emitted. The timer then fires 30 seconds later and calls client.destroy() on a socket that is already closed. That call is a no-op and the timer is short-lived. The risk is low, and the destroyed check covers the common case.

The finish path at Line 499 is the only path where a close can arrive before the callback runs. Node emits finish before close, so the order is safe in practice. No change is required.


493-497: Remove the finish listener when the client closes before the reply is flushed.

At Line 499, client.once("finish", linger) stays registered if client closes without emitting finish. For example, a reset destroys the socket and no finish event follows. The listener is garbage-collected with the socket, so nothing leaks. No linger call occurs after destruction, because the client.destroyed guard at Line 494 covers that case. No change is required.

devlog/_plan/261013_deferred_v1_collab_surface/020_6984_verification.md (1)

1-1: LGTM!

structure/clients/claude-desktop.md (1)

234-248: LGTM!

tests/claude-integration/claude-picker-linger.test.ts (1)

1-121: LGTM!

devlog/_plan/261013_deferred_v1_collab_surface/000_plan.md (1)

1-81: LGTM!

src/server/responses/deferred-collab-surface.ts (1)

1-158: LGTM!

I checked the following cases against the code:

  • The opening and closing tag checks reject text that only mentions the tag.
  • parseFragment rejects a repeated group, an Added group after Removed, an empty group, and content after the empty-state line.
  • ROW uses [\s\S] so U+2028 and U+2029 stay opaque.
  • The replay switch handles malformed, snapshot, and diff. Omitted removals clear before the explicit adds.
  • Line 140 clears on the empty-state notice for both snapshot and diff.

The OpenGrep hint at Line 99 is a false positive. ROW.exec is RegExp.prototype.exec, not child_process.exec.

src/server/responses/code-mode-collab-surface.ts (1)

13-18: LGTM!

Also applies to: 28-36, 176-195, 197-204

src/server/responses/collaboration.ts (1)

12-13: LGTM!

The rendered-only paths match the old behavior:

  • Rendered V1 with a foreign claim returns null.
  • Rendered V1 alone follows the same direct-surface rule as before.
  • No inferred V1 returns direct.surface.

Also applies to: 322-330

structure/subagents.md (1)

451-469: LGTM!

tests/codex-integration/deferred-collab-surface.test.ts (1)

1-292: LGTM!

The tests cover the following, and the continuation suite isolates OPENCODEX_HOME:

  • Grammar and replay.
  • Budget omissions.
  • Host gates.
  • Surface combination.
  • Continuations.
scripts/test-layout/layout.json (1)

23-23: LGTM!

Also applies to: 1247-1247

tests/fixtures/test-layout-expected.json (1)

32-32: LGTM!

Also applies to: 790-790

docs-site/src/content/docs/guides/sub-agent-surface.md (1)

131-135: 📐 Maintainability & Code Quality

The translated pages do not state that deferred V1 tools are always undetectable. They describe general V1 guidance behavior and omit the English page's code-mode detail, but that omission does not contradict the updated English paragraph.

devlog/_plan/261013_deferred_v1_collab_surface/010_deferred_v1_evidence.md-66-74 (1)

66-74: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

Update the plan: its deferredV1Evidence signature and collabSurface() snippet no longer match the implementation.

The plan shows deferredV1Evidence(parsed) (Line 20) and calls it with one argument (Line 70). The implemented function in src/server/responses/deferred-collab-surface.ts Line 154 takes (parsed, codeMode). The plan also says the helper calls analyzeCodeModeExec itself (Line 23). The implementation receives that analysis from collabSurface(). A later reader who follows this plan will reintroduce a second scan of the exec tool description.

Update the signature and the call site in the plan to match the code.


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: d3665632-f4a4-492b-a956-8a85560b34d1
📥 Commits

Reviewing files that changed from the base of the PR and between 8f10f23 and ed2e435.

📒 Files selected for processing (14)
  • devlog/_plan/261013_deferred_v1_collab_surface/000_plan.md
  • devlog/_plan/261013_deferred_v1_collab_surface/010_deferred_v1_evidence.md
  • devlog/_plan/261013_deferred_v1_collab_surface/020_6984_verification.md
  • docs-site/src/content/docs/guides/sub-agent-surface.md
  • scripts/test-layout/layout.json
  • src/claude/intercept/picker-listener.ts
  • src/server/responses/code-mode-collab-surface.ts
  • src/server/responses/collaboration.ts
  • src/server/responses/deferred-collab-surface.ts
  • structure/clients/claude-desktop.md
  • structure/subagents.md
  • tests/claude-integration/claude-picker-linger.test.ts
  • tests/codex-integration/deferred-collab-surface.test.ts
  • tests/fixtures/test-layout-expected.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

@lidge-jun
lidge-jun merged commit b71d1e1 into dev Oct 12, 2026
79 of 83 checks passed
@lidge-jun
lidge-jun deleted the codex/rt284-issues-proxy branch October 12, 2026 21:44
agentHits added a commit to agentHits/opencodex that referenced this pull request Oct 12, 2026
Ten more commits landed on dev (lidge-jun#7010, lidge-jun#7011). The merge is automatic and
none of them touch gui/, src/oauth/, src/providers/ or
src/server/management/, the areas this branch changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant