Replace the handoff notes with a durable spec and ADRs

The handoff was written as a message to relay information; several
decisions lived only there. Split into permanent homes:

- docs/spec.md — scope, geometry model, pipeline order, detection,
  levels, editor, project file, markers, bundle format, noteman's
  changes, reference values
- ADR 0002 — raster only in release 1; SVG slices measured at 40x WebP
  naive, 2.6x with a bounding-box cull, deferred on risk not size
- ADR 0003 — lossless WebP with levels and 16-level alpha; every lossy
  option and alternative format measured larger for line art
- ADR 0004 — detection proposes, the human disposes; no unattended mode
- ADR 0005 — PyMuPDF for all PDF access, accepting AGPL
- ADR 0006 — systems are found by vertical brackets, not row-darkness
  gaps, which miscount every page of a 6-voice score

Also from testing against the hardest score in the repertoire: scanned
PDFs carry their scan as an embedded image and must be extracted at
native resolution rather than re-rendered at 600 DPI, and per-page
deskew is mandatory (skew varies -2.6 to +1.2 within one PDF).
This commit is contained in:
Esa Kataja
2026-07-28 22:05:09 +03:00
parent efc920fdc5
commit 46ae7e813a
8 changed files with 674 additions and 7 deletions
@@ -0,0 +1,55 @@
# Detection proposes, the human disposes — there is no unattended mode
Every automatic result the slicer produces — skew angle, cut positions, source
type, staff height, ink bounds — is a **suggestion the user confirms or modifies**
before it is committed. There is no batch mode, no headless "slice this folder",
and no code path that writes a bundle without a human having looked at it.
This is a constraint on the tool's shape, not a UI preference, which is why it
gets an ADR: it deletes an entire phase of the original plan and it will look
like a missing feature to anyone who finds the detection code and wonders why it
isn't wired to a CLI.
## Why
The corpus is PDFs from a choir's distribution channel, and quality varies
wildly — clean vector engravings at one end, noisy scans with a previous owner's
pencil markings at the other. **Testing showed the detection algorithms produce
unusable slices on any source with speckles or otherwise poor quality.** Not
slightly-off slices: unusable ones.
But the same testing showed the suggestions land *close* on decent sources —
close enough that correcting them is faster than placing cuts from scratch. So
detection earns its place as an accelerator, and loses any claim to being
load-bearing.
## What this rejected
The original plan's **Phase A** was a deliberately non-interactive CLI:
rasterize, auto-deskew, auto-detect boundaries, write numbered slices, and fix
the misses by hand in GIMP. Its justification was "learn the failure modes before
designing the editor," which is a good idea.
It doesn't survive the premise. A CLI whose output can't be trusted has GIMP as
its repair path — routing work back into the manual process the project exists to
remove. A diagnostic variant (dump per-page PNGs with proposed cuts drawn in red)
was considered and also dropped: it only re-shows a failure already confirmed by
testing, and the editor shows the same thing live.
Release 1 is therefore the editor and detection together. There is no smaller
first release that is actually usable.
## Consequences
- **Manual placement is the primary interaction**, not a correction affordance.
The editor must be fully usable with detection producing nothing.
- **Despeckling targets the detector, not the output.** The known failure mode is
specks, so a median blur and a small-component filter clean the row-darkness
profile the detector reads; the shipped pixels come from the levels-adjusted
image.
- Cut placement is deliberately **forgiving** — anywhere in the whitespace gap
yields the same output, since trim crops to ink afterwards. Precision is not
asked of the human.
- The editor should surface **slice edges**, not just cut lines, so trim
anomalies (a speck anchoring the bounding box) are visible rather than
discovered later in the viewer.