Conversation
The first "SDK gap" phase. Finding: joins and aggregation do NOT need a core
change. They ride the existing named-operation port (`store.run`), whose calling
convention is portable but whose implementation is per-backend, which is exactly
the seam the core reserves for where backends genuinely diverge. The capability
flags (serverSideJoins / aggregations) declare the divergence; the UI surfaces it.
Schema (both backends): people + credits make cast/director a real many-to-many
relation; Supabase adds FK constraints (for PostgREST embeds) and a genre_counts
SQL view.
Named queries, same shapes, divergent implementations:
- movieCredits (the JOIN): Supabase does a server-side PostgREST embed over the
FKs; Convex (convex/marquee.ts) and memory follow refs by hand.
- genreCounts (the AGGREGATION): Supabase reads a GROUP BY view; Convex and memory
scan and tally (the cost the `aggregations: false` flag warns about, and which
Phase 5 scale will exercise).
makeBackend wires the typed MarqueeSchema with per-backend query impls (src/lib/
enrich.ts, kept env-free so tests build typed backends directly). The catalog
functions are generic over the schema so the bare test backends still fit.
UI: MovieDetail shows the real joined cast (director + billed actors with
characters); the catalog shows per-genre counts. Both render an understated
caption declaring HOW the data loaded on the active backend ("Cast joined
server-side" vs "assembled by following references"; "Counted with a SQL view"
vs "by scanning") -- the thin-honest-waist thesis made visible.
Verification: enrich.live.test.ts (12 tests: join order + name resolution, empty
cast, aggregation, capability declaration) green on memory + Supabase + Convex;
catalog gate still 20/20. A Playwright UI smoke confirmed the cast join and the
genre-stats strip with the correct divergence captions on both live backends.
avg-rating aggregation defers to Phase 3 (reviews need auth); Phase 2's
aggregation is genre counts over existing data.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #51 (Phase 1). Phase 2 is the first "SDK gap" phase, and the finding is that there is no core gap: joins and aggregation ride the existing named-operation port (
store.run), whose calling convention is portable but whose implementation is per-backend. That is exactly the seam the core reserves for genuine divergence. The capability flags declare it; the UI surfaces it.Schema (both backends)
people+creditsmake cast/director a real many-to-many relation. Supabase adds FK constraints (so PostgREST can embed) and agenre_countsGROUP BY view.Named queries: same shape, divergent implementation
convex/marquee.ts) + memory = follow refs by hand.aggregations: falseflag warns about, exercised for real at Phase 5 scale).makeBackendwires the typedMarqueeSchemawith per-backend query impls (src/lib/enrich.ts, env-free so tests build typed backends directly). The catalog functions became generic over the schema so the bare test backends still fit.UI (the thesis, made visible)
MovieDetail shows the real joined cast (director + billed actors with characters); the catalog shows per-genre counts. Both render an understated caption declaring HOW the data loaded on the active backend: "Cast joined server-side" vs "assembled by following references"; "Counted with a SQL view" vs "by scanning".
Verification
test/enrich.live.test.ts: 12 tests (join order + name resolution, empty cast, aggregation, capability declaration) green on memory + Supabase + Convex. Catalog gate still 20/20. Full suite 32/32.No
packages/*change (the named-op port already covered it), so no changeset. avg-rating aggregation defers to Phase 3 (reviews need auth); Phase 2's aggregation is genre counts over existing data.