From fdda36ce002d0a6e9b12a325e40f91dee51fc5db Mon Sep 17 00:00:00 2001 From: PhysShell <45852143+PhysShell@users.noreply.github.com> Date: Mon, 13 Jul 2026 04:28:23 +0500 Subject: [PATCH 1/9] docs: add S15 tonal context stage --- .../S15-tonal-context-and-harmonic-control.md | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 docs/stages/S15-tonal-context-and-harmonic-control.md diff --git a/docs/stages/S15-tonal-context-and-harmonic-control.md b/docs/stages/S15-tonal-context-and-harmonic-control.md new file mode 100644 index 00000000..4f32abde --- /dev/null +++ b/docs/stages/S15-tonal-context-and-harmonic-control.md @@ -0,0 +1,214 @@ +# S15: Tonal context and harmonic control + +Status: in progress — Phase 0 (evidence audit) and Phase 1 (shared tonal core) +accepted and closed on 2026-07-12; Phase 2 is next +Depends on: S1 (canonical score), S5 (corpus), S6 (rule generator) +Builds on: S13 harmonic-context analysis +Feeds: S6 generation, S7 graph costs, S11 regeneration, S13 complement + +## Goal + +Make tonal and harmonic context explicit, uncertain, scoped, and reusable before +it is allowed to influence generation. Separate observed evidence from inferred +musical meaning; preserve an honest abstention path; never turn one best guess +into a hard seven-note whitelist. + +S15 owns the meaning of tonal/harmonic states. S7 owns global path optimisation +over such states. S8 displays the alternatives and provenance. S9 learns from +human choices among them. + +## Guardrails + +- A real-song key result is a tonal hypothesis for one `EvidenceScope`, not + verified ground truth. +- Confidence thresholds and automatic scope selection require calibration; a + larger margin alone does not prove that one track is the correct reference. +- The observed `PitchClassSet` remains distinct from an inferred scale or tonal + hierarchy. Chromatic passing tones, borrowed notes, and tensions are not + automatically errors. +- `None` / ambiguous context is a valid result. No silent fallback to C major, + the lowest pitch, or the highest-margin track. +- Cadence and generation integration remain frozen until their phase-specific + acceptance gates are met. + +## Phase 0 — evidence audit and diagnostics ✅ + +Accepted and closed. + +- Audited the existing generation input and established that + `PitchMaterial.root` was an anchor derived from the minimum input pitch, not a + tonic. +- Measured `WholeScore`, `Track`, and `Voice` evidence on real and synthetic + inputs. +- Established raw evidence vocabulary: onset counts, duration mass, note count, + and observed pitch range. +- Demonstrated that scope can change the winning tonal hypothesis (including the + Wolf & Bear whole-score vs track conflict). +- Rejected confidence cut-offs inferred from the small diagnostic fixture set. + +Primary record: +[`../audit/2026-07-tonal-context-phase0.md`](../audit/2026-07-tonal-context-phase0.md). + +## Phase 1 — shared evidence/inference core ✅ + +Accepted and closed. + +`core/src/tonal.rs` now provides: + +- `EvidenceScope::{WholeScore, Track, Voice}`; +- `PitchEvidence::measure` with raw integer `onset_counts`, `duration_mass`, + `note_count`, and observed `feature::PitchRange`; +- `estimate_key` returning all 24 major/natural-minor `TonalCandidate`s, + best-first, with per-candidate correlation and `scale_fit`; +- `TonalEstimate::confidence_margin` as winner minus runner-up; +- duration-only KS v1, with onset-count fallback only when total duration mass is + zero. + +`complement::estimate_harmony` delegates to the shared inference core and keeps +its public winner-only projection. Focused validation proved: + +- `HarmonicContext`: 16/16 exact, 0 changed; +- structure consumer: 7/7 byte-identical; +- evidence mapping: 39/39, 0 mismatches; +- histogram additivity: pass; +- 24 finite candidates per non-empty scope: pass; +- generation smoke: 30/30 byte-identical. + +Cloud implementation: `6f9114d` (red), `184b586` (green), `e2c9c7f` (docs), +`af26206` (accepted/closed). Local validation: `bd2c7c8`; archival: +`3993bb0`. + +## Phase 2 — explicit scoped context contract (next) + +Allow generation-facing requests and provenance to carry an optional, explicit +scoped tonal estimate **without changing note selection yet**. + +The exact type is a design output, not pre-decided, but it must preserve: + +- the chosen `EvidenceScope`; +- the ranked estimate or an intentionally compact immutable projection; +- absence / ambiguity; +- deterministic serialisation and replay; +- provenance identifying how the estimate was measured. + +Acceptance: + +- requests without tonal context remain byte-identical to the Phase-1 baseline; +- context is optional and scope is explicit; +- no automatic whole-score/track/voice selection; +- no pitch restriction, reranker-weight change, cadence, or production behaviour + change; +- round-trip and deterministic replay tests cover the new contract. + +## Phase 3 — scope policy and confidence calibration + +### Phase 3A — scope-selection experiments + +Compare explicit policies rather than silently choosing the largest margin: + +- selected/reference track; +- whole score; +- guitar-only subsets; +- weighted combinations of tracks; +- multiple competing scope estimates carried together. + +A repetitive bass pedal or ostinato may yield a strong margin while describing +only one layer, so `argmax(margin)` is not an approved policy. + +### Phase 3B — confidence calibration and synthetic controls + +Build labelled, programmatic controls covering: + +- exactly flat chromatic material; +- diatonic and pentatonic material; +- pedal tones and omitted tones; +- borrowed notes and secondary dominants; +- modal ambiguity; +- modulations / tonicisations; +- transpositions and alternative textures. + +Report error and abstention behaviour by scope/material class. Only then may a +stable confidence vocabulary or threshold be proposed. + +## Phase 4 — harmonic fixture DSL + +Introduce a small external fixture language inspired by RomanText / harmonic +analysis DSLs, for example: + +```text +C: I | vi | IV | V +a: i | VI | III | VII +C: I | V/V | V | I +``` + +The text format is for fixtures, debugging, and synthetic corpus generation. +Core uses typed structures (`Degree`, `HarmonicFunction`, chord quality, +inversion, modulation/tonicisation); parser strings are not the domain model. + +Acceptance: + +- scripts transpose deterministically; +- scripts generate labelled symbolic fixtures with multiple textures; +- parser failures are typed and localised; +- no runtime dependency on Python, TensorFlow, MusicXML, or an external analysis + service. + +## Phase 5 — soft harmonic generation policy + +Allow calibrated tonal/harmonic information to influence candidate generation or +ranking as a **soft preference**: + +- observed pitch classes stay legal unless an explicit user constraint says + otherwise; +- inferred hierarchy may reward chord/scale tones and controlled resolutions; +- ambiguous estimates abstain; +- borrowed/chromatic colour tones remain representable; +- A/B evaluation covers harmonic fit, closure, novelty, rhythm, register, and + playability together. + +No hard `inferred scale == allowed notes` shortcut. + +## Phase 6 — local context and cadence + +Move the remaining S6 cadence-aware-ending backlog here. Cadence requires local +section context, phrase boundaries, calibrated confidence, and an abstention +path; a global winner plus `last_note = tonic` is not a cadence model. + +Candidate ending states and explainable resolution costs may be optimised through +the S7 layered-path engine once both stages provide stable contracts. + +Acceptance: + +- section-local context beats global-only context on defined fixtures; +- ambiguous/modulating regions may decline to force a cadence; +- endings are returned as ranked alternatives with explanations; +- context-free generation remains unchanged. + +## Research inputs + +See +[`../audit/2026-07-symbolic-harmony-and-evolution-research.md`](../audit/2026-07-symbolic-harmony-and-evolution-research.md). +The main inputs are: + +- `ekzhang/harmony` and `napulen/romanyh`: layered DP, transition costs, and + k-best global alternatives (algorithmic shape shared with S7); +- `napulen/AugmentedNet`: decomposed harmonic targets and synthetic labelled + examples, not a runtime dependency; +- `napulen/harmalysis` / RomanText: fixture-language inspiration. + +## Non-goals + +- No classical SATB rules copied wholesale into swancore guitar generation. +- No neural runtime dependency in S15; neural assistance remains S12. +- No audio chroma/HMM round-trip while the source is already symbolic. +- No generic `MusicDPGodObject`; S7 owns a small path engine with separate + state/cost clients. + +## See also + +- [`S6-rule-generator-v0.md`](S6-rule-generator-v0.md) +- [`S7-graph-layer.md`](S7-graph-layer.md) +- [`S8-preview-app.md`](S8-preview-app.md) +- [`S9-feedback-layer.md`](S9-feedback-layer.md) +- [`S13-complementary-part-generation.md`](S13-complementary-part-generation.md) +- [`../audit/2026-07-tonal-context-phase0.md`](../audit/2026-07-tonal-context-phase0.md) From ef826de2cb7561d875ff2de50bd2911148754358 Mon Sep 17 00:00:00 2001 From: PhysShell <45852143+PhysShell@users.noreply.github.com> Date: Mon, 13 Jul 2026 04:29:03 +0500 Subject: [PATCH 2/9] docs: record harmony and evolution research --- ...symbolic-harmony-and-evolution-research.md | 238 ++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 docs/audit/2026-07-symbolic-harmony-and-evolution-research.md diff --git a/docs/audit/2026-07-symbolic-harmony-and-evolution-research.md b/docs/audit/2026-07-symbolic-harmony-and-evolution-research.md new file mode 100644 index 00000000..fad8ff38 --- /dev/null +++ b/docs/audit/2026-07-symbolic-harmony-and-evolution-research.md @@ -0,0 +1,238 @@ +# Research: symbolic harmony, global paths, and interactive evolution (2026-07) + +Status: accepted as roadmap input; no dependency adoption +Decision: map the useful ideas onto S7/S8/S9/S12/S15 rather than create a +repository-per-stage roadmap + +## Executive verdict + +The strongest common pattern is: + +```text +enumerate feasible local possibilities +→ assign explainable local / transition costs +→ optimise globally +→ return diverse top-k paths +→ let the human choose +→ retain feedback and lineage +``` + +The responsibilities are intentionally split: + +- **S15** defines tonal/harmonic meaning and uncertainty; +- **S7** optimises multi-step paths; +- **S8** displays alternatives and provenance; +- **S9** captures selection and experiments with structural evolution; +- **S12** remains the owner of future neural assistance. + +No reviewed repository is adopted as a production dependency by this decision. + +## Source assessment + +| Source | Value now | Later | What to take | Owner | +|---|---:|---:|---|---| +| [`ekzhang/harmony`](https://github.com/ekzhang/harmony) | 8/10 | 8/10 | layered DP, transition costs, path reconstruction | S7 | +| [`napulen/romanyh`](https://github.com/napulen/romanyh) | 8/10 | 9/10 | alternative harmonisations, k-best global paths, RomanText fixtures | S7 + S15 | +| [`napulen/AugmentedNet`](https://github.com/napulen/AugmentedNet) | 4/10 | 9/10 | decomposed harmonic targets, uncertainty, synthetic labelled examples | S15 + S12 radar | +| [`perfect-shuffle-music`](https://github.com/kroger66/perfect-shuffle-music) | 6/10 concept | 7/10 | human-in-the-loop generations, crossover concept, lineage | S9, surfaced by S8 | +| [`napulen/harmalysis`](https://github.com/napulen/harmalysis) | 4/10 | 7/10 | external harmonic fixture DSL inspiration | S15 | +| [`ekzhang/composing.studio`](https://github.com/ekzhang/composing.studio) | 3/10 | 6/10 | textual playground, live preview/playback, inspectable edits | S8 | +| [`ekzhang/crepe`](https://github.com/ekzhang/crepe) | 5/10 | 6/10 | possible declarative rule engine when rule closure/explanations justify it | S7/S15 radar | + +The ratings describe architectural relevance to `griff`, not general project +quality. + +## 1. `ekzhang/harmony`: global path shape + +The useful lesson is not classical four-part harmony itself. It is the layered +optimisation shape: + +1. enumerate valid states for each musical position; +2. calculate local and adjacent-state costs; +3. use dynamic programming to select a globally coherent path; +4. reconstruct the selected path with an inspectable total cost. + +This is directly relevant to S7's multi-bar candidate chain. Potential Griff +transition terms include: + +- phrase / contour continuity; +- register continuity; +- rhythm continuity or complement; +- repeated-technique penalties; +- playability / fret travel; +- harmonic fit supplied by S15; +- repetition and mud penalties. + +Do **not** copy SATB-specific prohibitions or doubling/resolution rules as +swancore policy. Transfer the algorithmic form; make costs Griff-specific and +explainable. + +The earlier idea of making a new generic `RegisterPlanner` the first client is +superseded: the register track is already accepted and closed after generator +semantics were repaired. Reopen register planning only when a new measured +multi-bar problem justifies it. + +## 2. `napulen/romanyh`: k-best paths + +The important extension is returning several ranked global alternatives rather +than one optimum. For Griff this supports: + +- globally coherent alternatives without seed-only noise; +- several complementary-guitar trajectories; +- controlled register/harmonic alternatives; +- human selection feeding S9; +- explicit diversity constraints and fixed tie-breaking. + +S7 should first extract a concrete layered-path contract from a real multi-bar +client, then add deterministic k-best enumeration. Avoid a universal +`MusicDPGodObject`; specialised state/cost modules share only the small engine. + +## 3. Nápoles ecosystem: harmonic decomposition and fixtures + +### `AugmentedNet` + +Do not introduce its Python/TensorFlow/MusicXML runtime into Griff. Useful ideas: + +- decompose harmonic analysis into tonal centre, mode, chord root, quality, + inversion, and related targets; +- expose distributions/alternatives rather than one unquestioned label; +- create labelled synthetic examples and vary their texture. + +S15 should grow incrementally from its accepted tonic/mode estimate. Full Roman +numeral analysis is not the next task. + +### `harmalysis` and RomanText + +Use a small text language only as an external fixture/debugging surface: + +```text +C: I | vi | IV | V +C: I | V/V | V | I +a: i | VI | III | VII +``` + +Core representation stays typed. The fixture pipeline can generate +transpositions, omissions, inversions, passing tones, pedal textures, and +modulations with known labels for calibration tests. + +### Audio key detection + +Audio chroma/HMM approaches are deferred. Griff currently receives symbolic +MIDI/Guitar Pro evidence; rendering it to audio/chroma and guessing the lost +symbolic information back would be an avoidable information-loss loop. Revisit +only with a real audio-input stage. + +## 4. `perfect-shuffle-music`: concept, not code + +The implementation is too note-array-centric for Griff. Do not port its genome +or crossover code. + +The useful experiment is structural evolution over Griff objects: + +```text +candidate set +→ human selects parents +→ bar/motif/parameter crossover +→ mutation +→ normalisation and validators +→ existing rerank as a safety/quality guard +→ next generation +``` + +Candidate operators for an S9 experiment: + +```rust +pub enum EvolutionOperator { + AlternateBars, + AlternateMotifs, + RhythmFromAContourFromB, + PrefixSuffixCrossover, + ParameterBlend, +} +``` + +Lineage must record parents, operator, mutations, generation, and session. Track +population collapse, strategy diversity, operator survival, and repeated-parent +dominance. This remains an **Evolution Lab** experiment under S9; create a new +stage only if it later becomes a standalone persistent workflow. + +## 5. `composing.studio`: S8 playground direction + +The transferable UI idea is editable text plus immediate visual/audio feedback. +A Griff playground should expose: + +- textual request / constraints / future harmonic fixture input; +- piano roll / tab / playback; +- candidate list and score axes; +- register, novelty, playability, and tonal diagnostics; +- path and transition explanations; +- like/dislike/favourite controls; +- parent/child lineage for the Evolution Lab. + +S8 supplies the surface; it does not own tonal inference, path optimisation, or +preference semantics. + +## 6. `crepe`: parked implementation option + +A Datalog-like rule engine may become useful when Griff has all of: + +- many independently maintained rules; +- recursive graph closure; +- a need to explain derivations; +- frequent rule additions that make imperative orchestration brittle. + +Until then, typed Rust remains simpler. A pleasant macro is not evidence that the +generator needs an expert-system runtime. + +## Roadmap mapping + +### S7 — graph layer + +- concrete layered-path contract from the first multi-bar client; +- global candidate-chain DP/Viterbi; +- deterministic k-best diverse paths; +- later harmonic/complement/cadence clients using S15 states. + +### S8 — preview app / cockpit + +- textual playground; +- candidate, tonal, path, and lineage inspectors; +- UI for S9 feedback/evolution experiments. + +### S9 — human feedback + +- feedback capture and preference reranking first; +- Evolution Lab second; +- diversity/collapse controls before productisation. + +### S12 — neural assistance + +- AugmentedNet/MiniBach remain decomposition and synthetic-data research inputs; +- no runtime model before the existing corpus, baseline, and feedback gates. + +### S15 — tonal context and harmonic control + +- Phase 0 evidence audit: accepted/closed; +- Phase 1 shared tonal core: accepted/closed; +- Phase 2 explicit scoped context: next; +- later calibration, fixture DSL, soft harmonic generation, local context and + cadence. + +## Immediate actions + +1. Maintain S15 as the owner of tonal meaning and confidence. +2. Implement S15 Phase 2 without changing generated output. +3. Write the S7 layered-path design against a concrete multi-bar candidate-chain + client before extracting a generic engine. +4. Add harmonic synthetic-fixture planning to S15 Phase 3/4. +5. Add Evolution Lab to the S9 backlog, not the production API. +6. Add the textual/candidate/tonal/lineage playground to the S8 backlog. + +## Explicit non-decisions + +- no automatic highest-margin track selection; +- no hard inferred-scale pitch whitelist; +- no generic register planner without new evidence; +- no classical harmony rule transplant; +- no neural or Datalog dependency; +- no new Evolution stage yet. From 2f8dcc4162696f076a40237d8a66c98029687634 Mon Sep 17 00:00:00 2001 From: PhysShell <45852143+PhysShell@users.noreply.github.com> Date: Mon, 13 Jul 2026 04:29:19 +0500 Subject: [PATCH 3/9] docs: extend canonical roadmap through S15 --- docs/audit/2026-05-stage-label-reconciliation.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/audit/2026-05-stage-label-reconciliation.md b/docs/audit/2026-05-stage-label-reconciliation.md index 7d8f67e4..b464af10 100644 --- a/docs/audit/2026-05-stage-label-reconciliation.md +++ b/docs/audit/2026-05-stage-label-reconciliation.md @@ -19,7 +19,12 @@ forward. transport refactor · `S3` Guitar Pro import · `S4` phrase boundary detection · `S5` corpus + schema · `S6` rule generator v0 · `S7` graph layer · `S8` preview app · `S9` feedback layer · `S10` CLAP MVP · `S11` region -regeneration · `S12` neural assistance. +regeneration · `S12` neural assistance · `S13` complementary part generation · +`S14` structure controls and metrics · `S15` tonal context and harmonic control. + +S13 and later stages are append-only additions. Their logical dependency order +may place them beside or before an earlier-numbered future stage; existing stage +numbers are never repurposed or renumbered to make the list look prettier. ## Mislabel mapping @@ -43,14 +48,17 @@ baseline**. It is the input to: ## Rules from here -1. New commits use canonical `S0…S12` numbering per the glossary only. +1. New commits use canonical stage numbers per the glossary and this roadmap. 2. A stage is "closed" only when its acceptance criterion (its stage doc) is met, tested, and documented. 3. Earlier mislabeled work is **not** re-closed under its old number; relevant pieces are re-credited to their true stage in the stage docs' "See also". +4. New cross-cutting stages take the next free number. Existing S-numbers are + never reassigned, even when the logical execution order differs. ## See also - [`../glossary.md`](../glossary.md) §0, §17 - [`../SPEC.md`](../SPEC.md) - [`../stages/S0-baseline-and-tests.md`](../stages/S0-baseline-and-tests.md) +- [`../stages/S15-tonal-context-and-harmonic-control.md`](../stages/S15-tonal-context-and-harmonic-control.md) From 2d81f3096191871b49987a351ba393ce081ab7e1 Mon Sep 17 00:00:00 2001 From: PhysShell <45852143+PhysShell@users.noreply.github.com> Date: Mon, 13 Jul 2026 04:30:39 +0500 Subject: [PATCH 4/9] docs: map register hardening and cadence ownership --- docs/stages/S6-rule-generator-v0.md | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/docs/stages/S6-rule-generator-v0.md b/docs/stages/S6-rule-generator-v0.md index 842598b1..82a60f3e 100644 --- a/docs/stages/S6-rule-generator-v0.md +++ b/docs/stages/S6-rule-generator-v0.md @@ -10,9 +10,21 @@ ADRs: ADR-0005, ADR-0010 > policy (ADR-0017; melodic-closure note §7.2/§7.3). `griff generate` uses it > by default, and `--corpus ` feeds rhythm templates, novelty > references, and the burst/rest gesture ask from curated chunks -> (decisions.log 2026-07-11). Still open from the list below: cadence-aware -> endings inside the strategies, anchor preservation, the string/fret -> playability filter, and the density/syncopation corpus gates. +> (decisions.log 2026-07-11). +> +> Post-acceptance hardening (2026-07-12): the register track is **accepted and +> closed**. `ScaleLadder` provides full-range reachability; Shuffle uses an +> unbiased ≤-octave `LadderWindow`; RhythmCopy traverses reflectively without +> wrapping; RepeatVariation chooses an endpoint local to the bar's actual +> penultimate degree. Focused corpus/synthetic validation found no remaining +> target-strategy >12-semitone jumps. A generic register rerank axis and global +> `RegisterPlan` were not justified and remain rejected/not started. +> +> Remaining follow-ups from the list below: anchor preservation, the string/fret +> playability filter, and the density/syncopation corpus gates. Cadence-aware +> endings are no longer owned as an unscoped S6 patch: they move to **S15 Phase +> 6**, after explicit tonal context, scope/confidence calibration, and an +> abstention path exist. ## Goal @@ -33,7 +45,8 @@ swancore-like riffs. off-style density). 4. Shuffle motifs grouped by tags. 5. Repeat + variation (call/response — replace last beat). -- Cadence-aware endings; anchor preservation; string/fret playability filter. +- Anchor preservation; string/fret playability filter. +- Cadence-aware endings are deferred to S15 Phase 6. ## Acceptance criteria @@ -50,5 +63,6 @@ swancore-like riffs. ## See also +- [`S15-tonal-context-and-harmonic-control.md`](S15-tonal-context-and-harmonic-control.md) - [`../glossary.md`](../glossary.md) §8 - [`../fuzzing.md`](../fuzzing.md) (`generation_request`, P2) From 98a374e8f5fe3b803283e54c6f5574f113cbae0b Mon Sep 17 00:00:00 2001 From: PhysShell <45852143+PhysShell@users.noreply.github.com> Date: Mon, 13 Jul 2026 04:31:07 +0500 Subject: [PATCH 5/9] docs: add layered path and k-best roadmap to S7 --- docs/stages/S7-graph-layer.md | 55 +++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/docs/stages/S7-graph-layer.md b/docs/stages/S7-graph-layer.md index 8f9cc412..83d50820 100644 --- a/docs/stages/S7-graph-layer.md +++ b/docs/stages/S7-graph-layer.md @@ -21,6 +21,13 @@ multi-technique with evidence; supersedes ADR-0014) > idea (a)). Nodes, transition / co-occurrence edges, complement hyperedges, > and the DP/Viterbi traversal remain gated on S6 acceptance and corpus > scale. +> +> Research update (2026-07): `ekzhang/harmony` and `napulen/romanyh` reinforce +> the stage's existing architecture: enumerate feasible states per layer, +> calculate explainable local/transition costs, optimise globally, reconstruct +> the path, and later return deterministic k-best alternatives. The algorithmic +> form is adopted as roadmap input; their classical SATB rules and runtime code +> are not. ## Goal @@ -33,7 +40,8 @@ connected / possible); DP/Viterbi is the *route* (which sequence is best). - In: corpus chunks + features (≥ ~100 phrases recommended before this pays off). - Out: a (hyper)graph (nodes + edges) and a DP/Viterbi traversal producing the - optimal candidate chain. + optimal candidate chain and, after the first path is validated, ranked k-best + alternatives. ## Approach @@ -48,11 +56,47 @@ connected / possible); DP/Viterbi is the *route* (which sequence is best). approximation for graphs too large for exact DP. - DP state carries running context: current candidate, fretboard position and last technique (ADR-0018 — the rich note model makes both expressible), - `EnergyState`, rhythmic similarity to part A. + `EnergyState`, rhythmic similarity to part A, and optional S15 harmonic state + once that contract is calibrated. - Cost function (inspectable, the same weights S9 later tunes): `harmonic_fit + rhythm_complement + style_fit + playability + phrase_continuity − mud_penalty − repetition_penalty − fret_jump_penalty`. +## Planned slices + +### Slice A — concrete layered-path contract + +Extract the smallest reusable path contract from a real multi-bar client, not +from a speculative universal framework. A layer exposes feasible states; the +client supplies local and transition costs plus explanations; the engine returns +the deterministic best path. + +The first preferred client is a multi-bar `GenerationCandidate` chain. The +already-accepted register track is **not** reopened merely to manufacture a +first generic client. + +### Slice B — multi-bar global candidate chain + +For each bar/phrase layer, enumerate candidate states and optimise the whole +sequence using continuity, rhythm, register, technique, playability, style, and +available harmonic costs. Compare against S6's locally ranked output. + +### Slice C — deterministic k-best alternatives + +Return several ranked global paths with: + +- fixed tie-breaking; +- complete total/local/transition explanations; +- an explicit diversity rule so alternatives are not path clones; +- stable provenance for S8 display and S9 feedback. + +### Slice D — specialised clients + +After the engine and first client are accepted, consider complementary-guitar, +harmonic, and cadence planners. Reuse existing fretboard DP rather than rewrite +it only for abstraction symmetry. Register planning requires new measured +counterevidence before reopening. + ## Acceptance criteria - Recombined chains beat S6 single-strategy output on a defined quality score. @@ -60,15 +104,22 @@ connected / possible); DP/Viterbi is the *route* (which sequence is best). by a fixed documented rule). - Multi-bar output shows a global arc (e.g. no 4 identical-technique bars in a row), not a chain of locally-best fragments. +- Every selected path exposes local and transition-cost explanations. +- k-best alternatives are deterministic and measurably distinct under the + documented diversity rule. ## Open questions - Minimum corpus size before the graph beats rule-based v0. - Exact cost-term weights (calibrated on the corpus; later tuned by S9). - State-size vs exactness trade-off before beam search is needed. +- Which multi-bar client produces enough value to justify the first reusable + path contract. ## See also +- [`../audit/2026-07-symbolic-harmony-and-evolution-research.md`](../audit/2026-07-symbolic-harmony-and-evolution-research.md) +- [`S15-tonal-context-and-harmonic-control.md`](S15-tonal-context-and-harmonic-control.md) - [`../glossary.md`](../glossary.md) §9 - [`../adr/0013-dp-viterbi-traversal.md`](../adr/0013-dp-viterbi-traversal.md) - [`../adr/0018-rich-note-model-fretboard-and-techniques.md`](../adr/0018-rich-note-model-fretboard-and-techniques.md) From cea56c3adbe9674e17210d6847fd553790952d6e Mon Sep 17 00:00:00 2001 From: PhysShell <45852143+PhysShell@users.noreply.github.com> Date: Mon, 13 Jul 2026 04:31:38 +0500 Subject: [PATCH 6/9] docs: add Griff playground direction to S8 --- docs/stages/S8-preview-app.md | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/stages/S8-preview-app.md b/docs/stages/S8-preview-app.md index 2a748a8e..767f431d 100644 --- a/docs/stages/S8-preview-app.md +++ b/docs/stages/S8-preview-app.md @@ -20,6 +20,12 @@ ADRs: — > > The `griff-preview` binary launches the TUI, or prints one headless frame with > `--snapshot=WxH`. +> +> Research update (2026-07): the future cockpit/playground should borrow the +> **editable text + immediate visual/audio feedback** shape from symbolic music +> editors, without adopting their notation format as Griff's domain model. S8 +> owns the surface for S7 path alternatives, S9 feedback/evolution lineage, and +> S15 tonal/harmonic provenance; those stages retain their own semantics. ## UI design reference @@ -50,6 +56,16 @@ front-ends and audio build on them: - [ ] `eframe`/`egui` native window — the canonical desktop target (piano-roll canvas, pan/zoom), reusing the same `PianoRollView`. - [ ] MIDI playback via `midir`, with a playhead overlay. +- [ ] **Griff textual playground** — editable request/constraint text with live + parse diagnostics and immediate candidate refresh. Future S15 harmonic + fixture scripts may be edited here, but typed core structures remain the + source of truth. +- [ ] **Candidate/provenance inspector** — candidate scores, novelty, register, + playability, tonal hypotheses, S7 path/transition explanations, and stable + ids sufficient for S9 feedback. +- [ ] **Feedback/evolution surface** — like/dislike/favorite controls first; + parent/child lineage and generation history when the S9 Evolution Lab is + active. S8 displays and edits; S9 owns preference/evolution semantics. - [ ] Curation actions feeding the S5 corpus schema — **first slice landed 2026-06-11**: approve/reject intents in the interaction core (`Viewport::decision`, ADR-0016 — repeat to undo), 'a'/'x' keys and a @@ -95,24 +111,36 @@ the CLAP plugin, to debug transport/slicing/graph without DAW quirks. ## Inputs / Outputs - In: `.mid` / corpus chunks / candidates. -- Out: piano-roll view, MIDI playback, boundary overlays, history, - approve/reject/split/merge/rename/tag actions feeding the corpus. +- Out: piano-roll/tab view, MIDI playback, boundary overlays, candidate history, + score/provenance inspectors, and approve/reject/split/merge/rename/tag actions + feeding the corpus. ## Approach - New workspace member `preview/` using `eframe`/`egui` (immediate-mode, native; not Tauri — IPC/HTML overhead for an offline MIDI tool). - Playback via `midir`. Headless fallback: a `ratatui` TUI. +- Text is an editable request/fixture surface, not a replacement for the typed + canonical model. ## Acceptance criteria - Loads a `.mid`, shows a piano-roll, plays it back. - Curation actions persist into the S5 corpus schema. +- Candidate and provenance views use stable ids and headless-testable view + models. +- S7/S9/S15 data is displayed without reimplementing their inference or policy + in the UI. ## Open questions - Playback engine details on each OS. +- Minimal textual request syntax before the S15 fixture DSL exists. ## See also +- [`../audit/2026-07-symbolic-harmony-and-evolution-research.md`](../audit/2026-07-symbolic-harmony-and-evolution-research.md) +- [`S7-graph-layer.md`](S7-graph-layer.md) +- [`S9-feedback-layer.md`](S9-feedback-layer.md) +- [`S15-tonal-context-and-harmonic-control.md`](S15-tonal-context-and-harmonic-control.md) - [`../glossary.md`](../glossary.md) §11 From deb910e335ae900fd4ac350118df3784bb502dde Mon Sep 17 00:00:00 2001 From: PhysShell <45852143+PhysShell@users.noreply.github.com> Date: Mon, 13 Jul 2026 04:31:57 +0500 Subject: [PATCH 7/9] docs: add Evolution Lab roadmap to S9 --- docs/stages/S9-feedback-layer.md | 87 ++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/docs/stages/S9-feedback-layer.md b/docs/stages/S9-feedback-layer.md index 68a2e776..0317b5c4 100644 --- a/docs/stages/S9-feedback-layer.md +++ b/docs/stages/S9-feedback-layer.md @@ -7,14 +7,36 @@ ADRs: — ## Goal Let like/dislike/favorite steer ranking and sampling of candidates — not train -a model in a vacuum. +a model in a vacuum. Once basic preference learning is accepted, experiment with +structural parent selection, crossover, and mutation while retaining full +lineage and existing validators. ## Inputs / Outputs - In: candidates + their feature vectors, user ratings. -- Out: a `PreferenceProfile`; reranked/ resampled candidate sets. +- Out: a `PreferenceProfile`; reranked/resampled candidate sets. +- Later experiment: parent selections + structural evolution operators → a new + candidate population carrying explicit lineage. -## Approach +## Planned phases + +### Phase 0 — feedback capture + +Persist inspectable events with stable candidate/session identity: + +```rust +pub struct HumanFeedback { + pub candidate_id: CandidateId, + pub verdict: FeedbackVerdict, + pub generation: u32, + pub session_id: SessionId, +} +``` + +The final names and storage format remain a design decision. `Skip`/no-op must be +representable so absence of a like is not silently treated as a dislike. + +### Phase 1 — preference reranking - Like/dislike/favorite → update feature weights. - Baseline EMA update: `w_i ← (1-α)·w_i + α·sign(approve)·feature_i_norm`, @@ -22,16 +44,75 @@ a model in a vacuum. - Explainable rerank by similarity / features / tags. - No gradient descent / RL before S10. +### Phase 2 — Evolution Lab (experiment) + +Adapt only the human-in-the-loop idea from `perfect-shuffle-music`; do not port +its note-array genome or crossover implementation. + +```text +candidate set +→ user selects parents +→ bar/motif/parameter crossover +→ mutation +→ meter/register/playability/novelty validators +→ existing rerank as a safety/quality guard +→ next generation +``` + +Candidate operator vocabulary: + +```rust +pub enum EvolutionOperator { + AlternateBars, + AlternateMotifs, + RhythmFromAContourFromB, + PrefixSuffixCrossover, + ParameterBlend, +} +``` + +Lineage records generation, parents, operator, mutations, and session. Musical +units are bars, motifs, rhythm grids, contours, gesture plans, register windows, +endings, and strategy parameters — never a blind alternating array of MIDI note +indices. + +### Phase 3 — diversity and collapse controls + +Measure and expose: + +- population and strategy diversity; +- rhythm/contour diversity; +- repeated-parent dominance; +- operator survival rates; +- population collapse across generations. + +Evolution Lab remains an S9 experiment. A new stage is justified only if it +becomes a standalone persistent workflow with branching histories, undo/fork, +operator analytics, and its own acceptance contract. + ## Acceptance criteria - Ratings measurably shift subsequent ranking toward liked features (deterministic test with synthetic ratings). - The profile is inspectable and resettable. +- Feedback events retain stable candidate/session provenance. +- Evolution operators preserve structural validity and pass the normal generator + validators. +- Fixed inputs, feedback sequence, and seed reproduce the same population and + lineage. +- Diversity/collapse metrics are reported before Evolution Lab is considered for + product use. ## Open questions - Per-tag Beta-prior alternative vs single EMA. +- Minimal parent-selection UX and population size. +- Whether lineage belongs in the corpus schema or an experiment/session store. ## See also +- [`../audit/2026-07-symbolic-harmony-and-evolution-research.md`](../audit/2026-07-symbolic-harmony-and-evolution-research.md) +- [`S7-graph-layer.md`](S7-graph-layer.md) — deterministic k-best global alternatives +- [`S8-preview-app.md`](S8-preview-app.md) — feedback and lineage UI +- [`S15-tonal-context-and-harmonic-control.md`](S15-tonal-context-and-harmonic-control.md) - [`../glossary.md`](../glossary.md) §10 From 7c1beb5316ddda4f119206e6fe217bf129bf88bf Mon Sep 17 00:00:00 2001 From: PhysShell <45852143+PhysShell@users.noreply.github.com> Date: Mon, 13 Jul 2026 04:32:14 +0500 Subject: [PATCH 8/9] docs: park harmonic ML research under S12 gates --- docs/stages/S12-neural-assistance.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/stages/S12-neural-assistance.md b/docs/stages/S12-neural-assistance.md index 6b705934..83532c24 100644 --- a/docs/stages/S12-neural-assistance.md +++ b/docs/stages/S12-neural-assistance.md @@ -22,17 +22,38 @@ from scratch". - Models suited to fixed-region control / infilling (e.g. anticipatory / masked-LM style on MIDI tokens). - Inference in Rust via `candle` or ONNX (`ort`); training offline. +- Harmonic-analysis research such as AugmentedNet is useful for **task + decomposition** (tonal centre, mode, chord root, quality, inversion) and + synthetic labelled examples, not as a Phase-1 runtime dependency. +- Symbolic generation projects such as MiniBach remain research references only; + they do not replace the S6/S7 deterministic baseline or S15 calibrated tonal + context. ## Preconditions (hard gate) - Corpus ≥ ~100 phrases; working S6 baseline; S9 feedback integration. - Not started before all three hold (glossary §17.5). +- Any harmonic neural proposal must also compare against the accepted S15 + symbolic estimator/fixtures and preserve uncertainty/abstention rather than + emit one unquestioned label. ## Acceptance criteria - Neural suggestions beat S6/S7 on the quality score in a blind comparison. - Deterministic given a fixed seed and model checkpoint. +- Harmonic assistance, when attempted, beats or complements the S15 symbolic + baseline on a labelled test set and reports calibrated uncertainty. + +## Non-goals + +- No Python/TensorFlow/MusicXML service in the core runtime merely because a + research implementation uses that stack. +- No rendering symbolic input to audio/chroma and guessing its lost semantics + back while native symbolic evidence is available. ## See also +- [`../audit/2026-07-symbolic-harmony-and-evolution-research.md`](../audit/2026-07-symbolic-harmony-and-evolution-research.md) +- [`S9-feedback-layer.md`](S9-feedback-layer.md) +- [`S15-tonal-context-and-harmonic-control.md`](S15-tonal-context-and-harmonic-control.md) - [`../glossary.md`](../glossary.md) §8, §17.5 From 445231cd6269c467f30019e4777301ff58d39770 Mon Sep 17 00:00:00 2001 From: PhysShell <45852143+PhysShell@users.noreply.github.com> Date: Mon, 13 Jul 2026 04:32:38 +0500 Subject: [PATCH 9/9] docs: clarify S13 and S15 harmonic ownership --- docs/stages/S13-complementary-part-generation.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/stages/S13-complementary-part-generation.md b/docs/stages/S13-complementary-part-generation.md index a1fdadc3..2fda7157 100644 --- a/docs/stages/S13-complementary-part-generation.md +++ b/docs/stages/S13-complementary-part-generation.md @@ -22,6 +22,13 @@ ADRs: ADR-0012, ADR-0011 > `ConstrainedRandomWalk` line over a request derived from A; typed > `NonUniformTimeline` on mid-score meter changes). `ModeNotImplemented` is > gone — every `RelationMode` arranges. +> +> Ownership update (2026-07): the original private winner-only key estimate was +> generalised into the accepted shared `core::tonal` layer. S13 keeps the +> backwards-compatible `PartProfile::harmony` projection and complement-specific +> use of it; **S15** owns scoped tonal evidence, uncertainty, calibration, +> harmonic fixtures, and future soft harmonic/cadence policy. **S7** owns any +> later multi-bar global optimisation or k-best complementary trajectories. ## Remaining work (follow-up increments) @@ -42,7 +49,8 @@ ADRs: ADR-0012, ADR-0011 `PartProfile::harmony` (tonic, major/natural minor, `scale_fit` as a fact); B's substitution material becomes A's literal pitch classes *plus* the inferred key's scale, so a sparse part no longer collapses - B onto one pitch per band (2026-06-11). + B onto one pitch per band (2026-06-11). The estimator now delegates to + S15's shared `core::tonal` implementation. > Roadmap note: appended as the next free stage number (append-only, per the > stage-label audit). Logically it sits between the single-part generator (S6) @@ -103,7 +111,7 @@ Generative-first: B is derived from A by rule; no corpus pair mining. `ChunkMeta ## Open questions - Harmonic-compatibility thresholds (allowed coincident intervals) — calibrate - on the corpus. + on the corpus and S15 labelled fixtures. - Default per-axis ratios (e.g. support-layer density factor) before S9 feedback exists to tune them. - Where the part profile lives: extend the feature layer vs a dedicated @@ -111,6 +119,8 @@ Generative-first: B is derived from A by rule; no corpus pair mining. `ChunkMeta ## See also +- [`S15-tonal-context-and-harmonic-control.md`](S15-tonal-context-and-harmonic-control.md) +- [`../audit/2026-07-symbolic-harmony-and-evolution-research.md`](../audit/2026-07-symbolic-harmony-and-evolution-research.md) - [`../glossary.md`](../glossary.md) §8 (Complementary part, Complement relation, Relation mode), §9 (Complement hyperedge), §10 (Relation preference) - [`../adr/0012-complementary-part-generation.md`](../adr/0012-complementary-part-generation.md)