@amg555/frameforge-mcp 2.4.10 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/.claude-plugin/marketplace.json +22 -4
  2. package/CHANGELOG.md +174 -0
  3. package/CLAUDE.md +192 -9
  4. package/README.md +47 -6
  5. package/package.json +4 -3
  6. package/plugins/video-pipeline/.claude-plugin/plugin.json +8 -2
  7. package/plugins/video-pipeline/skills/.upstream-skills.json +143 -0
  8. package/plugins/video-pipeline/skills/html-renderer/SKILL.md +59 -15
  9. package/plugins/video-pipeline/skills/html-renderer/references/animation-patterns.md +609 -0
  10. package/plugins/video-pipeline/skills/html-renderer/references/character-animation.md +388 -0
  11. package/plugins/video-pipeline/skills/html-renderer/references/collage-broll.md +41 -0
  12. package/plugins/video-pipeline/skills/html-renderer/references/design.md +217 -0
  13. package/plugins/video-pipeline/skills/html-renderer/references/directing.md +165 -0
  14. package/plugins/video-pipeline/skills/html-renderer/references/earshot-audio.md +201 -0
  15. package/plugins/video-pipeline/skills/html-renderer/references/engine-api.md +480 -0
  16. package/plugins/video-pipeline/skills/html-renderer/references/film-styles.md +95 -0
  17. package/plugins/video-pipeline/skills/html-renderer/references/hyperframes-motion.md +208 -0
  18. package/plugins/video-pipeline/skills/html-renderer/references/onetake-camera.md +59 -0
  19. package/plugins/video-pipeline/skills/html-renderer/references/procedural-sfx.md +135 -0
  20. package/plugins/video-pipeline/skills/html-renderer/references/remotion-patterns.md +159 -0
  21. package/plugins/video-pipeline/skills/video-pipeline/SKILL.md +19 -2
  22. package/plugins/video-pipeline/skills/video-pipeline/assets/project/pipeline/briefings/orchestrator.md +15 -0
  23. package/plugins/video-pipeline/skills/video-pipeline/assets/project/pipeline/briefings/scene-author.md +21 -0
  24. package/plugins/video-pipeline/skills/video-pipeline/assets/project/reel/engine.js +1293 -20
  25. package/plugins/video-pipeline/skills/video-pipeline/assets/project/reel/virtual-clock.js +36 -6
  26. package/plugins/video-pipeline/skills/video-pipeline/references/mcp-tools.md +126 -2
  27. package/scripts/deep-validate.js +52 -2
  28. package/src/audio-mixer/mixer.js +594 -63
  29. package/src/cli/doctor.js +36 -2
  30. package/src/cli/make.js +113 -9
  31. package/src/harness/bin/harness.mjs +127 -5
  32. package/src/harness/lib/capture.mjs +215 -192
  33. package/src/harness/lib/verify-quality.mjs +47 -7
  34. package/src/mcp-server/server.js +1015 -59
  35. package/src/skills/sync-upstream.js +290 -0
  36. package/src/utils/media-downloader.js +162 -0
  37. package/src/utils/transcribe.js +341 -0
  38. package/src/video-editor/editor.js +96 -11
  39. package/src/workflows/ingest.js +10 -0
  40. package/.bob/artifacts/enterprise-ai-video-agent-platform-agnostic-implementation-guide.html +0 -464
  41. package/out/check/purity_report.json +0 -79
  42. package/out/frames/f000000.jpg +0 -0
  43. package/out/frames/f000001.jpg +0 -0
  44. package/out/frames/f000002.jpg +0 -0
  45. package/out/frames/f000003.jpg +0 -0
  46. package/out/frames/f000004.jpg +0 -0
  47. package/out/frames/f000005.jpg +0 -0
  48. package/out/frames/f000006.jpg +0 -0
  49. package/out/frames/f000007.jpg +0 -0
  50. package/out/frames/f000008.jpg +0 -0
  51. package/out/frames/f000009.jpg +0 -0
  52. package/out/frames/f000010.jpg +0 -0
  53. package/out/frames/f000011.jpg +0 -0
  54. package/out/frames/f000012.jpg +0 -0
  55. package/out/frames/f000013.jpg +0 -0
  56. package/out/frames/f000014.jpg +0 -0
  57. package/out/frames/f000015.jpg +0 -0
  58. package/out/frames/f000016.jpg +0 -0
  59. package/out/frames/f000017.jpg +0 -0
  60. package/out/frames/f000018.jpg +0 -0
  61. package/out/frames/f000019.jpg +0 -0
  62. package/out/frames/f000020.jpg +0 -0
  63. package/out/frames/f000021.jpg +0 -0
  64. package/out/frames/f000022.jpg +0 -0
  65. package/out/frames/f000023.jpg +0 -0
  66. package/out/frames/f000024.jpg +0 -0
  67. package/out/frames/f000025.jpg +0 -0
  68. package/out/frames/f000026.jpg +0 -0
  69. package/out/frames/f000027.jpg +0 -0
  70. package/out/frames/f000028.jpg +0 -0
  71. package/out/frames/f000029.jpg +0 -0
  72. package/out/frames/f000030.jpg +0 -0
  73. package/out/frames/f000031.jpg +0 -0
  74. package/out/frames/f000032.jpg +0 -0
  75. package/out/frames/f000033.jpg +0 -0
  76. package/out/frames/f000034.jpg +0 -0
  77. package/out/frames/f000035.jpg +0 -0
  78. package/out/frames/f000036.jpg +0 -0
  79. package/out/frames/f000037.jpg +0 -0
  80. package/out/frames/f000038.jpg +0 -0
  81. package/out/frames/f000039.jpg +0 -0
  82. package/out/frames/f000040.jpg +0 -0
  83. package/out/frames/f000041.jpg +0 -0
  84. package/out/frames/f000042.jpg +0 -0
  85. package/out/frames/f000043.jpg +0 -0
  86. package/out/frames/f000044.jpg +0 -0
  87. package/out/frames/f000045.jpg +0 -0
  88. package/out/frames/f000046.jpg +0 -0
  89. package/out/frames/f000047.jpg +0 -0
  90. package/out/frames/f000048.jpg +0 -0
  91. package/out/frames/f000049.jpg +0 -0
  92. package/out/frames/f000050.jpg +0 -0
  93. package/out/frames/f000051.jpg +0 -0
  94. package/out/frames/f000052.jpg +0 -0
  95. package/out/frames/f000053.jpg +0 -0
  96. package/out/frames/f000054.jpg +0 -0
  97. package/out/frames/f000055.jpg +0 -0
  98. package/out/frames/f000056.jpg +0 -0
  99. package/out/frames/f000057.jpg +0 -0
  100. package/out/frames/f000058.jpg +0 -0
  101. package/out/frames/f000059.jpg +0 -0
  102. package/src/harness/test/fixtures/broken-scene.html +0 -27
  103. package/src/harness/test/fixtures/reference-scene.html +0 -23
  104. package/src/harness/test/fixtures/sample-script.json +0 -18
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "frameforge",
3
3
  "displayName": "FrameForge — AI Video Production",
4
- "description": "Full AI video production engine. Produce short-form reels (1080×1920), YouTube videos (1920×1080), or code-driven animated explainers — directly from your IDE. Playwright + FFmpeg renders every frame. 17 MCP tools.",
5
- "version": "2.3.1",
4
+ "description": "Full AI video production engine. Produce short-form reels (1080×1920), YouTube videos (1920×1080), or code-driven animated explainers — directly from your IDE. Playwright + FFmpeg renders every frame. 28 MCP tools. Whisper, yt-dlp, broadcast audio, 24 film styles, ClaudeAnimationBase, onetake 39-move library, HyperFrames motion craft.",
5
+ "version": "2.7.0",
6
6
  "homepage": "https://github.com/AMG555/FrameForge",
7
7
  "plugins": [
8
8
  {
@@ -12,7 +12,7 @@
12
12
  {
13
13
  "name": "video-pipeline",
14
14
  "displayName": "FrameForge Video Pipeline",
15
- "description": "End-to-end video production: research → script → TTS → images → render → publish. Three paths: (1) IDE writes scenes (most common, no API key), (2) code-driven Playwright animation, (3) auto-research pipeline. 17 MCP tools.",
15
+ "description": "End-to-end video production: research → script → TTS → images → render → publish. Three paths: (1) IDE writes scenes (most common, no API key), (2) code-driven Playwright animation, (3) auto-research pipeline. 28 MCP tools. Includes Whisper transcription, yt-dlp ingestion, broadcast-grade audio, upstream skills sync.",
16
16
  "triggerPhrases": [
17
17
  "make a video about",
18
18
  "produce a reel on",
@@ -25,7 +25,25 @@
25
25
  "run the pipeline",
26
26
  "publish video",
27
27
  "overnight batch",
28
- "queue videos"
28
+ "queue videos",
29
+ "ingest this video",
30
+ "transcribe this",
31
+ "download from youtube",
32
+ "mix audio",
33
+ "sync upstream skills",
34
+ "check for updates"
35
+ ]
36
+ },
37
+ {
38
+ "name": "html-renderer",
39
+ "displayName": "HTML Renderer",
40
+ "description": "HTML-as-compositor rendering: pure seek(t) function, Playwright capture, closed-loop visual QA.",
41
+ "triggerPhrases": [
42
+ "html video",
43
+ "remotion style",
44
+ "code-driven animation",
45
+ "harness render",
46
+ "render animation"
29
47
  ]
30
48
  }
31
49
  ]
package/CHANGELOG.md CHANGED
@@ -4,6 +4,180 @@ All notable changes to FrameForge are documented here.
4
4
 
5
5
  ---
6
6
 
7
+ ## [2.7.0] — 2026-11-11
8
+
9
+ ### Added
10
+
11
+ - **OM Motion Library — 24 moves** (`reel/engine.js`):
12
+ - `beatAt(index, bpm, fps)` / `beatTime(index, bpm)` / `snapToBeat(t, bpm)` — HyperFrames beat-grid formula; each index rounded independently (never accumulated, eliminates drift).
13
+ - `OM` object — 24 pure `(t, opts) → CSS style` motion primitives from OneTake's 39-move library: `spring`, `rise`, `iris`, `irisClose`, `zoomThrough`, `morphRect`, `silk`, `belt`, `ripple`, `odometer`, `camera`, `handheld`, `popOut`, `drop`, `implode`, `slideExit`, `wordByWord`, `scalePop`, `revealWipe`, `typewriter`, `counterFlip`, `breathe`, `float`, `pulseOpacity`, `carryScore`.
14
+ - `ROOM_SFX` palette — OneTake 5-material standard (air/wood/glass/sub/bubble at −8 dBFS) for use with `cue()`.
15
+ - `event(type, t, meta)` + `window.__events()` — Sound-from-composition contract; render.mjs extracts cues to `sfx-events.json` after probe.
16
+
17
+ - **Earshot Forge DSP Primitives** (`src/audio-mixer/mixer.js`):
18
+ - `forgeModalResonator(freq, q, gainDb)` — FFmpeg EQ approximating physical material resonance (wood/glass/metal/sub frequency guidelines from earshot).
19
+ - `forgeSVFilter(type, freq, q)` — State-variable filter: lp/hp/bp/notch.
20
+ - `forgeComputedRoom(sizeM, damp, earlyMs)` — Computed room from physical dimensions using Sabine RT60 approximation; produces `aecho` filter string with 3-tap early reflections.
21
+ - `forgeKitSoundBank(material, role)` — Maps earshot material + role to `SFX_FREQ_MAP` key.
22
+ - `"computed:sizeM:damp:earlyMs"` room string supported in `mix_audio_pro` and `_buildVoiceChainFilter`.
23
+
24
+ - **J/L-Cut Editing in plan_video_edit** (`src/mcp-server/server.js`):
25
+ - Style-aware cut type assignment: cinematic/documentary → J-cut; vintage/film_16mm/lofi_chill → L-cut; fast_paced/cyberpunk/anime_action → hard cut.
26
+ - `audio_offset` field in every clip: negative = J-cut (audio precedes video by 0.25–0.5s), positive = L-cut (audio trails by 0.3s).
27
+ - `cut_type` field in `edit.json` clips; emojis in `edit-plan.md` (🎵/🔊/✂️).
28
+ - `bpm` param for beat-grid snapping of cut points.
29
+
30
+ - **TREATMENT.md Director Document** (`src/mcp-server/server.js` — `plan_video_edit`):
31
+ - Auto-generated 8-section director treatment (lemo-opuscar DIRECTOR.md format): Concept, Tone, Visual Language, Sound, Narrative Arc, Shot List, Delivery, Director Notes.
32
+ - `generate_treatment` param (default true); path returned in `treatmentPath`.
33
+
34
+ - **check_upstream_updates — Changelog Notice**:
35
+ - Response now includes `pendingUpdates[]` with per-repo human-readable impact descriptions.
36
+ - `hasUpdates` boolean field for agent routing.
37
+ - `hint` field shows update count or next action.
38
+
39
+ - **Version Consistency Pass**:
40
+ - All agent configs synced to v2.7.0: `cloudflare-mcp/src/index.js`, `scripts/deep-validate.js`, `plugins/video-pipeline/.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, `AGENT.md`, `README.md`, `mcp-tools.md`, `.github/copilot-instructions.md`, `.upstream-skills.json`.
41
+
42
+ ---
43
+
44
+ ## [2.6.0] — 2026-11-12
45
+
46
+ ### Added
47
+
48
+ - **Unified Standalone CLI Commands** (`src/cli/make.js`):
49
+ - `frameforge download <url>` — yt-dlp media ingestion with optional subtitles (`--subtitles`), audio extraction (`--audio`), output directory (`--out-dir`), and custom naming (`--filename`).
50
+ - `frameforge transcribe <file>` — Whisper speech transcription exporting SRT, NDJSON, and JSON formats with model selection (`--model`) and language hints (`--language`).
51
+ - `frameforge sync` / `frameforge update` — Upstream skills synchronizer checking all 9 frontier repos.
52
+ - `frameforge doctor` and `frameforge setup` — First-class subcommand routing.
53
+ - **15+ Year Sound Engineer Signal Chain & Procedural Audio Engine** (`src/audio-mixer/mixer.js`):
54
+ - Multi-element procedural SFX synthesis (shaped pink/white noise, sub-bass pitch drop, dual-sine chime harmonics, acoustic chord triads) replacing plain sine beeps across all 13 SFX types (`whoosh`, `swish`, `impact`, `deep_boom`, `punch`, `pop`, `click`, `tick`, `riser`, `chime`, `sparkle`, `buzz`, `transition`).
55
+ - Enhanced voice mastering chain: 80Hz rumble cut, 300Hz boxy mud notch (-1.5dB), 5kHz presence boost (+2dB), 12kHz air shelf (+1.5dB), 3:1 broadcast compressor, 6.5kHz de-esser, and -60dBFS noise gate.
56
+ - Acoustic pocket carving: 2.5kHz notch (-3.5dB) on music layer prevents vocal masking and guarantees intelligibility on mobile phone speakers.
57
+ - Dynamic sidechain ducking (-18dB attenuation) with 40ms perceptual lead and musical release.
58
+ - Video SFX mixing: `mixVideo` supports direct timeline SFX cue placement and two-pass EBU R128 loudness normalization.
59
+ - **`check_upstream_updates` MCP Tool (Tool #28)** (`src/mcp-server/server.js`):
60
+ - Fast offline check of the last sync state across all 9 upstream reference repositories.
61
+ - Automatic notification caching: users and agents are visibly notified on CLI doctor runs, make runs, and tool responses whenever upstream commits are updated.
62
+ - **Camera Motion & Punch-Ins in Video Editor** (`src/video-editor/editor.js`):
63
+ - `editClip` and `editAndAssemble` support dynamic camera moves (`punch_in`, `zoom_in`, `ken_burns`, `slow_zoom_out`, `pan_left`, `pan_right`) using broadcast-grade zoompan filter expressions.
64
+ - **Frontier Craft Documentation References**:
65
+ - `character-animation.md`: Complete ClaudeAnimationBase guide (31 emotions, timing principles, 12fps line boil).
66
+ - `directing.md`: Professional directing method from lemo-opuscar (sound, rhythm, camera, staging).
67
+ - `earshot-audio.md`: Professional 5-loop audio quality workflow and LUFS tables.
68
+ - `hyperframes-motion.md`: Measured motion craft from HyperFrames launch films.
69
+ - **Tests & Quality**:
70
+ - 100% test pass rate across 636 tests in 136 suites.
71
+
72
+ ---
73
+
74
+ ## [2.4.13] — 2026-11-12
75
+
76
+ ### Added
77
+
78
+ - **HyperFrames Declarative Clips** (`engine.js`):
79
+ - `.clip[data-start]` elements automatically participate in the timeline during `seek(t)` without manual JS registration.
80
+ - Computes and binds `--lt` (local time in seconds), `--progress` ($0.0000 \to 1.0000$), `data-lt`, and `data-progress` dynamically.
81
+ - **OneTake Continuous Camera Choreography** (`engine.js`):
82
+ - `cameraPath(waypoints, opts)`: Smooth continuous camera panning, zooming, and tilting across the `#stage` using cubic easing (`easeInOut`) without harsh cuts.
83
+ - `cameraShake(t, opts)`: Deterministic organic handheld camera noise using 2D continuous simplex noise (`noise2D`).
84
+ - **ClaudeAnimationBase Mascot Vector Character** (`engine.js`):
85
+ - `mascot(emotion, opts)`: Procedural SVG mascot character supporting 12 emotions (`happy`, `excited`, `thinking`, `confused`, `skeptical`, `surprised`, `alarmed`, `celebrating`, `proud`, `curious`, `sad`, `neutral`).
86
+ - Includes 12fps line boil, eye blink cycle, and speech mouth flutter (`setSpeaking(true)`).
87
+ - **gbro-collage-broll Editorial Halftone Paper Collage** (`engine.js`):
88
+ - `collageCard(content, opts)`: Paper collage card component featuring radial halftone dot pattern, washi tape accent strip, 2.5D perspective tilt, and drop shadow.
89
+ - **Viral Karaoke Captions** (`engine.js`):
90
+ - Enhanced `captions()` and `_tickCaptions()` to split transcript segments into word tokens.
91
+ - Spoken words pop with $1.14\times$ scale, glow shadow, and high-contrast highlight (`#facc15`).
92
+ - **Earshot Web Audio SFX Live Preview** (`engine.js`):
93
+ - Real-time procedural audio synthesis in browser preview (`!window.__playwright`) for `cue()` sound triggers (`whoosh`, `impact`, `pop`, `click`, `riser`).
94
+ - **Lemo-Opuscar J-Cut and L-Cut Audio Splits** (`editor.js`):
95
+ - `splitCut: 'j-cut' | 'l-cut'` support in `concatClipsWithTransitions` using asymmetric S-curve audio crossfades (`qsin` / `hsin`).
96
+ - **FFmpeg Concurrency & Memory Safety** (`editor.js`):
97
+ - Constrained x264 encoding threads (`-threads 2`) across clip trimming and transition concatenation to prevent thread pool exhaustion and memory allocation failures.
98
+
99
+ ### Tests & Validation
100
+
101
+ - Unit tests added for camera waypoints, camera shake, declarative clips, karaoke word formatting, and mascot emotion catalog in `engine.test.js`.
102
+ - J-cut transition assembly test added to `editor.test.js`.
103
+ - `deep-validate.js` updated to verify all frontier primitives and editor split cut capabilities.
104
+ - 100% test pass rate across 624 tests in 135 suites.
105
+
106
+ ---
107
+
108
+ ## [2.4.12] — 2026-11-11
109
+
110
+ ### Added
111
+
112
+ - **`transcribe_media` MCP tool (Tool #25)** — Whisper speech transcription with word-level timestamps.
113
+ - Supports `openai-whisper` (local GPU/CPU), `faster-whisper` (CTranslate2), `whisper-cli` binary, or `OPENAI_API_KEY` cloud fallback.
114
+ - Output formats: `ndjson` (NDJSON for `engine.js captions()`/`cuePhrase()`), `srt` (standard subtitle file), `json` (full structured data), `all` (all three).
115
+ - Returns silence/pause boundaries for intelligent cut alignment in `plan_video_edit`.
116
+ - Install: `pip install openai-whisper` (local, free, no API key required).
117
+ - **`ingest_url` MCP tool (Tool #26)** — yt-dlp-powered media ingestion from any web URL.
118
+ - Supports YouTube, Vimeo, Twitter/X, Instagram, TikTok, Twitch, SoundCloud, direct MP4/MP3 URLs, and 1000+ other sites.
119
+ - Downloads up to 1080p MP4 (video) or MP3 (audio-only). Probes and returns `duration`, `width`, `height`.
120
+ - Output goes to `.frameforge-files/downloads/` and can be passed directly to `edit_video`, `transcribe_media`, or any scene `video_path`/`audio_path`.
121
+ - Install: `pip install yt-dlp` (or `winget install yt-dlp` on Windows).
122
+ - **`mix_audio_pro` MCP tool (Tool #27)** — Professional broadcast-grade audio post-production.
123
+ - Full 10+ year sound engineer signal chain: 80Hz HPF → presence +2dB@5kHz → air shelf +1.5dB@12kHz → 3:1 compressor → de-esser @6.5kHz → optional room acoustics → sidechain duck (-18dB) → stereo widener (M/S 1.4x) → procedural SFX timeline → two-pass EBU R128 loudnorm.
124
+ - Procedural SFX synthesis from the earshot pattern: `whoosh` (200Hz/400ms), `impact` (60Hz/500ms), `pop` (600Hz/120ms), `click` (2.5kHz/50ms), `riser` (100Hz/2s). All placed with 40ms perceptual lead.
125
+ - `sfxCues: [{ name, time, volume }]` — millisecond-accurate placement, no sample files required.
126
+ - `addReverb: true` — 30ms pre-delay + 0.3s RT60 aecho for cinematic narrator warmth.
127
+ - `stereoWiden: true` — mid-side extrastereo 1.4x on music layer (voice stays mono-center).
128
+ - `videoPath` parameter — mux the final mixed audio directly into a video file.
129
+ - Returns `{ measuredLufs, measuredTp, passed, chain }` with full signal chain summary.
130
+ - **Professional AudioMixer upgrade** (`src/audio-mixer/mixer.js`):
131
+ - `_buildVoiceChainFilter()` — unified voice chain: HPF + presence EQ + air shelf + compressor + de-esser.
132
+ - `_twoPassNorm()` — two-pass EBU R128 loudnorm (measure + apply with measured values for linear accuracy).
133
+ - `_synthesizeSfxCue()` — earshot-pattern procedural SFX synthesis with 40ms perceptual lead via FFmpeg lavfi.
134
+ - `SFX_FREQ_MAP` and `PERCEPTUAL_LEAD_S` exported for consumers.
135
+ - `mixWithDucking()` now accepts `{ addReverb, stereoWiden, sfxCues }` optional parameters.
136
+ - `_sidechainMixPro()` — full pro chain replacing legacy `_sidechainMix()`.
137
+ - Music band now filtered to 16kHz (up from 8kHz) and stereo-widened when `stereoWiden: true`.
138
+ - Music attenuation updated from -15dB to -18dB for better voice intelligibility.
139
+ - Backward-compatible: existing callers work unchanged.
140
+ - **`mix_audio_pro.py`** scaffold script (`plugins/...scripts/mix_audio_pro.py`) — standalone Python CLI with the same professional chain, usable from within HTML-renderer projects via `uv run scripts/mix_audio_pro.py`.
141
+ - **Upstream skills auto-notification** (`src/skills/sync-upstream.js`):
142
+ - `sync_upstream_skills` MCP tool now returns `updatedRepos[]` and emits a visible user notice when any of the 9 tracked repositories has new commits.
143
+ - Optional `SKILL_UPDATE_WEBHOOK_URL` env var — POSTs a JSON callback whenever upstream repos update.
144
+ - Console output in non-silent mode now lists each updated repo and explains that techniques were automatically applied.
145
+ - **Expanded `procedural-sfx.md` reference** — added full professional voice chain documentation (10+ year rationale per stage), music bed mood matching table, and broadcast loudness standards reference (YouTube, Podcast, Netflix, EBU R128).
146
+
147
+ ### Documentation
148
+ - **CLAUDE.md** — Updated tool count to 27, added `PROFESSIONAL AUDIO WORKFLOW` section covering Whisper transcription → cuePhrase sync, yt-dlp ingestion, `mix_audio_pro` call examples, and upstream skills auto-update workflow.
149
+
150
+ ---
151
+
152
+ ## [2.4.7] — 2026-11-11
153
+
154
+ ### Added
155
+ - **`quality` mode in `render_animation` MCP tool** — Closed-loop visual QA gate (1–10 per-frame score, worst frames, motion delta) is now a first-class MCP mode. Returns `{ passed, overallScore, worstFrames, motionDelta }` structured directly on the tool response — the Opus 5.5 fix-loop entry point.
156
+ - **`golden` mode in `render_animation` MCP tool** — Golden stills regression baseline. `goldenSave: true` captures 4-keyframe SHA-256 hashes; `goldenCheck: true` compares against baseline and fails on any hash drift (refactor broke determinism).
157
+ - **`subframes` parameter in `render_animation` full mode** — Motion-blur 180° shutter simulation. `subframes: 6` renders 6 sub-frames per output frame and blends them; eliminates ghosting on fast morphs. Default 1 (no blur). Documented in CLAUDE.md.
158
+ - **`skipVerify` parameter in `render_animation` full mode** — Skip the automatic purity gate before full render. Default `false` (gate always runs).
159
+ - **`sampleRate` parameter in `render_animation` quality mode** — Override samples-per-second for quality gate (default 2). Higher values = more samples = more precise worst-frame detection.
160
+ - **Automatic purity gate before `render full`** — `render.mjs` now auto-invokes `harness verify` before starting frame rendering unless `--skip-verify` is passed or a passing `purity_report.json` is already cached.
161
+
162
+ ### Improved
163
+ - **`scaffold_animation_project` edit.js generation** — Starter code now implements all 10 Motion Craft rules:
164
+ - Rule 1: `spring()` damped harmonic entrance instead of linear `Math.min(1, lt / 0.3)` fade.
165
+ - Rule 2: 3-property entrance — `opacity` + `scale(0.88→1.0)` + `translateY(40→0)` for every subject layer.
166
+ - Rule 3: Caption overlay staggered 0.18s after primary subject.
167
+ - Rule 4: Exits 0.25s, entrances 0.6s (asymmetric timing).
168
+ - Rule 5: 5 named layers per scene (`bg`, `env`, `subject`, `overlay`, `fg`) with correct z-ordering.
169
+ - Rule 7: Lissajous camera drift (`sin(0.4t)`, `cos(0.3t)`) on the `bg` layer — no scene ever freezes.
170
+ - Import line now includes `spring` from `reel/engine.js`.
171
+ - **`verify_scene_quality` dynamic sample density** — Previously hardcoded to 5 samples at fixed percentiles. Now derives sample count from `sampleRate * duration`, minimum 5, evenly distributed. Enables richer QA on long-form videos at `sampleRate: 4+`.
172
+ - **CLAUDE.md closed-loop QA protocol** — Expanded Step 5b with actionable fix guidance per issue type (blank frame, stuck motion, corner-confined, blown, low-contrast). Added Step 5c for motion-blur pass. Added Step 6 effort table (xhigh/medium per stage). Upgraded Step 9 golden regression to use the new `golden` MCP mode.
173
+
174
+ ### Technical
175
+ - `render_animation` handler now returns `overallScore`, `worstFrames`, `motionDelta`, `qualityReport`, and `goldenReport` fields from the tool response — agents no longer need to read report files manually.
176
+ - `harness.mjs quality` command now uses a separate `quality_sheet.jpg` output (not `sheet.jpg`) to avoid overwriting the visual review contact sheet.
177
+ - `render_animation` quality/golden modes route through `harness.mjs` (not `render.mjs`) since that's where the implementations live.
178
+
179
+ ---
180
+
7
181
  ## [2.4.6] — 2026-11-10
8
182
 
9
183
  ### Enhanced
package/CLAUDE.md CHANGED
@@ -20,7 +20,7 @@ You are a **video producer** working inside FrameForge. Your job is to design sc
20
20
 
21
21
  ## WHAT YOU MAY DO
22
22
 
23
- - Call any of the 17 FrameForge MCP tools (listed below)
23
+ - Call any of the 28 FrameForge MCP tools (listed below)
24
24
  - Write scene arrays, narration text, captions, and visual descriptions **in your context**
25
25
  - Write animation code in `edit.js` inside a **scaffolded project directory** (e.g. `.frameforge-files/my-animation/edit.js`)
26
26
  - Read files inside `.frameforge-files/` to inspect rendered output
@@ -148,9 +148,15 @@ validate_storyboard({ storyboardPath: ".frameforge-files/my-animation/STORYBOARD
148
148
 
149
149
  **Step 4 — Write `edit.js`** (the one file you may write in an animation project):
150
150
  - Read `ANIMATION_GUIDE.md` in the project folder first
151
+ - Also read `references/animation-patterns.md` — contains ClaudeAnimationBase 12fps boil, onetake continuous camera, and collage halftone patterns
152
+ - Also read `references/motion-craft.md` — 10 hard motion craft rules (springs, 5-layer stack, exits faster, continuous life)
153
+ - Also read `references/film-styles.md` — 12 cinematic styles (anamorphic, cyberpunk, anime, lofi, broadcast news...)
151
154
  - Every style must be a **pure function of `t`**
152
155
  - Use `layer('name').on(t => ({ ...styles }))` for each scene
153
156
  - Sync animation to narration using `cuePhrase('the exact words spoken')` — this reads `voice_0.captions.json` and returns the frame when those words start. **The build fails if the phrase isn't found**, so re-recording VO can never silently desync the animation.
157
+ - **12fps organic boil** (ClaudeAnimationBase): `const step = Math.floor(lt * 12); const bx = Math.sin(seed * 19.37 + step * 2.41) * 2.4;` — never `Math.random()` inside render loop
158
+ - **SFX cues** (earshot): `cue('whoosh', t, 0.8)` in edit.js — registered in `window.__cues` for render.mjs to read back during audio mix
159
+ - **Onetake camera**: place all scenes on one 2.5D spatial canvas, spring-interpolate the camera between them instead of cutting
154
160
 
155
161
  **Step 5 — Pre-flight, then stills, then full render:**
156
162
  ```
@@ -167,14 +173,68 @@ render_animation({ projectDir: ".frameforge-files/my-animation/", mode: "full",
167
173
  - One `strip` per key motion or transition
168
174
  - One `crop` per story-carrying face or detail
169
175
 
170
- **Step 6 — Optional: hook variants**
176
+ **Step 5b — Closed-Loop QA Fix Protocol (mandatory after full render)**
177
+
178
+ After `full` render, run the quality gate:
179
+ ```
180
+ render_animation({ projectDir: ".frameforge-files/my-animation/", mode: "quality" })
181
+ ```
182
+ Returns `{ passed, overallScore, worstFrames: [{time, score, issues}], motionDelta }`.
183
+
184
+ - **`passed: true`** → continue to Step 6.
185
+ - **`passed: false`** → enter the fix loop (max 3 rounds):
186
+
187
+ ```
188
+ Round N (repeat until passed or 3 rounds exhausted):
189
+ 1. Read worstFrames[] — note timestamps and issue descriptions.
190
+ 2. Open edit.js. Fix ONLY the code paths that affect those timestamps.
191
+ Common issues and fixes:
192
+ - "Blank frame" → layer is returning opacity: 0 when it shouldn't; check lt bounds
193
+ - "Stuck motion" → two frames have identical hashes; motion formula may be constant
194
+ - "Corner-confined" → element x/y is outside safe zone; move to centre stage
195
+ - "Blown frame" → background colour too bright; switch to #0c1116–#111827 range
196
+ - "Low contrast" → scene is too dark; raise ambient layer brightness
197
+ 3. Run: render_animation({ mode: "strip", timestamps: [t-0.5, t+0.5] })
198
+ for each failing timestamp to verify the fix visually.
199
+ 4. Run: render_animation({ mode: "quality" }) again.
200
+ 5. If passed: true → done. If still failing → next round.
201
+
202
+ After 3 rounds without passing: stop, report worstFrames to user, do not re-render full film.
203
+ ```
204
+
205
+ **Never re-render the full film to fix a single failing timestamp.** Use `strip` on the
206
+ failing time range only. This is the Claude Code + Opus 5.5 closed-loop correction pattern:
207
+ render → score worst 3 frames → patch edit.js → re-strip → re-score → ship.
208
+
209
+ **Step 5c — Motion-blur pass (optional, high-quality reels)**
210
+
211
+ For fast morphs or kinetic reveals that show ghost copies at standard render:
212
+ ```
213
+ render_animation({ projectDir: "...", mode: "full", subframes: 6, audioPath: "..." })
214
+ ```
215
+ `subframes: 6` = 180° shutter — renders 6 frames per output frame, blends them. Adds ~6× render
216
+ time. Only needed when fast-moving elements look strobed. Standard renders use `subframes: 1`.
217
+
218
+ **Step 6 — Model effort guide (Opus 5.5 / Claude Code)**
219
+
220
+ | Stage | `effort` | Why |
221
+ |-------|----------|-----|
222
+ | Beat sheet + storyboard authorship | `xhigh` | New creative work — max reasoning |
223
+ | First-time scene code authorship | `xhigh` | New composition, determinism critical |
224
+ | Storyboard gate review / patch | `medium` | Analytical, not creative |
225
+ | Strip-range patch (fix failing frames) | `medium` | Targeted surgical fix |
226
+ | Encode-only / mux-only runs | `medium` | No creative decisions |
227
+
228
+ `tool_choice` must always be `auto` — Opus 5.5 does not support forced tool use.
229
+
230
+ **Step 7 — Optional: hook variants**
171
231
 
172
232
  For reels and Shorts, make 2–3 versions with different opening hooks:
173
233
  - Change only the first shot (0s–3s) in `edit.js`
174
234
  - `render_animation({ mode: "stills", timestamps: [0.0, 1.5, 3.0] })` to compare openings
175
235
  - Full render each variant, deliver as `hook_a.mp4`, `hook_b.mp4`, etc.
176
236
 
177
- **Step 7 — Optional: unattended / spend-capped batch**
237
+ **Step 8 — Optional: unattended / spend-capped batch**
178
238
  ```
179
239
  // run from projectDir
180
240
  python scripts/video_job.py submit --spec spec.json --max-usd 2.00
@@ -184,14 +244,18 @@ python scripts/video_job.py result --id <jobId>
184
244
  ```
185
245
  Each step only starts if the running cost won't exceed `--max-usd`. Receipts go to `jobs/receipts.jsonl`.
186
246
 
187
- **Step 8 — Golden stills regression test (before any refactor)**
247
+ **Step 9 — Golden stills regression test (before any refactor)**
188
248
 
189
- After the video passes QC, save the test stills:
249
+ After the video passes QC, save the 4-keyframe golden baseline:
250
+ ```
251
+ render_animation({ projectDir, mode: "golden", goldenSave: true })
252
+ // → writes out/check/golden.json with SHA-256 hashes for 4 keyframes
190
253
  ```
191
- render_animation({ projectDir, mode: "storyboard" }) // 4 keyframes, file to out/storyboard.jpg
192
- // → copy out/storyboard.jpg to test/golden/storyboard.jpg
254
+ Before future refactors, run the check:
255
+ ```
256
+ render_animation({ projectDir, mode: "golden", goldenCheck: true })
257
+ // → fails if any keyframe hash has drifted (refactor broke determinism)
193
258
  ```
194
- Before future refactors, re-run and compare. If pixels shift, the refactor broke determinism.
195
259
 
196
260
  > Requires one-time setup in the project directory: `npm install playwright && npx playwright install chromium`
197
261
 
@@ -210,7 +274,7 @@ get_job_status({ jobId }) // poll every 30s until status = "SUCCEEDED"
210
274
 
211
275
  ---
212
276
 
213
- ## ALL 18 MCP TOOLS
277
+ ## ALL 28 MCP TOOLS
214
278
 
215
279
  **Primary — code-driven animation (no LLM key, no image gen API):**
216
280
 
@@ -236,6 +300,28 @@ get_job_status({ jobId }) // poll every 30s until status = "SUCCEEDED"
236
300
  | `generate_scene_image` | Generate one scene image |
237
301
  | `publish_video` | Deliver via file copy or HTTP webhook |
238
302
 
303
+ **Media ingestion (yt-dlp & Whisper):**
304
+
305
+ | Tool | What it does |
306
+ |------|-------------|
307
+ | `ingest_url` | Download video/audio from any web URL (YouTube, Vimeo, Twitter/X, TikTok, 1000+ sites) via yt-dlp |
308
+ | `transcribe_media` | Transcribe speech with Whisper — word-level timestamps (NDJSON for `cuePhrase()`), SRT subtitles, pause detection |
309
+
310
+ **Professional audio post-production:**
311
+
312
+ | Tool | What it does |
313
+ |------|-------------|
314
+ | `mix_audio_pro` | 15+ year sound engineer chain: noise gate → 80Hz HPF → EQ → de-esser → compressor → room acoustics (5 profiles) → sidechain duck → stereo widen → 13-type SFX library (earshot) → two-pass EBU R128 loudnorm. Platform presets: youtube/podcast/broadcast/netflix/instagram. |
315
+
316
+ **Editing & planning:**
317
+
318
+ | Tool | What it does |
319
+ |------|-------------|
320
+ | `edit_video` | Autonomous local editor — cut, trim, speed-ramp, color-grade (24 presets incl. lemo-opuscar styles), reframe, captions, transitions (35+), audio mix |
321
+ | `plan_video_edit` | Plan/Approve/Render workflow — generates `edit-plan.md` + `edit.json`. Styles: cinematic / fast_paced / documentary / vintage / cyberpunk / editorial_collage / anime_action / cinematic_anamorphic / broadcast_news / film_16mm / product_obsidian / retro_vhs_80s and more |
322
+ | `preview_scene` | Render still frames of a scene HTML/code for visual inspection |
323
+ | `verify_scene_quality` | Closed-loop QA gate: 1–10 score on 4 axes (content, exposure, layout, motion delta) |
324
+
239
325
  **Auto-research (needs a free LLM key):**
240
326
 
241
327
  | Tool | What it does |
@@ -245,6 +331,103 @@ get_job_status({ jobId }) // poll every 30s until status = "SUCCEEDED"
245
331
  | `queue_full_pipeline` | Queue a full pipeline run; returns `{ jobId }` |
246
332
  | `get_job_status` | Poll a queued job for status |
247
333
 
334
+ **Upstream skills maintenance:**
335
+
336
+ | Tool | What it does |
337
+ |------|-------------|
338
+ | `sync_upstream_skills` | Check & merge updates from 9 reference repos (HyperFrames, Earshot, Remotion, OneTake, lemo-opuscar, gbro-collage-broll, ClaudeAnimationBase, ffmpeg-skill). Makes GitHub API requests to fetch new commits. Returns `{ updatedRepos, perCategoryUpdates }` with `userImpact` and `capabilities[]` per changed repo. |
339
+ | `check_upstream_updates` | Fast offline check — reads the local manifest without any network requests. Shows last sync timestamp, per-repo SHA, and which repos have been synced. Use this for a quick status check; use `sync_upstream_skills` to actually fetch new commits. |
340
+
341
+ ---
342
+
343
+ ## PROFESSIONAL AUDIO WORKFLOW
344
+
345
+ ### Whisper transcription → word-level caption sync
346
+
347
+ ```
348
+ // Step 1: Generate TTS
349
+ multi_voice_tts({ text: "Your narration.", outputPath: ".frameforge-files/voice_0.m4a" })
350
+
351
+ // Step 2: Transcribe for exact word timestamps (requires: pip install openai-whisper)
352
+ transcribe_media({
353
+ mediaPath: ".frameforge-files/voice_0.m4a",
354
+ model: "base", // tiny|base|small|medium|large
355
+ format: "all", // writes .ndjson (for captions()) + .srt + .json
356
+ })
357
+ // → returns: { outputs: { ndjson: "...", srt: "...", json: "..." }, pauses: [...] }
358
+
359
+ // Step 3: Load in edit.js for word-sync captions
360
+ // captions('audio/outline.txt'); ← use the ndjson output path
361
+ // cuePhrase("your words here"); ← returns exact timestamp from transcript
362
+ ```
363
+
364
+ ### yt-dlp media ingestion
365
+
366
+ ```
367
+ // Download YouTube video for B-roll
368
+ ingest_url({ url: "https://youtube.com/watch?v=...", format: "video" })
369
+ // → returns: { localPath: "...", duration: 45.2, width: 1920, height: 1080 }
370
+
371
+ // Download audio-only (podcast, music)
372
+ ingest_url({ url: "https://soundcloud.com/...", format: "audio" })
373
+ // → returns: { localPath: "...", duration: 180.5 }
374
+
375
+ // Then pass to any other tool
376
+ edit_video({ clips: [{ video_path: localPath, ... }] })
377
+ transcribe_media({ mediaPath: localPath, format: "srt" })
378
+ ```
379
+
380
+ ### Professional audio mix (15+ year sound engineer chain)
381
+
382
+ ```
383
+ mix_audio_pro({
384
+ voicePath: ".frameforge-files/voice_0.m4a",
385
+ outputPath: ".frameforge-files/audio_pro.m4a",
386
+ musicPath: "/path/to/bg-music.mp3", // optional — will be sidechain ducked
387
+ platform: "youtube", // youtube (-14) | podcast (-16) | broadcast (-23) | netflix (-27) | instagram
388
+ roomProfile: "cinematic", // studio_dry | broadcast | cinematic | concert_hall | intimate
389
+ noiseGate: true, // remove breath noise between words (field recordings)
390
+ stereoWiden: true, // M/S expansion 1.4x on music layer
391
+ sfxCues: [ // 13-type earshot procedural SFX library
392
+ { name: "whoosh", time: 2.5, volume: 0.8 }, // camera translation (40ms perceptual lead)
393
+ { name: "impact", time: 8.0, volume: 1.0 }, // title punch
394
+ { name: "pop", time: 12.3, volume: 0.6 }, // badge reveal
395
+ { name: "riser", time: 18.0, volume: 0.7 }, // build-up before climax
396
+ { name: "chime", time: 25.5, volume: 0.5 }, // success / completion
397
+ { name: "deep_boom",time: 30.0, volume: 0.9 }, // cinematic reveal
398
+ { name: "sparkle", time: 35.2, volume: 0.4 }, // aha moment
399
+ // Also: click | buzz | tick | swish | punch | transition
400
+ ],
401
+ // videoPath: ".frameforge-files/animation.mp4" // optional: mux directly into video
402
+ })
403
+ // Returns: { outputPath, measuredLufs, measuredTp, platform, passed, chain: { noiseGate, hpf, presenceBoost,
404
+ // airShelf, deEsser, compressor, roomAcoustics, sidechainDuck, stereoWiden, sfxCues, masterBus } }
405
+ ```
406
+
407
+ **Full signal chain** (in order):
408
+ 1. Noise gate (agate -60dBFS) — removes breath/room tone between words
409
+ 2. 80Hz HPF — removes proximity effect and desk rumble
410
+ 3. Presence +2dB@5kHz — adds speech intelligibility
411
+ 4. Air shelf +1.5dB@12kHz — adds breathiness/openness
412
+ 5. 3:1 compressor @ -20dBFS, 5ms attack, 50ms release
413
+ 6. De-esser 6.5kHz dynamic (-3dB) — removes "s/sh/ch" harshness
414
+ 7. Room acoustics (selected profile) — 0.1–0.55s RT60 reverb tail
415
+ 8. Sidechain ducking — music ducks -18dB when voice is active (40ms perceptual lead)
416
+ 9. Stereo widener — M/S extrastereo 1.4x on music layer (voice stays mono-center)
417
+ 10. SFX timeline — procedural 13-type library, millisecond-accurate placement
418
+ 11. Two-pass EBU R128 loudnorm — platform-aware LUFS target
419
+
420
+ ### Upstream skills auto-update
421
+
422
+ Run this at the start of any session to get the latest motion craft rules, film styles,
423
+ camera techniques, and audio presets from all 9 reference repositories:
424
+
425
+ ```
426
+ sync_upstream_skills({})
427
+ // → If repos have new commits: returns updatedRepos[] and a visible update notice
428
+ // → Set SKILL_UPDATE_WEBHOOK_URL in .env for POST callback notifications
429
+ ```
430
+
248
431
  ---
249
432
 
250
433
  ## VOICE — VoxForge custom audio
package/README.md CHANGED
@@ -4,14 +4,14 @@
4
4
 
5
5
  ### AI Video Production Engine for Any Agentic IDE
6
6
 
7
- **Any IDE. Any topic. Any style. 1080p videos from a single prompt.**
7
+ **Any IDE. Any topic. Any style. Broadcast-quality videos from a single prompt.**
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/@amg555/frameforge-mcp.svg?label=npm)](https://www.npmjs.com/package/@amg555/frameforge-mcp)
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
11
11
  [![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
12
- [![Version](https://img.shields.io/badge/version-2.3.8-blue.svg)](CHANGELOG.md)
12
+ [![Version](https://img.shields.io/badge/version-2.7.0-blue.svg)](CHANGELOG.md)
13
13
  [![MCP Spec](https://img.shields.io/badge/MCP-2024--11--05-blue.svg)](https://modelcontextprotocol.io/)
14
- [![Tests](https://img.shields.io/badge/tests-539%20passing-brightgreen.svg)](#testing)
14
+ [![Tests](https://img.shields.io/badge/tests-636%20passing-brightgreen.svg)](#testing)
15
15
 
16
16
  </div>
17
17
 
@@ -19,6 +19,8 @@
19
19
 
20
20
  FrameForge is an MCP server your IDE agent calls to make videos. You (or your agent) write the scenes — FrameForge handles voice, images, FFmpeg compositing, and quality checking. Works in Bob, Cursor, Windsurf, Codex, opencode, Claude Code, and any MCP-capable IDE.
21
21
 
22
+ **28 MCP tools.** Includes Whisper transcription, yt-dlp media ingestion, broadcast-grade audio post-production (EQ + de-esser + SFX synthesis + room acoustics), and auto-updating motion craft from 9 frontier video repositories.
23
+
22
24
  ---
23
25
 
24
26
  ## Zero-install quickstart (npx)
@@ -52,7 +54,23 @@ Add to your IDE's MCP config (works in Bob, Cursor, Windsurf, Codex, Claude Code
52
54
  }
53
55
  ```
54
56
 
55
- That's it. Your agent now has 19 video production & autonomous editing tools. FFmpeg and TTS run on your machine — no cloud render costs.
57
+ That's it. Your agent now has 28 video production & autonomous editing tools. FFmpeg and TTS run on your machine — no cloud render costs.
58
+
59
+ ### Standalone CLI Commands (no IDE required)
60
+
61
+ ```bash
62
+ # Ingest any web clip or audio via yt-dlp
63
+ npx --package=@amg555/frameforge-mcp frameforge download "https://youtube.com/watch?v=..." --subtitles
64
+
65
+ # Transcribe speech with word-level timestamps & SRT via Whisper
66
+ npx --package=@amg555/frameforge-mcp frameforge transcribe ./narration.mp3 --format all
67
+
68
+ # Sync upstream techniques from 9 frontier video repositories
69
+ npx --package=@amg555/frameforge-mcp frameforge sync
70
+
71
+ # Diagnostics and system check
72
+ npx --package=@amg555/frameforge-mcp frameforge doctor
73
+ ```
56
74
 
57
75
  ---
58
76
 
@@ -174,7 +192,7 @@ Any combination of `image_path`, `video_path`, `audio_path` works — FrameForge
174
192
 
175
193
  ## Tools
176
194
 
177
- 19 tools, grouped by what you're doing:
195
+ 28 tools, grouped by what you're doing:
178
196
 
179
197
  **Make a video from your own script (no LLM key)**
180
198
 
@@ -192,6 +210,20 @@ Any combination of `image_path`, `video_path`, `audio_path` works — FrameForge
192
210
  | `publish_video` | Deliver the finished video via file copy or HTTP webhook |
193
211
  | `external_platform_call` | Bridge to ElevenLabs, Runway, VoxForge, or local FFmpeg editor fallback |
194
212
  | `export_to_editor` | Bridge/import into DaVinci Resolve, Premiere Pro, After Effects, Remotion, or CapCut |
213
+ | `plan_video_edit` | Plan/Approve/Render: analyze footage, generate `edit-plan.md` + `edit.json` with rationale per cut |
214
+
215
+ **Media ingestion (yt-dlp & Whisper)**
216
+
217
+ | Tool | What it does |
218
+ |------|-------------|
219
+ | `ingest_url` | Download video/audio from YouTube, Vimeo, Twitter/X, TikTok, and 1000+ sites via yt-dlp |
220
+ | `transcribe_media` | Whisper transcription with word-level timestamps → NDJSON (for `cuePhrase()`), SRT, JSON |
221
+
222
+ **Professional audio post-production**
223
+
224
+ | Tool | What it does |
225
+ |------|-------------|
226
+ | `mix_audio_pro` | Broadcast-grade chain: HPF → EQ → de-esser → compressor → reverb → duck → stereo widen → SFX synthesis → two-pass EBU R128 |
195
227
 
196
228
  **Auto-research pipeline (needs a free LLM key)**
197
229
 
@@ -208,7 +240,16 @@ Any combination of `image_path`, `video_path`, `audio_path` works — FrameForge
208
240
  |------|-------------|
209
241
  | `scaffold_animation_project` | Create a project where every frame is a pure function of time `t` |
210
242
  | `validate_storyboard` | Check `STORYBOARD.md` against the 4-gate beat-sheet contract |
211
- | `render_animation` | Run the Playwright renderer: sheet / strip / storyboard / crop / full |
243
+ | `render_animation` | Run the Playwright renderer: sheet / strip / storyboard / crop / full / quality / golden |
244
+ | `preview_scene` | Render still frames of a scene HTML/code for visual inspection before full render |
245
+ | `verify_scene_quality` | Closed-loop visual QA gate: 1–10 score on content, exposure, layout, and motion delta |
246
+
247
+ **Upstream skills**
248
+
249
+ | Tool | What it does |
250
+ |------|-------------|
251
+ | `sync_upstream_skills` | Fetch latest commits from 9 reference repos and update local manifest. Returns per-category update summary with `userImpact` and affected tools. |
252
+ | `check_upstream_updates` | Fast offline read of local manifest — shows last sync time, per-repo SHA, and sync status without any network requests. |
212
253
 
213
254
  ---
214
255
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@amg555/frameforge-mcp",
3
- "version": "2.4.10",
4
- "description": "FrameForge — AI video production engine for agentic IDEs. npx @amg555/frameforge-mcp. FFmpeg + TTS run on your machine. 23 MCP tools.",
3
+ "version": "2.7.1",
4
+ "description": "FrameForge — AI video production engine for agentic IDEs. npx @amg555/frameforge-mcp. FFmpeg + TTS on your machine. 28 MCP tools. Whisper, yt-dlp, broadcast-grade audio, 13-type SFX library, 24 film styles, ClaudeAnimationBase full guide, onetake 39-move library + OM motion primitives, HyperFrames beat-grid, earshot forge DSP, J/L-cut editing, lemo-opuscar TREATMENT.md, upstream auto-update changelog.",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -19,6 +19,7 @@
19
19
  "harness": "node src/harness/bin/harness.mjs",
20
20
  "harness:doctor": "node src/harness/bin/harness.mjs doctor",
21
21
  "harness:verify": "node src/harness/bin/harness.mjs verify",
22
+ "skills:sync": "node src/skills/sync-upstream.js",
22
23
  "setup": "node src/cli/setup-keys.js",
23
24
  "setup:check": "node src/cli/setup-keys.js --check",
24
25
  "doctor": "node src/cli/doctor.js",
@@ -31,7 +32,7 @@
31
32
  "start:local-render": "cross-env RENDER_MODE=full WORKER_PORT=3211 node src/worker/server-render-free.js",
32
33
  "db:migrate": "node scripts/db-migrate.js",
33
34
  "validate": "node scripts/deep-validate.js",
34
- "test": "node --test src/pipeline/retry-policy.test.js src/pipeline/telemetry.test.js src/pipeline/artifact-manifest.test.js src/pipeline/artifact-retention.test.js src/pipeline/external-adapter.test.js src/workflows/publishing.test.js src/workflows/script.test.js src/workflows/ingest.test.js src/animation/animation-system.test.js src/fact-checker/review-gate.test.js src/fact-checker/checker.test.js src/utils/log-redaction.test.js src/worker/server-render-free.test.js src/worker/server.test.js src/mcp-server/server.test.js src/quality-gate/gate.test.js src/shorts-extractor/extractor.test.js src/audio-mixer/mixer.test.js src/video-renderer/scene-animator.test.js src/video-renderer/renderer.test.js src/video-editor/editor.test.js plugins/video-pipeline/skills/video-pipeline/assets/project/reel/engine.test.js src/harness/lib/pixels.test.js src/harness/lib/verify-purity.test.js src/harness/lib/verify-quality.test.js src/harness/harness.test.js src/integration.test.js",
35
+ "test": "node --test --test-concurrency=2 src/pipeline/retry-policy.test.js src/pipeline/telemetry.test.js src/pipeline/artifact-manifest.test.js src/pipeline/artifact-retention.test.js src/pipeline/external-adapter.test.js src/workflows/publishing.test.js src/workflows/script.test.js src/workflows/ingest.test.js src/animation/animation-system.test.js src/fact-checker/review-gate.test.js src/fact-checker/checker.test.js src/utils/log-redaction.test.js src/utils/media-downloader.test.js src/utils/transcribe.test.js src/worker/server-render-free.test.js src/worker/server.test.js src/mcp-server/server.test.js src/quality-gate/gate.test.js src/shorts-extractor/extractor.test.js src/audio-mixer/mixer.test.js src/video-renderer/scene-animator.test.js src/video-renderer/renderer.test.js src/video-editor/editor.test.js plugins/video-pipeline/skills/video-pipeline/assets/project/reel/engine.test.js src/harness/lib/pixels.test.js src/harness/lib/verify-purity.test.js src/harness/lib/verify-quality.test.js src/harness/harness.test.js src/integration.test.js",
35
36
  "lint": "echo 'No linter configured — add eslint for production'",
36
37
  "check-credentials": "node src/utils/log-redaction.js",
37
38
  "generate-assets": "node scripts/generate-initial-assets.js",
@@ -1,14 +1,20 @@
1
1
  {
2
2
  "name": "video-pipeline",
3
3
  "displayName": "FrameForge Video Pipeline",
4
- "version": "2.3.1",
4
+ "version": "2.7.0",
5
5
  "description": "End-to-end AI video production. IDE writes scenes → FrameForge renders. Or: scaffold a Playwright+ffmpeg code-driven animation. Or: auto-research and script the video.",
6
6
  "skills": [
7
7
  {
8
8
  "name": "video-pipeline",
9
9
  "path": "skills/video-pipeline/SKILL.md",
10
10
  "displayName": "Video Pipeline",
11
- "description": "17 MCP tools: create_video_from_script, scaffold_animation_project, render_animation, validate_storyboard, multi_voice_tts, ingest_media, edit_scenes, research_topic, write_script, queue_full_pipeline, and more."
11
+ "description": "28 MCP tools: create_video_from_script, edit_video, plan_video_edit, preview_scene, verify_scene_quality, scaffold_animation_project, render_animation, validate_storyboard, mix_audio_pro, transcribe_media, ingest_url, sync_upstream_skills, check_upstream_updates, and more."
12
+ },
13
+ {
14
+ "name": "html-renderer",
15
+ "path": "skills/html-renderer/SKILL.md",
16
+ "displayName": "HTML Renderer",
17
+ "description": "HTML-as-compositor rendering engine: pure function of time t, virtual clock, Playwright headless capture, and FFmpeg broadcast-standard encoding."
12
18
  }
13
19
  ],
14
20
  "mcpServer": {