diff --git a/.env.example b/.env.example index 2fe2e76..1ae8933 100644 --- a/.env.example +++ b/.env.example @@ -20,6 +20,10 @@ OLLAMA_MODEL=llama3.2 HIGGSFIELD_MCP_ACTIVE=true TOPVIEW_API_KEY= WAVESPEED_API_KEY= +# HyperFrames is a local HTML→MP4 renderer; no API key needed. +# Set HYPERFRAMES_ACTIVE=true once `npx hyperframes doctor` passes locally +# (Node >= 22, FFmpeg on PATH). See https://github.com/wesleysimplicio/hyperframes +HYPERFRAMES_ACTIVE=false # Publish + ads ADAPTLYPOST_API_KEY= diff --git a/.skills/hyperframes-cli/SKILL.md b/.skills/hyperframes-cli/SKILL.md new file mode 100644 index 0000000..173bd31 --- /dev/null +++ b/.skills/hyperframes-cli/SKILL.md @@ -0,0 +1,88 @@ +--- +name: hyperframes-cli +description: Runs the HyperFrames CLI dev loop — init, lint, inspect, preview, render — for compositions authored under the `hyperframes` skill. Invoked after the composition HTML is on disk and before the piece is marked complete. +version: 0.1.0 +upstream: https://github.com/wesleysimplicio/hyperframes +--- + +# HyperFrames CLI + +Wraps `npx hyperframes` for the marketing-engine pipeline. Requires Node.js >= 22 and FFmpeg on PATH (`npx hyperframes doctor` verifies). All commands run in DRY_RUN-safe mode by default — the lint/inspect passes have no external calls; only `render` writes an MP4. + +## When to invoke + +- Immediately after `hyperframes-prompt-builder` produces a project under `outputs////`. +- Whenever a composition needs validation before publish (`lint` + `inspect`). +- For local preview during iteration on a piece (`preview`). +- For the final render that produces the artefact picked up by the publish step (`render`). +- For environment troubleshooting when render fails (`doctor`, `browser`, `info`). + +## Inputs + +- `project_path`: string. Path to the HyperFrames project (must contain `index.html` and `composition.json`). +- `mode`: `"lint" | "inspect" | "preview" | "render" | "doctor"`. +- `render_opts`: object, optional, only for `mode = "render"`. Recognized keys: + - `fps`: 24 | 30 | 60 (default 30). + - `quality`: `"draft" | "standard" | "high"` (default `"standard"`; use `"draft"` while iterating). + - `format`: `"mp4" | "webm"` (default `"mp4"`). + - `variables`: object. JSON object keyed by variable id, overrides `data-composition-variables` defaults. + - `strict`: boolean. Maps to `--strict`. Default `true` in the pipeline — fail render on lint errors. + - `strict_variables`: boolean. Maps to `--strict-variables`. Default `true` for piece runs. + - `workers`: integer 1-8 or `"auto"`. Default `"auto"`. + - `output`: string. Output file path inside `outputs////`. + +## Process + +1. **Verify environment** on first run of a session: `npx hyperframes doctor`. Surface missing FFmpeg or Chrome as a hard block — do not attempt to render. +2. **Lint.** `npx hyperframes lint --json`. Treat all `error`-level findings as blockers. Warnings are surfaced to the orchestrator; let the operator decide. +3. **Inspect.** `npx hyperframes inspect --json`. Resolve any reported text overflow or canvas escape before render. If the overflow is intentional for an entrance/exit, mark the element with `data-layout-allow-overflow` (or the ancestor with `data-layout-ignore` for decorative elements) — do not silence the rule globally. +4. **Preview** (operator only). `npx hyperframes preview --port `. Hand back the **Studio project URL** (`http://localhost:/#project/`), not the source `index.html` path. +5. **Render.** `npx hyperframes render ` with the flags resolved from `render_opts`. Build the `--variables` argument from `render_opts.variables` using a single-line JSON string. Always pass `--strict` and `--strict-variables` for piece runs. +6. **Verify output.** After render, check the MP4 exists and is non-zero. Log to `data/video-usage.jsonl` with `{ ts, provider: "hyperframes", composition_id, render_args, duration_seconds, file_bytes, latency_ms }`. + +## Outputs + +- `lint`: `{ pass: boolean, errors: [...], warnings: [...] }`. +- `inspect`: `{ pass: boolean, findings: [...] }`. +- `render`: `{ artifact_path: string, duration_s: number, file_bytes: number, render_ms: number }`. +- `preview`: `{ url: string }`. + +## Command cheat sheet + +```bash +npx hyperframes init # scaffold (used once per piece by the prompt builder) +npx hyperframes lint # validate markup +npx hyperframes inspect # layout/overflow audit +npx hyperframes preview --port 3017 # local dev +npx hyperframes render \ + --fps 30 --quality standard --strict --strict-variables \ + --variables '{"leads":42,"delta_pct":12}' \ + --output outputs////final.mp4 +npx hyperframes doctor # environment check +npx hyperframes info # version/env details +``` + +## Non-negotiable rules + +- Never render without a passing `lint` and `inspect` pass. The pipeline has no recovery path for a malformed composition. +- Never silence a lint or inspect finding globally — fix the markup, or whitelist the specific element with `data-layout-allow-overflow` / `data-layout-ignore`. +- For pieces with declared variables, always pass `--strict-variables`. A typo in a variable id must fail loudly, not silently fall through to the default. +- For final-delivery renders, `--quality high`. For iteration loops, `--quality draft` to save compute. +- Asset preprocessing (`tts`, `transcribe`, `remove-background`) is **out of scope** for this skill — invoke them through a future `hyperframes-media` skill rather than inlining here. + +## Failure modes + +- `doctor` reports missing FFmpeg or Chrome: install via the project's setup instructions; do not work around. +- `render` fails with `unknown variable`: a key passed via `--variables` is not declared in `data-composition-variables`. Fix the markup or remove the override. +- `render` exceeds wall-time budget: drop `--quality` to `standard`, or split the composition into sub-compositions and parallelize via `--workers`. +- Output MP4 has zero bytes: re-run `doctor`; almost always a Chrome crash mid-capture. + +## Related skills + +- `hyperframes`: composition authoring rules; produces the project this skill validates and renders. +- `hyperframes-prompt-builder`: brief → composition spec; runs before this skill. +- `qa-tech-specs`: runs after this skill against the rendered MP4 to validate platform specs. + +## Upstream reference + +Full upstream skill (every flag, troubleshooting matrix, parametrized renders): https://github.com/wesleysimplicio/hyperframes/tree/main/skills/hyperframes-cli diff --git a/.skills/hyperframes-prompt-builder/SKILL.md b/.skills/hyperframes-prompt-builder/SKILL.md new file mode 100644 index 0000000..a0ee53c --- /dev/null +++ b/.skills/hyperframes-prompt-builder/SKILL.md @@ -0,0 +1,90 @@ +--- +name: hyperframes-prompt-builder +description: Translates a marketing-engine piece brief into the input shape the `hyperframes` skill expects (composition spec) and the flags the `hyperframes-cli` skill needs to render it. Selected by `video-prompt-builder` when the routing matrix resolves to the `hyperframes` provider. +version: 0.1.0 +--- + +# HyperFrames Prompt Builder + +Specialist that bridges the marketing-engine piece model (`brief`, `task_kind`, `provider_override`) and the HyperFrames composition contract. Mirrors `higgsfield-prompt-builder` and `topview-prompt-builder` in shape — same dispatcher, different target — so `video-prompt-builder` can swap providers without changing its own logic. + +## When to invoke + +- `video-prompt-builder` resolves the video provider to `hyperframes` for a piece. +- `task_kind` is one of `motion-typography`, `data-viz-reel`, `programmatic-short` (the hyperframes-native tasks in `PROVIDERS.md`). +- A piece declares `provider_override.video: hyperframes` in its frontmatter. +- An approved still (quote card from `gpt-image`, carousel from `topview`) is being promoted to motion and the type system must stay byte-faithful to the original. +- The orchestrator needs the same composition re-rendered with new variable values (weekly KPI reel, daily price update, A/B variant copy) without re-prompting an AI generator. + +## Inputs + +- `brief`: object. The piece brief with at least `headline`, `body?`, `cta?`, `aspect`, `duration_seconds`. +- `task_kind`: `"motion-typography" | "data-viz-reel" | "programmatic-short"`. +- `piece_path`: string, optional. Path to `.specs/pieces/.md`. Frontmatter may carry `provider_override`, `compliance_flags`, `variables`. +- `client_slug`: string. Used to load `.marketing-engine/clients//design.md` (or `clients//design.md` in the engine repo). +- `output_dir`: string. Where the project and final MP4 live (defaults to `outputs////`). +- `dry_run`: boolean, optional. When true, returns the composition spec and render args without invoking `hyperframes-cli`. + +## Process + +1. **Load brand context.** Read `clients//design.md` and resolve `{ colors, type_pairing, spacing_scale, brand_voice }`. If missing, refuse to proceed — surface the missing path. Brand violations cannot be fixed downstream. +2. **Resolve overrides.** If `piece_path` is set and frontmatter has `provider_override.video`, confirm it is `hyperframes`; otherwise this skill should not be running. +3. **Map task_kind to a composition template.** + - `motion-typography` → `kinetic-type` template, single scene, type-driven. + - `data-viz-reel` → `nyt-graph` template, body scene with declared numeric variables. + - `programmatic-short` → `play-mode` template, hook/body/cta, all client copy declared as variables. +4. **Declare variables.** Anything from the brief that could change per re-render (headline, body, KPI numbers, CTA, date stamp) goes into `variables` with explicit type + label + default. Hardcoded copy is forbidden when a variable would work. +5. **Build the composition spec** in the shape `hyperframes` expects: `{ composition_id, aspect, duration_seconds, scenes, design_tokens, variables, assets, output_dir }`. Compute `composition_id` from `` (slug-safe). +6. **Build the render args** in the shape `hyperframes-cli` expects: `{ project_path, mode: "render", render_opts: { fps, quality, format, variables, strict: true, strict_variables: true, output } }`. Pick `quality: "high"` for promoted pieces, `"draft"` for first-pass review. +7. **Cost estimate.** Local render — estimate from `duration_seconds × workers × $0.00` (zero out-of-pocket; report wall-time minutes as `latency_estimate_min` instead). +8. **Log the resolution** to `data/video-usage.jsonl` with `{ ts, provider: "hyperframes", piece_id, task_kind, composition_id, dry_run }`. +9. If `dry_run`, return without calling `hyperframes-cli`. Otherwise invoke `hyperframes` (to author the project) then `hyperframes-cli` (mode `lint` → `inspect` → `render`) in order. + +## Outputs + +- `provider_used`: `"hyperframes"`. +- `composition_spec`: object. The input passed to the `hyperframes` skill. +- `render_args`: object. The input passed to the `hyperframes-cli` skill (mode `render`). +- `expected_artifact`: string. The MP4 path that will exist after `render`. +- `latency_estimate_min`: number. Wall-time estimate for the render. +- `cost_estimate_usd`: 0 (local render; opex only). + +## Examples + +### Example 1: weekly KPI reel (`programmatic-short`) + +Input: `{ brief: { headline: "Semana 21 em números", aspect: "9:16", duration_seconds: 12 }, task_kind: "programmatic-short", client_slug: "saas-consultoria-imagem", piece_path: ".specs/pieces/2026-05-22-kpi.md" }` +Output: composition spec with `composition_id: "kpi-weekly-2026-05-22"`, three scenes (hook/body/cta), numeric variables (`leads`, `delta_pct`); render args with `--strict --strict-variables --quality high --variables '{"leads":42,"delta_pct":12}'`. + +### Example 2: motion quote card (`motion-typography`) + +Input: `{ brief: { headline: "Coloque a sua marca onde os olhos já estão.", aspect: "1:1", duration_seconds: 6 }, task_kind: "motion-typography", client_slug: "saas-consultoria-imagem" }` +Output: composition spec with a single kinetic-type scene, masked-text entrance, design tokens pulled from the active client's `design.md`; render args targeting `outputs/saas-consultoria-imagem///final.mp4`. + +### Example 3: provider override + +Input: a piece with `provider_override.video: hyperframes` whose `task_kind` is not in the matrix. +Output: still routed here, default `task_kind` to `programmatic-short`, log the fallback. + +## Non-negotiable rules + +- Never invent design tokens. Refuse to proceed if `design.md` is missing. +- Always declare per-piece copy as a `variable`, even when it looks static — the composition must be re-renderable without code edits. +- Always pass `--strict-variables` in the render args. A typo in a variable id is a hard fail. +- Never call `hyperframes-cli` directly bypassing the `lint → inspect → render` sequence. + +## Failure modes + +- Unknown `task_kind`: default to `programmatic-short`, log a warning, and continue. +- `design.md` missing: stop. Do not pick a palette; ask the operator to add the file. +- Brief includes a brand-prohibited claim (per `compliance-`): block before authoring; compliance runs upstream of render. +- HyperFrames CLI not installed: surface the install command (`npm i -g hyperframes` or `npx hyperframes@latest`) and stop. + +## Related skills + +- `hyperframes`: composition authoring rules (consumed by this skill). +- `hyperframes-cli`: lint/inspect/render execution (consumed by this skill). +- `video-prompt-builder`: dispatcher that selects this skill. +- `qa-tech-specs`: runs against the final MP4. +- `compliance-` / `compliance-generic`: runs against the resolved variables and the rendered artefact. +- `llm-router`: not used directly here, but may pick the LLM that drafts the headline/body before this skill assembles the composition spec. diff --git a/.skills/hyperframes/SKILL.md b/.skills/hyperframes/SKILL.md new file mode 100644 index 0000000..d78d6be --- /dev/null +++ b/.skills/hyperframes/SKILL.md @@ -0,0 +1,89 @@ +--- +name: hyperframes +description: Author HTML-as-source-of-truth motion compositions (kinetic type, motion quote cards, programmatic data-viz reels) for the HyperFrames renderer. Used whenever the video provider resolved by the routing matrix is `hyperframes`. +version: 0.1.0 +upstream: https://github.com/wesleysimplicio/hyperframes +--- + +# HyperFrames + +HyperFrames is an HTML → MP4 renderer (Apache 2.0). Compositions are plain HTML files with `data-start`, `data-duration`, `data-track-index` attributes; the renderer drives a headless Chrome through the timeline frame-accurately and pipes frames into FFmpeg. The skill `hyperframes-prompt-builder` is the marketing-engine dispatcher entry point; this skill carries the authoring rules. + +## When to invoke + +- A piece is routed (via `PROVIDERS.md` or a `provider_override.video: hyperframes` in the frontmatter) to the HyperFrames provider. +- Task is `motion-typography`, `data-viz-reel`, `programmatic-short`, or any composition that needs deterministic output from declared variables (e.g. weekly KPI reel that re-renders unchanged with new numbers). +- An approved still (quote card, carousel slide) needs to be promoted to a short motion piece without changing the typographic system. +- The orchestrator needs a re-renderable artefact: same composition, different `--variables`, byte-identical baseline. + +## Inputs + +- `composition_id`: string. Short slug used for the project directory and `data-composition-id`. +- `aspect`: `9:16` | `1:1` | `16:9` | `4:5`. +- `duration_seconds`: integer. Total composition length. +- `scenes`: array. Each `{ id, start_s, duration_s, role: "hook" | "body" | "cta", copy?, asset_ref? }`. +- `design_tokens`: object. Brand colors, primary/secondary type families, spacing scale. Sourced from `clients//design.md` when present. +- `variables`: array, optional. Declared parameters that callers can override at render time `{ id, type, label, default }`. +- `assets`: object, optional. `{ video?, audio?, images[] }` — local paths under the project. +- `output_dir`: string. Where the renderer writes the MP4 (defaults to `outputs////`). + +## Process + +1. **Read brand context first.** Load `clients//design.md` (or the design tokens passed in). Refuse to author HTML before tokens are known — fall back to the in-repo defaults only if the client has none. +2. **Plan the narrative arc** out loud (scenes, rhythm, transitions, beat) before writing markup. Hook in the first 1.5s, body, CTA at the tail. +3. **Layout before animation.** Write the final on-screen layout first — position elements where they end up. Animate *into* those positions with `gsap.from()`; only the final scene may use `gsap.to()` exits. +4. **Compose the HTML.** Root `` carries `data-composition-id`, `data-width`, `data-height`. Each clip carries `id`, `data-start`, `data-duration`, `data-track-index`. Parametrize with `data-composition-variables` (JSON array on ``); read at runtime with `window.__hyperframes.getVariables()`. +5. **Register every timeline paused.** `const tl = gsap.timeline({ paused: true }); window.__timelines[""] = tl;` — the framework drives playback. No infinite repeats, no `Math.random()`, no time-based logic, no async timeline construction. +6. **Transitions between every scene.** No jump cuts. Use the catalogued transitions (fade, wipe, masked, shader) listed in the upstream `references/transitions.md`. +7. **Video and audio.** `