Harden for agent users: spec validation, key-sig accidentals, N64 chord qualities
- make_tune: validate_spec() reports every spec problem in one run (missing keys, unknown style, bad qualities, bpm<=0, out-of-range loop/fills, melody longer than chart, unsafe name) — no raw KeyErrors - make_tune: key_sig_for handles accidentals in minor and major keys, any case (Bb minor, F# minor, bb major); real spellings kept (C# major) - make_tune: n64 pad uses QUALITIES table (dim/aug/sus now correct) - make_tune: WARNING on stderr for fields a style can't use (counter for non-DOS, fills_at for n64) instead of silent drops - make_tune: name sanitised ([A-Za-z0-9][A-Za-z0-9._-]*), no traversal - make_tune: render errors actionable (timidity presence check, stderr surfaced, sys.executable instead of bare python3) - songkit: parse_score lints the FINAL bar too (was unchecked); this caught a real 5-beat bar in 01_service_station_2am COUNTER_A (fixed) - build_all.sh: dependency + soundfont checks, removes stale midi/wav outputs with no current source, fails if nothing was produced - smoke_test: runs every spec, checks loop marker tick positions, feeds malformed bars to the linter, covers validation + key sigs - AGENTS.md: documents 0-based bars and exclusive end_bar, validation behaviour; SKILL.md added so the repo loads as an agent skill
This commit is contained in:
1 parent
f5bd7ae13c
commit
810f127d01
7 files changed
+482
-50
No files matched your search
@@ -33,14 +33,36 @@ You supply the music theory: a per-bar chord chart and a melody.
|
||||
}
|
||||
```
|
||||
|
||||
## Indexing convention (read this once, then never guess)
|
||||
|
||||
- **Bars are 0-based everywhere**: bar 0 is the first bar of the chord chart.
|
||||
- **`loop.end_bar` is EXCLUSIVE**: `{"start_bar": 4, "end_bar": 20}` loops
|
||||
bars 4..19 — 16 bars. `start_bar` is inclusive.
|
||||
- The melody must fit the chart: `melody_start_bar + (number of '|' bars)
|
||||
<= len(chords)`. Bars past the melody (e.g. chords 20–23 above) are an
|
||||
outro the engine plays before jumping back to `start_bar`.
|
||||
- `fills_at` entries are 0-based bar numbers, `0 <= bar < len(chords)`.
|
||||
|
||||
## Validation behaviour
|
||||
|
||||
`make_tune.py` validates the whole spec up front and reports **every**
|
||||
problem in one go (missing keys, unknown style, bad chord quality,
|
||||
`bpm <= 0`, out-of-range loop/fill bars, melody longer than the chart,
|
||||
unsafe `name`) — no raw `KeyError`s, no silently wrong output. Fields a
|
||||
style can't use (e.g. `counter` for `n64_ambient`, `fills_at` for styles
|
||||
without drums) print `WARNING:` to stderr and are skipped, never dropped
|
||||
in silence. `name` must match `[A-Za-z0-9][A-Za-z0-9._-]*` — it becomes
|
||||
`midi/<name>.mid`, so no `/`, no `..`.
|
||||
|
||||
## Score grammar (melody strings)
|
||||
|
||||
- Tokens: `PITCH-dur-vel` — `A4-8-90` (A4 eighth, vel 90). Durations:
|
||||
`1` whole, `2` half, `4` quarter (default), `8` eighth, `16` sixteenth.
|
||||
- Rests: `r4`, `r8`, `r16`, `r2`, `r1`.
|
||||
- `|` separates bars. **If you use `|`, every bar must total exactly 4/4**
|
||||
— the parser raises `ValueError: bar N totals X ticks` and tells you which
|
||||
bar is wrong. Use it; it is the single most useful bug-catcher here.
|
||||
- `|` separates bars. **If you use `|`, every bar — including the final
|
||||
one — must total exactly 4/4** — the parser raises
|
||||
`ValueError: bar N totals X ticks` and tells you which bar is wrong.
|
||||
Use it; it is the single most useful bug-catcher here.
|
||||
- Pitches: letter + optional `#`/`b` + octave, e.g. `Bb3`, `F#5`.
|
||||
|
||||
## Verification loop (do this, don't skip it)
|
||||
|
||||
Reference in new issue
Block a user