mirror of
https://github.com/calesthio/OpenMontage.git
synced 2026-08-05 15:20:40 +08:00
Add taste direction governance
This commit is contained in:
@@ -143,7 +143,7 @@ Orthogonal to *runtime* is *authoring mode*: **how** the composition is built. P
|
||||
- **Templated** — assemble the stock `cut.type` scene-types (`text_card`, `stat_card`, `bar_chart`, …) into the `Explainer`/`CinematicRenderer` compositions. Fast, cheap, reliable — and the reason most videos look alike. Right for batch output, localization variants, quick drafts, and low-stakes internal clips.
|
||||
- **Atelier** — **hand-author the composition from scratch**: bespoke scenes, a one-off theme, and motion written for this piece, rendered via `composition_mode: "atelier"` (see `video_compose` → `_render_via_atelier`). No reusable creative components; a fresh visual language every time.
|
||||
|
||||
**Default to atelier for hero work** — marketing, launches, brand pieces, any single-deliverable explainer that must impress. The deciding rule: *reuse engine knowledge, never creative components.* In atelier mode the stock scene-type catalog, `hyperframes-registry` blocks, fixtures, and finished components are **off-limits** — they are frozen looks that reintroduce sameness. Before building, route through **`skills/meta/bespoke-composition.md`**, which sequences: art direction (`visual-style`) → motion principles (Disney 12 via `framer-motion`/`lottie-bodymovin`) → engine mechanics (`remotion-best-practices` + the stock components read *only as a mechanics codex*) → render via the atelier path. Close with a **distinctness review**: *could this be any other product's video? does it reuse a look I've made before?* — the inverse of "does it match the reference." Atelier costs more tokens and iteration than templated; say so at proposal so the user opts in knowingly.
|
||||
**Default to atelier for hero work** — marketing, launches, brand pieces, any single-deliverable explainer that must impress. The deciding rule: *reuse engine knowledge, never creative components.* In atelier mode the stock scene-type catalog, `hyperframes-registry` blocks, fixtures, and finished components are **off-limits** — they are frozen looks that reintroduce sameness. Before building, route through **`skills/meta/taste-direction.md`** to set the design read and taste dials, then **`skills/meta/bespoke-composition.md`**, which sequences: art direction (`visual-style`) → motion principles (Disney 12 via `framer-motion`/`lottie-bodymovin`) → engine mechanics (`remotion-best-practices` + the stock components read *only as a mechanics codex*) → render via the atelier path. Close with a **distinctness review**: *could this be any other product's video? does it reuse a look I've made before?* — the inverse of "does it match the reference." Atelier costs more tokens and iteration than templated; say so at proposal so the user opts in knowingly.
|
||||
|
||||
### Escalate Blockers Explicitly
|
||||
|
||||
@@ -630,10 +630,13 @@ Tool rules:
|
||||
| Playbook | Best For |
|
||||
|----------|----------|
|
||||
| `clean-professional` | Corporate, educational, SaaS |
|
||||
| `premium-minimalist` | Investor updates, expert explainers, product narratives |
|
||||
| `flat-motion-graphics` | Social media, TikTok, startups |
|
||||
| `minimalist-diagram` | Technical deep-dives, architecture |
|
||||
| `ink-sketch` (Ink Theater) | Hand-drawn ink-on-white doodle animation; a character that draws itself, walks, dances; contraption explainers |
|
||||
|
||||
For custom, atelier, brand, launch, or hero work, read `skills/meta/taste-direction.md` before choosing a playbook. Carry its `taste_profile` into the proposal so later stages can preserve the design read, visual variance, motion intensity, information density, reference strategy, and anti-patterns.
|
||||
|
||||
### Hand-drawn "doodle" animation → Ink Theater / Ink Puppet
|
||||
|
||||
For any brief that wants a **hand-drawn ink doodle** look — "a sketch that comes to life", "a pencil / stick figure that walks or dances", "a little character that acts out the idea", whiteboard-doodle explainers — use the **Ink Theater** engine + **Ink Puppet** mocap system (`skills/creative/ink-theater.md`, `ink-theater/README.md`). It is a **style + reusable engine, not a new pipeline**: illustration / contraption pieces run on the `animation` pipeline; a mocap character (draws itself → walks / dances / waves via `InkPuppet.choreograph([...])`) runs on `character-animation`. Cross-tool entry points: **`/ink-art`** (create a vector doodle from scratch) and **`/animated-drawing`** (animate a *supplied* drawing with mocap — raster; `skills/creative/animated-drawing.md`). Never hand-tune character motion — the agent only chooses named mocap clips.
|
||||
|
||||
@@ -164,6 +164,7 @@
|
||||
"type": "string",
|
||||
"description": "Required when composition_mode='atelier'. Short note (or path to art-direction.md) committing to a fresh visual language for THIS piece — palette, type, motion, signature device. Per skills/meta/bespoke-composition.md step 1, written down BEFORE authoring scenes."
|
||||
},
|
||||
"taste_profile": { "$ref": "#/$defs/taste_profile" },
|
||||
"music_source": {
|
||||
"type": "object",
|
||||
"description": "Resolved music plan from the proposal stage",
|
||||
@@ -331,5 +332,47 @@
|
||||
},
|
||||
"metadata": { "type": "object" }
|
||||
},
|
||||
"$defs": {
|
||||
"taste_profile": {
|
||||
"type": "object",
|
||||
"required": ["design_read", "visual_variance", "motion_intensity", "information_density"],
|
||||
"properties": {
|
||||
"design_read": {
|
||||
"type": "string",
|
||||
"description": "Brief-specific read of what the video should feel like and why."
|
||||
},
|
||||
"visual_variance": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 10,
|
||||
"description": "How much scenes may vary visually while still feeling coherent."
|
||||
},
|
||||
"motion_intensity": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 10,
|
||||
"description": "How energetic the motion language should be."
|
||||
},
|
||||
"information_density": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 10,
|
||||
"description": "How much information can be on screen at once."
|
||||
},
|
||||
"palette_discipline": { "type": "string" },
|
||||
"layout_variation": { "type": "string" },
|
||||
"reference_strategy": { "type": "string" },
|
||||
"anti_patterns": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"quality_gates": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
||||
@@ -159,6 +159,7 @@
|
||||
"items": { "type": "string" },
|
||||
"minItems": 1
|
||||
},
|
||||
"taste_profile": { "$ref": "#/$defs/taste_profile" },
|
||||
"chart_palette": {
|
||||
"description": "Ordered array of hex colors for chart data series.",
|
||||
"type": "array",
|
||||
@@ -238,6 +239,46 @@
|
||||
"highlight": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"taste_profile": {
|
||||
"type": "object",
|
||||
"required": ["design_read", "visual_variance", "motion_intensity", "information_density"],
|
||||
"properties": {
|
||||
"design_read": {
|
||||
"type": "string",
|
||||
"description": "Brief-specific read of what the video should feel like and why."
|
||||
},
|
||||
"visual_variance": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 10,
|
||||
"description": "How much scenes may vary visually while still feeling coherent."
|
||||
},
|
||||
"motion_intensity": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 10,
|
||||
"description": "How energetic the motion language should be."
|
||||
},
|
||||
"information_density": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 10,
|
||||
"description": "How much information can be on screen at once."
|
||||
},
|
||||
"palette_discipline": { "type": "string" },
|
||||
"layout_variation": { "type": "string" },
|
||||
"reference_strategy": { "type": "string" },
|
||||
"anti_patterns": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"quality_gates": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,6 +281,7 @@ Cross-cutting skills that apply to all pipelines:
|
||||
| Checkpoint Protocol | `meta/checkpoint-protocol.md` | When/how to checkpoint and request human approval |
|
||||
| Skill Creator | `meta/skill-creator.md` | Dynamically create new skills during pipeline runs |
|
||||
| Animation Runtime Selector | `meta/animation-runtime-selector.md` | Choose render runtime + animation library per scene |
|
||||
| Taste Direction | `meta/taste-direction.md` | Convert a brief into taste dials, anti-patterns, and reference strategy for proposal/playbook/atelier work |
|
||||
| Bespoke Composition (Atelier) | `meta/bespoke-composition.md` | Hand-author a composition from scratch (hero work) — no stock scene-types; routes art-direction → motion principles → engine mechanics → atelier render |
|
||||
|
||||
## Style Playbooks
|
||||
@@ -290,6 +291,7 @@ Style playbooks (`styles/*.yaml`) define visual language, typography, motion, au
|
||||
| Playbook | Category | Mood | Best For |
|
||||
|----------|----------|------|----------|
|
||||
| `clean-professional` | motion-graphics | polished, trustworthy | Corporate, educational, SaaS |
|
||||
| `premium-minimalist` | minimalist | calm, editorial | Investor updates, expert explainers, product narratives |
|
||||
| `flat-motion-graphics` | motion-graphics | energetic, bold | Social media, TikTok, startups |
|
||||
| `minimalist-diagram` | whiteboard | focused, technical | Technical deep-dives, architecture |
|
||||
|
||||
|
||||
@@ -43,7 +43,9 @@ Author in this order. Each step routes you to existing knowledge — do not skip
|
||||
|
||||
### 1. Commit to an art direction *for this subject* — the divergence engine
|
||||
Before writing any component, decide a visual language that fits **this** topic and no other.
|
||||
Use the **`visual-style`** Layer 3 skill (CREATE mode) to lock: palette, type personality,
|
||||
Read **`skills/meta/taste-direction.md`** first and write the `taste_profile`: the design read,
|
||||
`visual_variance`, `motion_intensity`, `information_density`, reference strategy, and
|
||||
anti-patterns. Then use the **`visual-style`** Layer 3 skill (CREATE mode) to lock: palette, type personality,
|
||||
motion character, layout system, and **one signature device** unique to this piece. Difference
|
||||
between videos is guaranteed here — not by withholding components, but by forcing a fresh
|
||||
direction each time. Write it down (a short `art-direction.md` in the project) and build to it.
|
||||
|
||||
@@ -59,6 +59,17 @@ If a style playbook is active, verify:
|
||||
|
||||
Each violation is a **suggestion** severity finding.
|
||||
|
||||
### Step 4b: Taste Direction Review
|
||||
|
||||
If `proposal_packet.production_plan.taste_profile` or the active playbook's `taste_profile` exists, verify:
|
||||
- [ ] `design_read` explains the brief, audience, and delivery promise; it is not just "modern/clean/professional"
|
||||
- [ ] `visual_variance`, `motion_intensity`, and `information_density` are reflected in scene layout, pacing, callout density, and asset prompts
|
||||
- [ ] `reference_strategy` is present when atelier work, AI image/video, product/brand visuals, or mood boards depend on visual nuance
|
||||
- [ ] Listed `anti_patterns` are actually avoided
|
||||
- [ ] Quality gates are concrete enough for the next stage to enforce
|
||||
|
||||
At proposal stage, a missing `taste_profile` is a **suggestion** for preset/low-stakes work and a **critical** finding for atelier, product/brand, launch, hero, or custom-playbook work. At scene_plan/edit/compose, treat dial violations as **suggestion** unless they break the approved delivery promise.
|
||||
|
||||
### Step 5: Evaluate Success Criteria
|
||||
|
||||
For each `success_criteria` item from the manifest:
|
||||
|
||||
126
skills/meta/taste-direction.md
Normal file
126
skills/meta/taste-direction.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Taste Direction - Meta Skill
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this before committing to visual identity, mood boards, proposal packets, custom playbooks, atelier composition, image reference batches, or brand-heavy videos.
|
||||
|
||||
This skill defines OpenMontage's video taste profile contract. Do not treat it as a frontend style recipe. The output is a compact video taste profile that travels through proposal, scene planning, asset prompts, edit, compose, and review.
|
||||
|
||||
## Output Contract
|
||||
|
||||
Write a `taste_profile` when the proposal or playbook needs a stronger creative contract:
|
||||
|
||||
```json
|
||||
{
|
||||
"design_read": "Premium expert explainer: calm authority, high trust, low ornament.",
|
||||
"visual_variance": 4,
|
||||
"motion_intensity": 3,
|
||||
"information_density": 5,
|
||||
"palette_discipline": "Neutral base, one accent, no decorative gradients.",
|
||||
"layout_variation": "Alternate editorial split frames with data-forward full-frame scenes.",
|
||||
"reference_strategy": "One reference still per scene family before asset generation.",
|
||||
"anti_patterns": ["generic AI-purple gradient backgrounds"],
|
||||
"quality_gates": ["Every scene should carry the design read without explanatory labels."]
|
||||
}
|
||||
```
|
||||
|
||||
`visual_variance`, `motion_intensity`, and `information_density` are 1-10 integer dials:
|
||||
|
||||
| Dial | Low | Mid | High |
|
||||
|------|-----|-----|------|
|
||||
| `visual_variance` | Tight system, repeated grammar | Pattern with purposeful scene families | Each beat may use a distinct visual mode |
|
||||
| `motion_intensity` | Calm holds, small transitions | Clear motion accents and reveals | Fast kinetic language, frequent directional changes |
|
||||
| `information_density` | One idea per frame | Main idea plus support detail | Dense dashboards, diagrams, or layered callouts |
|
||||
|
||||
## Process
|
||||
|
||||
### 1. Make a Design Read
|
||||
|
||||
Before choosing a playbook or palette, state what the video needs to feel like and why. Tie it to the audience, promise, platform, and subject matter.
|
||||
|
||||
Good reads are specific:
|
||||
|
||||
- "Investor-facing AI launch: precise, restrained, and credible; avoid hype visuals."
|
||||
- "Youth science short: bright, curious, and kinetic; make invisible physics feel tactile."
|
||||
- "Security incident explainer: tense and surgical; high contrast, low ornament, readable evidence."
|
||||
|
||||
Weak reads are only adjectives:
|
||||
|
||||
- "modern and clean"
|
||||
- "cinematic"
|
||||
- "professional"
|
||||
|
||||
### 2. Set the Three Dials
|
||||
|
||||
Pick `visual_variance`, `motion_intensity`, and `information_density` before writing concepts. These numbers should explain later choices:
|
||||
|
||||
- High motion plus low information means short kinetic beats, not dense diagrams.
|
||||
- Low motion plus high information means stable frames, chart builds, and long readable holds.
|
||||
- High variance means scene families need stronger anchors: recurring type, palette, framing, or sound motif.
|
||||
|
||||
### 3. Choose a Style Path
|
||||
|
||||
Use the dials to pick one of three paths:
|
||||
|
||||
| Path | Use When | Artifact |
|
||||
|------|----------|----------|
|
||||
| Existing playbook | A preset honestly matches the read | `production_plan.playbook` |
|
||||
| Custom playbook | The subject has its own visual world | generated `styles/<name>.yaml` with `taste_profile` |
|
||||
| Atelier art direction | Hero work needs a one-off language | `production_plan.art_direction` plus `taste_profile` |
|
||||
|
||||
Do not let preset availability override the design read. If the content calls for a custom visual world, write the custom playbook or art direction.
|
||||
|
||||
### 4. Plan References
|
||||
|
||||
If the work uses AI image/video, mood boards, brand assets, or atelier composition, create a reference strategy:
|
||||
|
||||
- Use one reference still per scene family or major beat.
|
||||
- Do not compress the whole direction into one mood board image.
|
||||
- For brand/product work, create or inspect a brand kit before asset generation.
|
||||
- For screen demos, inspect the real UI and write a redesign/audit note before styling overlays.
|
||||
|
||||
### 5. Carry the Profile Downstream
|
||||
|
||||
At proposal stage:
|
||||
|
||||
- Add `production_plan.taste_profile`.
|
||||
- Log style/playbook selection in `decision_log`.
|
||||
- Explain how the dials affect runtime, composition mode, and asset generation.
|
||||
|
||||
At scene planning:
|
||||
|
||||
- Vary layouts according to `visual_variance`.
|
||||
- Keep on-screen text and callouts within `information_density`.
|
||||
- Set transition families and camera movement from `motion_intensity`.
|
||||
|
||||
At assets:
|
||||
|
||||
- Include palette, texture, framing, and reference strategy in image/video prompts.
|
||||
- Generate reference stills before full batches when the profile depends on visual nuance.
|
||||
|
||||
At edit/compose:
|
||||
|
||||
- Match hold times and cut rhythm to the motion dial.
|
||||
- Avoid adding decorative overlays that violate the design read.
|
||||
|
||||
## Anti-Default Checklist
|
||||
|
||||
Flag these before moving forward:
|
||||
|
||||
- Generic AI-purple gradients or default corporate-blue visuals with no subject reason.
|
||||
- Same transition on every cut when `visual_variance` is 4 or higher.
|
||||
- Kinetic motion that makes narration harder to follow.
|
||||
- Dense callouts when `information_density` is 4 or lower.
|
||||
- Text-only slides unless the design read intentionally calls for typographic storytelling.
|
||||
- Mood boards that look attractive but do not map to concrete scene families.
|
||||
- Brand/product videos that never show or inspect the real brand/product surface.
|
||||
|
||||
## Review Hooks
|
||||
|
||||
Reviewer should check:
|
||||
|
||||
- Does `taste_profile.design_read` explain a real creative choice?
|
||||
- Do scene plans and edits respect the three dials?
|
||||
- Are anti-patterns actually avoided?
|
||||
- Is the reference strategy present when AI images/video or atelier work depends on visual nuance?
|
||||
- Could this video belong to any topic after replacing the title? If yes, the taste direction is too generic.
|
||||
@@ -46,6 +46,7 @@ A `render_runtime_selection` decision with only one option considered when both
|
||||
| Tool registry | `support_envelope()` output | What's actually available right now |
|
||||
| Cost tracker | `tools/cost_tracker.py` | Cost estimation data |
|
||||
| Style playbooks | `styles/*.yaml` | Available visual styles |
|
||||
| Meta skill | `skills/meta/taste-direction.md` | Design read, taste dials, reference strategy |
|
||||
| User input | Topic, any preferences expressed | Creative direction |
|
||||
|
||||
## Process
|
||||
@@ -121,6 +122,8 @@ Record all findings. **Do not propose an animation mode that requires tools you
|
||||
|
||||
This is the key differentiator from the explainer proposal. **Present the user with concrete animation approaches, explain what each looks like, what tools/keys they need, and what's already available.**
|
||||
|
||||
Before locking animation mode or visual identity, read `skills/meta/taste-direction.md` and write a `production_plan.taste_profile`. The three dials (`visual_variance`, `motion_intensity`, `information_density`) should explain whether the concept needs calm data builds, kinetic typography, dense diagrams, reference stills, or a custom/atelier visual system.
|
||||
|
||||
#### Step 3a: Tool Availability Scan
|
||||
|
||||
Before designing concepts, scan what's available and present it honestly. **Do NOT hardcode provider names, costs, or key names in this output** — they drift. Read them live from the registry:
|
||||
|
||||
@@ -40,6 +40,7 @@ A `render_runtime_selection` decision with only one option considered when both
|
||||
| Tool registry | `support_envelope()` output | What's actually available right now |
|
||||
| Cost tracker | `tools/cost_tracker.py` | Cost estimation data |
|
||||
| Style playbooks | `styles/*.yaml` | Available visual styles |
|
||||
| Meta skill | `skills/meta/taste-direction.md` | Design read, taste dials, reference strategy |
|
||||
| User input | Topic, any preferences expressed | Creative direction |
|
||||
|
||||
## Process
|
||||
@@ -175,6 +176,8 @@ Choose the structure that best fits the research findings:
|
||||
|
||||
The existing playbooks (`clean-professional`, `flat-motion-graphics`, `minimalist-diagram`) are starting points, not destinations. Most videos should get a **custom visual identity** derived from the subject matter, audience, and tone. A video about coffee should feel warm and tactile. A video about cybersecurity should feel technical and urgent. A video about marine biology should feel deep and fluid.
|
||||
|
||||
Before choosing or generating a playbook, read `skills/meta/taste-direction.md` and write a compact `production_plan.taste_profile`. The taste profile records the design read, `visual_variance`, `motion_intensity`, `information_density`, reference strategy, and anti-patterns. Use it to explain why the selected playbook, `composition_mode`, and asset strategy fit the brief.
|
||||
|
||||
**How to design visual identity:**
|
||||
|
||||
1. **Start from the content.** What colors does the subject naturally evoke? What textures, materials, lighting? A video about volcanoes should feel different from a video about meditation — in colors, motion speed, typography weight, and transition style.
|
||||
@@ -194,6 +197,7 @@ The existing playbooks (`clean-professional`, `flat-motion-graphics`, `minimalis
|
||||
|
||||
**Record your visual identity choices in the proposal_packet:**
|
||||
- `production_plan.playbook`: name of preset OR "custom"
|
||||
- `production_plan.taste_profile`: design read, taste dials, reference strategy, and anti-patterns
|
||||
- If custom, include color choices and font choices in the concept's `visual_approach`
|
||||
- Include the reasoning: "Warm amber palette because the subject is coffee craftsmanship"
|
||||
- Log as decision: `category: "playbook_selection"`
|
||||
|
||||
117
styles/premium-minimalist.yaml
Normal file
117
styles/premium-minimalist.yaml
Normal file
@@ -0,0 +1,117 @@
|
||||
identity:
|
||||
name: "Premium Minimalist"
|
||||
category: minimalist
|
||||
mood: calm, editorial, precise
|
||||
pace: deliberate
|
||||
best_for: "Investor updates, expert explainers, product narratives, high-trust launch videos"
|
||||
|
||||
taste_profile:
|
||||
design_read: "Premium expert explainer: calm authority, high trust, low ornament."
|
||||
visual_variance: 4
|
||||
motion_intensity: 3
|
||||
information_density: 5
|
||||
palette_discipline: "Off-white field, charcoal text, restrained cobalt accent, no decorative gradients."
|
||||
layout_variation: "Alternate editorial split frames, centered evidence frames, and full-bleed product/detail moments."
|
||||
reference_strategy: "Create one reference still for each scene family before batch asset generation."
|
||||
anti_patterns:
|
||||
- "generic corporate-blue template cards"
|
||||
- "decorative gradient backgrounds"
|
||||
- "fast kinetic transitions that reduce comprehension"
|
||||
quality_gates:
|
||||
- "Every frame should feel intentionally sparse, not unfinished."
|
||||
- "Motion should clarify hierarchy instead of decorating it."
|
||||
|
||||
visual_language:
|
||||
color_palette:
|
||||
primary: ["#111827", "#374151"]
|
||||
accent: ["#2563EB", "#0F766E"]
|
||||
background: "#F9FAFB"
|
||||
text: "#111827"
|
||||
muted: "#6B7280"
|
||||
composition: asymmetrical editorial grid with large margins, hard alignment, and one focal object per frame
|
||||
texture: flat matte fields, fine divider lines, subtle photographic grain only when source imagery needs cohesion
|
||||
|
||||
typography:
|
||||
headings:
|
||||
font: "Inter"
|
||||
weight: 700
|
||||
tracking: "-0.01em"
|
||||
body:
|
||||
font: "Inter"
|
||||
weight: 400
|
||||
line_height: 1.55
|
||||
code:
|
||||
font: "JetBrains Mono"
|
||||
weight: 400
|
||||
stat_card:
|
||||
font: "Inter"
|
||||
weight: 800
|
||||
size_multiplier: 3.2
|
||||
scale_system: "major_third"
|
||||
weight_matrix:
|
||||
title: 800
|
||||
heading: 700
|
||||
body: 400
|
||||
caption: 500
|
||||
|
||||
motion:
|
||||
transitions: [fade, dissolve, slide-left]
|
||||
animation_style: "restrained ease-out, precise reveal, no bounce"
|
||||
pacing_rules:
|
||||
min_scene_hold_seconds: 2.75
|
||||
max_scene_hold_seconds: 12
|
||||
text_card_hold_seconds: 3.75
|
||||
stat_card_hold_seconds: 3.25
|
||||
transition_duration_seconds: 0.45
|
||||
entrance: "fade-up 12px with opacity ramp"
|
||||
exit: "soft fade with slight y-offset"
|
||||
|
||||
audio:
|
||||
voice_style: "measured, expert, warm, low hype"
|
||||
music_mood: "minimal pulse, clean synth bed, quiet confidence"
|
||||
music_volume: 0.07
|
||||
sfx_style: "small tactile ticks and soft paper-like swishes"
|
||||
ducking_threshold_db: -4
|
||||
|
||||
asset_generation:
|
||||
image_prompt_prefix: "premium minimalist editorial frame, restrained palette, precise composition, generous negative space, "
|
||||
image_negative_prompt: "busy, glossy, decorative gradient, neon, cluttered, low contrast, generic corporate template"
|
||||
diagram_style: "thin-line editorial diagram, charcoal text, cobalt highlight, large margins"
|
||||
consistency_anchors:
|
||||
- "Off-white background with charcoal typography"
|
||||
- "Cobalt accent used only for hierarchy or proof points"
|
||||
- "Large margins and hard alignment"
|
||||
- "No decorative shapes unless they carry information"
|
||||
|
||||
overlays:
|
||||
stat_card:
|
||||
bg: "#FFFFFF"
|
||||
border: "#D1D5DB"
|
||||
radius: 6
|
||||
shadow: "0 1px 6px rgba(17,24,39,0.08)"
|
||||
key_term:
|
||||
bg: "#EFF6FF"
|
||||
text: "#1D4ED8"
|
||||
radius: 4
|
||||
code_block:
|
||||
bg: "#111827"
|
||||
text: "#F9FAFB"
|
||||
highlight: "#93C5FD"
|
||||
|
||||
quality_rules:
|
||||
- "Minimum contrast ratio 4.5:1 for all text"
|
||||
- "No more than 2 accent colors on screen at once"
|
||||
- "Keep one primary focal object or claim per frame"
|
||||
- "Use motion to reveal hierarchy, not to add energy"
|
||||
- "Avoid decorative gradients and oversized floating shapes"
|
||||
|
||||
chart_palette:
|
||||
- "#2563EB"
|
||||
- "#0F766E"
|
||||
- "#111827"
|
||||
- "#64748B"
|
||||
|
||||
color_rules:
|
||||
harmony_type: "analogous"
|
||||
contrast_validation: true
|
||||
colorblind_safe: true
|
||||
104
tests/contracts/test_taste_governance_contracts.py
Normal file
104
tests/contracts/test_taste_governance_contracts.py
Normal file
@@ -0,0 +1,104 @@
|
||||
"""Contract tests for taste-direction governance.
|
||||
|
||||
The taste-direction meta skill is an agent-facing contract: it must be easy to
|
||||
discover, and its output must fit the canonical proposal/style artifacts.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import jsonschema
|
||||
import yaml
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent.parent
|
||||
|
||||
|
||||
def _load_json(path: Path) -> dict:
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def _taste_profile() -> dict:
|
||||
return {
|
||||
"design_read": "Premium expert explainer: calm authority, high trust, low ornament.",
|
||||
"visual_variance": 4,
|
||||
"motion_intensity": 3,
|
||||
"information_density": 5,
|
||||
"palette_discipline": "Neutral base, one blue accent, no decorative gradients.",
|
||||
"layout_variation": "Alternate editorial split frames with data-forward full-frame scenes.",
|
||||
"reference_strategy": "One reference still per scene family before asset generation.",
|
||||
"anti_patterns": [
|
||||
"generic AI-purple gradient backgrounds",
|
||||
"reusing the same transition on every cut",
|
||||
],
|
||||
"quality_gates": [
|
||||
"Each scene carries the design read without needing explanatory labels.",
|
||||
"Motion stays purposeful and never outruns narration comprehension.",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def test_style_playbook_schema_accepts_taste_profile():
|
||||
schema = _load_json(ROOT / "schemas" / "styles" / "playbook.schema.json")
|
||||
assert "taste_profile" in schema["properties"]
|
||||
playbook = yaml.safe_load((ROOT / "styles" / "clean-professional.yaml").read_text(encoding="utf-8"))
|
||||
playbook["taste_profile"] = _taste_profile()
|
||||
|
||||
jsonschema.validate(instance=playbook, schema=schema)
|
||||
|
||||
|
||||
def test_proposal_packet_schema_accepts_taste_profile():
|
||||
schema = _load_json(ROOT / "schemas" / "artifacts" / "proposal_packet.schema.json")
|
||||
proposal = {
|
||||
"version": "1.0",
|
||||
"concept_options": [
|
||||
{
|
||||
"id": f"c{i}",
|
||||
"title": f"Concept {i}",
|
||||
"hook": "A precise hook under twenty words.",
|
||||
"narrative_structure": "problem_solution",
|
||||
"visual_approach": "Premium minimalist scenes with data-led visual proof.",
|
||||
"target_duration_seconds": 60,
|
||||
"why_this_works": "It ties the audience problem to a visible payoff.",
|
||||
}
|
||||
for i in range(1, 4)
|
||||
],
|
||||
"selected_concept": {"concept_id": "c1", "rationale": "Best fit for the brief."},
|
||||
"production_plan": {
|
||||
"pipeline": "animated-explainer",
|
||||
"stages": [{"stage": "proposal", "tools": [], "approach": "Plan the production."}],
|
||||
"render_runtime": "remotion",
|
||||
"taste_profile": _taste_profile(),
|
||||
},
|
||||
"cost_estimate": {
|
||||
"total_estimated_usd": 0,
|
||||
"line_items": [],
|
||||
"budget_verdict": "no_budget_set",
|
||||
},
|
||||
"approval": {"status": "pending"},
|
||||
}
|
||||
|
||||
jsonschema.validate(instance=proposal, schema=schema)
|
||||
|
||||
|
||||
def test_taste_direction_is_discoverable_to_new_agents():
|
||||
skill_path = ROOT / "skills" / "meta" / "taste-direction.md"
|
||||
assert skill_path.is_file(), "Missing Layer 2 taste-direction meta skill"
|
||||
|
||||
index = (ROOT / "skills" / "INDEX.md").read_text(encoding="utf-8")
|
||||
assert "Taste Direction" in index
|
||||
assert "meta/taste-direction.md" in index
|
||||
|
||||
guide = (ROOT / "AGENT_GUIDE.md").read_text(encoding="utf-8")
|
||||
assert "taste-direction.md" in guide
|
||||
|
||||
|
||||
def test_premium_minimalist_playbook_exists_and_validates():
|
||||
from styles.playbook_loader import load_playbook, list_playbooks
|
||||
|
||||
assert "premium-minimalist" in list_playbooks()
|
||||
playbook = load_playbook("premium-minimalist")
|
||||
assert playbook["taste_profile"]["motion_intensity"] <= 4
|
||||
assert playbook["taste_profile"]["information_density"] >= 4
|
||||
Reference in New Issue
Block a user