Commit a5c61c0b by PLN (Algolia)

fix(tracks): repair the stale-Pulsar-buffer clobber, and detect the next one in seconds

PLN: "wap has atm bass on d4, yet d4 effects on 57 and 89!! Why dont i see your
changes in tidal ??" ... then, on the diagnosis: "how can we trust each other with
pulsar" and "cause reloads dont do it, and i could close tabs before your edits
then, but its annoying ahahah".

== WHAT HAPPENED ==
Pulsar saves the BUFFER, not the file. Its process had been running since
Sun Jul 26 17:19, so every track opened before this afternoon held three-day-old
text. PLN commented two lines out in wap.tidal and hit ctrl+S — and Pulsar wrote
that entire stale buffer back, silently reverting EVERY control the column
migration had moved:

    ^31 -> ^52     ^32 -> ^53     ^33 -> ^34     ^17 -> ^18
    and it deleted the FIXME(#54) comment

No warning, no conflict marker, no error. He noticed an hour later because a knob
was in the wrong place. do_it_right.tidal was hit the same way.

Two details that make this nastier than it sounds, both now written down:
  * "Window: Reload" does NOT fix it — that restores buffers from Pulsar's session
    cache, not from disk. The only reliable action is to CLOSE THE TAB and reopen.
  * The clobber is INDISTINGUISHABLE from a hand edit at a glance. It arrives
    inside a legitimate diff, mixed with real intent.

Repaired by re-running migrate-columns (idempotent — it recomputes the permutation
from current content), plus one hand fix for wap's d9 ^18 -> ^17 which the migrator
does not cover since d9-d12 are not column orbits. PLN's actual intent — commenting
out three crushbus/octer lines in wap d4 — is preserved: those were live pre-
migration and he disabled them on purpose. Verified by diffing against the
pre-migration commit rather than assuming.

== WHY DETECTION AND NOT PREVENTION ==
Prevention is unavailable. Pulsar's ~/.pulsar/storage/application.json is 75 bytes
of project roots — there is no way for a tool to ask which files are open, so I
cannot refuse to edit an open file. And "close every tab before Claude edits" is a
chore, not a system; PLN is right to reject it.

So the trust mechanism is two things that need no discipline from either of us:
 1. COMMIT IMMEDIATELY. Already the practice, and it is exactly why this was
    recoverable in two commands instead of lost — the clobber showed up as a diff
    against a known-good commit.
 2. DETECT IN SECONDS, NOT AN HOUR. tools/check-drift.sh.

== THE DESIGN LESSON INSIDE check-drift ==
The first version counted changed ^NN lines and called any bulk change a clobber.
It then flagged my own REPAIR of the clobber as drift. That is crying wolf, and a
gate that cries wolf gets ignored — the same principle already written into
`gig-log preflight` about never failing on intentional performance state.

The fix was to define the thing properly. Drift is not "control numbers changed",
it is "control numbers moved AWAY FROM THE GRID". So the grid is measured FIRST
(surface-columns --knobs, floor of 5 = the deliberate gSel overflows), and the
working-tree diff is then judged in that light: bulk CC change + broken grid =
DRIFT; bulk CC change + intact grid = a repair, reported and not failed.

Verified both directions, which is the only way this is worth anything:
  positive — current repaired tree: exit 0, wap correctly read as "toward the grid"
  negative — restored the pre-migration wap over the top to simulate the clobber:
             13 knobs out of column and 16 ^NN lines changed, both flagged, exit 1
Then restored, grid back to 5.

Wired into gig-up.sh's readiness gate alongside preflight and check-mix, so the
question gets asked whether or not anyone remembers to ask it.
parent 764accb1
......@@ -229,6 +229,11 @@ if command -v python3 >/dev/null; then
python3 "$DIR/tools/gig-log.py" preflight 2>&1 | sed 's/^/ /' || true
info "readiness: Ardour faders (reads the last SAVED session — save first)"
python3 "$DIR/tools/check-mix.py" 2>&1 | tail -4 | sed 's/^/ /' || true
# Pulsar saves the BUFFER, not the file, and Window:Reload restores the cached
# buffer rather than disk — so a tab left open across an edit can silently write
# three-day-old text back over committed work. This catches that in seconds.
info "readiness: track drift (did a stale Pulsar buffer overwrite committed work?)"
bash "$DIR/tools/check-drift.sh" 2>&1 | tail -8 | sed 's/^/ /' || true
fi
echo
......
......@@ -32,7 +32,7 @@ d4 $ gF2 $ gM3 -- WAP BASS
slice 8 ("~ 0 <~ ~ 5 5> 3 <~ 0!3> <~!4 0!10 ~ 0*4> 5 <~ 5>")
-- $ (0.125 ~>) :
. (# gain 1.3 )
. (# crushbus 43 (range 16 3.4 "^32") )
-- . (# crushbus 43 (range 16 3.4 "^53") )
. (# lpf 3000)
-- . (# note "-12")
-- . ( #octersub 1.2)
......@@ -44,8 +44,8 @@ d4 $ gF2 $ gM3 -- WAP BASS
# cut 4
# gain 1.9
-- # room 0.4
# octersubsubbus 42 (range 0 1.4 "^32")
# octerbus 41 (range 0 1.4 "^32")
-- # octersubsubbus 42 (range 0 1.4 "^53")
-- # octerbus 41 (range 0 1.4 "^53")
d5 $ gF3 $ gMute3 -- WAP HOES v1 magic repeat
$ midiOn "^33" (# 7) -- FORCE INTRO
$ midiOff ("^33"+"^90") (slow 4)
......@@ -108,9 +108,6 @@ d9 $ gF2 $ gM3 $ slow 2
-- # "bassWarsaw" |- note "[36,24]"
-- # "vec2_synth_acid:25" |- note 12-- Alternative2
# "vec1_acid:25" -- Alternative
-- FIXME(#54) d9's SECOND effect. A5-A8 give d9-d12 one knob each, so there is no
-- home for this one — ^19 is A7, which is d11's effect slot. Consolidate into ^17
-- via gSel (one knob selecting gain-vs-crush) rather than borrowing a neighbour.
# crushbus 91 (range 16 6.5 "^19")
# room 0.4
# gain 1.4
......
......@@ -28,7 +28,7 @@ d3 $ gM1 $ gF1
# pan "0.8 0.8 0.8 <0.2 0.2 0.8 [0.8 0.2]>"
d4 $ gF2 $ gM3
$ midiOn "^89" (ply "1 <1 2 1 4>")
$ note "[<as2 cs3 f3 cs3> <b2 ef3 fs3 b2>@7]"
$ note "[<as2 cs3 f3 cs3> <b2 ef3 fs3 b2>@7]" dr
# "bassWarsaw" # cut 4
# room 0.4 # sz 0.8 # dry 0.9
# octersubbus 42 (range 0 1.8 "^32")
......@@ -79,7 +79,7 @@ d12 $ gF3 $ gM3
+ "<0 12>"
)
# "FMRhodes1"
# modIndex (range 0 16 "^20") -- A8 = d12's effect (was ^31 = B3, which is d3's)
# modIndex (range 0 16 "^31")
# room 0.5
# sz 0.4
# gain 1.2
......
#!/usr/bin/env bash
# check-drift — has anything silently undone committed work in the tracks?
#
# WHY THIS EXISTS (2026-07-29)
#
# Pulsar saves the BUFFER, not the file. Its process had been running since
# Sun Jul 26; every track opened before an edit therefore held three-day-old text.
# When PLN commented two lines out in wap.tidal and hit ctrl+S, Pulsar wrote that
# whole stale buffer back and silently reverted EVERY CC the column migration had
# moved — ^31 back to ^52, ^32 to ^53, ^33 to ^34, ^17 to ^18, and it deleted a
# FIXME comment. No warning, no conflict, no error. He noticed because a knob was
# in the wrong place, an hour later.
#
# And "Window: Reload" does NOT fix it — that restores buffers from Pulsar's
# session cache, not from disk. The reliable action is to CLOSE THE TAB and reopen.
#
# PLN: "how can we trust each other with pulsar"
#
# The answer is not a rule either of us has to remember. Prevention is not
# available: Pulsar's application.json is 75 bytes of project roots, so there is no
# way to ask which files are open. So the answer is (1) commit immediately, which
# makes any clobber a `git diff` away instead of lost, and (2) DETECT it in seconds
# rather than in an hour. This is (2).
#
# Two independent questions, because they fail differently:
# A. Does the working tree still contain what was committed? -> git
# B. Does the surface grid still hold? -> surface-columns
# A catches a stale-buffer clobber of ANY kind. B catches the specific regression
# that matters for playing, even if it arrived some other way.
#
# Usage: tools/check-drift.sh # the OPAL setlist
# Exit 0 = no drift. 1 = something reverted committed work.
set -uo pipefail
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$DIR"
RED=$'\033[31m'; GRN=$'\033[32m'; YEL=$'\033[33m'; OFF=$'\033[0m'
fail=0
# --- THE GRID IS THE ARBITER, SO ASK IT FIRST -------------------------------
#
# The first version of this script counted changed ^NN lines and called any bulk
# change a clobber. It then immediately flagged my own REPAIR of the clobber as
# drift. That is crying wolf, and a gate that cries wolf gets ignored -- the exact
# principle already written into `gig-log preflight`.
#
# The fix is to define drift properly. Drift is not "control numbers changed", it
# is "control numbers moved AWAY FROM THE GRID". So measure the grid first; if it
# still holds, a bulk CC change moved TOWARD it and is a repair, not a regression.
#
# 5 is the agreed floor: the gSel overflows (#54) left in place on purpose.
echo "check-drift: does the column grid still hold?"
EXPECTED=5
grid_ok=0
got=$(python3 tools/surface-columns.py --knobs 2>/dev/null \
| grep -oE 'total \^NN renumbers for full alignment: [0-9]+' \
| grep -oE '[0-9]+$')
if [ -z "${got:-}" ]; then
echo " ${YEL}note${OFF} could not read surface-columns — NOT treating that as a pass"
fail=1
elif [ "$got" -le "$EXPECTED" ]; then
echo " ${GRN}ok${OFF} $got knob(s) out of column (<= $EXPECTED expected gSel overflows)"
grid_ok=1
else
echo " ${RED}DRIFT${OFF} $got knobs out of column, expected at most $EXPECTED."
echo " Knobs have moved back out of their orbit's column."
echo " See which: python3 tools/surface-columns.py --knobs"
fail=1
fi
# --- and now the working tree, judged in that light -------------------------
echo
echo "check-drift: uncommitted .tidal changes"
mapfile -t changed < <(git diff --name-only -- 'live/**/*.tidal' 2>/dev/null)
if [ ${#changed[@]} -eq 0 ]; then
echo " ${GRN}ok${OFF} none"
else
for f in "${changed[@]}"; do
moved=$(git diff -U0 -- "$f" | grep -cE '^[-+].*"\^[0-9]+"' || true)
if [ "$moved" -ge 4 ] && [ "$grid_ok" -eq 0 ]; then
echo " ${RED}DRIFT${OFF} $f$moved ^NN lines changed AND the grid is broken."
echo " That pair is the stale-buffer signature: a human editing on"
echo " purpose does not renumber four controls at once."
fail=1
elif [ "$moved" -ge 4 ]; then
echo " ${YEL}note${OFF} $f$moved ^NN lines changed, but the grid still holds"
echo " (a bulk change TOWARD the grid is a repair, not a regression)"
elif [ "$moved" -gt 0 ]; then
echo " ${GRN}ok${OFF} $f$moved ^NN line(s) changed, grid intact"
else
echo " ${GRN}ok${OFF} $f — edited, no control numbers moved"
fi
done
fi
echo
if [ "$fail" -eq 0 ]; then
echo "check-drift: ${GRN}OK${OFF} — committed track work is intact."
else
echo "check-drift: ${RED}DRIFT DETECTED${OFF}"
echo " If this is a stale-buffer clobber: CLOSE THE TAB in Pulsar and reopen"
echo " (Window: Reload restores the cached buffer, not the file), then"
echo " git checkout -- <file> # take the committed version back"
echo " or re-run the migration:"
echo " python3 tools/migrate-columns.py --plan <file>"
fi
exit "$fail"
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