test(next): add the warm-process soak arm #8163's residual needs - #8215
Conversation
… the cold loop cannot see) The cold-start loop runs two verifier passes per process. In NORMAL mode two passes run ZERO copying minors — measured — so that arm cannot exercise a moving-GC holder at all, and #8163's residual (a holder surviving the default collector, ~1 broken request per 100 verifier passes in a warm process) is invisible to it. A hundred passes is not enough either: at p=0.01 a clean 100-pass run happens ~37% of the time on a known-broken build, and two of five measured 100-pass runs came back clean while the bug was present. run_warm_soak drives one warm process for N passes and prints the confidence that N actually buys (rule of three: ~300 for 95%, ~460 for 99%), so a green run cannot imply more than it proves. OFF by default because a meaningful N is slow; this is the acceptance instrument for closing #8163, not a per-run check. It asserts its subject was live (copying minors > 0), and reports an OBSERVED failure ahead of that complaint so a real broken request is never masked by "exercised nothing" — a mistake caught by running the arm rather than reading it. Validated end to end against real provider images: catches a pre-fix build at pass 19, catches the surviving residual on the merged fix at pass 3 and pass 6, stays quiet at N=0, and both asserts fire when sabotaged. Refs #8163 Claude-Session: https://claude.ai/code/session_01YAif84burv8q6QngSN6wU8
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan includes up to 8 reviews per rolling hour; 2 remain after this review. 📝 WalkthroughWalkthroughThe Next App Route fixture adds an opt-in warm-process soak arm. It repeats verifier passes, checks request and GC results, reports statistical confidence, and runs after cold-start validation. The changelog documents its behavior and validation cases. ChangesNext App Route warm-soak validation
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This change adds an opt-in warm-process soak test without altering default behavior, and no actionable merge-blocking risk remains after normal checks and review. Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
…s not model The printed percentages assume the ~1/100 failure is independent per pass. It is not: failures track collections, and collections accelerate as the heap grows (measured: minors at passes 3 5 11 19 28 ... 94 97 99 — 8-9 pass gaps early, 2-3 late). So the figure is a conservative floor, and a long run buys more than it claims. Records the same measurement for the per-cold-start pass count, which buys something different: a fresh process gets ~2 collections in ten passes, always in the small-heap regime, so cold starts buy restart/ABI/guard coverage while the warm soak buys collection depth. Refs #8163 Claude-Session: https://claude.ai/code/session_01YAif84burv8q6QngSN6wU8
Per-cold-start passes buy restart/ABI/parity/bypass-guard coverage at ~2-3 copying minors per fresh process; collection depth in one warm process is PERRY_NEXT_ROUTE_WARM_PASSES (#8215). Neither substitutes for the other.
Per-cold-start passes buy restart/ABI/parity/bypass-guard coverage at ~2-3 copying minors per fresh process; collection depth in one warm process is PERRY_NEXT_ROUTE_WARM_PASSES (#8215). Neither substitutes for the other.
Validation status vs current
|
… per cold start a knob (default 10) in the release App Route fixture (#8210) * test(next): arm the routeModule.handle guard and make verifier passes per cold start a knob (default 10) in the release App Route fixture Port the armed perry-host.js from tests/fixtures/next-app-route (byte-identical) into tests/release/packages/next-app-route and grep every cold-start log for 'generated handler bypassed' as a hard failure — the guard's only signal is the host log, verify.mjs exits 0 when it fires. Replace the hard-coded two verifier runs per cold start with PERRY_NEXT_ROUTE_VERIFIERS_PER_START (default 10), so the default run is 10 cold starts x 10 passes = 100 batches, matching #8040's 100-iteration bullet and tests/test_next_app_route_dylib.sh. With the default this fixture is red on today's main because of #8163; =2 recovers the previous coverage. * changelog: fragment for #8210 * test(next): show the cold-start log tail when a verifier pass fails * test(next): document the two coverage regimes at the verifier knob Per-cold-start passes buy restart/ABI/parity/bypass-guard coverage at ~2-3 copying minors per fresh process; collection depth in one warm process is PERRY_NEXT_ROUTE_WARM_PASSES (#8215). Neither substitutes for the other. * test(next): reconcile the header with post-#8211 state (#8163 reopened on the default-GC residual) --------- Co-authored-by: Ralph Küpper <ralph@skelpo.com>
Refs #8163. Adds the acceptance instrument that issue needs, and shows why the existing one cannot serve.
Why
fixture.sh's cold-start loop makes two verifier passes per process. Two facts about that, both measured here:So "the fixture is green" has never been evidence about this class, and closing #8163 on it would be the failure mode CLAUDE.md names — a gate that cannot fail.
What
run_warm_soak: one warm process, N verifier passes, default GC (forcing evacuation would measure the arm that is already fixed).OFF by default (
PERRY_NEXT_ROUTE_WARM_PASSES=0) because a meaningful N is slow. This is the close-condition instrument for [Next.js/dylib] Forced-evacuation App Route arm: stale closure from a holder outside the GC heap #8163, not a per-run check.Prints the confidence its N actually buys instead of letting any green run imply elimination — rule of three, ~3/p passes for 95%:
Asserts its subject was live (
copying minors > 0), the same rule the forced arm's evacuation-liveness assert applies.Reports an observed failure ahead of the liveness complaint. I had these the other way round at first, and a real broken request got masked behind "exercised nothing" — caught by running the arm, not by reading it.
Validation — every path exercised against real provider images
N=0N=100N=100N=10N=2, cleanThe middle two rows are an independent local reproduction of the residual that @proggeramlug measured on the bench mini — same signature, different host, on the merged fix.
Note for whoever closes #8163
The pass numbers that fail (3, 6, 12, 19 across runs) track collection boundaries, not request counts:
N=10produced 2 copying minors and one failure. The per-collection failure rate is much higher than the per-pass rate, so if the hunt wants a faster reproducer, drive collections rather than requests.Summary by CodeRabbit
Tests
Documentation