Skip to content

WS4: patchSmith — downloadable Vital (.vital) presets with cited parameters - #130

Merged
slittycode merged 2 commits into
mainfrom
claude/patchsmith-vital
Jun 2, 2026
Merged

WS4: patchSmith — downloadable Vital (.vital) presets with cited parameters#130
slittycode merged 2 commits into
mainfrom
claude/patchsmith-vital

Conversation

@slittycode

Copy link
Copy Markdown
Owner

What this is

The first half of WS4 (patchSmith): turn measured synthesis character into a downloadable Vital preset where every parameter cites the Phase 1 measurement that justifies it (PURPOSE.md invariant #2), and weak/absent evidence is disclosed, not guessed (invariant #4).

The mapping (apps/ui/src/services/patchSmith.ts, pure & deterministic)

buildPatch(phase1) emits Vital controls, each with a full citation {label, vitalParam, value, display, phase1Fields, rationale, confidence}:

Measurement → Vital control Confidence
supersawDetail.voiceCount / avgDetuneCents osc_1_unison_voices + osc_1_unison_detune from detector score
spectralBalance.subBass (strong) octave-down osc_2 sub layer MED
acidDetail.* + spectral brightness resonant filter_1 + cutoff from detector score
bassDetail.averageDecayMs / type amp envelope decay / sustain MED

No measurement → no bound parameter. Low-confidence or absent sources are skipped or set to a conservative default with an explicit hedge; the manifest's overall confidence is the worst band across cited params. synthesisCharacter / textureCharacter inform the preset comments (they have no clean control binding without wavetable editing — a documented v2 follow-up).

Format correctness

The .vital file is JSON. I confirmed against Vital's own load_save.cpp (jsonToState) that missing wavetables/modulations/lfos/sample arrays load on init defaults with no error — so this writes an override-only settings object rather than embedding fragile base64 wavetables. Unit mappers encode Vital's real ValueDetails: env times use seconds = value⁴; filter cutoff is the semitone 69 + 12·log₂(f/440).

Verification

  • 14 unit tests: deterministic mapping, citation provenance (every cited param carries ≥1 phase1Fields), hedging on low-confidence/empty inputs, the unit mappers, and a .vital re-parse asserting the JSON shape + in-range control values (the machine-verifiable gate the plan called for).
  • npm run lint + build clean; full unit suite 730 passing.

Caveat (honest)

The re-parse test proves the file is structurally valid JSON with in-range controls; it does not prove Vital loads it (I can't run Vital in this container). The format was authored from Vital's source, and the override-only approach is the low-risk path — but a quick load-check in Vital is worth doing before relying on it. This is the lighter analog of the .adg PR's owner-round-trip gate.

Notes

https://claude.ai/code/session_01Wq1vE1D7o3W9xZKSHXz43Q


Generated by Claude Code

Turns measured synthesis character into a loadable Vital preset where every
parameter cites the Phase 1 measurement behind it (PURPOSE.md invariant #2)
and weak/absent evidence is disclosed rather than guessed (invariant #4).

apps/ui/src/services/patchSmith.ts (pure, deterministic):
- buildPatch(phase1) maps measurements -> Vital controls, each with a
  PatchParameterCitation {label, vitalParam, value, display, phase1Fields,
  rationale, confidence}:
    * supersawDetail.voiceCount/avgDetuneCents -> osc_1 unison voices + detune
    * spectralBalance.subBass (strong)         -> octave-down osc_2 sub layer
    * acidDetail.* + spectralBalance brightness -> resonant filter + cutoff
    * bassDetail.averageDecayMs/type           -> amp envelope decay/sustain
  No measurement -> no bound parameter. Low-confidence/absent sources are
  skipped or defaulted with an explicit hedge; overall confidence = worst band.
- serializeVital(): override-only settings JSON. Confirmed against Vital's
  load_save.cpp that missing wavetables/modulations/lfos arrays load on init
  defaults (no fragile base64 wavetable embedding). Unit mappers encode Vital's
  real ValueDetails (env seconds = value^4; cutoff semitone = 69+12log2(f/440)).

apps/ui/src/components/PatchSmithPanel.tsx: a DeviceRack "Generate Vital patch"
panel (mounted in AnalysisResults) rendering the cited-parameter manifest,
per-param + overall confidence pills, hedges, and the .vital download.

Tests (14): deterministic mapping, citation provenance, hedging on
low-confidence/empty inputs, the unit mappers, and a .vital re-parse asserting
the JSON shape + in-range control values (the machine-verifiable gate).

https://claude.ai/code/session_01Wq1vE1D7o3W9xZKSHXz43Q

@slittycode slittycode left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Summary

Implements patchSmith.ts — the BACKLOG.md item for Phase 3 synth-patch generation. Pure read of Phase 1 synthesis measurements, no backend or schema changes. All 747 unit tests pass (14 new), TypeScript clean. The honest-uncertainty design (hedged manifest alongside the preset, worst-band confidence rollup) is the right call for a tool that can't guarantee Vital round-trip accuracy without actually running Vital.

Findings

Worth considering (not blocking)

mapSubLayer (patchSmith.ts:224–228) writes osc_2_transpose = -12.0 and osc_2_level = 0.5 directly to acc.settings without going through applyCitation. These appear in the downloaded preset but have no entry in the manifest's citations array. The decision to enable osc_2 is cited (osc_2_onspectralBalance.subBass), and the specific values are just what "octave-down sub layer" means rather than measurement-derived quantities, so it's not a hard invariant #2 violation. But a manifest consumer will see osc_2_on: 1.0 cited and won't see osc_2_transpose: -12.0 or osc_2_level: 0.5 at all. Could add them as citations with confidence: "MED" and the same phase1Fields: ["spectralBalance.subBass"] for completeness.

Informational

detuneCentsToVital's linear cents / 7.0 approximation of Vital's kQuadratic control is acknowledged in the comment. At 35 cents the result is 5.0 (mid-range), but Vital's actual quadratic mapping at 5.0 may not land at 35 cents of spread — expect ear-tuning on first real load.

After "Generate" is pressed there are two download buttons: one in the action prop (header) and one at the bottom of the expanded view. Redundant but not harmful.

Test results

747 passed, 4 skipped. 14 new tests cover unit mappers, citation provenance (invariant #2 check for every cited param), hedge/confidence behavior across all four mappers, determinism, and the .vital re-parse gate. All tests exercise real invariants.

Phase boundary check

Clean. patchSmith.ts and PatchSmithPanel.tsx are read-only consumers of Phase1Result. No mutations, no re-derivations of Phase 1 values, no Phase 1 schema changes.


Generated by Claude Code

Addresses the PR #130 review:
- mapSubLayer now routes osc_2_transpose (−1 octave) and osc_2_level through
  applyCitation with spectralBalance.subBass provenance, so every osc_2 value
  in the preset appears in the manifest (invariant #2 completeness) rather than
  only osc_2_on. Test asserts the new citations.
- Removed the redundant header "Download .vital" link from PatchSmithPanel;
  the body primary CTA is the single download affordance.

https://claude.ai/code/session_01Wq1vE1D7o3W9xZKSHXz43Q
@slittycode
slittycode merged commit 50fc918 into main Jun 2, 2026
4 checks passed
@slittycode
slittycode deleted the claude/patchsmith-vital branch June 2, 2026 03:44
slittycode added a commit that referenced this pull request Jun 5, 2026
* docs: sync AGENTS.md files against post-#141 codebase

Two files drifted when the separation backend landed in #141 (which updated
CLAUDE.md but not the per-app AGENTS.md overlays) and when patchSmith landed
in #130.

apps/backend/AGENTS.md:
- Add separation_backend.py entry (selectable Demucs ↔ MSST backend)
- Add separation_ab.py entry (research-only A/B harness)
- Add tests/test_separation_backend.py entry
- Add msst_separate_runner.py and ab_separation_backends.py to the
  Operator and Research Scripts section

apps/ui/AGENTS.md:
- Add patchSmith.ts entry (Phase 3 Vital preset generation service)

No code changes; CLAUDE.md was already complete after #141.

https://claude.ai/code/session_011v17uVcfV8rM9EQpRn72Ra

* docs: fix patchSmith.ts description in apps/ui/AGENTS.md

The initial entry incorrectly said the preset builder uses Phase 2
recommendations. patchSmith.ts imports only Phase1Result — every
parameter cites a Phase 1 field per PURPOSE.md invariant #2. Correct
the description to reflect that.

Caught by review on PR #142.

https://claude.ai/code/session_011v17uVcfV8rM9EQpRn72Ra

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants