Skip to content

ci: run the cross-version tests when the chat send builders or the RPC request path change - #25061

Merged
brennanb2025 merged 6 commits into
mainfrom
brennanb2025/ci-cross-version-selector
Oct 4, 2026
Merged

brennanb2025 merged 6 commits into
mainfrom
brennanb2025/ci-cross-version-selector

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 4 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​191 $\color{#cf222e}{\Huge{\mathbf{−}}}$​3 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​188
Prod 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​14 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​14

Problem

CI skipped the cross-version wire compatibility tests for #24901, a PR that changed what a client sends to a host. Those tests (tests/e2e/cross-version-wire/) run current code against the newest release, to catch an older client or host breaking on what a newer one sends.

#24901 changed the shared builder that produces the structured chat send request and its fingerprint (src/shared/structured-agent-session-send-mutation.ts, called through structured-agent-session-outbox.ts), plus orchestration code. The desktop app uses that builder to send chat messages to remote Orca servers, which can run a different version. So a mistake there could get a user's message refused by an older server. The job was marked skipped, and the PR's compatibility evidence rested on running the suites by hand.

The cause: the PR job selector (config/scripts/pr-code-change-scope.mjs) runs that job only for files listed in CROSS_VERSION_WIRE_PREFIXES, and the send builders were not listed. There was also a deeper gap: even when the job ran, no suite built a send with the shared builder. The agent-session suite computed its own fingerprint, so a builder change an older host rejects would still have passed.

What this changes for you

Before After
PR changes the chat send builder or outbox Cross-version job skipped Job runs, and a send built by the changed builder is sent to the newest release's host
Builder change an older host refuses (wrong field, or a fingerprint it derives differently), for a plain message or one queued behind a running turn Not caught anywhere The new agent-session send test fails
PR changes the request-dispatch code every request passes through (reply and error building, and the orchestration checks in src/main/runtime/rpc/) Cross-version job skipped Job runs
PR changes only orchestration RPC methods or send-agent-turn.ts Job skipped Still skipped: no cross-version suite calls them (see below)

CI cost: over the last 400 commits on main the job would have run on 78 instead of 74.

The change

New tests/e2e/cross-version-wire/cross-version-agent-session-send.unit.test.ts. The suite's send params now come from the same outbox functions the desktop app sends from (createStructuredAgentSessionOutboxEntry and structuredAgentSessionSendRequest), not a hand-built envelope. The test sends that request to both the current build and the newest release (v1.4.219 today) through each build's real dispatcher. It runs twice: once for a plain message, and once for a message queued behind a running turn (delivery: 'queue-if-active', which joins the fingerprint). Per build it checks two things. First, the build's own request schema accepts the send and the call reaches the host. Second, the build's own admission code (sendPlan and admitAndRunAgentSessionMutation, loaded from that build) accepts the fingerprint the client declared. A mismatch there is what an older host refuses as an operation conflict.

The host in this test is the suite's existing stub, so the release's admission runs on the params its dispatcher handed that stub, with no journal open. Admission checks the fingerprint first and then stops at the missing journal, so the test expects "session not attached" and fails on "fingerprint mismatch". versioned-agent-session-wire.ts gains admitSend per build for this.

Because sendParams in the shared manifest now uses the builder, the existing agent-session tests that send through a real current host (the restart cursor tests) also go through the builder.

Selector (CROSS_VERSION_WIRE_PREFIXES), choosing only code a suite executes:

  • src/shared/structured-agent-session-mutation.ts, structured-agent-session-send-mutation.ts, structured-agent-session-outbox.ts: exact files. The rest of the outbox family (-outbox-admission, -outbox-delivery, -outbox-stop-withdrawal) is client-side queueing that no suite runs, so it stays off.
  • src/main/runtime/rpc/core.ts, errors.ts, rpc-streaming-dispatcher.ts, orchestration-contract-fence.ts, orchestration-session-caller.ts, orchestration-legacy-compatibility.ts, orchestration-mutation-executor.ts, and src/shared/orchestration-rpc-contract.ts: every request the suites dispatch runs through these, whatever its method (the registry, the reply and error builders the suites compare across versions, the migration fence, the caller-resolution check, the old-client compatibility hook, and the mutation wrapper). Other orchestration-legacy-* files do work only for orchestration.* methods and stay off.
  • The orchestration database entries are unchanged from main (db.ts, db/, orchestration-schema-version-skew).

config/scripts/pr-code-change-scope-cross-version-send-path.test.mjs pins each rule, and pins that the outbox siblings, send-agent-turn.ts, the orchestration RPC methods, and renderer-only structured chat modules stay off.

Why this approach

Selecting all of src/main/runtime/orchestration/ and src/main/runtime/rpc/methods/orchestration* would make the job run without testing anything there. The suites only load those modules because the dispatcher registers every RPC method; none of them calls an orchestration method or send-agent-turn.ts, so a break would only fail if a module stopped loading.

Computing the selection from the suites' import graph has the same problem at a larger scale. That graph reaches 2353 source files through the method registry. Selecting on it would run the job on about 142 of the last 400 commits, mostly git, GitHub and SSH code the suites never run. It would also need a source checkout and a bundler in the small job that decides which jobs run.

Making the send builder covered for real costs one small test, and it tests the producer #24901 changed: a request a current client really sends to a host of another version.

What is still not covered

  • No cross-version suite calls an orchestration.* RPC method. A PR that changes only those methods still skips the job. Adding a skew test for them is separate work.
  • send-agent-turn.ts builds a send inside the host process and hands it to that same host, so its builder and host are always the same build. Version skew does not reach that path, and it stays off.
  • The phone app builds its own agentSession.send request and fingerprint (mobile/src/session/mobile-structured-agent-session-send.ts). No suite runs it, and a change there does not select the job.
  • Attachments (image blocks in a message) are not part of the new test.
  • Some modules the suites exist to test are still missing from the list (for example the worktree identity migration and the terminal retirement proof files). That gap is older than this PR, and a test that keeps the list in step with the suites is planned as a follow-up.

Testing

  • The three selector test files pass (68 tests). Against main's selector, 11 of the 13 new "runs" cases fail and all 10 "stays off" cases pass.
  • The whole tests/e2e/cross-version-wire/ directory passes locally: 16 files, 96 tests.
  • The two agent-session cross-version files pass (21 tests). Each send case also checks that a deliberately wrong fingerprint is refused as "fingerprint mismatch" by both builds, so the "session not attached" answer cannot pass without the fingerprint check having run.
  • Proof the new test catches a skew, each change made in both the builder and the current host's send plan so current code still agrees with itself, then reverted:
    • Adding a field to the send fingerprint: both new cases fail on v1.4.219 only, with the release's admission answering "fingerprint mismatch". The other 19 agent-session tests stay green.
    • Dropping delivery from the fingerprint: only the queued-message case fails, on v1.4.219 only, with "fingerprint mismatch".
  • oxlint (full), the anti-slop lint on the changed files, oxfmt --check, and pnpm run check:code-quality:changed pass. The e2e typecheck project (config/tsconfig.e2e.json, not yet enforced in CI) reports no errors in the changed files.
  • This PR edits the selector itself, which makes every PR job run, so CI here runs the cross-version job too.

…hange

The selector skipped the cross-version wire job for #24901, which changed the
shared agent-send path, the structured send envelope builders, and orchestration
RPC code. Route the send payload/fingerprint builders, src/main/runtime/orchestration/,
and the orchestration RPC methods to the job, and pin each rule in a test.
@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: bd3bdaaa-417f-4c1f-abd7-cf1e34e7b445
📥 Commits

Reviewing files that changed from the base of the PR and between d77851b and cf6bd44.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 89a47c6b-63ce-41b4-897a-ddd5023de59d
📥 Commits

Reviewing files that changed from the base of the PR and between c3a2330 and d77851b.

📒 Files selected for processing (1)
  • tests/e2e/cross-version-wire/cross-version-agent-session-send.unit.test.ts

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


📝 Walkthrough

Walkthrough

The cross-version wire path list now includes agent-session mutation, outbox, RPC dispatch, and orchestration paths. Classification tests check which paths enable the job. The wire harness loads mutation-plan and admission modules for working-tree and baseline-release builds. A new test checks plain and queue-if-active sends, successful replies, host delivery values, admission refusal with sessionNotAttached, and fingerprintMismatch when the fingerprint changes.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to d7785

This change expands CI selection and cross-version send/admission coverage without changing application behavior; no actionable merge-blocking risk remains.

Architecture Summary

Architecture risk: 🔵 Low · up to d7785

The change affects 2 systems.

Changed systems: tests, config

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — tests (service) was modified; 3 changed files map to changed impact.
  • observed — config (service) was modified; 2 changed files map to changed impact.

Before / after behavior

  • observed — Modified behavior in config/scripts/pr-code-change-scope-cross-version-send-path.test.mjs: Imports classifyPrJobs and adds a comment distinguishing executed-code coverage from merely loading a registered module.
  • observed — Modified behavior in config/scripts/pr-code-change-scope-cross-version-send-path.test.mjs: Adds parameterized assertions that changes to the listed send-path, RPC, orchestration, contract, and migration files set should_run and cross-version-wire to true.
  • observed — Modified behavior in config/scripts/pr-code-change-scope-cross-version-send-path.test.mjs: Adds parameterized assertions that changes to the listed outbox, composer, reducer, send-turn, caller-identity, legacy-mail, and orchestration-method files set should_run to true and cross-version-wire to false.
  • observed — Modified behavior in config/scripts/pr-code-change-scope.mjs: Added three structured agent-session mutation and outbox paths to the cross-version-wire job’s watched paths. The accompanying comment describes coverage of the client-built send and host-rederived fingerprint.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 6 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly summarizes the main change: running cross-version tests when chat send builders or the RPC request path change.
Description check ✅ Passed The description gives detailed context, changes, rationale, known gaps, and test results. It omits several template sections, including the ELI5 heading, the linked-issue entry, Visual Proof (or N/A w…
✨ 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
  • Autopilot · 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.

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

✅ No new issues found.

Reviewed changes

  • Broadened CROSS_VERSION_WIRE_PREFIXES (config/scripts/pr-code-change-scope.mjs:168-203) — adds the structured send builders (structured-agent-session-mutation, …-send-mutation, …-outbox), replaces the three narrow orchestration entries with the whole src/main/runtime/orchestration/ directory, and adds the src/main/runtime/rpc/methods/orchestration method tree and its orchestration*.ts siblings.
  • New routing test (config/scripts/pr-code-change-scope-cross-version-send.test.mjs) — pins 13 paths that should trigger the cross-version-wire job and 4 that should not, via classifyPrJobs.

I verified the added prefixes are a strict superset of the three removed entries, so no prior coverage is lost; every file path named in the test exists; and the three selector suites (62 tests), oxlint, and check:code-quality:changed all pass. The new suite is auto-discovered through config/scripts/**/*.test.mjs in ci-unit-files.mjs.

One thing the PR body states plainly and I confirmed: no cross-version suite calls an orchestration RPC method or send-agent-turn.ts directly today, so these rules make the existing suites run on such PRs rather than add a new skew test for those paths. That is forward-looking coverage, not a defect.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

The agent-session suites now build their send through the shared outbox
builder and check it against the release host's schema and fingerprint,
so the send builder and outbox are selected exactly. Load-only
orchestration rules are dropped; the dispatcher-path files every suite
request runs through are selected instead.

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

✅ No new issues found.

Reviewed changes

  • Rewrote the cross-version selector rules. CROSS_VERSION_WIRE_PREFIXES now selects the send builders by exact file (structured-agent-session-mutation.ts, …-send-mutation.ts, …-outbox.ts) and the dispatcher-path files every dispatched request runs through (rpc/core.ts, rpc-streaming-dispatcher.ts, orchestration-contract-fence.ts, orchestration-session-caller.ts, orchestration-legacy-compatibility.ts, orchestration-mutation-executor.ts, shared/orchestration-rpc-contract.ts), dropping the prior whole-orchestration/-dir and methods/orchestration rules.
  • Added cross-version-agent-session-send.unit.test.ts. It builds a current client's agentSession.send through the shared outbox, dispatches it to both the current and newest-release dispatchers, and asserts it reaches each host with a declared fingerprint equal to that build's own re-derivation.
  • Switched the manifest's sendParams to the outbox builder (createStructuredAgentSessionOutboxEntry + structuredAgentSessionSendRequest), so the existing agent-session tests now exercise the real client path.
  • Added hostSendFingerprint per build in versioned-agent-session-wire.ts, reconstructing admission's digest from each build's own sendPlan and computeAgentSessionPayloadFingerprint.

I verified the hostSendFingerprint reconstruction mirrors admitAndRunAgentSessionMutation (structured-agent-session-mutation-admission.ts:86) exactly; that the new sendParams output is shape- and value-identical to the old hand-built envelope for whitespace-free text (so the restart-cursor tests are unaffected); that all 12 newly selected paths exist; and that the selector suites (63 tests) and oxlint on the five changed files pass.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

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

🧹 Nitpick comments (1)
tests/e2e/cross-version-wire/cross-version-agent-session-send.unit.test.ts (1)

56-56: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Exercise release-host admission, or narrow the stated contract.

The test states that release admission must re-derive the send fingerprint. Instead, structuredHostStub.send returns success directly, and hostSendFingerprint separately recomputes the fingerprint. The test can pass even when real release admission would reject the send. Route the request through the release build’s actual mutation host to cover admission. If the intended scope is only dispatcher-to-host wire output, remove the admission guarantee from the test’s contract.


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: da5e2c34-b0c2-4484-adc3-c7ab7d31e581
📥 Commits

Reviewing files that changed from the base of the PR and between de9aa01 and f243192.

📒 Files selected for processing (5)
  • config/scripts/pr-code-change-scope-cross-version-send-path.test.mjs
  • config/scripts/pr-code-change-scope.mjs
  • tests/e2e/cross-version-wire/cross-version-agent-session-send.unit.test.ts
  • tests/e2e/cross-version-wire/structured-agent-session-surface-manifest.ts
  • tests/e2e/cross-version-wire/versioned-agent-session-wire.ts

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

@brennanb2025 brennanb2025 changed the title ci: run the cross-version tests when orchestration or the shared send code changes ci: run the cross-version tests when the chat send builders or the RPC request path change Oct 3, 2026

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

✅ No new issues found.

Reviewed changes

  • Exercised the release's own send admission — versioned-agent-session-wire.ts replaces the fingerprfint re-derivation (hostSendFingerprint) with admitSend, which loads each build's own admitAndRunAgentSessionMutation and runs it with no journal. A fingerprint the build derives differently now surfaces as fingerprintMismatch; an agreed one stops at sessionNotAttached, which the test asserts. This is stronger than comparing digests: it is the release's real admission deciding.
  • Covered a queued send — the send test is parameterised over a plain message and delivery: 'queue-if-active', which joins the operation fingerprint, so a builder that drops delivery is caught.
  • Added src/main/runtime/rpc/errors.ts to the selector (pr-code-change-scope.mjs:184) and pinned it in the routing test. It is imported eagerly by dispatcher.ts:12 and rpc-streaming-dispatcher.ts:9, so it is genuinely on every dispatched request's path.

I confirmed the new white-box assumption against the pinned baseline: the v1.4.219 checkout (commit 482a2438d5) exports admitAndRunAgentSessionMutation from the same module path with the same ordering — fingerprint check, then the absent-prepareSession skip, then journal() → sessionNotAttached — so the test is meaningful against the real release, not just current source. The now-unused computeAgentSessionPayloadFingerprint import was dropped cleanly.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review status

Problem. CI skipped the cross-version wire compatibility tests for #24901, even though that PR changed the shared builders that produce a structured chat send and its fingerprint. Those tests run current code against the latest release, so an older and a newer Orca can't silently disagree. The job selector (config/scripts/pr-code-change-scope.mjs) runs that job only for files on a hand-kept list, and the send code wasn't on it. Adding files to the list wouldn't have been enough: no cross-version test sent a message through those builders, so the job could run and still miss a break.

What changes for you. No app behavior changes. For contributors: a PR that changes the chat send builders, or the code that handles every RPC request and builds every reply, now runs the cross-version job. That job now catches a send an older host would refuse. Over the last 400 commits on main, the job would have run on 78 instead of 74.

What review changed (relative to the first version of this PR):

  • Dropped: the first version selected all of src/main/runtime/orchestration/ and the orchestration RPC methods. No cross-version test calls that code; it is only loaded, so those rules cost CI time without catching anything. The three original orchestration database rules are restored.
  • Added a real test: cross-version-agent-session-send.unit.test.ts builds a send with the app's own outbox builders and sends it through both the current build's and the release's real request handling. It covers a plain message and a queued one (delivery: 'queue-if-active'). Each build's own admission code then re-derives the fingerprint, so nothing in the comparison is copied from current code. A negative control proves the fingerprint check really ran.
  • Narrowed the send rules: they now name structured-agent-session-send-mutation.ts and -outbox.ts exactly. The broader outbox prefix also matched unrelated queue modules.
  • Added the request-path files that every request the tests send goes through: rpc/core.ts, rpc-streaming-dispatcher.ts, errors.ts, the dispatcher's orchestration compatibility files, and src/shared/orchestration-rpc-contract.ts.
  • Fixed a wrong "stays off" case for repo.ts, which clients do call on hosts of other versions.
  • Retitled the PR and rewrote the body to match.

Verified:

  • On purpose, the fingerprint was changed in both the builder and the current host. The new test went red against the release only, and both the plain and the queued case failed. The same happened when delivery alone was dropped from the fingerprint.
  • Against main's selector, 11 of the 13 "runs the job" cases fail, and all "stays off" cases pass.
  • All of tests/e2e/cross-version-wire/ passes locally (16 files, 96 tests), as do the selector tests (68). The cross-version CI job passed on the previous head; CI for this head is still running.
  • Lint and changed-code quality checks pass.

Not verified / known:

  • The CI typecheck failure comes from main, not this PR: claude-child-work-evidence-retention.test.ts:88, where two merged PRs conflict. Draft test(claude): pass the prompt registry the child-work drain now requires #25063 fixes it.
  • No app QA: this change is CI and tests only, so there's no UI to exercise.
  • Still not covered by any cross-version test: orchestration RPC methods, send-agent-turn.ts (which runs inside a single host), and the phone app's own send builder.

Deferred follow-ups:

  • A guard test that fails when a cross-version test imports a file the list doesn't cover.
  • Existing gaps where a test's own subject file doesn't trigger the job, such as worktree-identity-migration.ts, the terminal retirement-proof files, and mobile/src/worktree/agent-row-display.ts.
  • Small cleanups: the test's send() repeats a harness helper, and the harness names the release's send-plan and admission exports directly. A rename there fails the test loudly; it cannot pass by mistake.

This PR has not been merged.

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

✅ No new issues found.

Reviewed changes

  • Added a negative control to the cross-version send test (cross-version-agent-session-send.unit.test.ts:74-78) — after the positive assertion that an agreed fingerprint stops at sessionNotAttached, it overwrites sent.envelope.payloadFingerprint and asserts the same admitSend now answers fingerprintMismatch. This proves the fingerprint check ran, so the positive case can no longer pass vacuously. I traced it through admitAndRunAgentSessionMutation: the plan fields are re-digested and compared against the overwritten payloadFingerprint before the journal is read, so the agent_session_operation_conflict / fingerprintMismatch refusal is the only possible answer.

The change is test-only and matches the existing style; no runtime surface is touched.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@brennanb2025

Copy link
Copy Markdown
Contributor Author

CI on the final head d77851b has finished. Every job passes except two: typecheck fails at src/main/claude/claude-child-work-evidence-retention.test.ts:88 (TS2741, prompts missing), and the verify gate fails only because of it. The cross-version wire compatibility job passes. The typecheck break is on main itself and this PR changes nothing under src/main. Draft #25063 fixes it; once that lands, merging main into this branch should turn CI green.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Merged main (with the typecheck fix) into the branch; head is now cf6bd44 and CI is fully green. That includes typecheck, verify and cross-version wire compatibility; every other check passed or was skipped. Nothing else changed in this PR. It has not been merged.

@brennanb2025
brennanb2025 merged commit 1dc6157 into main Oct 4, 2026
34 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.

1 participant