Every comment naming a path in flutter_client/ now resolves to nothing,
which is the failure mode this project has already been bitten by twice
-- drift #572 came from delete.go describing behaviour it no longer had,
and that same docstring was still wrong when it was fixed last week. A
pointer to a deleted directory is the same thing in slower motion: the
reader follows it, finds nothing, and cannot tell whether the comment is
stale or they are looking in the wrong place.
Three treatments, per what each comment was actually doing:
- Naming a concept ("mirrors db.dart's CachedTracks Drift table"):
keep the concept, drop the path. The Drift table is why the entity
looks as it does; the file it lived in is not.
- Pure port bookkeeping ("Mirrors <path>." and nothing else): deleted.
Git history records the port; the comment only restated it.
- Substance introduced by a pointer (a lifecycle list, a 200 px/s
threshold, an inverted control-row placement): keep the substance,
drop the lead-in.
The two Go comments were the valuable ones and got more than a trim.
They stated a live contract -- "field names match the client's FromJson
helpers exactly, or fields are silently dropped" -- against a client
that no longer exists. They now name the real consumer,
SyncResponseWire.kt, and say why the failure is silent there too:
kotlinx.serialization skips unknown keys, so a renamed field arrives as
a default value rather than an error.
The ticket counted 64 files by grepping flutter_client/. A second tier
turned up during the sweep: 15 more references naming bare Dart files
(player_bar.dart, now_playing_screen.dart:464, auth_provider.dart) with
no directory prefix. Same dead tree, same treatment, folded in here.
Comments only -- verified no non-comment line is touched in the diff.
Two fixes in one commit because they're entangled — the systemVariant
work would have been theater otherwise.
## The wire-format bug
/api/library/sync was emitting PascalCase JSON for artist / album /
track / playlist upserts (raw json.Marshal of sqlc-generated structs
with no JSON tags — sqlc.yaml: emit_json_tags=false). Flutter's
sync_controller _*FromJson reads snake_case keys, so all metadata
sync rows landed in drift with empty strings / zero ints.
The like_track / like_album / like_artist / playlist_track entities
work because they're hand-built `map[string]string` payloads with
snake_case keys — they sidestepped the bug. The 4 raw-marshal
entities did not.
Existing sync test caught zero of this — it asserts on len(upserts)
not field shape.
Fix: server-side view structs in library_sync_views.go with proper
JSON tags + pgtype-flattening (UUID → 8-4-4-4-12 hex string,
Date → "2006-01-02"). Mirrors the playlistRowView pattern from
/api/playlists. New library_sync_views_test.go pins the wire keys
so future field-name drift breaks loud.
## systemVariant column (closes#357 plan C v1 limitation)
playlistSyncView now carries `system_variant` server → wire.
Flutter drift schema bumped from 1 → 2 with onUpgrade adding the
`systemVariant TEXT NULL` column to cached_playlists. Cursor reset
to 0 in the migration so existing rows refresh with the new field
on the next sync.
playlistsListProvider now filters locally by systemVariant:
- kind='user' → systemVariant IS NULL (the add-to-playlist sheet's intent)
- kind='system' → systemVariant IS NOT NULL
- kind='all' → no filter
Closes the documented v1 limitation where the add-to-playlist sheet
showed system playlists alongside user-created ones.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>