fix(server): persist only changed pull request links#19248
Each changed PR saved the whole thread, including every linked PR. Save only the changed link.
Impact on the maintainer's database
| Metric | Before | After |
|---|---|---|
| Average PR-update JSON | 208 KB | ~806 B (99.6% smaller) |
| JSON serialization per update | 265 µs | 0.73 µs (362× faster) |
| Serialization with 305 linked PRs | 314 µs | 0.73 µs (431× faster) |
| Historical automatic PR-update JSON | 90.48 GB measured | ~0.34 GB estimated |
| Cumulative storage avoided | — | ~90.14 GB estimated |
What caused the growth?
| Source | Share of all event JSON |
|---|---|
| Background PR status sync | 91.65% |
| Notification watcher | 0.01% |
| Turn-item updates | 6.23% |
| Everything else | 2.11% |
Storage totals come from a full scan of a copied database: 2.92 million events, 98.72 GB of event JSON. Serialization uses 180 real snapshots, 11 measured rounds after warm-up, Node 24.21.0 on Apple M4 Max. Timings isolate JSON.stringify; estimated savings exclude SQLite overhead and overlap with the next PR's compaction savings.
Scope and approval
Focused fix for an obvious persistence bug: one changed PR duplicated every linked PR. Existing refresh behavior is preserved; only the event payload becomes link-specific.
Validation: 137 focused tests; server/client typechecks. Existing events remain readable across server replay and all clients.
Implemented with GPT-6.1 Sol via Codex.
Checks
Added 1 commit
- fix(server): persist only changed pull request links740f601
Approvability
Verdict: Approved at 740f601
Macroscope's review found this PR approvable — This is a contained event-persistence bug fix that stores only the changed pull-request link while preserving full-thread projections and backward compatibility. The server replay, compaction, and client reducer paths are updated consistently and covered by focused tests.
You can add or adjust custom eligibility rules. Learn more.
Thread transfer impact
✅ Thread transfer remains within every enforced ceiling.
| Provider | Metric | Main baseline | This PR | Impact | PR ceiling | |
|---|---|---|---|---|---|---|
| Codex | Total thread wire | 5.0 KiB | 5.0 KiB | 0 B (0.0%) | 6.8 KiB | ✅ |
| Codex | Thread snapshot wire | 3.8 KiB | 3.8 KiB | 0 B (0.0%) | 4.9 KiB | ✅ |
| Codex | Live turn WebSocket wire | 1.2 KiB | 1.2 KiB | 0 B (0.0%) | 2.0 KiB | ✅ |
| Codex | Live turn WebSocket decoded | 20.9 KiB | 20.9 KiB | 0 B (0.0%) | 29.3 KiB | ✅ |
| Codex | Live turn messages | 2 | 2 | 0 (0.0%) | 8 | ✅ |
| Claude | Total thread wire | 5.0 KiB | 5.0 KiB | 0 B (0.0%) | 6.8 KiB | ✅ |
| Claude | Thread snapshot wire | 3.8 KiB | 3.8 KiB | 0 B (0.0%) | 4.9 KiB | ✅ |
| Claude | Live turn WebSocket wire | 1.2 KiB | 1.2 KiB | 0 B (0.0%) | 2.0 KiB | ✅ |
| Claude | Live turn WebSocket decoded | 21.2 KiB | 21.2 KiB | 0 B (0.0%) | 29.3 KiB | ✅ |
| Claude | Live turn messages | 2 | 2 | 0 (0.0%) | 8 | ✅ |
Baseline: cb65643 · PR result: 740f601 · Source CI: success
Scenario and decoded snapshot size
10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
- Codex decoded thread snapshot: 108.5 KiB
- Claude decoded thread snapshot: 108.8 KiB
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.
No actionable comments were generated in the recent review. 🎉
ℹ️ Recent review info
⚙️ Run configuration
- Configuration used: Path: .coderabbit.config.ts
- Review profile: CHILL
- Plan: Team
- Run ID:
b0b730c7-af4b-44b5-ab94-766771ce448a
📥 Commits
Reviewing files that changed from the base of the PR and between cb65643b076c79cfe39a5197553b143889da64ab and 740f6012ba1d9a1eadd227c3722ccb520318204c.
📒 Files selected for processing: 10
apps/server/src/orchestration-v2/Orchestrator.tsapps/server/src/orchestration-v2/ProjectionStore.tsapps/server/src/orchestration-v2/PullRequestSyncReactor.tsapps/server/src/orchestration-v2/ThreadSettlementService.tsapps/server/src/orchestration-v2/runtimeLayer.test.tsapps/server/src/relay/AgentAwarenessRelay.tspackages/client-runtime/src/state/orchestrationV2Projection.test.tspackages/client-runtime/src/state/orchestrationV2Projection.tspackages/contracts/src/orchestrationV2.tspackages/shared/src/threadPullRequests.ts
Included review availability: This review used your included allowance. 7 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 10 reviews per hour.
📝 Walkthrough
Pull-request link sync commands now emit link-specific update events. Server and client projections apply those events, and related event handlers process them. Tests cover link replacement, event payloads, and projection rebuilds.
Changes: Pull-request link updates
Layer / File(s) Summary Define and emit link updates
packages/contracts/src/orchestrationV2.ts,packages/shared/src/threadPullRequests.ts,apps/server/src/orchestration-v2/Orchestrator.tsThe event contract accepts a ThreadPullRequestLinkpayload. The shared helper replaces matching links, and pull-request link and watch sync commands emit the link-specific event instead of the generic thread event.Apply and process server link updates
apps/server/src/orchestration-v2/ProjectionStore.ts,apps/server/src/orchestration-v2/PullRequestSyncReactor.ts,apps/server/src/orchestration-v2/ThreadSettlementService.ts,apps/server/src/relay/AgentAwarenessRelay.ts,apps/server/src/orchestration-v2/runtimeLayer.test.tsServer projections apply the event. Related handlers request a sync for links with null snapshots, enqueue settlement sweeps, and publish agent-awareness updates. The integration test checks event payloads and projection rebuilds. Apply link updates in the client projection
packages/client-runtime/src/state/orchestrationV2Projection.ts,packages/client-runtime/src/state/orchestrationV2Projection.test.tsThe client projection applies the updated link and updates its timestamp. The test checks that other links and thread metadata remain unchanged. Priority: ➖ Normal
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Bug fix
Sequence Diagram(s)
mermaid1 sequenceDiagram 2 participant Orchestrator 3 participant ProjectionStore 4 participant PullRequestSyncReactor 5 participant ThreadSettlementService 6 participant AgentAwarenessRelay 7 Orchestrator->>ProjectionStore: Emit thread.pull-request-link-updated 8 ProjectionStore->>ProjectionStore: Apply updated link to thread 9 Orchestrator->>PullRequestSyncReactor: Process link update event 10 Orchestrator->>ThreadSettlementService: Process link update event 11 Orchestrator->>AgentAwarenessRelay: Process link update event Suggested reviewers:
t3dotgg,maria-rcks
Merge Risk: ⚪ Minimal · up to 740f6
The compact pull-request link update is ready to merge after normal checks.
Pre-merge checks: Passed 4
Passed 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. Description check Passed The description explains the persistence problem, quantifies its impact, describes the focused fix, justifies the approval exemption, and reports focused tests and typechecks. It does not use the temp… Title check Passed The title is concise, specific, and accurately describes the main change: persisting only changed pull request links.
✨ Finishing Touches
📝 Generate docstrings
- 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
Comment @coderabbitai help to get the list of available commands.