blamcode 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. blamcode/__init__.py +9 -0
  2. blamcode/cli.py +122 -0
  3. blamcode/layer/README.md +43 -0
  4. blamcode/layer/config/agent/build.md +118 -0
  5. blamcode/layer/config/agent/debugger.md +32 -0
  6. blamcode/layer/config/agent/designer.md +31 -0
  7. blamcode/layer/config/agent/vision.md +26 -0
  8. blamcode/layer/config/agent/writer.md +28 -0
  9. blamcode/layer/config/command/ask.md +41 -0
  10. blamcode/layer/config/command/blam.md +24 -0
  11. blamcode/layer/config/command/explore.md +14 -0
  12. blamcode/layer/config/command/fix.md +14 -0
  13. blamcode/layer/config/command/open.md +18 -0
  14. blamcode/layer/config/command/review.md +14 -0
  15. blamcode/layer/config/opencode.json +53 -0
  16. blamcode/layer/config/themes/bangladeshi.json +67 -0
  17. blamcode/layer/config/themes/blamcode.json +217 -0
  18. blamcode/layer/config/tui.json +4 -0
  19. blamcode/layer/install.sh +752 -0
  20. blamcode/layer/scripts/__pycache__/patch-brand.cpython-312.pyc +0 -0
  21. blamcode/layer/scripts/blamcode +518 -0
  22. blamcode/layer/scripts/blamcode-browser +315 -0
  23. blamcode/layer/scripts/blamcode-menu +140 -0
  24. blamcode/layer/scripts/blamcode-uninstall +71 -0
  25. blamcode/layer/scripts/blamcode-vision +542 -0
  26. blamcode/layer/scripts/oc-settings.sh +138 -0
  27. blamcode/layer/scripts/patch-brand.py +267 -0
  28. blamcode/layer/skills/android-app/SKILL.md +53 -0
  29. blamcode/layer/skills/api-integration/SKILL.md +49 -0
  30. blamcode/layer/skills/bash-cli-expert/SKILL.md +48 -0
  31. blamcode/layer/skills/bot-development/SKILL.md +53 -0
  32. blamcode/layer/skills/clean-code-performance/SKILL.md +45 -0
  33. blamcode/layer/skills/database/SKILL.md +56 -0
  34. blamcode/layer/skills/debugging-fixes/SKILL.md +45 -0
  35. blamcode/layer/skills/deploy-hosting/SKILL.md +38 -0
  36. blamcode/layer/skills/docker/SKILL.md +74 -0
  37. blamcode/layer/skills/firebase-supabase/SKILL.md +61 -0
  38. blamcode/layer/skills/git-workflow/SKILL.md +63 -0
  39. blamcode/layer/skills/lets-scroll/SKILL.md +877 -0
  40. blamcode/layer/skills/lets-scroll/references/index-template.html +73 -0
  41. blamcode/layer/skills/lets-scroll/references/knockout.py +89 -0
  42. blamcode/layer/skills/lets-scroll/references/pipeline.md +312 -0
  43. blamcode/layer/skills/lets-scroll/references/prompts.md +194 -0
  44. blamcode/layer/skills/lets-scroll/references/scrub-engine.js +448 -0
  45. blamcode/layer/skills/project-structure/SKILL.md +74 -0
  46. blamcode/layer/skills/python-automation/SKILL.md +52 -0
  47. blamcode/layer/skills/react-next-best-practices/SKILL.md +54 -0
  48. blamcode/layer/skills/security-review/SKILL.md +48 -0
  49. blamcode/layer/skills/seo-basics/SKILL.md +44 -0
  50. blamcode/layer/skills/testing/SKILL.md +58 -0
  51. blamcode/layer/skills/ui-ux-responsive/SKILL.md +53 -0
  52. blamcode/layer/skills/website-builder/SKILL.md +47 -0
  53. blamcode-0.4.0.dist-info/METADATA +62 -0
  54. blamcode-0.4.0.dist-info/RECORD +58 -0
  55. blamcode-0.4.0.dist-info/WHEEL +5 -0
  56. blamcode-0.4.0.dist-info/entry_points.txt +2 -0
  57. blamcode-0.4.0.dist-info/licenses/LICENSE +21 -0
  58. blamcode-0.4.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,73 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
6
+ <title>BRAND — the world of SUBJECT</title>
7
+ <meta name="description" content="Scroll to fly through the world of BRAND." />
8
+ <style>
9
+ /* Theme the engine here. These match your generated scenes' background + palette. */
10
+ :root, .sw-root {
11
+ --sw-bg: #F5EDE0; /* == the scene background colour */
12
+ --sw-ink: #241d2b;
13
+ --sw-ink-soft: #6a6072;
14
+ --sw-accent: #9B7EBD; /* per-section accents override this at runtime */
15
+ }
16
+ </style>
17
+ </head>
18
+ <body>
19
+ <div id="top"></div>
20
+ <div id="world"></div>
21
+
22
+ <script src="scrub-engine.js"></script>
23
+ <script>
24
+ mountLetsScroll(document.getElementById('world'), {
25
+ brand: { name: 'BRAND', href: '#top' },
26
+ cta: { label: 'Order now', href: '#finale' },
27
+ hint: 'scroll to fly in',
28
+ diveScroll: 1.3,
29
+ connScroll: 0.9,
30
+ sections: [
31
+ // One object per scene, in order. `accent` colours the copy/route for that scene.
32
+ // First section is the hero (its copy greets on landing); last carries the CTA.
33
+ {
34
+ id: 'sceneA', label: 'Scene A',
35
+ still: 'assets/sceneA.webp',
36
+ clip: 'assets/vid/sceneA.mp4',
37
+ clipMobile: 'assets/vid/sceneA-m.mp4', // mobile opt-in only: lighter 720p encode served on phones
38
+ accent: '#8FB98A',
39
+ // scroll: 1.6, linger: 0.45, // optional pacing: longer dwell; camera settles mid-scene
40
+ eyebrow: 'Value prop label',
41
+ title: 'The hero line.',
42
+ body: 'One plain-spoken sentence about this stage.',
43
+ tags: ['Proof', 'Proof', 'Proof'],
44
+ },
45
+ // …middle scenes…
46
+ {
47
+ id: 'finale', label: 'The Product',
48
+ still: 'assets/product.webp',
49
+ clip: 'assets/vid/finale.mp4',
50
+ clipMobile: 'assets/vid/finale-m.mp4',
51
+ accent: '#9B7EBD',
52
+ eyebrow: 'And it all pours into',
53
+ title: 'One perfect thing.',
54
+ body: 'The payoff sentence.',
55
+ tags: [],
56
+ cta: { primary: { label: 'Get started', href: '#' },
57
+ secondary: { label: 'See more', href: '#' } },
58
+ },
59
+ ],
60
+ // length === sections.length - 1, in order. Generated per SKILL.md Step 5.
61
+ connectors: [
62
+ 'assets/vid/conn1.mp4',
63
+ // 'assets/vid/conn2.mp4', …
64
+ ],
65
+ // Mobile opt-in only: lighter connectors for phones — same length/order as `connectors`.
66
+ connectorsMobile: [
67
+ 'assets/vid/conn1-m.mp4',
68
+ // 'assets/vid/conn2-m.mp4', …
69
+ ],
70
+ });
71
+ </script>
72
+ </body>
73
+ </html>
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env python3
2
+ """Border-connected background knockout for diorama stills.
3
+
4
+ Removes the flat background of a scene image (leaving the diorama floating on
5
+ transparency) via a flood fill from the borders over pixels near the corner
6
+ colour. Interior regions that happen to match the background (e.g. cream walls
7
+ inside the scene) are preserved because the fill only reaches border-connected
8
+ pixels. The soft contact shadow is kept as a natural base.
9
+
10
+ Usage:
11
+ python3 knockout.py scene1.png scene2.png ...
12
+ # writes scene1.rgba.png, scene2.rgba.png, ...
13
+ # optional: TOL env var (default 34) widens/narrows the bg match
14
+
15
+ Then encode to webp with alpha, e.g.:
16
+ cwebp -q 84 -alpha_q 95 -resize 1800 0 scene1.rgba.png -o scene1.webp
17
+
18
+ No numpy/ImageMagick needed — pure PIL. Pairs with SKILL.md Step 3.
19
+ """
20
+ import os
21
+ import sys
22
+ from collections import deque
23
+ from PIL import Image, ImageFilter
24
+
25
+ TOL = float(os.environ.get("TOL", "34")) # RGB Euclidean distance counted as background
26
+
27
+
28
+ def corner_color(im):
29
+ w, h = im.size
30
+ px = im.load()
31
+ pts = [(1, 1), (w - 2, 1), (1, h - 2), (w - 2, h - 2)]
32
+ r = sum(px[x, y][0] for x, y in pts) // 4
33
+ g = sum(px[x, y][1] for x, y in pts) // 4
34
+ b = sum(px[x, y][2] for x, y in pts) // 4
35
+ return (r, g, b)
36
+
37
+
38
+ def knock(inp, outp):
39
+ im = Image.open(inp).convert("RGB")
40
+ w, h = im.size
41
+ px = im.load()
42
+ cr, cg, cb = corner_color(im)
43
+ tol2 = TOL * TOL
44
+
45
+ def is_bg(x, y):
46
+ r, g, b = px[x, y]
47
+ dr, dg, db = r - cr, g - cg, b - cb
48
+ return dr * dr + dg * dg + db * db <= tol2
49
+
50
+ bg = bytearray(w * h)
51
+ seen = bytearray(w * h)
52
+ dq = deque()
53
+ for x in range(w):
54
+ for y in (0, h - 1):
55
+ i = y * w + x
56
+ if not seen[i] and is_bg(x, y):
57
+ seen[i] = 1; bg[i] = 1; dq.append((x, y))
58
+ for y in range(h):
59
+ for x in (0, w - 1):
60
+ i = y * w + x
61
+ if not seen[i] and is_bg(x, y):
62
+ seen[i] = 1; bg[i] = 1; dq.append((x, y))
63
+ while dq:
64
+ x, y = dq.popleft()
65
+ for nx, ny in ((x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)):
66
+ if 0 <= nx < w and 0 <= ny < h:
67
+ i = ny * w + nx
68
+ if not seen[i]:
69
+ seen[i] = 1
70
+ if is_bg(nx, ny):
71
+ bg[i] = 1; dq.append((nx, ny))
72
+
73
+ alpha = Image.new("L", (w, h), 255)
74
+ ap = alpha.load()
75
+ for y in range(h):
76
+ base = y * w
77
+ for x in range(w):
78
+ if bg[base + x]:
79
+ ap[x, y] = 0
80
+ alpha = alpha.filter(ImageFilter.GaussianBlur(1.4)) # soften the threshold contour
81
+ out = im.convert("RGBA")
82
+ out.putalpha(alpha)
83
+ out.save(outp)
84
+ print("knocked", outp)
85
+
86
+
87
+ if __name__ == "__main__":
88
+ for name in sys.argv[1:]:
89
+ knock(name, name.rsplit(".", 1)[0] + ".rgba.png")
@@ -0,0 +1,312 @@
1
+ # Pipeline: copy-paste scripts (bash 3.2 safe)
2
+
3
+ Set these once. `NAMES` is the ordered section ids; the last is the hero/finale.
4
+
5
+ ```bash
6
+ WORK=/tmp/lets-scroll # scratch dir for prompts, sources, frames
7
+ ASSETS=./assets # where the site reads stills (webp) + clips (mp4)
8
+ mkdir -p "$WORK" "$ASSETS/vid"
9
+ NAMES="farm kitchen shop delivery plaza finale" # <-- your section ids, in order
10
+
11
+ # Chain video model — ONE for every chained clip (SKILL Step 4 roster).
12
+ # Must accept --start-image AND --end-image (verify: higgsfield model get <model>):
13
+ # seedance_2_0 | kling3_0 | seedance_2_0_mini (draft tier). Reference-only models can't
14
+ # hold a seam; models without --mode (e.g. kling3_0_turbo) need their own flag branch below.
15
+ # DEFAULT backend: Monid pay-per-clip (§7 — gen_dive_monid/gen_conn_monid with
16
+ # VRES=1080p|720p|480p instead of VOPTS). The gen_dive/gen_conn functions in §2/§4
17
+ # below are the Higgsfield-credits FALLBACK (and the only home of kling3_0/mini).
18
+ VMODEL=seedance_2_0
19
+ case "$VMODEL" in # per-model flags + durations (bash 3.2 safe)
20
+ kling3_0) VOPTS="--mode std --sound off"; DIVE_DUR=10; CONN_DUR=5 ;; # no --resolution param on Kling
21
+ seedance_2_0_mini) VOPTS="--mode std --resolution 720p"; DIVE_DUR=8; CONN_DUR=5 ;; # cheap frame-locked previz
22
+ *) VOPTS="--mode std --resolution 1080p"; DIVE_DUR=8; CONN_DUR=5 ;; # seedance_2_0 default
23
+ esac
24
+ ```
25
+
26
+ Higgsfield generations take minutes — every `higgsfield ... --wait` call below is meant
27
+ to run inside a **backgrounded** script. Launch the whole script with your tool's
28
+ background/detached mode and poll the progress log; never block the foreground.
29
+
30
+ **Manual asset path (SKILL Step 1.7):** none of the generate scripts here run — the
31
+ user renders from the prompt files and drops `still_<name>.png`, `dive_<name>.mp4`,
32
+ `conn_<i>.mp4` into `$WORK` themselves. Validate each drop (count, aspect, duration,
33
+ frame 0 matches the handed-over start frame), then §3 (frame extraction), §5/§6
34
+ (encode) and everything after run unchanged.
35
+
36
+ ## 1. Scene stills (Step 2)
37
+
38
+ Write one prompt file per section to `$WORK/still_<name>.txt` (see prompts.md), then:
39
+
40
+ ```bash
41
+ gen_still() { # name
42
+ higgsfield generate create gpt_image_2 --prompt "$(cat "$WORK/still_$1.txt")" \
43
+ --aspect_ratio 3:2 --resolution 2k --quality high --wait --wait-timeout 15m --json \
44
+ > "$WORK/still_$1.json" 2> "$WORK/still_$1.err"
45
+ url=$(jq -r '.[0].result_url // empty' "$WORK/still_$1.json")
46
+ [ -n "$url" ] && curl -fsSL "$url" -o "$WORK/still_$1.png" && echo "still $1 ok" || echo "still $1 FAIL"
47
+ }
48
+ for n in $NAMES; do gen_still "$n" & done ; wait
49
+ ```
50
+
51
+ Codex variant (STILLS_SOURCE=codex, SKILL Step 1.8 — subscription-billed, zero
52
+ credits; ~1–3 min each, parallelize in small batches):
53
+
54
+ ```bash
55
+ gen_still_codex() { # name (< /dev/null is REQUIRED for parallel calls — see SKILL Gotchas)
56
+ codex exec -C "$WORK" -s workspace-write --skip-git-repo-check \
57
+ 'Use the image generation tool ($imagegen) to generate: '"$(cat "$WORK/still_$1.txt")"' Wide 3:2 landscape, high resolution. Save it as ./still_'"$1"'.png. Do not do anything else.' \
58
+ > "$WORK/still_$1.codex.log" 2>&1 < /dev/null
59
+ [ -f "$WORK/still_$1.png" ] && echo "still $1 ok (codex)" || echo "still $1 FAIL (see .codex.log)"
60
+ }
61
+ ```
62
+
63
+ Convert to webp for the site (and optionally run knockout.py first for transparency):
64
+
65
+ ```bash
66
+ for n in $NAMES; do cwebp -quiet -q 84 -resize 1800 0 "$WORK/still_$n.png" -o "$ASSETS/$n.webp"; done
67
+ ```
68
+
69
+ Review the stills for cohesion before continuing. Re-roll any off-style one (optionally
70
+ add `--image "$WORK/still_<good>.png"` to lock style).
71
+
72
+ ## 2. Dive-in clips (Step 4)
73
+
74
+ Prompt files at `$WORK/dive_<name>.txt`. Start image = the solid-bg still PNG.
75
+
76
+ ```bash
77
+ gen_dive() { # name ($VOPTS is unquoted on purpose — word-split flags)
78
+ higgsfield generate create "$VMODEL" --prompt "$(cat "$WORK/dive_$1.txt")" \
79
+ --start-image "$WORK/still_$1.png" \
80
+ $VOPTS --aspect_ratio 16:9 --duration "$DIVE_DUR" \
81
+ --wait --wait-timeout 20m --json > "$WORK/dive_$1.json" 2> "$WORK/dive_$1.err"
82
+ url=$(jq -r '.[0].result_url // empty' "$WORK/dive_$1.json")
83
+ [ -n "$url" ] && curl -fsSL "$url" -o "$WORK/dive_$1.mp4" && echo "dive $1 ok" || echo "dive $1 FAIL"
84
+ }
85
+ for n in $NAMES; do gen_dive "$n" & done ; wait
86
+ ```
87
+
88
+ Re-roll individual failures (503 / credit race are transient):
89
+ `gen_dive shop` (just that one).
90
+
91
+ ## 3. Extract boundary frames — the seam handoff (Step 5)
92
+
93
+ For each adjacent pair, the connector's start = dive_i's LAST frame, end = dive_{i+1}'s
94
+ FIRST frame — extracted from the **rendered videos**, never the stills.
95
+
96
+ ```bash
97
+ set -- $NAMES
98
+ prev=""
99
+ for n in "$@"; do
100
+ ffmpeg -v error -ss 0 -i "$WORK/dive_$n.mp4" -frames:v 1 -q:v 2 "$WORK/first_$n.png" # establishing
101
+ ffmpeg -v error -sseof -0.15 -i "$WORK/dive_$n.mp4" -frames:v 1 -q:v 2 "$WORK/last_$n.png" # interior
102
+ done
103
+ ```
104
+
105
+ ## 4. Connector clips (Step 5)
106
+
107
+ Prompt files at `$WORK/conn_<i>.txt` (i = 1..N-1). Iterate adjacent pairs:
108
+
109
+ ```bash
110
+ gen_conn() { # i startPng endPng (end-image required → seedance/kling3_0 only)
111
+ higgsfield generate create "$VMODEL" --prompt "$(cat "$WORK/conn_$1.txt")" \
112
+ --start-image "$2" --end-image "$3" \
113
+ $VOPTS --aspect_ratio 16:9 --duration "$CONN_DUR" \
114
+ --wait --wait-timeout 20m --json > "$WORK/conn_$1.json" 2> "$WORK/conn_$1.err"
115
+ url=$(jq -r '.[0].result_url // empty' "$WORK/conn_$1.json")
116
+ [ -n "$url" ] && curl -fsSL "$url" -o "$WORK/conn_$1.mp4" && echo "conn $1 ok" || echo "conn $1 FAIL"
117
+ }
118
+ set -- $NAMES ; i=0 ; prev=""
119
+ for n in "$@"; do
120
+ if [ -n "$prev" ]; then i=$((i+1)); gen_conn "$i" "$WORK/last_$prev.png" "$WORK/first_$n.png" & fi
121
+ prev="$n"
122
+ done ; wait
123
+ ```
124
+
125
+ ## 5. Encode everything for scrubbing (Step 6)
126
+
127
+ Native resolution (1080p from seedance std; kling3_0 std returned **720p** in testing —
128
+ never upscale, encode what ffprobe reports), crf 20, GOP 8, light sharpen, no audio,
129
+ faststart. Same for dives + connectors.
130
+
131
+ ```bash
132
+ enc() { ffmpeg -v error -y -i "$1" -an -vf "unsharp=5:5:0.8:5:5:0.0" \
133
+ -c:v libx264 -preset slow -crf 20 -pix_fmt yuv420p \
134
+ -g 8 -keyint_min 8 -sc_threshold 0 -movflags +faststart "$2"; echo "enc $2 $(du -h "$2"|cut -f1)"; }
135
+
136
+ for n in $NAMES; do enc "$WORK/dive_$n.mp4" "$ASSETS/vid/$n.mp4"; done
137
+ i=0; for f in "$WORK"/conn_*.mp4; do i=$((i+1)); enc "$f" "$ASSETS/vid/conn$i.mp4"; done
138
+ ```
139
+
140
+ Now the engine config's `sections[k].clip = assets/vid/<name>.mp4` and
141
+ `connectors = [assets/vid/conn1.mp4, …]` (length N-1, in order).
142
+
143
+ ## 6. Centre-crop mobile encodes — FALLBACK ONLY, not the mobile version
144
+
145
+ **The mobile version is the native 9:16 portrait chain (§6b).** This section's crop
146
+ encodes exist for one case: the user opted into mobile but credits can't cover the
147
+ portrait chain — and shipping them must be called out and approved, never silent
148
+ (portrait phones will see the landscape film's centre ~26%). The encode mechanics
149
+ matter either way: scrubbing sets `currentTime` every frame, and a phone decoder's
150
+ **seek cost scales with how many frames it must decode from the nearest keyframe** — so
151
+ a 1080p `-g 8` master that scrubs fine on a laptop stutters on a phone. A **smaller
152
+ frame + tighter GOP** fixes that (and halves the bytes on cellular). The crop `-m.mp4`
153
+ sibling per clip:
154
+
155
+ ```bash
156
+ # 720p, GOP 4 (twice the keyframes = ~half the seek-decode work), crf 23, same sharpen/faststart.
157
+ encm() { ffmpeg -v error -y -i "$1" -an -vf "scale=-2:720,unsharp=5:5:0.6:5:5:0.0" \
158
+ -c:v libx264 -preset slow -crf 23 -pix_fmt yuv420p \
159
+ -g 4 -keyint_min 4 -sc_threshold 0 -movflags +faststart "$2"; echo "encm $2 $(du -h "$2"|cut -f1)"; }
160
+
161
+ for n in $NAMES; do encm "$WORK/dive_$n.mp4" "$ASSETS/vid/$n-m.mp4"; done
162
+ i=0; for f in "$WORK"/conn_*.mp4; do i=$((i+1)); encm "$f" "$ASSETS/vid/conn$i-m.mp4"; done
163
+ ```
164
+
165
+ Wire the variants in the engine config — the engine serves them automatically on phones,
166
+ falling back to the desktop `clip` when a mobile one is absent:
167
+
168
+ ```js
169
+ sections[k].clipMobile = 'assets/vid/<name>-m.mp4';
170
+ connectorsMobile = ['assets/vid/conn1-m.mp4', …]; // length N-1, in order
171
+ ```
172
+
173
+ If phone scrubbing still stutters, tighten the GOP further (`-g 2`, or `-g 1` for all-intra
174
+ = instant seeks at the cost of larger files); if cellular weight is the bigger worry, raise
175
+ `crf` (24–26) or drop to `scale=-2:600`. If the master is already 720p (e.g. kling3_0 std),
176
+ the mobile encode still pays off — the tighter GOP is what makes phone seeks cheap. All-mobile encodes stay 16:9 — the engine
177
+ centre-crops them; see the portrait note in SKILL Step 8 / prompts.md.
178
+
179
+ ## 6b. Native 9:16 portrait chain — THE mobile version (Step 1.6 opt-in)
180
+
181
+ When the user opts into mobile, this is what they get: a **parallel 9:16 chain** rendered
182
+ natively for phones and shipped as the mobile variants — never the §6 crops (those are the
183
+ no-credits stopgap). Same seam laws as the main chain — the portrait chain frame-locks
184
+ against its own rendered frames, never the landscape ones. Budget ~2N-1 video gens +
185
+ re-rolls (interiors trip the NSFW filter in portrait too); state the credit cost at the
186
+ Step 1.6 interview.
187
+
188
+ 1. **Portrait start canvases.** Don't hand the video model a 3:2 still and hope: composite
189
+ each scene onto a 1080×1920 canvas in the page bg colour (island at ~94% width, visual
190
+ centre at ~45% height). The render then opens exactly on what the portrait poster shows.
191
+ For knocked-out stills, composite the RGBA over the bg colour first.
192
+ 2. **Dives/legs**: same prompt templates with a portrait clause up front ("Vertical
193
+ portrait composition, the diorama centered with generous [bg] space above and below"),
194
+ `--aspect_ratio 9:16`, same model/params as the main chain. Review each last frame
195
+ before chaining, as ever.
196
+ 3. **Connectors**: extract first/last frames **from the 9:16 renders** and generate 9:16
197
+ connectors between them. A native 9:16 scene mixed into cropped-16:9 neighbours pops at
198
+ both seams — the portrait chain must be complete, not partial.
199
+ 4. **Encode** with the §6 settings but portrait-oriented scale: `scale=720:-2` (720 wide),
200
+ `-g 4`, crf 23 → these ARE the `-m.mp4` mobile files (and they replace any §6 crop
201
+ stopgaps that shipped earlier).
202
+ 5. **Posters**: extract each 9:16 dive's first frame → webp → wire as the section's
203
+ `stillMobile` so the poster matches the portrait video's frame 0 (no landscape→portrait
204
+ flash when the clip paints). Engine support: `sections[k].stillMobile`.
205
+
206
+ ## 7. Monid backend — Seedance 2.0 pay-per-clip (the DEFAULT; qualified 2026-07-25)
207
+
208
+ `bytedance /v1/video/seedance-2.0` via Monid is the roster's `seedance_2_0` billed
209
+ per clip in USD, and the **default** chain backend (SKILL Step 4 → Monid backend;
210
+ both probes passed) — use these functions in the §2/§4 loops unless the build fell
211
+ back to Higgsfield credits. Same chain laws as everywhere else — only the I/O
212
+ differs: **frames ride Monid's free `sfs` file
213
+ system** (inline base64 is rejected), **`ratio` must be explicit** (the adaptive
214
+ default follows the input image's aspect), and runs are fire-and-poll. Token-priced
215
+ `w×h×24×sec/1024` at $7/1M (480p/720p), $7.7/1M (1080p) — measured: 1080p ≈ $2.99
216
+ dive / $1.87 connector; 720p ≈ $1.21 / $0.76; 480p previz ≈ $0.28 / $0.35.
217
+
218
+ ```bash
219
+ # helper: upload a local frame to sfs, print a signed public URL for it ($0).
220
+ # NB: /cat and /ls take the SAME relative path you gave /put — not the
221
+ # "home/..."-prefixed path /put echoes back (that one 404s).
222
+ monid_frame_url() { # localPng remoteName (JPEG-compresses on the way up)
223
+ jpg="$WORK/sfs_$2.jpg"
224
+ ffmpeg -v error -y -i "$1" -vf "scale='min(1536,iw)':-2" -q:v 2 "$jpg"
225
+ size=$(stat -f%z "$jpg")
226
+ up=$(NO_COLOR=1 monid run -p sfs -e /put \
227
+ -i "{\"path\":\"chain/$2.jpg\",\"sizeBytes\":$size,\"ttl\":\"1h\"}" -w 60 -j \
228
+ | jq -r '.output.uploadUrl')
229
+ curl -fsS -T "$jpg" "$up" > /dev/null
230
+ NO_COLOR=1 monid run -p sfs -e /cat -i "{\"path\":\"chain/$2.jpg\",\"ttl\":\"1d\"}" \
231
+ -w 60 -j | jq -r '.output.url'
232
+ }
233
+
234
+ # fire-and-poll (the CLI's -w caps at 120s and seedance can exceed it)
235
+ monid_wait() { # runId outJson
236
+ while :; do
237
+ NO_COLOR=1 monid runs get -r "$1" -j > "$2" 2>/dev/null
238
+ case "$(jq -r '.status // empty' "$2")" in
239
+ COMPLETED|FAILED|BLOCKED|STOPPED|TIME_OUT) break ;;
240
+ esac
241
+ sleep 8
242
+ done
243
+ }
244
+
245
+ gen_dive_monid() { # name (VRES=1080p|720p|480p; DIVE_DUR as usual)
246
+ furl=$(monid_frame_url "$WORK/still_$1.png" "still_$1")
247
+ jq -n --arg p "$(cat "$WORK/dive_$1.txt")" --arg u "$furl" --arg r "$VRES" \
248
+ '{content:[{type:"text",text:$p},
249
+ {type:"image_url",image_url:{url:$u},role:"first_frame"}],
250
+ resolution:$r, duration:'"$DIVE_DUR"', ratio:"16:9", generate_audio:false}' \
251
+ > "$WORK/dive_$1.body.json"
252
+ rid=$(NO_COLOR=1 monid run -p bytedance -e /v1/video/seedance-2.0 \
253
+ -f "$WORK/dive_$1.body.json" -j | jq -r '.runId')
254
+ monid_wait "$rid" "$WORK/dive_$1.json"
255
+ url=$(jq -r '.output.content.video_url // empty' "$WORK/dive_$1.json")
256
+ [ -n "$url" ] && curl -fsSL "$url" -o "$WORK/dive_$1.mp4" \
257
+ && echo "dive $1 ok (\$$(jq -r '.cost.value' "$WORK/dive_$1.json"))" \
258
+ || echo "dive $1 FAIL ($(jq -r '.status' "$WORK/dive_$1.json"))"
259
+ }
260
+
261
+ gen_conn_monid() { # i startPng endPng
262
+ su=$(monid_frame_url "$2" "conn$1_start"); eu=$(monid_frame_url "$3" "conn$1_end")
263
+ jq -n --arg p "$(cat "$WORK/conn_$1.txt")" --arg s "$su" --arg e "$eu" --arg r "$VRES" \
264
+ '{content:[{type:"text",text:$p},
265
+ {type:"image_url",image_url:{url:$s},role:"first_frame"},
266
+ {type:"image_url",image_url:{url:$e},role:"last_frame"}],
267
+ resolution:$r, duration:'"$CONN_DUR"', ratio:"16:9", generate_audio:false}' \
268
+ > "$WORK/conn_$1.body.json"
269
+ rid=$(NO_COLOR=1 monid run -p bytedance -e /v1/video/seedance-2.0 \
270
+ -f "$WORK/conn_$1.body.json" -j | jq -r '.runId')
271
+ monid_wait "$rid" "$WORK/conn_$1.json"
272
+ url=$(jq -r '.output.content.video_url // empty' "$WORK/conn_$1.json")
273
+ [ -n "$url" ] && curl -fsSL "$url" -o "$WORK/conn_$1.mp4" \
274
+ && echo "conn $1 ok (\$$(jq -r '.cost.value' "$WORK/conn_$1.json"))" \
275
+ || echo "conn $1 FAIL ($(jq -r '.status' "$WORK/conn_$1.json"))"
276
+ }
277
+ ```
278
+
279
+ Default usage in §2/§4: same loops, `gen_dive_monid`/`gen_conn_monid` in place of
280
+ the Higgsfield `gen_dive`/`gen_conn` (mobile chain: `ratio:"9:16"` and the §6b
281
+ portrait canvases). Previz: same functions with `VRES=480p`.
282
+ Result URLs expire (~24–48 h) — the functions download immediately. Read the billed
283
+ `cost.value` per clip (echoed in the ok-line) and `monid balance` between phases; a
284
+ `BLOCKED` status is a workspace budget/run cap — terminal, surface it to the user.
285
+ Frame extraction, encoding, QA: identical to the Higgsfield path.
286
+
287
+ **Qualification harness for future/changed endpoints** (each probe = one cheap 480p
288
+ clip): (1) prompt + first_frame from a real still → downloaded video's frame 0 must
289
+ match the still (eyeball + PSNR ≳ 30 dB) and `cost.value` must match the advertised
290
+ cell; (2) add a last_frame from a *different* still → the final frame must land on
291
+ that composition (Seedance-style near-miss ok — the crossfade covers it). Known
292
+ failure to watch for (it's why the harness exists): `minimax /v1/video_generation`
293
+ still silently drops the image when `prompt` is present — image-only output proves
294
+ nothing about steerability.
295
+
296
+ ## Notes
297
+
298
+ - `.[0].result_url` is the field on the `--wait --json` job object. `.min_result_url` is
299
+ a lower-res preview if you ever want it.
300
+ - **NSFW fallback across models**: if one clip keeps getting flagged on seedance after
301
+ re-rolls + prompt scrubbing, regenerate just that clip on `kling3_0` with the SAME
302
+ start/end frames: `VMODEL=kling3_0; VOPTS="--mode std --sound off"; gen_conn 3 …` —
303
+ then restore your chain model. See SKILL Gotchas for the trade-off.
304
+ - **Previz on the cheap**: run the whole chain once with `VMODEL=seedance_2_0_mini`
305
+ (frame-locking intact, ~720p) to validate the journey and seams before spending
306
+ full-model credits — because it's still seamless, the previz translates directly to the
307
+ final render. Don't reach for reference-only models here: without `--start/--end-image`
308
+ they can't hold a seam, so their output can't be chained (Step 4 rule).
309
+ - If a whole batch stalls, check `higgsfield workspace list` for credits and
310
+ `$WORK/*.err` for the reason.
311
+ - Concurrency: launching ~5–6 gens at once is fine; much more can trigger transient
312
+ credit/race errors — stagger or re-roll.
@@ -0,0 +1,194 @@
1
+ # Prompt templates & intake
2
+
3
+ Everything here is fill-in-the-slots. Keep the **style preamble** byte-for-byte identical
4
+ across all scene stills — that identical text is what makes the world feel like one place.
5
+
6
+ ## Intake checklist (Step 1)
7
+
8
+ Collect and write down:
9
+
10
+ - `SUBJECT` — the business + one-line pitch.
11
+ - `BRAND_NAME` — display name.
12
+ - `PALETTE` — 4–6 named hexes, e.g. `taro #9B7EBD, cream #F5EDE0, caramel #C88A5A, matcha #8FB98A, plum #3A2E48`. Pick ONE as the scene **background** colour (usually the lightest) and one as the primary **accent**.
13
+ - `TONE` — a word or two (cozy/premium, playful, industrial…).
14
+ - `STYLE` — the art direction (default below).
15
+ - `SECTIONS[]` — ordered list; for each: `id`, `label`, `subject` (what's in the diorama), `eyebrow`, `title`, `body` (≤ 1 sentence), `tags[]` (0–3). Last section = hero product + CTA.
16
+ - `N` — scene count: 2 (teaser: opener + hero/CTA) | 4 (short journey) | 6 (full
17
+ film — **maximum**). **Always asked** (SKILL Step 1.5) before proposing the section
18
+ list. Assets = N stills + (2N−1) clips.
19
+ - `CAMERA` — fly-through (arch B: dives + aerial hops — the flagship-demo look) |
20
+ walkthrough (arch A: one continuous forward flight) | locked-iso (arch A + the
21
+ locked-iso clause below: one fixed angle for the whole film). **Always asked**
22
+ (SKILL Step 1.4), presented by feel with a one-line trade-off each.
23
+ - `MOBILE` — yes/no. **Always asked** (SKILL Step 1.6), presented to the user
24
+ with the ~2× credit cost stated. Yes = the **native 9:16 portrait chain**
25
+ (pipeline §6b): portrait renders of every dive/connector +
26
+ `clipMobile`/`connectorsMobile`/`stillMobile` wiring + the full mobile QA. The
27
+ §6 crop encodes are a no-credits stopgap only.
28
+ - `ASSET_SOURCE` — automatic (the skill renders: Higgsfield/Codex stills,
29
+ Monid/Higgsfield video) | manual (the skill writes every prompt file + the
30
+ conditioning frames; the user renders in tools of their choice and drops the
31
+ finished files into `$WORK`). **Always asked** (SKILL Step 1.7). On the manual
32
+ path `VIDEO_TIER`/`STILLS_SOURCE` below don't apply — but the user's video tool
33
+ must accept a start frame (and, for arch B connectors, an end frame).
34
+ - `VIDEO_TIER` — (automatic path only) default is `seedance_2_0` **via Monid**
35
+ (pay-per-clip; previz = same endpoint at 480p, final at 1080p).
36
+ Higgsfield-credit alternates: draft (`seedance_2_0_mini`) | standard
37
+ (`seedance_2_0`) | alternate (`kling3_0`). Chosen by cost at SKILL Step 1.8,
38
+ with the estimated total stated before anything renders.
39
+ - `STILLS_SOURCE` — (automatic path only) higgsfield (`gpt_image_2`, spends
40
+ credits) | codex (`image_gen`, subscription-billed; only offer when the Codex
41
+ CLI is present).
42
+
43
+ ## Style preamble (default: clay diorama)
44
+
45
+ Reuse verbatim in every scene prompt. Swap the bracketed bits for the brand's palette/bg.
46
+
47
+ ```
48
+ Isometric low-poly 3D diorama floating as a small rounded island on a plain solid
49
+ [BG_HEX] background with a soft contact shadow beneath it. Soft matte clay 3D render,
50
+ rounded toy-model shapes, gentle warm studio lighting, soft long shadows, tilt-shift
51
+ miniature look. Cohesive color palette of [PALETTE]. Highly detailed, centered
52
+ composition, absolutely no text, no letters, no numbers, no logos.
53
+ ```
54
+
55
+ Alternate directions (swap the first two sentences, keep the palette/no-text tail):
56
+ - **Flat papercraft:** "Isometric layered paper-craft diorama, matte cardstock, clean die-cut edges, subtle drop shadows between layers."
57
+ - **Glossy toy:** "Isometric glossy vinyl-toy diorama, smooth plastic shading, soft rim light, collectible figurine look."
58
+ - **Claymation:** "Isometric stop-motion clay set, visible thumbprints, handmade plasticine texture, soft studio softbox light."
59
+ - **Neon night:** "Isometric miniature at night, warm interior glow and neon signage, moody rim light, wet reflective ground."
60
+ - **Photoreal architectural** (real estate, hospitality, premium/luxury): "Ultra-photorealistic architectural photography of a single cohesive [subject], cinematic wide-angle, warm golden-hour light, natural materials, restrained designer furnishings, a breathtaking view, editorial magazine quality (Architectural Digest), shallow depth of field, no people." For photoreal, drop the floating-island framing and the knockout (Step 3) — the scenes are **full-bleed** (a dark page background reads premium), the "dive" glides *through doorways/glass* rather than opening a roof, and cohesion comes entirely from the identical preamble (do NOT pass an `--image` reference — it clones the same room). Interiors trip Seedance's NSFW filter often; see SKILL Gotchas.
61
+
62
+ ## Scene still prompt (Step 2)
63
+
64
+ Every prompt must be **fully self-contained**: on the manual path each still may be
65
+ rendered in a different tool or session, so the aspect ratio, the background lock and
66
+ the palette must live IN THE PROMPT TEXT — never rely on tool-side settings you can't
67
+ guarantee, and never strip these lines when adapting the template.
68
+
69
+ ```
70
+ [STYLE PREAMBLE]
71
+ Render a wide 3:2 landscape image, at least 1536 px wide. The background stays a plain
72
+ solid [BG_HEX] across the whole frame — a completely empty backdrop: no sky, no clouds,
73
+ no horizon, no gradient. Centered composition with a little headroom; the focal subject
74
+ horizontally centred and nothing essential at the far left/right edges. Absolutely no
75
+ text, no letters, no numbers, no logos.
76
+ Subject: [SECTION.subject — describe the miniature scene: the building/space, a few
77
+ characters doing the work, the props that signal this stage of the business].
78
+ ```
79
+
80
+ Tips:
81
+ - Name concrete props (they anchor the scene): tanks, cauldrons, conveyor, crates, awning, string lights, benches, scooters, map pins.
82
+ - For the final "hero product" section, drop the diorama-island framing and prompt a
83
+ single oversized product centerpiece floating on the same background with a few small
84
+ orbiting props.
85
+ - **Compose for the centre.** The page renders every clip `object-fit:cover`. Keep the
86
+ focal subject horizontally centred with a little headroom, and don't park anything
87
+ essential at the far left/right edges. Mobile ships its own native 9:16 chain
88
+ (pipeline §6b), so this is not about surviving a crop — but a centred composition makes
89
+ the portrait renders open cleanly from the same still, and it keeps the dive's focal
90
+ point where the camera actually flies.
91
+ - Automatic-path CLI flags: `--aspect_ratio 3:2 --resolution 2k --quality high`. The
92
+ prompt's own 3:2 + background-lock sentences still do the consistency work whenever a
93
+ still is rendered outside that CLI (manual path, another tool, a re-roll elsewhere).
94
+
95
+ ## Leg prompt — architecture A, continuous forward take (Step 4)
96
+
97
+ `--start-image = previous leg's ACTUAL last frame` (leg 0: the first scene's still).
98
+ **No `--end-image`.** The bolded clauses are the motion-handoff contract — keep them
99
+ verbatim; the mid-leg move is where the expression goes.
100
+
101
+ ```
102
+ Single continuous cinematic camera move, no cuts. **Continue the same slow, steady
103
+ forward glide.** [MID-LEG MOVE — optional, from the library below.] The camera moves
104
+ into [SCENE i] toward [FOCAL POINT]. **In the final second, settle back into a slow,
105
+ steady forward glide toward [the doorway / opening / direction of the next scene].**
106
+ [STYLE tail + PALETTE]. Smooth, graceful, slow motion, subtle parallax. No text, no captions.
107
+ ```
108
+
109
+ ### Mid-leg move library (pick by concept; omit for a plain glide)
110
+
111
+ Reversals are safe *inside* a leg (it's one continuous render) — only a seam may never
112
+ reverse. That's why "ease back out" is fine mid-leg.
113
+
114
+ **Locked-iso clause** (`CAMERA` = locked isometric glide — SKILL Step 1.4/Step 4):
115
+ skip this library entirely and put this clause, verbatim, in the mid-leg slot of
116
+ EVERY leg:
117
+
118
+ ```
119
+ The camera keeps exactly the same high isometric angle throughout — no rotation, no
120
+ orbit, no tilt. It only travels straight and level, the world sliding past beneath
121
+ the same view.
122
+ ```
123
+
124
+ Keep the handoff-contract clauses around it unchanged. When checking each leg's last
125
+ frame, also check the ANGLE hasn't drifted (Seedance rotates slightly on long legs) —
126
+ re-roll the leg if the view has turned.
127
+
128
+ - **Half-orbit** (product, luxury): "sweeping in a slow half-orbit around [the hero
129
+ object], keeping it centered, then continuing past it"
130
+ - **Crane-up reveal** (scale, atriums, campuses): "rising smoothly as the full scale of
131
+ [the space] reveals below"
132
+ - **Low lateral track** (production lines, counters, shelves): "tracking low and level
133
+ alongside [the line], foreground objects sliding past in parallax"
134
+ - **Push-in + ease back** (craft, detail): "pushing in close to [the craft moment] until
135
+ it nearly fills the frame, then easing gently back out"
136
+ - **Rise-and-swoop** (travel, outdoors): "climbing in a gentle arc over [the terrain],
137
+ then swooping down toward [the next focal point]"
138
+
139
+ After rendering each leg, **check its last frame** before generating the next: it should
140
+ read as a frame from a calm forward glide (no motion blur sideways, no half-finished
141
+ orbit). If it doesn't, re-roll this leg — a bad handoff frame poisons every leg after it.
142
+
143
+ ## Dive-in clip prompt (Step 4)
144
+
145
+ `--start-image = the scene still` (solid-bg version).
146
+
147
+ ```
148
+ Single continuous cinematic camera move, no cuts. Begin high and far, looking down at the
149
+ whole [SECTION.subject] from outside like a tiny model. The camera slowly glides forward
150
+ and descends toward it, sweeping in toward [FOCAL POINT — the counter/the cauldrons/the
151
+ people], as if flying inside. As the camera pushes in, the roof and upper structure
152
+ gently lift and open away to reveal the warm interior. The backdrop stays a plain solid
153
+ [BG_HEX] the whole time — completely empty, no sky, no clouds, no horizon, no ground.
154
+ [STYLE tail: soft matte clay diorama, tilt-shift miniature, warm light, [PALETTE]].
155
+ Smooth, graceful, slow motion, subtle parallax. No text, no captions.
156
+ ```
157
+
158
+ For scenes with no building to open (a field, a plaza, a road), replace the roof clause
159
+ with "the camera flies low across [the scene] toward [focal point]."
160
+
161
+ Params by chain model (SKILL Step 4 table): seedance —
162
+ `--mode std --resolution 1080p --aspect_ratio 16:9 --duration 8`, no audio flag;
163
+ kling3_0 — `--mode std --sound off --aspect_ratio 16:9 --duration 10` (no `--resolution`
164
+ param). Same for architecture-A legs.
165
+
166
+ ## Connector clip prompt (Step 5)
167
+
168
+ `--start-image = dive_i LAST frame` (extracted), `--end-image = dive_{i+1} FIRST frame`
169
+ (extracted). Both from the RENDERED videos, not the stills.
170
+
171
+ ```
172
+ Single continuous cinematic camera move, no cuts. The camera smoothly pulls up and back
173
+ out of [SCENE i], rising into the sky, then glides forward across the connected miniature
174
+ world and arrives above [SCENE i+1], beginning to descend toward it. One connected
175
+ miniature clay world floating in a plain solid [BG_HEX] void — empty backdrop, no sky,
176
+ no clouds — seamless flowing aerial transition. [STYLE tail + PALETTE]. Smooth
177
+ graceful slow motion. No text, no captions.
178
+ ```
179
+
180
+ For the last connector into a hero-product finale: "…glides forward and the world
181
+ dissolves toward a single giant [PRODUCT] floating in soft [BG] space, arriving in front
182
+ of it."
183
+
184
+ seedance: `--mode std --resolution 1080p --aspect_ratio 16:9 --duration 5`; kling3_0:
185
+ `--mode std --sound off --aspect_ratio 16:9 --duration 5`. Connectors need `--end-image`
186
+ → use a roster model that accepts it (Step 4).
187
+
188
+ ## Copy per section (for the engine config)
189
+
190
+ - `eyebrow` — 2–4 words, uppercase feel (a value-prop label).
191
+ - `title` — 3–6 words, the beat's headline. First section = the site's hero line; last =
192
+ the payoff + it carries the CTA.
193
+ - `body` — one sentence, plain-spoken, from the visitor's side.
194
+ - `tags` — 0–3 short proof chips (e.g. "Fresh-cooked", "30-min delivery").