Commit 9a428b6e by PLN (Algolia)

feat(backlog_setlists v2): explicit ends, label-strip, leet fallback + tests

- ANCHORS support (slug, end_line) to bound bleeders (mephisteuf/opal-2025/
  38c3-toilet) into clean blocks — no more swallowing neighbour setlists.
- clean_track_line: strip leading set-position labels (Intro:/Finale:/Sunset),
  keep 'Label: Name' / drop 'Name: gloss'; recovers the LIVE-Noctambule pattern.
- leet_fold fallback (B00K→book, T01l3ts→toilets, G00D→good) — resolves only
  after a straight miss so genuine digits (sept1) still match first.
- 9 gap gigs recovered (opal-2024 14/14, algolia-fdlm 26/26, 39c3 13/14…).
- 6 mechanical tests (leet, label, gloss, bpm/transition, ascii/comment skip,
  real-backlog coverage guard). 59 pass.
parent 21d003dd
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
"confirm": false, "confirm": false,
"header": "## Live @MephisTeuf 😈‍💻😈", "header": "## Live @MephisTeuf 😈‍💻😈",
"anchor_line": 710, "anchor_line": 710,
"n_tracks": 63, "n_tracks": 6,
"n_resolved": 44, "n_resolved": 5,
"suspect_bleed": true, "suspect_bleed": false,
"tracks": [ "tracks": [
{ {
"raw": "TOP HATS", "raw": "TOP HATS",
...@@ -22,574 +22,189 @@ ...@@ -22,574 +22,189 @@
"section": null "section": null
}, },
{ {
"raw": "Something about us", "raw": "Contre-Visite",
"track": null,
"bpm": null,
"transition": null,
"section": "3 Live Love 3"
},
{
"raw": "Best Part",
"track": null,
"bpm": null,
"transition": null,
"section": "3 Live Love 3"
},
{
"raw": "Dream a little dream of Me",
"track": null,
"bpm": null,
"transition": null,
"section": "3 Live Love 3"
},
{
"raw": "Until I found U",
"track": null,
"bpm": null,
"transition": null,
"section": "3 Live Love 3"
},
{
"raw": "Killing me Softly",
"track": null,
"bpm": null,
"transition": null,
"section": "3 Live Love 3"
},
{
"raw": "Can't Help Falling in Love",
"track": null,
"bpm": null,
"transition": null,
"section": "3 Live Love 3"
},
{
"raw": "U remind me",
"track": null,
"bpm": null,
"transition": null,
"section": "3 Live Love 3"
},
{
"raw": "Invoque l'Été",
"track": "live/midi/nova/lounge/invoque_ete.tidal",
"bpm": null,
"transition": null,
"section": "Intro Meme l'hiver a une fin"
},
{
"raw": "Solar",
"track": "live/midi/nova/breaks/solar.tidal",
"bpm": null,
"transition": null,
"section": "Le jour est court"
},
{
"raw": "Contre Visite",
"track": "live/midi/nova/ambient/contre_visite.tidal", "track": "live/midi/nova/ambient/contre_visite.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "La nuit est LONGUE" "section": "LIVE Noctambule"
},
{
"raw": "Empreinte du Numerique",
"track": "live/midi/nova/ambient/empreinte_du_numerique.tidal",
"bpm": null,
"transition": null,
"section": "La nuit est LONGUE"
}, },
{ {
"raw": "Break the Loop", "raw": "ATARI-ght",
"track": "live/midi/nova/dnb/break_the_loop.tidal", "track": "live/chip/ataright.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "La nuit est LONGUE" "section": "LIVE Noctambule"
}, },
{ {
"raw": "Alerte Verte", "raw": "Burn this B00K",
"track": "live/midi/nova/dnb/alerte_verte.tidal", "track": "live/techno/noir/burn_this_book.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "La nuit est LONGUE" "section": "LIVE Noctambule"
}, },
{ {
"raw": "Invoque l'été", "raw": "It's About TIME",
"track": "live/midi/nova/lounge/invoque_ete.tidal", "track": "live/midi/nova/breaks/its_about_time.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "_Aperitif_" "section": "LIVE Noctambule"
}, },
{ {
"raw": "Solar", "raw": "Solar",
"track": "live/midi/nova/breaks/solar.tidal", "track": "live/midi/nova/breaks/solar.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "_Entree_" "section": "LIVE Noctambule"
}, }
{ ]
"raw": "Lunar",
"track": "live/midi/nova/breaks/lunar.tidal",
"bpm": null,
"transition": null,
"section": "_Entree_"
},
{
"raw": "Michael",
"track": "live/midi/nova/lounge/michael.tidal",
"bpm": null,
"transition": null,
"section": "_Accompagnement_"
}, },
"2024/opal-festival-2024": {
"slug": "2024/opal-festival-2024",
"confirm": false,
"header": "## Opal <3🦉",
"anchor_line": 1031,
"n_tracks": 14,
"n_resolved": 14,
"suspect_bleed": false,
"tracks": [
{ {
"raw": "Nightly Repair", "raw": "Fabuleux",
"track": "live/techno/nightly_repair.tidal", "track": "live/midi/nova/lounge/fabuleux.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "_Accompagnement_" "section": null
}, },
{ {
"raw": "Contre visite", "raw": "Cafe Glacé",
"track": "live/midi/nova/ambient/contre_visite.tidal", "track": "live/midi/nova/nujazz/cafe_glace.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "_Accompagnement_" "section": null
}, },
{ {
"raw": "Burn this Book", "raw": "Café Bouillant",
"track": "live/techno/noir/burn_this_book.tidal", "track": "live/midi/nova/nujazz/cafe_bouillant.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "_Plat de resistance_" "section": null
}, },
{ {
"raw": "Break the Loop", "raw": "Cafe Tiède",
"track": "live/midi/nova/dnb/break_the_loop.tidal", "track": "live/midi/nova/nujazz/cafe_tiede.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "_Dessert_" "section": null
}, },
{ {
"raw": "Atari-ght", "raw": "Force MOTRICE",
"track": "live/chip/ataright.tidal", "track": "live/midi/nova/dnb/force_motrice.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "_Dessert_" "section": null
}, },
{ {
"raw": "Alerte Verte", "raw": "Alerte verte",
"track": "live/midi/nova/dnb/alerte_verte.tidal", "track": "live/midi/nova/dnb/alerte_verte.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "_Dernier Verre_" "section": null
},
{
"raw": "It's About Time",
"track": "live/midi/nova/breaks/its_about_time.tidal",
"bpm": null,
"transition": null,
"section": "__Digestif__"
},
{
"raw": "Premiere Grillade",
"track": "live/midi/nova/lofi/premiere_grillade.tidal",
"bpm": null,
"transition": null,
"section": "Live toi toi mon toit"
},
{
"raw": "Break Dynasty",
"track": "live/midi/nova/breaks/break_dynasty.tidal",
"bpm": null,
"transition": null,
"section": "Live toi toi mon toit"
},
{
"raw": "Clameur",
"track": "live/hip/darkside/clameur.tidal",
"bpm": null,
"transition": null,
"section": "Live toi toi mon toit"
},
{
"raw": "Nouveau Soleil",
"track": "live/midi/nova/dnb/nouveau_soleil.tidal",
"bpm": null,
"transition": null,
"section": "Live toi toi mon toit"
},
{
"raw": "It's About Time",
"track": "live/midi/nova/breaks/its_about_time.tidal",
"bpm": null,
"transition": null,
"section": "Live toi toi mon toit"
},
{
"raw": "Accueil",
"track": null,
"bpm": null,
"transition": null,
"section": "Pour _Demeter_ 3"
},
{
"raw": "Paradis perdu",
"track": null,
"bpm": null,
"transition": null,
"section": "Pour _Demeter_ 3"
},
{
"raw": "Véneration",
"track": null,
"bpm": null,
"transition": null,
"section": "Pour _Demeter_ 3"
},
{
"raw": "Idoles",
"track": null,
"bpm": null,
"transition": null,
"section": "Pour _Demeter_ 3"
},
{
"raw": "Nuit",
"track": null,
"bpm": null,
"transition": null,
"section": "Pour _Demeter_ 3"
}, },
{ {
"raw": "Bouquet", "raw": "Nouveau Punk",
"track": null, "track": "live/collab/raph/nouveau_punk.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "Pour _Demeter_ 3" "section": null
}, },
{ {
"raw": "Rite Final", "raw": "Jeudrill",
"track": null, "track": "live/collab/raph/jeudrill.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "Pour _Demeter_ 3" "section": null
}, },
{ {
"raw": "Invoque l'été", "raw": "Bain Bouillant",
"track": "live/midi/nova/lounge/invoque_ete.tidal", "track": "live/midi/nova/nujazz/cafe_bouillant.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "Pour _Demeter_ 3" "section": null
}, },
{ {
"raw": "Alerte VERTE", "raw": "Haunted House",
"track": "live/midi/nova/dnb/alerte_verte.tidal", "track": "live/midi/nova/beatober/oct_16_haunted_house_insouciance.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "Pour _Demeter_ 3" "section": null
}, },
{ {
"raw": "Nouveau Soleil", "raw": "Blue Gold",
"track": "live/midi/nova/dnb/nouveau_soleil.tidal", "track": "live/collab/ccc/ccc0.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "CANCELED Live Orleans - Labomedia's festival fire" "section": null
}, },
{ {
"raw": "Mauerpark", "raw": "L'été à MauerPark",
"track": "live/midi/nova/techno/ete_a_mauerpark.tidal", "track": "live/midi/nova/techno/ete_a_mauerpark.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "CANCELED Live Orleans - Labomedia's festival fire" "section": null
}, },
{ {
"raw": "SlowMo", "raw": "Contre Visite",
"track": "live/hip/lofi/slow_mo.tidal", "track": "live/midi/nova/ambient/contre_visite.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "PreShow with Chuck 15mn" "section": null
}, },
{ {
"raw": "Lendemain Divin", "raw": "Lendemain Divin",
"track": "live/midi/nova/lofi/lendemain_divin.tidal", "track": "live/midi/nova/lofi/lendemain_divin.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "PreShow with Chuck 15mn" "section": null
}, }
{ ]
"raw": "Invoque l'été",
"track": "live/midi/nova/lounge/invoque_ete.tidal",
"bpm": null,
"transition": null,
"section": "PreShow with Chuck 15mn"
}, },
"2024/toplap-solstice-2024": {
"slug": "2024/toplap-solstice-2024",
"confirm": false,
"header": "### TopLap Solstice Stream 2024",
"anchor_line": 1169,
"n_tracks": 4,
"n_resolved": 3,
"suspect_bleed": false,
"tracks": [
{ {
"raw": "Before", "raw": "Deck the Hall",
"track": null, "track": null,
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "Sessions Break 15mn" "section": "Tracklist"
},
{
"raw": "Nouveau Soleil",
"track": "live/midi/nova/dnb/nouveau_soleil.tidal",
"bpm": null,
"transition": null,
"section": "Sessions Break 15mn"
},
{
"raw": "Premiere Grillade",
"track": "live/midi/nova/lofi/premiere_grillade.tidal",
"bpm": null,
"transition": null,
"section": "Sessions Break 15mn"
},
{
"raw": "Été à Mauerpark",
"track": "live/midi/nova/techno/ete_a_mauerpark.tidal",
"bpm": null,
"transition": null,
"section": "Sessions Break 15mn"
},
{
"raw": "Nouveau soleil",
"track": "live/midi/nova/dnb/nouveau_soleil.tidal",
"bpm": null,
"transition": null,
"section": "REPAIR MULTILINE"
},
{
"raw": "Prestance",
"track": "live/midi/nova/ambient/prestance.tidal",
"bpm": null,
"transition": null,
"section": "Adapt to DAW removing midiG calls"
},
{
"raw": "Oct4 Glitch Sauvages",
"track": "live/midi/nova/beatober/oct_glitchs_sauvages.tidal",
"bpm": null,
"transition": null,
"section": "Adapt to DAW removing midiG calls"
},
{
"raw": "About time",
"track": "live/midi/nova/breaks/its_about_time.tidal",
"bpm": null,
"transition": null,
"section": "Adapt to DAW removing midiG calls"
},
{
"raw": "Toxic",
"track": "live/boeuf/algorythm/fdlm2022/toxic.tidal",
"bpm": null,
"transition": null,
"section": "Adapt to DAW removing midiG calls"
},
{
"raw": "Venons ensemble",
"track": "live/midi/nova/dnb/venons_ensemble.tidal",
"bpm": null,
"transition": null,
"section": "Adapt to DAW removing midiG calls"
},
{
"raw": "Reboot",
"track": "live/midi/nova/lofi/reboot.tidal",
"bpm": null,
"transition": null,
"section": "READY FOR MIX"
}, },
{ {
"raw": "Premiere Grillade", "raw": "Something about DRUMS",
"track": "live/midi/nova/lofi/premiere_grillade.tidal", "track": "live/midi/nova/dnb/something_about_drums.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "READY FOR MIX" "section": "Tracklist"
}, },
{ {
"raw": "Rainy day", "raw": "La fin de l'insouciance",
"track": "live/collab/josh/oct_18_rainy_day.tidal", "track": "live/midi/nova/beatober/oct_16_haunted_house_insouciance.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "READY FOR MIX" "section": "Tracklist"
}, },
{ {
"raw": "Rainy day", "raw": "Blue Gold",
"track": "live/collab/josh/oct_18_rainy_day.tidal", "track": "live/collab/ccc/ccc0.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "READY FOR TAKEOFF" "section": "Tracklist"
}, }
{ ]
"raw": "Bain bouillant",
"track": "live/midi/nova/nujazz/cafe_bouillant.tidal",
"bpm": null,
"transition": null,
"section": "VELOCITE"
},
{
"raw": "Acid RAIN",
"track": null,
"bpm": null,
"transition": null,
"section": "VELOCITE"
},
{
"raw": "No Time to Die",
"track": null,
"bpm": null,
"transition": null,
"section": "VELOCITE"
},
{
"raw": "Haunted house",
"track": "live/midi/nova/beatober/oct_16_haunted_house_insouciance.tidal",
"bpm": null,
"transition": null,
"section": "VELOCITE"
},
{
"raw": "Finale",
"track": null,
"bpm": null,
"transition": null,
"section": "VELOCITE"
}
]
},
"2024/opal-festival-2024": {
"slug": "2024/opal-festival-2024",
"confirm": false,
"header": "## Opal <3🦉",
"anchor_line": 1031,
"n_tracks": 12,
"n_resolved": 11,
"suspect_bleed": false,
"tracks": [
{
"raw": "Cafe Glacé",
"track": "live/midi/nova/nujazz/cafe_glace.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "Café Bouillant",
"track": "live/midi/nova/nujazz/cafe_bouillant.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "Cafe Tiède",
"track": "live/midi/nova/nujazz/cafe_tiede.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "Force MOTRICE",
"track": "live/midi/nova/dnb/force_motrice.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "Alerte verte",
"track": "live/midi/nova/dnb/alerte_verte.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "Nouveau Punk",
"track": "live/collab/raph/nouveau_punk.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "Jeudrill",
"track": "live/collab/raph/jeudrill.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "Bain Bouillant",
"track": "live/midi/nova/nujazz/cafe_bouillant.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "Haunted House",
"track": "live/midi/nova/beatober/oct_16_haunted_house_insouciance.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "Blue Gold",
"track": "live/collab/ccc/ccc0.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "L'été à MauerPark",
"track": "live/midi/nova/techno/ete_a_mauerpark.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "Passation",
"track": null,
"bpm": null,
"transition": null,
"section": null
}
]
},
"2024/toplap-solstice-2024": {
"slug": "2024/toplap-solstice-2024",
"confirm": false,
"header": "### TopLap Solstice Stream 2024",
"anchor_line": 1169,
"n_tracks": 4,
"n_resolved": 3,
"suspect_bleed": false,
"tracks": [
{
"raw": "Deck the Hall",
"track": null,
"bpm": null,
"transition": null,
"section": "Tracklist"
},
{
"raw": "Something about DRUMS",
"track": "live/midi/nova/dnb/something_about_drums.tidal",
"bpm": null,
"transition": null,
"section": "Tracklist"
},
{
"raw": "La fin de l'insouciance",
"track": "live/midi/nova/beatober/oct_16_haunted_house_insouciance.tidal",
"bpm": null,
"transition": null,
"section": "Tracklist"
},
{
"raw": "Blue Gold",
"track": "live/collab/ccc/ccc0.tidal",
"bpm": null,
"transition": null,
"section": "Tracklist"
}
]
}, },
"2024/38c3-house-of-tea": { "2024/38c3-house-of-tea": {
"slug": "2024/38c3-house-of-tea", "slug": "2024/38c3-house-of-tea",
...@@ -597,881 +212,335 @@ ...@@ -597,881 +212,335 @@
"header": "#### Day 2 - HOUSE OF Tea", "header": "#### Day 2 - HOUSE OF Tea",
"anchor_line": 1194, "anchor_line": 1194,
"n_tracks": 12, "n_tracks": 12,
"n_resolved": 11, "n_resolved": 11,
"suspect_bleed": false, "suspect_bleed": false,
"tracks": [ "tracks": [
{
"raw": "Contre Visite",
"track": "live/midi/nova/ambient/contre_visite.tidal",
"bpm": null,
"transition": null,
"section": "TRACKLIST"
},
{
"raw": "Bain Electrique",
"track": "live/midi/nova/breaks/bain_electrique.tidal",
"bpm": null,
"transition": null,
"section": "TRACKLIST"
},
{
"raw": "Salut Nu",
"track": "live/midi/nova/nujazz/salut_nu.tidal",
"bpm": null,
"transition": null,
"section": "TRACKLIST"
},
{
"raw": "Cafe Tiede",
"track": "live/midi/nova/nujazz/cafe_tiede.tidal",
"bpm": null,
"transition": null,
"section": "TRACKLIST"
},
{
"raw": "Force Motrice",
"track": "live/midi/nova/dnb/force_motrice.tidal",
"bpm": null,
"transition": null,
"section": "TRACKLIST"
},
{
"raw": "Cafe Glace",
"track": "live/midi/nova/nujazz/cafe_glace.tidal",
"bpm": null,
"transition": null,
"section": "TRACKLIST"
},
{
"raw": "CCC0",
"track": null,
"bpm": null,
"transition": null,
"section": "TRACKLIST"
},
{
"raw": "ACIDULE",
"track": "live/collab/raph/acidule.tidal",
"bpm": null,
"transition": null,
"section": "TRACKLIST"
},
{
"raw": "Something about Drums",
"track": "live/midi/nova/dnb/something_about_drums.tidal",
"bpm": null,
"transition": null,
"section": "TRACKLIST"
},
{
"raw": "Alerte Verte",
"track": "live/midi/nova/dnb/alerte_verte.tidal",
"bpm": null,
"transition": null,
"section": "TRACKLIST"
},
{
"raw": "Permanence",
"track": "live/collab/raph/permanence.tidal",
"bpm": null,
"transition": null,
"section": "TRACKLIST"
},
{
"raw": "L'or Bleu",
"track": "live/collab/mousquetaires/blue_gold.tidal",
"bpm": null,
"transition": null,
"section": "TRACKLIST"
}
]
},
"2024/38c3-toilet": {
"slug": "2024/38c3-toilet",
"confirm": false,
"header": "#### Day 3 - Hardcore in the Toilet Club",
"anchor_line": 1242,
"n_tracks": 21,
"n_resolved": 12,
"suspect_bleed": true,
"tracks": [
{
"raw": "GHOSTS IN THE TOILETS",
"track": "live/collab/ccc/ghosts_in_the_toilets.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "NOUVEAU PUNK",
"track": "live/collab/raph/nouveau_punk.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "PITBULL PUNK",
"track": null,
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "ACIDULE",
"track": "live/collab/raph/acidule.tidal",
"bpm": null,
"transition": null,
"section": null
},
{
"raw": "Si Bon 142bpm",
"track": null,
"bpm": 142,
"transition": null,
"section": "Samedi au Paradis"
},
{
"raw": "Because it's there 110bpm",
"track": null,
"bpm": 110,
"transition": null,
"section": "Samedi au Paradis"
},
{
"raw": "L'amour d'abord 120bpm",
"track": null,
"bpm": 120,
"transition": null,
"section": "Samedi au Paradis"
},
{
"raw": "Ton Numero",
"track": "live/midi/nova/breaks/ton_numero.tidal",
"bpm": null,
"transition": null,
"section": "Boboche Session2"
},
{
"raw": "Because it's there",
"track": "copycat/because_its_there.tidal",
"bpm": null,
"transition": null,
"section": "Boboche Session2"
},
{
"raw": "Sunny Side Up",
"track": "live/midi/nova/lounge/sunny_side_up.tidal",
"bpm": null,
"transition": null,
"section": "Boboche Session2"
},
{
"raw": "Larmes Salees",
"track": null,
"bpm": null,
"transition": null,
"section": "Boboche Session2"
},
{
"raw": "Blues du Mic",
"track": null,
"bpm": null,
"transition": null,
"section": "Boboche Session2"
},
{
"raw": "Sept1",
"track": "live/collab/baba/sept1.tidal",
"bpm": null,
"transition": null,
"section": "Boboche Session2"
},
{
"raw": "Ton Numero",
"track": "live/midi/nova/breaks/ton_numero.tidal",
"bpm": null,
"transition": null,
"section": "ALGOLIA's CKO 2025"
},
{
"raw": "Paris you want",
"track": null,
"bpm": null,
"transition": null,
"section": "ALGOLIA's CKO 2025"
},
{
"raw": "Sunny Side Up",
"track": "live/midi/nova/lounge/sunny_side_up.tidal",
"bpm": null,
"transition": null,
"section": "ALGOLIA's CKO 2025"
},
{
"raw": "Cafe Glace",
"track": "live/midi/nova/nujazz/cafe_glace.tidal",
"bpm": null,
"transition": null,
"section": "ALGOLIA's CKO 2025"
},
{
"raw": "Cafe Bouillant",
"track": "live/midi/nova/nujazz/cafe_bouillant.tidal",
"bpm": null,
"transition": null,
"section": "ALGOLIA's CKO 2025"
},
{
"raw": "Force motrice",
"track": "live/midi/nova/dnb/force_motrice.tidal",
"bpm": null,
"transition": null,
"section": "ALGOLIA's CKO 2025"
},
{
"raw": "Sept1 Mode mineur",
"track": null,
"bpm": null,
"transition": null,
"section": "ALGOLIA's CKO 2025"
},
{
"raw": "Finish",
"track": null,
"bpm": null,
"transition": null,
"section": "ALGOLIA's CKO 2025"
}
]
},
"2025/ensad": {
"slug": "2025/ensad",
"confirm": false,
"header": "# Set @ENSAD 2025",
"anchor_line": 1441,
"n_tracks": 9,
"n_resolved": 7,
"suspect_bleed": false,
"tracks": [
{
"raw": "Quand on décolle",
"track": "live/midi/nova/ambient/quand_on_decolle.tidal",
"bpm": null,
"transition": "0 - / 11",
"section": null
},
{
"raw": "Parce qu'Elle est là",
"track": null,
"bpm": null,
"transition": "7",
"section": null
},
{
"raw": "Ere de jeu",
"track": "live/midi/nova/techno/ere_de_jeu.tidal",
"bpm": null,
"transition": "123- 9",
"section": null
},
{
"raw": "l'Été à Mauerpark",
"track": "live/midi/nova/techno/ete_a_mauerpark.tidal",
"bpm": null,
"transition": "9",
"section": null
},
{
"raw": "Sept1",
"track": "live/collab/baba/sept1.tidal",
"bpm": null,
"transition": "11",
"section": null
},
{
"raw": "Sunny Side Up",
"track": "live/midi/nova/lounge/sunny_side_up.tidal",
"bpm": null,
"transition": "11 /",
"section": null
},
{
"raw": "L'or Bleu",
"track": "live/collab/mousquetaires/blue_gold.tidal",
"bpm": null,
"transition": "5",
"section": null
},
{
"raw": "Cafe Tiede",
"track": "live/midi/nova/nujazz/cafe_tiede.tidal",
"bpm": null,
"transition": "5",
"section": null
},
{
"raw": "Finale",
"track": null,
"bpm": null,
"transition": null,
"section": "- Atelier de Force Motrice - 57"
}
]
},
"2025/opal-festival-2025": {
"slug": "2025/opal-festival-2025",
"confirm": false,
"header": "# OPAL 2025",
"anchor_line": 1632,
"n_tracks": 78,
"n_resolved": 49,
"suspect_bleed": true,
"tracks": [
{
"raw": "Drifting soul",
"track": "live/collab/jane/drifting_soul.tidal",
"bpm": 80,
"transition": "10+5->4+11",
"section": "INTRO"
},
{
"raw": "Lendemain Divin",
"track": "live/midi/nova/lofi/lendemain_divin.tidal",
"bpm": 95,
"transition": "4,5,6->6",
"section": "INTRO"
},
{
"raw": "Quand on Décolle",
"track": "live/midi/nova/ambient/quand_on_decolle.tidal",
"bpm": 120,
"transition": "11+12->11",
"section": "INTRO"
},
{
"raw": "The Secret",
"track": null,
"bpm": 80,
"transition": "11.3->3.12",
"section": "LA DRILL BEBE"
},
{
"raw": "Jeudi Drill",
"track": "live/collab/raph/jeudrill.tidal",
"bpm": 70,
"transition": "3..10->10..3",
"section": "LA DRILL BEBE"
},
{
"raw": "1er Septembre Pour Elle",
"track": null,
"bpm": 60,
"transition": "9.11.->5",
"section": "LE SOMMET"
},
{
"raw": "Sunny Side Up",
"track": "live/midi/nova/lounge/sunny_side_up.tidal",
"bpm": 120,
"transition": "4.5->5..11...",
"section": "LE SOMMET"
},
{
"raw": "Chere Mireille",
"track": null,
"bpm": 120,
"transition": "11+6..4",
"section": "LE SOMMET"
},
{
"raw": "So G00D",
"track": null,
"bpm": 140,
"transition": "3.4->11...",
"section": "LE SOMMET"
},
{
"raw": "Nuit d'Orage",
"track": "live/midi/nova/techno/techno_orage.tidal",
"bpm": 104,
"transition": "11.3.4->",
"section": "LE SOMMET"
},
{
"raw": "Something About Drums",
"track": "live/midi/nova/dnb/something_about_drums.tidal",
"bpm": 160,
"transition": "10.5..9->5.9",
"section": "LE SOMMET"
},
{
"raw": "Ton Numero",
"track": "live/midi/nova/breaks/ton_numero.tidal",
"bpm": 99,
"transition": "RTFM",
"section": "REDESCENTE"
},
{
"raw": "Finale",
"track": null,
"bpm": 138,
"transition": null,
"section": "REDESCENTE"
},
{
"raw": "JEROME",
"track": null,
"bpm": null,
"transition": null,
"section": "REDESCENTE"
},
{
"raw": "Cafes du plus chaud au plus froid",
"track": null,
"bpm": null,
"transition": null,
"section": "REDESCENTE"
},
{
"raw": "El Mundo Interior",
"track": null,
"bpm": null,
"transition": null,
"section": "INTRO LATINO"
},
{
"raw": "Fabuleux",
"track": "live/midi/nova/lounge/fabuleux.tidal",
"bpm": null,
"transition": null,
"section": "INTRO LATINO"
},
{
"raw": "Contre Visite",
"track": "live/midi/nova/ambient/contre_visite.tidal",
"bpm": null,
"transition": null,
"section": "INTRO LATINO"
},
{
"raw": "Jeudi Drill",
"track": "live/collab/raph/jeudrill.tidal",
"bpm": null,
"transition": null,
"section": "INTRO LATINO"
},
{
"raw": "Ouais je Funk",
"track": null,
"bpm": null,
"transition": null,
"section": "BASS MUSIC BROTHERS"
},
{
"raw": "WAP",
"track": "live/midi/nova/dnb/wap.tidal",
"bpm": null,
"transition": null,
"section": "BASS MUSIC BROTHERS"
},
{
"raw": "Sunny Side Up",
"track": "live/midi/nova/lounge/sunny_side_up.tidal",
"bpm": null,
"transition": null,
"section": "BASS MUSIC BROTHERS"
},
{
"raw": "Sept1",
"track": "live/collab/baba/sept1.tidal",
"bpm": null,
"transition": null,
"section": "BASS MUSIC BROTHERS"
},
{
"raw": "Finale",
"track": null,
"bpm": null,
"transition": null,
"section": "BASS MUSIC BROTHERS"
},
{
"raw": "Contre Visite",
"track": "live/midi/nova/ambient/contre_visite.tidal",
"bpm": null,
"transition": null,
"section": "NON-ANNIVERSAIRE"
},
{
"raw": "Orage",
"track": "live/midi/nova/techno/techno_orage.tidal",
"bpm": null,
"transition": null,
"section": "NON-ANNIVERSAIRE"
},
{
"raw": "Ouais je Funk",
"track": null,
"bpm": null,
"transition": null,
"section": "NON-ANNIVERSAIRE"
},
{
"raw": "WAP",
"track": "live/midi/nova/dnb/wap.tidal",
"bpm": null,
"transition": null,
"section": "NON-ANNIVERSAIRE"
},
{
"raw": "WET HARD PUSSY",
"track": null,
"bpm": null,
"transition": null,
"section": "NON-ANNIVERSAIRE"
},
{
"raw": "Nouveau PUNK",
"track": "live/collab/raph/nouveau_punk.tidal",
"bpm": null,
"transition": null,
"section": "NON-ANNIVERSAIRE"
},
{
"raw": "PUNKACHIEN",
"track": "live/collab/raph/punkachien.tidal",
"bpm": null,
"transition": null,
"section": "NON-ANNIVERSAIRE"
},
{
"raw": "Ghosts in the Toilets",
"track": "live/collab/ccc/ghosts_in_the_toilets.tidal",
"bpm": null,
"transition": null,
"section": "NON-ANNIVERSAIRE"
},
{
"raw": "Sept1",
"track": "live/collab/baba/sept1.tidal",
"bpm": null,
"transition": null,
"section": "NON-ANNIVERSAIRE"
},
{
"raw": "JeuDrill",
"track": "live/collab/raph/jeudrill.tidal",
"bpm": null,
"transition": null,
"section": "INTRO FEERIE DU VOYAGE"
},
{
"raw": "Sunny Side Up",
"track": "live/midi/nova/lounge/sunny_side_up.tidal",
"bpm": null,
"transition": null,
"section": "INTRO FEERIE DU VOYAGE"
},
{
"raw": "Savoir Voyager",
"track": null,
"bpm": null,
"transition": null,
"section": "INTRO FEERIE DU VOYAGE"
},
{
"raw": "Menthe Givrée",
"track": null,
"bpm": null,
"transition": null,
"section": "INTRO FEERIE DU VOYAGE"
},
{
"raw": "Ouais je funk",
"track": null,
"bpm": null,
"transition": null,
"section": "COEUR FEERIE NOCTURNE"
},
{
"raw": "WAP",
"track": "live/midi/nova/dnb/wap.tidal",
"bpm": null,
"transition": null,
"section": "COEUR FEERIE NOCTURNE"
},
{
"raw": "Long Way",
"track": "live/collab/raph/long_way.tidal",
"bpm": null,
"transition": null,
"section": "COEUR FEERIE NOCTURNE"
},
{
"raw": "Esperluette",
"track": "live/collab/raph/esperluette.tidal",
"bpm": null,
"transition": null,
"section": "COEUR FEERIE NOCTURNE"
},
{
"raw": "Piment Bresilien",
"track": "live/collab/raph/piment_bresilien.tidal",
"bpm": null,
"transition": null,
"section": "COEUR FEERIE NOCTURNE"
},
{ {
"raw": "Biscuit Acide", "raw": "Contre Visite",
"track": "live/collab/raph/biscuit_acide.tidal", "track": "live/midi/nova/ambient/contre_visite.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "COEUR FEERIE NOCTURNE" "section": "TRACKLIST"
}, },
{ {
"raw": "Des Efforts", "raw": "Bain Electrique",
"track": "live/collab/raph/des_efforts.tidal", "track": "live/midi/nova/breaks/bain_electrique.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "COEUR FEERIE NOCTURNE" "section": "TRACKLIST"
}, },
{ {
"raw": "AUXiliaire", "raw": "Salut Nu",
"track": null, "track": "live/midi/nova/nujazz/salut_nu.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "COEUR FEERIE NOCTURNE" "section": "TRACKLIST"
}, },
{ {
"raw": "Quand on Decolle", "raw": "Cafe Tiede",
"track": "live/midi/nova/ambient/quand_on_decolle.tidal", "track": "live/midi/nova/nujazz/cafe_tiede.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": "TRACKLIST"
}, },
{ {
"raw": "Fabuleux", "raw": "Force Motrice",
"track": "live/midi/nova/lounge/fabuleux.tidal", "track": "live/midi/nova/dnb/force_motrice.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": "TRACKLIST"
}, },
{ {
"raw": "Paris", "raw": "Cafe Glace",
"track": "live/midi/nova/breaks/madeleine_de_paris.tidal", "track": "live/midi/nova/nujazz/cafe_glace.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": "TRACKLIST"
}, },
{ {
"raw": "Liquid Finale", "raw": "CCC0",
"track": null, "track": null,
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": "TRACKLIST"
}, },
{ {
"raw": "Sunshine", "raw": "ACIDULE",
"track": null, "track": "live/collab/raph/acidule.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": "TRACKLIST"
}, },
{ {
"raw": "WAP", "raw": "Something about Drums",
"track": "live/midi/nova/dnb/wap.tidal", "track": "live/midi/nova/dnb/something_about_drums.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": "TRACKLIST"
}, },
{ {
"raw": "The Secret", "raw": "Alerte Verte",
"track": null, "track": "live/midi/nova/dnb/alerte_verte.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": "TRACKLIST"
}, },
{ {
"raw": "Bain Electrique", "raw": "Permanence",
"track": "live/midi/nova/breaks/bain_electrique.tidal", "track": "live/collab/raph/permanence.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": "TRACKLIST"
}, },
{ {
"raw": "La Fin de l'insouciance", "raw": "L'or Bleu",
"track": "live/midi/nova/beatober/oct_16_haunted_house_insouciance.tidal", "track": "live/collab/mousquetaires/blue_gold.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": "TRACKLIST"
}
]
}, },
"2024/38c3-toilet": {
"slug": "2024/38c3-toilet",
"confirm": false,
"header": "#### Day 3 - Hardcore in the Toilet Club",
"anchor_line": 1242,
"n_tracks": 4,
"n_resolved": 3,
"suspect_bleed": false,
"tracks": [
{ {
"raw": "Piment Bresilien", "raw": "GHOSTS IN THE TOILETS",
"track": "live/collab/raph/piment_bresilien.tidal", "track": "live/collab/ccc/ghosts_in_the_toilets.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": null
}, },
{ {
"raw": "PERFECT", "raw": "NOUVEAU PUNK",
"track": null, "track": "live/collab/raph/nouveau_punk.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": null
}, },
{ {
"raw": "L'or Bleu", "raw": "PITBULL PUNK",
"track": "live/collab/mousquetaires/blue_gold.tidal", "track": null,
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": null
}, },
{ {
"raw": "Sunny Side Up", "raw": "ACIDULE",
"track": "live/midi/nova/lounge/sunny_side_up.tidal", "track": "live/collab/raph/acidule.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "2025 11 SovieTeuf" "section": null
}
]
}, },
"2025/ensad": {
"slug": "2025/ensad",
"confirm": false,
"header": "# Set @ENSAD 2025",
"anchor_line": 1441,
"n_tracks": 9,
"n_resolved": 8,
"suspect_bleed": false,
"tracks": [
{ {
"raw": "L'été à MauerPark", "raw": "Quand on décolle",
"track": "live/midi/nova/techno/ete_a_mauerpark.tidal", "track": "live/midi/nova/ambient/quand_on_decolle.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": "0 - / 11",
"section": "2025 11 SovieTeuf" "section": null
}, },
{ {
"raw": "Sept", "raw": "Parce qu'Elle est là",
"track": null, "track": null,
"bpm": null, "bpm": null,
"transition": "1", "transition": "7",
"section": "2025 11 SovieTeuf" "section": null
}, },
{ {
"raw": "Quand on decolle", "raw": "Ere de jeu",
"track": "live/midi/nova/ambient/quand_on_decolle.tidal", "track": "live/midi/nova/techno/ere_de_jeu.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": "123- 9",
"section": "NOUVEAU Novembre set" "section": null
}, },
{ {
"raw": "Liquid Finale", "raw": "l'Été à Mauerpark",
"track": null, "track": "live/midi/nova/techno/ete_a_mauerpark.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": "9",
"section": "NOUVEAU Novembre set" "section": null
}, },
{ {
"raw": "Sept1", "raw": "Sept1",
"track": "live/collab/baba/sept1.tidal", "track": "live/collab/baba/sept1.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": "11",
"section": "NOUVEAU Novembre set" "section": null
}, },
{ {
"raw": "I'M PERFECT", "raw": "Sunny Side Up",
"track": null, "track": "live/midi/nova/lounge/sunny_side_up.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": "11 /",
"section": "NOUVEAU Novembre set" "section": null
}, },
{ {
"raw": "SoGood", "raw": "L'or Bleu",
"track": "live/collab/nass/sogood.tidal", "track": "live/collab/mousquetaires/blue_gold.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": "5",
"section": "NOUVEAU Novembre set" "section": null
}, },
{ {
"raw": "Perfect Party", "raw": "Cafe Tiede",
"track": null, "track": "live/midi/nova/nujazz/cafe_tiede.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": "5",
"section": "Day 1 - Secret Toilet Rave" "section": null
}, },
{ {
"raw": "WAP", "raw": "Lady Perplexity",
"track": "live/midi/nova/dnb/wap.tidal", "track": "live/midi/nova/breaks/lady_perplexity.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "Day 1 - Secret Toilet Rave" "section": "- Atelier de Force Motrice - 57"
}
]
}, },
"2025/opal-festival-2025": {
"slug": "2025/opal-festival-2025",
"confirm": false,
"header": "# OPAL 2025",
"anchor_line": 1632,
"n_tracks": 17,
"n_resolved": 11,
"suspect_bleed": false,
"tracks": [
{ {
"raw": "Piment Bresilien", "raw": "Drifting soul",
"track": "live/collab/raph/piment_bresilien.tidal", "track": "live/collab/jane/drifting_soul.tidal",
"bpm": null, "bpm": 80,
"transition": null, "transition": "10+5->4+11",
"section": "Day 1 - Secret Toilet Rave" "section": "INTRO"
}, },
{ {
"raw": "JeuDrill", "raw": "Lendemain Divin",
"track": "live/collab/raph/jeudrill.tidal", "track": "live/midi/nova/lofi/lendemain_divin.tidal",
"bpm": null, "bpm": 95,
"transition": null, "transition": "4,5,6->6",
"section": "Day 1 - Secret Toilet Rave" "section": "INTRO"
}, },
{ {
"raw": "L'or Bleu", "raw": "Quand on Décolle",
"track": "live/collab/mousquetaires/blue_gold.tidal", "track": "live/midi/nova/ambient/quand_on_decolle.tidal",
"bpm": null, "bpm": 120,
"transition": null, "transition": "11+12->11",
"section": "Day 1 - Secret Toilet Rave" "section": "INTRO"
}, },
{ {
"raw": "Sept1", "raw": "The Secret",
"track": "live/collab/baba/sept1.tidal", "track": null,
"bpm": null, "bpm": 80,
"transition": null, "transition": "11.3->3.12",
"section": "Day 1 - Secret Toilet Rave" "section": "LA DRILL BEBE"
},
{
"raw": "Jeudi Drill",
"track": "live/collab/raph/jeudrill.tidal",
"bpm": 70,
"transition": "3..10->10..3",
"section": "LA DRILL BEBE"
},
{
"raw": "1er Septembre Pour Elle",
"track": null,
"bpm": 60,
"transition": "9.11.->5",
"section": "LE SOMMET"
}, },
{ {
"raw": "Sunny Side Up", "raw": "Sunny Side Up",
"track": "live/midi/nova/lounge/sunny_side_up.tidal", "track": "live/midi/nova/lounge/sunny_side_up.tidal",
"bpm": null, "bpm": 120,
"transition": null, "transition": "4.5->5..11...",
"section": "Day 1 - Secret Toilet Rave" "section": "LE SOMMET"
}, },
{ {
"raw": "My Sunshine", "raw": "Chere Mireille",
"track": null, "track": null,
"bpm": null, "bpm": 120,
"transition": null, "transition": "11+6..4",
"section": "Day 1 - Secret Toilet Rave" "section": "LE SOMMET"
}, },
{ {
"raw": "L'été à MauerPark", "raw": "So G00D",
"track": "live/midi/nova/techno/ete_a_mauerpark.tidal", "track": "live/collab/nass/sogood.tidal",
"bpm": null, "bpm": 140,
"transition": "3.4->11...",
"section": "LE SOMMET"
},
{
"raw": "Nuit d'Orage",
"track": "live/midi/nova/techno/techno_orage.tidal",
"bpm": 104,
"transition": "11.3.4->",
"section": "LE SOMMET"
},
{
"raw": "Something About Drums",
"track": "live/midi/nova/dnb/something_about_drums.tidal",
"bpm": 160,
"transition": "10.5..9->5.9",
"section": "LE SOMMET"
},
{
"raw": "Ton Numero",
"track": "live/midi/nova/breaks/ton_numero.tidal",
"bpm": 99,
"transition": "RTFM",
"section": "REDESCENTE"
},
{
"raw": "Lady Perplexity",
"track": "live/midi/nova/breaks/lady_perplexity.tidal",
"bpm": 138,
"transition": null, "transition": null,
"section": "Day 1 - Secret Toilet Rave" "section": "REDESCENTE"
}, },
{ {
"raw": "TECHNOLIGARCHIE", "raw": "JEROME",
"track": null, "track": null,
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "Day 1 - Secret Toilet Rave" "section": "REDESCENTE"
}, },
{ {
"raw": "My Sunshine", "raw": "Contre Visite",
"track": null, "track": "live/midi/nova/ambient/contre_visite.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "Day 1 - Secret Toilet Rave" "section": "REDESCENTE"
}, },
{ {
"raw": "Suns of Gold", "raw": "Oct29 Love First",
"track": null, "track": null,
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "Day 1 - Secret Toilet Rave" "section": "REDESCENTE"
}, },
{ {
"raw": "END", "raw": "Cafes du plus chaud au plus froid",
"track": null, "track": null,
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "Day 1 - Secret Toilet Rave" "section": "REDESCENTE"
} }
] ]
}, },
...@@ -1481,7 +550,7 @@ ...@@ -1481,7 +550,7 @@
"header": "# CCC 39c3 ALGORAVE <3", "header": "# CCC 39c3 ALGORAVE <3",
"anchor_line": 1786, "anchor_line": 1786,
"n_tracks": 14, "n_tracks": 14,
"n_resolved": 12, "n_resolved": 13,
"suspect_bleed": false, "suspect_bleed": false,
"tracks": [ "tracks": [
{ {
...@@ -1541,8 +610,8 @@ ...@@ -1541,8 +610,8 @@
"section": "TECHNO HIGH" "section": "TECHNO HIGH"
}, },
{ {
"raw": "Paris you want", "raw": "Something about Drums",
"track": null, "track": "live/midi/nova/dnb/something_about_drums.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "DNBish" "section": "DNBish"
...@@ -1666,7 +735,7 @@ ...@@ -1666,7 +735,7 @@
"header": "## Algolia FDLM2024", "header": "## Algolia FDLM2024",
"anchor_line": 988, "anchor_line": 988,
"n_tracks": 26, "n_tracks": 26,
"n_resolved": 25, "n_resolved": 26,
"suspect_bleed": true, "suspect_bleed": true,
"tracks": [ "tracks": [
{ {
...@@ -1845,8 +914,8 @@ ...@@ -1845,8 +914,8 @@
"section": "Sur le Toit 3" "section": "Sur le Toit 3"
}, },
{ {
"raw": "Encore", "raw": "Blue Gold",
"track": null, "track": "live/collab/ccc/ccc0.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "Sur le Toit 3" "section": "Sur le Toit 3"
...@@ -1869,7 +938,7 @@ ...@@ -1869,7 +938,7 @@
"header": "## SURPRISE IT'S A DANCEFLOOR", "header": "## SURPRISE IT'S A DANCEFLOOR",
"anchor_line": 1831, "anchor_line": 1831,
"n_tracks": 11, "n_tracks": 11,
"n_resolved": 7, "n_resolved": 8,
"suspect_bleed": false, "suspect_bleed": false,
"tracks": [ "tracks": [
{ {
...@@ -1880,8 +949,8 @@ ...@@ -1880,8 +949,8 @@
"section": null "section": null
}, },
{ {
"raw": "Paris you want", "raw": "Something about Drums",
"track": null, "track": "live/midi/nova/dnb/something_about_drums.tidal",
"bpm": null, "bpm": null,
"transition": null, "transition": null,
"section": "DNBish" "section": "DNBish"
......
...@@ -30,22 +30,26 @@ AS_OF = "2026-06-06" ...@@ -30,22 +30,26 @@ AS_OF = "2026-06-06"
# ── Authored gig anchors: (1-based line of the header in backlog.md) → site slug ── # ── Authored gig anchors: (1-based line of the header in backlog.md) → site slug ──
# `confirm:`-prefixed slugs are NOT yet trusted (ambiguous header / needs PLN's ear); # `confirm:`-prefixed slugs are NOT yet trusted (ambiguous header / needs PLN's ear);
# they are parsed and reported but withheld from the emitted artifact. # they are parsed and reported but withheld from the emitted artifact.
# value = slug OR (slug, end_line) to bound a block that would otherwise bleed
# into the next densely-packed setlist (the backlog has no blank-gap between them).
ANCHORS = { ANCHORS = {
1441: "2025/ensad", # "# Set @ENSAD 2025" 1441: "2025/ensad", # "# Set @ENSAD 2025"
1816: "2026/le-vortex", # "# VORTEX26" 1816: "2026/le-vortex", # "# VORTEX26"
1031: "2024/opal-festival-2024", # "## Opal <3🦉" / OPAL 2024 1031: "2024/opal-festival-2024", # "## Opal <3🦉" / OPAL 2024
1632: "2025/opal-festival-2025", # "# OPAL 2025" 1632: ("2025/opal-festival-2025", 1667), # "# OPAL 2025" (bleeds into Latin Heritage)
710: "2023/mephisteuf", # "## Live @MephisTeuf" 710: ("2023/mephisteuf", 735), # "## Live @MephisTeuf" (commented block = cut)
1194: "2024/38c3-house-of-tea", # "#### Day 2 - HOUSE OF Tea" (under 38C3) 1194: "2024/38c3-house-of-tea", # "#### Day 2 - HOUSE OF Tea" (under 38C3)
1242: "2024/38c3-toilet", # "#### Day 3 - Hardcore in the Toilet Club" 1242: ("2024/38c3-toilet", 1253), # cross-check only (already has tracks.json)
1786: "2025/39c3-house-of-tea", # "# CCC 39c3 ALGORAVE ... Pour Un Thé Dansant" 1786: "2025/39c3-house-of-tea", # "# CCC 39c3 ALGORAVE ... Pour Un Thé Dansant"
1169: "2024/toplap-solstice-2024", # "### TopLap Solstice Stream 2024" 1169: "2024/toplap-solstice-2024", # "### TopLap Solstice Stream 2024"
988: "confirm:2024/algolia-fdlm", # "## Algolia FDLM2024" — already has tracks.json 988: "confirm:2024/algolia-fdlm", # "## Algolia FDLM2024" — already has tracks.json
1550: "confirm:2025/algorave-lyon", # "GZ 2025 LYON ALGORAVE" then "# LABENNE LIVE" (?) 1550: "confirm:2025/algorave-lyon", # "GZ 2025 LYON ALGORAVE" then "# LABENNE LIVE" (?)
1831: "confirm:2026/ete-surprise", # "## SURPRISE IT'S A DANCEFLOOR" — slug guess 1831: "confirm:2026/ete-surprise", # "## SURPRISE IT'S A DANCEFLOOR" — slug guess
} }
# Gigs still unanchored (no clear backlog block found): 2022/algolia-fdlm-2022, # Still unanchored (gaps for #66, need PLN's ear / SC confirmation): 2022/algolia-fdlm-2022,
# 2024/38c3-chaos-music-club, 2025/39c3-toilet-rave, 2025/toplap-fromscratch-2025. # 2024/38c3-chaos-music-club, 2025/39c3-toilet-rave, 2025/toplap-fromscratch-2025. The
# backlog also holds many UNMAPPED setlists (Latin Heritage, NON-ANNIVERSAIRE, MICROLIVE,
# SovieTeuf, CCC Day-1, RAISE afterparty, Garibaldi…) whose slugs need confirming.
# Lines that are decoration / structure, never tracks. # Lines that are decoration / structure, never tracks.
_ASCII_ART = re.compile(r"[⠀-⣿▓▒░█▀▄■◆◢◣◤◥╔╗╚╝║═]") _ASCII_ART = re.compile(r"[⠀-⣿▓▒░█▀▄■◆◢◣◤◥╔╗╚╝║═]")
...@@ -65,6 +69,15 @@ def norm_name(s: str) -> str: ...@@ -65,6 +69,15 @@ def norm_name(s: str) -> str:
return re.sub(r"[^a-z0-9]+", "", deaccent(s).lower()) return re.sub(r"[^a-z0-9]+", "", deaccent(s).lower())
_LEET = str.maketrans({"0": "o", "1": "i", "3": "e", "4": "a", "5": "s", "7": "t"})
def leet_fold(s: str) -> str:
"""Fold ParVagues' leetspeak (B00K, T01l3ts, G00D, L1VEC0DE) → letters. Used only
as a FALLBACK so genuine digits (sept1, 165) still match straight first."""
return s.translate(_LEET)
def build_name_index(): def build_name_index():
"""norm(name) → .tidal path, from the catalog's existing alias set (DRY).""" """norm(name) → .tidal path, from the catalog's existing alias set (DRY)."""
cv = json.load(open(CATALOG_VIEW)) cv = json.load(open(CATALOG_VIEW))
...@@ -102,7 +115,12 @@ def clean_track_line(raw: str): ...@@ -102,7 +115,12 @@ def clean_track_line(raw: str):
body = re.sub(r"\([^)]*\)", "", body) # (Chloe cover) etc body = re.sub(r"\([^)]*\)", "", body) # (Chloe cover) etc
body = re.sub(r"\bfeat\b.*$", "", body, flags=re.I) body = re.sub(r"\bfeat\b.*$", "", body, flags=re.I)
body = body.replace("*", "").replace("_", "").replace("`", "") body = body.replace("*", "").replace("_", "").replace("`", "")
body = re.sub(r":\s*.*$", "", body) # "Café tiède: note" → drop gloss after colon # strip a leading set-position label ("Intro: X", "Finale: X", "Sunset X")
body = _LABEL.sub("", body)
# remaining colon: "Label: Name" → keep Name; "Name: gloss" → keep Name
if ":" in body:
left, right = (p.strip() for p in body.split(":", 1))
body = right if right and (right[:1].isupper() and len(right.split()) <= 5) else left
# remove emoji / symbol chars, keep letters/digits/space/'-/& # remove emoji / symbol chars, keep letters/digits/space/'-/&
body = "".join(ch for ch in body body = "".join(ch for ch in body
if ch.isalnum() or ch in " '-/&." or unicodedata.category(ch).startswith("L")) if ch.isalnum() or ch in " '-/&." or unicodedata.category(ch).startswith("L"))
...@@ -118,14 +136,21 @@ def clean_track_line(raw: str): ...@@ -118,14 +136,21 @@ def clean_track_line(raw: str):
return body, bpm, transition, True return body, bpm, transition, True
def block_span(lines, start_idx): def _slug_end(val):
"""ANCHORS value → (slug, end_line|None)."""
return val if isinstance(val, tuple) else (val, None)
def block_span(lines, start_idx, end_line=None):
"""Collect a gig block. Headers in backlog.md are DECORATIVE (stylized banners, """Collect a gig block. Headers in backlog.md are DECORATIVE (stylized banners,
repeated `# PARVAGUES`, sub-labels) not hierarchical, so we don't scope by level. repeated `# PARVAGUES`, sub-labels) not hierarchical, so we don't scope by level.
Instead: from the anchor, walk to the next ANCHOR, but terminate early once the From the anchor, walk to the next ANCHOR (or an explicit end_line), terminating
setlist proper ends — a run of ≥3 blank lines after we've collected ≥2 items early once the setlist proper ends — a run of ≥3 blank lines after we've collected
(journal prose resumes). Decorative headers are kept as section context, not breaks.""" ≥2 items (journal prose resumes). Decorative headers are kept as section context."""
anchor_lines = sorted(k - 1 for k in ANCHORS) anchor_lines = sorted(k - 1 for k in ANCHORS)
hard_end = next((a for a in anchor_lines if a > start_idx), len(lines)) hard_end = next((a for a in anchor_lines if a > start_idx), len(lines))
if end_line is not None:
hard_end = min(hard_end, end_line - 1)
out, items, blanks = [], 0, 0 out, items, blanks = [], 0, 0
for raw in lines[start_idx + 1:hard_end]: for raw in lines[start_idx + 1:hard_end]:
if not raw.strip(): if not raw.strip():
...@@ -142,18 +167,23 @@ def block_span(lines, start_idx): ...@@ -142,18 +167,23 @@ def block_span(lines, start_idx):
# transition tails appended to a track name: "-> 5+7", " 0 - / 11", "- 9" # transition tails appended to a track name: "-> 5+7", " 0 - / 11", "- 9"
_TRANS_TAIL = re.compile(r"\s*(->|[-–])\s*[\d\s./+,]*$|\s+[\d][\d\s./+,>-]*$") _TRANS_TAIL = re.compile(r"\s*(->|[-–])\s*[\d\s./+,]*$|\s+[\d][\d\s./+,>-]*$")
# leading set-position label to strip ("Intro: ", "Finale ", "Sunset — ", "Day 1 ")
_LABEL = re.compile(
r"^\s*(intro|outro|final[e]?|bonus|rappel|sunset|sunrise|darkness|pause|"
r"d[eé]but|fin|end|day\s*\d+)\b\s*[:.\-–]?\s*", re.I)
def parse(lines, name_idx): def parse(lines, name_idx):
gigs = {} gigs = {}
for ln1, slug in sorted(ANCHORS.items()): for ln1, val in sorted(ANCHORS.items()):
slug, end_line = _slug_end(val)
confirm = slug.startswith("confirm:") confirm = slug.startswith("confirm:")
real_slug = slug.split(":", 1)[1] if confirm else slug real_slug = slug.split(":", 1)[1] if confirm else slug
i = ln1 - 1 i = ln1 - 1
header = lines[i].strip() header = lines[i].strip()
section = None section = None
tracks, unmatched = [], [] tracks, unmatched = [], []
for raw in block_span(lines, i): for raw in block_span(lines, i, end_line):
hm = re.match(r"\s*#{1,6}\s+(.+)$", raw) hm = re.match(r"\s*#{1,6}\s+(.+)$", raw)
if hm: # subsection label if hm: # subsection label
section = re.sub(r"[^\w\s'-]", "", deaccent(hm.group(1))).strip() or None section = re.sub(r"[^\w\s'-]", "", deaccent(hm.group(1))).strip() or None
...@@ -163,7 +193,8 @@ def parse(lines, name_idx): ...@@ -163,7 +193,8 @@ def parse(lines, name_idx):
continue continue
if _SECTION_HINT.match(name) and norm_name(name) not in name_idx: if _SECTION_HINT.match(name) and norm_name(name) not in name_idx:
continue continue
track = name_idx.get(norm_name(name)) nm = norm_name(name)
track = name_idx.get(nm) or name_idx.get(leet_fold(nm))
entry = {"raw": name, "track": track, "bpm": bpm, "transition": transition, "section": section} entry = {"raw": name, "track": track, "bpm": bpm, "transition": transition, "section": section}
(tracks if track else unmatched).append(entry) (tracks if track else unmatched).append(entry)
if not track: if not track:
......
"""Backlog setlist recovery — mechanical guards (parsers-over-copy).
The parser cleans noisy backlog lines and resolves to canonical .tidal via the
catalog alias index. Test the load-bearing bits (leet fold, label strip, transition
tails) on synthetic lines, plus a coverage regression guard on the real backlog."""
import backlog_setlists as B
def test_leet_fold():
assert B.leet_fold(B.norm_name("Burn this B00K")) == "burnthisbook"
assert B.leet_fold(B.norm_name("Ghosts in the T01l3ts")) == "ghostsinthetoilets"
assert B.leet_fold(B.norm_name("So G00D")) == "sogood"
def test_clean_strips_labels_and_keeps_track():
# "Intro: X" / "Finale: X" → keep X, not the label
name, *_ , ok = B.clean_track_line("- Intro _🚪 Contre-Visite 👁️_")
assert ok and name == "Contre-Visite"
name, *_, ok = B.clean_track_line("- Finale: Lady Perplexity [138bpm]")
assert ok and name == "Lady Perplexity"
def test_clean_drops_gloss_after_colon():
# "Name: gloss" (lowercase gloss) → keep Name
name, *_, ok = B.clean_track_line("- Café tiède: au plus chaud")
assert ok and name.lower().startswith("café tiède")
def test_clean_captures_bpm_and_transition():
name, bpm, trans, ok = B.clean_track_line("- Quand on Décolle [120] {11+12->11}")
assert ok and bpm == 120 and trans == "11+12->11"
def test_clean_skips_ascii_and_comments():
assert B.clean_track_line("⣿-----⣿")[-1] is False
assert B.clean_track_line("<!-- - It's about Time -->")[-1] is False
def test_real_backlog_coverage_does_not_regress():
"""Guard: the cleanly-recovered gigs keep resolving. If the backlog or parser
changes and these drop, that's a regression to look at (not a silent loss)."""
out = B.build()
by = {**out["gigs"], **out["pending"]}
assert out["n_gigs"] >= 8
# opal-2024 is a clean, fully-resolvable block — it must stay at parity
assert by["2024/opal-festival-2024"]["n_resolved"] >= 13
# no recovered gig should be empty
for slug, g in out["gigs"].items():
assert g["n_tracks"] >= 1, slug
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment