feat(lint): pvlint — the bugs that silenced this rig, encoded as rules
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.
Showing
tools/pvlint/__init__.py
0 → 100644
tools/pvlint/__main__.py
0 → 100644
tools/pvlint/core.py
0 → 100644
tools/pvlint/rules.py
0 → 100644
This diff is collapsed.
Click to expand it.
tools/pvlint/tests/__init__.py
0 → 100644
tools/pvlint/tests/test_rules.py
0 → 100644
Please
register
or
sign in
to comment