{"id":67515,"plugin_id":"plugin_asdk_app_6ac64f4127ac8191a614f4860d640c20","kind":"skill","collection_source":"plugin_package","comparison_source":null,"observed_at":"2026-10-28T13:09:02.374Z","digest":"d86572f0529ff8043ed6a45dbc87a1638ab8f90b21cba6d133f194cdc90242c6","against":null,"payload":{"description":"Analyze a creative input — an ad concept, creative brief, ad transcript, script, or even a rough idea — and find which shot types are MISSING from the user's Recharm clip library. Use whenever the user asks \"what footage are we missing\", \"find gaps in our library\", \"what do we need to shoot\", \"can our library support this idea\", wants a shoot list of footage to capture before production, or wants to stress-test a creative concept against their existing clips. Brainstorms many shot types the concept calls for, searches the library visually for each, verifies hits by inspecting poster images, and delivers an HTML gap report (saved locally AND uploaded to a shareable Recharm URL) explaining each missing shot and why it would be useful. Produces a findings report, NOT a brief — never use this when the user wants a brief or clip picks for an edit.","included_files":[{"relative_path":"assets/template.html","size_in_bytes":12377}],"name":"footage-gap-finder","skill_md_contents":"---\nname: footage-gap-finder\ndescription: Analyze a creative input — an ad concept, creative brief, ad transcript, script, or even a rough idea — and find which shot types are MISSING from the user's Recharm clip library. Use whenever the user asks \"what footage are we missing\", \"find gaps in our library\", \"what do we need to shoot\", \"can our library support this idea\", wants a shoot list of footage to capture before production, or wants to stress-test a creative concept against their existing clips. Brainstorms many shot types the concept calls for, searches the library visually for each, verifies hits by inspecting poster images, and delivers an HTML gap report (saved locally AND uploaded to a shareable Recharm URL) explaining each missing shot and why it would be useful. Produces a findings report, NOT a brief — never use this when the user wants a brief or clip picks for an edit.\n---\n\n# Footage Gap Finder\n\nYou are acting as a pre-production footage auditor. The user gives you a creative input — a polished brief, an ad transcript, a concept, or a one-line idea — and your job is to figure out what shots that idea _would need_, check whether the Recharm library actually has them, and report the ones it doesn't. The deliverable is an HTML gap report that a team can take straight into a shoot-planning meeting: each gap names the missing shot, why the creative needs it, and what to capture. The report is saved locally **and** uploaded to Recharm's public-share storage so the user gets a shareable link.\n\nThe Recharm MCP server provides: `list_brands`, `list_labels`, `search_clips_visually`, `get_clip_poster_image`, `get_clip_sprite_image`, `save_html_file`. Check the live tool schemas for current parameters.\n\n**Two kinds of \"poster image\" — don't confuse them:**\n\n- Every `search_clips_visually` hit already includes a `posterUrl` (a public HTTPS still-frame URL) plus `previewUrl` and `recharmUrl`. These URLs are what you embed in the HTML report — record the `posterUrl` for every clip you cite. No extra tool call is needed to get an image URL.\n- `get_clip_poster_image` / `get_clip_sprite_image` return raw JPEG bytes **for you to look at** when judging whether a clip really depicts a shot. They are your verification eyes, not a source of embeddable URLs.\n\nThree principles drive everything below:\n\n1. **Generate generously, verify ruthlessly.** Brainstorm far more shot ideas than you expect to be missing. The value of this skill is breadth — a gap you never thought to search for is a gap you'll never report.\n2. **Visual search always returns _something_.** `search_clips_visually` ranks by similarity; it rarely returns empty. A low cosine distance is encouraging and a high one is suspicious, but neither decides anything. A shot is only \"covered\" or \"missing\" after you have **looked at poster images** of the top hits and judged whether they actually depict the shot. (An empty or near-empty result set, however, is a strong gap signal — note it.)\n3. **A gap is only worth reporting if you can argue for it.** Every gap in the report must say why this specific creative needs that shot — not \"more footage is always nice\".\n\n## Step 1 — Brand\n\nUse the brand slug if the user named one. Otherwise call `list_brands` and ask the user to pick. Don't guess.\n\n## Step 2 — Derive shot ideas from the creative input\n\nRead the input and reconstruct how the finished ad would actually be cut together. Then brainstorm **12–20 candidate shot types** that would help fulfill it. Cover the full structure, not just the obvious centerpiece:\n\n- **Hook** — the scroll-stopping first frame (often the least-stocked and most valuable category)\n- **Problem / tension** — the frustration, symptom, or \"before\" moment\n- **Product in action** — demo, application, unboxing, close-ups of texture/mechanism/UI\n- **Proof** — results, before/after, testimonial-to-camera, reactions\n- **Lifestyle / world** — the setting and people the ad lives in\n- **CTA support** — packaging, offer-friendly framing, end-card-able shots\n\nFor each shot idea, write one line: a short name, a literal visual description of what's on screen, and which beat of the creative it serves. If the input is a transcript or script, anchor shot ideas to specific lines. If it's a vague idea, infer the likely structure and say what you assumed.\n\nState the full shot-idea list before searching — it's the audit checklist, and listing it first stops you from quietly skipping ideas that are awkward to search.\n\n## Step 3 — Fetch labels\n\nCall `list_labels(brandName)` once and keep the result. Categories like **Scene Type, Asset Type, Gender, Age, Creator** are useful as search filters and as context for what the library even tracks. Only ever filter with label values returned by this call. The label list also calibrates expectations — if the concept needs gym footage and there's no fitness-adjacent label anywhere, you already suspect where gaps will cluster.\n\n## Step 4 — Search the library for each shot idea\n\nWork through the checklist. For each shot idea run **1–2 visual searches** with short literal visual phrases (under ~8 words; describe what's on screen, not concepts — \"hands opening cardboard box on counter\", not \"unboxing excitement\"). Add a label filter only when the shot clearly implies one; over-filtering hides footage that exists under unexpected labels.\n\nIf the first query for a shot comes back with nothing promising, try one rephrasing (different subject, framing, or setting) before judging — one bad query phrase shouldn't condemn a shot to gap status.\n\nWhile searching, **record `posterUrl` and `clipSymbol` for every hit you may cite later** — you'll need them for the report.\n\n## Step 5 — Judge each shot: covered or gap (the heart of this skill)\n\nFor each shot idea, look at the top hits' `cosineDistance` and descriptions, then **inspect poster images** with `get_clip_poster_image` for the hits that might plausibly match — typically the top 1–3. Judge each frame against the shot's visual description:\n\n- Does the frame actually show the shot, or something merely adjacent? (A search for \"frustrated person rubbing temples\" that returns smiling testimonials is a gap, whatever the distance score.)\n- Is the subject, framing, and setting usable for this beat — or would an editor reject it on sight?\n- If a poster is ambiguous (mid-motion, too wide), pull `get_clip_sprite_image` for the same clip before deciding.\n\nVerdict per shot idea, one line each:\n\n- **Covered** — at least one inspected clip genuinely depicts the shot. Record the best clip's `clipSymbol`, its `posterUrl`, and a short visual description of its poster. Move on.\n- **Gap** — none of the inspected hits work. Record the queries you tried and, if there was a near-miss, the closest clip's `clipSymbol`, its `posterUrl`, and _why it falls short_ — that contrast makes the report persuasive, and the thumbnail lets the reader see the miss for themselves.\n\nShortcut for clear cases: if the top hit's metadata is unambiguous and its distance is strong, one poster check is enough to confirm coverage. Spend your image-inspection budget on the borderline shots — those are where false gaps and false coverage both live.\n\n**If everything is covered, that's not the end.** A fully-covered checklist usually means the ideas were too safe. Generate a second wave of 5–10 more ambitious shot ideas — alternate hooks, unusual angles or macro details, seasonal/contextual variants, reaction shots, formats the brand likely never shot — and audit those the same way. A report with zero gaps should be rare and should explicitly say the concept is fully shootable from the library today.\n\n## Step 6 — Write up the gaps\n\nFor each gap, prepare the fields the report needs:\n\n- **Title** — short shot name (e.g. \"Late-night doomscroll hook\")\n- **Priority** — `Critical` (the ad cannot be cut without it), `High` (weakens the core narrative if missing), or `Medium` (nice-to-have variety/coverage). The report renders these as chips and a prioritized shoot list.\n- **What to capture** — a literal, shootable description a videographer could act on: subject, action, setting, framing\n- **Why it's useful** — tie it to the creative: which beat it unlocks, what the ad loses without it. This is the argument; make it concrete.\n- **What was searched** — the query phrases tried, so the user can trust (or re-run) the audit\n- **Closest existing clip** (optional) — the near-miss (`clipSymbol` + `posterUrl`) and why it doesn't work\n\nThen rank gaps by how much they'd hurt the creative if left unfilled — hook and proof gaps usually outrank b-roll gaps. Order = priority order in the shoot list.\n\n## Step 7 — Build the HTML report\n\nThe report is generated by merging your findings into a pre-built template — you don't need to write any HTML.\n\n### 7a — Assemble findings as JSON\n\n```json\n{\n  \"meta\": {\n    \"brand\": \"<brandSlug>\",\n    \"concept\": \"<one-line name of the creative input, e.g. 'Morning-routine UGC ad'>\",\n    \"date\": \"<YYYY-MM-DD>\",\n    \"shotIdeasConsidered\": <number>,\n    \"searchesRun\": <number>,\n    \"gapsFound\": <number>,\n    \"summary\": \"<1–2 sentence verdict: can the library carry this concept, and what's the biggest hole? Use <strong> tags for key phrases.>\"\n  },\n  \"gaps\": [\n    {\n      \"title\": \"<short shot name>\",\n      \"priority\": \"Critical | High | Medium\",\n      \"lookFor\": \"<what to capture — a full, shootable sentence or two: subject, action, setting, framing>\",\n      \"whyUseful\": \"<why the creative needs this shot. Use <strong> tags for key phrases.>\",\n      \"searchedFor\": [\"<query 1>\", \"<query 2>\"],\n      \"closestMatch\": {\n        \"clipSymbol\": \"<clipSymbol>\",\n        \"posterUrl\": \"<posterUrl from the search hit>\",\n        \"visualCue\": \"<short visual description of that clip's poster>\",\n        \"whyNotEnough\": \"<one sentence on why it falls short>\"\n      }\n    }\n  ],\n  \"covered\": [\n    {\n      \"title\": \"<short shot name>\",\n      \"visualCue\": \"<short visual description of the best clip's poster>\",\n      \"clipSymbol\": \"<best clipSymbol>\",\n      \"posterUrl\": \"<posterUrl from the search hit>\"\n    }\n  ]\n}\n```\n\nField notes:\n\n- Order `gaps` by impact (Step 6 ranking) — the template numbers them and builds the shoot list in this order.\n- `closestMatch` is optional; omit the key when no hit was even close. When present, always include its `posterUrl` so the reader can see the near-miss.\n- Every shot idea from your checklist (both waves) must land in either `gaps` or `covered`. Silent drops undermine trust in the audit.\n- `posterUrl` values must be copied **verbatim** from `search_clips_visually` hits — never construct or guess media URLs.\n- `lookFor` is rendered in a highlighted \"What to capture\" box — write it as direction a videographer can shoot from, not fragment cues.\n- `whyUseful` and `meta.summary` support inline HTML (`<strong>`, `<em>`). Keep each 2–4 sentences max.\n- `clipSymbol` is used to construct \"View clip\" Recharm links automatically.\n\n### 7b — Merge into the template\n\nThe template is at `<skill_base_dir>/assets/template.html` where `<skill_base_dir>` is shown in the skill header line at the top of this session (e.g. `Base directory for this skill: /path/to/footage-gap-finder`).\n\nRun this Python snippet in the bash shell to produce the output file:\n\n```python\nimport json, pathlib\n\nskill_dir  = \"<skill_base_dir>\"    # from the skill header\nbrand      = \"<brandSlug>\"\noutputs    = \"<outputs_dir>\"       # Claude's working outputs folder\n\ndata = { ... }  # your assembled JSON object from 7a\n\ntemplate = pathlib.Path(f\"{skill_dir}/assets/template.html\").read_text()\nhtml     = template.replace(\"__DATA_JSON__\", json.dumps(data)).replace(\"__BRAND__\", brand)\n\nout = pathlib.Path(outputs) / f\"footage-gaps-{brand}.html\"\nout.write_text(html)\nprint(f\"Written: {out}\")\n```\n\n**Critical — always use `json.dumps(data)`, never hand-write the JSON.** Manually constructing the JSON string inline (e.g. typing `{\"meta\": {...}, \"gaps\": [` directly into a Write tool call) is structurally fragile: an unclosed array or mismatched bracket produces a blank HTML report with no error message. Build the `data` dict as a Python object and let `json.dumps` serialize it — it is the only safe path.\n\n## Step 8 — Upload and share\n\nAfter the local file is written, upload the **same HTML string** with `save_html_file(brandName, html)`. It returns a public shareable URL.\n\nDeliver both to the user:\n\n1. The local HTML file (present it so they can open it from their machine)\n2. The shareable URL (for dropping into Slack/email — it renders the identical report, including poster thumbnails, since `posterUrl`s are public)\n\nClose with a 3–5 sentence chat summary: how many gaps, the one or two most important, and the overall verdict on whether the library can carry the concept.\n\n## What not to do\n\n- Don't call `save_brief` — this skill produces a findings report, not a brief. This holds even if the input was a brief. (`save_html_file` for the finished report is expected — that's Step 8.)\n- Don't declare a shot covered or missing from search scores alone — verdicts require inspecting poster (or sprite) images.\n- Don't condemn a shot to gap status off a single query phrasing — try a rephrase first.\n- Don't invent label values — only filter with values returned by `list_labels`.\n- Don't pad the report with generic gaps (\"more b-roll\") that aren't tied to a beat of this creative.\n- Don't drop shot ideas silently — every idea ends up in `gaps` or `covered`.\n- Don't construct media URLs by hand — embed only `posterUrl` / `recharmUrl` values copied verbatim from `search_clips_visually` hits.\n- Don't call `get_clip_poster_image` to fetch URLs for the report — it returns image bytes for your own inspection; the embeddable URL is already on the search hit.\n- Don't stop after the first wave if everything is covered — escalate to more ambitious shot ideas.\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}