Skip to content

Transition voting: rate a blend, adapt that pair's next one - #126

Merged
sanylax0 merged 1 commit into
mainfrom
claude/transition-voting-restore
Jul 21, 2026
Merged

sanylax0 merged 1 commit into
mainfrom
claude/transition-voting-restore

Conversation

@sanylax2

Copy link
Copy Markdown
Collaborator

What this is

This is your own WIP, reassembled — please sanity-check the design before merging. The feature was split across two places and neither built on its own:

  • unpushed local commit f7c07ca "Worktree WIP" on main — TransitionVote, Player+Voting, TransitionVoteBar, TransitionFeedback tests
  • stash@{0} on feat/transition-voting — the stored properties (transitionVoteHistoryStorage, adaptationCache), TransitionSettings.simplified(level:), and the app-layer wiring

That's why Player+Voting.swift referenced three symbols declared nowhere in the repo. The halves are disjoint and compose exactly; together they build and pass. Your stash@{0} and the feat/transition-voting branch are untouched — I used stash apply, not pop, and worked on a scratch branch.

The feature

Thumbs up/down on the transition you just heard. Votes are keyed by the directional track pair (A→B rated separately from B→A — the blend isn't symmetric) and snapshot the settings that actually produced the blend, so a downvote on an already-simplified transition is distinguishable from one on your full settings. Repeated downvotes back that pair's blend off a step at a time; upvotes let it climb back.

  • TransitionVote (@Model) — plain UUID references rather than SwiftData relationships, so votes survive a track being deleted and re-imported without cascade rules getting involved.
  • TransitionFeedback.simplificationLevel (ContinuityCore) — pure vote-history → level math, unit-tested and Linux-portable like the rest of the policy code.
  • TransitionSettings.simplified(level:) — progressively drops beatmatching, bass swap, harmonic mixing, and shortens the blend.
  • Player+Voting — adaptedTransitionSettings is cached per pair, because the scheduling check runs at 20 Hz and the history lookup is a SwiftData fetch. Invalidated on a new vote and on any settings change.
  • clearTransitionState drops the votable record — an aborted blend was never fully heard, so there's nothing to rate.
  • RootView supplies vote history via the same hook pattern as onQueueExhausted; TransitionVoteBar appears in both the compact and sheet Now Playing layouts.

Rebase note

One conflict, resolved by keeping both sides: origin/main (#121) added pitch-settle teardown to clearTransitionState(), and this branch added vote-state teardown to the same function. Both are now there.

Testing

  • ContinuityCore 175 tests pass (+7 from TransitionFeedbackTests).
  • App target builds clean for the iOS 27 simulator.
  • Device verification is yours — in particular whether the thumbs bar's placement and timing feel right, which I can't judge from a build.

🤖 Generated with Claude Code

Thumbs up/down on the transition you just heard. Votes are keyed by the
*directional* track pair (A→B is rated separately from B→A — the blend isn't
symmetric) and snapshot the settings that actually produced the blend, so a
downvote on an already-simplified transition is distinguishable from one on the
user's full settings. Repeated downvotes back that pair's blend off a step at a
time; upvotes let it climb back.

- TransitionVote (@model): plain UUID references rather than SwiftData
  relationships, so votes survive a track being deleted and re-imported without
  cascade rules getting involved.
- TransitionFeedback.simplificationLevel (ContinuityCore): pure vote-history →
  level math, unit-tested and Linux-portable like the rest of the DSP//policy
  code.
- TransitionSettings.simplified(level:): progressively drops beatmatching, bass
  swap, and harmonic mixing, and shortens the blend.
- Player+Voting: adaptedTransitionSettings is cached per pair, because the
  scheduling check runs at 20 Hz and the history lookup is a SwiftData fetch.
  Cache is invalidated on a new vote and on any settings change.
- clearTransitionState drops the votable record: an aborted blend was never
  fully heard, so there's nothing to rate.
- RootView supplies vote history via the same hook pattern as onQueueExhausted;
  TransitionVoteBar appears in both the compact and sheet Now Playing layouts.

Reassembled from work that was split across an unpushed local commit and a
stash, then rebased onto main (clearTransitionState needed both the new
pitch-settle teardown and the vote teardown).

ContinuityCore: 175 tests pass. App target builds for the simulator.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sanylax0
sanylax0 merged commit f9f4de5 into main Jul 21, 2026
2 of 4 checks passed
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.

2 participants