From 5fb80f82ed22e9314c80a15e570e46f1761c4b9f Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sun, 1 Nov 2026 13:55:49 -0500 Subject: [PATCH] test(podcasts): the briefing acceptance plays the born-reversed order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The §0-item-2 acceptance pin predates the chain-order system and assumed the native default: it started the chain at feed position 1 and expected a forward hop. With the born-reversed default (d56031f3), the page's first card is feed position 5 and the chain runs 5 → 1 — the acceptance's MEANING is unchanged (play from the first card you see, chained back-to-back within the live briefing set); the fixture card it starts from flipped accordingly. Changelogged. This was the only failure in the full-suite validation run (154s, green) — the first whole-suite pass across today's four units (chips, label endpoint, apply-path seed, born-reversed acceptance). --- cmd/server/tests/podcast_test.go | 16 +++++++++------- docs/contract_pins.md | 6 ++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/cmd/server/tests/podcast_test.go b/cmd/server/tests/podcast_test.go index c90325c3..16d1ac84 100644 --- a/cmd/server/tests/podcast_test.go +++ b/cmd/server/tests/podcast_test.go @@ -884,9 +884,10 @@ func TestPodcastSmartCollections(t *testing.T) { t.Run("acceptance_briefing_plays_back_to_back", func(t *testing.T) { // ALL mode is the stored tree root: today's unplayed feed-A - // episodes = aNew + aNew2, chained in native feed order. Playing - // the FIRST match (the header's Play-as-Sequence target) must - // chain into the second. + // episodes = aNew + aNew2. BORN REVERSED (2026-11-01): the + // collection's default chain order is reverse, so the page's + // first card is feed position 5 (aNew2) and the chain runs + // 5 → 1 — book order for feeds that list newest-first. // The detail page (smart branch, All Libraries view) renders // episode cards with the play affordance + the header button. @@ -905,16 +906,17 @@ func TestPodcastSmartCollections(t *testing.T) { assert.Contains(t, html, "Play as Sequence", "smart collections play as a sequence too") assert.Contains(t, html, "?queue=collection:"+collID, "smart episode cards chain through the queue param") - // Start from the first briefing match (feed position 1): index 1 - // of 2, next = the second, both hops carrying the queue param. + // Start from the page's FIRST card (feed position 5 under the + // reversed default): index 1 of 2, next = feed position 1, both + // hops carrying the queue param. code, body = podcastAuthed(t, setup, regToken, "GET", - "/readers/"+uuid.UUID(aNew.ID.Bytes).String()+"?queue=collection:"+collID, "") + "/readers/"+uuid.UUID(aNew2.ID.Bytes).String()+"?queue=collection:"+collID, "") require.Equal(t, http.StatusOK, code) html = string(body) assert.Contains(t, html, esc(`"source":"collection"`)) assert.Contains(t, html, esc(`"episode_index":1`)) assert.Contains(t, html, esc(`"index_total":2`), "exactly the briefing set: aOld fails <7d, aPlayed fails unplayed, aPending is un-downloaded, bEp is RLS-dropped") - assert.Contains(t, html, esc(`"next_url":"/readers/`+uuid.UUID(aNew2.ID.Bytes).String()+`?queue=collection:`+collID+`"`)) + assert.Contains(t, html, esc(`"next_url":"/readers/`+uuid.UUID(aNew.ID.Bytes).String()+`?queue=collection:`+collID+`"`)) assert.NotContains(t, html, `id="player-order-select"`, "computed order — the order control stays hidden (R1)") }) diff --git a/docs/contract_pins.md b/docs/contract_pins.md index d1f64d97..a24eeaff 100644 --- a/docs/contract_pins.md +++ b/docs/contract_pins.md @@ -714,3 +714,9 @@ Explicit values (client-sent or stored — e.g. a deliberate native) are never clobbered. Pinned (TestSmartCollectionBornReversed): apply-seeds-when-unordered, respects stored native, respects client native. + +TestPodcastSmartCollections' acceptance pin updated with the same flip: +the briefing acceptance now starts from the page's FIRST card (feed +position 5 — the born-reversed default's book order) and chains into +feed position 1. The acceptance meaning is unchanged: play from what +you see, chained back-to-back within the live briefing set.