Skip to content

feat(sessions): un-stub Manual TrackSource via shared write sink#51

Open
mads-jm wants to merge 1 commit into
mvpfrom
feat/track-sourcing-manual
Open

feat(sessions): un-stub Manual TrackSource via shared write sink#51
mads-jm wants to merge 1 commit into
mvpfrom
feat/track-sourcing-manual

Conversation

@mads-jm

@mads-jm mads-jm commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Short Description

Un-stubs the Manual TrackSource (it was a no-op at useTrackSource.ts:322) by routing it through a new shared normalize→write sink, so a manually-entered track now actually lands in the playlist with correct attribution and source provenance. The P2P TrackSource stays a deliberate no-op — that's #38, a separate P2P-gated lane.

Background

This is the renderer-cluster predecessor for Wave 2/3 (#43 turn coordination, #50 SessionView extraction, #26 CRUD tests). The point of doing it first is the sink: track-sink.ts is the single place that normalizes an incoming track (manual, and later P2P) into a canonical record and appends it, so the later lanes build on a fixed contract instead of negotiating one live. The hook wrapper stays intentionally thin — all the load-bearing logic lives in the sink, where it's testable without a React/RxDB harness.

What Has Changed

  • track-sink.ts (new) — normalize→createTrackaddTrackToPlaylist with attribution (addedBy) and source provenance; Spotify-only externalIdspotifyId mapping, localFilePath passthrough, deterministic create-then-append order
  • useTrackSource.ts — the 'manual' branch calls the sink instead of returning a no-op; 'p2p' remains a no-op by design (out of scope)
  • AddTrackPanel.tsx (new) + SessionView.tsx — the manual add affordance and its wiring
  • session-interfaces.ts — types for the sink input
  • track-sink.test.ts (new, 5 cases) — attribution, source provenance, externalIdspotifyId, localFilePath passthrough, create→append ordering

Steps for Reviewing

  1. Start at track-sink.ts — this is the contract Wave 2/3 will consume; judge it as load-bearing API, not a one-off.
  2. useTrackSource.ts: confirm 'manual' now writes and 'p2p' is still a no-op (scope was feat(sessions): un-stub Manual TrackSource #37 only). ✅ inspector verified no P2P TrackSource code present
  3. Confirm no schema change — track records stay v3-compatible, no migration. ✅
  4. cd app && npm run test — 191 pass incl. the 5 new sink tests. ✅ independently re-run by inspector
  5. Manual QA (not exercised — headless): add a track via the panel in a live session; confirm one feed entry, correct attribution, turn advances once.

Checklist

  • Typecheck clean on changed files (the 15 node_modules/vite.config.ts tsc errors are a pre-existing base baseline)
  • Tests green (191/0); inspector verdict APPROVE on the first pass
  • Scope held to feat(sessions): un-stub Manual TrackSource #37; P2P arm untouched
  • Live-session manual QA pending (no component/RxDB test harness in the repo yet)
  • Lint: ESLint config doesn't load on base — see chore/fix-dev-env-lint; changed files were lint-validated via a temporary .mjs config

Closes #37


Comments

Carry-forwards (non-blocking, for a later cycle):

  • Library-search errors in the add flow are currently swallowed silently with no user feedback (medium).
  • AddTrackPanel + the useTrackSource.addTrack wrapper are untested — the repo has no React/hook test harness; the load-bearing normalization is fully covered in track-sink.test.ts.

Merging this first unblocks Wave 2 (#43, #39).

The 'manual' arm of useTrackSource was a no-op (useTrackSource.ts:322), so a
session could only be sourced from a Spotify Premium coordinator. Add a
source-agnostic normalize->write sink (addIncomingTrack) shared with the
Spotify path, expose a functional addTrack from the hook for manual sessions,
and add an AddTrackPanel affordance (manual entry + local-library search) to
SessionView. Turn advancement stays derived (computeEffectiveTurn) to avoid the
advanceTurn double-fire race. P2P arm (#38) remains a no-op (out of scope).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant