Motivation
The voltage coach (B1291) suggests a non-default voltage value when the user's recent forge history clusters in a narrow band. Five kinds (cluster_low, cluster_mid, cluster_high, spread, too_few) trigger different hint copy + suggestion math. Today each kind's behavior is hardcoded in `src/lib/voltage-coach.ts` with no documented contract for when that behavior can change.
The B1346 kind-breakdown dashboard at `/admin/funnel` now surfaces accept rates per kind. The data informs whether each hint is converting. But "the data says cluster_low has a 12% accept rate, let's reword the hint" needs governance — silent copy changes between builds break the very longitudinal measurement the dashboard exists to produce.
This RFC pins what counts as a behavior change + what the publication window is for each.
Proposal
Definition of behavior change
A "behavior change" is any modification that alters which kind fires for a given history, the suggestion math (currently mean ± stretchDelta), or the user-visible hint copy. Specifically:
- **Kind classification logic** (cluster_low / cluster_mid / cluster_high boundary thresholds): changes here invalidate every prior accept-rate measurement. Treat as a MAJOR change.
- **Suggestion math** (mean derivation, stretch delta of 25, minimum history floor of 5): treat as MAJOR.
- **Hint copy**: treat as MINOR. The kind classification is the same; only the words differ.
- **Suggestion bounds** (currently 0-100): treat as MAJOR.
Publication discipline per change class
- **MAJOR**: 7-day public RFC + a freeze period on the /admin/funnel kind-breakdown dashboard during the comment window (operator note: "the data is in transition; do not cite per-kind accept rates until the RFC resolves").
- **MINOR**: inline commit with a one-line entry in docs/CHANGELOG-VOLTAGE-COACH.md (new file). No comment window required.
- **PATCH** (typo fixes, accessibility tweaks, color tweaks): inline commit, no doc entry required.
Acceptance gate for any MAJOR change
A MAJOR change accepts only if at least one of:
1. The current kind has demonstrated <10% accept rate over ≥30 day rolling window with n ≥ 100 shown events 2. The change is required by a parent RFC (e.g., RFC-0001 versioning policy) 3. The change was operator-instructed and explicitly cites a specific user-impact observation
This prevents tweaking-for-tweaking's-sake. A coach that's ALREADY converting at 35% should not be changed because someone "thinks the copy is stale."
Reproducibility consequence
When a MAJOR change ships, the seal field on every score response gains a new field `pipeline.voltageCoachVersion: <int>` (currently implicit at version 1). This lets longitudinal analysis distinguish scores from songs forged under coach v1 from scores forged under coach v2.
PATCH and MINOR changes don't bump the version because they don't affect the kind classification or suggestion math.
Empirical input as of RFC opening (B1346)
The B1346 dashboard (shipped earlier this session) makes the per-kind accept-rate visible. Today's snapshot will be captured in the next Quality Council entry as the v1 baseline. Any future MAJOR change cites the trajectory from that baseline as part of its motivation section.
Out of scope
- Adding new kinds (e.g., cluster_extreme_low). Future RFC.
- Removing the coach entirely. Future RFC; very high bar.
- Per-genre coach behavior. Future RFC; would be its own moat conversation about genre-specific calibration.
- Cross-coach interactions (voltage + ghost + splice combinations). Each coach evolves independently for now.
Comment window
This RFC is open for comment until 2026-05-03. Email support@songforgeai.com with the subject `RFC-0004` to leave a comment.
Resolution
(Pending — will be filled in after 2026-05-03 with a summary of comments + the accepted text. The thresholds above are the working defaults until then.)