WS2: Phase 2 prompt — v2 loudness units, PLR mastering rules, bpm hedge - #131
Conversation
slittycode
left a comment
There was a problem hiding this comment.
Verdict: APPROVE
Summary
Corrects the Phase 2 prompt to match Phase 1 v2 semantics established in #128: truePeak is now dBTP (old >1.0 linear threshold was actively wrong), PLR-driven mastering bands are surfaced with correct citation fields, and the bpmConfidence hedge fires at the same 0.4 threshold the frontend validator uses. All three new test assertions pass; they're meaningful regression pins, not padding. No phase boundary violations.
Findings
Worth considering:
apps/backend/prompts/phase2_system.txt:164–167 — The PLR bands have a gap: ≤ 8 LU, 8–12 LU, ≥ 14 LU. The 12–14 LU range has no explicit instruction. For a track landing at PLR 13 LU, Gemini has nothing to anchor to and will interpolate unpredictably. Either extend the middle band to 8–14 LU, or add a one-liner fallthrough ("PLR 12–14 LU: treat as the 8–12 band unless crestFactor confirms significant dynamic headroom"). Not blocking — the worst case is inconsistent advice in that narrow range, not wrong advice — but a one-liner closes it.
Test results
3 / 3 pass (test_phase2_prompt_catalog). The other test_phase2_* ERRORs (citation_paths, grammar_fix, validator_catalogue) are import failures from the missing venv in this environment, not logic failures — pre-existing and unrelated to this diff.
Phase boundary check
Clean. Text-only prompt change. plr, truePeak, bpmConfidence, and lufsIntegrated are all confirmed real top-level Phase1Result fields (measurement.ts:657, JSON_SCHEMA.md). The updated MUST loudness-defect rule matches loudnessGuardrails.ts's TRUE_PEAK_OVER_DBTP = 0.0 exactly. The 0.4 bpmConfidence threshold matches phase2Validator.ts's NORMALIZED_LOW_CONFIDENCE_THRESHOLD. Chain of custody intact.
Generated by Claude Code
Stacked on the Phase 1 v2 branch (#128), the prompt's loudness guidance now matches what the backend actually emits under v2: - truePeak framing corrected from the v1 "linear amplitude proxy; >1.0 is an over" to dBTP ">0.0 dBTP is an inter-sample over; null for silence" — in both the citation hint table and the load-bearing MUST loudness-defect rule. Under v1 these would now tell Gemini the wrong over-threshold. - New PLR-driven mastering decision bands (plr = truePeak_dBTP − lufsIntegrated): PLR <=8 already-limited (don't pile on), 8-12 transparent limiter, >=14 dynamic (glue into a limiter). Plus a worked Glue Compressor card citing plr + lufsIntegrated. plr added to the Saturator/Limiter citation row. - bpmConfidence hedge at the v2 normalized 0.4 threshold (matches the frontend validator's NORMALIZED_LOW_CONFIDENCE_THRESHOLD): hedge tempo-locked advice and name the half/double-time alternative below 0.4. All cited paths (plr, truePeak, bpmConfidence, lufsIntegrated, crestFactor) are real top-level Phase1Result fields, so the citation-existence validator accepts them. test_phase2_prompt_catalog gains a regression case pinning the v2 units + new rules; the PLR worked card validates against the Live 12 catalog. Descriptor-hooks expansion (snare/hihat/reverb in _build_descriptor_hooks) is deferred — those fields are already in the citable catalog and the hook work carries the documented invented-citation hazard; a focused follow-up is safer. https://claude.ai/code/session_01Wq1vE1D7o3W9xZKSHXz43Q
The PLR mastering bands were ≤8 / 8–12 / ≥14, leaving 12–14 LU with no instruction (a PLR-13 master had nothing to anchor to). Extend the middle band to 8–14 LU so the bands are contiguous. Regression test pins it. https://claude.ai/code/session_01Wq1vE1D7o3W9xZKSHXz43Q
be99d6c to
d1b3c9f
Compare
Stacking note
Based on
claude/practical-hypatia-0l9jF(#128), notmain— WS2 depends on the Phase 1 v2 semantics from #128 (truePeak in dBTP, bpmConfidence normalized 0–1). Basing it there keeps this diff to just the WS2 changes. Once #128 merges tomain, I'll retarget this PR tomain.Why this is necessary (not just additive)
The prompt's loudness guidance still carried v1 framing that is now wrong under v2. The backend emits
truePeakin dBTP, but the prompt told Gemini it was a "linear amplitude proxy; >1.0 is an over" — including in the load-bearing MUST loudness-defect rule. Left unfixed, Gemini would apply the wrong over-threshold and mis-handle mastering. So part of WS2 is the prompt half of the v2 migration.Changes (
prompts/phase2_system.txt)>0.0 dBTP is an inter-sample over; null is silence(was>1.0, linear).plr = truePeak_dBTP − lufsIntegrated): ≤8 LU already-limited (don't pile on), 8–12 transparent limiter, ≥14 dynamic (glue → limiter). Plus a worked Glue Compressor card citingplr+lufsIntegrated, andplradded to the Saturator/Limiter citation row.NORMALIZED_LOW_CONFIDENCE_THRESHOLD. Below 0.4, hedge tempo-locked advice and name the half/double-time alternative.Verification
test_phase2_prompt_catalogpass; the new PLR worked card validates against the Live 12 device catalog (the cards test).plr,truePeak,bpmConfidence,lufsIntegrated,crestFactor) is a real top-levelPhase1Resultfield → the citation-existence validator accepts them.RUN_GEMINI_LIVE_SMOKE=true, yourGEMINI_API_KEY— CI skips it). The text/structure is verified here; the recommendation quality is best confirmed against a known track.Deferred
The
_build_descriptor_hooksexpansion (snare/hihat/reverb pre-digested context) is deferred — those fields are already in the citable hint catalog, and the hook work carries the documented invented-citation hazard. A focused follow-up is safer than bundling it here.https://claude.ai/code/session_01Wq1vE1D7o3W9xZKSHXz43Q
Generated by Claude Code