Skip to content

feat(run-ops): read presenters — de-join control-plane relations + read-through hydration#4122

Merged
d-cs merged 14 commits into
mainfrom
runops/pr08-presenters
Jul 3, 2026
Merged

feat(run-ops): read presenters — de-join control-plane relations + read-through hydration#4122
d-cs merged 14 commits into
mainfrom
runops/pr08-presenters

Conversation

@d-cs

@d-cs d-cs commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

What

Reworks the read-side presenters so they no longer depend on control-plane relations being co-located with the run subgraph. This is a read-path-only change — no writes, no schema, no runtime flag flips.

For every presenter that previously joined across what is becoming a database boundary, the join is removed from the primary query and the missing data is instead hydrated per-run through the run store. The pattern is a pair of internal helpers (#callSplit / #callPassthrough): when the split is active, the presenter selects only scalar/id-shaped columns from the primary query and hydrates the run-subgraph fields via a read-through lookup; when it isn't, it falls back to the existing passthrough path. Presenters key their behaviour on id-shape only — they don't consult a per-record "known-migrated" flag.

Presenters touched:

  • ApiBatchResultsPresenter, ApiRetrieveRunPresenter, ApiRunListPresenter, ApiRunResultPresenter
  • ApiWaitpointPresenter, ApiWaitpointListPresenter, WaitpointPresenter, WaitpointListPresenter, WaitpointTagListPresenter
  • BatchPresenter, BatchListPresenter, NextRunListPresenter
  • RunPresenter, RunStreamPresenter, SpanPresenter, TestTaskPresenter

A dead connectedRuns relation is dropped from the ApiWaitpointPresenter hydrate select.

New read-through / read-route tests cover each presenter under both the split-active and passthrough paths. A superseded ApiBatchResultsPresenter.split.test.ts is removed and the remaining ApiBatchResultsPresenter.test.ts trimmed — its coverage is subsumed by the new apiBatchResultsPresenter.readthrough suite.

Why

Part of the run-ops database split. This is PR8 of the series (PR8/9/10) and covers the read path only: it makes presenters correct against a split store before any routes are switched to route reads (PR9) or the split is actually enabled (PR10). Landing the read-side rework on its own keeps the behaviour-changing activation isolated at the top of the stack.

Tests

pnpm run test --filter webapp for the affected presenter suites. New suites exercise both the split-active read-through path and the passthrough path for each reworked presenter.

Notes

Draft, stacked on #4119 (runops/pr07-replication). Review that first; this diff is against it.

Server-change / changeset note to be added at stack-assembly time.

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented Jul 2, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 1ef21cf

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 26ffa774-714e-45aa-a285-1c8ef3e2a9be

📥 Commits

Reviewing files that changed from the base of the PR and between 77236dd and 1ef21cf.

📒 Files selected for processing (1)
  • apps/webapp/app/presenters/v3/BatchListPresenter.server.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/webapp/app/presenters/v3/BatchListPresenter.server.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout. (11)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 10)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 10)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (10, 10)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (9, 10)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 10)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 10)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 10)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 10)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 10)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 10)
  • GitHub Check: typecheck / typecheck
⚠️ CI failures not shown inline (4)

GitHub Actions: 📝 CLAUDE.md Audit / 0_audit.txt: feat(run-ops): read presenters — de-join control-plane relations + read-through hydration

Conclusion: failure

View job details

`@trigger.dev/yalt`@3.0.0-beta.47 -> `@trigger.dev/yalt`@3.0.0-beta.47
  * [new tag]             `@trigger.dev/yalt`@3.0.0-beta.48 -> `@trigger.dev/yalt`@3.0.0-beta.48
  * [new tag]             `@trigger.dev/yalt`@3.0.0-beta.49 -> `@trigger.dev/yalt`@3.0.0-beta.49
  * [new tag]             `@trigger.dev/yalt`@3.0.0-beta.5 -> `@trigger.dev/yalt`@3.0.0-beta.5
  * [new tag]             `@trigger.dev/yalt`@3.0.0-beta.50 -> `@trigger.dev/yalt`@3.0.0-beta.50
  * [new tag]             `@trigger.dev/yalt`@3.0.0-beta.51 -> `@trigger.dev/yalt`@3.0.0-beta.51
  * [new tag]             `@trigger.dev/yalt`@3.0.0-beta.52 -> `@trigger.dev/yalt`@3.0.0-beta.52
  * [new tag]             `@trigger.dev/yalt`@3.0.0-beta.53 -> `@trigger.dev/yalt`@3.0.0-beta.53
  * [new tag]             `@trigger.dev/yalt`@3.0.0-beta.55 -> `@trigger.dev/yalt`@3.0.0-beta.55
  * [new tag]             `@trigger.dev/yalt`@3.0.0-beta.6 -> `@trigger.dev/yalt`@3.0.0-beta.6
  * [new tag]             `@trigger.dev/yalt`@3.0.0-beta.7 -> `@trigger.dev/yalt`@3.0.0-beta.7
  * [new tag]             build-alert-hotfix.rc1      -> build-alert-hotfix.rc1
  * [new tag]             build-alert-hotfix.rc2      -> build-alert-hotfix.rc2
  * [new tag]             build-arm-builds-rc.1       -> build-arm-builds-rc.1
  * [new tag]             build-arm-builds-rc.2       -> build-arm-builds-rc.2
  * [new tag]             build-arm-builds-rc.3       -> build-arm-builds-rc.3
  * [new tag]             build-batchid-carryover-rc.0 -> build-batchid-carryover-rc.0
  * [new tag]             build-batching-rc.1         -> build-batching-rc.1
  * [new tag]             build-batching-rc.2         -> build-batching-rc.2
  * [new tag]             build-billing-0.0.1         -> build-billing-0.0.1
  * [new tag]             build-billing-0.0.2         -> build-billing-0.0.2
  * [new tag]             build-billing-0.0.3         -> build-billing-0.0.3
  * [new tag]             build-buildinfo-rc.0        -> build-buildinfo-rc.0
  * [new tag]             build-buildinfo-rc.1        -> bu...

GitHub Actions: 📝 CLAUDE.md Audit / audit: feat(run-ops): read presenters — de-join control-plane relations + read-through hydration

Conclusion: failure

View job details

##[group]Run anthropics/claude-code-action@428971d2ecd6e3a7cb0ee0da2a3a8b33fdb3678d
 with:
   anthropic_***REDACTED***
   use_sticky_comment: true
   allowed_bots: devin-ai-integration[bot]
   claude_args: --max-turns 25
--model claude-opus-4-8
--allowedTools "Read,Glob,Grep,Bash(git diff:*)"
   prompt: You are reviewing a PR to check whether any CLAUDE.md files or .claude/rules/ files need updating.
## Your task
1. Run `git diff origin/main...HEAD --name-only` to see which files changed in this PR.
2. For each changed directory, check if there's a CLAUDE.md in that directory or a parent directory.
3. Determine if any CLAUDE.md or .claude/rules/ file should be updated based on the changes. Consider:
   - New files/directories that aren't covered by existing documentation
   - Changed architecture or patterns that contradict current CLAUDE.md guidance
   - New dependencies, services, or infrastructure that Claude should know about
   - Renamed or moved files that are referenced in CLAUDE.md
   - Changes to build commands, test patterns, or development workflows
## Response format
If NO updates are needed, respond with exactly:
✅ CLAUDE.md files look current for this PR.
If updates ARE needed, respond with a short list:
📝 **CLAUDE.md updates suggested:**
- `path/to/CLAUDE.md`: [what should be added/changed]
- `.claude/rules/file.md`: [what should be added/changed]
Keep suggestions specific and brief. Only flag things that would actually mislead Claude in future sessions.
Do NOT suggest updates for trivial changes (bug fixes, small refactors within existing patterns).
Do NOT suggest creating new CLAUDE.md files - only updates to existing ones.
   trigger_phrase: `@claude`
   label_trigger: claude
   branch_prefix: claude/
   use_bedrock: false
   use_vertex: false
   use_foundry: false
   classify_inline_comments: true
   use_commit_signing: false
   bot_id: 41898282
   bot_name: claude[bot]
   track_progress: false
   include_fix_links: true
   display_report: false...

GitHub Actions: 🔎 REVIEW.md Drift Audit / audit: feat(run-ops): read presenters — de-join control-plane relations + read-through hydration

Conclusion: failure

View job details

##[group]Run anthropics/claude-code-action@428971d2ecd6e3a7cb0ee0da2a3a8b33fdb3678d
 with:
   anthropic_***REDACTED***
   use_sticky_comment: true
   allowed_bots: devin-ai-integration[bot]
   claude_args: --max-turns 30
--allowedTools "Read,Glob,Grep,Bash(git diff:*)"
   prompt: You are auditing this PR for drift against `.claude/REVIEW.md`.
## Context
`.claude/REVIEW.md` is the repo's source of truth for what AI / agent code reviewers should treat as critical findings (rolling-deploy safety, hot-table indexes, recovery-path queries, testcontainers usage, Lua versioning, etc.). It is consumed by review agents to calibrate severity. If REVIEW.md goes stale, every future agent review degrades.
## Strategy — read this first
You have a hard turn budget. Spend it on signal, not coverage. The audit is allowed to miss things; it is NOT allowed to time out.
1. Read `.claude/REVIEW.md` once, in full.
2. Run `git diff origin/main...HEAD --name-only` to get the list of changed files. Do NOT read the diff content yet.
3. Scan the file-list for relevance to REVIEW.md scope. Relevance signals: changes to Prisma schema, Redis / queue / Lua code, hot tables, recovery / restart loops, new packages, deletions of paths REVIEW.md cites. Skim everything else.
4. Open at most **5 files** total — only the ones most likely to surface a real signal. If nothing in the file-list looks relevant to any REVIEW.md rule, do NOT read any files; go straight to the verdict.
5. Form a verdict and stop. Do not exhaust the turn budget exploring.
Large PRs (>50 files changed) are a strong signal to be MORE selective, not more thorough. Pick 3-5 files at most.
## What to look for
- **Stale references** — does any REVIEW.md rule cite a file, directory, function, table, Prisma model, or package name that has been removed or renamed in this PR (or is already gone from `main`)?
- **Contradictions** — does code in this PR clearly violate a current REVIEW.md rule? (Don't re-review the PR. Only flag if REVIE...

GitHub Actions: 🔎 REVIEW.md Drift Audit / 0_audit.txt: feat(run-ops): read presenters — de-join control-plane relations + read-through hydration

Conclusion: failure

View job details

manual-checkpoints.rc1 -> build-manual-checkpoints.rc1
  * [new tag]             build-metadata-upgrade-logging.rc1 -> build-metadata-upgrade-logging.rc1
  * [new tag]             build-metadata-upgrade-logging.rc2 -> build-metadata-upgrade-logging.rc2
  * [new tag]             build-metadata-upgrade-logging.rc3 -> build-metadata-upgrade-logging.rc3
  * [new tag]             build-new-build-system.rc.1 -> build-new-build-system.rc.1
  * [new tag]             build-otel-upgrade-rc.0     -> build-otel-upgrade-rc.0
  * [new tag]             build-otel-upgrade-rc.1     -> build-otel-upgrade-rc.1
  * [new tag]             build-pre-pull-deployments-rc.1 -> build-pre-pull-deployments-rc.1
  * [new tag]             build-prod-rescue-rc.1      -> build-prod-rescue-rc.1
  * [new tag]             build-rate-limiter-fix-rc.1 -> build-rate-limiter-fix-rc.1
  * [new tag]             build-re2.rc0               -> build-re2.rc0
  * [new tag]             build-realtime-v2-stream-fix -> build-realtime-v2-stream-fix
  * [new tag]             build-realtime-v2-stream-fix-2 -> build-realtime-v2-stream-fix-2
  * [new tag]             build-realtime-v2-stream-fix-3 -> build-realtime-v2-stream-fix-3
  * [new tag]             build-realtime-v2-stream-fix-4 -> build-realtime-v2-stream-fix-4
  * [new tag]             build-realtime-v2-stream-fix-5 -> build-realtime-v2-stream-fix-5
  * [new tag]             build-realtimestreams-dedupe -> build-realtimestreams-dedupe
  * [new tag]             build-registry-maintenance-rc.1 -> build-registry-maintenance-rc.1
  * [new tag]             build-registry-maintenance-rc.2 -> build-registry-maintenance-rc.2
  * [new tag]             build-remote-ecr-rc.0       -> build-remote-ecr-rc.0
  * [new tag]             build-reschedule-hotfix.rc1 -> build-reschedule-hotfix.rc1
  * [new tag]             build-resume-fixes.rc1      -> build-resume-fixes.rc1
  * [new tag]             build-resume-fixes.rc2      -> build-resume-fixes.rc2
  * [new tag]        ...

Walkthrough

This PR adds optional split-read and read-through routing across v3 presenters. Batch, run, span, waitpoint, and task-list flows now resolve data through new/legacy Postgres handles with fallback logic, while control-plane lookups handle authorization, environment, schedule, and locked-worker data separately. Several presenters replace direct replica queries or raw SQL scans with Prisma-based scan/probe helpers. New integration tests cover split mode, passthrough mode, cross-DB seams, and parity across Postgres variants.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and clearly summarizes the main read-through/de-join presenter change.
Description check ✅ Passed The description is mostly complete and aligns with the template, with clear What/Why/Tests/Notes sections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch runops/pr08-presenters

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.

devin-ai-integration[bot]

This comment was marked as resolved.

@d-cs d-cs force-pushed the runops/pr07-replication branch from 5de29cb to 5c2d010 Compare July 2, 2026 18:02
@d-cs d-cs force-pushed the runops/pr08-presenters branch from 9b6eee8 to 94eaef6 Compare July 2, 2026 18:02
@pkg-pr-new

pkg-pr-new Bot commented Jul 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

@trigger.dev/build

npm i https://pkg.pr.new/@trigger.dev/build@abb6c01

trigger.dev

npm i https://pkg.pr.new/trigger.dev@abb6c01

@trigger.dev/core

npm i https://pkg.pr.new/@trigger.dev/core@abb6c01

@trigger.dev/python

npm i https://pkg.pr.new/@trigger.dev/python@abb6c01

@trigger.dev/react-hooks

npm i https://pkg.pr.new/@trigger.dev/react-hooks@abb6c01

@trigger.dev/redis-worker

npm i https://pkg.pr.new/@trigger.dev/redis-worker@abb6c01

@trigger.dev/rsc

npm i https://pkg.pr.new/@trigger.dev/rsc@abb6c01

@trigger.dev/schema-to-json

npm i https://pkg.pr.new/@trigger.dev/schema-to-json@abb6c01

@trigger.dev/sdk

npm i https://pkg.pr.new/@trigger.dev/sdk@abb6c01

commit: abb6c01

coderabbitai[bot]

This comment was marked as resolved.

@d-cs d-cs force-pushed the runops/pr07-replication branch from 8fb6e8a to 4e08dc7 Compare July 2, 2026 19:25
@d-cs d-cs force-pushed the runops/pr08-presenters branch from 6e4c0de to 48c395b Compare July 2, 2026 19:25
@d-cs d-cs force-pushed the runops/pr07-replication branch from 4e08dc7 to 11dc0b7 Compare July 2, 2026 20:23
@d-cs d-cs force-pushed the runops/pr08-presenters branch from f8b64bd to e145839 Compare July 2, 2026 20:23
@d-cs d-cs force-pushed the runops/pr07-replication branch from 11dc0b7 to a9bc9e6 Compare July 2, 2026 20:38
@d-cs d-cs force-pushed the runops/pr08-presenters branch from e145839 to 6cd0085 Compare July 2, 2026 20:38
@d-cs d-cs force-pushed the runops/pr07-replication branch from a9bc9e6 to 277ecea Compare July 2, 2026 21:44
@d-cs d-cs force-pushed the runops/pr08-presenters branch from 6cd0085 to 5ccf63f Compare July 2, 2026 21:44
@d-cs d-cs force-pushed the runops/pr07-replication branch from 277ecea to 2bba3b8 Compare July 3, 2026 00:17
@d-cs d-cs force-pushed the runops/pr08-presenters branch 2 times, most recently from f7cf260 to d31f2e9 Compare July 3, 2026 08:51
@d-cs d-cs force-pushed the runops/pr07-replication branch from 0f1da3f to 5a17a98 Compare July 3, 2026 10:02
@d-cs d-cs force-pushed the runops/pr08-presenters branch from d31f2e9 to 4bfd808 Compare July 3, 2026 10:02
@d-cs d-cs force-pushed the runops/pr07-replication branch from 5a17a98 to 6b7fb6d Compare July 3, 2026 10:36
@d-cs d-cs force-pushed the runops/pr08-presenters branch from 4bfd808 to 9197016 Compare July 3, 2026 10:37
@d-cs d-cs force-pushed the runops/pr07-replication branch from 6b7fb6d to ac94ac3 Compare July 3, 2026 10:44
@d-cs d-cs force-pushed the runops/pr08-presenters branch from 9197016 to fa0d473 Compare July 3, 2026 10:44
@d-cs d-cs force-pushed the runops/pr07-replication branch from ac94ac3 to 62ce160 Compare July 3, 2026 11:08
@d-cs d-cs force-pushed the runops/pr08-presenters branch from fa0d473 to 50463ce Compare July 3, 2026 11:08
@d-cs d-cs force-pushed the runops/pr07-replication branch from 62ce160 to 2be7e51 Compare July 3, 2026 12:08
@d-cs d-cs force-pushed the runops/pr08-presenters branch from 50463ce to e33cfc4 Compare July 3, 2026 12:09
@d-cs d-cs force-pushed the runops/pr08-presenters branch from 5189c23 to 15d6987 Compare July 3, 2026 16:33
@d-cs d-cs force-pushed the runops/pr07-replication branch from 3538e4e to e497155 Compare July 3, 2026 16:44
@d-cs d-cs force-pushed the runops/pr08-presenters branch from 15d6987 to 4862283 Compare July 3, 2026 16:44
@d-cs d-cs force-pushed the runops/pr07-replication branch from e497155 to ef571f9 Compare July 3, 2026 17:08
@d-cs d-cs force-pushed the runops/pr08-presenters branch from 4862283 to abb6c01 Compare July 3, 2026 17:08
@d-cs d-cs force-pushed the runops/pr07-replication branch from ef571f9 to 766138c Compare July 3, 2026 17:53
@d-cs d-cs force-pushed the runops/pr08-presenters branch 2 times, most recently from a4deee1 to 7ed8483 Compare July 3, 2026 18:06
Base automatically changed from runops/pr07-replication to main July 3, 2026 19:01
d-cs and others added 13 commits July 3, 2026 20:03
…ad-through hydration

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- readRedirectMarker fails open on an unprovisioned marker table
  (undefined_table): the known-migrated read optimization must never
  break the run-list read path when the marker table is absent.
- expose runOps new/legacy handles through the db.server test seam so
  the routed-store reads resolve to the real containers.
- hoist the runStore ref so the vi.mock factory no longer hits a TDZ.
- correct the getActivity bucket expectation: a 6h window buckets into
  72 five-minute buckets (chooseBucketSeconds targets ~72), not 6.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… only

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…r09 presenters

Comment/label hygiene pass over the PR09 presenter read-routing work. No
product logic, assertions, seeds, or test structure changed — only comment
text and test/it titles.

- Remove the SPLIT-NEUTRAL scaffolding comment on TaskDetailPresenter.getActivity.
- Drop `// --- ... ---` comment fencing across the touched test files, keeping
  the behavioral text.
- Strip Task/Step enumeration prefixes from comments and it/test titles, keeping
  the behavioral descriptions.
- Remove Definition-of-Done ("DoD") framing and RED/GREEN TDD phase commentary.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tPresenter hydrate select

GET /api/v1/waitpoints/tokens/:id returned HTTP 500 under split routing. The
hydrate() select in ApiWaitpointPresenter included the connectedRuns RELATION,
but it is never referenced in the returned object (all scalars) — dead code left
over from the presenters de-join pass (48ae62b70), which stripped relations from
WaitpointListPresenter but missed this one.

Under split routing a standalone cuid token classifies LEGACY, so readThroughRun
probes the scalar-only run-ops NEW client FIRST. The dedicated run-ops Waitpoint
model is scalar-only (relations de-normalized), so Prisma threw
PrismaClientValidationError: Unknown field connectedRuns before the legacy
fallback could run.

Removing the block makes the select all-scalar and valid against both the
control-plane client and the scalar-only run-ops-new client. No return-shape,
type, or SDK change.

Regression test: extends apiWaitpointPresenter.readthrough.test.ts with a
heteroRunOpsPostgresTest case that uses the REAL scalar-only run-ops client
(prisma17) as the split-mode NEW client and seeds a cuid token on the legacy
side. Fails before the fix (Unknown field connectedRuns), passes after
(resolves via the legacy fallback). Not caught by the existing heteroPostgresTest
cases because those run the full control-plane schema on both sides.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d-through presenter design

The pr04-era ApiBatchResultsPresenter.split.test.ts asserted a bare
`new ApiBatchResultsPresenter()` routes the batch-row lookup through the
runStore singleton (via vi.mock("~/v3/runStore.server")) so a NEW-resident
ksuid batch resolves. pr08's call() supersedes that contract: a bare
presenter has readThrough === undefined, so splitEnabled is false and it
takes #callPassthrough, which reads this._replica.batchTaskRun directly
(not through runStore). The test therefore fails against pr08 and encodes a
design that no longer exists.

Both cases it covered are already covered by pr08's own
apiBatchResultsPresenter.readthrough.test.ts against the current #callSplit
API: (a) a NEW-resident batch resolving under split (batch row + items on the
NEW DB, resolved via newClient) and (b) a genuinely-missing batch returning
undefined (split on). Remove the redundant, superseded test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…epair read-side test shims

- WaitpointPresenter: default omitted read-through clients to the presenter's own
  replica instead of the global run-ops singletons, so single-DB/self-host reads
  hydrate the waitpoint and its connected runs from one DB.
- SpanPresenter test: bind proxy-returned store methods to the target so private
  field access holds for all methods (e.g. findRunOnPrimary), not just findRun/findRuns.
- ApiRetrieveRunPresenter read-route test: select scalar lockedToVersionId and fold
  the resolved lockedToVersion per node, matching the presenter's current shape.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… testcontainer

The RunStore singleton is built once at import and its error-normalizing
wrapper memoizes each Prisma model delegate on first access. The test's
delegating proxy returned current.taskRun directly, so the store cached the
first test's container-bound delegate and later tests (fresh containers)
failed with "Database test_0 does not exist". Object-valued delegates now
return a stable per-key sub-proxy the store can safely cache, re-delegating
to the live current client on each access. Production code is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…c empty CH window

Two webapp unit-test shards were red on this branch:

- Shard 6 (apiRetrieveRunPresenter.readroute.test.ts): the
  organizationDataStoresRegistry singleton is constructed at import (pulled in
  transitively via the ClickHouse factory instance) and immediately fires a
  `forever` pRetry(loadFromDatabase) plus a setInterval reload against
  db.server's $replica. In CI (no Postgres on localhost) those retry forever and
  saturate the worker event loop, timing out an awaiting test's hook. Mock the
  instance module to a no-op in test/setup.ts, mirroring the other eager-singleton
  stubs. No unit test uses this singleton — the registry-behavior tests construct
  the class directly — so this is safe and should also help other shards/branches
  that import the presenter graph.

- Shard 2 (nextRunListPresenter.readthrough.test.ts): the two empty-state tests
  seeded a run then assumed it had NOT yet replicated to ClickHouse within the page
  window, so result.runs would be empty. That held on a slow local stack but raced
  on CI, where replication had completed and the run surfaced (length 1, not 0).
  Scope those two calls to a `to` one hour in the past; the CH page filters
  created_at <= to, so a just-created run is deterministically excluded regardless
  of replication timing. The PG existence probe has no time filter, so it still
  finds the row and hasAnyRuns stays true — the exact behavior each test verifies.

Reproduced both failures and verified the fix under a CI-faithful env (DATABASE_URL
+ REDIS at dead ports, GITHUB_ACTIONS=true, --no-file-parallelism): shard 2 now
18 files / 118 tests green, shard 6 now 16 files / 212 tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…NEW-resident batch

Adds the route-level sibling of the other readroute presenter tests. Seeds a
NEW-resident (ksuid) batch + member on the NEW store and asserts the presenter
wired as the route wires it (splitEnabled + newClient + legacyReplica) resolves
it, while a passthrough-only build of the same presenter returns undefined -- the
exact 404 the route produced before the fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@d-cs d-cs force-pushed the runops/pr08-presenters branch from 7ed8483 to 77236dd Compare July 3, 2026 19:03
@d-cs d-cs marked this pull request as ready for review July 3, 2026 19:03
devin-ai-integration[bot]

This comment was marked as resolved.

…n's client

In passthrough mode (readRoute provided but splitEnabled false) the empty-state probe read
runOpsNew while the page scan reads _replica, so a configured-but-read-disabled run-ops DB
could make the 'no batches' hint disagree with the page. Gate the probe on splitEnabled first.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@d-cs d-cs merged commit 0a51341 into main Jul 3, 2026
31 checks passed
@d-cs d-cs deleted the runops/pr08-presenters branch July 3, 2026 19:38
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