You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #1265 added initialDataUpdatedAt to IslandQueryOptions specifically so a server-rendered
snapshot keeps its real cache age across hydration. The generated app's canonical island computes cachedAt in its loader, passes it through as a prop — and then uses it only as a display label,
never as initialDataUpdatedAt. The differentiator seam ships unexercised in the one example the
scaffold designates as canonical, so first paint tells TanStack the snapshot is fresh as of
hydration. The most polished downstream consumer made the same mistake independently, which is
evidence the seam is undiscoverable rather than unwanted.
Evidence
research/repo-audit/web-layer.md §4.2 and gap-register item 11; research/external/eis-chat.md §6 and §11 S10.
Repo, verified at fac9e339042c:
packages/fresh/src/application/query/query-types.ts:135-136 — the option exists:
"Timestamp when the server loaded initialData, used to preserve its cache age."
packages/cli/src/kernel/assets/app/routes/examples/(_shared)/service-showcase.ts.template:67
computes const cachedAt = Date.now(); and :77 returns it.
packages/cli/src/kernel/assets/app/routes/examples/(_islands)/ServiceShowcaseLab.tsx.template:43-49
calls useQuery<ServiceListData>({ queryKey, queryFn, initialData: props.initialList, staleTime: 15_000 }) — no initialDataUpdatedAt; :105 uses props.cachedAt only to
render a "Cached at" stat.
Downstream consumer evidence (research/external/eis-chat.md §6): cachedAt is threaded through
three files (routes/skills/index.tsx:49 → (_components)/skills-view.tsx:40-48 → islands/SkillsPanel.tsx:34) and then discarded at SkillsPanel.tsx:74
(cachedAt: _cachedAt).
Current surface
The seam exists, is documented in the type, and is used nowhere: not in the scaffold, not in the
reference consumer. Nothing fails when it is omitted, so the omission is invisible.
Target contract
The canonical generated island passes initialDataUpdatedAt: props.cachedAt alongside initialData, so the hydrated cache entry carries its true server age and staleTime behaves as
documented.
Both showcase variants (ServiceShowcaseLab.tsx.template and the memory variant) use the same
shape, so the two generated paths teach one dialect.
A regression test asserts that any generated island seeded with initialData from a loader that
returns cachedAt also passes initialDataUpdatedAt — the assertion is on the generated output,
not on prose.
Not in scope: the duplicate useLiveQuery exports and IslandLiveQueryResult.details
(web-layer.md §4.4), or any change to packages/fresh source — this is scaffold + docs only.
Docs/consumer proof
The proof is behavioral: in a scaffolded project, a page rendered from a server snapshot older than staleTime refetches immediately after hydration, and one rendered from a fresh snapshot does not.
The Web Layer query/cache-first documentation shows the same three lines the scaffold emits, and the
migration note gives a beta-era consumer an exact diff to apply.
Provenance
Seed run plan-fable5-remediation-roadmap--seed, PR #1347, 2026-08-08. Drafted from research/repo-audit/web-layer.md §4.2 and research/external/eis-chat.md §6/S10; every line
re-verified against worktree fac9e339042c. No GitHub mutation performed.
Filed from planning seed PR #1347 · source Draft-ID T2-07 · live issue #1360.
Summary
PR #1265 added
initialDataUpdatedAttoIslandQueryOptionsspecifically so a server-renderedsnapshot keeps its real cache age across hydration. The generated app's canonical island computes
cachedAtin its loader, passes it through as a prop — and then uses it only as a display label,never as
initialDataUpdatedAt. The differentiator seam ships unexercised in the one example thescaffold designates as canonical, so first paint tells TanStack the snapshot is fresh as of
hydration. The most polished downstream consumer made the same mistake independently, which is
evidence the seam is undiscoverable rather than unwanted.
Evidence
research/repo-audit/web-layer.md§4.2 and gap-register item 11;research/external/eis-chat.md§6 and §11 S10.fac9e339042c:packages/fresh/src/application/query/query-types.ts:135-136— the option exists:"Timestamp when the server loaded
initialData, used to preserve its cache age."packages/cli/src/kernel/assets/app/routes/examples/(_shared)/service-showcase.ts.template:67computes
const cachedAt = Date.now();and:77returns it.packages/cli/src/kernel/assets/app/routes/examples/(_islands)/ServiceShowcaseLab.tsx.template:43-49calls
useQuery<ServiceListData>({ queryKey, queryFn, initialData: props.initialList, staleTime: 15_000 })— noinitialDataUpdatedAt;:105usesprops.cachedAtonly torender a "Cached at" stat.
research/external/eis-chat.md§6):cachedAtis threaded throughthree files (
routes/skills/index.tsx:49→(_components)/skills-view.tsx:40-48→islands/SkillsPanel.tsx:34) and then discarded atSkillsPanel.tsx:74(
cachedAt: _cachedAt).Current surface
The seam exists, is documented in the type, and is used nowhere: not in the scaffold, not in the
reference consumer. Nothing fails when it is omitted, so the omission is invisible.
Target contract
initialDataUpdatedAt: props.cachedAtalongsideinitialData, so the hydrated cache entry carries its true server age andstaleTimebehaves asdocumented.
ServiceShowcaseLab.tsx.templateand the memory variant) use the sameshape, so the two generated paths teach one dialect.
initialDatafrom a loader thatreturns
cachedAtalso passesinitialDataUpdatedAt— the assertion is on the generated output,not on prose.
threaded
cachedAtintoinitialDataUpdatedAtinstead of dropping it, and (b) delete theclientKey → queryKeyas unknown ascasts that fix(fresh): converge SDK and island cache tiers #1265 made unnecessary. The cast half isfix(fresh/query): island query types reject the package's own documented patterns #1245's remnant scope; this issue contributes the
initialDataUpdatedAthalf and links to itrather than duplicating it.
Acceptance
initialDataUpdatedAtfrom the loader'scachedAt.initialDataUpdatedAtwhenever itpasses loader-seeded
initialData.initialDataUpdatedAtfrom the template fails that test.cachedAtintoinitialDataUpdatedAtfor apps upgradingfrom beta-era pins.
deno task e2e:cli run scaffold.runtime --cleanuptype-checks the generated app withthe corrected island.
Boundaries
getIslandQueryClient()@throwsJSDoc that documents a guard the body does not implement
(
packages/fresh/src/application/query/query-client.ts:26-27vs its body), theclientKeyasymmetry, and the consumer note about deleting the six copied casts. fix(fresh/query): island query types reject the package's own documented patterns #1245 is ~75% landed via
fix(fresh): converge SDK and island cache tiers #1265 and is proposed for rescope, not re-implementation; do not re-file its scope here and do
not close it with this PR.
independently.
useLiveQueryexports andIslandLiveQueryResult.details(
web-layer.md§4.4), or any change topackages/freshsource — this is scaffold + docs only.Docs/consumer proof
The proof is behavioral: in a scaffolded project, a page rendered from a server snapshot older than
staleTimerefetches immediately after hydration, and one rendered from a fresh snapshot does not.The Web Layer query/cache-first documentation shows the same three lines the scaffold emits, and the
migration note gives a beta-era consumer an exact diff to apply.
Provenance
Seed run
plan-fable5-remediation-roadmap--seed, PR #1347, 2026-08-08. Drafted fromresearch/repo-audit/web-layer.md§4.2 andresearch/external/eis-chat.md§6/S10; every linere-verified against worktree
fac9e339042c. No GitHub mutation performed.Filed from planning seed PR #1347 · source Draft-ID T2-07 · live issue #1360.