feat(skip): enable proven static layout transport skips#1437
feat(skip): enable proven static layout transport skips#1437NathanDrake2406 wants to merge 20 commits into
Conversation
Authorize skip transport only after a parsed client reuse manifest entry cross-checks against a public static layout cache proof. Add a skip transport planner that preserves rejection traces, falls back to render/send for absent, rejected, oversized, or over-budget manifests, and uses canonical parsed entry ids rather than verifier-provided ids. Wire enabled static-layout skip disposition into the RSC payload encoder so only proven layout records are omitted. HTML responses and non-layout entries still render and send the full tree.
commit: |
Canonical RSC requests could parse X-Vinext-Client-Reuse-Manifest but still send full AppElements payloads. The parsed manifest stopped at the App RSC handler, so dispatch and render never had the proof input needed to plan static layout omission. Thread the parsed manifest through generated App RSC dispatch into dispatchAppPage and renderAppPageLifecycle, then build the skip disposition from current static layout classifications and layout-scoped proof metadata before encoding the RSC payload. HTML renders still ignore skip dispositions. Tests cover header parsing into dispatch, generated entry wiring, static-only dispatch omission, dynamic fallback, and HTML full-payload behaviour.
Verified skip transport can omit layout records for a specific client. Caching that partial RSC stream under the normal route key is unsafe because later clients may not have the omitted layout locally. Bypass RSC capture and ISR cache scheduling when skip transport is enabled, force the client response to no-store, and emit a debug trace for the skipped cache write. Tests cover the render lifecycle cache boundary and the manifest-driven dispatch path.
|
/bigbonk review |
There was a problem hiding this comment.
Review: feat(skip): enable proven static layout transport skips
The architecture is sound. The planner stays untrusted-at-parse / verified-at-runtime, the cache bypass is correctly wired end-to-end, and the test coverage is thorough. The inline comments below are refinements, not blockers.
What's good
- Trust boundary is clean. Parser disposition stays
renderAndSend; only the runtime planner can upgrade toSKIP_STATIC_LAYOUT_VERIFIEDafter server-side verification. The hardening from #726 is preserved. - Cache bypass is correct.
shouldCaptureRscForCacheMetadatais gated off,capturedRscDataPromiseis null,scheduleAppPageRscCacheWritereturns false,finalizeAppPageRscCacheResponsereturns the response unchanged, andno-store, must-revalidateis set. No shared cache poisoning path. - Layout-only omission guard is correct.
createSkippedLayoutIdsre-parses each entry ID throughparseAppElementsWireElementKeyand only admitskind: "layout", so a malicious manifest that smuggles a page/template/route entry ID intoskippedEntryIdscannot omit non-layout content. - Budget enforcement — the
maxEntriesToVerifycheck rejects over-budget manifests before the verifier loop runs. The test for this is explicit. - Entry ID hardening —
skippedEntryIdsis populated fromentry.id(the canonical parsed entry), not from verifier-returned IDs. The "uses the verified manifest entry id instead of trusting verifier-provided skipped ids" test proves this. - HTML path is untouched — skip disposition is only passed to
encodeOutgoingPayloadfor RSC requests, and the dispatch test proves HTML responses still contain the full tree.
Nits and suggestions below.
|
Review submitted. Here's a summary of what I found: Overall: The PR is solid. The trust boundary design from #726 is correctly preserved — parse-time disposition stays 8 inline comments posted, all non-blocking refinements:
|
Browser navigation could only benefit from skip transport when an external caller manually supplied X-Vinext-Client-Reuse-Manifest. That left normal App Router soft navigations rendering full layout payloads even when the current visible state retained a proven public static layout. The missing boundary was the browser request path. Build a bounded manifest from visible AppElements metadata, reuse the same static-layout compatibility and payload-hash proof contract as server verification, and attach it through createRscRequestHeaders only for navigation fetches. Also folds in Bonk review refinements around skip planner policy ownership, invalid verification budgets, synthetic static-layout observations, no-store cache semantics, and dispatch-level waitUntil coverage.
|
To use Codex here, create an environment for this repo. |
|
@codex review |
There was a problem hiding this comment.
Pull request overview
This PR enables verified static-layout skip transport for App Router RSC navigations by introducing an untrusted client reuse manifest header, parsing it at the canonical RSC boundary, and upgrading to an enabled skip disposition only after server-side proof cross-checks at the render lifecycle boundary. It also ensures skipped (client-specific) RSC payloads bypass shared caching and are returned with Cache-Control: no-store, must-revalidate.
Changes:
- Add a browser-side producer for a bounded
X-Vinext-Client-Reuse-Manifestderived from visible retained static layout entries, and attach it to real RSC navigation requests. - Add server-side skip transport planning/proofing to upgrade from parsed (disabled) disposition to
SKIP_STATIC_LAYOUT_VERIFIED, and omit only proven layout records from RSC payload encoding. - Add extensive wiring + boundary tests (planner behavior, request normalization/dispatch plumbing, cache bypass/no-store behavior, and e2e header emission).
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/skip-cache-proof.test.ts | Expands unit coverage to assert verified entries produce enabled skip plans and that budgets/oversize/malicious cases fall back safely. |
| tests/e2e/app-router/build-id-navigation.spec.ts | Adds Playwright coverage proving RSC soft navigations send a bounded client reuse manifest header. |
| tests/app-rsc-handler.test.ts | Verifies parsed client reuse manifest hints are threaded from canonical RSC requests into page dispatch. |
| tests/app-rsc-cache-busting.test.ts | Ensures manifest header is attached without becoming a shared cache-variant input. |
| tests/app-router.test.ts | Asserts generated dispatchMatchedPage wiring includes clientReuseManifest threading. |
| tests/app-page-render.test.ts | Adds render lifecycle coverage for skip omission, no-store cache policy, and HTML non-omission behavior. |
| tests/app-page-dispatch.test.ts | Adds dispatch-boundary integration coverage for verified static-layout omission (RSC only) and cache bypass. |
| tests/app-elements.test.ts | Validates outgoing payload builder omits only layout keys when skip is enabled and preserves metadata/layout flags. |
| tests/app-browser-client-reuse-manifest.test.ts | New tests for browser manifest construction (static-only, retained-only) and byte-budget trimming. |
| packages/vinext/src/server/static-layout-client-reuse-proof.ts | Introduces shared proof helpers for static-layout compatibility shaping + payload hash computation. |
| packages/vinext/src/server/skip-cache-proof.ts | Adds skip transport planner (createClientReuseSkipTransportPlan) and upgrades verified cross-checks to enabled skip disposition. |
| packages/vinext/src/server/client-reuse-manifest.ts | Extends skip disposition type to include SKIP_STATIC_LAYOUT_VERIFIED (enabled) alongside disabled mode. |
| packages/vinext/src/server/app-rsc-handler.ts | Threads clientReuseManifest through handleAppRscRequest to dispatch boundary. |
| packages/vinext/src/server/app-rsc-cache-busting.ts | Allows createRscRequestHeaders() to attach the manifest header when provided. |
| packages/vinext/src/server/app-page-render.ts | Builds runtime skip disposition at render lifecycle boundary; omits proven layouts from RSC payload and bypasses RSC cache writes (no-store). |
| packages/vinext/src/server/app-page-dispatch.ts | Threads clientReuseManifest through dispatch into render lifecycle. |
| packages/vinext/src/server/app-elements-wire.ts | Applies skip disposition during outgoing payload encoding by filtering proven layout keys only. |
| packages/vinext/src/server/app-browser-entry.ts | Attaches the client reuse manifest header to real navigation RSC fetches (prefetch unchanged). |
| packages/vinext/src/server/app-browser-client-reuse-manifest.ts | New browser helper to construct a bounded manifest from visible AppElements metadata. |
| packages/vinext/src/entries/app-rsc-entry.ts | Updates generated entry wiring to pass clientReuseManifest into app page dispatch/render. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 58dfd28128
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Skip transport sends partial RSC payloads only for clients that already hold retained static layouts. Treating those payloads as restorable visited-cache entries, sending manifests on refresh, or skipping layouts marked dynamic by runtime segment config breaks that invariant. The previous wiring relied on generic payload metadata and build-time classifications, while hard-navigation recovery had drifted around the navigation controller guard. Record skipped layout ids in AppElements metadata, deny visited-cache restoration for skip-pruned payloads, preserve skipped layouts from current state on approved commits, restrict browser manifests to navigate requests, honor runtime dynamic segment config, and route hard navigations through the controller.
Compatibility-map acceptance lets a retained layout hint verify across compatible canary and rollback deployments, but it does not prove byte-for-byte transport identity. Treating that accepted compatibility as permission to omit layout bytes breaks the cache proof boundary when deployments only share a declared compatibility set. Keep the cross-check verified in that case, but return the disabled skip disposition unless the manifest entry compatibility exactly matches the current artifact compatibility. Add regression coverage for shared and stale canary/rollback compatibility maps.
…05-static-layout-skip-transport # Conflicts: # tests/skip-cache-proof.test.ts
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b04d9b7273
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
/bigbonk review |
There was a problem hiding this comment.
Review: feat(skip): enable proven static layout transport skips
I read the full diff, the #726 architectural spec, and the prior reviews from Bonk, Copilot, and Codex. The architecture is well-designed and the implementation is disciplined. I'm focusing on areas the other reviews didn't cover or where I disagree with their findings.
Correctness assessment
The end-to-end trust boundary is sound:
- Parse-time disposition stays disabled.
parseClientReuseManifestHeaderalways returnsenabled: false. OnlycreateClientReuseSkipTransportPlanat render time can upgrade toSKIP_STATIC_LAYOUT_VERIFIED. - Cache bypass is complete.
shouldCaptureRscForCacheMetadatais false,capturedRscDataPromiseis null,waitUntilis never called, andno-store, must-revalidateis set. - Visited-cache poisoning is prevented.
isCacheRestorableAppPayloadMetadatareturns false whenskippedLayoutIds.length > 0(line 157 ofapp-browser-state.ts), so skip-pruned payloads are never stored. The Codex P1 comment about visited-route cache keying is a false positive — the store path is gated off entirely. - Layout-only omission guard is structurally correct.
createSkippedLayoutIdsre-parses throughparseAppElementsWireElementKeyand only admitskind: "layout". - Render dependency release on skip is correct.
releaseAppElementRenderDependencyis called for skipped entries so downstreamrenderAfterAppDependenciesbarriers don't hang. - CDN cache coherence is correct. The manifest header is intentionally excluded from
createCacheBustingInputandVINEXT_RSC_VARY_HEADER, so CDN caches are not manifest-dimensioned. A CDN-cached full response is harmlessly served to manifest-bearing clients.
Param scope design is the strongest part
The structural param scope tracking (via resolveAppPageSegmentParamScopeKeys) is the right conservative approach. It blocks skip for any layout whose ancestor segments include dynamic, catch-all, or optional catch-all params — regardless of whether the layout component actually reads them. This is correct because:
- A layout under
[slug]could receiveparamsand pass them to children without reading them itself - The probe-time observation only catches direct reads, not pass-through
- Optional catch-all segments whose runtime value is
[]/{}still have non-empty structural scope
The three-gate rejection order in rejectParamDependentStaticLayout (incomplete observation → non-empty scope → observed reads) is clean and each gate has a distinct rejection code for traceability.
On the Codex P2 concern about synthetic observations
The second Codex comment about cacheTags: [] and dynamicFetches: [] in synthetic observations raises a real concern worth tracking. A layout that does await fetch(url, { next: { tags: ['config'] } }) without calling request APIs would be classified "s" at probe time, but revalidateTag('config') would change its output. The synthetic observation with cacheTags: [] means the skip proof doesn't know about the config tag. This is a known scope limitation for this PR (no tag-based invalidation tracking for skip proof), but it should be tracked as a future correctness gap.
Items below — all non-blocking refinements
See inline comments.
Static layout skip could still be authorised from a synthetic cache-clean observation. That was wrong when the retained layout output depended on cached fetches, dynamic fetches, fetch tags, or use-cache cache life discovered during layout probing. The violated invariant was that transport omission must be proven from the target layout's actual request observation, not only from static classification. Record per-layout data dependency observations during layout probes, evaluate returned server-component children under bounded probe limits, and reject skip when any data dependency is observed. Tests cover a nested layout child that records cache-tagged data and prove the RSC payload preserves that layout instead of omitting it.
Static-layout skip still treated finite layout revalidate segment config as eligible when build-time classification marked the layout static. That is too strong because a finite ISR policy means the retained layout is not a permanent artifact. The root assumption was that static classification alone described transport reusability. Record finite positive layout revalidate values in the per-layout observation, reject skip with SKIP_LAYOUT_REVALIDATE_PRESENT, and move generated layout probing into a typed helper that records skip observation scope. Tests cover finite-revalidate layouts rendering and sending normally, plus the helper's subtree probing and revalidate tracking.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7bbf954625
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Static-layout skip could still approve a layout whose returned child component was wrapped in React.memo() or forwardRef(). The subtree probe treated object element types as opaque and visited only props.children, so cache tags or params observed inside those wrapped children were invisible. Render through memo and forwardRef wrappers during the bounded layout subtree probe, preserving the existing render-and-send fallback on probe failures. Tests cover pure probe invocation for memo, forwardRef, and memo(forwardRef), plus dispatch rejection for wrapped cache-tagged layout children.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7702c682cb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Static-layout skip could over-share or under-observe probe dependency state. Fetch tags, cacheable fetch URLs, dynamic fetch URLs, and cacheLife were read from request-wide collections, so dependencies from one layout probe could be attributed to later probes. The violated invariant was that skip eligibility must be proven from the layout subtree being considered, not from neighbouring probes or from wrapper shapes the probe cannot see. Isolate each layout probe's dependency observation in a child request scope, render through React.lazy wrappers, and count array and iterable branches against the existing subtree depth and node budgets. Tests cover per-layout dependency isolation, lazy cache-tagged layout children preserving the RSC layout record, and array depth and node limit enforcement.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6de623645a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Browser soft navigation could emit more retained layout entries than the server skip planner will verify. When a valid manifest exceeded that verification budget, the server rejected the whole hint with SKIP_ENTRY_COUNT_EXCEEDED and skip transport stayed disabled for routes with many retained static layouts. The mistaken invariant was treating the parser's hostile-input entry limit as the producer budget. Keep the parser envelope larger, share the server verification budget through the manifest protocol module, and cap browser-produced manifests to that budget before byte-size trimming. The regression test builds a route with more retained static layouts than the verification budget and asserts the browser manifest only contains the verifiable prefix.
|
@codex review |
|
Codex Review: Didn't find any major issues. You're on a roll. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Static-layout skip could still authorize omission after a layout probe observed request APIs. Build-time or segment-config static classification can skip isolated dynamic detection, so a retained layout that reads headers(), cookies(), draftMode(), connection(), params, or search params needed an independent runtime negative proof before bytes could be omitted. The violated invariant was that skip proof must be based on evidence owned by the per-layout observation tracker, not a fabricated empty request API observation. Record request API usage inside each isolated layout probe, reject observed request APIs before static-layout proof construction, and feed the completed per-layout request API observation into the synthetic cache proof. Tests cover isolated request API tracking across layout probes and a dispatch regression where a static-classified layout probe observes headers usage and the RSC payload still includes the layout.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1863f07ab5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Layout subtree probing consumed arbitrary iterable children before the real RSC render. If an app returned a single-use iterator or shared generator from a layout subtree, the probe could advance it and leave the real render with missing children. The mistaken invariant was treating all iterables like arrays. Arrays are stable values to traverse, but arbitrary iterables can be stateful, so the probe now rejects non-array iterables without advancing them. That keeps the real render authoritative and makes skip fall back instead of mutating output. The regression verifies a shared generator is still unconsumed after the subtree probe rejects it.
|
@codex review |
|
Codex Review: Didn't find any major issues. You're on a roll. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Layout probes could record unsafe static-reuse observations while still publishing an "s" layout flag. That was safe for server skip authorization, but it let the browser keep proposing manifest entries for layouts that could never be accepted. The violated invariant was that client-facing layout flags should be derived from the same per-layout evidence used by skip authorization. Treat incomplete observations, structural params, observed params, request APIs, finite revalidate, cacheLife, cache tags, cacheable fetches, and dynamic fetches as dynamic for layout metadata. Tests cover both build-time-static false positives and runtime-probed request API layouts publishing "d" while still rendering and sending the layout.
|
@codex review |
Layout skip probes rendered layouts with children set to null. That could hide layout chrome dependencies behind children truthiness checks, producing a clean static observation for a layout whose real render would observe request or data dependencies. The violated invariant was that per-layout skip evidence must be gathered under a child shape equivalent to the real App Router render. Probe layouts now receive a terminal non-null React child, while the subtree probe treats it as inert instead of descending into page content. This also restores build-time layout flags before special-error probes so short-circuit responses keep the same metadata contract covered by CI. Tests cover children-dependent chrome observations and the special-error flag regression.
|
@codex review |
|
Codex Review: Didn't find any major issues. 🎉 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Static layout skip could treat layouts that read unstable_cache() data as clean. That was unsafe because cached data can be tagged, revalidated, and invalidated without passing through the fetch, cacheLife, request API, or params observation channels. The violated invariant was that skip proof must observe every layout data dependency source before synthesizing a static-layout proof. unstable_cache() now records a bounded observation for every invocation, including cache hits, using hashed keys and tag metadata rather than raw keys or values. Layout observation carries those dependencies into skip rejection and client-visible layout flags. Tests cover cache-miss and cache-hit observation plus dispatch fallback for a retained static layout whose probe reads unstable_cache() data.
|
@codex review |
|
Codex Review: Didn't find any major issues. Hooray! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Overview
Implements
#726-SKIP-04/05from #726.Bonk: please read issue #726 for the architectural big picture before reviewing this slice.
client-reuse-manifest,skip-cache-proof,app-page-render,app-page-dispatch,app-layout-param-observation,app-page-probe,app-page-route-wiring,app-page-params,app-browser-client-reuse-manifest, generatedapp-rsc-entrywiring.Why
Skip transport is only correct when the retained client layout is indistinguishable from the target server layout for this request. That means the client manifest cannot authorize omission by itself, partial RSC responses cannot become shared cache artifacts, and a layout whose output can depend on params, data invalidation, or finite revalidation cannot be reused without stronger proof. This PR keeps those responsibilities at the server render boundary and treats uncertain layouts conservatively.
params.unstable_cache()usage in an isolated child request scope before skip verification. Any observed dependency blocks skip for that layout without leaking into sibling or parent probe observations.revalidatesegment config, and skip rejects those layouts withSKIP_LAYOUT_REVALIDATE_PRESENT.childrenis present. Probes must not mutate single-use children.paramsobservation records sync reads,await params, destructuring/enumeration, andinchecks, while skip authorization now requires both complete observation and empty structural param scope.Cache-Control: no-store, must-revalidate, and avoids visited-response replay.What changed
navigateRsc()attachesX-Vinext-Client-Reuse-Manifestfor retained public static layouts, capped to the skip planner entry budget before byte-size trimming.paramsto children and be incorrectly retained across sibling values. Empty optional catch-all targets could look param-free because the runtime params object was{}.unstable_cache()usage, and publishes those unsafe observations as dynamic layout metadata.revalidatesegment config."s"layout flags even after per-layout observation proved skip would be rejected.unstable_cache()usage, and incomplete probes publish"d".childrencould hide chrome dependencies because probes rendered withchildren={null}.memo(),forwardRef(), andReact.lazyreturned below a layout could hide data dependencies from the probe, while arbitrary iterable children could be single-use.Maintainer review path
packages/vinext/src/server/client-reuse-manifest.tspackages/vinext/src/server/skip-cache-proof.tspackages/vinext/src/server/app-page-render.tspackages/vinext/src/server/app-page-dispatch.tspackages/vinext/src/server/app-layout-param-observation.tspackages/vinext/src/server/app-page-probe.tspackages/vinext/src/server/app-page-route-wiring.tsxpackages/vinext/src/server/app-page-params.tspackages/vinext/src/entries/app-rsc-entry.tspackages/vinext/src/shims/fetch-cache.tspackages/vinext/src/shims/thenable-params.tsawait params, destructuring, enumeration, and promise continuations.packages/vinext/src/server/app-browser-client-reuse-manifest.tsand browser entry testsValidation
vp checkvp test run tests/app-page-probe.test.ts tests/app-layout-param-observation.test.ts tests/app-page-dispatch.test.tsvp test run tests/app-page-probe.test.ts tests/app-page-dispatch.test.ts tests/app-page-render.test.ts tests/app-layout-param-observation.test.tsvp test run tests/app-page-dispatch.test.ts tests/app-layout-param-observation.test.ts tests/app-page-render.test.ts tests/skip-cache-proof.test.tsvp test run tests/app-layout-param-observation.test.ts tests/app-page-dispatch.test.ts -t "unstable_cache"unstable_cache()dependencies on cache miss and hit, and that verified static-layout skip falls back to render/send for retained layouts backed byunstable_cache()data. Passed: 2 tests.vp test run tests/app-layout-param-observation.test.ts tests/app-page-dispatch.test.ts tests/app-page-render.test.ts tests/shims.test.ts tests/unified-request-context.test.ts tests/skip-cache-proof.test.tsunstable_cache()observation channel. Passed: 6 files, 1094 tests.vp test run tests/app-browser-client-reuse-manifest.test.ts tests/client-reuse-manifest.test.ts tests/skip-cache-proof.test.tsvp test run tests/app-page-render.test.ts tests/app-router.test.tsvp test run tests/app-page-route-wiring.test.ts tests/app-page-execution.test.ts tests/app-page-probe.test.ts tests/app-page-dispatch.test.ts tests/app-page-render.test.ts tests/app-layout-param-observation.test.tsvp test run tests/app-router.test.ts tests/entry-templates.test.ts tests/app-page-route-wiring.test.tsvp test run tests/app-page-dispatch.test.ts tests/app-page-route-wiring.test.ts tests/app-page-probe.test.ts tests/app-page-render.test.ts tests/app-router.test.tsvp test run tests/app-page-probe.test.ts tests/app-page-dispatch.test.ts tests/app-page-render.test.ts tests/app-browser-client-reuse-manifest.test.ts tests/client-reuse-manifest.test.ts tests/skip-cache-proof.test.tsvp test run tests/app-router.test.ts tests/entry-templates.test.ts tests/app-page-request.test.ts tests/app-elements.test.ts tests/app-page-route-wiring.test.ts tests/thenable-params.test.ts tests/app-page-params.test.tsvp run vinext#buildprivate-next-instrumentation-client,virtual:vinext-rsc-entry, andvirtual:vite-rsc/client-references.PLAYWRIGHT_PROJECT=app-router pnpm exec playwright test tests/e2e/app-router/layout-persistence.spec.ts --project=app-router -g "dynamic segment layout counter survives param navigation while content updates"vp test run tests/app-page-execution.test.ts -t "build-time classified layout throws"git diff --checkknip. Passed.Previously on this PR, the navigation manifest and visited-cache e2e slice also passed:
Risk / compatibility
unstable_cache()usage observed during isolated layout probing block skip rather than relying on synthetic clean proof. Wrapped memo()/forwardRef()/React.lazy children are probed too.unstable_cache()trace metadata uses hashed keys and tag metadata, not raw keys or values.revalidateblocks skip because the retained layout has a revalidation policy, not a permanent artifact proof.Non-goals
References
#726-SKIP-04/05tests/app-page-dispatch.test.tsunstable_cache()rejection, optional catch-all empty-target rejection, data-dependent layout rejection including wrapped children and React.lazy children, finite-revalidate rejection, and hostile param-dependent layouts.tests/app-browser-client-reuse-manifest.test.tstests/app-page-route-wiring.test.tstests/app-layout-param-observation.test.tsunstable_cache()dependency observation isolation across child, parent, and sibling layouts.tests/app-page-probe.test.tstests/app-page-params.test.tstests/thenable-params.test.ts