Skip to content

  • Projects
  • Groups
  • Snippets
  • Help
  • This project
    • Loading...
  • Sign in / Register
T
Tidal
  • Overview
    • Overview
    • Details
    • Activity
    • Cycle Analytics
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Charts
  • Issues 0
    • Issues 0
    • List
    • Board
    • Labels
    • Milestones
  • Merge Requests 0
    • Merge Requests 0
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
    • Charts
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Charts
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • PLN
  • Tidal
  • Repository

Switch branch/tag
  • Tidal
  • tools
  • pvlint
  • core.py
Find file
BlameHistoryPermalink
  • PLN (Algolia)'s avatar
    feat(lint): pvlint — the bugs that silenced this rig, encoded as rules · 81eb4dc0
    Three evenings this week went to bugs that were VISIBLE IN THE TEXT and that
    no eye caught mid-set, because none of them produce an error message. They
    produce silence, on stage:
    
      * desire.tidal — `off 0.125 (|+ note 12 . (|* gain 0.6))`. `.` binds looser
        than application, so this composes a FUNCTION into a ValueMap. GHC refuses
        the whole block, and since a blank line is Tidal's block separator, ONE
        character silenced nine orbits while the file looked perfect on screen.
      * you_my_sunshine.tidal — a local `let gF3 = (# djfbus 3 (range 0.05 0.95
        "^51"))` shadowing the global helper we had already fixed. SuperDirt maps
        djf through linexp(0, 0.5, 20, 10000): bypass is 0.5, and 0.05 is a ~26 Hz
        low-pass. Four orbits (d5/d7/d9/d11) inaudible until a knob crossed centre.
      * the #55 mute-bomb — an untouched `^NN` yields NO events, so `range a b
        "^NN"` is `silence`, not a number.
    
    All three are static properties of the file, so they belong in a linter.
    
    Seven rules, each earned by a real failure: PV001 local djfbus shadow (with an
    autofix that deletes the line so the track inherits the corrected global),
    PV002 operator-section composition (autofix adds the missing parens), PV003
    double-applied global gain, PV004 shared cut group, PV005 duplicate orbit in
    one block, PV006 sample index past the end of its folder, PV007 orbit
    inventory (the input to the orphan-orbit transition check, `--setlist`).
    
    Three of my own rules were wrong on first contact with the corpus, and the
    corpus caught all three — which is the argument for running a linter against
    694 real files before trusting it:
    
      * PV002 was string-blind and called four mini-notation `.` separators
        compile-killers (`"k ~ ~ k . ~"` is grouping, not composition). 13 findings
        -> 0, all of them false.
      * PV003 claimed the whole 77-84 fader bank was "owned by Ardour" and raised
        1109 errors. BootTidal itself reads `^77` (midiGGlobal); reading a fader CC
        is the documented convention. Narrowed to the actual hazard — ^77 applied
        twice — and demoted to a warning.
      * PV005 flagged every re-declaration of an orbit, but keeping several
        evaluable versions per file is normal live practice. Scoped to one block:
        576 findings -> 32.
      * PV006 pooled all indices in an orbit against all folders and invented a
        finding on d8 (n=24 is org_jungle_breaks', not breaks165's).
    
    Also fixed the parser: ORBIT_RE demanded a same-line `$` and so dropped d5
    from you_my_sunshine's inventory WHILE THE TRACK WAS PLAYING IT — PLN writes
    `d5  -- comment` with the `$` on the continuation line, which Haskell's layout
    rule allows. A linter that under-reports is worse than none.
    
    Corpus after the corrections: 694 tracks, 316 errors (all PV001 shadows, in
    archive material), 281 warnings. First real run found a live one — d5 and d11
    of you_my_sunshine share cut group 5, so the voice and the chop truncate each
    other.
    
    33 unit tests, every negative case a real corpus line that an earlier rule
    version wrongly flagged.
    PLN (Algolia) authored Jul 28, 2026
    81eb4dc0
core.py 5.9 KB
EditWeb IDE
×

Replace core.py

Attach a file by drag & drop or click to upload


Cancel
A new branch will be created in your fork and a new merge request will be started.