Repository navigation
Description
Summary
Follow-up to #568, which was closed when #576 merged. #576 shipped 4 of the 6 internal refactors (middleware merge builder, loader-cache interceptor, cache-hit fresh-loader extraction, parallel-slot component extraction) plus the consumer-facing trie suffix longest-wins fix (#575). Two sub-items remain and were deliberately deferred because they carry real semantic risk that the current test suite does not cover. This issue tracks them with the forensic findings already gathered.
Remaining work
Sub-item 2 — orphan-revalidation calls the shared parallel helper (policy args)
resolveOrphanLayoutWithRevalidation still inlines ~166 lines of parallel-slot resolution instead of calling resolveParallelSegmentsWithRevalidation. Two divergences between the inlined loop and the shared helper (src/router/segment-resolution/revalidation.ts):
| Divergence | Verdict (forensic) | Action |
|---|---|---|
(A) orphan defaultOverride: { value: true } vs main belongsToRoute || isNewParent |
INTENTIONAL — present since #228, deliberately preserved in #482 with a justifying comment, reachable at belongsToRoute=false, and it avoids the #482 blank-parent-chain-slot staleness bug |
Carry as an explicit policy arg (e.g. parentChainDefault: "force-render" | "type-derived"). Do NOT normalize — that's a product decision that changes rendered output for parent-chain orphan parallels under non-route parents. |
| (B) orphan loader-resolve-before-push vs main push-before-loaders | DRIFT / cosmetic — provably unobservable (segment tree walk + handle filter discard intra-parent order; loaders memoized by $$id); the orphan order is the one out of parity with fresh.ts |
Safe to normalize to the shared push-then-loaders order (improves fresh/reval parity). |
Sub-item 1 — unify the fresh.ts vs revalidation.ts resolution trees
resolveSegment/resolveOrphanLayout/resolveParallelEntry/resolveLoaders + collectEntryLoaders mirror each other across the two files. The issue's "byte-identical" premise is false: collectEntryLoaders twins differ in the loader call (resolveLoaders vs resolveLoadersWithRevalidation, +8 args) and matchedIds accumulation, and the resolveSegment twins diverge in per-segment revalidate gating + route-handler ordering. So this is a strategy-parameterized traversal, not a literal dedup — higher risk, do it after sub-item 2.
Blocker — coverage must come first
parallel-revalidate-fns-invocation.test.ts (the supposed pin) does not lock either divergence: every orphan case it runs passes belongsToRoute=true (where (A)'s two policies coincide) and the revalidate fns override the seed value. It therefore stays green under any unification and cannot catch a regression in (A) or (B).
Before refactoring, add a pinning test for the divergent (A) case: orphan parallel with belongsToRoute=false, slot ∉ clientSegmentIds, parent ∈ clientSegmentIds (so isNewParent=false), and zero revalidate fns — assert the slot resolves to a non-null component and appears in matchedIds (the orphan force-render behavior; the main path would skip it). Then carry (A) as a policy arg, normalize (B), and re-run the semantic matrix.
Acceptance
- New (A)-divergence pinning test added and red-before/green-after the policy-arg wiring.
- Behavior-preserving (matrix rows unchanged),
semantic-matrixgreen,execution-model.mdupdated if the contract is restated. debugPerformancebefore/after for the partial-revalidation hot path.
Activity
ivogt commentedon Jun 14, 2026
Duplicate of #568 (now reopened) — folded the remaining-work breakdown + forensic verdict into #568. Tracking continues there.