luckiest-co 1.0.27 → 1.0.29
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/skills/luckiest-ad-creative/CHANGELOG.md +3 -0
- package/skills/luckiest-ad-creative/SKILL.md +5 -3
- package/skills/luckiest-brandkit/ATTRIBUTION.md +8 -0
- package/skills/luckiest-brandkit/CHANGELOG.md +26 -0
- package/skills/luckiest-brandkit/SKILL.md +173 -0
- package/skills/luckiest-brandkit/references/picks-and-review.md +48 -0
- package/skills/luckiest-brandkit/references/prompt-recipes.md +79 -0
- package/skills/luckiest-brandkit/scripts/composite_mark.py +36 -0
- package/skills/luckiest-brandkit/scripts/composite_screen.py +37 -0
- package/skills/luckiest-brandkit/scripts/contact_sheet.py +31 -0
- package/skills/luckiest-brandkit/scripts/make_refs.mjs +25 -0
- package/skills/luckiest-plan/SKILL.md +2 -0
- package/skills/luckiest-video/CHANGELOG.md +3 -0
- package/skills/luckiest-video/SKILL.md +5 -3
- package/skills/luckiest-video-studio/CHANGELOG.md +10 -0
- package/skills/luckiest-video-studio/SKILL.md +14 -3
- package/skills/luckiest-video-studio/references/step-2b-storyboard.md +17 -5
- package/skills/luckiest-video-studio/references/step-3-compose.md +12 -0
- package/skills/luckiest-video-studio-art-director/ATTRIBUTION.md +20 -0
- package/skills/luckiest-video-studio-art-director/CHANGELOG.md +28 -0
- package/skills/luckiest-video-studio-art-director/LICENSE-iart +21 -0
- package/skills/luckiest-video-studio-art-director/LICENSE-skillme +21 -0
- package/skills/luckiest-video-studio-art-director/SKILL.md +297 -0
- package/skills/luckiest-video-studio-cards/CHANGELOG.md +3 -0
- package/skills/luckiest-video-studio-cards/SKILL.md +5 -3
- package/skills/luckiest-video-studio-director/ATTRIBUTION.md +16 -0
- package/skills/luckiest-video-studio-director/CHANGELOG.md +18 -0
- package/skills/luckiest-video-studio-director/LICENSE-iart +21 -0
- package/skills/luckiest-video-studio-director/LICENSE-skillme +21 -0
- package/skills/luckiest-video-studio-director/SKILL.md +198 -0
- package/skills/luckiest-video-studio-director/scripts/breakdown.mjs +160 -0
- package/skills/luckiest-video-studio-recreate/CHANGELOG.md +3 -0
- package/skills/luckiest-video-studio-recreate/SKILL.md +6 -4
- package/skills/luckiest-video-studio-reel/CHANGELOG.md +3 -0
- package/skills/luckiest-video-studio-reel/SKILL.md +5 -3
- package/skills/luckiest-video-studio-script/CHANGELOG.md +3 -0
- package/skills/luckiest-video-studio-script/SKILL.md +8 -3
- package/skills/luckiest-video-studio-talk/CHANGELOG.md +3 -0
- package/skills/luckiest-video-studio-talk/SKILL.md +5 -3
package/package.json
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Changelog — luckiest-ad-creative
|
|
2
2
|
|
|
3
|
+
## 1.2.0 — 2026-10-05
|
|
4
|
+
- Video ads use the director and art director when installed.
|
|
5
|
+
|
|
3
6
|
## 1.1.1 — 2026-10-03
|
|
4
7
|
- Points at `luckiest-video-studio-composition` (when installed) for focal point, grid, white space, and safe areas.
|
|
5
8
|
|
|
@@ -3,7 +3,7 @@ name: luckiest-ad-creative
|
|
|
3
3
|
description: "Generates, iterates, and scales ad creative — headlines, descriptions, primary text, or full ad variations — for any paid advertising platform, and iterates from real performance data. Use when the user mentions 'ad copy variations,' 'ad creative,' 'generate headlines,' 'RSA headlines,' 'bulk ad copy,' 'ad iterations,' 'creative testing,' 'ad performance optimization,' 'write me some ads,' 'Facebook ad copy,' 'Google ad headlines,' 'LinkedIn ad text,' or 'I need more ad variations.' Use whenever someone needs to produce ad copy at scale or iterate on existing ads. For campaign strategy and targeting, see luckiest-ads. For landing page copy, see luckiest-copywriting."
|
|
4
4
|
license: See ATTRIBUTION.md
|
|
5
5
|
metadata:
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.2.0"
|
|
7
7
|
listing_id: luckiest-ad-creative
|
|
8
8
|
author: luckiest
|
|
9
9
|
---
|
|
@@ -14,9 +14,9 @@ This skill drives an expert performance creative strategist. The goal is to gene
|
|
|
14
14
|
|
|
15
15
|
## Staying current
|
|
16
16
|
|
|
17
|
-
On activation, call the Luckiest MCP check_updates tool with { listingId: "9ce2c363-e379-45f7-b7d2-c398992ed30f", installedSemver: "1.
|
|
17
|
+
On activation, call the Luckiest MCP check_updates tool with { listingId: "9ce2c363-e379-45f7-b7d2-c398992ed30f", installedSemver: "1.2.0" }. If it returns upToDate: false, surface the notice to the user once, then continue. Do nothing further if upToDate: true. Never block on this check — if the tool is unavailable, proceed.
|
|
18
18
|
|
|
19
|
-
When the skill's work is done, call the Luckiest MCP report_usage tool once with { listing_id: "luckiest-ad-creative", skill_version: "1.
|
|
19
|
+
When the skill's work is done, call the Luckiest MCP report_usage tool once with { listing_id: "luckiest-ad-creative", skill_version: "1.2.0", matched: true, success: <true if the skill completed, false otherwise> }. Metadata only, never prompt text. Never block on it — if the tool is unavailable, skip silently.
|
|
20
20
|
|
|
21
21
|
## Before Starting
|
|
22
22
|
|
|
@@ -152,6 +152,8 @@ For image and video ad creative, use generative AI tools and code-based video re
|
|
|
152
152
|
- **Platform image specs** — Correct dimensions for every ad placement
|
|
153
153
|
- **Cost comparison** — Pricing for 100+ ad variations across tools
|
|
154
154
|
|
|
155
|
+
**Video ads:** if the ad is a video and `luckiest-video-studio-director` is installed, use its insight and scored-angle steps to pick the concept and its five-beat shot list for the cut. If `luckiest-video-studio-art-director` is installed, lock the look with it before building.
|
|
156
|
+
|
|
155
157
|
**Composition:** if `luckiest-video-studio-composition` is installed, read it to place the focal point, pick the grid, and keep white space and platform safe areas. Check the headline, product, and CTA against the placement's safe area.
|
|
156
158
|
|
|
157
159
|
**Recommended workflow for scaled production:**
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Attribution
|
|
2
|
+
|
|
3
|
+
luckiest-brandkit is an original Luckiest skill. It is not adapted from a third-party skill.
|
|
4
|
+
|
|
5
|
+
It calls three other Luckiest skills at run time: luckiest-video-studio-art-director
|
|
6
|
+
(look and design-system rules), luckiest-video-studio-composition
|
|
7
|
+
(placement rules, itself adapted from iart.ai `shot-composition`, MIT) and
|
|
8
|
+
luckiest-upscale-image (Real-ESRGAN models from Upscayl). See their own ATTRIBUTION files.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog — luckiest-brandkit
|
|
2
|
+
|
|
3
|
+
## 1.0.0 — 2026-10-05
|
|
4
|
+
- New original Luckiest skill, built from a real 14-shot Luckiest brand mockup run.
|
|
5
|
+
- Pipeline: style block, composed prompt sheet (luckiest-video-studio-composition),
|
|
6
|
+
logo reference export, 3-shot approval batch, parallel generation, QA with
|
|
7
|
+
full-resolution text crops, real-logo fixes, local upscale, contact sheet.
|
|
8
|
+
- Scripts: `make_refs.mjs` (SVG to padded reference PNG via sips),
|
|
9
|
+
`composite_mark.py` (erase + multiply a real mark onto fabric or paper),
|
|
10
|
+
`composite_screen.py` (perspective-warp exact artwork onto a board or screen,
|
|
11
|
+
lit by the surface's own falloff), `contact_sheet.py`.
|
|
12
|
+
- Lessons baked in: no hex codes or UI labels in prompts, max two set planes as
|
|
13
|
+
leading lines, models draw custom symbols sideways so composite the real SVG,
|
|
14
|
+
one locked poster recipe per series, upscale loop that resumes.
|
|
15
|
+
- Sub-skills: the existing `luckiest-video-studio-art-director` (design system
|
|
16
|
+
first, rules with reasons, look lock; motion sections skipped for stills) and
|
|
17
|
+
`luckiest-video-studio-composition` (per-frame placement plus `frame_check.py`
|
|
18
|
+
on stills). Stills-specific art direction lives in `references/prompt-recipes.md`
|
|
19
|
+
(style skeleton, stills levers, poster recipe) and `references/picks-and-review.md`
|
|
20
|
+
(variant rejection, note-to-lever table, contact sheet review).
|
|
21
|
+
- Step 8: set review of the contact sheet before delivery.
|
|
22
|
+
- Network hook: offer to share the contact sheet with the tribe after delivery.
|
|
23
|
+
- Improve pass (/refract) and trend pass: not run. Original skill, scoped to the
|
|
24
|
+
pipeline as run. Trend pass: no actionable signal sought.
|
|
25
|
+
- Thumbnail: description matches "campaign"/"creative" and routes to the
|
|
26
|
+
`megaphone` scene in ListingThumbnail.jsx, not the hash fallback.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: luckiest-brandkit
|
|
3
|
+
description: >-
|
|
4
|
+
Produce a full set of photoreal brand mockups for a campaign or portfolio: merch
|
|
5
|
+
(hat, hoodie, tee), print (business cards, letterhead, posters, gift card, brand
|
|
6
|
+
book), devices, billboard, office signage, and a welcome kit, all in one shared art
|
|
7
|
+
direction with the brand's real logo. Writes one style block plus a composed prompt
|
|
8
|
+
per shot, exports the logo SVGs as reference images, runs a 3-shot test batch for
|
|
9
|
+
approval, generates the rest, fixes wrong logos and text by compositing the real
|
|
10
|
+
SVG or artwork, upscales, and delivers a contact sheet. Trigger on "brand mockups",
|
|
11
|
+
"product shots for my brand", "brand kit images", "mock up my logo on merch",
|
|
12
|
+
"billboard mockup", "poster mockups", "agency portfolio shots", "brand identity
|
|
13
|
+
presentation", or "/luckiest-brandkit". For one marketing image use luckiest-image.
|
|
14
|
+
For framing a single shot use luckiest-video-studio-composition.
|
|
15
|
+
argument-hint: "[shot list or brief] [--shots 01,04,06] [--out .luckiest/shots]"
|
|
16
|
+
user-invocable: true
|
|
17
|
+
allowed-tools: Bash, Read, Write, Edit, Glob, Grep
|
|
18
|
+
metadata:
|
|
19
|
+
version: "1.0.0"
|
|
20
|
+
listing_id: luckiest-brandkit
|
|
21
|
+
author: luckiest
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# Brand kit mockups
|
|
25
|
+
|
|
26
|
+
Turns a style brief and a shot list into a finished, consistent set of brand
|
|
27
|
+
mockups. The work happens in an image-generation MCP (any that exposes generate,
|
|
28
|
+
retouch-erase, and file upload), plus four local scripts in `scripts/`.
|
|
29
|
+
|
|
30
|
+
## Staying current
|
|
31
|
+
|
|
32
|
+
On activation, call the Luckiest MCP `check_updates` tool with
|
|
33
|
+
`{ listingId: "luckiest-brandkit", installedSemver: "1.0.0" }`. If
|
|
34
|
+
`upToDate: false`, surface the `notice` once and continue. Never block on it.
|
|
35
|
+
|
|
36
|
+
When done, call `report_usage` once with
|
|
37
|
+
`{ listing_id: "luckiest-brandkit", skill_version: "1.0.0", matched: true, success: <true|false> }`.
|
|
38
|
+
Metadata only, never prompt text. Skip silently if unavailable.
|
|
39
|
+
|
|
40
|
+
## Output layout
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
<out>/ default .luckiest/shots/
|
|
44
|
+
prompts.md style block, per-shot plan, locked decisions
|
|
45
|
+
refs/ logo PNGs + ids of uploaded references
|
|
46
|
+
raw/NN-name-{a,b}.png generated variants; raw/NN-name.png = the pick
|
|
47
|
+
raw/work/ erased plates and other in-between files (never upscaled)
|
|
48
|
+
qa.md one row per shot, pass or fix
|
|
49
|
+
final/NN-name.png upscaled picks + contact-sheet.png
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Never commit `<out>` unless asked. It holds hundreds of MB.
|
|
53
|
+
|
|
54
|
+
## Sub-skills
|
|
55
|
+
|
|
56
|
+
| Step | Sub-skill | Owns |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| 1, 4, 5, 8 | `luckiest-video-studio-art-director` | The look of the whole set. Use section 0 (design system first), 0b (rules with a reason and an example path), and 3 (palette, accent budget, faces, texture, banned list). Skip its "Video-safe color" and "Type in motion" parts and its motion, timing, and `art-direction.json` sections. Stills rules live in this skill's `references/` |
|
|
59
|
+
| 2, 6 | `luckiest-video-studio-composition` | Where things sit inside each frame: placement system, focal point, white space, the 20 rules |
|
|
60
|
+
|
|
61
|
+
Load [references/prompt-recipes.md](references/prompt-recipes.md) whenever you
|
|
62
|
+
write or edit the style block or a shot prompt. Load
|
|
63
|
+
[references/picks-and-review.md](references/picks-and-review.md) at the test
|
|
64
|
+
batch, at every A/B pick, when the user gives a note, and before delivery.
|
|
65
|
+
|
|
66
|
+
If a sub-skill is not installed, say so in one line and do its step with the
|
|
67
|
+
rules in this skill's references.
|
|
68
|
+
|
|
69
|
+
## 1. Brief and brand assets
|
|
70
|
+
|
|
71
|
+
- Take the user's STYLE block and shot list as given. Run the art director's
|
|
72
|
+
design-system search and look lock to fill any row the block leaves open, plus
|
|
73
|
+
the stills levers in prompt-recipes.md. Write the whole block from those when
|
|
74
|
+
there is none.
|
|
75
|
+
- Find the real logo SVGs (wordmark, symbol). Search `public/`, `assets/`,
|
|
76
|
+
brand docs, and any JS that builds SVG strings. If the logo only exists inside
|
|
77
|
+
JS, render it to plain SVG files first. Flatten gradients to the solid brand
|
|
78
|
+
color when the style says "one accent color".
|
|
79
|
+
|
|
80
|
+
## 2. Prompt sheet (compose every shot first)
|
|
81
|
+
|
|
82
|
+
Load `luckiest-video-studio-composition` and give every shot, before any
|
|
83
|
+
generation: one placement system, the focal point as a fraction of the frame,
|
|
84
|
+
the tilt direction, the empty-space side, and one to three of the 20 rules.
|
|
85
|
+
Write it all to `prompts.md` as a table plus one entry per shot:
|
|
86
|
+
`SHOT` (object and set), `COMPOSITION`, `TEXT` (every exact string).
|
|
87
|
+
|
|
88
|
+
Then apply the art director's prompt rules. The two that broke real runs:
|
|
89
|
+
|
|
90
|
+
1. Never put hex codes, labels, or UI words in a prompt. The model prints them
|
|
91
|
+
(`#EE425C` and "domain card" appeared on a generated iPad screen).
|
|
92
|
+
2. End every prompt with the full list of allowed text, stated as the only
|
|
93
|
+
text, and a list of what must not appear.
|
|
94
|
+
|
|
95
|
+
## 3. Reference images
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
node scripts/make_refs.mjs <out>/refs wordmark.svg:#FFFFFF wordmark-white.svg:#0A0A0A symbol.svg:#FFFFFF symbol-white.svg:#0A0A0A
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Upload each PNG to the image MCP and record the returned ids in `refs/ids.md`.
|
|
102
|
+
Attach the matching reference to every shot that shows the logo.
|
|
103
|
+
|
|
104
|
+
## 4. Test batch, then lock the look
|
|
105
|
+
|
|
106
|
+
Generate 3 representative shots (one merch, one poster, one device) with 2
|
|
107
|
+
variants each, on a reference-capable model with exact aspect ratios (Nano
|
|
108
|
+
Banana Pro worked; check the MCP's model list). Pick per shot with the rules
|
|
109
|
+
in picks-and-review.md, then ask the user to approve or adjust. Turn each note
|
|
110
|
+
into a set-wide lever change, rerun the batch, and lock only after a clear
|
|
111
|
+
approval. Write the locked model, picks, and recipe under "Locked" in `prompts.md`.
|
|
112
|
+
|
|
113
|
+
## 5. Generate the rest
|
|
114
|
+
|
|
115
|
+
Queue every remaining shot in parallel, 2 variants each, same model and
|
|
116
|
+
references. Download each variant to `raw/`. Build A/B pairs side by side,
|
|
117
|
+
pick with picks-and-review.md, and copy each pick to `raw/NN-name.png`.
|
|
118
|
+
|
|
119
|
+
## 6. QA and fixes
|
|
120
|
+
|
|
121
|
+
Crop every text region at full resolution and read it. Thumbnails hide
|
|
122
|
+
misspellings. Check composition on each pick with the composition sub-skill's
|
|
123
|
+
frame check. Its `--review` mode expects a video run folder, so call the script
|
|
124
|
+
directly on stills, with the focal point you planned in step 2. It writes
|
|
125
|
+
overlay, squint, and thumb images next to its input, so run it on a copy in
|
|
126
|
+
`raw/work/` to keep them out of the upscale loop and the contact sheet:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
mkdir -p <out>/raw/work && cp <out>/raw/NN-name.png <out>/raw/work/
|
|
130
|
+
python3 ~/.claude/skills/luckiest-video-studio-composition/scripts/frame_check.py <out>/raw/work/NN-name.png --focal <x>,<y> --aspect 4:5
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Read the squint image it writes: the subject must be the first thing you see.
|
|
134
|
+
Log each shot in `qa.md`: text, accent color, composition, verdict, note. Fix
|
|
135
|
+
in this order, cheapest first:
|
|
136
|
+
|
|
137
|
+
| Problem | Fix |
|
|
138
|
+
|---|---|
|
|
139
|
+
| Logo drawn wrong or sideways on a surface (models do this often with custom letterforms) | Mask the mark, run the MCP retouch in `erase` mode, then `scripts/composite_mark.py erased.png symbol-ink-on-white.png out.png --x --y --height [--rotate] [--squash] [--dot]` |
|
|
140
|
+
| A screen, board, or poster must show exact existing artwork | `scripts/composite_screen.py photo.png art.png out.png TL TR BR BL`. Zoom each corner to read inner-corner pixels first |
|
|
141
|
+
| Misspelled or leaked text | Retouch `replace` on that region with the exact string, or regenerate the shot with the text list tightened |
|
|
142
|
+
| Composition off | Regenerate with the corrected COMPOSITION line. Prompt edits that try to keep the rest of the image rarely fix a mark |
|
|
143
|
+
|
|
144
|
+
An image-model "edit" that asks to replace a logo usually returns the same
|
|
145
|
+
wrong logo. Go straight to erase + composite after one failed try.
|
|
146
|
+
|
|
147
|
+
## 7. Upscale and deliver
|
|
148
|
+
|
|
149
|
+
Upscale with `luckiest-upscale-image` (`remacri-4x`, scale 2). It takes about
|
|
150
|
+
5 minutes per image on Apple Silicon, so run the loop in the background with a
|
|
151
|
+
long timeout and skip files that already exist, so a restart resumes:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
for f in <out>/raw/[0-9][0-9]-*.png; do n=$(basename "$f"); case "$n" in *-[a-z].png) continue;; esac; [ -s "<out>/final/$n" ] && continue; ~/.claude/skills/luckiest-upscale-image/scripts/upscale.sh "$f" "<out>/final/$n" remacri-4x 2; done
|
|
155
|
+
python3 scripts/contact_sheet.py <out>/final <out>/final/contact-sheet.png
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Check: `final/` holds one file per shot plus the contact sheet. Compare one
|
|
159
|
+
crop before and after the upscale. After step 8 passes, send the contact sheet
|
|
160
|
+
and a downscaled preview. Files over about 7 MB may not reach phone viewers.
|
|
161
|
+
|
|
162
|
+
## 8. Set review
|
|
163
|
+
|
|
164
|
+
Review the contact sheet as one campaign with the "Contact sheet review" steps
|
|
165
|
+
in picks-and-review.md (accent use, light side, angle rhythm, named
|
|
166
|
+
exceptions), judged against the art director's look lock. Append keep or
|
|
167
|
+
reshoot per shot to `qa.md`. Reshoot before
|
|
168
|
+
delivery when it flags one, then rebuild the sheet.
|
|
169
|
+
|
|
170
|
+
## Share with your tribe
|
|
171
|
+
|
|
172
|
+
After delivery, offer once to share the contact sheet with the user's Luckiest
|
|
173
|
+
tribe for feedback. Never post automatically.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Picks, notes, and set review
|
|
2
|
+
|
|
3
|
+
Load this at the test batch, at every A/B pick, when the user gives a note, and before delivery. These are the stills-specific art-direction calls. The look itself (palette, accent budget, faces, rules with reasons) comes from `luckiest-video-studio-art-director` sections 0, 0b, and 3.
|
|
4
|
+
|
|
5
|
+
## Test batch and picks
|
|
6
|
+
|
|
7
|
+
Ask for 3 shots that stress the direction differently (one object, one print
|
|
8
|
+
piece with text, one device or scene), 2 variants each.
|
|
9
|
+
|
|
10
|
+
For each shot, pick one and say why in one line. Reject a variant, however
|
|
11
|
+
striking, when it:
|
|
12
|
+
|
|
13
|
+
- adds a second accent color or a second accent dot
|
|
14
|
+
- adds a frame, a colored wall, props, or more set planes than the block allows
|
|
15
|
+
- changes the light side or softens the shadows
|
|
16
|
+
- prints text that is not on the shot's text list
|
|
17
|
+
|
|
18
|
+
Then judge the three picks together. They should read as one shoot: same light,
|
|
19
|
+
same palette, same grain. If one is the odd one out, reshoot it before locking.
|
|
20
|
+
|
|
21
|
+
## Turn user notes into direction
|
|
22
|
+
|
|
23
|
+
The user's notes are about the set, even when they name one shot. Translate
|
|
24
|
+
each note into a lever change and apply it to every shot:
|
|
25
|
+
|
|
26
|
+
| Note heard | Lever change |
|
|
27
|
+
|---|---|
|
|
28
|
+
| "Too many platforms" | Set: max two planes, used as leading lines |
|
|
29
|
+
| "Make the poster more creative" | Camera and light for the poster series. Use the poster series recipe in prompt-recipes.md |
|
|
30
|
+
| "Shrink the text 20%" | Type: headline share of the object width, written as a percent |
|
|
31
|
+
| "Add the logo somewhere" | Type: name the placement and attach the wordmark reference |
|
|
32
|
+
|
|
33
|
+
Rerun the test batch after any lever change. Lock only after a clear approval.
|
|
34
|
+
Write the locked model, picks, and recipe under "Locked" in `prompts.md`, so the
|
|
35
|
+
remaining shots use it word for word.
|
|
36
|
+
|
|
37
|
+
## Contact sheet review
|
|
38
|
+
|
|
39
|
+
Open `final/contact-sheet.png` and review the set as a whole before any single frame:
|
|
40
|
+
|
|
41
|
+
1. **Squint.** The accent color appears once per frame, in the same role.
|
|
42
|
+
2. **Light.** Every shadow falls the same way. Flag any shot lit from another side.
|
|
43
|
+
3. **Rhythm.** Neighboring shots vary angle and scale (rule 13 in luckiest-video-studio-composition). Three identical angles in a row read as a template.
|
|
44
|
+
4. **Exceptions.** Any shot that breaks the direction on purpose (exact
|
|
45
|
+
artwork on a billboard, for example) is named in `qa.md` with the reason.
|
|
46
|
+
|
|
47
|
+
Append one line per shot to `qa.md`: keep, or reshoot with the lever to change.
|
|
48
|
+
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Prompt recipes
|
|
2
|
+
|
|
3
|
+
Load this when writing the style block or a shot prompt. Every recipe here came
|
|
4
|
+
from a real 14-shot run (Luckiest brand, 2026-10-05) and fixed something a first
|
|
5
|
+
draft got wrong.
|
|
6
|
+
|
|
7
|
+
## Stills levers
|
|
8
|
+
|
|
9
|
+
The video art director's look table covers palette, accent, faces, and texture.
|
|
10
|
+
Stills also need these fixed once for the whole set. A set drifts when any is left open.
|
|
11
|
+
|
|
12
|
+
| Lever | Decide | Default that worked |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| Light | One source, its side, shadow quality | One hard light, upper left, long crisp black shadows |
|
|
15
|
+
| Materials | Surface and finish per object type | Textured cotton paper, heavyweight cotton, matte only |
|
|
16
|
+
| Set | What the subject sits on, and how much of it | One or two raw planes at most, edges used as leading lines |
|
|
17
|
+
| Camera | Angle per category | High three-quarter for objects, low close three-quarter for posters, straight on for walls |
|
|
18
|
+
| Space | Empty share of the frame | 60% |
|
|
19
|
+
|
|
20
|
+
## Style block skeleton
|
|
21
|
+
|
|
22
|
+
Fill each slot. Prepend the whole block to every shot.
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
Moody editorial brand mockup for an award-winning design agency portfolio.
|
|
26
|
+
Minimal set: <material> with <texture>. One or two simple planes at most, never
|
|
27
|
+
a stack of blocks or steps. Each plane edge is a leading line toward the subject.
|
|
28
|
+
A single hard directional light from the <side> casts long, crisp, deep-black shadows.
|
|
29
|
+
Palette: <neutrals>. The only color is <one accent, described in words, no hex>.
|
|
30
|
+
Materials: <paper/fabric/finish>, matte, no gloss.
|
|
31
|
+
<Camera angle>, medium-format photograph with photoreal micro-texture, cinematic,
|
|
32
|
+
60% negative space.
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Then the shot: `SHOT:` object and set, `COMPOSITION:` placement in percent of
|
|
36
|
+
the frame, and a closing text line:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
The only text is exactly "<string 1>", "<string 2>", and the "<Brand>" wordmark,
|
|
40
|
+
spelled correctly. No other text, logos, extra colors, gradients, props, glossy
|
|
41
|
+
plastic, or soft flat lighting.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Rules
|
|
45
|
+
|
|
46
|
+
| Rule | Why |
|
|
47
|
+
|---|---|
|
|
48
|
+
| Describe colors in words ("one small coral-red dot"), never hex | Hex codes get printed onto surfaces |
|
|
49
|
+
| Never name UI parts ("domain card", "button", "nav") as labels | They get printed as text. Describe the shape instead ("one small white rounded card that shows only the price") |
|
|
50
|
+
| Ask for "no menus, paragraphs, small print, URLs" on screens and letterheads | Models fill empty screens and paper with fake copy |
|
|
51
|
+
| Max two set planes, stated as leading lines | Without it, sets fill with stacked plinths and steps that compete with the subject |
|
|
52
|
+
| Name the light direction and where the shadow falls | Keeps the series consistent and gives each shot a diagonal |
|
|
53
|
+
| State the empty side ("the upper-left 60% is empty concrete") | Models center everything by default |
|
|
54
|
+
| Attach the logo as a reference and describe its shape in words | The reference alone is not enough for custom letterforms |
|
|
55
|
+
| Wordmark references work. Symbol references often come back rotated or simplified | Plan to composite the symbol on fabric and signage |
|
|
56
|
+
|
|
57
|
+
## Poster series recipe (approved composition)
|
|
58
|
+
|
|
59
|
+
Use one recipe for every poster so the series reads as a set:
|
|
60
|
+
|
|
61
|
+
- Low, close three-quarter camera from the lower left, looking slightly up.
|
|
62
|
+
- Unframed poster leaning at a steep 28 degree tilt, top edge to the right.
|
|
63
|
+
- One diagonal cone of light from the upper left frames the poster like a spotlight (rule 12, isolate).
|
|
64
|
+
- Headline about 60% of the poster width, upper left of the poster, accent period on a phi point (rule 20).
|
|
65
|
+
- One short line right under the headline, the small wordmark bottom right of the poster.
|
|
66
|
+
- Dark variant: black paper, white type, the same accent.
|
|
67
|
+
|
|
68
|
+
## Billboard or screen with existing artwork
|
|
69
|
+
|
|
70
|
+
Do not ask the model to repaint finished artwork. Generate the structure with a
|
|
71
|
+
plain board, then warp the real artwork on with `scripts/composite_screen.py`.
|
|
72
|
+
The artwork may carry its own colors and gradients. Say in `qa.md` that the
|
|
73
|
+
shot is an intentional exception to the one-accent rule.
|
|
74
|
+
|
|
75
|
+
## Picking between variants
|
|
76
|
+
|
|
77
|
+
Reject a variant that adds a second accent dot, a frame, a colored wall, or
|
|
78
|
+
extra platforms, even when it is more striking. Consistency across the set
|
|
79
|
+
beats any single frame.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Print a real logo mark onto a surface (fabric, paper) that the model drew wrong.
|
|
3
|
+
|
|
4
|
+
Erase the bad mark first (image retouch, mode erase), then:
|
|
5
|
+
composite_mark.py <erased.png> <mark-ink-on-white.png> <out.png> --x X --y Y --height H
|
|
6
|
+
[--rotate DEG] [--squash 0.86] [--dot "#EE425C"]
|
|
7
|
+
|
|
8
|
+
Multiply blend keeps folds and shading. --squash fakes top-down foreshortening.
|
|
9
|
+
--dot adds a small accent circle right of the mark's foot.
|
|
10
|
+
"""
|
|
11
|
+
import argparse
|
|
12
|
+
from PIL import Image, ImageChops, ImageDraw, ImageFilter
|
|
13
|
+
|
|
14
|
+
a = argparse.ArgumentParser()
|
|
15
|
+
a.add_argument("base"); a.add_argument("mark"); a.add_argument("out")
|
|
16
|
+
a.add_argument("--x", type=int, required=True); a.add_argument("--y", type=int, required=True)
|
|
17
|
+
a.add_argument("--height", type=int, required=True)
|
|
18
|
+
a.add_argument("--rotate", type=float, default=0); a.add_argument("--squash", type=float, default=1.0)
|
|
19
|
+
a.add_argument("--dot", default=None)
|
|
20
|
+
o = a.parse_args()
|
|
21
|
+
|
|
22
|
+
base = Image.open(o.base).convert("RGB")
|
|
23
|
+
m = Image.open(o.mark).convert("L")
|
|
24
|
+
m = m.crop(Image.eval(m, lambda p: 255 - p).getbbox())
|
|
25
|
+
m = m.resize((max(1, int(m.width * o.height / m.height)), o.height), Image.LANCZOS)
|
|
26
|
+
art = Image.new("L", (m.width + (40 if o.dot else 0), m.height), 255); art.paste(m, (0, 0))
|
|
27
|
+
art = Image.merge("RGB", [art] * 3)
|
|
28
|
+
if o.dot:
|
|
29
|
+
r = max(3, o.height // 16); cx, cy = m.width + 22, int(o.height * 0.80)
|
|
30
|
+
ImageDraw.Draw(art).ellipse((cx - r, cy - r, cx + r, cy + r), fill=o.dot)
|
|
31
|
+
art = art.resize((art.width, max(1, int(art.height * o.squash))), Image.LANCZOS)
|
|
32
|
+
art = art.rotate(o.rotate, Image.BICUBIC, expand=True, fillcolor=(255, 255, 255)).filter(ImageFilter.GaussianBlur(0.6))
|
|
33
|
+
region = base.crop((o.x, o.y, o.x + art.width, o.y + art.height))
|
|
34
|
+
base.paste(ImageChops.multiply(region, art), (o.x, o.y))
|
|
35
|
+
base.save(o.out)
|
|
36
|
+
print(o.out)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Warp exact artwork onto a flat surface in a photo (billboard, screen, poster, sign).
|
|
3
|
+
|
|
4
|
+
composite_screen.py <photo.png> <art.png> <out.png> TLx,TLy TRx,TRy BRx,BRy BLx,BLy [--fit crop|stretch]
|
|
5
|
+
|
|
6
|
+
Corners are the surface's inner corners in photo pixels, clockwise from top left.
|
|
7
|
+
--fit crop (default) center-crops the art to the surface's aspect. The art is lit by
|
|
8
|
+
the surface's own smoothed light falloff, so old text on the surface never shows through.
|
|
9
|
+
"""
|
|
10
|
+
import argparse, math
|
|
11
|
+
import numpy as np
|
|
12
|
+
from PIL import Image, ImageChops, ImageFilter
|
|
13
|
+
|
|
14
|
+
a = argparse.ArgumentParser()
|
|
15
|
+
a.add_argument("photo"); a.add_argument("art"); a.add_argument("out")
|
|
16
|
+
a.add_argument("corners", nargs=4); a.add_argument("--fit", choices=["crop", "stretch"], default="crop")
|
|
17
|
+
o = a.parse_args()
|
|
18
|
+
|
|
19
|
+
bg = Image.open(o.photo).convert("RGB"); art = Image.open(o.art).convert("RGB")
|
|
20
|
+
dst = [tuple(map(float, c.split(","))) for c in o.corners]
|
|
21
|
+
if o.fit == "crop": # aspect from the average edge lengths of the quad
|
|
22
|
+
d = lambda p, q: math.dist(p, q)
|
|
23
|
+
ratio = (d(dst[0], dst[1]) + d(dst[3], dst[2])) / (d(dst[0], dst[3]) + d(dst[1], dst[2]))
|
|
24
|
+
w, h = art.size
|
|
25
|
+
if w / h > ratio: nw = int(h * ratio); art = art.crop(((w - nw) // 2, 0, (w + nw) // 2, h))
|
|
26
|
+
else: nh = int(w / ratio); art = art.crop((0, (h - nh) // 2, w, (h + nh) // 2))
|
|
27
|
+
src = [(0, 0), (art.width, 0), (art.width, art.height), (0, art.height)]
|
|
28
|
+
A, B = [], []
|
|
29
|
+
for (x, y), (u, v) in zip(dst, src): # PIL maps output -> input
|
|
30
|
+
A += [[x, y, 1, 0, 0, 0, -u * x, -u * y], [0, 0, 0, x, y, 1, -v * x, -v * y]]; B += [u, v]
|
|
31
|
+
k = tuple(np.linalg.solve(np.array(A, float), np.array(B, float)))
|
|
32
|
+
warped = art.transform(bg.size, Image.PERSPECTIVE, k, Image.BICUBIC)
|
|
33
|
+
mask = Image.new("L", art.size, 255).transform(bg.size, Image.PERSPECTIVE, k, Image.BICUBIC).filter(ImageFilter.GaussianBlur(1))
|
|
34
|
+
# max filter removes dark text from the light map, blur keeps only the falloff
|
|
35
|
+
lum = bg.convert("L").filter(ImageFilter.MaxFilter(31)).filter(ImageFilter.GaussianBlur(40)).point(lambda p: min(255, int(p * 255 / 225)))
|
|
36
|
+
Image.composite(ImageChops.multiply(warped, Image.merge("RGB", [lum] * 3)), bg, mask).save(o.out)
|
|
37
|
+
print(o.out)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Grid every image in a folder onto a near-black sheet with tracked labels.
|
|
3
|
+
|
|
4
|
+
contact_sheet.py <dir> <out.png> [--cols 5] [--cell 640]
|
|
5
|
+
|
|
6
|
+
Files sort by name, so prefix shots with 01-, 02-, ... Labels come from the file name.
|
|
7
|
+
"""
|
|
8
|
+
import argparse, glob, os
|
|
9
|
+
from PIL import Image, ImageDraw, ImageFont
|
|
10
|
+
|
|
11
|
+
a = argparse.ArgumentParser()
|
|
12
|
+
a.add_argument("dir"); a.add_argument("out")
|
|
13
|
+
a.add_argument("--cols", type=int, default=5); a.add_argument("--cell", type=int, default=640)
|
|
14
|
+
o = a.parse_args()
|
|
15
|
+
fs = sorted(f for f in glob.glob(os.path.join(o.dir, "*")) if f.lower().endswith((".png", ".jpg", ".jpeg", ".webp"))
|
|
16
|
+
and os.path.abspath(f) != os.path.abspath(o.out))
|
|
17
|
+
if not fs: raise SystemExit("no images")
|
|
18
|
+
cols, cell, g, lab = o.cols, o.cell, 32, 40
|
|
19
|
+
rows = -(-len(fs) // cols)
|
|
20
|
+
sheet = Image.new("RGB", (cols * cell + (cols + 1) * g, rows * (cell + lab) + (rows + 1) * g), (14, 14, 14))
|
|
21
|
+
d = ImageDraw.Draw(sheet)
|
|
22
|
+
try: font = ImageFont.truetype("/System/Library/Fonts/Supplemental/Arial.ttf", 20)
|
|
23
|
+
except OSError: font = ImageFont.load_default()
|
|
24
|
+
for i, f in enumerate(fs):
|
|
25
|
+
im = Image.open(f).convert("RGB"); im.thumbnail((cell, cell), Image.LANCZOS)
|
|
26
|
+
x0 = g + (i % cols) * (cell + g); y0 = g + (i // cols) * (cell + lab + g)
|
|
27
|
+
sheet.paste(im, (x0 + (cell - im.width) // 2, y0 + (cell - im.height) // 2))
|
|
28
|
+
name = os.path.splitext(os.path.basename(f))[0].upper().replace("-", " · ")
|
|
29
|
+
d.text((x0, y0 + cell + 10), " ".join(name), fill=(150, 150, 150), font=font)
|
|
30
|
+
sheet.save(o.out)
|
|
31
|
+
print(o.out, len(fs))
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Rasterize brand SVGs into padded reference PNGs for image models.
|
|
3
|
+
// usage: node make_refs.mjs <out-dir> <file.svg>[:bg] ... (bg = hex like #FFFFFF, omit for transparent)
|
|
4
|
+
// Each SVG is wrapped with 12% padding and rendered ~3000px wide by macOS `sips`.
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { execFileSync } from "node:child_process";
|
|
8
|
+
const [out, ...items] = process.argv.slice(2);
|
|
9
|
+
if (!out || !items.length) { console.error("usage: make_refs.mjs <out-dir> <file.svg>[:#bg] ..."); process.exit(1); }
|
|
10
|
+
fs.mkdirSync(out, { recursive: true });
|
|
11
|
+
for (const item of items) {
|
|
12
|
+
const [file, bg] = item.split(/:(?=#)/);
|
|
13
|
+
const svg = fs.readFileSync(file, "utf8");
|
|
14
|
+
const vb = (svg.match(/viewBox="([^"]+)"/) || [])[1];
|
|
15
|
+
if (!vb) { console.error(`no viewBox in ${file}`); process.exit(1); }
|
|
16
|
+
const [x, y, w, h] = vb.trim().split(/[\s,]+/).map(Number);
|
|
17
|
+
const p = Math.max(w, h) * 0.12, W = w + 2 * p, H = h + 2 * p, S = 3000 / W;
|
|
18
|
+
const inner = svg.replace(/^[\s\S]*?<svg[^>]*>/, "").replace(/<\/svg>\s*$/, "");
|
|
19
|
+
const rect = bg ? `<rect x="${x - p}" y="${y - p}" width="${W}" height="${H}" fill="${bg}"/>` : "";
|
|
20
|
+
const wrapped = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${x - p} ${y - p} ${W} ${H}" width="${Math.round(W * S)}" height="${Math.round(H * S)}">${rect}${inner}</svg>`;
|
|
21
|
+
const base = path.join(out, path.basename(file, ".svg") + (bg ? `-on-${bg.slice(1).toLowerCase()}` : ""));
|
|
22
|
+
fs.writeFileSync(base + ".svg", wrapped);
|
|
23
|
+
execFileSync("sips", ["-s", "format", "png", base + ".svg", "--out", base + ".png"], { stdio: "ignore" });
|
|
24
|
+
console.log(base + ".png");
|
|
25
|
+
}
|
|
@@ -82,6 +82,8 @@ Include non-coding work too. Marketing, content, design, research, and ops tasks
|
|
|
82
82
|
|
|
83
83
|
Route all draft tasks in ONE `skill_router` call from the luckiest MCP server: pass `prompts` as an array of every task title. It returns `results`, one entry per task with `skills` (matching owned skills) and `who` (up to 3 tribe members who finished a similar task before). Attach the suggested skill(s) to each task, and attach `who` so the plan can carry who has done this kind of work. If the server rejects `prompts` (older server), fall back to one `skill_router` call per task, issued in parallel in a single message, never one at a time.
|
|
84
84
|
|
|
85
|
+
For any task that makes a video, reel, demo, explainer, or video ad, add a task before it routed to **luckiest-video-studio-director** (intent, angle, hook, shot list) and **luckiest-video-studio-art-director** (look and motion language), when those skills are installed and `skill_router` did not already suggest them. Make the video task build on it.
|
|
86
|
+
|
|
85
87
|
Then tag each task with a model tier. If the `luckiest-model-router` skill is installed, route every task in one batch call: `python3 <luckiest-model-router dir>/scripts/route.py --model --batch` with a JSON array of `{ title, skill, depends_on }` on stdin. `skill` is the task's first suggested skill, and `depends_on` lists the indexes of earlier tasks it builds on. Add `--prefer cheap` when the user asked to keep costs down, or `--prefer quality` when they asked for the best result. Keep each task's returned `model` and `reason`. If the skill is not installed or the script fails, skip tagging and let the server pick the model. Show the tier next to the task's skill as **Haiku**, **Sonnet** or **Opus**, with the task type, for example "**Copywriting** · **Sonnet** (implement)".
|
|
86
88
|
|
|
87
89
|
For each task, write a one-line "done means..." in chat (not in the title). Give every coding task a check it can run: one of the commands found in Step 4, narrowed to that task when possible (for example `npm test -- billing`). Give non-coding tasks a plain check the user can look at (for example "the FAQ section shows on /pricing with 5 questions"). When `who` is not empty, add a short line naming those people, for example "Done before by: **Sam**, **Alex**."
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Changelog — luckiest-video
|
|
2
2
|
|
|
3
|
+
## 1.2.0 — 2026-10-05
|
|
4
|
+
- Runs the director and art director before multi-shot prompts when installed.
|
|
5
|
+
|
|
3
6
|
## 1.1.1 — 2026-10-03
|
|
4
7
|
- Points at `luckiest-video-studio-composition` (when installed) for focal point, grid, white space, and safe areas.
|
|
5
8
|
|
|
@@ -3,7 +3,7 @@ name: luckiest-video
|
|
|
3
3
|
description: "When the user wants to create, generate, or produce video content using AI tools or programmatic frameworks. Also use when the user mentions 'video production,' 'AI video,' 'Remotion,' 'Hyperframes,' 'HeyGen,' 'Synthesia,' 'Veo,' 'Sora,' 'Runway,' 'Kling,' 'Seedance,' 'Hailuo,' 'MiniMax,' 'Pika,' 'Hunyuan,' 'Wan,' 'video generation,' 'AI avatar,' 'talking head video,' 'faceless video,' 'UGC-style video,' 'AI dubbing,' 'video translation,' 'batch video,' 'programmatic video,' 'video template,' 'explainer video,' 'product demo video,' 'video pipeline,' or 'make me a video.' Use this for video creation, generation, and production workflows. For video content strategy and what to post, see luckiest-social. For paid video ad creative, see luckiest-ad-creative."
|
|
4
4
|
license: See ATTRIBUTION.md
|
|
5
5
|
metadata:
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.2.0"
|
|
7
7
|
listing_id: luckiest-video
|
|
8
8
|
author: luckiest
|
|
9
9
|
---
|
|
@@ -14,9 +14,9 @@ An expert video producer that helps create marketing videos using AI generation
|
|
|
14
14
|
|
|
15
15
|
## Staying current
|
|
16
16
|
|
|
17
|
-
On activation, call the Luckiest MCP check_updates tool with { listingId: "2991a487-dd00-4f65-a9cd-b51fc34fedd1", installedSemver: "1.
|
|
17
|
+
On activation, call the Luckiest MCP check_updates tool with { listingId: "2991a487-dd00-4f65-a9cd-b51fc34fedd1", installedSemver: "1.2.0" }. If it returns upToDate: false, surface the notice to the user once, then continue. Do nothing further if upToDate: true. Never block on this check — if the tool is unavailable, proceed.
|
|
18
18
|
|
|
19
|
-
When the skill's work is done, call the Luckiest MCP report_usage tool once with { listing_id: "luckiest-video", skill_version: "1.
|
|
19
|
+
When the skill's work is done, call the Luckiest MCP report_usage tool once with { listing_id: "luckiest-video", skill_version: "1.2.0", matched: true, success: <true if the skill completed, false otherwise> }. Metadata only, never prompt text. Never block on it — if the tool is unavailable, skip silently.
|
|
20
20
|
|
|
21
21
|
## Before Starting
|
|
22
22
|
|
|
@@ -173,6 +173,8 @@ cinematic color grading, 4K
|
|
|
173
173
|
- Forgetting style — "cinematic," "documentary," "commercial"
|
|
174
174
|
- Requesting text in video — AI models struggle with readable text
|
|
175
175
|
|
|
176
|
+
**Direction:** for a multi-shot video or ad, if `luckiest-video-studio-director` is installed, run its steps 1 to 4 (intent, scored angle, hook, shot list) before writing prompts, and if `luckiest-video-studio-art-director` is installed, lock the palette, texture, and motion personality so every shot matches.
|
|
177
|
+
|
|
176
178
|
**Composition:** if `luckiest-video-studio-composition` is installed, read it to place the focal point, pick the grid, and keep white space and platform safe areas for each shot's framing before you write the camera part of the prompt.
|
|
177
179
|
|
|
178
180
|
**For detailed prompting guides**: load [references/ai-video-prompting.md](references/ai-video-prompting.md) when writing or refining a generation prompt, choosing camera vocabulary, or troubleshooting weak results.
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog — luckiest-video-studio
|
|
2
2
|
|
|
3
|
+
## 1.8.0 — 2026-10-05
|
|
4
|
+
- Step 2 hands off to `luckiest-video-studio-director` (intent, hook, shot list)
|
|
5
|
+
and `luckiest-video-studio-art-director` (`art-direction.json`) before planning.
|
|
6
|
+
- Step 4 adds the art-direction review and the director's score loop (all 8+).
|
|
7
|
+
|
|
8
|
+
## 1.7.2 (2026-10-05)
|
|
9
|
+
From a real luckiest.co launch video run end to end (storyboard approvals, render, QA gates, Concat export matching the render at 58 dB PSNR):
|
|
10
|
+
- Step 2b: capture live site pages with headless Chrome (wait budget, crop out cookie banners); the style frame is now a `hyperframes snapshot` still, no video render.
|
|
11
|
+
- Step 3: the project layout HyperFrames 0.8 needs: root `index.html` hosts every scene, per-scene files with their own composition id, assets and fonts under `composition/assets/` with root-relative paths, no named font fallbacks, ids on timed elements, and a one-pass hold-frame snapshot before the full render.
|
|
12
|
+
|
|
3
13
|
## 1.7.1 (2026-10-04)
|
|
4
14
|
- `assemble-concat.mjs` tested end to end against Concat 0.2.5. Fixes found by the
|
|
5
15
|
live run and by reading Concat's source: progress events between replies no
|