fix(skills): address PR #2110 review feedback

- SSOT: the three assemble-index.mjs BGM fallbacks now import
  bgmDefaultVolume() from media-use's bgm.mjs instead of duplicating the
  0.12/0.9 literals (both reviewers). The cross-skill relative import
  matches the existing dependency (each workflow's audio.mjs adapter
  already resolves ../../media-use/audio/scripts/audio.mjs).
- STATUS_ROLE_KEY: extended with info|neutral|alert|caution|critical —
  same hue-carries-meaning class as the original set (all 3 copies).
- bgm.md: phrase the default as bgmDefaultVolume()/BGM_BED_VOLUME with
  "currently 0.12" so the prose survives future tuning.
- fetch-pr.mjs: drop dead mergeCommit field from the gh pr view FIELDS
  list (version resolution uses mergedAt only).
- music-to-video assemble-index.mjs: comment documenting why its BGM
  stays at 0.8 under VO — music is the content there, not a narration
  bed, so the explainer pipelines' 0.12 default deliberately does not
  apply.

Not changed: pickAccent's chroma fallback — both call sites pass keyless
capture palettes (tokens.json hex lists), so no status-role keys exist
to filter on; the keyed preset path goes through semanticColors and the
build-frame remix, which this PR already fixed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Vance Ingalls
2026-07-09 22:12:59 -07:00
co-authored by Claude Fable 5
parent c992a136bf
commit 23c9d15b69
10 changed files with 24 additions and 20 deletions
+5 -5
View File
@@ -6,7 +6,7 @@
"files": 144
},
"faceless-explainer": {
"hash": "a8f964f864ee3a14",
"hash": "09bc257e79dabebc",
"files": 18
},
"figma": {
@@ -46,7 +46,7 @@
"files": 10
},
"media-use": {
"hash": "74d80350ba0bccd9",
"hash": "f6f3af6648b1bd81",
"files": 122
},
"motion-graphics": {
@@ -54,15 +54,15 @@
"files": 23
},
"music-to-video": {
"hash": "901a19d0680f8c1b",
"hash": "5bb405421a7e19ba",
"files": 132
},
"pr-to-video": {
"hash": "da8e3cbebcd4b674",
"hash": "a93fde2b33b26e75",
"files": 22
},
"product-launch-video": {
"hash": "a88df1784155ace4",
"hash": "14404973ef5d38a0",
"files": 20
},
"remotion-to-hyperframes": {
@@ -55,6 +55,7 @@ import { parseStoryboard } from "./lib/storyboard.mjs";
import { parseFormat } from "./lib/dimensions.mjs";
import { stageAssets } from "./lib/assets.mjs";
import { parseColors, semanticColors } from "./lib/tokens.mjs";
import { bgmDefaultVolume } from "../../media-use/audio/scripts/lib/bgm.mjs";
// ---------- argv ----------
const argv = process.argv.slice(2);
@@ -388,9 +389,9 @@ if (audio.bgm?.path) {
`bgm is ${cov.dur?.toFixed?.(1) ?? "?"}s (< ${TOTAL}s) and could not be extended (${cov.reason}) — the tail will be silent; install ffmpeg`,
);
}
// An explicit volume from audio_meta always wins. Otherwise BGM under
// narration is a bed (0.12 ≈ -18 dB); a silent film sits it forward at 0.9.
const vol = audio.bgm.volume != null ? audio.bgm.volume : voiceCount > 0 ? 0.12 : 0.9;
// An explicit volume from audio_meta always wins; otherwise the shared
// media-use default (bed ~ -18 dB under narration, forward for a silent film).
const vol = audio.bgm.volume != null ? audio.bgm.volume : bgmDefaultVolume(voiceCount > 0);
body.push(
` <!-- BGM -->`,
` <audio`,
@@ -54,7 +54,7 @@ export const UA_DEFAULT_COLORS = new Set(
// 145) and would otherwise win a pure chroma ranking, painting captions/highlights the error red.
// build-frame.mjs uses this same key set to protect status colors during the preset→brand remix.
export const STATUS_ROLE_KEY =
/(?:^|[-_])(?:positive|negative|success|error|warning|danger|good|bad|up|down)(?:[-_]|$)/i;
/(?:^|[-_])(?:positive|negative|success|error|warning|danger|good|bad|up|down|info|neutral|alert|caution|critical)(?:[-_]|$)/i;
// Pick the brand ACCENT — never by raw chroma alone, never a UA-default link color.
// Priority:
+1 -1
View File
@@ -29,7 +29,7 @@ One music bed per composition, produced by the shared audio engine (`scripts/aud
}
```
`volume` is 0.12 (≈ -18 dB — a bed under the voice) under narration, 0.9 for a silent film (no voice). An explicit `volume` in `audio_meta.json` always overrides this default. `bgm_pending` is `false` — the file is on disk when the engine returns.
`volume` comes from the engine's `bgmDefaultVolume()`: `BGM_BED_VOLUME` (currently `0.12` ≈ -18 dB — a bed under the voice) under narration, `BGM_SILENT_VOLUME` (currently `0.9`) for a silent film (no voice). Tune those constants in `scripts/lib/bgm.mjs`, not call sites. An explicit `volume` in `audio_meta.json` always overrides this default. `bgm_pending` is `false` — the file is on disk when the engine returns.
## Local generation (fallback) — Lyria → MusicGen
@@ -153,7 +153,9 @@ for (const m of mounted) {
body.push("");
}
// BGM (track 11) — full duration; duck slightly when VO present
// BGM (track 11) — full duration. Here the music IS the content (music-first
// skill), so it never drops to the explainer pipelines' narration-bed default
// (bgmDefaultVolume() 0.12 ≈ -18 dB): an incidental VO ducks it only slightly.
let bgmEmitted = false;
if (existsSync(join(hyperframesDir, bgmRel))) {
const vol = voiceCount > 0 ? 0.8 : 0.9;
@@ -55,6 +55,7 @@ import { parseStoryboard } from "./lib/storyboard.mjs";
import { parseFormat } from "./lib/dimensions.mjs";
import { stageAssets } from "./lib/assets.mjs";
import { parseColors, semanticColors } from "./lib/tokens.mjs";
import { bgmDefaultVolume } from "../../media-use/audio/scripts/lib/bgm.mjs";
// ---------- argv ----------
const argv = process.argv.slice(2);
@@ -388,9 +389,9 @@ if (audio.bgm?.path) {
`bgm is ${cov.dur?.toFixed?.(1) ?? "?"}s (< ${TOTAL}s) and could not be extended (${cov.reason}) — the tail will be silent; install ffmpeg`,
);
}
// An explicit volume from audio_meta always wins. Otherwise BGM under
// narration is a bed (0.12 ≈ -18 dB); a silent film sits it forward at 0.9.
const vol = audio.bgm.volume != null ? audio.bgm.volume : voiceCount > 0 ? 0.12 : 0.9;
// An explicit volume from audio_meta always wins; otherwise the shared
// media-use default (bed ~ -18 dB under narration, forward for a silent film).
const vol = audio.bgm.volume != null ? audio.bgm.volume : bgmDefaultVolume(voiceCount > 0);
body.push(
` <!-- BGM -->`,
` <audio`,
-1
View File
@@ -86,7 +86,6 @@ const FIELDS = [
"mergedBy",
"state",
"mergedAt",
"mergeCommit",
].join(",");
const view = ghTry(["pr", "view", prRef, "--json", FIELDS]);
+1 -1
View File
@@ -54,7 +54,7 @@ export const UA_DEFAULT_COLORS = new Set(
// 145) and would otherwise win a pure chroma ranking, painting captions/highlights the error red.
// build-frame.mjs uses this same key set to protect status colors during the preset→brand remix.
export const STATUS_ROLE_KEY =
/(?:^|[-_])(?:positive|negative|success|error|warning|danger|good|bad|up|down)(?:[-_]|$)/i;
/(?:^|[-_])(?:positive|negative|success|error|warning|danger|good|bad|up|down|info|neutral|alert|caution|critical)(?:[-_]|$)/i;
// Pick the brand ACCENT — never by raw chroma alone, never a UA-default link color.
// Priority:
@@ -55,6 +55,7 @@ import { parseStoryboard } from "./lib/storyboard.mjs";
import { parseFormat } from "./lib/dimensions.mjs";
import { stageAssets } from "./lib/assets.mjs";
import { parseColors, semanticColors } from "./lib/tokens.mjs";
import { bgmDefaultVolume } from "../../media-use/audio/scripts/lib/bgm.mjs";
// ---------- argv ----------
const argv = process.argv.slice(2);
@@ -388,9 +389,9 @@ if (audio.bgm?.path) {
`bgm is ${cov.dur?.toFixed?.(1) ?? "?"}s (< ${TOTAL}s) and could not be extended (${cov.reason}) — the tail will be silent; install ffmpeg`,
);
}
// An explicit volume from audio_meta always wins. Otherwise BGM under
// narration is a bed (0.12 ≈ -18 dB); a silent film sits it forward at 0.9.
const vol = audio.bgm.volume != null ? audio.bgm.volume : voiceCount > 0 ? 0.12 : 0.9;
// An explicit volume from audio_meta always wins; otherwise the shared
// media-use default (bed ~ -18 dB under narration, forward for a silent film).
const vol = audio.bgm.volume != null ? audio.bgm.volume : bgmDefaultVolume(voiceCount > 0);
body.push(
` <!-- BGM -->`,
` <audio`,
@@ -54,7 +54,7 @@ export const UA_DEFAULT_COLORS = new Set(
// 145) and would otherwise win a pure chroma ranking, painting captions/highlights the error red.
// build-frame.mjs uses this same key set to protect status colors during the preset→brand remix.
export const STATUS_ROLE_KEY =
/(?:^|[-_])(?:positive|negative|success|error|warning|danger|good|bad|up|down)(?:[-_]|$)/i;
/(?:^|[-_])(?:positive|negative|success|error|warning|danger|good|bad|up|down|info|neutral|alert|caution|critical)(?:[-_]|$)/i;
// Pick the brand ACCENT — never by raw chroma alone, never a UA-default link color.
// Priority: