@kolbo/kolbo-code-linux-arm64
Advanced tools
| # Color DNA — Brand Palette Grading | ||
| Load this file when the user works with Color DNA / color palettes: creating, activating, analyzing, or opting a generation out of palette grading. | ||
| Core contract (also in SKILL.md): **Color DNA is sticky and account-wide — at most one palette is active at a time**, and while one is active it strict-grades **every** image and video generation automatically, with no per-call argument. | ||
| Operational detail: | ||
| - `analyze_color_palette` pulls colors out of 1–5 image URLs **for free** and does **NOT** save anything — use it to draft a palette before creating one. | ||
| - `create_color_palette` defaults `is_active: true`, which activates the new palette and deactivates any other active one. | ||
| - Per-generation opt-out: `skip_color_palette: true` on `generate_image` / `generate_image_edit` / `generate_video` / `generate_video_from_image`. | ||
| - Manage with `list_color_palettes` / `update_color_palette` / `activate_color_palette` / `deactivate_color_palette` / `delete_color_palette` (edit in place — never delete+recreate). |
| # Kolbo Review — client review & approval collections | ||
| Load this file when the user wants **feedback on finished media**: send a cut to a client, | ||
| collect timestamped comments, run an approve / request-changes loop, ship a v2 against the | ||
| same feedback thread, or share work with someone who has no Kolbo account. This is a | ||
| Frame.io-style layer over the media library — assets, versions, comments, statuses, and | ||
| guest share links — all project-scoped like everything else in Kolbo. | ||
| Not for: publishing a page (`publish_html_artifact`), sharing a whole media folder | ||
| (`share_media_folder`), or internal doc collaboration (`share_doc`). | ||
| ## Tool inventory | ||
| | Tool | What it does | | ||
| |---|---| | ||
| | `create_review_asset` | New review asset with v1 media attached (`name`, `media_id`, optional `collection_id`, `version_note`). | | ||
| | `list_review_assets` / `get_review_asset` | Browse a project's review assets (filter by `collection_id` / `status`); fetch one with all versions + URLs. | | ||
| | `update_review_asset` | Rename, move to a collection (`collection_id: null` = uncollected), or switch `current_version_index`. | | ||
| | `add_review_version` | Append a new version to an existing asset from a `media_id`. | | ||
| | `set_review_status` | Workflow status: `in_progress` / `needs_review` / `approved` / `changes_requested`. | | ||
| | `delete_review_asset` | Soft-delete an asset AND its underlying review media. | | ||
| | `create_review_collection` / `list_review_collections` / `update_review_collection` / `delete_review_collection` | Folder layer. Deleting a collection is soft — its assets become uncollected, not deleted. | | ||
| | `create_review_comment` / `list_review_comments` / `reply_review_comment` / `edit_review_comment` / `delete_review_comment` | Text comments, optional video timecodes (`time_start` / `time_end`, seconds). One level of reply threading. | | ||
| | `resolve_review_comment` / `unresolve_review_comment` | Close / reopen a comment thread. | | ||
| | `create_review_share_link` / `list_review_share_links` / `revoke_review_share_link` | Guest links (no Kolbo account) for one asset or a whole collection. | | ||
| | `get_review_storage_usage` | `usedBytes` vs the 5GB review cap for the API-key owner. | | ||
| ## The core flow | ||
| ``` | ||
| upload_media (or reuse a generation's media_id from list_media) | ||
| → create_review_collection (only if grouping multiple assets) | ||
| → create_review_asset ← media becomes v1 | ||
| → set_review_status "needs_review" | ||
| → create_review_share_link ← hand the client the share_url | ||
| → list_review_comments ← read what came back | ||
| → fix → add_review_version ← v2 on the SAME asset | ||
| → resolve_review_comment on each addressed note | ||
| → set_review_status "approved" (usually the client does this via the link) | ||
| ``` | ||
| Media must already exist in the library — every attach point takes a `media_id` from | ||
| `upload_media` / `create_upload_ticket` / `media_upload_widget` / `list_media`, never a raw | ||
| URL or local path. | ||
| ## Version semantics | ||
| - Versions **append**; labels are auto-set `v1`, `v2`, … — you can't choose or reorder them. | ||
| - `add_review_version` automatically makes the new version current. Use | ||
| `update_review_asset({ current_version_index })` only to point BACK at an older cut. | ||
| - **Comments attach to a version's media**, not the asset. `list_review_comments` defaults | ||
| to the current version — after adding v2, pass `version_media_id` to re-read v1 feedback. | ||
| Comments do not carry forward; the v2 thread starts clean. | ||
| - Never delete+recreate an asset to "update" it — that orphans the comment history and | ||
| every share link already sent to the client. New cut = `add_review_version`. Rename / | ||
| re-file = `update_review_asset`. Delete is for abandoning the review entirely. | ||
| ## Share links — permissions and defaults | ||
| `create_review_share_link` targets an `asset` or a `collection` (collection links cover | ||
| every asset inside, including ones added later). Guest defaults if you pass nothing: | ||
| | Permission | Default | | ||
| |---|---| | ||
| | `canComment`, `canViewOtherComments`, `canSwitchVersions` | **true** | | ||
| | `canDownload`, `canResolveOwn`, `canSetStatus` | **false** | | ||
| | `require_email` | **true** — guests identify by email before viewing | | ||
| | `role_label` | `"Client"` (max 40 chars) | | ||
| - Want the client to approve directly? Pass `permissions: { canSetStatus: true }` — | ||
| otherwise they can only comment and you relay the verdict via `set_review_status`. | ||
| - Lockdown options: `password` (a NEW guest password — never an account credential), | ||
| `allowed_emails`, `expires_at` (ISO8601). | ||
| - Links are revoked by id (`revoke_review_share_link`), not edited — to change permissions, | ||
| create a new link and revoke the old one. This is the one place recreate IS the mechanism. | ||
| - When someone other than the owner sets a status, the owner gets a notification — don't | ||
| also announce it manually. | ||
| ## Storage — the 5GB cap | ||
| Review media is **copied into dedicated review storage** and counts against a flat 5GB cap | ||
| per account — separate from library storage. The cap is enforced on `create_review_asset` | ||
| AND `add_review_version`; hitting it returns `REVIEW_STORAGE_LIMIT` (413). That error is a | ||
| real limit, not a transient failure — don't retry. Check `get_review_storage_usage` | ||
| (`usedBytes` / `capBytes`) before bulk-adding large videos, and free space by deleting | ||
| finished review assets (the library originals are untouched). | ||
| ## Practical notes | ||
| - All of this is instant CRUD — no credits, no polling, no `get_generation_status`. | ||
| - Project contract applies: pass the same `project_id` you resolved via `list_projects` on | ||
| `create_review_asset` / `create_review_collection` / the list calls. | ||
| - `status` filter on `list_review_assets` takes exactly the four enum values — "pending" / | ||
| "done" are not statuses. | ||
| - Comment ids are `note_id` in the reply/edit/delete/resolve tools; version notes cap at | ||
| 1000 chars. | ||
| - Guests can only resolve their own comments, and only if you granted `canResolveOwn` — the | ||
| resolve loop on client feedback is normally yours to run after fixing. |
+1
-1
| { | ||
| "name": "@kolbo/kolbo-code-linux-arm64", | ||
| "version": "2.4.24", | ||
| "version": "2.4.25", | ||
| "os": [ | ||
@@ -5,0 +5,0 @@ "linux" |
@@ -21,3 +21,3 @@ <!-- PARITY: this file mirrors getCreativeDirectorPromptSystemPrompt() in | ||
| ### Identity & Style Locks | ||
| - **Visual DNA** — attach a character/product preset via `visual_dna_ids` to lock identity across all scenes. Up to **8 Visual DNAs** can be active at once (e.g. main character + product + side character). See `workflows/visual-dna.md` for the `@name` syntax — every DNA must be tagged inside the prompt. | ||
| - **Visual DNA** — attach a character/product preset via `visual_dna_ids` to lock identity across all scenes (e.g. main character + product + side character). The cap is per model — read `max_visual_dna` from `list_models`. See `workflows/visual-dna.md` for the `@name` syntax — every DNA must be tagged inside the prompt. | ||
| - **Moodboard** — attach `moodboard_id` (or `moodboard_ids`) for a curated mood/style reference that anchors the aesthetic of the whole batch. | ||
@@ -101,10 +101,4 @@ - When the user mentions a recurring character/product, **ask** if they want to use a Visual DNA and recommend it. Same for a consistent aesthetic → recommend a Moodboard. | ||
| For any ad / story / scene-based video **created from scratch** featuring a Visual DNA character, do NOT jump straight from DNA to per-shot video. The right flow is: | ||
| SKILL.md's frames-first rule applies. The Creative Director deltas: generate the frames via `generate_creative_director` with `workflow_type: "image"` (+ `scene_count`, `visual_dna_ids`), then animate each approved frame with `generate_video_from_image`, passing it as `image_url`. | ||
| 1. **Generate the shot frames first** as still images via `generate_creative_director` with `scene_count` + `visual_dna_ids` + `workflow_type: "image"`. DNA is strongest in image generation; the user can approve cheaply before any expensive video runs. | ||
| 2. **Confirm the frames with the user** if there are more than ~3 shots, or if the user hasn't said "go straight to video." | ||
| 3. **Animate each frame** with `generate_video_from_image`, passing each approved frame as `image_url`. | ||
| Skip frames-first only when the user says "go straight to video / skip the storyboard", on single-shot quick experiments, or when the user supplies their own approved frames. | ||
| ## UGC sets and thumbnail sets | ||
@@ -111,0 +105,0 @@ |
@@ -7,3 +7,3 @@ <!-- PARITY: this file mirrors getMusicPromptSystemPrompt() in | ||
| Load this file when the user wants AI-generated **music** — full songs, lyrics, instrumentals, jingles, scores, soundtracks, lo-fi beats, trailers, ad music. Primarily Suno; the same craft applies to other music models. For TTS / voice cloning see `models/prompt-copilot.md`. For sound effects see SKILL.md "Sound Effects". | ||
| Load this file when the user wants AI-generated **music** — full songs, lyrics, instrumentals, jingles, scores, soundtracks, lo-fi beats, trailers, ad music. Primarily Suno; the same craft applies to other music models. For TTS / voice cloning see `models/prompt-copilot.md`. For sound effects see `generate_sound` (SKILL.md tool table). | ||
@@ -10,0 +10,0 @@ **Kolbo MCP routing:** call `generate_music`. Suno is a model option — use `list_models({ type: "music_gen" })` to see versions. Pass `instrumental` and `duration` as separate params; pass the Style/Description text as `style` and the Lyrics as `lyrics`. |
@@ -104,3 +104,3 @@ <!-- PARITY: this file mirrors getPromptCopilotSystemPrompt() in | ||
| Model-dependent — always check `supported_aspect_ratios` on the model via `list_models` before passing a value. See SKILL.md "Resolution / Aspect / Duration — validate against caps". | ||
| Model-dependent — always check `supported_aspect_ratios` on the model via `list_models` before passing a value. See `references/workflows/cost-and-validation.md`. | ||
@@ -107,0 +107,0 @@ ### Safety / content policy |
@@ -28,3 +28,3 @@ <!-- PARITY: this file mirrors getSeedancePromptSystemPrompt() in | ||
| - **Order inside each shot**: Subject → Action → Camera → Constraints → (Audio/SFX if relevant). Do NOT restack GLOBAL LOOK style inside the shot. | ||
| - **Prompt length**: simple single-idea pieces ~120–280 words. Locked-intro cinematic typically 400–900 words. Shorter than ~120 words = random output. The 8000-char cap below always wins. | ||
| - **Prompt length**: simple single-idea pieces ~120–280 words. Locked-intro cinematic typically 400–900 words. Shorter than ~120 words = random output. The 10,000-char cap below always wins. | ||
| - **Shot count is user-directed.** If the user asks for N shots, deliver exactly N in one prompt unless they ask to split. | ||
@@ -34,8 +34,3 @@ - **Always describe at least one camera movement per shot.** | ||
| - **Final prompt is always English**, wrapped in a copy-ready code block. Detect intent in any language and reply in the user's language, but the prompt itself is English. | ||
| - **HARD CAP: 8000 characters TOTAL for the ENTIRE prompt** — measured as one single string, including ALL shots, ALL boilerplate, ALL SFX lines, the opening style block, the closing `Total: …` line, every newline, every space, every punctuation mark. This is non-negotiable. | ||
| - Applies to ANY prompt: 1 shot or 6 shots, single POV or full montage — the WHOLE thing must fit under 8000 chars combined. | ||
| - It is NOT 8000 chars per shot. It is 8000 chars per prompt. | ||
| - If your draft exceeds 8000 chars, trim aggressively in this order: (1) cut redundant adjectives, (2) collapse the opening cinematic boilerplate, (3) shorten SFX lists, (4) merge or drop shots — keep escalation beats and cut filler beats, (5) tighten action descriptions to verb-led essentials. | ||
| - **Never** split into multiple prompts, multiple code blocks, or "part 1 / part 2" to evade the cap. | ||
| - Before outputting, internally count the characters of the final prompt as a single string. If > 8000, rewrite tighter and re-count. Repeat until ≤ 8000. Only then show the user. | ||
| - **HARD CAP: 10,000 characters TOTAL for the ENTIRE prompt** — measured as one single string including all shots, boilerplate, SFX lines, and the Total lines. It is per PROMPT, not per shot. **Never** split into multiple prompts, code blocks, or "part 1 / part 2" to evade the cap. Count the final prompt before output; if over, trim (cut adjectives, collapse boilerplate, shorten SFX lists, merge or drop shots) and re-count until it fits. | ||
@@ -77,17 +72,7 @@ ## Locked Intro (DEFAULT for any multi-shot cinematic — including Elements) | ||
| When a Visual DNA exists, its exact `@DNA_name` IS the cast name — never place a nickname before it or substitute one later. For plain image refs use `@ImageN`. | ||
| ## OUTPUT CONTRACT (WINS — same as help widget) | ||
| ONE fenced prompt. Required shape or the turn failed: | ||
| 1. `N connected cinematic shots, Xs total, AR, Multishot ON` | ||
| 2. `Total: Xs / N shots / AR` | ||
| 3. GLOBAL LOOK → CAST → LOCATION → LOCATION MAP → CONTINUITY → PHYSICS (dense, before any shot) | ||
| 4. `SHOT 1 — 0:00–0:02 — …` through SHOT N; timecodes sum to Xs; continuity bridge after SHOT 1 | ||
| 5. Closing `Total: Xs / N shots / AR` + short POSITIVE LOCKS | ||
| 6. Tool call `duration` = Xs | ||
| FORBIDDEN: omitting Total / Multishot; "same character throughout" as the only lock; one fence per shot; `[0s]`/`[3s]` stubs; splitting a ≤15s story into multiple generations unless the user asks. | ||
| ## The 5 Formats | ||
| ## The 6 Formats | ||
@@ -254,3 +239,3 @@ ### 1. Transformations (highest-performing format) | ||
| - Multishot: FOV per segment + "no drift mid-segment"? | ||
| - 8000-char cap honored? | ||
| - prompt-cap honored? | ||
@@ -280,3 +265,2 @@ ## Grid Storyboard Mode (3×3 grid input) | ||
| - If user asked in any language other than English, write your explanation in their language but keep the prompt itself English. | ||
| - **Never exceed 8000 characters TOTAL for the entire prompt as one string** — that is the WHOLE prompt including every shot, every line of boilerplate, every SFX list, every newline. NOT 8000 per shot — 8000 for the prompt as one combined unit. Count before output. If over, rewrite tighter (cut adjectives, collapse boilerplate, merge or drop shots). NEVER split into multiple prompts / multiple code blocks / "part 1 / part 2" to work around the limit. | ||
@@ -294,2 +278,2 @@ ## Where to run in Kolbo | ||
| When a character must stay consistent, pair Seedance with Visual DNA via `generate_elements` (NOT `generate_video` — text-to-video silently drops `visual_dna_ids`). Use the exact literal `@DNA_name` as the character name in CAST and re-anchor every shot where it appears — never a nickname, alias, possessive (`Zohar's`), or spatial label (`the left man`). See `workflows/visual-dna.md`. For grid/storyboard inputs, the source frame is `@image1`. | ||
| When a character must stay consistent, pair Seedance with Visual DNA via `generate_elements` (NOT `generate_video` — text-to-video silently drops `visual_dna_ids`). `@DNA_name` tagging rules: see `workflows/visual-dna.md`. For grid/storyboard inputs, the source frame is `@image1`. |
@@ -23,3 +23,3 @@ <!-- PARITY: this file mirrors getSeedance25PromptSystemPrompt() in | ||
| - **Prompt cap 15,000 characters** for the entire prompt as one string (`max_prompt_length` in the catalog; Seedance 2.0 is 10,000). Verify with `list_models` rather than trusting this number — it was documented as 30,000 for months, which is double the real limit. | ||
| - **Up to 50 reference medias / Visual DNA mentions** (`@Name`, `@ImageN`, `#Moodboard`). Every referenced asset must be tagged in the prompt text. A rewrite that drops or renames a tag ( `@doron_fauda_1` → `DORON` / `the hero` ) is a failed turn — put the exact tag back. | ||
| - **Large reference / Visual DNA capacity** (`@Name`, `@ImageN`, `#Moodboard`) — read the exact caps from `max_visual_dna` / `elements_max_images` in `list_models`. Every referenced asset must be tagged in the prompt text. A rewrite that drops or renames a tag ( `@doron_fauda_1` → `DORON` / `the hero` ) is a failed turn — put the exact tag back. | ||
| - **Multimodal refs:** images + video clips + audio can all anchor one generation. | ||
@@ -26,0 +26,0 @@ |
@@ -18,3 +18,3 @@ <!-- PARITY: this file mirrors getVeoPromptSystemPrompt() in | ||
| - **Aspect ratio, resolution, and clip length are MCP-tool params** (`aspect_ratio`, `resolution`, `duration`). **NEVER include "16:9", "9:16", "720p", "1080p", "4 seconds", "8s", or any duration / aspect / resolution string inside the prompt body.** | ||
| - Pass `sound_enabled: true/false` as a separate param when the user mentions audio — see SKILL.md "Sound on/off". | ||
| - Pass `sound_enabled: true/false` as a separate param when the user mentions audio — see `workflows/cost-and-validation.md`. | ||
| - Don't write Python / Vertex AI / API call syntax. The user is generating through Kolbo's MCP tools. | ||
@@ -21,0 +21,0 @@ |
@@ -11,5 +11,5 @@ # Cost Awareness, Validation & Constraints | ||
| |------|-------------|-------------|---------| | ||
| | **Image** | per image (flat) | 1–30 cr | Flux.1 Fast = 1 cr, Midjourney = 4 cr. If `resolution` is set, check `resolutionMultipliers` — some families multiply cost significantly at higher tiers. | | ||
| | **Image** | per image (flat) | 1–30 cr | Flux.1 Fast = 1 cr, Midjourney = 4 cr. If `resolution` is set, check `resolution_multipliers` — some families multiply cost significantly at higher tiers. | | ||
| | **Image edit** | per image (flat) | 2–20 cr | | | ||
| | **Video** | **cr/s × duration** | 2–30 cr/s | Kandinsky 5 Fast × 5s = 10 cr; Seedance 2.0 × 10s = 300 cr. Check `resolutionMultipliers` + `soundCreditMultiplier`. | | ||
| | **Video** | **cr/s × duration** | 2–30 cr/s | Kandinsky 5 Fast × 5s = 10 cr; Seedance 2.0 × 10s = 300 cr. Check `resolution_multipliers` + `sound_credit_multiplier`. | | ||
| | **Video from image** | **cr/s × duration** | 4–30 cr/s | Same per-second rule. | | ||
@@ -32,3 +32,3 @@ | **Elements (ref-to-video)** | **cr/s × duration** | 4–30 cr/s | Check `credit` and multipliers in `list_models type="elements"`. | | ||
| - **Images / 3D / Sound effects**: `total = model_credit × quantity`. | ||
| - **Resolution / audio multipliers**: if `resolution` is set or model has native audio, read `resolutionMultipliers[tier]` and `soundCreditMultiplier`. Formula: `final = base × resolutionMult × (sound ? soundMult : 1) × durationSeconds`. | ||
| - **Resolution / audio multipliers**: if `resolution` is set or model has native audio, read `resolution_multipliers[tier]` and `sound_credit_multiplier`. Formula: `final = base × resolutionMult × (sound ? soundMult : 1) × durationSeconds`. | ||
@@ -43,4 +43,3 @@ ### Tier label → pixel mapping (rough) | ||
| **Skip cost confirmation when:** | ||
| - The user already specified model + count + duration ("make 5 videos, seedance 2 fast, 15s" IS the confirmation). | ||
| - A single generation costs under 5 credits. | ||
| - Model + count + aspect + creative direction are already pinned by the user ("make 5 videos, seedance 2 fast, 15s" IS the confirmation). | ||
@@ -58,18 +57,4 @@ **Required cost confirmation when:** | ||
| Pre-flight formulas above are for **preview only**. After firing, every generation returns `credits_used` (multiplier-adjusted total) and `credits_breakdown` (per-model attribution). | ||
| Pre-flight formulas above are for **preview only** — after firing, quote the returned `credits_used`, never `base × count`. Log `credits_used`, resolution, duration and sound state per entry — format in `production-log.md`. | ||
| ```json | ||
| { | ||
| "credits_used": 12, | ||
| "credits_breakdown": [ | ||
| { "model": "nano-banana-2", "base": 8, "final": 12, ... } | ||
| ], | ||
| "urls": [...] | ||
| } | ||
| ``` | ||
| **Log `credits_used` to `.kolbo/production.md`**, not `base × count`. The multiplier-adjusted number is the only truth. | ||
| When the user asks "how much did I spend?" → call `get_session_usage` for the real, multiplier-adjusted session total + per-tool + per-model breakdowns (same numbers as the desktop bottom-bar counter). | ||
| ## Validation Pattern — Every Generation | ||
@@ -139,7 +124,2 @@ | ||
| Production-log entries should include the resolution and (for video) duration + sound state alongside the URL, so the user can see what they paid for: | ||
| ```md | ||
| - still: https://...01-coffee.png (flux-2-pro · 1K, 2026-05-14) | ||
| - video: https://...02-rain.mp4 (kling-2 · 1080p · 5s · sound-off, 2026-05-14) | ||
| ``` | ||
| Log `credits_used`, resolution, duration and sound state per entry — format in `production-log.md`. |
@@ -125,3 +125,3 @@ # DTC Ads — Composed Brand Image Workflow | ||
| 4. **Always log products + brand kits in `.kolbo/production.md`** so future ads reuse instead of re-uploading / re-scraping. | ||
| 5. **No auto-retry on failure** — surface the reason and let the user adjust. | ||
| 5. **Retries:** one retry only when `failure.retryable === true` or the generation completed with empty URLs (SKILL.md "⚠️ Generation lifecycle"); otherwise surface the reason and let the user adjust. | ||
| 6. **Strict NO uninvited additions** in every ad prompt: "NO captions, NO subtitles, NO watermarks, NO extra text beyond what's specified." |
@@ -33,2 +33,11 @@ # Filmmaking Router | ||
| Craft packs named in the table above (load only what the shot needs): | ||
| [scene-engine.md](references/filmmaking/scene-engine.md) · | ||
| [asset-preproduction.md](references/filmmaking/asset-preproduction.md) · | ||
| [acting-direction.md](references/filmmaking/acting-direction.md) · | ||
| [blocking-continuity.md](references/filmmaking/blocking-continuity.md) · | ||
| [cinematography.md](references/filmmaking/cinematography.md) · | ||
| [physics-action.md](references/filmmaking/physics-action.md) · | ||
| [audio-dialogue-music.md](references/filmmaking/audio-dialogue-music.md) | ||
| For Seedance 2.5, always read [seedance-2-5.md](references/models/seedance25.md) before final compilation. Treat capability numbers as a dated adapter snapshot and verify them against current provider/catalog truth when real money or production delivery depends on them. | ||
@@ -56,26 +65,2 @@ | ||
| ## Choose control density | ||
| Never equate sophistication with maximum length. | ||
| - **Strict** — lock exact blocking, count, timing, dialogue, hand/prop state, axis, scale, or failure-prone physics. Use for continuity-heavy dialogue, expensive hero shots, repeated failures, and exact music synchronization. | ||
| - **Anchored** — dictate non-negotiable story/continuity/physics anchors and allow camera or performance variation inside them. Use for complex spectacle where controlled discovery is valuable. | ||
| - **Exploratory** — protect identity, world, safety, and essential beats while inviting coverage variations. Use for montage, inserts, music-video coverage, and ideation. | ||
| If the user supplied an exact prompt, preserve its chosen density unless the failure diagnosis proves density itself is the problem. | ||
| ## Select craft packs | ||
| Load only what the shot needs: | ||
| - Story causality and scene reversals: [scene-engine.md](references/filmmaking/scene-engine.md) | ||
| - Asset building, versions, and stress tests: [asset-preproduction.md](references/filmmaking/asset-preproduction.md) | ||
| - Character performance, listening, and voice identity: [acting-direction.md](references/filmmaking/acting-direction.md) | ||
| - Geography, axes, eyelines, diagrams, and state continuity: [blocking-continuity.md](references/filmmaking/blocking-continuity.md) | ||
| - Shot size, optics, operator behavior, and visual grammar: [cinematography.md](references/filmmaking/cinematography.md) | ||
| - Action feasibility, mass, materials, transformations, and impossible shots: [physics-action.md](references/filmmaking/physics-action.md) | ||
| - Dialogue, ambience, native audio, source-song performance, and post music: [audio-dialogue-music.md](references/filmmaking/audio-dialogue-music.md) | ||
| Do not paste every craft pack into every prompt. Translate the selected pack into the shortest observable instructions that preserve the intended result. | ||
| ## Compile a shot | ||
@@ -97,3 +82,3 @@ | ||
| Prompt-length limits apply to the entire compiled generation prompt as one string, including whitespace, headers, timecodes, dialogue, audio, and locks. Count after compilation. For the current Seedance 2.5 adapter snapshot, the hard ceiling is 30,000 characters; never borrow that number for another model. | ||
| Prompt-length limits apply to the entire compiled generation prompt as one string, including whitespace, headers, timecodes, dialogue, audio, and locks. Count after compilation; read the cap from `max_prompt_length` via `list_models` (see `models/seedance25.md`). | ||
@@ -100,0 +85,0 @@ **Seedance 2 / Seedance 2.5 / `generate_elements` — Locked Intro is the only compile shape.** Read `references/models/seedance.md` (and `seedance25.md` for 2.5 caps). Do not emit the SCENE CONTEXT / OPTICS / ACTION department pack below as the generation prompt. Every Visual DNA in play must be `@ExactName` in CAST and in each shot — never "the left man" or a possessive. |
@@ -47,12 +47,14 @@ # Marketing Studio — UGC, Ads & Branded Video | ||
| | Mode | Primary tool | aspect_ratio | duration | sound_enabled | Captions / watermarks | | ||
| |---|---|---|---|:-:|:-:| | ||
| | `ugc`, `ugc_how_to`, `ugc_unboxing`, `ugc_virtual_try_on`, `product_review` | `generate_video_from_image` (frame-first) OR `generate_elements` (Visual DNA → video) | **`9:16`** | model's `default_duration` (5–8s) | OFF | **Never add** | | ||
| | `product_showcase` | `generate_creative_director` with `workflow_type: "video"` (for multi-shot) OR `generate_video` (single) | `16:9` or `1:1` | 5–10s | ON if model supports `sound_generation_type: "native"` | Allowed if user asks | | ||
| | `tv_spot` | `generate_creative_director` with `workflow_type: "video"` (3–6 shots for a beat structure) | `16:9` | 15–30s total | ON (full audio + dialogue) | Allowed if part of the spot | | ||
| | `virtual_try_on` | `generate_elements` with character Visual DNA + product as `reference_images` | `9:16` or `4:5` | 5–8s | OFF | Never add | | ||
| | `wild_card` | User's chosen model with broader prompt latitude (no mode-specific defaults) | User's pick | User's pick | User's pick | User's pick | | ||
| | Mode | Primary tool | | ||
| |---|---| | ||
| | `ugc`, `ugc_how_to`, `ugc_unboxing`, `ugc_virtual_try_on`, `product_review` | `generate_video_from_image` (frame-first) OR `generate_elements` (Visual DNA → video) | | ||
| | `product_showcase` | `generate_creative_director` with `workflow_type: "video"` (for multi-shot) OR `generate_video` (single) | | ||
| | `tv_spot` | `generate_creative_director` with `workflow_type: "video"` (3–6 shots for a beat structure) | | ||
| | `virtual_try_on` | `generate_elements` with character Visual DNA + product as `reference_images` | | ||
| | `wild_card` | User's chosen model with broader prompt latitude (no mode-specific defaults) | | ||
| **Pick the actual model** with `list_models({ type: "..." })` and validate caps before firing — see SKILL.md "Resolution / Aspect / Duration — validate against caps". | ||
| Aspect / duration / sound / captions defaults for the `ugc*` family live in "UGC Family Defaults" below. | ||
| **Pick the actual model** with `list_models({ type: "..." })` and validate caps before firing — see `references/workflows/cost-and-validation.md`. | ||
| ## The Look Itself — read `workflows/ugc-smartphone.md` | ||
@@ -153,4 +155,3 @@ | ||
| - One aspect ratio across all slots (UGC = `9:16`). Never mix. | ||
| - **No on-image text**, captions, subtitles, watermarks, or lower-thirds (users add captions in post). | ||
| - **Identity lock**: same presenter, same wardrobe, same lighting environment across all slots — open the prompt with `same character throughout all shots`. | ||
| - **Identity lock**: same presenter, same wardrobe, same lighting environment across all slots — bind identity by tagging `@<dna-name>` in every slot description (identity binds via the DNA; the phrase "same character throughout all shots" is FORBIDDEN — see `models/seedance.md`). | ||
| - Hands and product must read cleanly — no deformed hands, no floating / clipping product, product logo legible when held. | ||
@@ -188,3 +189,3 @@ - Phone-shot aesthetic (handheld sway, window/screen key) unless the mode is polished (`tv_spot`, `product_showcase`). | ||
| 1. Ensure/create presenter Visual DNA (tech-savvy woman) → `visual_dna_id`. | ||
| 2. Board: `generate_image` a 3-panel `16:9` sheet — (a) chest-up hook holding the serum, (b) hands applying it, (c) thumbs-up reaction — `same character throughout all shots`, locked to the DNA. → `board_media_id`. | ||
| 2. Board: `generate_image` a 3-panel `16:9` sheet — (a) chest-up hook holding the serum, (b) hands applying it, (c) thumbs-up reaction — `@<dna-name>` tagged in every panel description, locked to the DNA. → `board_media_id`. | ||
| 3. Slots (each `9:16`, ~5s, sound OFF, animate from the matching board panel + product `@image2`): | ||
@@ -200,5 +201,4 @@ - Slot 1 (hook): "Before this serum my routine was five products…" holding it to camera. | ||
| 2. **Always confirm aspect ratio + duration + sound** before firing — these materially change output and cost. One question, labeled options. | ||
| 3. **Default UGC settings are hard rules** — captions OFF, music OFF, watermarks OFF — even when the user doesn't mention them. Only flip when they ask. | ||
| 4. **No auto-retry on failure.** If the generation fails (content policy, model OOM), surface the reason and let the user adjust prompt or product. | ||
| 5. **Show results without dumping URLs** — see SKILL.md "Generated URLs in chat". | ||
| 3. **Retries:** one retry only when `failure.retryable === true` or the generation completed with empty URLs (SKILL.md "⚠️ Generation lifecycle"); otherwise surface the reason and let the user adjust prompt or product. | ||
| 4. **Show results without dumping URLs** — see SKILL.md "Generated URLs in chat". | ||
@@ -205,0 +205,0 @@ ## Prompt Template Seed for UGC |
@@ -73,3 +73,3 @@ # Media Library | ||
| |---|---| | ||
| | "Upload this file" / "host this" / "give me a public URL for this" | `upload_media` — but see "Local files" below if it's a path on the user's disk | | ||
| | "Upload this file" / "host this" / "give me a public URL for this" | `upload_media` — but see "Local files" above if it's a path on the user's disk | | ||
| | "Show my media" / "list my images/videos" / "what do I have?" | `list_media` (pass `type` / `category` / `project_id` / `folder_id` / `search`) | | ||
@@ -114,1 +114,11 @@ | "Show my favorites" / "list starred items" | `list_media` with `category=favorites` | | ||
| 10. **`get_media` accepts a generation_id as a fallback** for the `media_id` arg, so you can chase down items the user references by their original generation rather than by library id. | ||
| ## SYNCI licensed music — operational detail | ||
| The `*_music_library` tools (`search_music_library` / `browse_music_library` / `get_music_library_facets` / `get_music_track_audio` / `get_music_track_lyrics` / `get_music_track_related` / `analyze_script_for_music` / `acquire_clean_music_track` / `import_music_track_to_library`) front **SYNCI**, a commercially licensed catalog — not free stock. | ||
| - Discovery and previews are free but **watermarked** — there is no unwatermarked URL until you pay. | ||
| - `acquire_clean_music_track` **CHARGES CREDITS** for the clean master. Confirm with the user first, and pass a stable `requestId` so a retry doesn't buy the track twice. | ||
| - `import_music_track_to_library` charges the same way AND also copies the clean track into the media library. | ||
| - `analyze_script_for_music` turns a script into search terms for `search_music_library`. | ||
| - Use this family when the user needs music cleared for commercial use. When free stock will do, use `search_stock_media` with `mediaType: "music"` instead. |
@@ -64,3 +64,3 @@ # Product Photoshoot — Brand Product Imagery | ||
| **Always validate** `aspect_ratio` and `resolution` against the chosen model's `supported_aspect_ratios` / `supported_resolutions` via `list_models` — see SKILL.md "Resolution / Aspect / Duration — validate against caps". | ||
| **Always validate** `aspect_ratio` and `resolution` against the chosen model's `supported_aspect_ratios` / `supported_resolutions` via `list_models` — see `references/workflows/cost-and-validation.md`. | ||
@@ -67,0 +67,0 @@ ## Pre-Generation Interview (CRITICAL) |
@@ -41,17 +41,5 @@ # Production Log — `.kolbo/production.md` | ||
| If they did not volunteer a yes, end the turn with a **GATE** the next message can | ||
| parse (same contract as `production-planning.md`): | ||
| If they didn't volunteer a yes, end the turn with the GATE block from | ||
| `production-planning.md` §3. | ||
| ``` | ||
| GATE — <bucket name> | ||
| Presented: <what is in play> | ||
| Lock + next: "lock <bucket>" / "yes" / "next" / "now <next bucket>" | ||
| Stay: "redo @name" / "another take of …" | ||
| ``` | ||
| Confirmation the agent may treat as a lock: `yes`, `ok`, `lock`, `approved`, | ||
| `that's the one`, `use take 2`, `next`, `go`, `continue`, or they name the next | ||
| planned bucket while treating this set as done. Silence / "maybe" / a new | ||
| question is **not** a lock — repeat the GATE once, do not invent a yes. | ||
| **If the user genuinely doesn't care** — "whatever you think", "you pick", "don't care", or they hand you the whole job — then **you decide**. Choose, say in one line which you picked and why, and log it as usual with `(agent-selected)`. Do not stall a production waiting for an approval the user has already delegated to you. | ||
@@ -58,0 +46,0 @@ |
@@ -146,7 +146,8 @@ <!-- PARITY: the asset-first rule and the model defaults here are mirrored in | ||
| - **`generate_elements` with Seedance 2.5** (`seedance-2-5`) for the film itself — | ||
| up to 30s and 30 shots in ONE generation, up to 20 Visual DNAs, dialogue and SFX | ||
| baked in. `generate_video` also accepts `visual_dna_ids` now; Elements remains | ||
| the primary reference-driven route. | ||
| - **Seedance 2.0** (`seedance-2`, cheaper, 4–15s, 9 DNAs) when the piece is short | ||
| and the cast is small. `seedance-2-fast` / `seedance-2-mini` for cheap blocking. | ||
| up to 30s and 30 shots in ONE generation, dialogue and SFX baked in. DNA cap: | ||
| read `max_visual_dna` from `list_models`. `generate_video` also accepts | ||
| `visual_dna_ids` now; Elements remains the primary reference-driven route. | ||
| - **Seedance 2.0** (`seedance-2`, cheaper, 4–15s, smaller DNA cap per | ||
| `list_models`) when the piece is short and the cast is small. | ||
| `seedance-2-fast` / `seedance-2-mini` for cheap blocking. | ||
| - Every DNA in `visual_dna_ids` must also appear as `@ExactName` in the prompt. | ||
@@ -153,0 +154,0 @@ - Dialogue in quotes inside its shot beat — English only, never TTS or lipsync. |
@@ -8,3 +8,3 @@ # Thumbnails — YouTube, Shorts, Reels, TikTok covers | ||
| A thumbnail is not a nice image at small size. It is a different craft with a different | ||
| success test: **it is judged at ~200px inside a scrolling feed, next to a hundred others.** | ||
| success test: **it is judged at ~168px inside a scrolling feed, next to a hundred others.** | ||
| Everything below follows from that. | ||
@@ -14,50 +14,108 @@ | ||
| ## ⚠️ Two things to get right before advising anyone | ||
| **1. The metric is watch time, not clicks.** YouTube's own A/B thumbnail test optimises | ||
| "for overall watch time over other metrics, like click-through rate." A thumbnail that | ||
| wins the click and loses the viewer *loses the test*. This is the mechanical reason the | ||
| shock-face era ended. Never promise something the video does not deliver — it is both a | ||
| spam-policy violation ("malicious clickbait" names thumbnails explicitly) and a test loss. | ||
| **2. Most thumbnail statistics online are fabricated.** This topic is saturated with | ||
| AI-generated SEO spam inventing authoritative-looking numbers ("47.3% of creators…", | ||
| "9% vs 4% CTR study…", "70% higher CTR for dark thumbnails"). Traced individually, they | ||
| have no source. **Do not quote a thumbnail statistic to a user unless it is in this file.** | ||
| Everything below is graded: **[A]** real study/primary source · **[A?]** real study, but | ||
| its page could not be opened directly — figures corroborated only via secondary quotes, | ||
| so treat as directional, not exact · **[B]** credible practitioner claim · **[C]** craft | ||
| convention, no data. | ||
| Also useful to know: CTR *falling* as a video spreads is normal, not failure — early | ||
| impressions come from subscribers, then Browse/Suggested reach cold viewers. Half of all | ||
| channels sit between **2% and 10% CTR**. **[A]** | ||
| --- | ||
| ## The four layers | ||
| Every thumbnail that works has exactly these, in this order of importance. | ||
| ### 1. ONE hero subject | ||
| ### 1. ONE hero subject — 40–70% of the frame | ||
| A face with one **legible** emotion, or a single object caught mid-action. Crop tight. | ||
| A face with a big, readable emotion (eyes visible, mouth doing something), or a single | ||
| object caught mid-action. Crop tight — chest-up for a person. | ||
| **Faces scale with performance.** In a study of 500 breakout videos: 69% used a face, | ||
| rising to 75% of the top 100 and **80% of the top 50**. Face occupies about **one third | ||
| of the frame** in that top cohort. **[A?]** — the direction (faces matter, and matter more | ||
| at the top) is safe; the exact percentages are not verified at source. | ||
| Kill on sight: full-body wide shots, three competing focal points, a floating UI panel, an | ||
| abstract gradient, "a person at a desk". If the concept has no surprise, wit, or | ||
| impossibility in it, it will not stop a scroll — write the concept as one sentence first, | ||
| and if that sentence is boring, invent harder before generating. | ||
| **The exaggerated shocked face is dead as a default.** Only ~5% of those breakouts used | ||
| an exaggerated expression; 6% of the top 50. MrBeast's team A/B tested ~30 videos | ||
| open-mouth vs closed-mouth — **every closed-mouth version produced higher watch time**, | ||
| and they changed the channel's house style permanently. **[A]** | ||
| ### 2. Extreme separation | ||
| So: **a clear face beats a wild face.** Direct the expression to *one* readable emotion — | ||
| closed-mouth determination, a genuine restrained smile, focused concentration, real | ||
| scepticism. Direct eye contact into the lens, unless the gaze is deliberately pointing at | ||
| the subject. Forbid in the prompt: gaping "O" mouth, bulging eyes, strained forehead, | ||
| raised chin, any look of discomfort or effort. | ||
| The subject must pop off the background: a dark field behind a bright subject, or one | ||
| saturated accent against its complement. **Mid-tone on mid-tone is the number-one | ||
| unreadable-thumbnail failure.** Muted, tasteful palettes lose in a feed. | ||
| **Legibility test:** at 168×94, can someone name the emotion in under a second? | ||
| ### 3. Text — 2 to 4 words, maximum | ||
| **Faces are not mandatory** — 31% of breakouts had none. If the subject is a tool, an | ||
| interface, or a generated frame, the object can be the hero. | ||
| - Quote the exact words in the prompt: `render only this text: "STOP DOING THIS"`. | ||
| - Topmost layer, above every element and effect. | ||
| - Roughly **35–45% of the canvas width**. Heavy condensed sans. | ||
| - White or a single accent colour with a **thick dark outline or a solid backing bar** — | ||
| raw text on a busy image is illegible small. | ||
| - Upper or lower third. **Never across the face.** | ||
| - Forbid everything else explicitly: `no other text, no taglines, no watermark, no logo, | ||
| no captions, no placeholder text`. | ||
| Kill on sight: three competing focal points, a floating UI panel over an abstract | ||
| gradient, "a person at a desk". If the concept has no surprise, wit, or impossibility in | ||
| it, invent harder before generating. | ||
| Long strings come back mangled from every image model. If the user wrote a sentence, put | ||
| three words on the image and tell them the rest belongs in the video title. For brand | ||
| names, spell them letter-by-letter in the prompt and raise quality when the type is small. | ||
| ### 2. Separation — luminance first, hue second | ||
| **Depth trick:** let the subject overlap one word slightly (subject in front of one | ||
| letter). Instant production value. | ||
| **Greyscale test: desaturate the thumbnail. If the subject stops separating from the | ||
| background, no palette will save it.** Complementary pairs (orange/teal, blue/orange) | ||
| work mostly because they *also* carry a luminance gap. | ||
| - **Three dominant colours maximum, text included.** **[B]** | ||
| - **Restrain saturation.** The over-saturated HDR/clarity look — "exaggerated vibrancy, | ||
| bright lighting and sharp contrast" — is now documented as the visual signature of | ||
| AI-generated imagery, inherited from advertising imagery in training data. **[A]** | ||
| Push *luminance* contrast hard; keep saturation on one or two accent elements only. | ||
| - **Check on both YouTube themes.** The UI is near-white or near-black with red accents. | ||
| A dark vignette that separates your subject in dark mode can vanish in light mode. | ||
| Saturated red as a dominant field reads as UI chrome, not content. | ||
| - A single-hue thumbnail is *not* automatically weak — Kurzgesagt and MKBHD ship | ||
| near-monochrome successfully. What fails is a single hue with no luminance separation. | ||
| ### 3. Text — often none at all | ||
| The real distribution among breakout thumbnails: **28% had no text** (the largest single | ||
| group), **24% had 1–3 words**, median among those that had any was 5. **[A?]** Over half | ||
| carried three words or fewer. The ubiquitous "3–5 bold words" advice describes a minority. | ||
| - **Drop text entirely** when the image already states the promise and the title carries | ||
| the specifics. Text is a crutch for a thumbnail that hasn't found its image. | ||
| - **Three words maximum** when used. Never repeat the title — the title is right next to | ||
| it. Text should add the *second half* of an idea the image starts. | ||
| - Quote the exact words in the prompt: `render only this text: "…"`, and forbid the rest: | ||
| `no other text, no taglines, no watermark, no logo, no captions, no gibberish letters`. | ||
| - Heavy-weight sans, one typeface. Cap height ≈ **12–15% of frame height**. | ||
| - **Always** an outline, drop shadow, or solid colour block behind it. | ||
| - Placement: top third or the side opposite the face. **Never the bottom-right quadrant.** | ||
| - Let the subject overlap one letter slightly — instant depth. | ||
| Long strings come back mangled from every image model. If words garble twice, generate the | ||
| plate **text-free** and set type in the Canvas tool or in HTML — a clean plate plus real | ||
| type beats a third mangled attempt. Logos are the same: **image models cannot render a | ||
| real brand mark.** Generate the plate without it and composite the actual logo file. | ||
| ### 4. Platform-safe composition | ||
| | Format | Rules | | ||
| | Zone | Rule | | ||
| |---|---| | ||
| | **16:9 — YouTube** | Centre-weighted. Nothing critical in the outer 15%: the duration chip sits bottom-right and the red progress bar covers the bottom edge on watched videos. | | ||
| | **9:16 — Shorts / Reels / TikTok** | Every critical element must survive a **centre-square crop** (feeds and grids crop vertical media to its middle). Keep the top ~15% and the bottom ~20% clear of the platform's title, avatar, caption and buttons. | | ||
| | **1:1** | Community posts and square feeds. | | ||
| | **Bottom-right corner** | Duration chip sits here. Nothing important. | | ||
| | **Bottom edge, full width** | Red progress bar on partially-watched videos. Keep critical content ≥40px off the bottom (at 1280×720 scale). | | ||
| | **Overall safe area** | Everything load-bearing inside the centre ~1100×620 of a 1280×720 canvas. | | ||
| | **9:16 — Shorts/Reels/TikTok** | Must survive a **centre-square crop** (grids and cross-posts crop vertical media to the middle). Keep the top ~15% and bottom ~20% clear of platform UI. | | ||
| | **Validate at** | **168×94 px** — the desktop suggested-videos render size. Not 1280×720. | | ||
| **Verification is a release gate, not a suggestion:** view the render at ~200px, and for | ||
| 9:16 crop the centre square first. If the words or the face don't survive, iterate. | ||
| **File spec (updated — most guides are stale):** YouTube now recommends **3840×2160**, | ||
| minimum width 640px, file cap **50 MB** on desktop. Driven by TV overtaking mobile as the | ||
| primary US YouTube device in Feb 2025. **Export at 4K; design for 168px.** **[A]** | ||
@@ -68,7 +126,40 @@ --- | ||
| Text fidelity is the entire constraint. Pick the image model that renders type most | ||
| reliably, and raise the quality setting when the words are small or multi-font. If the | ||
| words come back garbled twice, generate the image **text-free** and tell the user to set | ||
| the type in the Canvas tool — a clean plate plus real type beats a third mangled attempt. | ||
| Text fidelity is the constraint. `gpt-image-2` is the strongest for type — use | ||
| **quality: medium** (its sweet spot) or high, and it handles **Hebrew** notably better | ||
| than the alternatives. `nano-banana-2` is strong on cinematic people but weak on text. | ||
| For a text-free plate, either is fine and the cheaper one wins. | ||
| **Field result (Aug 2026, head-to-head, same prompt/refs/1K):** `nano-banana-2` beat | ||
| `gpt-image-2` on BOTH photorealism (looked like a real studio photo, not a render) and | ||
| reference-mark fidelity — and rendered a short Hebrew headline + Latin badge cleanly. | ||
| The "weak on text" caveat applies to long/dense copy, not a 3-word headline. When a | ||
| thumbnail is a photographic person + short text + referenced logos, run both models | ||
| once and pick — do not assume gpt-image-2 wins by default. | ||
| Lock the host with a **character Visual DNA** (`workflows/visual-dna.md`) so every | ||
| thumbnail in a series is the same person — and check you are using the DNA of the person | ||
| *as themselves*, not a costumed character DNA built for a film shoot. | ||
| ## Kolbo brand-asset kit — reuse these, do not rediscover them | ||
| Learned the hard way (Time Machine tutorial thumbnail, Aug 2026): re-deriving logo | ||
| files and the right Visual DNA from scratch every session, then patching AI mis-draws | ||
| with HTML overlays, is slow and produces a worse result than just generating natively | ||
| with the right references from the start. Check this list before generating anything | ||
| with a Kolbo or model logo, or with Zohar's likeness, in it. | ||
| | Asset | Where | Status | | ||
| |---|---|---| | ||
| | Kolbo K icon — **THE reference to use** | `Graphics\Logo\kolbo-ai-new-icon-black2.jpg` (white K on black) | ✅ verified real mark. **Always pass THIS file as the generation reference**, never a transparent cutout: the black background gives the model contrast to lock onto and it reproduces the K correctly. Proven tricks that keep the geometry exact fully in-model: (a) print it as a white chest logo on a black t-shirt, (b) render it inside a small dark-navy rounded chip next to a live-typed 'Kolbo.AI' wordmark — both mirror the reference's white-on-dark context | | ||
| | Kolbo K icon, clean cutout | `Youtube\מכונת הזמן\Exports\Thumbnail\assets\k-icon-clean.png` | ⚠️ white-on-transparent — fine for HTML/PIL compositing, but as a *generation reference* on a light background it gives zero contrast and the model redraws the K wrong. Use the black-background source above instead | | ||
| | Kolbo lockup (K + wordmark) | `Youtube\מכונת הזמן\Exports\Thumbnail\assets\kolbo-lockup.png` | ⚠️ this is the **stacked t-shirt lockup** (K on top, small wordmark below) — do not use for a horizontal corner mark, it misreads or gets redrawn wrong when scaled | | ||
| | ByteDance icon | `kolbo-api\assets\Bytedance icon.png` | ❌ **wrong file** — a generic blue bar-chart icon, not ByteDance's real mark. Confirmed by hash, pre-existing bug (not from any recent edit). Filed as `task_f3fab040`. Do not composite this into a "real logo" claim; if a real ByteDance mark is needed, source and verify one first | | ||
| | Zohar — real likeness Visual DNA | id `6a64b8fa5bd226f7e763367b`, name **`zohar`** (single token, so `@zohar` binds) | ✅ correct — use this whenever the ask is "me"/"my face" | | ||
| | Zohar — costumed character DNA | `@zohar_salon` and similar | ⚠️ these are **film-character** DNAs from specific shoots, not his real likeness — never substitute for a "me presenting" thumbnail | | ||
| **DNA naming rule that bit us:** the `@Name` prompt tag only binds if it exactly | ||
| matches the DNA's stored `name` field as one token. A DNA named "Zohar (Copy)" can | ||
| never bind via `@zohar` — rename the DNA (`update_visual_dna`) once, don't work around | ||
| it per-prompt. | ||
| ## Routing in Kolbo | ||
@@ -78,44 +169,137 @@ | ||
| |---|---| | ||
| | One cover | `generate_image` (a single `text_to_image`) | | ||
| | Several options at once | The in-app **Thumbnail Generator** — topic + style + font + aspect, and it fans out 4–8 art-directed variations in one run (it uses Creative Director underneath) | | ||
| | A batch with a locked character or product | `generate_creative_director` with a Visual DNA attached | | ||
| | Cover for a video the user already made | Never crop a frame out of the video — generate a fresh comp. A film frame is exposed for motion, not for a 200px grid | | ||
| | One cover | `generate_image` | | ||
| | Several options at once | The in-app **Thumbnail Generator** — fans out 4–8 art-directed variations | | ||
| | A batch with a locked character or product | `generate_creative_director` with a Visual DNA | | ||
| | Cover for a video the user already made | Never crop a frame out of the video — generate a fresh comp. A film frame is exposed for motion, not for a 168px grid | | ||
| | A second aspect ratio (e.g. 9:16 Shorts after a 16:9 main) | **Generate it natively at that aspect ratio**, do not crop/recompose the other one in HTML. Reuse the same brief, DNA, and reference logo files; write a fresh detailed prompt sized for the new canvas | | ||
| **Default workflow, one shot:** `generate_image` (or `_edit`) at **`quality: high`**, | ||
| native target resolution (1024-class for GPT Image 2), passing every real logo file the | ||
| comp needs as `reference_images` plus the matching `@Name`/`#Name` tags in the prompt | ||
| text, and the correct Visual DNA id. Ask for **3 concept variations in the same call | ||
| batch** per the ladder below rather than iterating one image through many small manual | ||
| fixes. Reserve HTML-compositing patches for the rare case a specific mark still comes | ||
| back wrong after 2–3 regenerations with references — it is a fallback, not the default | ||
| path. | ||
| **9:16 safe-zone discipline:** keep the hero content (face, gesture, headline, badge, | ||
| logo) inside roughly the **centre 70% of the canvas width**, not edge-to-edge — verified | ||
| by the centre-square-crop test below. State this explicitly in the prompt ("generous | ||
| margin on both sides, nothing touches the left/right edge") rather than fixing it after | ||
| generation. | ||
| ## Variation ladder | ||
| When producing a set, vary the **concept**, never the words. This is the ladder the in-app | ||
| tool uses, and it is a good default order: | ||
| Vary the **concept**, never the words: bold dynamic · clean minimal · vibrant saturated · | ||
| cinematic wide · close-up dramatic · typography-forward · dark moody · flat illustration. | ||
| 1. Bold dynamic — high contrast, dramatic light, scroll-stopping energy | ||
| 2. Clean minimal — one focal point, premium negative space | ||
| 3. Vibrant saturated — rich colour, maximum visual impact | ||
| 4. Cinematic wide — epic scale, movie-poster feeling | ||
| 5. Close-up dramatic — intense subject detail, emotional impact | ||
| 6. Typography-forward — the text is the hero, graphic art direction | ||
| 7. Dark moody — deep shadows, selective highlights | ||
| 8. Flat bright illustration — playful shapes, bold outlines | ||
| Make **3 thumbnails and 10 titles** per video, and design them *before* shooting. Top | ||
| creators spend ~30% of their effort on packaging versus ~5% for small channels. **[B]** | ||
| ## Faces | ||
| --- | ||
| If the channel has a host, lock them with a **character Visual DNA** | ||
| (`workflows/visual-dna.md`) so every thumbnail in the series is the same person. Expression | ||
| is the payload: shock, delight, disbelief, triumph. A neutral face is a wasted thumbnail. | ||
| ## What now reads as dated or "AI slop" | ||
| ## Phone-shot thumbnails | ||
| **Correct the premise first: YouTube has NOT demoted AI thumbnails.** Its synthetic-content | ||
| policy explicitly exempts "using generative AI tools to create or improve a video outline, | ||
| script, **thumbnail**, title, or infographic." **[A]** Anyone claiming the algorithm | ||
| penalises AI thumbnails is repeating a fabrication. The damage is **competitive and | ||
| trust-based**, and it is real: | ||
| A "raw / authentic" cover is a real style — a phone-shot frame with big type over it beats | ||
| a polished render for vlog and UGC channels. Build the plate from | ||
| `workflows/ugc-smartphone.md`, then apply the text rules above unchanged. The type stays | ||
| graphic and deliberate even when the photo is deliberately casual. | ||
| - **The models converge — you disappear into sameness.** 700 generation trajectories | ||
| through image-model feedback loops all collapsed to just **12 dominant motifs**; the | ||
| authors call the result "visual elevator music." **[A]** | ||
| - **The gloss is the tell** — see the saturation note above. **[A]** | ||
| - **AI faces homogenise.** Diffusion models render same-demographic individuals as | ||
| near-identical across professions. Your AI face looks like everyone's AI face — which | ||
| is exactly why a real Visual DNA built from real photos matters. **[A]** | ||
| **Avoid — evidence-backed:** exaggerated open-mouth shock · over-saturated HDR/clarity · | ||
| plastic AI skin · piles of arrows and circles (one or two maximum) · **imagery not | ||
| actually in the video** (policy risk *and* it loses the watch-time test) · AI likeness of | ||
| real public figures (YouTube likeness detection is live for all YPP creators). | ||
| **Avoid — credibility damage in tech/AI niches:** glowing brains, robot-hand-touching- | ||
| human-hand, circuit boards, binary code, humanoid robots, the default blue "tech" wash. | ||
| Each is sci-fi-derived and misleading about what AI actually is. For a channel whose | ||
| credibility *is* the product, these are self-harm. | ||
| **Avoid on taste, no data — don't cite numbers for these:** golden particle dust and | ||
| bokeh, radial speed lines, neon collage, holographic UI overlays, floating tech icons, | ||
| gradient-mesh purple/blue backgrounds, hexagon grids, generic fantasy creatures. | ||
| --- | ||
| ## Tech / AI-tool / filmmaking channels | ||
| The grammar here is the **opposite** of the MrBeast formula, and that is the point. | ||
| Restraint reads as authority: controlled product photography, matte dark grounds, one | ||
| accent pulled from the subject itself, minimal or no text, a composed direct-to-camera | ||
| expression rather than a reaction. **The absence of arrows and explosions is the brand | ||
| signal.** For a channel selling expertise, the thumbnail is a claim about whether you | ||
| know what you are talking about. | ||
| What works specifically: | ||
| - **The tool logo as the recognisable object** — high search intent, heavily used; | ||
| differentiate through treatment (scale, lighting, physical staging), not by dropping it. | ||
| - **Before/after** — genuinely strong for AI filmmaking because the transformation *is* | ||
| the promise and it is honest. Skip the arrow; let the two images do the work. | ||
| - **The interface as hero** — a real UI cropped tight to one striking element signals | ||
| "actual tutorial, not hype." Under-used. | ||
| - **Face + artefact** — face at ~⅓ frame, closed-mouth focused, beside the generated | ||
| frame. Satisfies both the face finding and "show the thing." | ||
| --- | ||
| ## Hebrew and RTL | ||
| > **No evidence base exists for any of this.** There is no measured data on Hebrew vs | ||
| > Latin thumbnail text, Hebrew legibility at 168px, or RTL thumbnail composition. What | ||
| > follows is typographic reasoning plus Israeli foundry commentary. For a Hebrew channel | ||
| > this is worth settling empirically — ship a text-right/subject-left variant against a | ||
| > mirrored one and let YouTube's own test decide. | ||
| - **Hebrew has no ascenders or descenders and a uniform x-height.** Latin words have a | ||
| ragged silhouette that aids word-shape recognition at small size; Hebrew words are | ||
| near-rectangular blocks. **Hebrew needs more size, more weight and more letterspacing | ||
| than Latin to hit the same legibility at 168px.** Budget for it. **[C]** | ||
| - **Fonts:** **Ploni** (AlefAlefAlef) is purpose-built bilingual — Hebrew plus Latin | ||
| designed to sit together without either overshadowing the other, which is exactly the | ||
| problem when a tool name like `Seedance 2.5` sits inside a Hebrew phrase. **Heebo** and | ||
| **Rubik** are strong free alternatives with real bold weights. | ||
| - **Mirror the layout, not the logos.** RTL readers scan a mirrored F-pattern entering | ||
| from the **top-right**, so the natural composition inverts: **text block right, subject | ||
| left**, gaze pointing right-to-left toward the text. Latin brand marks and numerals stay | ||
| LTR regardless. **[B]** | ||
| - **Language split:** Hebrew for the emotional/promise word, Latin for the tool name — the | ||
| tool name is the search-intent anchor and the audience already reads it in Latin. | ||
| - **Per-language thumbnails exist** but are gated behind multi-language audio tracks: you | ||
| need at least one added audio track before a localised thumbnail can attach to it. **[A]** | ||
| --- | ||
| ## Honest limits | ||
| Thumbnail design is a craft with weak empirical foundations. A study of 2,400 news | ||
| thumbnails across 21 visual features found **few statistically significant correlations | ||
| with engagement at all** **[A]**. The breakout data above describes what winning | ||
| thumbnails *look like*, not what *caused* the win. Genuinely unsettled: rule-of-thirds vs | ||
| centred (no data either way), and saturation levels (creator orthodoxy vs the aesthetics | ||
| literature). Do not present either as settled. | ||
| A/B testing needs ~10k impressions per variant to mean anything. Below that, just replace | ||
| the thumbnail outright. | ||
| --- | ||
| ## Checklist | ||
| - [ ] One subject, 40–70% of frame, tight crop | ||
| - [ ] Subject separates hard from the background | ||
| - [ ] ≤ 4 words, quoted verbatim, everything else forbidden | ||
| - [ ] Text has an outline or backing bar, sits off the face | ||
| - [ ] Correct aspect, critical content inside the safe area | ||
| - [ ] Checked at 200px (and centre-cropped first, for 9:16) | ||
| - [ ] No watermark, no stray words, no gibberish letters | ||
| - [ ] One idea, nameable in under a second at 168×94 | ||
| - [ ] Face ~⅓ of frame, **one legible emotion, closed-mouth**, eye contact | ||
| - [ ] Greyscale test: subject still separates | ||
| - [ ] ≤3 colours, restrained saturation, checked on light *and* dark themes | ||
| - [ ] 0–3 words, outlined, ~12–15% frame height, off the face, never bottom-right | ||
| - [ ] Nothing in the bottom-right quadrant or bottom 40px | ||
| - [ ] Real logos composited from files, never model-rendered | ||
| - [ ] Nothing in the image that isn't in the video | ||
| - [ ] Exported 3840×2160; verified at 168×94 (and centre-cropped first, for 9:16) |
@@ -29,5 +29,5 @@ # Troubleshooting | ||
| ## Black / empty chat card while "Generating" | ||
| ## Generation status, waiting, black cards | ||
| **Not a bug and not a failure.** The chat generation card's preview stays dark until the job has media. Library shows a K/logo placeholder tile for the same in-flight job. Do **not** re-fire `generate_*`, do **not** `list_media` to "find" it. Wait, or call `get_generation_status` once with `wait=true`. When complete, the result appears in Library (This session) — that is the user-facing source of truth. | ||
| Status semantics, `wait=true` batching, black-card-is-normal and the credit guard live in SKILL.md "⚠️ Generation lifecycle — source of truth, waiting, failures". | ||
@@ -51,8 +51,2 @@ ## "Rate limited" (429 errors) | ||
| ## Checking generation status without spinning | ||
| `get_generation_status` supports `wait=true` (blocks server-side until the generation reaches a final state, up to ~3 min) and `generation_ids` (many ids in one call → returns `all_done`, `still_processing`, and per-generation results). **Never call it repeatedly in a loop** — one `wait=true` call replaces the loop. If some generations are still running after the wait window, call it ONCE more with `wait=true` and only the `still_processing` ids. | ||
| **Credit guard:** after a generate tool returns `submitted` / `_timed_out`, do not keep thinking or editing files while the card spins — that burns coding credits. End the turn, or make **one** `wait=true` status call if you need the URLs next. | ||
| ## Failure envelope from `get_generation_status` | ||
@@ -59,0 +53,0 @@ |
@@ -11,3 +11,3 @@ # Visual DNA — Character / Style Consistency | ||
| 1. **Sheet first, then DNA.** For any production asset (character / location / prop), resolve the sheet **preset** (`list_presets` with `search`) and `generate_image` with that `preset_id` — custom instructions live on the preset. Then `create_visual_dna` with the sheet as `character_sheet_url` (max 4 extra images — if the user gives more, pick the 4 most representative **that share the same identity and vibe**; never pass 5+). Optionally video and audio. See **Purity** above before you generate those stills. | ||
| 1. **Sheet first, then DNA.** For any production asset (character / location / prop), resolve the sheet **preset** (`list_presets` with `search`) and `generate_image` with that `preset_id` — custom instructions live on the preset. Then `create_visual_dna` with the sheet as `character_sheet_url` (max 4 extra images — if the user gives more, pick the 4 most representative **that share the same identity and vibe**; never pass 5+). Optionally video and audio. See **Purity** below before you generate those stills. | ||
| 2. **Types**: `character` (default), `style`, `product`, `scene`, `environment`. | ||
@@ -26,3 +26,3 @@ 3. **Use** the profile by passing its `id` in `visual_dna_ids` in: `generate_image`, `generate_creative_director`, `generate_elements`, `generate_video_from_image`, `generate_video_from_video`, `generate_first_last_frame`. | ||
| 1. **User-uploaded refs take image slots first.** | ||
| 2. **Remaining slots:** one main still per DNA, then leftover stills from each DNA **round-robin** until the model's image-slot cap (`elementsMaxImages` / equivalent) is full. | ||
| 2. **Remaining slots:** one main still per DNA, then leftover stills from each DNA **round-robin** until the model's image-slot cap (`elements_max_images` / equivalent) is full. | ||
| 3. **If every still fits the cap, every still is sent** as its own reference. A 4-image character DNA on a 9-slot model is four slots, not one. | ||
@@ -109,13 +109,4 @@ 4. **If a DNA only gets one leftover slot**, has **no distinct character sheet**, and still has unused stills, those leftovers are composited into a **white grid / collage** (up to 9 cells) so the model still sees them. A real character sheet is never overwritten by a collage. | ||
| Whenever a generation call passes `visual_dna_ids` (even just one), the prompt MUST refer to each Visual DNA by `@<exact-name>` — the literal `name` field as it was set in `create_visual_dna` and as it appears in `list_visual_dnas`. This is how the engine binds the DNA to a role in the scene. Without `@name`, the engine guesses, drops the DNA, or blends multiple DNAs together. | ||
| SKILL.md's `@Name` hard rule applies; here is why it binds that way: | ||
| **Use the actual stored name, programmatically.** When you call `list_visual_dnas` (or `create_visual_dna`), read the `name` field off the response and use that exact string after the `@`. Do NOT: | ||
| - Translate the name into another language ("אסתר" / "esther" / "אסתי" — pick whichever string is in `name` and use ONLY that one). | ||
| - Invent a friendlier alias ("the model", "המודל", "her", "Zohar's", "the left man", "the man on the LEFT"). | ||
| - Write a "Visual DNA anchors:" prose block that describes position/wardrobe but never writes `@ExactName`. | ||
| - Write the character's name in plain text without the `@` prefix. | ||
| - Drop the `@name` when only one DNA is passed — the engine still needs the binding so it knows the DNA is the *subject* and not a passive style. | ||
| - **Drop or "clean" tags while rewriting a prompt** (help-widget parity). Compiling SCENE CONTEXT / Locked Intro / a "better" English prompt is not permission to delete `@gal_suit` or rewrite `@yonatan` as `Yonatan`. Copy every existing `@` / `#` token into the new prompt, then add craft around them. | ||
| **Wrong** (DNA `name` is `esther_model`, user wrote prompt in Hebrew): | ||
@@ -234,28 +225,8 @@ ``` | ||
| Read `max_visual_dna` from `list_models` for the exact cap, AND `supports_visual_dna` for the on/off boolean. A model can support DNA without an explicit cap, or have a non-null cap but silently ignore DNA on certain paths (e.g. `generate_video`). Typical ranges: image models (non-Kling) up to **8**, Kling image models **3**, Elements video models **3–5**, everything else up to **3**. | ||
| Read `max_visual_dna` (and `elements_max_images` for image-slot packing) from `list_models` for the chosen model, AND `supports_visual_dna` for the on/off boolean. A model can support DNA without an explicit cap, or have a non-null cap but silently ignore DNA on certain paths (e.g. `generate_video`). Typical ranges: image models (non-Kling) up to **8**, Kling image models **3**, Elements video models **3–5**, everything else up to **3**. | ||
| ## ⚠️ Visual DNA Creation — Always Generate Reference Images First (MANDATORY) | ||
| **Before calling `create_visual_dna` for a character**, always generate 2 reference images first and include them alongside any user-provided images. These give the Visual DNA engine multi-angle coverage and dramatically improve consistency. | ||
| **Before calling `create_visual_dna` for a character**, generate the reference stills first — a multi-angle sheet plus a close-up gives the engine far better coverage than a single photo. Route the stills through the **preset contract** (`list_presets` search → `preset_id` on `generate_image`), never a raw hand-written sheet prompt — see "Character sheet — default for production assets" below for the full flow, preset search terms, and aspect-ratio rules. Include the user's reference photo(s) alongside only if they provided one. **Skip this only if** the user explicitly says "just use my image as-is" or provides 3+ reference images already covering multiple angles. | ||
| **Step 1 — Generate both images in parallel (one `generate_image` call each, fire simultaneously):** | ||
| 1. **4-angle character sheet** — prompt: `"[character description], character reference sheet showing front view, back view, left side view, right side view, four panels arranged in a 2x2 grid, neutral solid background, full body, photorealistic"`, aspect ratio `16:9` (or `3:2` — always landscape, see the aspect-ratio rule below) | ||
| 2. **Close-up portrait** — prompt: `"[character description], close-up portrait, face and shoulders, neutral solid background, soft studio lighting, photorealistic"`, aspect ratio `1:1` | ||
| **Step 2 — Call `create_visual_dna`** with: | ||
| - `images`: the 4-angle sheet URL first, then the close-up URL — **plus** the user's reference photo(s) only if they provided one (i.e. a real person or existing character they want to match). If they gave no reference image, the 2 generated images alone are sufficient. | ||
| - `type`: `"character"` | ||
| - `name`: single-token lowercase descriptive name (see naming rule above) | ||
| **Why:** A single reference photo only shows one angle. The close-up gives the engine facial detail; the 4-angle sheet gives it body geometry and pose range. Together they produce far more consistent generations. Both stills (and any user photos you add) must be the **same person, same vibe** — they will all be packed into the next generation. | ||
| **Skip this only if** the user explicitly says "just use my image as-is" or provides 3+ reference images already covering multiple angles. | ||
| ### Environments, products, style — same precision | ||
| - **Environment / location:** generate empty (or crowd-only) plates. Prompt out heroes and readable faces. A location DNA that contains `@maya` in the frame will put Maya in every later shot of that place. | ||
| - **Product:** isolated angles, consistent lighting, readable label. No extra hero unless the product is worn and the body is generic. | ||
| - **Style:** one look, applied cleanly. Do not mix neon-cyber and dusty-western stills on the same style DNA. | ||
| ## When to Use | ||
@@ -262,0 +233,0 @@ |
+60
-77
| --- | ||
| version: 0.9.6 | ||
| version: 0.9.10 | ||
| name: kolbo | ||
@@ -25,28 +25,4 @@ description: | | ||
| ## ⚠️ Source of truth for generations (HARD RULE — read this) | ||
| This file is the **always-loaded core**: tool inventory + universal hard rules + routing index — for model-specific prompt rules, workflows, cost validation, etc., Read the matching `references/` file from the index below; loading is mandatory, not optional flavor (users never invoke the bundled skills themselves — skipping them yields a lazy one-line prompt). | ||
| Agents keep getting confused because three UIs show the same job. Use this map — never invent a fourth: | ||
| | Surface | What it is | Trust it for | | ||
| |---|---|---| | ||
| | **Library** (right panel — "This session" / "All media") | User-facing gallery of **completed** media | "Is the user's output there?" Point humans here. Finished clips/images land automatically — do **not** `list_media` / `get_media` just to verify a `generate_*` you just ran. | | ||
| | **Chat generation card** | Progress chrome while a job is in flight | Status badge only (`Generating` / done). A **black / empty preview while Generating is NORMAL** — the iframe has nothing to paint yet. It is **not** failure, not "lost", not a reason to re-fire. | | ||
| | **`get_generation_status`** (MCP) | Agent API for job state | Whether the server job is `completed` / `failed` / still running, and the final `urls`. This is your SoT for in-flight work — **not** the card pixels. | | ||
| | **`.kolbo/production.md`** | Your private log across turns | Ids + URLs after success. Compaction-safe memory — not the user gallery. | | ||
| **Do NOT:** | ||
| - Treat an empty/black chat card as "generation failed" or "nothing produced". | ||
| - Re-call `generate_*` because Library still shows a K/logo spinner tile while the job is running — that tile **is** the in-progress placeholder for the same job. | ||
| - Call `list_media` / `get_media` / `list_session_generations` to "check if it worked" after a generate you already submitted — that burns credits/context and can pollute the session. | ||
| - Tell the user to look at chat history for finals — tell them **Library → This session**. | ||
| **Do:** | ||
| - After `submitted` / `_timed_out`: end the turn, or one `get_generation_status(..., wait=true)`. | ||
| - When done: say the result is in Library; log URLs to `.kolbo/production.md`. | ||
| - If the user asks "where is it?" → Library (This session). If they ask "is it done?" and you don't have urls yet → `get_generation_status` once. | ||
| This file is the **always-loaded core**: tool inventory + universal hard rules + routing index. For any model-specific prompt rules, Visual DNA workflow, production log format, marketing workflow, cost validation, etc., **Read the matching `references/` file from the index below**. Don't try to remember the rules — load the file when you need them. | ||
| Users never see the bundled prompting skills. If you skip them, they get a lazy one-line prompt. **Loading is mandatory, not optional flavor.** | ||
| ## Step 0 — Bootstrap | ||
@@ -58,7 +34,7 @@ | ||
| 2. **If `list_models` returns empty**, MCP isn't wired — same fix. | ||
| 3. Use the balance ONLY for the low-balance check at this moment. **Never quote a "credits remaining" number later in the session** — coding/chat usage also deducts credits, so any remembered or computed balance is stale. Report only what each generation cost (`credits_used`); if the user asks what's left, run `check_credits` fresh right then. | ||
| 3. Use the balance ONLY for the low-balance check at this moment (see the "credits remaining" rule in the brief section below). | ||
| If the user is on a whitelabel build (`sapir`, etc.), they must use their branded command — not `kolbo`. See `references/workflows/troubleshooting.md`. | ||
| ## 🎬 Confirm the Creative Brief BEFORE Generating (CRITICAL — read first) | ||
| ## 🎬 Confirm the Creative Brief & Cost BEFORE Generating (CRITICAL — read first) | ||
@@ -69,3 +45,3 @@ Never fire a paid generation the moment the user says "make X". First **present the brief back as a confirmation the user can change** — this is the single most important interaction. It gives the user control over what gets created and what it costs, instead of silently spending credits on defaults. | ||
| - **Model** — your recommended pick as the default option, plus 1–2 alternatives (with their credit cost). | ||
| - **Model** — your recommended pick as the default option, plus 1–2 alternatives (with their credit cost). Suggest a cheaper alternative if one fits. | ||
| - **Aspect ratio** — e.g. `1:1 / 9:16 / 16:9` (offer the sensible default first). | ||
@@ -77,6 +53,13 @@ - **Count** — how many (1 / 4 / …). | ||
| Then generate **only** with the confirmed parameters. If the user changes an option, use the change. This mirrors the approval-card flow: propose → let them adjust → confirm → generate. | ||
| Then generate **only** with the confirmed parameters. If the user changes an option, use the change. This mirrors the approval-card flow: propose → let them adjust → confirm → generate. Never fire on defaults the user didn't choose. | ||
| **Only skip the brief confirmation when** the user's message already pins model + aspect + count + creative direction (e.g. "generate 4 photoreal tabby cats, 1:1, z-image/turbo") — then just state the cost one-liner and fire. A low credit cost is **not** a reason to skip: cheap ≠ no-confirmation. What matters is whether the user actually chose the parameters. | ||
| **Only skip the brief/cost confirmation when** the user's message already pins model + aspect + count + creative direction (e.g. "generate 4 photoreal tabby cats, 1:1, z-image/turbo") — then just state the cost one-liner and fire. A low credit cost is **not** a reason to skip: cheap ≠ no-confirmation. What matters is whether the user actually chose the parameters. | ||
| **Cost rules** (full tables + formulas in `references/workflows/cost-and-validation.md`): | ||
| - **Video/lipsync `credit` is per-SECOND, not per-clip**: `total = credit × duration`. This is the universal rule for video/firstlast/elements/motion_graphic/cast types, not a per-model exception — `list_models` states it inline now. The one carve-out is a model with `flat_credit_by_resolution` set. | ||
| - **Batch totalling 100+ credits**: run `check_credits` first. | ||
| - **Quote real cost**: after firing, log `credits_used` (from the tool result) to `.kolbo/production.md` — never `base × count`. | ||
| - **Never state "credits remaining" from arithmetic** (opening balance − generation costs). Coding/chat usage deducts credits too, so the math is always wrong. Report cost only; if the user asks for their balance, call `check_credits` fresh at that moment. | ||
| For multi-scene / batch work this pairs with `generate_creative_director` (see below) — still confirm the brief first. | ||
@@ -109,2 +92,3 @@ | ||
| | Use **Visual DNA** / character consistency / `@name` syntax | `references/workflows/visual-dna.md` | | ||
| | Use **Color DNA** / brand palette grading | `references/workflows/color-dna.md` | | ||
| | Start or continue a **multi-step production** (storyboard → scenes → final cut) | `references/workflows/production-log.md` | | ||
@@ -115,2 +99,3 @@ | **Transcribe** or **analyze** audio/video | `references/workflows/transcription.md` | | ||
| | Browse, manage, or present existing **media library** items | `references/workflows/media-library.md` | | ||
| | Run a **client review / approval loop** — share a cut for feedback, timestamped comments, versions (v1→v2), approve / request-changes, guest links | `references/workflows/review-collections.md` | | ||
| | Confirm **cost** or validate **resolution / aspect / duration** against model caps | `references/workflows/cost-and-validation.md` | | ||
@@ -149,9 +134,9 @@ | Hit an **auth / MCP / 429** issue | `references/workflows/troubleshooting.md` | | ||
| | `create_visual_dna` / `update_visual_dna` / `generate_character_sheet` / `list_visual_dnas` / `get_visual_dna` / `delete_visual_dna` / `*_visual_dna_folder` (5 folder tools) | Visual DNA (+ character sheet, character folders) — see `workflows/visual-dna.md`. Edit with `update_visual_dna`; never delete+recreate. | | ||
| | `list_moodboards` / `get_moodboard` / `list_presets` | Style overlays + sheet presets. Always pass `search` when you know the name — that is a silent id lookup, not a catalog to show. Never omit `preset_id` after claiming a preset was used. | | ||
| | `list_color_palettes` / `analyze_color_palette` / `create_color_palette` / `update_color_palette` / `delete_color_palette` / `activate_color_palette` / `deactivate_color_palette` | **Color DNA — sticky and account-wide.** At most one palette is active at a time; while it is, it strict-grades **every** image and video generation automatically, with no per-call argument. `analyze_color_palette` pulls colors out of 1-5 image URLs for free and does NOT save. `create_color_palette` defaults `is_active: true`, which activates it and deactivates any other. Per-generation opt-out: `skip_color_palette: true` on `generate_image` / `generate_image_edit` / `generate_video` / `generate_video_from_image`. | | ||
| | `list_moodboards` / `get_moodboard` / `list_presets` | Style overlays + sheet presets — see **Preset contract** in Core Workflow. Never omit `preset_id` after claiming a preset was used. | | ||
| | `list_color_palettes` / `analyze_color_palette` / `create_color_palette` / `update_color_palette` / `delete_color_palette` / `activate_color_palette` / `deactivate_color_palette` | **Color DNA — sticky + account-wide; at most one palette active at a time**, and while active it strict-grades **every** image and video generation automatically. Per-generation opt-out: `skip_color_palette: true`. Details: `workflows/color-dna.md`. | | ||
| | `list_agents` / `create_agent` / `update_agent` / `delete_agent` | Custom chat agents — reusable named personas for `chat_send_message`. The agent's `description` IS the system instruction. Resolve a name the user mentions ("use my SEO agent") to an id with `list_agents`, then pass `agent_id`. Global/preset agents are read-only; only the user's own can be updated or deleted. | | ||
| | `search_stock_media` / `get_stock_sources` / `get_stock_categories` / `get_stock_collections` / `get_stock_asset` / `analyze_script_for_stock` / `import_stock_asset` | Stock library (free, no credits) — EXISTING photos / videos / 3D / SFX / music. For stock **music** use `search_stock_media` with `mediaType: "music"` (semantic vibe query, e.g. "uplifting corporate background") → `get_stock_asset` for downloads. The older `*_music_library` tools are deprecated adapters over this — prefer the stock tools, except for the licensed-catalog tools in the next row. | | ||
| | `search_music_library` / `browse_music_library` / `get_music_library_facets` / `get_music_track_audio` / `get_music_track_lyrics` / `get_music_track_related` / `analyze_script_for_music` / `acquire_clean_music_track` / `import_music_track_to_library` | **SYNCI licensed music** — a commercially licensed catalog, not free stock. Discovery and previews are free but **watermarked**; there is no unwatermarked URL until you pay. `acquire_clean_music_track` (or `import_music_track_to_library`, which also copies it to the media library) **CHARGES CREDITS** for the clean master — confirm with the user first, and pass a stable `requestId` so a retry doesn't buy it twice. `analyze_script_for_music` turns a script into search terms for `search_music_library`. Use this family when the user needs music cleared for commercial use; use `search_stock_media` with `mediaType: "music"` when free stock will do. | | ||
| | `list_projects` / `get_project` / `move_session` | Projects: resolve a project NAME → the `project_id` you pass on generation/upload/doc calls; `get_project` returns the full description (list clips it). `move_session` relocates a whole session + its media when work landed in the wrong project. See "Projects — Where Work Lands" below. | | ||
| | `create_project` / `update_project` / `archive_project` / `unarchive_project` / `list_sessions` / `rename_session` / `delete_session` / `restore_session` | Project lifecycle + session inventory. Edit name/description with `update_project` (read via `get_project` first). Rename sessions with `rename_session` — never delete+recreate. `list_sessions` returns `project_id` + `types[]` on every row. Soft-delete leftover empty sessions after a move; `restore_session` undoes trash. Create a project when the user starts new work, then pass its id on EVERY call. | | ||
| | `search_music_library` / `browse_music_library` / `get_music_library_facets` / `get_music_track_audio` / `get_music_track_lyrics` / `get_music_track_related` / `analyze_script_for_music` / `acquire_clean_music_track` / `import_music_track_to_library` | **SYNCI licensed music** — commercially licensed catalog, not free stock; previews are **watermarked**. `acquire_clean_music_track` / `import_music_track_to_library` **CHARGES CREDITS** for the clean master — confirm with the user first + pass a stable `requestId`. Details: `workflows/media-library.md` "SYNCI licensed music". | | ||
| | `list_projects` / `get_project` / `move_session` | Projects: resolve a project NAME → the `project_id` you pass on generation/upload/doc calls (`get_project` returns the full description — list clips it); `move_session` relocates a whole session + its media. See "Projects — Where Work Lands" below. | | ||
| | `create_project` / `update_project` / `archive_project` / `unarchive_project` / `list_sessions` / `rename_session` / `delete_session` / `restore_session` | Project lifecycle + session inventory. Edit name/description with `update_project` (read via `get_project` first); rename sessions with `rename_session` — never delete+recreate. `list_sessions` returns `project_id` + `types[]` on every row. | | ||
| | `bulk_move_sessions` / `list_session_generations` / `move_generations_to_session` / `split_session` / `undo_session_organization` | Reorganize many sessions or generations. `list_session_generations` is an inventory (not a live generation card). | | ||
@@ -165,2 +150,3 @@ | `add_project_context` / `list_project_context` / `delete_project_context` / `get_project_profile` / `regenerate_project_profile` | Project knowledge base (RAG): feed scripts/URLs/notes; `get_project_profile` = the living brief — read it to ground work in the project | | ||
| | `chat_send_message` / `chat_list_conversations` / `chat_get_messages` | Kolbo chat with optional `media_urls` (up to 10 per call) | | ||
| | `create_review_asset` / `add_review_version` / `set_review_status` / `create_review_comment` / `reply_review_comment` / `resolve_review_comment` / `unresolve_review_comment` / `create_review_collection` / `create_review_share_link` / `revoke_review_share_link` / `get_review_storage_usage` (+ list/get/update/delete siblings) | **Kolbo Review** — Frame.io-style client review: asset = media + appended versions (new cut = `add_review_version`, never delete+recreate), timecoded comments per version, approve/request-changes status, guest share links (no Kolbo account; comment-only unless `canSetStatus`). 5GB review storage cap. See `workflows/review-collections.md`. | | ||
| | `publish_html_artifact` | Publish HTML / SVG / Mermaid to `sites.kolbo.ai`. Server dedupes by content hash. Strict CSP. | | ||
@@ -220,3 +206,3 @@ | ||
| - Hosts that are already hosted: `media.kolbo.ai`, any `*.kolbo.ai`, Kolbo DigitalOcean Spaces. | ||
| - `upload_media` is only for a **local disk path** or an **external** (non-Kolbo) URL that the tools would 400 on. | ||
| - `upload_media` is only for a **local disk path** or an **external** (non-Kolbo) URL — `files`/`source_images`/`image_url` reject unknown hosts with `400`; a Kolbo URL passes through as-is. | ||
| - Same rule after compaction: pull the URL from `.kolbo/production.md` and reuse it. Never download-then-reupload. | ||
@@ -294,3 +280,3 @@ | ||
| 1. **Check credits** ONCE per conversation (Step 0). Skip if already checked. | ||
| 2. **Load the matching skill** (HARD RULE above) — `skill` tool + Read the `references/` file. Do this before the first paid call in the turn. | ||
| 2. **Load the matching skill** (HARD RULE above) before the first paid call in the turn. | ||
| 3. **Discover models** with `list_models` using a `type` filter — but **skip when the user names a specific model** (this turn **or** earlier in the conversation / compaction `## Locked choices`). | ||
@@ -303,12 +289,40 @@ 4. **Pick the model**: | ||
| 5. **Validate inputs** against model caps — see `references/workflows/cost-and-validation.md`. | ||
| 6. **How calls work**: each tool blocks until generation is fully complete. Images: seconds. Video: minutes. Multiple tool calls in one response run concurrently. On hosts with live widgets the tool instead returns `submitted` (or `_timed_out`) instantly — the card updates on its own. | ||
| 7. **🛑 After `submitted` / `_timed_out` — END THE TURN (credit guard)**: Do **not** keep thinking, writing skills, editing files, or planning "next steps" while a generation is still running. That burns the user's coding/chat credits for nothing. Either: | ||
| - **Stop immediately** after telling the user it's generating in Library / the card above (preferred when you do not need the output URLs yet), OR | ||
| - If the **next** required step needs those URLs, call `get_generation_status` **once** with `wait=true` (and `generation_ids` for a batch) as the **only** follow-up — no parallel Write/Edit/Think while it waits. | ||
| - A black preview on the chat card is expected until URLs exist — not a signal to retry. | ||
| 8. **Checking status — NEVER poll in a loop**: `get_generation_status` takes `wait=true` (blocks server-side until done, ~3 min) and `generation_ids` (check MANY generations in ONE call — returns `all_done` + which are still running). One `wait=true` call replaces any polling loop. If it comes back with some still processing, call it ONCE more with `wait=true` and the remaining ids. | ||
| 9. **Share the URL** after success. Never fabricate URLs. | ||
| 6. **Fire the call(s)** — then follow "⚠️ Generation lifecycle" below for waiting, status, and failure handling. | ||
| 7. **Share the result** after success — per "⚠️ Generated URLs in Chat" and the no-fabricated-URLs rule in Limitations & Safety. | ||
| Model types for `list_models`: `text_to_img`, `image_editing`, `text_to_video`, `img_to_video`, `draw_to_video`, `video_to_video`, `elements`, `firstlastgenerations`, `lipsync-image`, `lipsync-video`, `music_gen`, `text_to_speech`, `text_to_sound`, `stt`, `text`, `3d_text_to_model`, `3d_image_to_model`, `3d_multi_image_to_model`, `3d_world`. | ||
| ## ⚠️ Generation lifecycle — source of truth, waiting, failures (HARD RULE — read this) | ||
| **How calls work:** each generation tool blocks until the job is fully complete. Images: seconds. Video: minutes. Multiple tool calls in one response run concurrently. On hosts with live widgets the tool instead returns `submitted` (or `_timed_out`) instantly — the card updates on its own. | ||
| Four surfaces show the same job. Use this map — never invent a fifth: | ||
| | Surface | What it is | Trust it for | | ||
| |---|---|---| | ||
| | **Library** (right panel — "This session" / "All media") | User-facing gallery of **completed** media | "Is the user's output there?" Point humans here — never to chat history. Finished clips/images land automatically — do **not** call `list_media` / `get_media` / `list_session_generations` to "check if it worked" after a generate you already submitted (burns credits/context, can pollute the session). A K/logo spinner tile **is** the in-progress placeholder for the same job, not a missing one. | | ||
| | **Chat generation card** | Progress chrome while a job is in flight | Status badge only (`Generating` / done). A **black / empty preview while Generating is NORMAL** — the iframe has nothing to paint yet. It is **not** failure, not "lost", not a reason to re-fire. | | ||
| | **`get_generation_status`** (MCP) | Agent API for job state | Whether the server job is `completed` / `failed` / still running, and the final `urls`. This is your SoT for in-flight work — **not** the card pixels. | | ||
| | **`.kolbo/production.md`** | Your private log across turns | Ids + URLs after success. Compaction-safe memory — not the user gallery. | | ||
| **🛑 NEVER re-fire a generation you already called.** Aborted / timed-out / `submitted` calls still process server-side. Finish with `get_generation_status` (`wait=true`) — never a second `generate_*`. | ||
| **🛑 After `submitted` / `_timed_out` — END THE TURN (credit guard).** Do **not** keep thinking, writing skills, editing files, or planning "next steps" while a generation is still running — that burns the user's coding/chat credits for nothing. Either **stop immediately** after telling the user it's generating in Library / the card above (preferred when you do not need the output URLs yet), OR — if the **next** required step needs those URLs — call `get_generation_status` **once** with `wait=true` as the **only** follow-up, no parallel Write/Edit/Think while it waits. | ||
| **Checking status — NEVER poll in a loop.** `get_generation_status` takes `wait=true` (blocks server-side until done, ~3 min) and `generation_ids` (check MANY generations in ONE call — returns `all_done` + which are still running). One `wait=true` call replaces any polling loop: check ALL in-flight ids in ONE call, never one by one, never without `wait`. If it comes back with some still processing, call it ONCE more with `wait=true` and the remaining ids. | ||
| **Detecting failure — a generation can fail three ways. Treat ALL as failure:** | ||
| 1. **Tool returns `error`** — explicit. Surface, suggest retry, log `generation_id`. | ||
| 2. **Tool returns `completed` but `urls` is empty** — silent failure (NSFW filter, model OOM, upstream 5xx). Tell user "completed without an output — retrying" and re-fire ONCE. Do NOT claim it worked. | ||
| 3. **Tool hangs / never returns** — MCP poll timed out. Call `get_generation_status(generation_id, wait=true)` IMMEDIATELY. The server might be done. | ||
| **Reporting:** | ||
| - Don't celebrate before reading the result. Verify `urls` is non-empty. | ||
| - Don't auto-retry without surfacing the failure. Partial batches: list failed items + reasons + successful count, and surface the user's count — "6 of 8 ready", not "videos ready". Never "✅ all done!" on partials. | ||
| - Log only successes to `.kolbo/production.md` — never failed items. | ||
| - When done: say the result is in **Library → This session**. "Where is it?" → Library (This session). "Is it done?" with no urls yet → `get_generation_status` once. | ||
| `failure` envelope structure + retry rules: `references/workflows/troubleshooting.md`. | ||
| ## 📁 Projects — Where Work Lands (CRITICAL) | ||
@@ -318,3 +332,3 @@ | ||
| 1. **User names a project** ("in my Acme project", "for the film") → call `list_projects` ONCE to resolve the name to an ObjectId, then pass that **same** id as `project_id` on **EVERY** subsequent `generate_*` / `upload_media` / `create_doc` / `chat_send_message` call in **this conversation**. There is no server-side sticky store — omitting it on any later call silently lands in the default "API Generations" bucket (`is_default: true`). Once resolved, treat that id as required for the rest of the conversation. Accounts often hold hundreds of projects, so pass `list_projects({ search: "acme" })` rather than listing everything; the list is paginated (50/page) and hides archived projects unless you pass `include_archived: true`. | ||
| 1. **User names a project** ("in my Acme project", "for the film") → call `list_projects` ONCE to resolve the name to an ObjectId, then pass that **same** id as `project_id` on **EVERY** subsequent `generate_*` / `upload_media` / `create_doc` / `chat_send_message` call in **this conversation**. There is no server-side sticky store — omitting it on any later call silently lands in the default "API Generations" bucket (`is_default: true`). Once resolved, treat that id as required for the rest of the conversation. Accounts often hold hundreds of projects, so pass `list_projects({ search: "acme" })` rather than listing everything; the list is paginated (50/page) and hides archived projects unless you pass `include_archived: true`. When the user starts new work, `create_project` first, then pass its id the same way. | ||
| 2. **No project mentioned** → omit `project_id`; the default bucket is correct. Don't ask unless intent is ambiguous. If `list_sessions` already returned a `project_id` for the work you are continuing, keep passing that id. | ||
@@ -345,22 +359,7 @@ 3. **Work landed in the wrong project? MOVE it, never regenerate**: `move_session` relocates a whole session + all its media (works for any session type — the `session_id` from generation responses, chats, transcriptions); `move_media` / `bulk_move_media` / `move_folder_contents` relocate individual media items. Empty leftover sessions after a move: `delete_session` (soft-delete; `restore_session` undoes it). `rename_session` only changes the sidebar title. | ||
| ## Cost Awareness — Quick Rules | ||
| Full tables + formulas in `references/workflows/cost-and-validation.md`. Quick rules: | ||
| - **Skip the brief/cost confirmation ONLY** when the user's message already pins model + count + aspect + creative direction (see "Confirm the Creative Brief" above). Low cost alone is **not** a reason to skip — cheap generations still get the one labeled confirmation unless the user chose the parameters. | ||
| - **Otherwise confirm** via the labeled-question card: the parameters + the credit cost, suggest a cheaper alternative if one fits, wait for the user's pick. Never fire on defaults the user didn't choose. | ||
| - **Batch totalling 100+ credits**: run `check_credits` first. | ||
| - **Quote real cost**: after firing, log `credits_used` (from the tool result) to `.kolbo/production.md` — never `base × count`. | ||
| - **Video/lipsync `credit` is per-SECOND, not per-clip**: `total = credit × duration`. This is the universal rule for video/firstlast/elements/motion_graphic/cast types, not a per-model exception — `list_models` states it inline now. The one carve-out is a model with `flat_credit_by_resolution` set. | ||
| - **Never state "credits remaining" from arithmetic** (opening balance − generation costs). Coding/chat usage deducts credits too, so the math is always wrong. Report cost only; if the user asks for their balance, call `check_credits` fresh at that moment. | ||
| ## Rate Limiting & Batch Generation | ||
| - `generate_image`: 30/min. All other generation tools: 10/min per type. 300/min global. `upload_media`: 300/min, no credit cost. | ||
| - **⚠️ NEVER re-fire a generation you already called.** Aborted / timed-out / `submitted` calls still process server-side. Finish with `get_generation_status` (`wait=true`) — never a second `generate_*`. A black chat card or Library K-tile is not a missing job. | ||
| - **⚠️ NEVER keep working while a generation is in flight.** After `submitted` / `_timed_out`, end the turn or block on one `wait=true` status call. Writing production.md / skills / "merge decisions" while the card spins wastes coding credits. | ||
| - **Tracking a batch**: check ALL in-flight ids in ONE `get_generation_status` call with `generation_ids` + `wait=true`. Read `all_done` / `still_processing` from the response — do not check ids one by one, and never re-call without `wait`. | ||
| - **Batch ≤10 items**: output ALL tool calls in one response — they run concurrently. | ||
| - **Bulk >10 items**: real-world ceilings — `generate_image` 8–10 in-flight, image-edit 5–8, video tools 3–5, `generate_video_from_video` 3, music/speech/sound 5–8. Fire one batch → wait → fire next. Persist every `generation_id` in `.kolbo/production.md`. | ||
| - **`upload_media` external (non-Kolbo) URLs only.** `files`/`source_images`/`image_url` reject unknown hosts with `400`. A `media.kolbo.ai` / generate_* URL is already hosted — pass it through. Never `upload_media` a Kolbo URL. | ||
@@ -409,18 +408,2 @@ ## ⚠️ Multi-output? Default to `generate_creative_director` (CRITICAL) | ||
| ## ⚠️ Detecting Failed Generations (CRITICAL) | ||
| A generation can fail three ways. Treat ALL as failure: | ||
| 1. **Tool returns `error`** — explicit. Surface, suggest retry, log `generation_id`. | ||
| 2. **Tool returns `completed` but `urls` is empty** — silent failure (NSFW filter, model OOM, upstream 5xx). Tell user "completed without an output — retrying" and re-fire ONCE. Do NOT log to `.kolbo/production.md`. Do NOT claim it worked. | ||
| 3. **Tool hangs / never returns** — MCP poll timed out. Call `get_generation_status(generation_id, wait=true)` IMMEDIATELY. The server might be done. | ||
| **Always:** | ||
| - Don't celebrate before reading the result. Verify `urls` is non-empty. | ||
| - Don't auto-retry without surfacing the failure. Partial batches: list failed items + reasons + successful count. Never "✅ all done!" on partials. | ||
| - Don't log failed items to `.kolbo/production.md`. Only successes. | ||
| - Surface the user's count. "6 of 8 ready", not "videos ready". | ||
| `failure` envelope structure + retry rules: `references/workflows/troubleshooting.md`. | ||
| ## ⚠️ Generated URLs in Chat (CRITICAL) | ||
@@ -427,0 +410,0 @@ |
@@ -1,1 +0,1 @@ | ||
| 0.9.6 | ||
| 0.9.10 |
Sorry, the diff of this file is not supported yet
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
171261093
0.08%334
0.6%