# Issue 24190 — real app/server runtime evidence

Reviewed checkout: 3631d874a15bad86a5aa209441210ece421b79f8; base 27e0c684c5.
Worktree /home/ubuntu/wt/issue-24190 remained clean. No implementation edits or commits. No server start/stop. Lead-owned server port 16356, web port 8316, isolated worktree .t3.
Own default-profile preview tab: tab_4_3f619d25-27df-4ed3-9104-8eede0d54c34 (reuseExistingTab=false). The new tab required a fresh local pairing; credentials and pairing URLs are excluded.
Real target: [GitLab MR 2](https://gitlab.com/juliusmarminge/gitlab-test/-/merge_requests/2), viewer julius54, cwd /tmp/issue-24190-gitlab. RPC responses identify provider=gitlab, viewer=julius54, state=open, checks=[]. Existing MR mergeability=conflicting is unrelated to this cache fix.

Driver imports the running Vite app's connectionAtomRuntime, appAtomRegistry, EnvironmentRegistry, and actual RPC client. It calls the authenticated WebSocket through that app connection. No fake provider or stub. Strict detail reads use allowStale=false. Timers here measure real TTL behavior, not unit-test synchronization.

## Successful proof rows (UTC, 2026-10-24)

| Sequence | Client interval | Result | glab descendants | Sampled endpoint reads |
|---|---|---|---:|---|
| Cold detail after natural project-cache expiry and explicit MR invalidation | 10:28:15.056–15.878 | Success | 3 | MR=1, project settings=1, user=1 |
| Immediate cold checks | 10:28:15.878–15.888 | Success | 0 | none |
| Checks 20 seconds after cold completion (outer 15s expired, provider 60s live) | 10:28:35.889–35.900 | Success | 0 | none |
| Clean detail expiry cycle, 65.2s after the previous successful MR response | 10:30:47.000–47.829 | Success | 1 | MR=1, project settings=0 |
| Immediate checks | 10:30:47.829–47.843 | Success | 0 | none |
| Explicit invalidation | 10:29:40.869–40.876 | Success | 0 | none |
| Detail immediately after invalidation (previous successful read ended 10:29:40.863) | 10:29:40.876–41.800 | Success | 1 | MR=1, project settings=0 |
| Immediate checks | 10:29:41.800–41.805 | Success | 0 | none |

The table groups proof requirements; chronological RPC history is in rpc-complete.json and trace-analysis-final.txt. The clean expiry cycle follows the invalidation row chronologically.

Cold endpoints sampled from /proc, each once (unique PID):
- glab api projects/juliusmarminge%2Fgitlab-test/merge_requests/2?include_diverged_commits_count=true (PID 1792594)
- glab api projects/juliusmarminge%2Fgitlab-test?license=false (PID 1792595)
- glab api user (PID 1792601)

The extra cold user lookup is identity work; it is included in the total of 3, not hidden as an MR/settings read. The earlier project cache was populated around 10:13:04; we waited until 10:28:15 to prove a genuinely cold settings read without restarting the lead's server.

## Trace attribution

Source: .t3/userdata/logs/server.trace.ndjson. Each selected RPC belongs to this preview client's server parentSpanId f07b63368403ae01. Other app tabs continued polling; they are excluded by that parent ID, not merely by wall-clock windows. Subprocess counts walk parentSpanId chains from processRunner.runProcessCore with process.command=glab to the selected RPC. See trace-analysis-final.txt for startTimeUnixNano, span IDs, chains, RPC success/failure, and sanitized /proc samples. Samples are deduplicated by PID. Concurrent process intervals do not establish a one-to-one PID/span mapping; the report does not claim one.

Selected RPC spans:
- Cold detail 79b0746681944355, startTimeUnixNano=1792837695054873187
- Cold checks 9d3236ed2938cb59
- +20s checks ee20d7594dcbcd36
- Clean expired detail 6222883f66cb7766, startTimeUnixNano=1792837847002405383
- Immediate checks 41c2b5c6b956b251
- Invalidate 59c2be9cfb606699
- Fresh detail 21eb5fa322d2e33e
- Immediate checks 2452197529cc5d51

## Failed attempt retained

The first 65-second expiry attempt at 10:29:20.889 failed with PullRequestOperationError / GitLab CLI command failed (glab exited 1). Its following immediate checks and first post-invalidation reads also failed. The trace did not retain an actionable stderr reason. A single direct read-only glab diagnostic then exited 0, and actual app RPC retries at 10:29:40 succeeded. A separate clean 65-second cycle at 10:30:47 also succeeded. We do not attribute the transient error to a specific network or GitLab cause without evidence. All failed client rows remain in rpc-complete.json.

Early exploratory labels were provisional: initial expectedAccountId invoked a GitHub identity gate and was removed; a casing probe canonicalized to the same cache; a premature 'detail-after-provider-ttl' label was only 32 seconds and is excluded from proof. These are retained in the raw RPC history, not represented as passing matrix rows.

## Scope and friction

What else changed: none visible; only ephemeral pairing/auth state, normal read caches/logs, and /tmp evidence files. No screenshots or recordings required. No direct database writes or seed scripts used. Servers and scratch left for lead cleanup. Sampler session 47162 has a bounded 20-minute lifetime; earlier sampler session 8073 ended naturally.

Unverified required rows: none. Transient failure root cause remains unknown and is disclosed above.

FRICTION category | happened | avoidance
- AUTH | new default-profile tab was not paired | fresh local one-time pairing, excluded credentials from uploads.
- SHARED CACHE | another app tab had already populated caches | waited for natural 15-minute expiry; used own tab and strict reads.
- TOOL ARGUMENT | preview_evaluate rejected trailing whitespace once | trimmed script before evaluation.
- DRIVER INPUT | expectedAccountId activated GitHub routing validation | omitted it for the GitLab reference; verified returned viewer.
- EXTERNAL CLI | first expiry attempt returned glab exit 1, reason unavailable | retained failure, verified recovery, repeated a clean real expiry cycle.

Skills used: test-t3-app and ghdrop. No implementation changes.
