gooseworks 0.5.0-dev.3.8661ef81 → 0.5.0-dev.5.1ff84a4f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6CpC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,OAAO,CAAC;IACZ,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,WAAW,EAAE,CAsCtI;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CA+C7C;AAED,eAAO,MAAM,aAAa,SAAwB,CAAC"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4CpC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,OAAO,CAAC;IACZ,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,WAAW,EAAE,CAsCtI;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CA+C7C;AAED,eAAO,MAAM,aAAa,SAAwB,CAAC"}
@@ -59,9 +59,8 @@ function onPath(bin) {
59
59
  return run(probe, [bin]).status === 0;
60
60
  }
61
61
  /**
62
- * Local video renders burn subtitles with libass and encode with libx264. An
63
- * ffmpeg without either passes a bare `which ffmpeg` and then fails mid-render,
64
- * so check the build, not the path.
62
+ * Common setup requires H.264 encoding. ASS captions additionally need libass;
63
+ * Pillow overlays do not. The selected caption renderer checks its own needs.
65
64
  */
66
65
  function ffmpegBuild() {
67
66
  if (!onPath('ffmpeg'))
@@ -70,9 +69,9 @@ function ffmpegBuild() {
70
69
  const filters = run('ffmpeg', ['-hide_banner', '-filters']).out;
71
70
  const hasX264 = /\blibx264\b/.test(encoders);
72
71
  const hasAss = /\bass\b/.test(filters);
73
- if (hasX264 && hasAss)
74
- return { ok: true, detail: 'libx264 + libass present' };
75
- const missing = [!hasX264 && 'libx264 encoder', !hasAss && 'libass `ass` filter'].filter(Boolean).join(' and ');
72
+ if (hasX264)
73
+ return { ok: true, detail: hasAss ? 'libx264 + libass present' : 'libx264 present; ASS captions unavailable, Pillow overlays supported' };
74
+ const missing = 'libx264 encoder';
76
75
  return { ok: false, detail: `ffmpeg is installed but lacks ${missing}` };
77
76
  }
78
77
  function nodeVersion() {
@@ -103,7 +102,7 @@ function runDoctorChecks(opts = {}) {
103
102
  const ffmpeg = ffmpegBuild();
104
103
  checks.push({ id: 'node', label: 'Node.js 18 or newer', ok: node.ok, detail: node.detail, fix: 'install Node 18+ (https://nodejs.org) or `nvm install 22`' }, {
105
104
  id: 'ffmpeg',
106
- label: 'ffmpeg with libx264 + libass',
105
+ label: 'ffmpeg with libx264',
107
106
  ok: ffmpeg.ok,
108
107
  detail: ffmpeg.detail,
109
108
  fix: 'brew install ffmpeg (macOS) / apt-get install ffmpeg (Linux)',
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  /** GooseWorks host binding only. Production instructions are fetched from the shared catalog. */
2
- export declare const CUSTOM_VIDEO_ADAPTER_CONTENT = "---\nname: make-custom-video\nslug: make-custom-video\ndescription: Connect the shared video production harness to GooseWorks projects, script and ingredient approvals, managed media generation, budgets and final delivery. Use for original briefs, Instagram/video references and resumed custom projects.\ncategory: ads\nversion: 2.3.2\nauthor: GooseWorks\nrequires_skills: [video-production-harness]\nharness_binding: gooseworks/v2\n---\n\n# Human version\n\nThis adapter connects the production playbook and specialist skill catalog to GooseWorks. It matches each scene to existing creator, footage, graphics, audio and review tools. Customers review and approve their script, actual ingredients and budget in the same chat. Studio is an optional review surface. The agent saves the checked final video to the same project.\n\n---\n\n# Agent version\n\n## Make Custom Video\n\nThe generic production phases run in the Growth sandbox or a connected agent with a shell. GooseWorks owns the project, approvals, budget, uploads and final selection. This adapter replaces Studio desktop files and Tauri approval events with the product contract below.\n\n## Check the connected tool contract first\n\nInspect the tool parameters exposed by the selected connection before creating or changing a custom project. catalog_fetch returns skill packages, not tool schemas. Use the host's registered tool definitions (MCP tools/list when available); do not assume that fetching a newer skill updates a connector's saved schema.\n\nvideo_project_upsert must expose custom_mode and idempotency_key for creation, reference_url when a reference is requested, and patch.script.expected_plan_revision for review saves. Before approvals, require patch.approve fields user_quote, total_credits, phase and review_token, plus custom_review.approval_quote in video_project_read. Before later writes, check that the connected tool exposes every field required by that action, including production clip checks and final quality evidence. If a required field is missing, stop before project writes or paid calls and report that the connected tools and custom-video skill are out of sync. Keep any proposed script in chat and label it as an unsaved, unapproved proposal. Do not drop required fields, switch environments, import the reference as a finished file, or create an HTML review page to work around the mismatch.\n\nThe environment owner must confirm the app-MCP service rollout and refresh the connector's discovered tool schemas. Resume only when the required parameters are visible on the same selected connection. Review and approval stay in the current chat; the Studio creative page is optional. Custom generation requires separate authenticated script and ingredient approvals with their current review tokens and cumulative budgets. Template skills' one-approval instructions do not replace either custom gate. A missing approval field is a tool rollout mismatch, not a reason to require Chrome.\n\n## Match a named format before going custom\n\nBefore creating a custom project, when the brief changes, and before any paid preview, check whether the request names or implies a catalog format: street interview / vox pop / man-on-the-street, street testimonial, podcast, iMessage or chat, split-screen creator, screen insert, listicle, and so on. Call video_catalog_list {kind:\"formats\", brand_id}, then fetch that format's renderer or recipe skill and run its own selector or checks.\n\nFor a street interview, fetch render-street-interview, read its street-script-writing guide, write a brief JSON with mode, offering_type (physical, service or digital), interaction_type and participants (people interviewed on screen, not counting the interviewer), and run python3 scripts/prepare_script_context.py --brief <brief.json> --out <context.json>. It exits 2 whenever the status is not ready-for-writing. Its route output is binding: route.support (\"render\" or \"preview-only\"), route.person_reference and route.max_participants. A status of unsupported-route lists route_gaps and alternatives; it is a stop, not permission to go custom: show the alternatives and go custom only if the customer picks it.\n\n| Street route | On screen | Person image reference | Status |\n| --- | --- | --- | --- |\n| render-street-interview product-guess (physical product only) | Interviewer and up to four participants in one take | Forbidden: people are written in the prompt; the only reference is a standalone physical product photo | Renders |\n| render-street-interview conversation (mic-only, product-sample, concept-challenge) | Interviewer and one participant | Forbidden: no reference images, no phone, screen or UI | Preview only in this format: script and prompt dry run, no paid render |\n| ugc-street-testimonial format | One person, no interviewer | Required: the creator still that format's recipe prescribes | Template format |\n\nIf the request fits a route, use that format; a fitting template format is not a custom video. If nothing fits, tell the customer in plain words what is supported and what is preview only, and name the closest supported options (the selector's alternatives) and how each differs. Or propose custom and say why. Go custom only when the customer chooses it. A custom video built on a named format still keeps that format's hard constraints. For a street interview, those are:\n\n- people described in text, never as uploaded person photos;\n- one generation per interview take;\n- deep focus;\n- the first take at 720p;\n- every caption and letter drawn locally.\n\nA selector result of needs-reference or unsupported-route, a provisional creative review or an unobserved reference is unresolved. Report it and ask before script approval; never continue past it silently.\n\n## Load the shared production harness first\n\nThis entry contains only the GooseWorks connection. Production sequencing, creative craft, reviews and repair loops are maintained in video-production-harness, published from the existing Studio harness. Do not invent a shorter local workflow.\n\nFor a new run, use the video-production-harness dependency returned by catalog_fetch or fetch_skill. If absent, fetch catalog_fetch {type:\"skill\",slug:\"video-production-harness\"}; CLI users can use gooseworks fetch video-production-harness. Require nonempty content, scripts, files, version and contentHash. Require the returned files references/editorial-review.md, references/specialist-handoff.md and references/hook-compatibility.md as nonempty text too; a coherent older release or version label does not supply missing guides. If unavailable, stop before new creative work, project writes or generation; never fall back to a vendored playbook. An unchanged approved resume keeps its recorded package and approvals.\n\nRead the returned content, orchestrator.md, capabilities.md and every detailed step invoked by the orchestrator. Materialize every returned script and file at its package-relative path in a run-specific video-production-harness folder. scripts are relative to its scripts directory; files are relative to the package root. Reject paths outside the package. Save the exact bundle only in the run's persistent workspace. Store only {slug,version,content_hash,package_path} as script_drafts.harness in the saved project; never inline the package content, files or scripts into the review draft. The review payload must stay below its 256,000-character limit. Keep the saved package in this run's durable folder, not a shared mutable installation.\n\nOn resume, read video_project_read and use the saved package matching script_drafts.harness.content_hash. Do not refetch latest or overwrite this run's package. If the package is missing, stop and restore that version before continuing; fetching today's release does not restore it. New projects load the current catalog release. This is an agent-held saved package, not a server-enforced immutable registry.\n\n## Discover specialists for the actual scenes\n\nCustom means composing available capabilities around the brief. Before the design/tool plan,\nmatch each scene and finishing step to the current skill catalog. Repeat this check when a\nnew requirement or repair appears, before writing a helper or making a provider call. The\nshared harness owns the sequence; specialist skills supply implementations inside its phases.\n\nUse the known routes below as starting points. Fetch the relevant skill, read its instructions\nand failure modes, and inspect its returned scripts/files/dependencies before choosing it.\nFor an unmatched need, use the advertised catalog_search {type:\"skill\",query:\"<capability>\"},\nor search_skills on a connection exposing that alias; CLI: gooseworks search \"<capability>\".\nUse short separate queries such as \"creator\", \"footage\", \"motion\" or \"captions\": search words\nare ANDed. Do not restrict discovery to category \"ads\"; video helpers also live under\n\"general\" and \"content\". Follow returned pagination when relevant results are not on the\nfirst page. Fetch by returned slug with catalog_fetch {type:\"skill\",slug:\"<slug>\"}, fetch_skill,\nor gooseworks fetch <slug>. Inspect the selected connection's advertised schemas first.\n\n| Scene or operation | Specialist to fetch | How it fits custom production |\n| --- | --- | --- |\n| Evidence-backed hook, script or script rewrite | [[composes::write-video-ad-script]] | Supply the actual custom scene/tool plan and brand evidence in place of a fixed template recipe. Keep the harness script review and lock. |\n| Generated creator saying an exact script across takes | [[composes::create-creator-takes-h3]] | Plan on line boundaries, preserve approved face/room/dialogue, review the first take alone and carry its native voice to later takes. |\n| Real product footage, screen recordings or screenshots | [[composes::footage-cutlist]] | Inspect source windows, map each proof shot to its line, review the cut list and render the product layer. |\n| Creator beside, over or between product footage | [[composes::compose-creator-layer]] | Combine the inspected creator track and product layer per beat. Preserve the creator's dialogue as the master audio. |\n| Native multi-cut performance or general generated B-roll | [[composes::create-video-seedance-2-fal]] or [[composes::create-video-fal]] | Choose from the actual supported endpoint/schema and quoted operations; use H3 when a continuous exact-script creator track is the better fit. |\n| Street interview, vox pop or man-on-the-street | [[composes::render-street-interview]] | Run its selector first (see \"Match a named format before going custom\"). Keep its route contract: people in text, one take per interview, 720p first take, local captions, end card and ambience bed. Do not call its one-shot driver or create a second project. |\n| A generated person in any still or as a video reference | [[composes::create-creator-takes-h3]] (scripts/make_character.py) | Follow \"People in generated images\" below. The selected route decides whether a person still is allowed at all. |\n| Grounded product edits or scene stills without a person | [[composes::create-image-fal]] or [[composes::create-image-gpt-image-fal]] | Reuse approved product references. Check preview eligibility and bounded pricing for the exact endpoint. |\n| Separate narrator or voice audition | [[composes::create-vo-elevenlabs]] | Use the host-approved voice and locked copy. Do not add a second narration over native creator speech. |\n| Music bed or song | [[composes::create-music-elevenlabs]] | Include its actual quote in the phase budget; preserve the approved audio strategy and lyric/beat timing. |\n| Branded text cards, graphics or end card | [[composes::goose-graphics]] | Start from a fitting layout/style and real logo. It produces graphics; animation still requires an actual local renderer. |\n| Narration-led zoom/pan on an existing demo | [[composes::video-polish]] | Use its measured zoom targets only with the installed Remotion/transcription capabilities required by this route. |\n| Conventional clip stitching or overlays | [[composes::stitch-videos-ffmpeg]] | Use its local implementation when it fits the edit; the shared harness assembly helper remains available for ordinary concat/mix. |\n| Word timing and final caption treatment | [[composes::caption-burn]] | Inspect the actual transcript against locked copy. Caption only after picture and mix polish, then repeat final review. |\n| Replace a defective silent B-roll window in a UGC master | [[composes::ugc-fixloop]] | Keep the original continuous dialogue; this repair does not fix a talking shot's lips or voice. |\n| Complete-video observation and finished-ad checks | [[composes::watch]] and [[composes::review-finished-ad]] | Supply real frames/audio, brand assets and timestamps. Their results support the shared final QC; they do not grant approval. |\n\nFor format-specific motion, chat, podcast, street-interview, product or music layouts, search the catalog for\nthe matching render-* capability and inspect its config and inputs. Reuse a compatible\nrenderer or phase implementation without changing the custom project into a fixed template.\nDo not call a template's one-shot driver, create a second project, or replace the shared\nproduction sequence just to use one of its helpers. The table is a starting map, not an\nexhaustive catalog or a promise that every published skill is executable on this connection.\n\n## People in generated images\n\nApply this whenever a generated image or video shows a person: creator, presenter, interviewee or any face in focus. Customers reject smooth, airbrushed, AI-looking people and blurred backgrounds.\n\n- The selected route decides first. When it forbids person references (every render-street-interview route), describe people in the video prompt and make no person stills. When it requires a person reference, make it with the builder that route prescribes. The ugc-street-testimonial recipe prescribes its own creator still.\n- Otherwise, every generated person comes from create-creator-takes-h3's scripts/make_character.py. Fetch create-creator-takes-h3 and create-image-fal together, because the builder calls create-image-fal's gen_image.py. Pass the customer's six choices (age, gender, ethnicity, hair, wardrobe and scene) and keep its defaults: fal-ai/nano-banana-pro, 4K, phone capture with deep focus, head and upper chest, face filling 45 to 55 percent. Run it with --dry-run --payload-out <file> first: the file holds {model, body}, the exact request. Quote that body through data_post_provider with path set to its model and query:{quote_only:true}, as in \"Saved review schema\". Once the still is approved and quoted, run make_character.py again without --dry-run and with GW_PROJECT_ID set to this project, so the same body goes through the managed proxy.\n- Never hand-write a person prompt, fill the generic avatar template by hand, or use fal-ai/flux/dev, fal-ai/flux/schnell or another Flux route for a face. A hand-written generic prompt is not a substitute for the builder. If the builder's request cannot be quoted, report a pricing blocker.\n- Never send a generated photoreal person still as a reference image to bytedance/seedance-2.0/reference-to-video; its likeness gate refuses uploaded images of people. For an exact-script creator from an approved still, use create-creator-takes-h3's takes.\n- Before showing ingredients, crop each face, enlarge it 2\u00D7 and look. Fix it or report it when skin is waxy or glossy, pores are missing, the background is blurred or bokeh, hands or lettering are garbled, or the face is under about 300 px tall. Show the customer only stills that pass.\n\n## Bind and retain the selected specialists\n\nA fetched package proves that instructions exist; it does not prove that its provider,\npricing, dependencies or local renderer are available. Check each selected route before\nspending. Materialize all returned scripts, files and dependency packages in separate,\nrun-specific package folders, preserving relative paths and rejecting paths outside the\npackage. Do not save several skills into one scripts folder: helpers with the same filename\nwould overwrite each other. Read the installed media-proxy dependency before running any\npaid helper. Every paid submit must propagate this project's project_id / GW_PROJECT_ID\nthrough the managed transport on the selected connection and pass the normal quote and\napproval checks. A helper that cannot carry that context is unavailable for paid custom work.\nNever run its direct-key path or substitute a guessed endpoint or price.\n\nUse specialist craft and executable helpers inside the corresponding shared phase. This\nadapter's project state, supported providers, authenticated script/ingredient gates and\nbudget override a specialist's legacy setup, dollar estimate or standalone approval flow.\nCaptions remain last even if a renderer normally burns them earlier: choose its uncaptioned\noutput or use another compatible implementation. Verify the returned scripts implement any\nrequested setting; prose alone is not an executable capability.\n\nFor H3, the creator still is a script-approved image preview, while the first native-speaking\ntake is a video and requires ingredient approval and its quoted budget. Review that take's\nvoice before the remaining takes; do not spend on it as an image/voice audition. Native H3\nspeech is not a selected ElevenLabs voice: do not invent a voice_id or replace its audio with\nseparate TTS. Save the actual audio strategy and take/reference provenance in extra draft\nfields. Use selected voice roles and playable auditions when the route actually uses them.\n\nSave a compact script_drafts.capability_plan with each selected operation's purpose,\nscene numbers (or \"final\"), skill_slug, version, content_hash, package_path, dependency\nidentities, inputs, expected outputs and supported execution route. Keep full packages in the\nrun's durable workspace, outside the 256 KB review payload. On resume, reuse the recorded\npackages and existing jobs; do not silently fetch latest over an approved run. A missing\npackage must be restored, and a changed route/model/input must be quoted and reviewed through\nthe affected custom gate before spending. If a required capability is unavailable, record\nthe limitation and propose a supported revision instead of improvising a bypass.\n\n## Carry the sourced brief and verify the handoff\n\nBefore script writing, save the writer's documented creative-brief.json from the current brand/product evidence (the Brain search's evidence brief: cited findings, the state of each query and open gaps) and project directions. Include exact product/variant, buyer situation, supported mechanism/claims, offer/CTA, constraints, delivery intent, locked copy, applicable prior decisions and explicit unknowns with source references. Before using the writer, run its free python3 <saved-writer-package>/scripts/verify_handoff.py --package-dir <saved-writer-package> --out working/script/writer-handoff-check.json check against the actual fetched prepare/lint scripts and retain the result and script hashes. A missing checker, failed check or unsupported --brief command blocks the required writer route before saving or approving a new plan; keep any chat proposal unsaved and unapproved until the compatible package is available on this same connection. Do not remove the brief, strict check or requires_creative_brief requirement to run an older parser. Use the fetched write-video-ad-script preparation command with --brief working/script/creative-brief.json and its documented bank/brand/product/template arguments; set the new shape.requires_creative_brief to true. The writer and critic consume that same angle-context. Save only the concise brief/revision and workspace reference in script_drafts extra fields, never full research/package contents. A missing required brief fails the script check; do not rerun known research or rewrite user-locked wording silently.\n\nRead references/specialist-handoff.md from the saved shared harness. For each selected UGC, product/demo or motion operation, extend the existing script_drafts.capability_plan entry with the exact approved brief/script revisions, mapped scene/beat numbers and timing, selected product/reference/source IDs and excerpt ranges, audio/performance choice, package/version/hash and expected returned artifact roles. These are existing extra draft/project artifacts, not new API parameters. Preserve the distinction between numeric script_drafts.scenes[].scene and string production scene IDs.\n\nCheck the actual returned package before executing: H3 plan_takes uses beats id/start/end/vo and character image/identity/environment/delivery; footage-cutlist uses sources and per-beat source/in/out/fit/why; goose-graphics returns static composition/PNG and still needs an actual motion renderer. Do not replace an unsupported helper with a guessed tool name. Preflight the real binary/import/browser and a free dry run, not just its presence. Existing-file skip behavior is not validity: probe saved media and verify fingerprints/approval/job results first, then reuse approved media on resume without new generation.\n\nValidate returned media and provenance against the handoff before clip checks/assembly: exact scene/source revision, words/product/variant, visible proof, measured duration/ratio, selected voice/native speech and neighboring continuity. All speech requires actual isolated performance listening and full mixed-output listening; transcript/word timing only supports that judgment. Audition representative unresolved material and reuse valid approved takes. No mandatory faster delivery or louder climax.\n\n## Hook changes and editorial review\n\nRead references/hook-compatibility.md and references/editorial-review.md from this run's saved harness. Resolve the exact watched source/render and classify same-promise hook versus a new promise requiring different body/proof/payoff. Every changed opening gets new image/action/audio/text review, including visual-only restyles with unchanged words. Shortlist cheap ideas before media spend; keep a broader recut distinct from an isolated opening test.\n\nFor an isolated hook replacement, fetch the existing render-hook-replacement package and inspect its real preflight/config contract. A not-found/empty catalog response blocks that route before paid generation; an open source change is not proof of served availability. Preserve source/body/ending using its own verification, then play/listen to the complete candidates and register each separately. Recommendations are creative judgments, never unmeasured performance winners.\n\nRun rough/fine/final review questions through the current Studio surfaces. First save what the actual cut communicates, then compare with the brief; concept review has no watched-cut verdict. Route unsupported promise to script/concept, missing proof to production, sequence problems to edit and local defects to repair. Unavailable required playback/listening is incomplete and cannot become quality_status passed.\n\nKeep exact feedback text/source/time, intended effect and acceptance condition. Consolidate duplicate notes and record conflicting intentions plus the authorized owner's decision. Preserve changed versus verified dispositions in existing feedback/production metadata or linked project artifacts; executing a fix does not resolve it. Invalidate only affected script/assets/timings/captions/mix/approvals/derivatives, retain valid unrelated work, and rewatch each actual delivered file. Preserve editable timeline, stems, caption sources, selected/candidate versions, rejected options with reasons and scoped pronunciation/delivery history for the next run. Approval and model scores are not audience performance.\n\n## GooseWorks capability binding\n\nRead capabilities.md to bind shared instructions. GooseWorks is authoritative for project state and approvals; local working artifacts grant no spending permission.\n\n- Brand facts and product assets: brand_get_context plus the saved brief/reference analysis.\n- Durable state, concept/design/script/scene/continuity records and feedback: video_project_read and video_project_upsert. Save shared artifact roles in script_drafts extra fields and production metadata; translate spoken lines, captions and scenes into the review schema below.\n- Human gates: discuss free creative choices in chat. Persist concept/design/script before authenticated script approval. Selected storyboard, playable voice auditions, characters, worlds and end card become actual ingredients. Stop for authenticated ingredient approval before any paid clip or preview video. Record the customer's explicit chat approval through patch.approve with the current phase, review token and cumulative budget; a reply alone, local artifact or shared auto mode does not record approval. A handed-off coworker cannot approve its own work. Changes require renewed approval.\n- Provider access, bounded pricing and spend: managed fal/ElevenLabs tools and currently supported endpoints only. Do not switch to direct provider keys, Higgsfield or an unpriced fallback. A missing capability blocks its state until a supported equivalent is reviewed and quoted.\n- Storage: media_upload and media_confirm with exact project ownership; use durable previews in ingredients.\n- Assembly, probes, frame extraction, transcript comparison and continuous inspection: shared package scripts, FFmpeg/FFprobe/Python and available media review tools. A thumbnail or text description cannot satisfy video review.\n- Render attempts, QC, history and promotion: video_render_run and video_project_upsert using the backend contract below. Shared QC still applies; the backend checklist is a minimum.\n\nGrowth and connected coding agents supply local execution. A terminal-free MCP client can prepare/review with connected tools, but must stop or continue through the project's Growth session when required local capabilities are absent. Never claim a render ran without execution.\n\n## Start and resume\n\nAfter the connected tool contract passes the checks above, for a new brief call video_project_upsert with brand_id, name, format:\"custom\", custom_mode:\"generate\", brief:{prompt, audience, objective, product_name, cta, ratio, duration_seconds}, optional reference_url and a stable idempotency_key. Use only brief fields present in the schema. Instagram references have a metered public-data lookup; direct files are downloaded, probed and stored. generated_video_url and media_id mean finished-file imports, never references. Do not use import mode to bypass a generation project's review gates.\n\nRead video_project_read on every resume. When it returns remix.direction for this generated custom project, use remix.direction.implementation as the production starting point: keep the pipeline, full prompts and guards, timings, assembly settings and fixes. Watch the reference. Rewrite all spoken lines and bind products, claims, images and CTA to the target brand. Stay on this same custom project; obtain fresh approvals for its own script/ingredients and budget before any paid call. A source approval or source voice recording never authorizes this new run.\n\nRead video_project_read on every resume. Its project and custom_review are authoritative. Growth creates and retains origin_session_id from trusted chat context. Show the saved review in this conversation and record the customer's explicit approval through the authenticated customer-facing connection as described below. Studio remains available when the customer wants it; never require Chrome to approve. Continue in Growth resumes the bound conversation. A handed-off production coworker prepares the review, ends its turn and waits for the customer-facing connection to record approval before it resumes the same project.\n\nIf reference preparation failed, explain custom_review.reference.error. Continue from the brief if requested, or retry with patch:{retry_reference:true}. A live preparation claim is protected for twenty minutes; after interruption an explicit retry reuses a saved resolved URL when possible. Never invent a reference analysis when no reference was viewed.\n\n## Saved review schema\n\nSave through video_project_upsert {brand_id,project_id,patch:{script:{script_drafts,script,expected_plan_revision}}}. script_drafts contains format:\"custom\", title, duration_target_sec (<=180), aspect_ratio, scenes:[{scene:1,time:\"0\u20135s\",text,caption,direction}], preview_estimate:{total_credits,basis,operations:[\"Describe each priced operation as a string\"]}, optional render_estimate in the same shape, voices:{narrator:{voice_id,name}} and ingredients:[{container,label,subtitle,url,text,note,pending}]. script_drafts.scenes[].scene is a positive integer such as 1; production scene IDs use the separate string shape described below. The plain script is joined spoken copy. Read project.plan_revision and pass it as expected_plan_revision on every existing-draft save; a stale write is refused. Store concept, reference_analysis, continuity, planned operations and job/asset provenance as extra draft fields; keep the review set under 256 KB.\n\nEach estimate requires total_credits (a nonnegative number, at most 3,000), basis (a nonempty string) and operations (1\u2013100 nonempty strings, each at most 500 characters). Do not put operation objects in either estimate. Keep detailed model/settings/cost rows in a separate extra field such as planned_operations. voices is an optional object keyed by role, never an array; each selected role is {voice_id, name?}. Keep unselected audition candidates in a separate extra field. Copy actual catalog voice IDs into the selected roles; every selected role later needs a matching playable voice ingredient.\n\nFor example, a narrator selection is voices:{narrator:{voice_id:\"<actual catalog ID>\",name:\"<catalog name>\"}}. A preview estimate is preview_estimate:{total_credits:100,basis:\"One presenter image and two voice auditions\",operations:[\"Presenter image: fixed-price supported model\",\"Two voice auditions: the saved script\"]}. These values illustrate the shape; quote the actual supported operations for the run.\n\nBefore saving either preview_estimate or render_estimate, quote each remaining paid media operation through data_post_provider with its exact supported path, body and project_id plus query:{quote_only:true}. Before sending this flag, read a fresh data_post_provider tool description from the selected connection. It must explicitly advertise query:{quote_only:true}, maximum_credits and no generation, reservation or debit. Alternatively, require explicit environment-owner evidence that this same selected app-MCP runtime has deployed free quote support. An extensible query schema or a newer fetched skill is not evidence. If the description is old and no verified runtime evidence exists, stop before the call and request the backend rollout and connector refresh; an older server can treat this flag as a paid generation request. The quote requires no approval and generates no media. This mode is MCP-only; do not send quote_only to an HTTP generation proxy.\n\n```json\n{\n \"provider\": \"fal\",\n \"path\": \"fal-ai/kling-video/v3/standard/image-to-video\",\n \"body\": {\n \"image_url\": \"https://example.com/approved-anchor.png\",\n \"duration\": \"5\",\n \"generate_audio\": false\n },\n \"project_id\": \"<this project ID>\",\n \"query\": {\n \"quote_only\": true\n }\n}\n```\n\nRequire quote_only:true, a finite positive maximum_credits and cost.credits:0 in the result. If the server returns a job, audio, a charge or any non-quote result, stop and report the tool/runtime mismatch; never retry it as a quote. Unknown or unbounded prices block planning. Do not substitute public unit prices or guessed billed discounts for maximum_credits: the custom reservation includes conservative quantity, size, audio and preset bounds, while actual settlement can be lower.\n\nSum maximum_credits for all remaining operations in the phase into that estimate's total_credits, including every concurrently planned job. Keep local free assembly/QC operations at zero. The approved project cap includes custom_review.committed_credits plus the remaining quoted estimate; committed includes both settled spend and outstanding reservations. Read the current review again before approval, avoid counting an already reserved job twice, and quote any changed model/body before seeking revised approval. Quotes are not approval tokens or locked prices; real submission rechecks its current conservative bound and the approved budget.\n\nBefore script approval, only plan/save free text. preview_estimate quotes future storyboard images and voice auditions. custom_review.script_approved permits priced image previews on supported fal image endpoints and ElevenLabs text-to-speech auditions. Unknown endpoints require ingredient approval. Use catalog voice previews when possible; do not silently select a paid model outside the preview allowlist.\n\nUpload actual previews with media_upload/media_confirm. Put public/durable URLs on image/avatar/background/endcard/voice/audio/video ingredients. Text containers can carry inline text; a voice or image description cannot replace its preview. Save a render_estimate for remaining clips/assembly and show the complete ingredients. Stop until custom_review.ingredients_approved. Script and ingredient tokens are independent; do not infer approval from project.status.\n\n## Record each approval in this chat\n\nThere are two independent gates. Script approval permits the quoted image/voice previews. Ingredient approval permits the quoted clips and finishing work after the actual review set is ready. Keep both gates even when the customer prefers chat to Studio.\n\n1. Read video_project_read. Show the current saved script or actual playable ingredients, the changes since any previous approval and the cumulative credit limit in custom_review.approval_quote. Explain that the limit includes custom_review.committed_credits plus the remaining quoted operations. An old estimate, approval from a previous revision or remaining-only amount is not the current budget.\n2. Ask for the customer's explicit approval of that phase and amount in this conversation. Copy their actual words as user_quote; never invent consent or interpret a pricing-error complaint as approval of a changed creative plan or larger budget.\n3. Read video_project_read again before recording the yes. Require the same review token, phase and total shown to the customer. If any changed, show the changed review and ask for approval of it; never silently attach the earlier yes to a newer token or amount.\n4. Through the authenticated customer-facing connection call video_project_upsert {brand_id,project_id,patch:{approve:{user_quote:\"<the customer's actual words>\",phase:custom_review.approval_quote.phase,review_token:custom_review.approval_quote.review_token,total_credits:custom_review.approval_quote.total_credits}}}. This is the custom contract; template approvals without phase and review_token cannot authorize custom production. Do not combine this approval with a script edit.\n5. Read back custom_review. For phase:\"script\", require script_approved:true and the matching script_token. For phase:\"ingredients\", require ingredients_approved:true and the matching ingredient_token. Check the approved max_credits covers the current cumulative total before dispatch. A tool error or merely sending patch.approve is not approval.\n\nThe approval_quote.phase is \"script\" or \"ingredients\". Its review_token is the matching custom_review.script_token or custom_review.ingredient_token from that saved snapshot. If approval_quote is missing or the requested phase's review is not ready, finish the free preparation or resolve the returned blocker; never guess a token, reuse the other phase's token or change the budget to force approval.\n\nOnly the authenticated customer-facing connection can record the customer's approval. A handed-off coworker with a production task prepares and displays the review, ends its turn, and waits. It cannot call patch.approve to approve its own work, forward a fabricated user_quote or treat the original brief as approval. After the customer-facing connection records and verifies approval, resume that same task/project with goose_run_task when required. Studio can record the same authenticated approvals if the customer chooses it; do not require Chrome, browser unlocks or Studio access just to approve in chat.\n\n## Paid execution and resume\n\nEvery managed media call carries project_id (GW_PROJECT_ID in scripts) and a stable input fingerprint. Use the managed fal/ElevenLabs endpoints and credentials supplied by Growth; never request customer provider keys. Do not expose those credentials in logs. Recheck custom_review before dispatch. The backend reserves estimated outstanding costs atomically, enforces the approved total (maximum 3,000 credits) and prevents duplicate submissions. At most a 20% overrun can be newly approved; this is not automatic permission to spend above the customer's selected limit. A custom video's budget grows only through a renewed approval. On SPEND_CAP_REACHED the open render is asked to stop: report it \"stopped\" with what was kept (see \"Render run states\") and tell the customer what was made and spent. Then save a revised estimate, show the new custom_review.approval_quote with its current total, record the customer's approval of that total, and open a new render that reuses the saved pieces.\n\nPreview eligibility and price support are separate checks. Use an exact endpoint permitted by the backend preview policy and confirm its current request schema and server quote. Model discovery and provider pricing can change: use the selected connection's actual quote, including supported provider estimates, instead of a skill-maintained priced-model list. A model-family name does not make every route eligible for script previews. Do not move a preview to another phase to bypass its approval gate. If pricing cannot be established, keep the saved request and report a system pricing blocker; do not ask the customer to choose when their choices are already approved. Final clip models require ingredient approval. Existing-job polls remain permitted after edits; retrieval does not authorize new media.\n\nSave provider request IDs and actual uploaded URLs promptly. Custom operations with known rejection can retry safely; ambiguous timeouts keep their authorization until reconciled. Media spend is metered through the shared gateway. Custom videos have no extra template base render fee. Imported finished files still file for zero credits.\n\n## Clips, assembly and quality\n\nUse the selected packages in script_drafts.capability_plan for each scene and operation. Recheck specialist discovery for new requirements or repairs before improvising a helper. Keep anchors and exact lines fixed. Use the Python assembly helper returned in the shared harness scripts for actual existing clips. It needs only Python, FFmpeg and FFprobe; it does not call a provider or require Chromium. Inspect generated clips before assembly, and watch the final export after assembly/captions.\n\nOpen a render with video_render_run {brand_id,project_id,kind:\"full\"}; executor:\"cloud_agent\" for Growth when exposed by the current schema. Report live workflow_stage/progress_note/progress_percent while producing it. Upload the final file to scope:\"video_project\", scope_id:project_id. The tool opens/reports a client-executed render; fixed server orders remain paused.\n\n### Render run states\n\nReport the open render's state with video_render_run {brand_id,project_id,render:{render_id,...}}. Use the row that matches:\n\n| Situation | status | workflow_stage | quality_status | Also send |\n| --- | --- | --- | --- | --- |\n| Producing, checking or repairing | \"running\" | preparing, rendering, checking, repairing or rechecking | \"pending\" | progress_note, progress_percent, steps |\n| Waiting for the customer: they must approve a candidate, choose or give feedback, with or without an uploaded candidate | \"running\" | \"blocked\" | \"blocked\" | output_url when an uploaded candidate exists, error_message saying in plain words what you need from them, and choices (at most 4 buttons; put credits on any paid choice). A quality_report is optional while waiting; when sent, it carries the current findings |\n| Stop requested: a progress callback returned stop:true because the customer stopped the video or a paid step hit the spending limit | \"stopped\" | omit | omit | progress_note saying in plain words what was kept. Start no new paid step; let a call already running finish. |\n| Real failure: no usable candidate can be produced (provider refusal with no approved alternative, or a system blocker you cannot recover) | \"failed\" | omit (the server sets blocked) | \"blocked\" | error_message in plain words |\n| Done | \"complete\" | omit (the server sets ready) | \"passed\" | output_url and the full quality_report, only after the final recipe is saved and read back as described below |\n\nWaiting for the customer is not a failure, and neither is a stop. Never report \"failed\" because you are waiting for approval, a choice or feedback, or because the customer or the spending limit stopped the video. When stop:true comes with stop_reason \"superseded\", report nothing further on that render. The app shows a waiting render's candidate as \"Needs your approval\" and keeps it for up to 14 days; after that the server ends it as failed with failure_code review_expired. The uploaded file stays in the project either way.\n\nA waiting state is valid only while the approval it rests on is current. A render can complete only under the approval it was opened with. After any script or ingredient edit (yours or the customer's), or after review_expired, the old render cannot be completed: read video_project_read {brand_id,project_id,include:[\"assets\",\"renders\"]}, show the changed review and the current custom_review.approval_quote in chat, record the customer's approval of each phase it asks for, then open a new render. Opening a new render stops the older open render of this video with stop_reason \"superseded\" (\"Replaced by a newer version.\"). Report nothing more on a superseded render and start no paid step for it; continue on the new one. To deliver an unchanged candidate on the new render, follow \"Finalize an existing candidate after re-approval\" below.\n\nWhen the customer approves a waiting candidate and nothing in the review changed, finish the shared final review and complete that same render; a candidate needs no separate approval phase. When they ask for changes, save the feedback and follow the normal edit and approval gates.\n\nOn resume, treat a render left at \"running\" with workflow_stage \"blocked\" as a pending customer decision. Read custom_review and custom_review.feedback before doing anything else. If your own render shows stop_reason \"superseded\", another run replaced it: read video_project_read {brand_id,project_id,include:[\"assets\",\"renders\"]} and continue on the newer render; do not open another one just to resume.\n\nAfter each accepted generation or deterministic edit, update patch.production with the steps and settings that actually ran. Save and read back the actual candidate recipe before showing its preview or pausing for review, so an interrupted or waiting run does not leave only an early plan in the backend. Partial progress is allowed; pending creative approval or QC must stay explicit and must never be converted into passing clip evidence.\n\nBefore completing or pinning a candidate, replace the early planning manifest with the actual production recipe. Record every current script scene using its string scene number, exact current spoken line, measured duration and full generation prompts or deterministic rendering instructions. Record the actual pipeline/model settings, assembly/captions/audio settings, and repairs in fixes. Never leave blocked/pending planning statuses in a completed recipe. Preserve full prompts and guards; do not reduce them to summaries. Save partial progress while working, but an unfinished recipe is not a reusable final.\n\nSave the final recipe through patch.production, then read video_project_read and compare production_manifest with what you just saved, including all scene IDs and spoken lines. If the save fails or the read-back is stale/incomplete, repair it before completion; do not describe the run as finished or remixable. Final completion freezes the actual recipe and reviewed script together for the next agent.\n\nSave patch.production as a production manifest with version:1 and a nonempty pipeline array. Each pipeline item requires step and model; purpose and settings are optional. production.characters is an optional array, never a record/object: each entry requires both name and prompt strings. Store anchor media IDs, URLs, actual appearance and other extra provenance in script_drafts; character entries accept name and the full design prompt.\n\nproduction.scenes[].id is a string containing the corresponding script scene number, for example \"1\". script_drafts.scenes[].scene and production.clips[].scene remain positive integers, for example 1. Map production scene IDs with String(scriptScene.scene); do not convert clip.scene or script scene IDs to strings. Each scene can also carry line, still_prompt, motion_prompt, duration_s and notes. style is an object; voice and music are objects when present; assembly is an object; fixes is an array of {problem,fix}.\n\nEach clip requires a numeric scene, a stored URL and exactly one of each named check: visual_artifacts, brand, product, voice_and_script, duration_and_ratio. Each clip check is {check,status:\"pass\"|\"fail\",note?}; not_applicable is not valid for clip checks. Save exactly one checked clip per approved script scene before final completion, with every check passing. Before clips exist, omit clips from an ingredient-preparation save.\n\nThe following is a one-scene JSON shape example. Replace all placeholders with actual saved values. Its failed QC statuses are deliberately unapproved; never copy a passing status without performing the shared review.\n\n```json\n{\n \"patch\": {\n \"production\": {\n \"version\": 1,\n \"pipeline\": [\n {\n \"step\": \"Scene clips\",\n \"model\": \"<actual supported model>\",\n \"settings\": {}\n }\n ],\n \"style\": {\n \"prompt\": \"<shared visual direction>\",\n \"negative\": \"<shared guards>\"\n },\n \"characters\": [\n {\n \"name\": \"Presenter\",\n \"prompt\": \"<exact full character design prompt>\"\n }\n ],\n \"scenes\": [\n {\n \"id\": \"1\",\n \"line\": \"<approved spoken line>\",\n \"still_prompt\": \"<exact full still prompt>\",\n \"motion_prompt\": \"<exact full motion prompt and guards>\",\n \"duration_s\": 5\n }\n ],\n \"voice\": {\n \"voice_id\": \"<selected catalog voice ID>\",\n \"name\": \"<selected voice name>\",\n \"model\": \"<actual voice model>\",\n \"settings\": {}\n },\n \"assembly\": {\n \"ratio\": \"9:16\",\n \"fps\": 30\n },\n \"fixes\": [],\n \"clips\": [\n {\n \"scene\": 1,\n \"url\": \"https://example.com/confirmed-scene-1.mp4\",\n \"checks\": [\n {\n \"check\": \"visual_artifacts\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"brand\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"product\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"voice_and_script\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"duration_and_ratio\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n }\n ]\n }\n ]\n }\n }\n}\n```\n\nComplete with video_render_run {brand_id,project_id,render:{render_id,status:\"complete\",output_url,quality_status:\"passed\",quality_report:{version:1,summary,checks:{source,brand,product,hook_and_scene_order,voice_and_script,captions,endcard_and_cta,duration_and_ratio,visual_artifacts},detected_issues:[],repair_actions:[],checked_at}}}. Each final check is {status:\"pass\"|\"fail\"|\"not_applicable\",note}; brand/product/scene order/duration/visual artifacts must pass. A candidate that fails QC is never complete: keep it \"running\" with workflow_stage \"repairing\" while you fix it, report the waiting state above when the customer must decide, and use \"failed\" only for a real failure. Final completion binds approval revisions, output and quality evidence to the render; pin with patch.final_render_id only after passing.\n\nAll nine named final checks above are required, including source, voice_and_script, captions and endcard_and_cta when they are not applicable. A final check uses status:\"pass\"|\"fail\"|\"not_applicable\" and an optional note. The five mandatory passing checks are brand, product, hook_and_scene_order, duration_and_ratio and visual_artifacts; no final check may fail and detected_issues must be empty to complete. Record why a permitted check is not_applicable. Keep actual repair_actions and use the actual ISO 8601 checked_at time. The backend report is a minimum; it does not replace the full shared watch, claim verification or craft review.\n\nThis waiting-for-the-customer report illustrates every required field. Replace the URL, reason, choices, findings and example timestamp with actual evidence. Only after repairs and the shared final review pass may the render be reported complete with quality_status:\"passed\", its confirmed output_url and no unresolved issues.\n\n```json\n{\n \"render\": {\n \"render_id\": \"<existing render ID>\",\n \"status\": \"running\",\n \"workflow_stage\": \"blocked\",\n \"quality_status\": \"blocked\",\n \"output_url\": \"https://example.com/confirmed-candidate-in-this-project.mp4\",\n \"error_message\": \"<what you need from the customer, in plain words>\",\n \"choices\": [\n {\n \"label\": \"Approve this version\",\n \"message\": \"I approve this version\"\n },\n {\n \"label\": \"Change something\",\n \"message\": \"I want to change something in this version\"\n }\n ],\n \"quality_report\": {\n \"version\": 1,\n \"summary\": \"<actual full-video review summary>\",\n \"checks\": {\n \"source\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"brand\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"product\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"hook_and_scene_order\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"voice_and_script\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"captions\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"endcard_and_cta\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"duration_and_ratio\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"visual_artifacts\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n }\n },\n \"detected_issues\": [\n \"<actual unresolved issue>\"\n ],\n \"repair_actions\": [],\n \"checked_at\": \"2026-10-03T00:00:00Z\"\n }\n }\n}\n```\n\n### Finalize an existing candidate after re-approval\n\nUse this when an uploaded candidate (a confirmed video in this project) already shows and says exactly what the current script says, but its render can no longer complete: the script was amended to match the take, or the wait ended as review_expired. If any spoken line, caption, scene or ingredient differs from the current script, this route does not apply: repair or regenerate under the normal gates.\n\n1. If the script changed, save it and record the customer's script approval first, as in \"Record each approval in this chat\". Then save the candidate as a video ingredient (its confirmed URL) in the review set, show the candidate and the current custom_review.approval_quote in chat, and record the ingredient approval. The earlier render was approved against the old review, and the server will not complete it.\n2. Open a new render with video_render_run {brand_id,project_id,kind:\"full\"}. Start no provider call. The older waiting render stops as superseded.\n3. Run the shared final review on the existing file against the current script. voice_and_script and captions must match the current lines.\n4. Save and read back the final production recipe with the current lines and one checked clip per scene, as described in \"Clips, assembly and quality\". Reuse the clip records from the candidate's saved recipe, updated to the current lines.\n5. Complete the new render with status:\"complete\", output_url set to the existing candidate's confirmed URL, quality_status:\"passed\" and the full quality_report. Do not regenerate or re-upload. No credits are spent.\n6. Pin it with video_project_upsert patch.final_render_id (alias set_final_render).\n\n## Feedback and delivery\n\nSave customer script/ingredient/video feedback through the connected project tools before continuation; affected creative edits invalidate their approvals. Read custom_review.feedback on every turn, preserving the original watched render/time and text when provided. A selected final change never relocates an earlier note. Resolve only after the candidate satisfies the original intended effect and full-output recheck; keep incomplete or conflicting notes open. Replace only the affected assets; save revised estimates and show the changed review and cumulative budget in the same chat before recording renewed approval. Deliver the playable current_render_url with render_artifact kind:\"video\" in Growth and actual project spend. Include the Studio app_url when a text host or the customer needs it; do not require it for approval. Keep final history; never create another project just because an agent restarted.\n\n## Reviewed snapshot, voices and supported pricing\n\ncustom_review returns script_drafts and plan_revision from the same saved snapshot as its tokens. Show that snapshot in chat; Studio can also render it. Use the revision for edits and the current approval_quote for each approval. Spoken copy (text) and on-screen copy (caption) are separate fields. Voice audition ingredients carry role and voice_id; script_drafts.voices maps each role to its selected voice_id/name. Every selected role needs an actual matching playable preview before approval.\n\nA pending/processing/failed reference blocks script approval. If the customer explicitly chooses to continue from the brief without the reference, save that choice through the connected reference-review tool when exposed, or offer Studio's Continue from brief action when needed. This is a reference decision, not a requirement to approve in Chrome. Do not silently replace a requested reference with brief-only production.\n\nCustom provider submits require a positive server quote, including quantity, supported dimensions/audio and any provider estimate. The server must establish source duration for audio/video-driven routes from authorized media metadata or a bounded probe; do not add invented duration fields to the provider body to force a quote. A provider estimate permits production within the approved budget even when exact final billing is unavailable. Missing source duration or an unavailable provider estimate is a system blocker to resolve on the saved project, not a model allowlist or a new creative choice. A conservative reservation is released to actual charged spend when the provider result settles. Final output must be a confirmed, stored video_asset in this exact organization/project, and completion binds its media_id to the render. External hotlinks cannot be pinned as generated custom finals. The portable helper checks FFmpeg's libass capability before local captions, rejects clips shorter than their timeline and validates video-stream duration.\n";
2
+ export declare const CUSTOM_VIDEO_ADAPTER_CONTENT = "---\nname: make-custom-video\nslug: make-custom-video\ndescription: Connect the shared video production harness to GooseWorks projects, script and ingredient approvals, managed media generation, budgets and final delivery. Use for original briefs, Instagram/video references and resumed custom projects.\ncategory: ads\nversion: 2.3.2\nauthor: GooseWorks\nrequires_skills: [video-production-harness]\nharness_binding: gooseworks/v2\n---\n\n# Human version\n\nThis adapter connects the production playbook and specialist skill catalog to GooseWorks. It matches each scene to existing creator, footage, graphics, audio and review tools. Customers review and approve their script, actual ingredients and budget in the same chat. Studio is an optional review surface. The agent saves the checked final video to the same project.\n\n---\n\n# Agent version\n\n## Make Custom Video\n\nThe generic production phases run in the Growth sandbox or a connected agent with a shell. GooseWorks owns the project, approvals, budget, uploads and final selection. This adapter replaces Studio desktop files and Tauri approval events with the product contract below.\n\n## Execution preflight\n\nA connected agent with a working shell executes this custom project locally. Declare client:{shell:true} on every video/format/catalog request that accepts it, including video_project_read. Each call can reach a different server process; a previous capability report does not carry over reliably. Missing libass does not remove shell capability: fetch [[composes::caption-burn]], which uses Pillow and FFmpeg overlay. Fetch every selected specialist and the invoked harness step files before declaring a route unavailable.\n\nFor MCP-owned runs set GW_MEDIA_VIA=mcp and GW_PROJECT_ID before running any helper, even if CLI credentials exist. Record the selected account_whoami public API origin as GW_EXPECTED_API_ORIGIN; never open credential files to discover it. Use HTTP only after verifying the matching origin through supported CLI diagnostics. For large MCP relay bodies, use the helper's body_file without retyping: upload that JSON file to this same video project, confirm the returned asset, then call data_post_provider with body_asset_id and omit body when the tool advertises that argument. Its normal project, approval, budget and secret checks still apply. Older connectors must relay the exact saved JSON unchanged.\n\nBefore taking over a delegated project, cancel its delegate task and read back that it is detached. Do not request another approval while a stale delegate remains attached. If cancellation is unsupported, save the blocker; a Stop followed by reapproval can wake the same delegate again.\n\nAfter a paid failure, reconcile the known job and actual charges. Stop after the first identical infrastructure failure; a failed coworker turn can still cost credits. Quotes are estimates, not actual spend. Preserve approved copy while changing cost explanations; show actual cumulative charges from the project ledger.\n\nRun helpers from the run's working directory with explicit absolute input/output paths. For footage, save inspected source in/out bounds and fit:width, including screen.fit:width. A planned creator image may be absent during free take planning; use plan_takes --plan-only instead of generating a placeholder.\n\nThe writer's paid critic cannot run before custom script approval. Perform its rubric locally before script review and save that evidence. Only run an external critic when the host explicitly supports it in the current approved phase and budget; never bypass a spend gate or silently claim an independent critic ran.\n\n## Check the connected tool contract first\n\nInspect the tool parameters exposed by the selected connection before creating or changing a custom project. catalog_fetch returns skill packages, not tool schemas. Use the host's registered tool definitions (MCP tools/list when available); do not assume that fetching a newer skill updates a connector's saved schema.\n\nvideo_project_upsert must expose custom_mode and idempotency_key for creation, reference_url when a reference is requested, and patch.script.expected_plan_revision for review saves. Before approvals, require patch.approve fields user_quote, total_credits, phase and review_token, plus custom_review.approval_quote in video_project_read. Before later writes, check that the connected tool exposes every field required by that action, including production clip checks and final quality evidence. If a required field is missing, stop before project writes or paid calls and report that the connected tools and custom-video skill are out of sync. Keep any proposed script in chat and label it as an unsaved, unapproved proposal. Do not drop required fields, switch environments, import the reference as a finished file, or create an HTML review page to work around the mismatch.\n\nThe environment owner must confirm the app-MCP service rollout and refresh the connector's discovered tool schemas. Resume only when the required parameters are visible on the same selected connection. Review and approval stay in the current chat; the Studio creative page is optional. Custom generation requires separate authenticated script and ingredient approvals with their current review tokens and cumulative budgets. Template skills' one-approval instructions do not replace either custom gate. A missing approval field is a tool rollout mismatch, not a reason to require Chrome.\n\n## Match a named format before going custom\n\nBefore creating a custom project, when the brief changes, and before any paid preview, check whether the request names or implies a catalog format: street interview / vox pop / man-on-the-street, street testimonial, podcast, iMessage or chat, split-screen creator, screen insert, listicle, and so on. Call video_catalog_list {kind:\"formats\", brand_id}, then fetch that format's renderer or recipe skill and run its own selector or checks.\n\nFor a street interview, fetch render-street-interview, read its street-script-writing guide, write a brief JSON with mode, offering_type (physical, service or digital), interaction_type and participants (people interviewed on screen, not counting the interviewer), and run python3 scripts/prepare_script_context.py --brief <brief.json> --out <context.json>. It exits 2 whenever the status is not ready-for-writing. Its route output is binding: route.support (\"render\" or \"preview-only\"), route.person_reference and route.max_participants. A status of unsupported-route lists route_gaps and alternatives; it is a stop, not permission to go custom: show the alternatives and go custom only if the customer picks it.\n\n| Street route | On screen | Person image reference | Status |\n| --- | --- | --- | --- |\n| render-street-interview product-guess (physical product only) | Interviewer and up to four participants in one take | Forbidden: people are written in the prompt; the only reference is a standalone physical product photo | Renders |\n| render-street-interview conversation (mic-only, product-sample, concept-challenge) | Interviewer and one participant | Forbidden: no reference images, no phone, screen or UI | Preview only in this format: script and prompt dry run, no paid render |\n| ugc-street-testimonial format | One person, no interviewer | Required: the creator still that format's recipe prescribes | Template format |\n\nIf the request fits a route, use that format; a fitting template format is not a custom video. If nothing fits, tell the customer in plain words what is supported and what is preview only, and name the closest supported options (the selector's alternatives) and how each differs. Or propose custom and say why. Go custom only when the customer chooses it. A custom video built on a named format still keeps that format's hard constraints. For a street interview, those are:\n\n- people described in text, never as uploaded person photos;\n- one generation per interview take;\n- deep focus;\n- the first take at 720p;\n- every caption and letter drawn locally.\n\nA selector result of needs-reference or unsupported-route, a provisional creative review or an unobserved reference is unresolved. Report it and ask before script approval; never continue past it silently.\n\n## Load the shared production harness first\n\nThis entry contains only the GooseWorks connection. Production sequencing, creative craft, reviews and repair loops are maintained in video-production-harness, published from the existing Studio harness. Do not invent a shorter local workflow.\n\nFor a new run, use the video-production-harness dependency returned by catalog_fetch or fetch_skill. If absent, fetch catalog_fetch {type:\"skill\",slug:\"video-production-harness\"}; CLI users can use gooseworks fetch video-production-harness. Require nonempty content, scripts, files, version and contentHash. Require the returned files references/editorial-review.md, references/specialist-handoff.md and references/hook-compatibility.md as nonempty text too; a coherent older release or version label does not supply missing guides. If unavailable, stop before new creative work, project writes or generation; never fall back to a vendored playbook. An unchanged approved resume keeps its recorded package and approvals.\n\nRead the returned content, orchestrator.md, capabilities.md and every detailed step invoked by the orchestrator. Materialize every returned script and file at its package-relative path in a run-specific video-production-harness folder. scripts are relative to its scripts directory; files are relative to the package root. Reject paths outside the package. Save the exact bundle only in the run's persistent workspace. Store only {slug,version,content_hash,package_path} as script_drafts.harness in the saved project; never inline the package content, files or scripts into the review draft. The review payload must stay below its 256,000-character limit. Keep the saved package in this run's durable folder, not a shared mutable installation.\n\nOn resume, read video_project_read and use the saved package matching script_drafts.harness.content_hash. Do not refetch latest or overwrite this run's package. If the package is missing, stop and restore that version before continuing; fetching today's release does not restore it. New projects load the current catalog release. This is an agent-held saved package, not a server-enforced immutable registry.\n\n## Discover specialists for the actual scenes\n\nCustom means composing available capabilities around the brief. Before the design/tool plan,\nmatch each scene and finishing step to the current skill catalog. Repeat this check when a\nnew requirement or repair appears, before writing a helper or making a provider call. The\nshared harness owns the sequence; specialist skills supply implementations inside its phases.\n\nUse the known routes below as starting points. Fetch the relevant skill, read its instructions\nand failure modes, and inspect its returned scripts/files/dependencies before choosing it.\nFor an unmatched need, use the advertised catalog_search {type:\"skill\",query:\"<capability>\"},\nor search_skills on a connection exposing that alias; CLI: gooseworks search \"<capability>\".\nUse short separate queries such as \"creator\", \"footage\", \"motion\" or \"captions\": search words\nare ANDed. Do not restrict discovery to category \"ads\"; video helpers also live under\n\"general\" and \"content\". Follow returned pagination when relevant results are not on the\nfirst page. Fetch by returned slug with catalog_fetch {type:\"skill\",slug:\"<slug>\"}, fetch_skill,\nor gooseworks fetch <slug>. Inspect the selected connection's advertised schemas first.\n\n| Scene or operation | Specialist to fetch | How it fits custom production |\n| --- | --- | --- |\n| Evidence-backed hook, script or script rewrite | [[composes::write-video-ad-script]] | Supply the actual custom scene/tool plan and brand evidence in place of a fixed template recipe. Keep the harness script review and lock. |\n| Generated creator saying an exact script across takes | [[composes::create-creator-takes-h3]] | Plan on line boundaries, preserve approved face/room/dialogue, review the first take alone and carry its native voice to later takes. |\n| Real product footage, screen recordings or screenshots | [[composes::footage-cutlist]] | Inspect source windows, map each proof shot to its line, review the cut list and render the product layer. |\n| Creator beside, over or between product footage | [[composes::compose-creator-layer]] | Combine the inspected creator track and product layer per beat. Preserve the creator's dialogue as the master audio. |\n| Native multi-cut performance or general generated B-roll | [[composes::create-video-seedance-2-fal]] or [[composes::create-video-fal]] | Choose from the actual supported endpoint/schema and quoted operations; use H3 when a continuous exact-script creator track is the better fit. |\n| Street interview, vox pop or man-on-the-street | [[composes::render-street-interview]] | Run its selector first (see \"Match a named format before going custom\"). Keep its route contract: people in text, one take per interview, 720p first take, local captions, end card and ambience bed. Do not call its one-shot driver or create a second project. |\n| A generated person in any still or as a video reference | [[composes::create-creator-takes-h3]] (scripts/make_character.py) | Follow \"People in generated images\" below. The selected route decides whether a person still is allowed at all. |\n| Grounded product edits or scene stills without a person | [[composes::create-image-fal]] or [[composes::create-image-gpt-image-fal]] | Reuse approved product references. Check preview eligibility and bounded pricing for the exact endpoint. |\n| Separate narrator or voice audition | [[composes::create-vo-elevenlabs]] | Use the host-approved voice and locked copy. Do not add a second narration over native creator speech. |\n| Music bed or song | [[composes::create-music-elevenlabs]] | Include its actual quote in the phase budget; preserve the approved audio strategy and lyric/beat timing. |\n| Branded text cards, graphics or end card | [[composes::goose-graphics]] | Start from a fitting layout/style and real logo. It produces graphics; animation still requires an actual local renderer. |\n| Narration-led zoom/pan on an existing demo | [[composes::video-polish]] | Use its measured zoom targets only with the installed Remotion/transcription capabilities required by this route. |\n| Conventional clip stitching or overlays | [[composes::stitch-videos-ffmpeg]] | Use its local implementation when it fits the edit; the shared harness assembly helper remains available for ordinary concat/mix. |\n| Word timing and final caption treatment | [[composes::caption-burn]] | Inspect the actual transcript against locked copy. Caption only after picture and mix polish, then repeat final review. |\n| Replace a defective silent B-roll window in a UGC master | [[composes::ugc-fixloop]] | Keep the original continuous dialogue; this repair does not fix a talking shot's lips or voice. |\n| Complete-video observation and finished-ad checks | [[composes::watch]] and [[composes::review-finished-ad]] | Supply real frames/audio, brand assets and timestamps. Their results support the shared final QC; they do not grant approval. |\n\nFor format-specific motion, chat, podcast, street-interview, product or music layouts, search the catalog for\nthe matching render-* capability and inspect its config and inputs. Reuse a compatible\nrenderer or phase implementation without changing the custom project into a fixed template.\nDo not call a template's one-shot driver, create a second project, or replace the shared\nproduction sequence just to use one of its helpers. The table is a starting map, not an\nexhaustive catalog or a promise that every published skill is executable on this connection.\n\n## People in generated images\n\nApply this whenever a generated image or video shows a person: creator, presenter, interviewee or any face in focus. Customers reject smooth, airbrushed, AI-looking people and blurred backgrounds.\n\n- The selected route decides first. When it forbids person references (every render-street-interview route), describe people in the video prompt and make no person stills. When it requires a person reference, make it with the builder that route prescribes. The ugc-street-testimonial recipe prescribes its own creator still.\n- Otherwise, every generated person comes from create-creator-takes-h3's scripts/make_character.py. Fetch create-creator-takes-h3 and create-image-fal together, because the builder calls create-image-fal's gen_image.py. Pass the customer's six choices (age, gender, ethnicity, hair, wardrobe and scene) and keep its defaults: fal-ai/nano-banana-pro, 4K, phone capture with deep focus, head and upper chest, face filling 45 to 55 percent. Run it with --dry-run --payload-out <file> first: the file holds {model, body}, the exact request. Quote that body through data_post_provider with path set to its model and query:{quote_only:true}, as in \"Saved review schema\". Once the still is approved and quoted, run make_character.py again without --dry-run and with GW_PROJECT_ID set to this project, so the same body goes through the managed proxy.\n- Never hand-write a person prompt, fill the generic avatar template by hand, or use fal-ai/flux/dev, fal-ai/flux/schnell or another Flux route for a face. A hand-written generic prompt is not a substitute for the builder. If the builder's request cannot be quoted, report a pricing blocker.\n- Never send a generated photoreal person still as a reference image to bytedance/seedance-2.0/reference-to-video; its likeness gate refuses uploaded images of people. For an exact-script creator from an approved still, use create-creator-takes-h3's takes.\n- Before showing ingredients, crop each face, enlarge it 2\u00D7 and look. Fix it or report it when skin is waxy or glossy, pores are missing, the background is blurred or bokeh, hands or lettering are garbled, or the face is under about 300 px tall. Show the customer only stills that pass.\n\n## Bind and retain the selected specialists\n\nA fetched package proves that instructions exist; it does not prove that its provider,\npricing, dependencies or local renderer are available. Check each selected route before\nspending. Materialize all returned scripts, files and dependency packages in separate,\nrun-specific package folders, preserving relative paths and rejecting paths outside the\npackage. Do not save several skills into one scripts folder: helpers with the same filename\nwould overwrite each other. Read the installed media-proxy dependency before running any\npaid helper. Every paid submit must propagate this project's project_id / GW_PROJECT_ID\nthrough the managed transport on the selected connection and pass the normal quote and\napproval checks. A helper that cannot carry that context is unavailable for paid custom work.\nNever run its direct-key path or substitute a guessed endpoint or price.\n\nUse specialist craft and executable helpers inside the corresponding shared phase. This\nadapter's project state, supported providers, authenticated script/ingredient gates and\nbudget override a specialist's legacy setup, dollar estimate or standalone approval flow.\nCaptions remain last even if a renderer normally burns them earlier: choose its uncaptioned\noutput or use another compatible implementation. Verify the returned scripts implement any\nrequested setting; prose alone is not an executable capability.\n\nFor H3, the creator still is a script-approved image preview, while the first native-speaking\ntake is a video and requires ingredient approval and its quoted budget. Review that take's\nvoice before the remaining takes; do not spend on it as an image/voice audition. Native H3\nspeech is not a selected ElevenLabs voice: do not invent a voice_id or replace its audio with\nseparate TTS. Save the actual audio strategy and take/reference provenance in extra draft\nfields. Use selected voice roles and playable auditions when the route actually uses them.\n\nSave a compact script_drafts.capability_plan with each selected operation's purpose,\nscene numbers (or \"final\"), skill_slug, version, content_hash, package_path, dependency\nidentities, inputs, expected outputs and supported execution route. Keep full packages in the\nrun's durable workspace, outside the 256 KB review payload. On resume, reuse the recorded\npackages and existing jobs; do not silently fetch latest over an approved run. A missing\npackage must be restored, and a changed route/model/input must be quoted and reviewed through\nthe affected custom gate before spending. If a required capability is unavailable, record\nthe limitation and propose a supported revision instead of improvising a bypass.\n\n## Carry the sourced brief and verify the handoff\n\nBefore script writing, save the writer's documented creative-brief.json from the current brand/product evidence (the Brain search's evidence brief: cited findings, the state of each query and open gaps) and project directions. Include exact product/variant, buyer situation, supported mechanism/claims, offer/CTA, constraints, delivery intent, locked copy, applicable prior decisions and explicit unknowns with source references. Before using the writer, run its free python3 <saved-writer-package>/scripts/verify_handoff.py --package-dir <saved-writer-package> --out working/script/writer-handoff-check.json check against the actual fetched prepare/lint scripts and retain the result and script hashes. A missing checker, failed check or unsupported --brief command blocks the required writer route before saving or approving a new plan; keep any chat proposal unsaved and unapproved until the compatible package is available on this same connection. Do not remove the brief, strict check or requires_creative_brief requirement to run an older parser. Use the fetched write-video-ad-script preparation command with --brief working/script/creative-brief.json and its documented bank/brand/product/template arguments; set the new shape.requires_creative_brief to true. The writer and critic consume that same angle-context. Save only the concise brief/revision and workspace reference in script_drafts extra fields, never full research/package contents. A missing required brief fails the script check; do not rerun known research or rewrite user-locked wording silently.\n\nRead references/specialist-handoff.md from the saved shared harness. For each selected UGC, product/demo or motion operation, extend the existing script_drafts.capability_plan entry with the exact approved brief/script revisions, mapped scene/beat numbers and timing, selected product/reference/source IDs and excerpt ranges, audio/performance choice, package/version/hash and expected returned artifact roles. These are existing extra draft/project artifacts, not new API parameters. Preserve the distinction between numeric script_drafts.scenes[].scene and string production scene IDs.\n\nCheck the actual returned package before executing: H3 plan_takes uses beats id/start/end/vo and character image/identity/environment/delivery; footage-cutlist uses sources and per-beat source/in/out/fit/why; goose-graphics returns static composition/PNG and still needs an actual motion renderer. Do not replace an unsupported helper with a guessed tool name. Preflight the real binary/import/browser and a free dry run, not just its presence. Existing-file skip behavior is not validity: probe saved media and verify fingerprints/approval/job results first, then reuse approved media on resume without new generation.\n\nValidate returned media and provenance against the handoff before clip checks/assembly: exact scene/source revision, words/product/variant, visible proof, measured duration/ratio, selected voice/native speech and neighboring continuity. All speech requires actual isolated performance listening and full mixed-output listening; transcript/word timing only supports that judgment. Audition representative unresolved material and reuse valid approved takes. No mandatory faster delivery or louder climax.\n\n## Hook changes and editorial review\n\nRead references/hook-compatibility.md and references/editorial-review.md from this run's saved harness. Resolve the exact watched source/render and classify same-promise hook versus a new promise requiring different body/proof/payoff. Every changed opening gets new image/action/audio/text review, including visual-only restyles with unchanged words. Shortlist cheap ideas before media spend; keep a broader recut distinct from an isolated opening test.\n\nFor an isolated hook replacement, fetch the existing render-hook-replacement package and inspect its real preflight/config contract. A not-found/empty catalog response blocks that route before paid generation; an open source change is not proof of served availability. Preserve source/body/ending using its own verification, then play/listen to the complete candidates and register each separately. Recommendations are creative judgments, never unmeasured performance winners.\n\nRun rough/fine/final review questions through the current Studio surfaces. First save what the actual cut communicates, then compare with the brief; concept review has no watched-cut verdict. Route unsupported promise to script/concept, missing proof to production, sequence problems to edit and local defects to repair. Unavailable required playback/listening is incomplete and cannot become quality_status passed.\n\nKeep exact feedback text/source/time, intended effect and acceptance condition. Consolidate duplicate notes and record conflicting intentions plus the authorized owner's decision. Preserve changed versus verified dispositions in existing feedback/production metadata or linked project artifacts; executing a fix does not resolve it. Invalidate only affected script/assets/timings/captions/mix/approvals/derivatives, retain valid unrelated work, and rewatch each actual delivered file. Preserve editable timeline, stems, caption sources, selected/candidate versions, rejected options with reasons and scoped pronunciation/delivery history for the next run. Approval and model scores are not audience performance.\n\n## GooseWorks capability binding\n\nRead capabilities.md to bind shared instructions. GooseWorks is authoritative for project state and approvals; local working artifacts grant no spending permission.\n\n- Brand facts and product assets: brand_get_context plus the saved brief/reference analysis.\n- Durable state, concept/design/script/scene/continuity records and feedback: video_project_read and video_project_upsert. Save shared artifact roles in script_drafts extra fields and production metadata; translate spoken lines, captions and scenes into the review schema below.\n- Human gates: discuss free creative choices in chat. Persist concept/design/script before authenticated script approval. Selected storyboard, playable voice auditions, characters, worlds and end card become actual ingredients. Stop for authenticated ingredient approval before any paid clip or preview video. Record the customer's explicit chat approval through patch.approve with the current phase, review token and cumulative budget; a reply alone, local artifact or shared auto mode does not record approval. A handed-off coworker cannot approve its own work. Changes require renewed approval.\n- Provider access, bounded pricing and spend: managed fal/ElevenLabs tools and currently supported endpoints only. Do not switch to direct provider keys, Higgsfield or an unpriced fallback. A missing capability blocks its state until a supported equivalent is reviewed and quoted.\n- Storage: media_upload and media_confirm with exact project ownership; use durable previews in ingredients.\n- Assembly, probes, frame extraction, transcript comparison and continuous inspection: shared package scripts, FFmpeg/FFprobe/Python and available media review tools. A thumbnail or text description cannot satisfy video review.\n- Render attempts, QC, history and promotion: video_render_run and video_project_upsert using the backend contract below. Shared QC still applies; the backend checklist is a minimum.\n\nGrowth and connected coding agents supply local execution. A terminal-free MCP client can prepare/review with connected tools, but must stop or continue through the project's Growth session when required local capabilities are absent. Never claim a render ran without execution.\n\n## Start and resume\n\nAfter the connected tool contract passes the checks above, for a new brief call video_project_upsert with brand_id, name, format:\"custom\", custom_mode:\"generate\", brief:{prompt, audience, objective, product_name, cta, ratio, duration_seconds}, optional reference_url and a stable idempotency_key. Use only brief fields present in the schema. Instagram references have a metered public-data lookup; direct files are downloaded, probed and stored. generated_video_url and media_id mean finished-file imports, never references. Do not use import mode to bypass a generation project's review gates.\n\nRead video_project_read on every resume. When it returns remix.direction for this generated custom project, use remix.direction.implementation as the production starting point: keep the pipeline, full prompts and guards, timings, assembly settings and fixes. Watch the reference. Rewrite all spoken lines and bind products, claims, images and CTA to the target brand. Stay on this same custom project; obtain fresh approvals for its own script/ingredients and budget before any paid call. A source approval or source voice recording never authorizes this new run.\n\nRead video_project_read on every resume. Its project and custom_review are authoritative. Growth creates and retains origin_session_id from trusted chat context. Show the saved review in this conversation and record the customer's explicit approval through the authenticated customer-facing connection as described below. Studio remains available when the customer wants it; never require Chrome to approve. Continue in Growth resumes the bound conversation. A handed-off production coworker prepares the review, ends its turn and waits for the customer-facing connection to record approval before it resumes the same project.\n\nIf reference preparation failed, explain custom_review.reference.error. Continue from the brief if requested, or retry with patch:{retry_reference:true}. A live preparation claim is protected for twenty minutes; after interruption an explicit retry reuses a saved resolved URL when possible. Never invent a reference analysis when no reference was viewed.\n\n## Saved review schema\n\nSave through video_project_upsert {brand_id,project_id,patch:{script:{script_drafts,script,expected_plan_revision}}}. script_drafts contains format:\"custom\", title, duration_target_sec (<=180), aspect_ratio, scenes:[{scene:1,time:\"0\u20135s\",text,caption,direction}], preview_estimate:{total_credits,basis,operations:[\"Describe each priced operation as a string\"]}, optional render_estimate in the same shape, voices:{narrator:{voice_id,name}} and ingredients:[{container,label,subtitle,url,text,note,pending}]. script_drafts.scenes[].scene is a positive integer such as 1; production scene IDs use the separate string shape described below. The plain script is joined spoken copy. Read project.plan_revision and pass it as expected_plan_revision on every existing-draft save; a stale write is refused. Store concept, reference_analysis, continuity, planned operations and job/asset provenance as extra draft fields; keep the review set under 256 KB.\n\nEach estimate requires total_credits (a nonnegative number, at most 3,000), basis (a nonempty string) and operations (1\u2013100 nonempty strings, each at most 500 characters). Do not put operation objects in either estimate. Keep detailed model/settings/cost rows in a separate extra field such as planned_operations. voices is an optional object keyed by role, never an array; each selected role is {voice_id, name?}. Keep unselected audition candidates in a separate extra field. Copy actual catalog voice IDs into the selected roles; every selected role later needs a matching playable voice ingredient.\n\nFor example, a narrator selection is voices:{narrator:{voice_id:\"<actual catalog ID>\",name:\"<catalog name>\"}}. A preview estimate is preview_estimate:{total_credits:100,basis:\"One presenter image and two voice auditions\",operations:[\"Presenter image: fixed-price supported model\",\"Two voice auditions: the saved script\"]}. These values illustrate the shape; quote the actual supported operations for the run.\n\nBefore saving either preview_estimate or render_estimate, quote each remaining paid media operation through data_post_provider with its exact supported path, body and project_id plus query:{quote_only:true}. Before sending this flag, read a fresh data_post_provider tool description from the selected connection. It must explicitly advertise query:{quote_only:true}, maximum_credits and no generation, reservation or debit. Alternatively, require explicit environment-owner evidence that this same selected app-MCP runtime has deployed free quote support. An extensible query schema or a newer fetched skill is not evidence. If the description is old and no verified runtime evidence exists, stop before the call and request the backend rollout and connector refresh; an older server can treat this flag as a paid generation request. The quote requires no approval and generates no media. This mode is MCP-only; do not send quote_only to an HTTP generation proxy.\n\n```json\n{\n \"provider\": \"fal\",\n \"path\": \"fal-ai/kling-video/v3/standard/image-to-video\",\n \"body\": {\n \"image_url\": \"https://example.com/approved-anchor.png\",\n \"duration\": \"5\",\n \"generate_audio\": false\n },\n \"project_id\": \"<this project ID>\",\n \"query\": {\n \"quote_only\": true\n }\n}\n```\n\nRequire quote_only:true, a finite positive maximum_credits and cost.credits:0 in the result. If the server returns a job, audio, a charge or any non-quote result, stop and report the tool/runtime mismatch; never retry it as a quote. Unknown or unbounded prices block planning. Do not substitute public unit prices or guessed billed discounts for maximum_credits: the custom reservation includes conservative quantity, size, audio and preset bounds, while actual settlement can be lower.\n\nSum maximum_credits for all remaining operations in the phase into that estimate's total_credits, including every concurrently planned job. Keep local free assembly/QC operations at zero. The approved project cap includes custom_review.committed_credits plus the remaining quoted estimate; committed includes both settled spend and outstanding reservations. Read the current review again before approval, avoid counting an already reserved job twice, and quote any changed model/body before seeking revised approval. Quotes are not approval tokens or locked prices; real submission rechecks its current conservative bound and the approved budget.\n\nBefore script approval, only plan/save free text. preview_estimate quotes future storyboard images and voice auditions. custom_review.script_approved permits priced image previews on supported fal image endpoints and ElevenLabs text-to-speech auditions. Unknown endpoints require ingredient approval. Use catalog voice previews when possible; do not silently select a paid model outside the preview allowlist.\n\nUpload actual previews with media_upload/media_confirm. Put public/durable URLs on image/avatar/background/endcard/voice/audio/video ingredients. Text containers can carry inline text; a voice or image description cannot replace its preview. Save a render_estimate for remaining clips/assembly and show the complete ingredients. Stop until custom_review.ingredients_approved. Script and ingredient tokens are independent; do not infer approval from project.status.\n\n## Record each approval in this chat\n\nThere are two independent gates. Script approval permits the quoted image/voice previews. Ingredient approval permits the quoted clips and finishing work after the actual review set is ready. Keep both gates even when the customer prefers chat to Studio.\n\n1. Read video_project_read. Show the current saved script or actual playable ingredients, the changes since any previous approval and the cumulative credit limit in custom_review.approval_quote. Explain that the limit includes custom_review.committed_credits plus the remaining quoted operations. An old estimate, approval from a previous revision or remaining-only amount is not the current budget.\n2. Ask for the customer's explicit approval of that phase and amount in this conversation. Copy their actual words as user_quote; never invent consent or interpret a pricing-error complaint as approval of a changed creative plan or larger budget.\n3. Read video_project_read again before recording the yes. Require the same review token, phase and total shown to the customer. If any changed, show the changed review and ask for approval of it; never silently attach the earlier yes to a newer token or amount.\n4. Through the authenticated customer-facing connection call video_project_upsert {brand_id,project_id,patch:{approve:{user_quote:\"<the customer's actual words>\",phase:custom_review.approval_quote.phase,review_token:custom_review.approval_quote.review_token,total_credits:custom_review.approval_quote.total_credits}}}. This is the custom contract; template approvals without phase and review_token cannot authorize custom production. Do not combine this approval with a script edit.\n5. Read back custom_review. For phase:\"script\", require script_approved:true and the matching script_token. For phase:\"ingredients\", require ingredients_approved:true and the matching ingredient_token. Check the approved max_credits covers the current cumulative total before dispatch. A tool error or merely sending patch.approve is not approval.\n\nThe approval_quote.phase is \"script\" or \"ingredients\". Its review_token is the matching custom_review.script_token or custom_review.ingredient_token from that saved snapshot. If approval_quote is missing or the requested phase's review is not ready, finish the free preparation or resolve the returned blocker; never guess a token, reuse the other phase's token or change the budget to force approval.\n\nOnly the authenticated customer-facing connection can record the customer's approval. A handed-off coworker with a production task prepares and displays the review, ends its turn, and waits. It cannot call patch.approve to approve its own work, forward a fabricated user_quote or treat the original brief as approval. After the customer-facing connection records and verifies approval, resume that same task/project with goose_run_task when required. Studio can record the same authenticated approvals if the customer chooses it; do not require Chrome, browser unlocks or Studio access just to approve in chat.\n\n## Paid execution and resume\n\nEvery managed media call carries project_id (GW_PROJECT_ID in scripts) and a stable input fingerprint. Use the managed fal/ElevenLabs endpoints and credentials supplied by Growth; never request customer provider keys. Do not expose those credentials in logs. Recheck custom_review before dispatch. The backend reserves estimated outstanding costs atomically, enforces the approved total (maximum 3,000 credits) and prevents duplicate submissions. At most a 20% overrun can be newly approved; this is not automatic permission to spend above the customer's selected limit. A custom video's budget grows only through a renewed approval. On SPEND_CAP_REACHED the open render is asked to stop: report it \"stopped\" with what was kept (see \"Render run states\") and tell the customer what was made and spent. Then save a revised estimate, show the new custom_review.approval_quote with its current total, record the customer's approval of that total, and open a new render that reuses the saved pieces.\n\nPreview eligibility and price support are separate checks. Use an exact endpoint permitted by the backend preview policy and confirm its current request schema and server quote. Model discovery and provider pricing can change: use the selected connection's actual quote, including supported provider estimates, instead of a skill-maintained priced-model list. A model-family name does not make every route eligible for script previews. Do not move a preview to another phase to bypass its approval gate. If pricing cannot be established, keep the saved request and report a system pricing blocker; do not ask the customer to choose when their choices are already approved. Final clip models require ingredient approval. Existing-job polls remain permitted after edits; retrieval does not authorize new media.\n\nSave provider request IDs and actual uploaded URLs promptly. Custom operations with known rejection can retry safely; ambiguous timeouts keep their authorization until reconciled. Media spend is metered through the shared gateway. Custom videos have no extra template base render fee. Imported finished files still file for zero credits.\n\n## Clips, assembly and quality\n\nUse the selected packages in script_drafts.capability_plan for each scene and operation. Recheck specialist discovery for new requirements or repairs before improvising a helper. Keep anchors and exact lines fixed. Use the Python assembly helper returned in the shared harness scripts for actual existing clips. It needs only Python, FFmpeg and FFprobe; it does not call a provider or require Chromium. Inspect generated clips before assembly, and watch the final export after assembly/captions.\n\nOpen a render with video_render_run {brand_id,project_id,kind:\"full\"}; executor:\"cloud_agent\" for Growth when exposed by the current schema. Report live workflow_stage/progress_note/progress_percent while producing it. Upload the final file to scope:\"video_project\", scope_id:project_id. The tool opens/reports a client-executed render; fixed server orders remain paused.\n\n### Render run states\n\nReport the open render's state with video_render_run {brand_id,project_id,render:{render_id,...}}. Use the row that matches:\n\n| Situation | status | workflow_stage | quality_status | Also send |\n| --- | --- | --- | --- | --- |\n| Producing, checking or repairing | \"running\" | preparing, rendering, checking, repairing or rechecking | \"pending\" | progress_note, progress_percent, steps |\n| Waiting for the customer: they must approve a candidate, choose or give feedback, with or without an uploaded candidate | \"running\" | \"blocked\" | \"blocked\" | output_url when an uploaded candidate exists, error_message saying in plain words what you need from them, and choices (at most 4 buttons; put credits on any paid choice). A quality_report is optional while waiting; when sent, it carries the current findings |\n| Stop requested: a progress callback returned stop:true because the customer stopped the video or a paid step hit the spending limit | \"stopped\" | omit | omit | progress_note saying in plain words what was kept. Start no new paid step; let a call already running finish. |\n| Real failure: no usable candidate can be produced (provider refusal with no approved alternative, or a system blocker you cannot recover) | \"failed\" | omit (the server sets blocked) | \"blocked\" | error_message in plain words |\n| Done | \"complete\" | omit (the server sets ready) | \"passed\" | output_url and the full quality_report, only after the final recipe is saved and read back as described below |\n\nWaiting for the customer is not a failure, and neither is a stop. Never report \"failed\" because you are waiting for approval, a choice or feedback, or because the customer or the spending limit stopped the video. When stop:true comes with stop_reason \"superseded\", report nothing further on that render. The app shows a waiting render's candidate as \"Needs your approval\" and keeps it for up to 14 days; after that the server ends it as failed with failure_code review_expired. The uploaded file stays in the project either way.\n\nA waiting state is valid only while the approval it rests on is current. A render can complete only under the approval it was opened with. After any script or ingredient edit (yours or the customer's), or after review_expired, the old render cannot be completed: read video_project_read {brand_id,project_id,include:[\"assets\",\"renders\"]}, show the changed review and the current custom_review.approval_quote in chat, record the customer's approval of each phase it asks for, then open a new render. Opening a new render stops the older open render of this video with stop_reason \"superseded\" (\"Replaced by a newer version.\"). Report nothing more on a superseded render and start no paid step for it; continue on the new one. To deliver an unchanged candidate on the new render, follow \"Finalize an existing candidate after re-approval\" below.\n\nWhen the customer approves a waiting candidate and nothing in the review changed, finish the shared final review and complete that same render; a candidate needs no separate approval phase. When they ask for changes, save the feedback and follow the normal edit and approval gates.\n\nOn resume, treat a render left at \"running\" with workflow_stage \"blocked\" as a pending customer decision. Read custom_review and custom_review.feedback before doing anything else. If your own render shows stop_reason \"superseded\", another run replaced it: read video_project_read {brand_id,project_id,include:[\"assets\",\"renders\"]} and continue on the newer render; do not open another one just to resume.\n\nAfter each accepted generation or deterministic edit, update patch.production with the steps and settings that actually ran. Save and read back the actual candidate recipe before showing its preview or pausing for review, so an interrupted or waiting run does not leave only an early plan in the backend. Partial progress is allowed; pending creative approval or QC must stay explicit and must never be converted into passing clip evidence.\n\nBefore completing or pinning a candidate, replace the early planning manifest with the actual production recipe. Record every current script scene using its string scene number, exact current spoken line, measured duration and full generation prompts or deterministic rendering instructions. Record the actual pipeline/model settings, assembly/captions/audio settings, and repairs in fixes. Never leave blocked/pending planning statuses in a completed recipe. Preserve full prompts and guards; do not reduce them to summaries. Save partial progress while working, but an unfinished recipe is not a reusable final.\n\nSave the final recipe through patch.production, then read video_project_read and compare production_manifest with what you just saved, including all scene IDs and spoken lines. If the save fails or the read-back is stale/incomplete, repair it before completion; do not describe the run as finished or remixable. Final completion freezes the actual recipe and reviewed script together for the next agent.\n\nSave patch.production as a production manifest with version:1 and a nonempty pipeline array. Each pipeline item requires step and model; purpose and settings are optional. production.characters is an optional array, never a record/object: each entry requires both name and prompt strings. Store anchor media IDs, URLs, actual appearance and other extra provenance in script_drafts; character entries accept name and the full design prompt.\n\nproduction.scenes[].id is a string containing the corresponding script scene number, for example \"1\". script_drafts.scenes[].scene and production.clips[].scene remain positive integers, for example 1. Map production scene IDs with String(scriptScene.scene); do not convert clip.scene or script scene IDs to strings. Each scene can also carry line, still_prompt, motion_prompt, duration_s and notes. style is an object; voice and music are objects when present; assembly is an object; fixes is an array of {problem,fix}.\n\nEach clip requires a numeric scene, a stored URL and exactly one of each named check: visual_artifacts, brand, product, voice_and_script, duration_and_ratio. Each clip check is {check,status:\"pass\"|\"fail\",note?}; not_applicable is not valid for clip checks. Save exactly one checked clip per approved script scene before final completion, with every check passing. Before clips exist, omit clips from an ingredient-preparation save.\n\nThe following is a one-scene JSON shape example. Replace all placeholders with actual saved values. Its failed QC statuses are deliberately unapproved; never copy a passing status without performing the shared review.\n\n```json\n{\n \"patch\": {\n \"production\": {\n \"version\": 1,\n \"pipeline\": [\n {\n \"step\": \"Scene clips\",\n \"model\": \"<actual supported model>\",\n \"settings\": {}\n }\n ],\n \"style\": {\n \"prompt\": \"<shared visual direction>\",\n \"negative\": \"<shared guards>\"\n },\n \"characters\": [\n {\n \"name\": \"Presenter\",\n \"prompt\": \"<exact full character design prompt>\"\n }\n ],\n \"scenes\": [\n {\n \"id\": \"1\",\n \"line\": \"<approved spoken line>\",\n \"still_prompt\": \"<exact full still prompt>\",\n \"motion_prompt\": \"<exact full motion prompt and guards>\",\n \"duration_s\": 5\n }\n ],\n \"voice\": {\n \"voice_id\": \"<selected catalog voice ID>\",\n \"name\": \"<selected voice name>\",\n \"model\": \"<actual voice model>\",\n \"settings\": {}\n },\n \"assembly\": {\n \"ratio\": \"9:16\",\n \"fps\": 30\n },\n \"fixes\": [],\n \"clips\": [\n {\n \"scene\": 1,\n \"url\": \"https://example.com/confirmed-scene-1.mp4\",\n \"checks\": [\n {\n \"check\": \"visual_artifacts\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"brand\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"product\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"voice_and_script\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"duration_and_ratio\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n }\n ]\n }\n ]\n }\n }\n}\n```\n\nComplete with video_render_run {brand_id,project_id,render:{render_id,status:\"complete\",output_url,quality_status:\"passed\",quality_report:{version:1,summary,checks:{source,brand,product,hook_and_scene_order,voice_and_script,captions,endcard_and_cta,duration_and_ratio,visual_artifacts},detected_issues:[],repair_actions:[],checked_at}}}. Each final check is {status:\"pass\"|\"fail\"|\"not_applicable\",note}; brand/product/scene order/duration/visual artifacts must pass. A candidate that fails QC is never complete: keep it \"running\" with workflow_stage \"repairing\" while you fix it, report the waiting state above when the customer must decide, and use \"failed\" only for a real failure. Final completion binds approval revisions, output and quality evidence to the render; pin with patch.final_render_id only after passing.\n\nAll nine named final checks above are required, including source, voice_and_script, captions and endcard_and_cta when they are not applicable. A final check uses status:\"pass\"|\"fail\"|\"not_applicable\" and an optional note. The five mandatory passing checks are brand, product, hook_and_scene_order, duration_and_ratio and visual_artifacts; no final check may fail and detected_issues must be empty to complete. Record why a permitted check is not_applicable. Keep actual repair_actions and use the actual ISO 8601 checked_at time. The backend report is a minimum; it does not replace the full shared watch, claim verification or craft review.\n\nThis waiting-for-the-customer report illustrates every required field. Replace the URL, reason, choices, findings and example timestamp with actual evidence. Only after repairs and the shared final review pass may the render be reported complete with quality_status:\"passed\", its confirmed output_url and no unresolved issues.\n\n```json\n{\n \"render\": {\n \"render_id\": \"<existing render ID>\",\n \"status\": \"running\",\n \"workflow_stage\": \"blocked\",\n \"quality_status\": \"blocked\",\n \"output_url\": \"https://example.com/confirmed-candidate-in-this-project.mp4\",\n \"error_message\": \"<what you need from the customer, in plain words>\",\n \"choices\": [\n {\n \"label\": \"Approve this version\",\n \"message\": \"I approve this version\"\n },\n {\n \"label\": \"Change something\",\n \"message\": \"I want to change something in this version\"\n }\n ],\n \"quality_report\": {\n \"version\": 1,\n \"summary\": \"<actual full-video review summary>\",\n \"checks\": {\n \"source\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"brand\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"product\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"hook_and_scene_order\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"voice_and_script\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"captions\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"endcard_and_cta\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"duration_and_ratio\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"visual_artifacts\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n }\n },\n \"detected_issues\": [\n \"<actual unresolved issue>\"\n ],\n \"repair_actions\": [],\n \"checked_at\": \"2026-10-03T00:00:00Z\"\n }\n }\n}\n```\n\n### Finalize an existing candidate after re-approval\n\nUse this when an uploaded candidate (a confirmed video in this project) already shows and says exactly what the current script says, but its render can no longer complete: the script was amended to match the take, or the wait ended as review_expired. If any spoken line, caption, scene or ingredient differs from the current script, this route does not apply: repair or regenerate under the normal gates.\n\n1. If the script changed, save it and record the customer's script approval first, as in \"Record each approval in this chat\". Then save the candidate as a video ingredient (its confirmed URL) in the review set, show the candidate and the current custom_review.approval_quote in chat, and record the ingredient approval. The earlier render was approved against the old review, and the server will not complete it.\n2. Open a new render with video_render_run {brand_id,project_id,kind:\"full\"}. Start no provider call. The older waiting render stops as superseded.\n3. Run the shared final review on the existing file against the current script. voice_and_script and captions must match the current lines.\n4. Save and read back the final production recipe with the current lines and one checked clip per scene, as described in \"Clips, assembly and quality\". Reuse the clip records from the candidate's saved recipe, updated to the current lines.\n5. Complete the new render with status:\"complete\", output_url set to the existing candidate's confirmed URL, quality_status:\"passed\" and the full quality_report. Do not regenerate or re-upload. No credits are spent.\n6. Pin it with video_project_upsert patch.final_render_id (alias set_final_render).\n\n## Feedback and delivery\n\nSave customer script/ingredient/video feedback through the connected project tools before continuation; affected creative edits invalidate their approvals. Read custom_review.feedback on every turn, preserving the original watched render/time and text when provided. A selected final change never relocates an earlier note. Resolve only after the candidate satisfies the original intended effect and full-output recheck; keep incomplete or conflicting notes open. Replace only the affected assets; save revised estimates and show the changed review and cumulative budget in the same chat before recording renewed approval. Deliver the playable current_render_url with render_artifact kind:\"video\" in Growth and actual project spend. Include the Studio app_url when a text host or the customer needs it; do not require it for approval. Keep final history; never create another project just because an agent restarted.\n\n## Reviewed snapshot, voices and supported pricing\n\ncustom_review returns script_drafts and plan_revision from the same saved snapshot as its tokens. Show that snapshot in chat; Studio can also render it. Use the revision for edits and the current approval_quote for each approval. Spoken copy (text) and on-screen copy (caption) are separate fields. Voice audition ingredients carry role and voice_id; script_drafts.voices maps each role to its selected voice_id/name. Every selected role needs an actual matching playable preview before approval.\n\nA pending/processing/failed reference blocks script approval. If the customer explicitly chooses to continue from the brief without the reference, save that choice through the connected reference-review tool when exposed, or offer Studio's Continue from brief action when needed. This is a reference decision, not a requirement to approve in Chrome. Do not silently replace a requested reference with brief-only production.\n\nCustom provider submits require a positive server quote, including quantity, supported dimensions/audio and any provider estimate. The server must establish source duration for audio/video-driven routes from authorized media metadata or a bounded probe; do not add invented duration fields to the provider body to force a quote. A provider estimate permits production within the approved budget even when exact final billing is unavailable. Missing source duration or an unavailable provider estimate is a system blocker to resolve on the saved project, not a model allowlist or a new creative choice. A conservative reservation is released to actual charged spend when the provider result settles. Final output must be a confirmed, stored video_asset in this exact organization/project, and completion binds its media_id to the render. External hotlinks cannot be pinned as generated custom finals. The portable helper checks FFmpeg's libass capability before local captions, rejects clips shorter than their timeline and validates video-stream duration.\n";
3
3
  //# sourceMappingURL=custom-video-skill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-video-skill.d.ts","sourceRoot":"","sources":["../../src/skills/custom-video-skill.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,eAAO,MAAM,4BAA4B,61wDAA80wD,CAAC"}
1
+ {"version":3,"file":"custom-video-skill.d.ts","sourceRoot":"","sources":["../../src/skills/custom-video-skill.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,eAAO,MAAM,4BAA4B,wy1DAAyx1D,CAAC"}
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CUSTOM_VIDEO_ADAPTER_CONTENT = void 0;
4
4
  /** GooseWorks host binding only. Production instructions are fetched from the shared catalog. */
5
- exports.CUSTOM_VIDEO_ADAPTER_CONTENT = "---\nname: make-custom-video\nslug: make-custom-video\ndescription: Connect the shared video production harness to GooseWorks projects, script and ingredient approvals, managed media generation, budgets and final delivery. Use for original briefs, Instagram/video references and resumed custom projects.\ncategory: ads\nversion: 2.3.2\nauthor: GooseWorks\nrequires_skills: [video-production-harness]\nharness_binding: gooseworks/v2\n---\n\n# Human version\n\nThis adapter connects the production playbook and specialist skill catalog to GooseWorks. It matches each scene to existing creator, footage, graphics, audio and review tools. Customers review and approve their script, actual ingredients and budget in the same chat. Studio is an optional review surface. The agent saves the checked final video to the same project.\n\n---\n\n# Agent version\n\n## Make Custom Video\n\nThe generic production phases run in the Growth sandbox or a connected agent with a shell. GooseWorks owns the project, approvals, budget, uploads and final selection. This adapter replaces Studio desktop files and Tauri approval events with the product contract below.\n\n## Check the connected tool contract first\n\nInspect the tool parameters exposed by the selected connection before creating or changing a custom project. catalog_fetch returns skill packages, not tool schemas. Use the host's registered tool definitions (MCP tools/list when available); do not assume that fetching a newer skill updates a connector's saved schema.\n\nvideo_project_upsert must expose custom_mode and idempotency_key for creation, reference_url when a reference is requested, and patch.script.expected_plan_revision for review saves. Before approvals, require patch.approve fields user_quote, total_credits, phase and review_token, plus custom_review.approval_quote in video_project_read. Before later writes, check that the connected tool exposes every field required by that action, including production clip checks and final quality evidence. If a required field is missing, stop before project writes or paid calls and report that the connected tools and custom-video skill are out of sync. Keep any proposed script in chat and label it as an unsaved, unapproved proposal. Do not drop required fields, switch environments, import the reference as a finished file, or create an HTML review page to work around the mismatch.\n\nThe environment owner must confirm the app-MCP service rollout and refresh the connector's discovered tool schemas. Resume only when the required parameters are visible on the same selected connection. Review and approval stay in the current chat; the Studio creative page is optional. Custom generation requires separate authenticated script and ingredient approvals with their current review tokens and cumulative budgets. Template skills' one-approval instructions do not replace either custom gate. A missing approval field is a tool rollout mismatch, not a reason to require Chrome.\n\n## Match a named format before going custom\n\nBefore creating a custom project, when the brief changes, and before any paid preview, check whether the request names or implies a catalog format: street interview / vox pop / man-on-the-street, street testimonial, podcast, iMessage or chat, split-screen creator, screen insert, listicle, and so on. Call video_catalog_list {kind:\"formats\", brand_id}, then fetch that format's renderer or recipe skill and run its own selector or checks.\n\nFor a street interview, fetch render-street-interview, read its street-script-writing guide, write a brief JSON with mode, offering_type (physical, service or digital), interaction_type and participants (people interviewed on screen, not counting the interviewer), and run python3 scripts/prepare_script_context.py --brief <brief.json> --out <context.json>. It exits 2 whenever the status is not ready-for-writing. Its route output is binding: route.support (\"render\" or \"preview-only\"), route.person_reference and route.max_participants. A status of unsupported-route lists route_gaps and alternatives; it is a stop, not permission to go custom: show the alternatives and go custom only if the customer picks it.\n\n| Street route | On screen | Person image reference | Status |\n| --- | --- | --- | --- |\n| render-street-interview product-guess (physical product only) | Interviewer and up to four participants in one take | Forbidden: people are written in the prompt; the only reference is a standalone physical product photo | Renders |\n| render-street-interview conversation (mic-only, product-sample, concept-challenge) | Interviewer and one participant | Forbidden: no reference images, no phone, screen or UI | Preview only in this format: script and prompt dry run, no paid render |\n| ugc-street-testimonial format | One person, no interviewer | Required: the creator still that format's recipe prescribes | Template format |\n\nIf the request fits a route, use that format; a fitting template format is not a custom video. If nothing fits, tell the customer in plain words what is supported and what is preview only, and name the closest supported options (the selector's alternatives) and how each differs. Or propose custom and say why. Go custom only when the customer chooses it. A custom video built on a named format still keeps that format's hard constraints. For a street interview, those are:\n\n- people described in text, never as uploaded person photos;\n- one generation per interview take;\n- deep focus;\n- the first take at 720p;\n- every caption and letter drawn locally.\n\nA selector result of needs-reference or unsupported-route, a provisional creative review or an unobserved reference is unresolved. Report it and ask before script approval; never continue past it silently.\n\n## Load the shared production harness first\n\nThis entry contains only the GooseWorks connection. Production sequencing, creative craft, reviews and repair loops are maintained in video-production-harness, published from the existing Studio harness. Do not invent a shorter local workflow.\n\nFor a new run, use the video-production-harness dependency returned by catalog_fetch or fetch_skill. If absent, fetch catalog_fetch {type:\"skill\",slug:\"video-production-harness\"}; CLI users can use gooseworks fetch video-production-harness. Require nonempty content, scripts, files, version and contentHash. Require the returned files references/editorial-review.md, references/specialist-handoff.md and references/hook-compatibility.md as nonempty text too; a coherent older release or version label does not supply missing guides. If unavailable, stop before new creative work, project writes or generation; never fall back to a vendored playbook. An unchanged approved resume keeps its recorded package and approvals.\n\nRead the returned content, orchestrator.md, capabilities.md and every detailed step invoked by the orchestrator. Materialize every returned script and file at its package-relative path in a run-specific video-production-harness folder. scripts are relative to its scripts directory; files are relative to the package root. Reject paths outside the package. Save the exact bundle only in the run's persistent workspace. Store only {slug,version,content_hash,package_path} as script_drafts.harness in the saved project; never inline the package content, files or scripts into the review draft. The review payload must stay below its 256,000-character limit. Keep the saved package in this run's durable folder, not a shared mutable installation.\n\nOn resume, read video_project_read and use the saved package matching script_drafts.harness.content_hash. Do not refetch latest or overwrite this run's package. If the package is missing, stop and restore that version before continuing; fetching today's release does not restore it. New projects load the current catalog release. This is an agent-held saved package, not a server-enforced immutable registry.\n\n## Discover specialists for the actual scenes\n\nCustom means composing available capabilities around the brief. Before the design/tool plan,\nmatch each scene and finishing step to the current skill catalog. Repeat this check when a\nnew requirement or repair appears, before writing a helper or making a provider call. The\nshared harness owns the sequence; specialist skills supply implementations inside its phases.\n\nUse the known routes below as starting points. Fetch the relevant skill, read its instructions\nand failure modes, and inspect its returned scripts/files/dependencies before choosing it.\nFor an unmatched need, use the advertised catalog_search {type:\"skill\",query:\"<capability>\"},\nor search_skills on a connection exposing that alias; CLI: gooseworks search \"<capability>\".\nUse short separate queries such as \"creator\", \"footage\", \"motion\" or \"captions\": search words\nare ANDed. Do not restrict discovery to category \"ads\"; video helpers also live under\n\"general\" and \"content\". Follow returned pagination when relevant results are not on the\nfirst page. Fetch by returned slug with catalog_fetch {type:\"skill\",slug:\"<slug>\"}, fetch_skill,\nor gooseworks fetch <slug>. Inspect the selected connection's advertised schemas first.\n\n| Scene or operation | Specialist to fetch | How it fits custom production |\n| --- | --- | --- |\n| Evidence-backed hook, script or script rewrite | [[composes::write-video-ad-script]] | Supply the actual custom scene/tool plan and brand evidence in place of a fixed template recipe. Keep the harness script review and lock. |\n| Generated creator saying an exact script across takes | [[composes::create-creator-takes-h3]] | Plan on line boundaries, preserve approved face/room/dialogue, review the first take alone and carry its native voice to later takes. |\n| Real product footage, screen recordings or screenshots | [[composes::footage-cutlist]] | Inspect source windows, map each proof shot to its line, review the cut list and render the product layer. |\n| Creator beside, over or between product footage | [[composes::compose-creator-layer]] | Combine the inspected creator track and product layer per beat. Preserve the creator's dialogue as the master audio. |\n| Native multi-cut performance or general generated B-roll | [[composes::create-video-seedance-2-fal]] or [[composes::create-video-fal]] | Choose from the actual supported endpoint/schema and quoted operations; use H3 when a continuous exact-script creator track is the better fit. |\n| Street interview, vox pop or man-on-the-street | [[composes::render-street-interview]] | Run its selector first (see \"Match a named format before going custom\"). Keep its route contract: people in text, one take per interview, 720p first take, local captions, end card and ambience bed. Do not call its one-shot driver or create a second project. |\n| A generated person in any still or as a video reference | [[composes::create-creator-takes-h3]] (scripts/make_character.py) | Follow \"People in generated images\" below. The selected route decides whether a person still is allowed at all. |\n| Grounded product edits or scene stills without a person | [[composes::create-image-fal]] or [[composes::create-image-gpt-image-fal]] | Reuse approved product references. Check preview eligibility and bounded pricing for the exact endpoint. |\n| Separate narrator or voice audition | [[composes::create-vo-elevenlabs]] | Use the host-approved voice and locked copy. Do not add a second narration over native creator speech. |\n| Music bed or song | [[composes::create-music-elevenlabs]] | Include its actual quote in the phase budget; preserve the approved audio strategy and lyric/beat timing. |\n| Branded text cards, graphics or end card | [[composes::goose-graphics]] | Start from a fitting layout/style and real logo. It produces graphics; animation still requires an actual local renderer. |\n| Narration-led zoom/pan on an existing demo | [[composes::video-polish]] | Use its measured zoom targets only with the installed Remotion/transcription capabilities required by this route. |\n| Conventional clip stitching or overlays | [[composes::stitch-videos-ffmpeg]] | Use its local implementation when it fits the edit; the shared harness assembly helper remains available for ordinary concat/mix. |\n| Word timing and final caption treatment | [[composes::caption-burn]] | Inspect the actual transcript against locked copy. Caption only after picture and mix polish, then repeat final review. |\n| Replace a defective silent B-roll window in a UGC master | [[composes::ugc-fixloop]] | Keep the original continuous dialogue; this repair does not fix a talking shot's lips or voice. |\n| Complete-video observation and finished-ad checks | [[composes::watch]] and [[composes::review-finished-ad]] | Supply real frames/audio, brand assets and timestamps. Their results support the shared final QC; they do not grant approval. |\n\nFor format-specific motion, chat, podcast, street-interview, product or music layouts, search the catalog for\nthe matching render-* capability and inspect its config and inputs. Reuse a compatible\nrenderer or phase implementation without changing the custom project into a fixed template.\nDo not call a template's one-shot driver, create a second project, or replace the shared\nproduction sequence just to use one of its helpers. The table is a starting map, not an\nexhaustive catalog or a promise that every published skill is executable on this connection.\n\n## People in generated images\n\nApply this whenever a generated image or video shows a person: creator, presenter, interviewee or any face in focus. Customers reject smooth, airbrushed, AI-looking people and blurred backgrounds.\n\n- The selected route decides first. When it forbids person references (every render-street-interview route), describe people in the video prompt and make no person stills. When it requires a person reference, make it with the builder that route prescribes. The ugc-street-testimonial recipe prescribes its own creator still.\n- Otherwise, every generated person comes from create-creator-takes-h3's scripts/make_character.py. Fetch create-creator-takes-h3 and create-image-fal together, because the builder calls create-image-fal's gen_image.py. Pass the customer's six choices (age, gender, ethnicity, hair, wardrobe and scene) and keep its defaults: fal-ai/nano-banana-pro, 4K, phone capture with deep focus, head and upper chest, face filling 45 to 55 percent. Run it with --dry-run --payload-out <file> first: the file holds {model, body}, the exact request. Quote that body through data_post_provider with path set to its model and query:{quote_only:true}, as in \"Saved review schema\". Once the still is approved and quoted, run make_character.py again without --dry-run and with GW_PROJECT_ID set to this project, so the same body goes through the managed proxy.\n- Never hand-write a person prompt, fill the generic avatar template by hand, or use fal-ai/flux/dev, fal-ai/flux/schnell or another Flux route for a face. A hand-written generic prompt is not a substitute for the builder. If the builder's request cannot be quoted, report a pricing blocker.\n- Never send a generated photoreal person still as a reference image to bytedance/seedance-2.0/reference-to-video; its likeness gate refuses uploaded images of people. For an exact-script creator from an approved still, use create-creator-takes-h3's takes.\n- Before showing ingredients, crop each face, enlarge it 2× and look. Fix it or report it when skin is waxy or glossy, pores are missing, the background is blurred or bokeh, hands or lettering are garbled, or the face is under about 300 px tall. Show the customer only stills that pass.\n\n## Bind and retain the selected specialists\n\nA fetched package proves that instructions exist; it does not prove that its provider,\npricing, dependencies or local renderer are available. Check each selected route before\nspending. Materialize all returned scripts, files and dependency packages in separate,\nrun-specific package folders, preserving relative paths and rejecting paths outside the\npackage. Do not save several skills into one scripts folder: helpers with the same filename\nwould overwrite each other. Read the installed media-proxy dependency before running any\npaid helper. Every paid submit must propagate this project's project_id / GW_PROJECT_ID\nthrough the managed transport on the selected connection and pass the normal quote and\napproval checks. A helper that cannot carry that context is unavailable for paid custom work.\nNever run its direct-key path or substitute a guessed endpoint or price.\n\nUse specialist craft and executable helpers inside the corresponding shared phase. This\nadapter's project state, supported providers, authenticated script/ingredient gates and\nbudget override a specialist's legacy setup, dollar estimate or standalone approval flow.\nCaptions remain last even if a renderer normally burns them earlier: choose its uncaptioned\noutput or use another compatible implementation. Verify the returned scripts implement any\nrequested setting; prose alone is not an executable capability.\n\nFor H3, the creator still is a script-approved image preview, while the first native-speaking\ntake is a video and requires ingredient approval and its quoted budget. Review that take's\nvoice before the remaining takes; do not spend on it as an image/voice audition. Native H3\nspeech is not a selected ElevenLabs voice: do not invent a voice_id or replace its audio with\nseparate TTS. Save the actual audio strategy and take/reference provenance in extra draft\nfields. Use selected voice roles and playable auditions when the route actually uses them.\n\nSave a compact script_drafts.capability_plan with each selected operation's purpose,\nscene numbers (or \"final\"), skill_slug, version, content_hash, package_path, dependency\nidentities, inputs, expected outputs and supported execution route. Keep full packages in the\nrun's durable workspace, outside the 256 KB review payload. On resume, reuse the recorded\npackages and existing jobs; do not silently fetch latest over an approved run. A missing\npackage must be restored, and a changed route/model/input must be quoted and reviewed through\nthe affected custom gate before spending. If a required capability is unavailable, record\nthe limitation and propose a supported revision instead of improvising a bypass.\n\n## Carry the sourced brief and verify the handoff\n\nBefore script writing, save the writer's documented creative-brief.json from the current brand/product evidence (the Brain search's evidence brief: cited findings, the state of each query and open gaps) and project directions. Include exact product/variant, buyer situation, supported mechanism/claims, offer/CTA, constraints, delivery intent, locked copy, applicable prior decisions and explicit unknowns with source references. Before using the writer, run its free python3 <saved-writer-package>/scripts/verify_handoff.py --package-dir <saved-writer-package> --out working/script/writer-handoff-check.json check against the actual fetched prepare/lint scripts and retain the result and script hashes. A missing checker, failed check or unsupported --brief command blocks the required writer route before saving or approving a new plan; keep any chat proposal unsaved and unapproved until the compatible package is available on this same connection. Do not remove the brief, strict check or requires_creative_brief requirement to run an older parser. Use the fetched write-video-ad-script preparation command with --brief working/script/creative-brief.json and its documented bank/brand/product/template arguments; set the new shape.requires_creative_brief to true. The writer and critic consume that same angle-context. Save only the concise brief/revision and workspace reference in script_drafts extra fields, never full research/package contents. A missing required brief fails the script check; do not rerun known research or rewrite user-locked wording silently.\n\nRead references/specialist-handoff.md from the saved shared harness. For each selected UGC, product/demo or motion operation, extend the existing script_drafts.capability_plan entry with the exact approved brief/script revisions, mapped scene/beat numbers and timing, selected product/reference/source IDs and excerpt ranges, audio/performance choice, package/version/hash and expected returned artifact roles. These are existing extra draft/project artifacts, not new API parameters. Preserve the distinction between numeric script_drafts.scenes[].scene and string production scene IDs.\n\nCheck the actual returned package before executing: H3 plan_takes uses beats id/start/end/vo and character image/identity/environment/delivery; footage-cutlist uses sources and per-beat source/in/out/fit/why; goose-graphics returns static composition/PNG and still needs an actual motion renderer. Do not replace an unsupported helper with a guessed tool name. Preflight the real binary/import/browser and a free dry run, not just its presence. Existing-file skip behavior is not validity: probe saved media and verify fingerprints/approval/job results first, then reuse approved media on resume without new generation.\n\nValidate returned media and provenance against the handoff before clip checks/assembly: exact scene/source revision, words/product/variant, visible proof, measured duration/ratio, selected voice/native speech and neighboring continuity. All speech requires actual isolated performance listening and full mixed-output listening; transcript/word timing only supports that judgment. Audition representative unresolved material and reuse valid approved takes. No mandatory faster delivery or louder climax.\n\n## Hook changes and editorial review\n\nRead references/hook-compatibility.md and references/editorial-review.md from this run's saved harness. Resolve the exact watched source/render and classify same-promise hook versus a new promise requiring different body/proof/payoff. Every changed opening gets new image/action/audio/text review, including visual-only restyles with unchanged words. Shortlist cheap ideas before media spend; keep a broader recut distinct from an isolated opening test.\n\nFor an isolated hook replacement, fetch the existing render-hook-replacement package and inspect its real preflight/config contract. A not-found/empty catalog response blocks that route before paid generation; an open source change is not proof of served availability. Preserve source/body/ending using its own verification, then play/listen to the complete candidates and register each separately. Recommendations are creative judgments, never unmeasured performance winners.\n\nRun rough/fine/final review questions through the current Studio surfaces. First save what the actual cut communicates, then compare with the brief; concept review has no watched-cut verdict. Route unsupported promise to script/concept, missing proof to production, sequence problems to edit and local defects to repair. Unavailable required playback/listening is incomplete and cannot become quality_status passed.\n\nKeep exact feedback text/source/time, intended effect and acceptance condition. Consolidate duplicate notes and record conflicting intentions plus the authorized owner's decision. Preserve changed versus verified dispositions in existing feedback/production metadata or linked project artifacts; executing a fix does not resolve it. Invalidate only affected script/assets/timings/captions/mix/approvals/derivatives, retain valid unrelated work, and rewatch each actual delivered file. Preserve editable timeline, stems, caption sources, selected/candidate versions, rejected options with reasons and scoped pronunciation/delivery history for the next run. Approval and model scores are not audience performance.\n\n## GooseWorks capability binding\n\nRead capabilities.md to bind shared instructions. GooseWorks is authoritative for project state and approvals; local working artifacts grant no spending permission.\n\n- Brand facts and product assets: brand_get_context plus the saved brief/reference analysis.\n- Durable state, concept/design/script/scene/continuity records and feedback: video_project_read and video_project_upsert. Save shared artifact roles in script_drafts extra fields and production metadata; translate spoken lines, captions and scenes into the review schema below.\n- Human gates: discuss free creative choices in chat. Persist concept/design/script before authenticated script approval. Selected storyboard, playable voice auditions, characters, worlds and end card become actual ingredients. Stop for authenticated ingredient approval before any paid clip or preview video. Record the customer's explicit chat approval through patch.approve with the current phase, review token and cumulative budget; a reply alone, local artifact or shared auto mode does not record approval. A handed-off coworker cannot approve its own work. Changes require renewed approval.\n- Provider access, bounded pricing and spend: managed fal/ElevenLabs tools and currently supported endpoints only. Do not switch to direct provider keys, Higgsfield or an unpriced fallback. A missing capability blocks its state until a supported equivalent is reviewed and quoted.\n- Storage: media_upload and media_confirm with exact project ownership; use durable previews in ingredients.\n- Assembly, probes, frame extraction, transcript comparison and continuous inspection: shared package scripts, FFmpeg/FFprobe/Python and available media review tools. A thumbnail or text description cannot satisfy video review.\n- Render attempts, QC, history and promotion: video_render_run and video_project_upsert using the backend contract below. Shared QC still applies; the backend checklist is a minimum.\n\nGrowth and connected coding agents supply local execution. A terminal-free MCP client can prepare/review with connected tools, but must stop or continue through the project's Growth session when required local capabilities are absent. Never claim a render ran without execution.\n\n## Start and resume\n\nAfter the connected tool contract passes the checks above, for a new brief call video_project_upsert with brand_id, name, format:\"custom\", custom_mode:\"generate\", brief:{prompt, audience, objective, product_name, cta, ratio, duration_seconds}, optional reference_url and a stable idempotency_key. Use only brief fields present in the schema. Instagram references have a metered public-data lookup; direct files are downloaded, probed and stored. generated_video_url and media_id mean finished-file imports, never references. Do not use import mode to bypass a generation project's review gates.\n\nRead video_project_read on every resume. When it returns remix.direction for this generated custom project, use remix.direction.implementation as the production starting point: keep the pipeline, full prompts and guards, timings, assembly settings and fixes. Watch the reference. Rewrite all spoken lines and bind products, claims, images and CTA to the target brand. Stay on this same custom project; obtain fresh approvals for its own script/ingredients and budget before any paid call. A source approval or source voice recording never authorizes this new run.\n\nRead video_project_read on every resume. Its project and custom_review are authoritative. Growth creates and retains origin_session_id from trusted chat context. Show the saved review in this conversation and record the customer's explicit approval through the authenticated customer-facing connection as described below. Studio remains available when the customer wants it; never require Chrome to approve. Continue in Growth resumes the bound conversation. A handed-off production coworker prepares the review, ends its turn and waits for the customer-facing connection to record approval before it resumes the same project.\n\nIf reference preparation failed, explain custom_review.reference.error. Continue from the brief if requested, or retry with patch:{retry_reference:true}. A live preparation claim is protected for twenty minutes; after interruption an explicit retry reuses a saved resolved URL when possible. Never invent a reference analysis when no reference was viewed.\n\n## Saved review schema\n\nSave through video_project_upsert {brand_id,project_id,patch:{script:{script_drafts,script,expected_plan_revision}}}. script_drafts contains format:\"custom\", title, duration_target_sec (<=180), aspect_ratio, scenes:[{scene:1,time:\"0–5s\",text,caption,direction}], preview_estimate:{total_credits,basis,operations:[\"Describe each priced operation as a string\"]}, optional render_estimate in the same shape, voices:{narrator:{voice_id,name}} and ingredients:[{container,label,subtitle,url,text,note,pending}]. script_drafts.scenes[].scene is a positive integer such as 1; production scene IDs use the separate string shape described below. The plain script is joined spoken copy. Read project.plan_revision and pass it as expected_plan_revision on every existing-draft save; a stale write is refused. Store concept, reference_analysis, continuity, planned operations and job/asset provenance as extra draft fields; keep the review set under 256 KB.\n\nEach estimate requires total_credits (a nonnegative number, at most 3,000), basis (a nonempty string) and operations (1–100 nonempty strings, each at most 500 characters). Do not put operation objects in either estimate. Keep detailed model/settings/cost rows in a separate extra field such as planned_operations. voices is an optional object keyed by role, never an array; each selected role is {voice_id, name?}. Keep unselected audition candidates in a separate extra field. Copy actual catalog voice IDs into the selected roles; every selected role later needs a matching playable voice ingredient.\n\nFor example, a narrator selection is voices:{narrator:{voice_id:\"<actual catalog ID>\",name:\"<catalog name>\"}}. A preview estimate is preview_estimate:{total_credits:100,basis:\"One presenter image and two voice auditions\",operations:[\"Presenter image: fixed-price supported model\",\"Two voice auditions: the saved script\"]}. These values illustrate the shape; quote the actual supported operations for the run.\n\nBefore saving either preview_estimate or render_estimate, quote each remaining paid media operation through data_post_provider with its exact supported path, body and project_id plus query:{quote_only:true}. Before sending this flag, read a fresh data_post_provider tool description from the selected connection. It must explicitly advertise query:{quote_only:true}, maximum_credits and no generation, reservation or debit. Alternatively, require explicit environment-owner evidence that this same selected app-MCP runtime has deployed free quote support. An extensible query schema or a newer fetched skill is not evidence. If the description is old and no verified runtime evidence exists, stop before the call and request the backend rollout and connector refresh; an older server can treat this flag as a paid generation request. The quote requires no approval and generates no media. This mode is MCP-only; do not send quote_only to an HTTP generation proxy.\n\n```json\n{\n \"provider\": \"fal\",\n \"path\": \"fal-ai/kling-video/v3/standard/image-to-video\",\n \"body\": {\n \"image_url\": \"https://example.com/approved-anchor.png\",\n \"duration\": \"5\",\n \"generate_audio\": false\n },\n \"project_id\": \"<this project ID>\",\n \"query\": {\n \"quote_only\": true\n }\n}\n```\n\nRequire quote_only:true, a finite positive maximum_credits and cost.credits:0 in the result. If the server returns a job, audio, a charge or any non-quote result, stop and report the tool/runtime mismatch; never retry it as a quote. Unknown or unbounded prices block planning. Do not substitute public unit prices or guessed billed discounts for maximum_credits: the custom reservation includes conservative quantity, size, audio and preset bounds, while actual settlement can be lower.\n\nSum maximum_credits for all remaining operations in the phase into that estimate's total_credits, including every concurrently planned job. Keep local free assembly/QC operations at zero. The approved project cap includes custom_review.committed_credits plus the remaining quoted estimate; committed includes both settled spend and outstanding reservations. Read the current review again before approval, avoid counting an already reserved job twice, and quote any changed model/body before seeking revised approval. Quotes are not approval tokens or locked prices; real submission rechecks its current conservative bound and the approved budget.\n\nBefore script approval, only plan/save free text. preview_estimate quotes future storyboard images and voice auditions. custom_review.script_approved permits priced image previews on supported fal image endpoints and ElevenLabs text-to-speech auditions. Unknown endpoints require ingredient approval. Use catalog voice previews when possible; do not silently select a paid model outside the preview allowlist.\n\nUpload actual previews with media_upload/media_confirm. Put public/durable URLs on image/avatar/background/endcard/voice/audio/video ingredients. Text containers can carry inline text; a voice or image description cannot replace its preview. Save a render_estimate for remaining clips/assembly and show the complete ingredients. Stop until custom_review.ingredients_approved. Script and ingredient tokens are independent; do not infer approval from project.status.\n\n## Record each approval in this chat\n\nThere are two independent gates. Script approval permits the quoted image/voice previews. Ingredient approval permits the quoted clips and finishing work after the actual review set is ready. Keep both gates even when the customer prefers chat to Studio.\n\n1. Read video_project_read. Show the current saved script or actual playable ingredients, the changes since any previous approval and the cumulative credit limit in custom_review.approval_quote. Explain that the limit includes custom_review.committed_credits plus the remaining quoted operations. An old estimate, approval from a previous revision or remaining-only amount is not the current budget.\n2. Ask for the customer's explicit approval of that phase and amount in this conversation. Copy their actual words as user_quote; never invent consent or interpret a pricing-error complaint as approval of a changed creative plan or larger budget.\n3. Read video_project_read again before recording the yes. Require the same review token, phase and total shown to the customer. If any changed, show the changed review and ask for approval of it; never silently attach the earlier yes to a newer token or amount.\n4. Through the authenticated customer-facing connection call video_project_upsert {brand_id,project_id,patch:{approve:{user_quote:\"<the customer's actual words>\",phase:custom_review.approval_quote.phase,review_token:custom_review.approval_quote.review_token,total_credits:custom_review.approval_quote.total_credits}}}. This is the custom contract; template approvals without phase and review_token cannot authorize custom production. Do not combine this approval with a script edit.\n5. Read back custom_review. For phase:\"script\", require script_approved:true and the matching script_token. For phase:\"ingredients\", require ingredients_approved:true and the matching ingredient_token. Check the approved max_credits covers the current cumulative total before dispatch. A tool error or merely sending patch.approve is not approval.\n\nThe approval_quote.phase is \"script\" or \"ingredients\". Its review_token is the matching custom_review.script_token or custom_review.ingredient_token from that saved snapshot. If approval_quote is missing or the requested phase's review is not ready, finish the free preparation or resolve the returned blocker; never guess a token, reuse the other phase's token or change the budget to force approval.\n\nOnly the authenticated customer-facing connection can record the customer's approval. A handed-off coworker with a production task prepares and displays the review, ends its turn, and waits. It cannot call patch.approve to approve its own work, forward a fabricated user_quote or treat the original brief as approval. After the customer-facing connection records and verifies approval, resume that same task/project with goose_run_task when required. Studio can record the same authenticated approvals if the customer chooses it; do not require Chrome, browser unlocks or Studio access just to approve in chat.\n\n## Paid execution and resume\n\nEvery managed media call carries project_id (GW_PROJECT_ID in scripts) and a stable input fingerprint. Use the managed fal/ElevenLabs endpoints and credentials supplied by Growth; never request customer provider keys. Do not expose those credentials in logs. Recheck custom_review before dispatch. The backend reserves estimated outstanding costs atomically, enforces the approved total (maximum 3,000 credits) and prevents duplicate submissions. At most a 20% overrun can be newly approved; this is not automatic permission to spend above the customer's selected limit. A custom video's budget grows only through a renewed approval. On SPEND_CAP_REACHED the open render is asked to stop: report it \"stopped\" with what was kept (see \"Render run states\") and tell the customer what was made and spent. Then save a revised estimate, show the new custom_review.approval_quote with its current total, record the customer's approval of that total, and open a new render that reuses the saved pieces.\n\nPreview eligibility and price support are separate checks. Use an exact endpoint permitted by the backend preview policy and confirm its current request schema and server quote. Model discovery and provider pricing can change: use the selected connection's actual quote, including supported provider estimates, instead of a skill-maintained priced-model list. A model-family name does not make every route eligible for script previews. Do not move a preview to another phase to bypass its approval gate. If pricing cannot be established, keep the saved request and report a system pricing blocker; do not ask the customer to choose when their choices are already approved. Final clip models require ingredient approval. Existing-job polls remain permitted after edits; retrieval does not authorize new media.\n\nSave provider request IDs and actual uploaded URLs promptly. Custom operations with known rejection can retry safely; ambiguous timeouts keep their authorization until reconciled. Media spend is metered through the shared gateway. Custom videos have no extra template base render fee. Imported finished files still file for zero credits.\n\n## Clips, assembly and quality\n\nUse the selected packages in script_drafts.capability_plan for each scene and operation. Recheck specialist discovery for new requirements or repairs before improvising a helper. Keep anchors and exact lines fixed. Use the Python assembly helper returned in the shared harness scripts for actual existing clips. It needs only Python, FFmpeg and FFprobe; it does not call a provider or require Chromium. Inspect generated clips before assembly, and watch the final export after assembly/captions.\n\nOpen a render with video_render_run {brand_id,project_id,kind:\"full\"}; executor:\"cloud_agent\" for Growth when exposed by the current schema. Report live workflow_stage/progress_note/progress_percent while producing it. Upload the final file to scope:\"video_project\", scope_id:project_id. The tool opens/reports a client-executed render; fixed server orders remain paused.\n\n### Render run states\n\nReport the open render's state with video_render_run {brand_id,project_id,render:{render_id,...}}. Use the row that matches:\n\n| Situation | status | workflow_stage | quality_status | Also send |\n| --- | --- | --- | --- | --- |\n| Producing, checking or repairing | \"running\" | preparing, rendering, checking, repairing or rechecking | \"pending\" | progress_note, progress_percent, steps |\n| Waiting for the customer: they must approve a candidate, choose or give feedback, with or without an uploaded candidate | \"running\" | \"blocked\" | \"blocked\" | output_url when an uploaded candidate exists, error_message saying in plain words what you need from them, and choices (at most 4 buttons; put credits on any paid choice). A quality_report is optional while waiting; when sent, it carries the current findings |\n| Stop requested: a progress callback returned stop:true because the customer stopped the video or a paid step hit the spending limit | \"stopped\" | omit | omit | progress_note saying in plain words what was kept. Start no new paid step; let a call already running finish. |\n| Real failure: no usable candidate can be produced (provider refusal with no approved alternative, or a system blocker you cannot recover) | \"failed\" | omit (the server sets blocked) | \"blocked\" | error_message in plain words |\n| Done | \"complete\" | omit (the server sets ready) | \"passed\" | output_url and the full quality_report, only after the final recipe is saved and read back as described below |\n\nWaiting for the customer is not a failure, and neither is a stop. Never report \"failed\" because you are waiting for approval, a choice or feedback, or because the customer or the spending limit stopped the video. When stop:true comes with stop_reason \"superseded\", report nothing further on that render. The app shows a waiting render's candidate as \"Needs your approval\" and keeps it for up to 14 days; after that the server ends it as failed with failure_code review_expired. The uploaded file stays in the project either way.\n\nA waiting state is valid only while the approval it rests on is current. A render can complete only under the approval it was opened with. After any script or ingredient edit (yours or the customer's), or after review_expired, the old render cannot be completed: read video_project_read {brand_id,project_id,include:[\"assets\",\"renders\"]}, show the changed review and the current custom_review.approval_quote in chat, record the customer's approval of each phase it asks for, then open a new render. Opening a new render stops the older open render of this video with stop_reason \"superseded\" (\"Replaced by a newer version.\"). Report nothing more on a superseded render and start no paid step for it; continue on the new one. To deliver an unchanged candidate on the new render, follow \"Finalize an existing candidate after re-approval\" below.\n\nWhen the customer approves a waiting candidate and nothing in the review changed, finish the shared final review and complete that same render; a candidate needs no separate approval phase. When they ask for changes, save the feedback and follow the normal edit and approval gates.\n\nOn resume, treat a render left at \"running\" with workflow_stage \"blocked\" as a pending customer decision. Read custom_review and custom_review.feedback before doing anything else. If your own render shows stop_reason \"superseded\", another run replaced it: read video_project_read {brand_id,project_id,include:[\"assets\",\"renders\"]} and continue on the newer render; do not open another one just to resume.\n\nAfter each accepted generation or deterministic edit, update patch.production with the steps and settings that actually ran. Save and read back the actual candidate recipe before showing its preview or pausing for review, so an interrupted or waiting run does not leave only an early plan in the backend. Partial progress is allowed; pending creative approval or QC must stay explicit and must never be converted into passing clip evidence.\n\nBefore completing or pinning a candidate, replace the early planning manifest with the actual production recipe. Record every current script scene using its string scene number, exact current spoken line, measured duration and full generation prompts or deterministic rendering instructions. Record the actual pipeline/model settings, assembly/captions/audio settings, and repairs in fixes. Never leave blocked/pending planning statuses in a completed recipe. Preserve full prompts and guards; do not reduce them to summaries. Save partial progress while working, but an unfinished recipe is not a reusable final.\n\nSave the final recipe through patch.production, then read video_project_read and compare production_manifest with what you just saved, including all scene IDs and spoken lines. If the save fails or the read-back is stale/incomplete, repair it before completion; do not describe the run as finished or remixable. Final completion freezes the actual recipe and reviewed script together for the next agent.\n\nSave patch.production as a production manifest with version:1 and a nonempty pipeline array. Each pipeline item requires step and model; purpose and settings are optional. production.characters is an optional array, never a record/object: each entry requires both name and prompt strings. Store anchor media IDs, URLs, actual appearance and other extra provenance in script_drafts; character entries accept name and the full design prompt.\n\nproduction.scenes[].id is a string containing the corresponding script scene number, for example \"1\". script_drafts.scenes[].scene and production.clips[].scene remain positive integers, for example 1. Map production scene IDs with String(scriptScene.scene); do not convert clip.scene or script scene IDs to strings. Each scene can also carry line, still_prompt, motion_prompt, duration_s and notes. style is an object; voice and music are objects when present; assembly is an object; fixes is an array of {problem,fix}.\n\nEach clip requires a numeric scene, a stored URL and exactly one of each named check: visual_artifacts, brand, product, voice_and_script, duration_and_ratio. Each clip check is {check,status:\"pass\"|\"fail\",note?}; not_applicable is not valid for clip checks. Save exactly one checked clip per approved script scene before final completion, with every check passing. Before clips exist, omit clips from an ingredient-preparation save.\n\nThe following is a one-scene JSON shape example. Replace all placeholders with actual saved values. Its failed QC statuses are deliberately unapproved; never copy a passing status without performing the shared review.\n\n```json\n{\n \"patch\": {\n \"production\": {\n \"version\": 1,\n \"pipeline\": [\n {\n \"step\": \"Scene clips\",\n \"model\": \"<actual supported model>\",\n \"settings\": {}\n }\n ],\n \"style\": {\n \"prompt\": \"<shared visual direction>\",\n \"negative\": \"<shared guards>\"\n },\n \"characters\": [\n {\n \"name\": \"Presenter\",\n \"prompt\": \"<exact full character design prompt>\"\n }\n ],\n \"scenes\": [\n {\n \"id\": \"1\",\n \"line\": \"<approved spoken line>\",\n \"still_prompt\": \"<exact full still prompt>\",\n \"motion_prompt\": \"<exact full motion prompt and guards>\",\n \"duration_s\": 5\n }\n ],\n \"voice\": {\n \"voice_id\": \"<selected catalog voice ID>\",\n \"name\": \"<selected voice name>\",\n \"model\": \"<actual voice model>\",\n \"settings\": {}\n },\n \"assembly\": {\n \"ratio\": \"9:16\",\n \"fps\": 30\n },\n \"fixes\": [],\n \"clips\": [\n {\n \"scene\": 1,\n \"url\": \"https://example.com/confirmed-scene-1.mp4\",\n \"checks\": [\n {\n \"check\": \"visual_artifacts\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"brand\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"product\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"voice_and_script\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"duration_and_ratio\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n }\n ]\n }\n ]\n }\n }\n}\n```\n\nComplete with video_render_run {brand_id,project_id,render:{render_id,status:\"complete\",output_url,quality_status:\"passed\",quality_report:{version:1,summary,checks:{source,brand,product,hook_and_scene_order,voice_and_script,captions,endcard_and_cta,duration_and_ratio,visual_artifacts},detected_issues:[],repair_actions:[],checked_at}}}. Each final check is {status:\"pass\"|\"fail\"|\"not_applicable\",note}; brand/product/scene order/duration/visual artifacts must pass. A candidate that fails QC is never complete: keep it \"running\" with workflow_stage \"repairing\" while you fix it, report the waiting state above when the customer must decide, and use \"failed\" only for a real failure. Final completion binds approval revisions, output and quality evidence to the render; pin with patch.final_render_id only after passing.\n\nAll nine named final checks above are required, including source, voice_and_script, captions and endcard_and_cta when they are not applicable. A final check uses status:\"pass\"|\"fail\"|\"not_applicable\" and an optional note. The five mandatory passing checks are brand, product, hook_and_scene_order, duration_and_ratio and visual_artifacts; no final check may fail and detected_issues must be empty to complete. Record why a permitted check is not_applicable. Keep actual repair_actions and use the actual ISO 8601 checked_at time. The backend report is a minimum; it does not replace the full shared watch, claim verification or craft review.\n\nThis waiting-for-the-customer report illustrates every required field. Replace the URL, reason, choices, findings and example timestamp with actual evidence. Only after repairs and the shared final review pass may the render be reported complete with quality_status:\"passed\", its confirmed output_url and no unresolved issues.\n\n```json\n{\n \"render\": {\n \"render_id\": \"<existing render ID>\",\n \"status\": \"running\",\n \"workflow_stage\": \"blocked\",\n \"quality_status\": \"blocked\",\n \"output_url\": \"https://example.com/confirmed-candidate-in-this-project.mp4\",\n \"error_message\": \"<what you need from the customer, in plain words>\",\n \"choices\": [\n {\n \"label\": \"Approve this version\",\n \"message\": \"I approve this version\"\n },\n {\n \"label\": \"Change something\",\n \"message\": \"I want to change something in this version\"\n }\n ],\n \"quality_report\": {\n \"version\": 1,\n \"summary\": \"<actual full-video review summary>\",\n \"checks\": {\n \"source\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"brand\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"product\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"hook_and_scene_order\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"voice_and_script\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"captions\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"endcard_and_cta\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"duration_and_ratio\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"visual_artifacts\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n }\n },\n \"detected_issues\": [\n \"<actual unresolved issue>\"\n ],\n \"repair_actions\": [],\n \"checked_at\": \"2026-10-03T00:00:00Z\"\n }\n }\n}\n```\n\n### Finalize an existing candidate after re-approval\n\nUse this when an uploaded candidate (a confirmed video in this project) already shows and says exactly what the current script says, but its render can no longer complete: the script was amended to match the take, or the wait ended as review_expired. If any spoken line, caption, scene or ingredient differs from the current script, this route does not apply: repair or regenerate under the normal gates.\n\n1. If the script changed, save it and record the customer's script approval first, as in \"Record each approval in this chat\". Then save the candidate as a video ingredient (its confirmed URL) in the review set, show the candidate and the current custom_review.approval_quote in chat, and record the ingredient approval. The earlier render was approved against the old review, and the server will not complete it.\n2. Open a new render with video_render_run {brand_id,project_id,kind:\"full\"}. Start no provider call. The older waiting render stops as superseded.\n3. Run the shared final review on the existing file against the current script. voice_and_script and captions must match the current lines.\n4. Save and read back the final production recipe with the current lines and one checked clip per scene, as described in \"Clips, assembly and quality\". Reuse the clip records from the candidate's saved recipe, updated to the current lines.\n5. Complete the new render with status:\"complete\", output_url set to the existing candidate's confirmed URL, quality_status:\"passed\" and the full quality_report. Do not regenerate or re-upload. No credits are spent.\n6. Pin it with video_project_upsert patch.final_render_id (alias set_final_render).\n\n## Feedback and delivery\n\nSave customer script/ingredient/video feedback through the connected project tools before continuation; affected creative edits invalidate their approvals. Read custom_review.feedback on every turn, preserving the original watched render/time and text when provided. A selected final change never relocates an earlier note. Resolve only after the candidate satisfies the original intended effect and full-output recheck; keep incomplete or conflicting notes open. Replace only the affected assets; save revised estimates and show the changed review and cumulative budget in the same chat before recording renewed approval. Deliver the playable current_render_url with render_artifact kind:\"video\" in Growth and actual project spend. Include the Studio app_url when a text host or the customer needs it; do not require it for approval. Keep final history; never create another project just because an agent restarted.\n\n## Reviewed snapshot, voices and supported pricing\n\ncustom_review returns script_drafts and plan_revision from the same saved snapshot as its tokens. Show that snapshot in chat; Studio can also render it. Use the revision for edits and the current approval_quote for each approval. Spoken copy (text) and on-screen copy (caption) are separate fields. Voice audition ingredients carry role and voice_id; script_drafts.voices maps each role to its selected voice_id/name. Every selected role needs an actual matching playable preview before approval.\n\nA pending/processing/failed reference blocks script approval. If the customer explicitly chooses to continue from the brief without the reference, save that choice through the connected reference-review tool when exposed, or offer Studio's Continue from brief action when needed. This is a reference decision, not a requirement to approve in Chrome. Do not silently replace a requested reference with brief-only production.\n\nCustom provider submits require a positive server quote, including quantity, supported dimensions/audio and any provider estimate. The server must establish source duration for audio/video-driven routes from authorized media metadata or a bounded probe; do not add invented duration fields to the provider body to force a quote. A provider estimate permits production within the approved budget even when exact final billing is unavailable. Missing source duration or an unavailable provider estimate is a system blocker to resolve on the saved project, not a model allowlist or a new creative choice. A conservative reservation is released to actual charged spend when the provider result settles. Final output must be a confirmed, stored video_asset in this exact organization/project, and completion binds its media_id to the render. External hotlinks cannot be pinned as generated custom finals. The portable helper checks FFmpeg's libass capability before local captions, rejects clips shorter than their timeline and validates video-stream duration.\n";
5
+ exports.CUSTOM_VIDEO_ADAPTER_CONTENT = "---\nname: make-custom-video\nslug: make-custom-video\ndescription: Connect the shared video production harness to GooseWorks projects, script and ingredient approvals, managed media generation, budgets and final delivery. Use for original briefs, Instagram/video references and resumed custom projects.\ncategory: ads\nversion: 2.3.2\nauthor: GooseWorks\nrequires_skills: [video-production-harness]\nharness_binding: gooseworks/v2\n---\n\n# Human version\n\nThis adapter connects the production playbook and specialist skill catalog to GooseWorks. It matches each scene to existing creator, footage, graphics, audio and review tools. Customers review and approve their script, actual ingredients and budget in the same chat. Studio is an optional review surface. The agent saves the checked final video to the same project.\n\n---\n\n# Agent version\n\n## Make Custom Video\n\nThe generic production phases run in the Growth sandbox or a connected agent with a shell. GooseWorks owns the project, approvals, budget, uploads and final selection. This adapter replaces Studio desktop files and Tauri approval events with the product contract below.\n\n## Execution preflight\n\nA connected agent with a working shell executes this custom project locally. Declare client:{shell:true} on every video/format/catalog request that accepts it, including video_project_read. Each call can reach a different server process; a previous capability report does not carry over reliably. Missing libass does not remove shell capability: fetch [[composes::caption-burn]], which uses Pillow and FFmpeg overlay. Fetch every selected specialist and the invoked harness step files before declaring a route unavailable.\n\nFor MCP-owned runs set GW_MEDIA_VIA=mcp and GW_PROJECT_ID before running any helper, even if CLI credentials exist. Record the selected account_whoami public API origin as GW_EXPECTED_API_ORIGIN; never open credential files to discover it. Use HTTP only after verifying the matching origin through supported CLI diagnostics. For large MCP relay bodies, use the helper's body_file without retyping: upload that JSON file to this same video project, confirm the returned asset, then call data_post_provider with body_asset_id and omit body when the tool advertises that argument. Its normal project, approval, budget and secret checks still apply. Older connectors must relay the exact saved JSON unchanged.\n\nBefore taking over a delegated project, cancel its delegate task and read back that it is detached. Do not request another approval while a stale delegate remains attached. If cancellation is unsupported, save the blocker; a Stop followed by reapproval can wake the same delegate again.\n\nAfter a paid failure, reconcile the known job and actual charges. Stop after the first identical infrastructure failure; a failed coworker turn can still cost credits. Quotes are estimates, not actual spend. Preserve approved copy while changing cost explanations; show actual cumulative charges from the project ledger.\n\nRun helpers from the run's working directory with explicit absolute input/output paths. For footage, save inspected source in/out bounds and fit:width, including screen.fit:width. A planned creator image may be absent during free take planning; use plan_takes --plan-only instead of generating a placeholder.\n\nThe writer's paid critic cannot run before custom script approval. Perform its rubric locally before script review and save that evidence. Only run an external critic when the host explicitly supports it in the current approved phase and budget; never bypass a spend gate or silently claim an independent critic ran.\n\n## Check the connected tool contract first\n\nInspect the tool parameters exposed by the selected connection before creating or changing a custom project. catalog_fetch returns skill packages, not tool schemas. Use the host's registered tool definitions (MCP tools/list when available); do not assume that fetching a newer skill updates a connector's saved schema.\n\nvideo_project_upsert must expose custom_mode and idempotency_key for creation, reference_url when a reference is requested, and patch.script.expected_plan_revision for review saves. Before approvals, require patch.approve fields user_quote, total_credits, phase and review_token, plus custom_review.approval_quote in video_project_read. Before later writes, check that the connected tool exposes every field required by that action, including production clip checks and final quality evidence. If a required field is missing, stop before project writes or paid calls and report that the connected tools and custom-video skill are out of sync. Keep any proposed script in chat and label it as an unsaved, unapproved proposal. Do not drop required fields, switch environments, import the reference as a finished file, or create an HTML review page to work around the mismatch.\n\nThe environment owner must confirm the app-MCP service rollout and refresh the connector's discovered tool schemas. Resume only when the required parameters are visible on the same selected connection. Review and approval stay in the current chat; the Studio creative page is optional. Custom generation requires separate authenticated script and ingredient approvals with their current review tokens and cumulative budgets. Template skills' one-approval instructions do not replace either custom gate. A missing approval field is a tool rollout mismatch, not a reason to require Chrome.\n\n## Match a named format before going custom\n\nBefore creating a custom project, when the brief changes, and before any paid preview, check whether the request names or implies a catalog format: street interview / vox pop / man-on-the-street, street testimonial, podcast, iMessage or chat, split-screen creator, screen insert, listicle, and so on. Call video_catalog_list {kind:\"formats\", brand_id}, then fetch that format's renderer or recipe skill and run its own selector or checks.\n\nFor a street interview, fetch render-street-interview, read its street-script-writing guide, write a brief JSON with mode, offering_type (physical, service or digital), interaction_type and participants (people interviewed on screen, not counting the interviewer), and run python3 scripts/prepare_script_context.py --brief <brief.json> --out <context.json>. It exits 2 whenever the status is not ready-for-writing. Its route output is binding: route.support (\"render\" or \"preview-only\"), route.person_reference and route.max_participants. A status of unsupported-route lists route_gaps and alternatives; it is a stop, not permission to go custom: show the alternatives and go custom only if the customer picks it.\n\n| Street route | On screen | Person image reference | Status |\n| --- | --- | --- | --- |\n| render-street-interview product-guess (physical product only) | Interviewer and up to four participants in one take | Forbidden: people are written in the prompt; the only reference is a standalone physical product photo | Renders |\n| render-street-interview conversation (mic-only, product-sample, concept-challenge) | Interviewer and one participant | Forbidden: no reference images, no phone, screen or UI | Preview only in this format: script and prompt dry run, no paid render |\n| ugc-street-testimonial format | One person, no interviewer | Required: the creator still that format's recipe prescribes | Template format |\n\nIf the request fits a route, use that format; a fitting template format is not a custom video. If nothing fits, tell the customer in plain words what is supported and what is preview only, and name the closest supported options (the selector's alternatives) and how each differs. Or propose custom and say why. Go custom only when the customer chooses it. A custom video built on a named format still keeps that format's hard constraints. For a street interview, those are:\n\n- people described in text, never as uploaded person photos;\n- one generation per interview take;\n- deep focus;\n- the first take at 720p;\n- every caption and letter drawn locally.\n\nA selector result of needs-reference or unsupported-route, a provisional creative review or an unobserved reference is unresolved. Report it and ask before script approval; never continue past it silently.\n\n## Load the shared production harness first\n\nThis entry contains only the GooseWorks connection. Production sequencing, creative craft, reviews and repair loops are maintained in video-production-harness, published from the existing Studio harness. Do not invent a shorter local workflow.\n\nFor a new run, use the video-production-harness dependency returned by catalog_fetch or fetch_skill. If absent, fetch catalog_fetch {type:\"skill\",slug:\"video-production-harness\"}; CLI users can use gooseworks fetch video-production-harness. Require nonempty content, scripts, files, version and contentHash. Require the returned files references/editorial-review.md, references/specialist-handoff.md and references/hook-compatibility.md as nonempty text too; a coherent older release or version label does not supply missing guides. If unavailable, stop before new creative work, project writes or generation; never fall back to a vendored playbook. An unchanged approved resume keeps its recorded package and approvals.\n\nRead the returned content, orchestrator.md, capabilities.md and every detailed step invoked by the orchestrator. Materialize every returned script and file at its package-relative path in a run-specific video-production-harness folder. scripts are relative to its scripts directory; files are relative to the package root. Reject paths outside the package. Save the exact bundle only in the run's persistent workspace. Store only {slug,version,content_hash,package_path} as script_drafts.harness in the saved project; never inline the package content, files or scripts into the review draft. The review payload must stay below its 256,000-character limit. Keep the saved package in this run's durable folder, not a shared mutable installation.\n\nOn resume, read video_project_read and use the saved package matching script_drafts.harness.content_hash. Do not refetch latest or overwrite this run's package. If the package is missing, stop and restore that version before continuing; fetching today's release does not restore it. New projects load the current catalog release. This is an agent-held saved package, not a server-enforced immutable registry.\n\n## Discover specialists for the actual scenes\n\nCustom means composing available capabilities around the brief. Before the design/tool plan,\nmatch each scene and finishing step to the current skill catalog. Repeat this check when a\nnew requirement or repair appears, before writing a helper or making a provider call. The\nshared harness owns the sequence; specialist skills supply implementations inside its phases.\n\nUse the known routes below as starting points. Fetch the relevant skill, read its instructions\nand failure modes, and inspect its returned scripts/files/dependencies before choosing it.\nFor an unmatched need, use the advertised catalog_search {type:\"skill\",query:\"<capability>\"},\nor search_skills on a connection exposing that alias; CLI: gooseworks search \"<capability>\".\nUse short separate queries such as \"creator\", \"footage\", \"motion\" or \"captions\": search words\nare ANDed. Do not restrict discovery to category \"ads\"; video helpers also live under\n\"general\" and \"content\". Follow returned pagination when relevant results are not on the\nfirst page. Fetch by returned slug with catalog_fetch {type:\"skill\",slug:\"<slug>\"}, fetch_skill,\nor gooseworks fetch <slug>. Inspect the selected connection's advertised schemas first.\n\n| Scene or operation | Specialist to fetch | How it fits custom production |\n| --- | --- | --- |\n| Evidence-backed hook, script or script rewrite | [[composes::write-video-ad-script]] | Supply the actual custom scene/tool plan and brand evidence in place of a fixed template recipe. Keep the harness script review and lock. |\n| Generated creator saying an exact script across takes | [[composes::create-creator-takes-h3]] | Plan on line boundaries, preserve approved face/room/dialogue, review the first take alone and carry its native voice to later takes. |\n| Real product footage, screen recordings or screenshots | [[composes::footage-cutlist]] | Inspect source windows, map each proof shot to its line, review the cut list and render the product layer. |\n| Creator beside, over or between product footage | [[composes::compose-creator-layer]] | Combine the inspected creator track and product layer per beat. Preserve the creator's dialogue as the master audio. |\n| Native multi-cut performance or general generated B-roll | [[composes::create-video-seedance-2-fal]] or [[composes::create-video-fal]] | Choose from the actual supported endpoint/schema and quoted operations; use H3 when a continuous exact-script creator track is the better fit. |\n| Street interview, vox pop or man-on-the-street | [[composes::render-street-interview]] | Run its selector first (see \"Match a named format before going custom\"). Keep its route contract: people in text, one take per interview, 720p first take, local captions, end card and ambience bed. Do not call its one-shot driver or create a second project. |\n| A generated person in any still or as a video reference | [[composes::create-creator-takes-h3]] (scripts/make_character.py) | Follow \"People in generated images\" below. The selected route decides whether a person still is allowed at all. |\n| Grounded product edits or scene stills without a person | [[composes::create-image-fal]] or [[composes::create-image-gpt-image-fal]] | Reuse approved product references. Check preview eligibility and bounded pricing for the exact endpoint. |\n| Separate narrator or voice audition | [[composes::create-vo-elevenlabs]] | Use the host-approved voice and locked copy. Do not add a second narration over native creator speech. |\n| Music bed or song | [[composes::create-music-elevenlabs]] | Include its actual quote in the phase budget; preserve the approved audio strategy and lyric/beat timing. |\n| Branded text cards, graphics or end card | [[composes::goose-graphics]] | Start from a fitting layout/style and real logo. It produces graphics; animation still requires an actual local renderer. |\n| Narration-led zoom/pan on an existing demo | [[composes::video-polish]] | Use its measured zoom targets only with the installed Remotion/transcription capabilities required by this route. |\n| Conventional clip stitching or overlays | [[composes::stitch-videos-ffmpeg]] | Use its local implementation when it fits the edit; the shared harness assembly helper remains available for ordinary concat/mix. |\n| Word timing and final caption treatment | [[composes::caption-burn]] | Inspect the actual transcript against locked copy. Caption only after picture and mix polish, then repeat final review. |\n| Replace a defective silent B-roll window in a UGC master | [[composes::ugc-fixloop]] | Keep the original continuous dialogue; this repair does not fix a talking shot's lips or voice. |\n| Complete-video observation and finished-ad checks | [[composes::watch]] and [[composes::review-finished-ad]] | Supply real frames/audio, brand assets and timestamps. Their results support the shared final QC; they do not grant approval. |\n\nFor format-specific motion, chat, podcast, street-interview, product or music layouts, search the catalog for\nthe matching render-* capability and inspect its config and inputs. Reuse a compatible\nrenderer or phase implementation without changing the custom project into a fixed template.\nDo not call a template's one-shot driver, create a second project, or replace the shared\nproduction sequence just to use one of its helpers. The table is a starting map, not an\nexhaustive catalog or a promise that every published skill is executable on this connection.\n\n## People in generated images\n\nApply this whenever a generated image or video shows a person: creator, presenter, interviewee or any face in focus. Customers reject smooth, airbrushed, AI-looking people and blurred backgrounds.\n\n- The selected route decides first. When it forbids person references (every render-street-interview route), describe people in the video prompt and make no person stills. When it requires a person reference, make it with the builder that route prescribes. The ugc-street-testimonial recipe prescribes its own creator still.\n- Otherwise, every generated person comes from create-creator-takes-h3's scripts/make_character.py. Fetch create-creator-takes-h3 and create-image-fal together, because the builder calls create-image-fal's gen_image.py. Pass the customer's six choices (age, gender, ethnicity, hair, wardrobe and scene) and keep its defaults: fal-ai/nano-banana-pro, 4K, phone capture with deep focus, head and upper chest, face filling 45 to 55 percent. Run it with --dry-run --payload-out <file> first: the file holds {model, body}, the exact request. Quote that body through data_post_provider with path set to its model and query:{quote_only:true}, as in \"Saved review schema\". Once the still is approved and quoted, run make_character.py again without --dry-run and with GW_PROJECT_ID set to this project, so the same body goes through the managed proxy.\n- Never hand-write a person prompt, fill the generic avatar template by hand, or use fal-ai/flux/dev, fal-ai/flux/schnell or another Flux route for a face. A hand-written generic prompt is not a substitute for the builder. If the builder's request cannot be quoted, report a pricing blocker.\n- Never send a generated photoreal person still as a reference image to bytedance/seedance-2.0/reference-to-video; its likeness gate refuses uploaded images of people. For an exact-script creator from an approved still, use create-creator-takes-h3's takes.\n- Before showing ingredients, crop each face, enlarge it 2× and look. Fix it or report it when skin is waxy or glossy, pores are missing, the background is blurred or bokeh, hands or lettering are garbled, or the face is under about 300 px tall. Show the customer only stills that pass.\n\n## Bind and retain the selected specialists\n\nA fetched package proves that instructions exist; it does not prove that its provider,\npricing, dependencies or local renderer are available. Check each selected route before\nspending. Materialize all returned scripts, files and dependency packages in separate,\nrun-specific package folders, preserving relative paths and rejecting paths outside the\npackage. Do not save several skills into one scripts folder: helpers with the same filename\nwould overwrite each other. Read the installed media-proxy dependency before running any\npaid helper. Every paid submit must propagate this project's project_id / GW_PROJECT_ID\nthrough the managed transport on the selected connection and pass the normal quote and\napproval checks. A helper that cannot carry that context is unavailable for paid custom work.\nNever run its direct-key path or substitute a guessed endpoint or price.\n\nUse specialist craft and executable helpers inside the corresponding shared phase. This\nadapter's project state, supported providers, authenticated script/ingredient gates and\nbudget override a specialist's legacy setup, dollar estimate or standalone approval flow.\nCaptions remain last even if a renderer normally burns them earlier: choose its uncaptioned\noutput or use another compatible implementation. Verify the returned scripts implement any\nrequested setting; prose alone is not an executable capability.\n\nFor H3, the creator still is a script-approved image preview, while the first native-speaking\ntake is a video and requires ingredient approval and its quoted budget. Review that take's\nvoice before the remaining takes; do not spend on it as an image/voice audition. Native H3\nspeech is not a selected ElevenLabs voice: do not invent a voice_id or replace its audio with\nseparate TTS. Save the actual audio strategy and take/reference provenance in extra draft\nfields. Use selected voice roles and playable auditions when the route actually uses them.\n\nSave a compact script_drafts.capability_plan with each selected operation's purpose,\nscene numbers (or \"final\"), skill_slug, version, content_hash, package_path, dependency\nidentities, inputs, expected outputs and supported execution route. Keep full packages in the\nrun's durable workspace, outside the 256 KB review payload. On resume, reuse the recorded\npackages and existing jobs; do not silently fetch latest over an approved run. A missing\npackage must be restored, and a changed route/model/input must be quoted and reviewed through\nthe affected custom gate before spending. If a required capability is unavailable, record\nthe limitation and propose a supported revision instead of improvising a bypass.\n\n## Carry the sourced brief and verify the handoff\n\nBefore script writing, save the writer's documented creative-brief.json from the current brand/product evidence (the Brain search's evidence brief: cited findings, the state of each query and open gaps) and project directions. Include exact product/variant, buyer situation, supported mechanism/claims, offer/CTA, constraints, delivery intent, locked copy, applicable prior decisions and explicit unknowns with source references. Before using the writer, run its free python3 <saved-writer-package>/scripts/verify_handoff.py --package-dir <saved-writer-package> --out working/script/writer-handoff-check.json check against the actual fetched prepare/lint scripts and retain the result and script hashes. A missing checker, failed check or unsupported --brief command blocks the required writer route before saving or approving a new plan; keep any chat proposal unsaved and unapproved until the compatible package is available on this same connection. Do not remove the brief, strict check or requires_creative_brief requirement to run an older parser. Use the fetched write-video-ad-script preparation command with --brief working/script/creative-brief.json and its documented bank/brand/product/template arguments; set the new shape.requires_creative_brief to true. The writer and critic consume that same angle-context. Save only the concise brief/revision and workspace reference in script_drafts extra fields, never full research/package contents. A missing required brief fails the script check; do not rerun known research or rewrite user-locked wording silently.\n\nRead references/specialist-handoff.md from the saved shared harness. For each selected UGC, product/demo or motion operation, extend the existing script_drafts.capability_plan entry with the exact approved brief/script revisions, mapped scene/beat numbers and timing, selected product/reference/source IDs and excerpt ranges, audio/performance choice, package/version/hash and expected returned artifact roles. These are existing extra draft/project artifacts, not new API parameters. Preserve the distinction between numeric script_drafts.scenes[].scene and string production scene IDs.\n\nCheck the actual returned package before executing: H3 plan_takes uses beats id/start/end/vo and character image/identity/environment/delivery; footage-cutlist uses sources and per-beat source/in/out/fit/why; goose-graphics returns static composition/PNG and still needs an actual motion renderer. Do not replace an unsupported helper with a guessed tool name. Preflight the real binary/import/browser and a free dry run, not just its presence. Existing-file skip behavior is not validity: probe saved media and verify fingerprints/approval/job results first, then reuse approved media on resume without new generation.\n\nValidate returned media and provenance against the handoff before clip checks/assembly: exact scene/source revision, words/product/variant, visible proof, measured duration/ratio, selected voice/native speech and neighboring continuity. All speech requires actual isolated performance listening and full mixed-output listening; transcript/word timing only supports that judgment. Audition representative unresolved material and reuse valid approved takes. No mandatory faster delivery or louder climax.\n\n## Hook changes and editorial review\n\nRead references/hook-compatibility.md and references/editorial-review.md from this run's saved harness. Resolve the exact watched source/render and classify same-promise hook versus a new promise requiring different body/proof/payoff. Every changed opening gets new image/action/audio/text review, including visual-only restyles with unchanged words. Shortlist cheap ideas before media spend; keep a broader recut distinct from an isolated opening test.\n\nFor an isolated hook replacement, fetch the existing render-hook-replacement package and inspect its real preflight/config contract. A not-found/empty catalog response blocks that route before paid generation; an open source change is not proof of served availability. Preserve source/body/ending using its own verification, then play/listen to the complete candidates and register each separately. Recommendations are creative judgments, never unmeasured performance winners.\n\nRun rough/fine/final review questions through the current Studio surfaces. First save what the actual cut communicates, then compare with the brief; concept review has no watched-cut verdict. Route unsupported promise to script/concept, missing proof to production, sequence problems to edit and local defects to repair. Unavailable required playback/listening is incomplete and cannot become quality_status passed.\n\nKeep exact feedback text/source/time, intended effect and acceptance condition. Consolidate duplicate notes and record conflicting intentions plus the authorized owner's decision. Preserve changed versus verified dispositions in existing feedback/production metadata or linked project artifacts; executing a fix does not resolve it. Invalidate only affected script/assets/timings/captions/mix/approvals/derivatives, retain valid unrelated work, and rewatch each actual delivered file. Preserve editable timeline, stems, caption sources, selected/candidate versions, rejected options with reasons and scoped pronunciation/delivery history for the next run. Approval and model scores are not audience performance.\n\n## GooseWorks capability binding\n\nRead capabilities.md to bind shared instructions. GooseWorks is authoritative for project state and approvals; local working artifacts grant no spending permission.\n\n- Brand facts and product assets: brand_get_context plus the saved brief/reference analysis.\n- Durable state, concept/design/script/scene/continuity records and feedback: video_project_read and video_project_upsert. Save shared artifact roles in script_drafts extra fields and production metadata; translate spoken lines, captions and scenes into the review schema below.\n- Human gates: discuss free creative choices in chat. Persist concept/design/script before authenticated script approval. Selected storyboard, playable voice auditions, characters, worlds and end card become actual ingredients. Stop for authenticated ingredient approval before any paid clip or preview video. Record the customer's explicit chat approval through patch.approve with the current phase, review token and cumulative budget; a reply alone, local artifact or shared auto mode does not record approval. A handed-off coworker cannot approve its own work. Changes require renewed approval.\n- Provider access, bounded pricing and spend: managed fal/ElevenLabs tools and currently supported endpoints only. Do not switch to direct provider keys, Higgsfield or an unpriced fallback. A missing capability blocks its state until a supported equivalent is reviewed and quoted.\n- Storage: media_upload and media_confirm with exact project ownership; use durable previews in ingredients.\n- Assembly, probes, frame extraction, transcript comparison and continuous inspection: shared package scripts, FFmpeg/FFprobe/Python and available media review tools. A thumbnail or text description cannot satisfy video review.\n- Render attempts, QC, history and promotion: video_render_run and video_project_upsert using the backend contract below. Shared QC still applies; the backend checklist is a minimum.\n\nGrowth and connected coding agents supply local execution. A terminal-free MCP client can prepare/review with connected tools, but must stop or continue through the project's Growth session when required local capabilities are absent. Never claim a render ran without execution.\n\n## Start and resume\n\nAfter the connected tool contract passes the checks above, for a new brief call video_project_upsert with brand_id, name, format:\"custom\", custom_mode:\"generate\", brief:{prompt, audience, objective, product_name, cta, ratio, duration_seconds}, optional reference_url and a stable idempotency_key. Use only brief fields present in the schema. Instagram references have a metered public-data lookup; direct files are downloaded, probed and stored. generated_video_url and media_id mean finished-file imports, never references. Do not use import mode to bypass a generation project's review gates.\n\nRead video_project_read on every resume. When it returns remix.direction for this generated custom project, use remix.direction.implementation as the production starting point: keep the pipeline, full prompts and guards, timings, assembly settings and fixes. Watch the reference. Rewrite all spoken lines and bind products, claims, images and CTA to the target brand. Stay on this same custom project; obtain fresh approvals for its own script/ingredients and budget before any paid call. A source approval or source voice recording never authorizes this new run.\n\nRead video_project_read on every resume. Its project and custom_review are authoritative. Growth creates and retains origin_session_id from trusted chat context. Show the saved review in this conversation and record the customer's explicit approval through the authenticated customer-facing connection as described below. Studio remains available when the customer wants it; never require Chrome to approve. Continue in Growth resumes the bound conversation. A handed-off production coworker prepares the review, ends its turn and waits for the customer-facing connection to record approval before it resumes the same project.\n\nIf reference preparation failed, explain custom_review.reference.error. Continue from the brief if requested, or retry with patch:{retry_reference:true}. A live preparation claim is protected for twenty minutes; after interruption an explicit retry reuses a saved resolved URL when possible. Never invent a reference analysis when no reference was viewed.\n\n## Saved review schema\n\nSave through video_project_upsert {brand_id,project_id,patch:{script:{script_drafts,script,expected_plan_revision}}}. script_drafts contains format:\"custom\", title, duration_target_sec (<=180), aspect_ratio, scenes:[{scene:1,time:\"0–5s\",text,caption,direction}], preview_estimate:{total_credits,basis,operations:[\"Describe each priced operation as a string\"]}, optional render_estimate in the same shape, voices:{narrator:{voice_id,name}} and ingredients:[{container,label,subtitle,url,text,note,pending}]. script_drafts.scenes[].scene is a positive integer such as 1; production scene IDs use the separate string shape described below. The plain script is joined spoken copy. Read project.plan_revision and pass it as expected_plan_revision on every existing-draft save; a stale write is refused. Store concept, reference_analysis, continuity, planned operations and job/asset provenance as extra draft fields; keep the review set under 256 KB.\n\nEach estimate requires total_credits (a nonnegative number, at most 3,000), basis (a nonempty string) and operations (1–100 nonempty strings, each at most 500 characters). Do not put operation objects in either estimate. Keep detailed model/settings/cost rows in a separate extra field such as planned_operations. voices is an optional object keyed by role, never an array; each selected role is {voice_id, name?}. Keep unselected audition candidates in a separate extra field. Copy actual catalog voice IDs into the selected roles; every selected role later needs a matching playable voice ingredient.\n\nFor example, a narrator selection is voices:{narrator:{voice_id:\"<actual catalog ID>\",name:\"<catalog name>\"}}. A preview estimate is preview_estimate:{total_credits:100,basis:\"One presenter image and two voice auditions\",operations:[\"Presenter image: fixed-price supported model\",\"Two voice auditions: the saved script\"]}. These values illustrate the shape; quote the actual supported operations for the run.\n\nBefore saving either preview_estimate or render_estimate, quote each remaining paid media operation through data_post_provider with its exact supported path, body and project_id plus query:{quote_only:true}. Before sending this flag, read a fresh data_post_provider tool description from the selected connection. It must explicitly advertise query:{quote_only:true}, maximum_credits and no generation, reservation or debit. Alternatively, require explicit environment-owner evidence that this same selected app-MCP runtime has deployed free quote support. An extensible query schema or a newer fetched skill is not evidence. If the description is old and no verified runtime evidence exists, stop before the call and request the backend rollout and connector refresh; an older server can treat this flag as a paid generation request. The quote requires no approval and generates no media. This mode is MCP-only; do not send quote_only to an HTTP generation proxy.\n\n```json\n{\n \"provider\": \"fal\",\n \"path\": \"fal-ai/kling-video/v3/standard/image-to-video\",\n \"body\": {\n \"image_url\": \"https://example.com/approved-anchor.png\",\n \"duration\": \"5\",\n \"generate_audio\": false\n },\n \"project_id\": \"<this project ID>\",\n \"query\": {\n \"quote_only\": true\n }\n}\n```\n\nRequire quote_only:true, a finite positive maximum_credits and cost.credits:0 in the result. If the server returns a job, audio, a charge or any non-quote result, stop and report the tool/runtime mismatch; never retry it as a quote. Unknown or unbounded prices block planning. Do not substitute public unit prices or guessed billed discounts for maximum_credits: the custom reservation includes conservative quantity, size, audio and preset bounds, while actual settlement can be lower.\n\nSum maximum_credits for all remaining operations in the phase into that estimate's total_credits, including every concurrently planned job. Keep local free assembly/QC operations at zero. The approved project cap includes custom_review.committed_credits plus the remaining quoted estimate; committed includes both settled spend and outstanding reservations. Read the current review again before approval, avoid counting an already reserved job twice, and quote any changed model/body before seeking revised approval. Quotes are not approval tokens or locked prices; real submission rechecks its current conservative bound and the approved budget.\n\nBefore script approval, only plan/save free text. preview_estimate quotes future storyboard images and voice auditions. custom_review.script_approved permits priced image previews on supported fal image endpoints and ElevenLabs text-to-speech auditions. Unknown endpoints require ingredient approval. Use catalog voice previews when possible; do not silently select a paid model outside the preview allowlist.\n\nUpload actual previews with media_upload/media_confirm. Put public/durable URLs on image/avatar/background/endcard/voice/audio/video ingredients. Text containers can carry inline text; a voice or image description cannot replace its preview. Save a render_estimate for remaining clips/assembly and show the complete ingredients. Stop until custom_review.ingredients_approved. Script and ingredient tokens are independent; do not infer approval from project.status.\n\n## Record each approval in this chat\n\nThere are two independent gates. Script approval permits the quoted image/voice previews. Ingredient approval permits the quoted clips and finishing work after the actual review set is ready. Keep both gates even when the customer prefers chat to Studio.\n\n1. Read video_project_read. Show the current saved script or actual playable ingredients, the changes since any previous approval and the cumulative credit limit in custom_review.approval_quote. Explain that the limit includes custom_review.committed_credits plus the remaining quoted operations. An old estimate, approval from a previous revision or remaining-only amount is not the current budget.\n2. Ask for the customer's explicit approval of that phase and amount in this conversation. Copy their actual words as user_quote; never invent consent or interpret a pricing-error complaint as approval of a changed creative plan or larger budget.\n3. Read video_project_read again before recording the yes. Require the same review token, phase and total shown to the customer. If any changed, show the changed review and ask for approval of it; never silently attach the earlier yes to a newer token or amount.\n4. Through the authenticated customer-facing connection call video_project_upsert {brand_id,project_id,patch:{approve:{user_quote:\"<the customer's actual words>\",phase:custom_review.approval_quote.phase,review_token:custom_review.approval_quote.review_token,total_credits:custom_review.approval_quote.total_credits}}}. This is the custom contract; template approvals without phase and review_token cannot authorize custom production. Do not combine this approval with a script edit.\n5. Read back custom_review. For phase:\"script\", require script_approved:true and the matching script_token. For phase:\"ingredients\", require ingredients_approved:true and the matching ingredient_token. Check the approved max_credits covers the current cumulative total before dispatch. A tool error or merely sending patch.approve is not approval.\n\nThe approval_quote.phase is \"script\" or \"ingredients\". Its review_token is the matching custom_review.script_token or custom_review.ingredient_token from that saved snapshot. If approval_quote is missing or the requested phase's review is not ready, finish the free preparation or resolve the returned blocker; never guess a token, reuse the other phase's token or change the budget to force approval.\n\nOnly the authenticated customer-facing connection can record the customer's approval. A handed-off coworker with a production task prepares and displays the review, ends its turn, and waits. It cannot call patch.approve to approve its own work, forward a fabricated user_quote or treat the original brief as approval. After the customer-facing connection records and verifies approval, resume that same task/project with goose_run_task when required. Studio can record the same authenticated approvals if the customer chooses it; do not require Chrome, browser unlocks or Studio access just to approve in chat.\n\n## Paid execution and resume\n\nEvery managed media call carries project_id (GW_PROJECT_ID in scripts) and a stable input fingerprint. Use the managed fal/ElevenLabs endpoints and credentials supplied by Growth; never request customer provider keys. Do not expose those credentials in logs. Recheck custom_review before dispatch. The backend reserves estimated outstanding costs atomically, enforces the approved total (maximum 3,000 credits) and prevents duplicate submissions. At most a 20% overrun can be newly approved; this is not automatic permission to spend above the customer's selected limit. A custom video's budget grows only through a renewed approval. On SPEND_CAP_REACHED the open render is asked to stop: report it \"stopped\" with what was kept (see \"Render run states\") and tell the customer what was made and spent. Then save a revised estimate, show the new custom_review.approval_quote with its current total, record the customer's approval of that total, and open a new render that reuses the saved pieces.\n\nPreview eligibility and price support are separate checks. Use an exact endpoint permitted by the backend preview policy and confirm its current request schema and server quote. Model discovery and provider pricing can change: use the selected connection's actual quote, including supported provider estimates, instead of a skill-maintained priced-model list. A model-family name does not make every route eligible for script previews. Do not move a preview to another phase to bypass its approval gate. If pricing cannot be established, keep the saved request and report a system pricing blocker; do not ask the customer to choose when their choices are already approved. Final clip models require ingredient approval. Existing-job polls remain permitted after edits; retrieval does not authorize new media.\n\nSave provider request IDs and actual uploaded URLs promptly. Custom operations with known rejection can retry safely; ambiguous timeouts keep their authorization until reconciled. Media spend is metered through the shared gateway. Custom videos have no extra template base render fee. Imported finished files still file for zero credits.\n\n## Clips, assembly and quality\n\nUse the selected packages in script_drafts.capability_plan for each scene and operation. Recheck specialist discovery for new requirements or repairs before improvising a helper. Keep anchors and exact lines fixed. Use the Python assembly helper returned in the shared harness scripts for actual existing clips. It needs only Python, FFmpeg and FFprobe; it does not call a provider or require Chromium. Inspect generated clips before assembly, and watch the final export after assembly/captions.\n\nOpen a render with video_render_run {brand_id,project_id,kind:\"full\"}; executor:\"cloud_agent\" for Growth when exposed by the current schema. Report live workflow_stage/progress_note/progress_percent while producing it. Upload the final file to scope:\"video_project\", scope_id:project_id. The tool opens/reports a client-executed render; fixed server orders remain paused.\n\n### Render run states\n\nReport the open render's state with video_render_run {brand_id,project_id,render:{render_id,...}}. Use the row that matches:\n\n| Situation | status | workflow_stage | quality_status | Also send |\n| --- | --- | --- | --- | --- |\n| Producing, checking or repairing | \"running\" | preparing, rendering, checking, repairing or rechecking | \"pending\" | progress_note, progress_percent, steps |\n| Waiting for the customer: they must approve a candidate, choose or give feedback, with or without an uploaded candidate | \"running\" | \"blocked\" | \"blocked\" | output_url when an uploaded candidate exists, error_message saying in plain words what you need from them, and choices (at most 4 buttons; put credits on any paid choice). A quality_report is optional while waiting; when sent, it carries the current findings |\n| Stop requested: a progress callback returned stop:true because the customer stopped the video or a paid step hit the spending limit | \"stopped\" | omit | omit | progress_note saying in plain words what was kept. Start no new paid step; let a call already running finish. |\n| Real failure: no usable candidate can be produced (provider refusal with no approved alternative, or a system blocker you cannot recover) | \"failed\" | omit (the server sets blocked) | \"blocked\" | error_message in plain words |\n| Done | \"complete\" | omit (the server sets ready) | \"passed\" | output_url and the full quality_report, only after the final recipe is saved and read back as described below |\n\nWaiting for the customer is not a failure, and neither is a stop. Never report \"failed\" because you are waiting for approval, a choice or feedback, or because the customer or the spending limit stopped the video. When stop:true comes with stop_reason \"superseded\", report nothing further on that render. The app shows a waiting render's candidate as \"Needs your approval\" and keeps it for up to 14 days; after that the server ends it as failed with failure_code review_expired. The uploaded file stays in the project either way.\n\nA waiting state is valid only while the approval it rests on is current. A render can complete only under the approval it was opened with. After any script or ingredient edit (yours or the customer's), or after review_expired, the old render cannot be completed: read video_project_read {brand_id,project_id,include:[\"assets\",\"renders\"]}, show the changed review and the current custom_review.approval_quote in chat, record the customer's approval of each phase it asks for, then open a new render. Opening a new render stops the older open render of this video with stop_reason \"superseded\" (\"Replaced by a newer version.\"). Report nothing more on a superseded render and start no paid step for it; continue on the new one. To deliver an unchanged candidate on the new render, follow \"Finalize an existing candidate after re-approval\" below.\n\nWhen the customer approves a waiting candidate and nothing in the review changed, finish the shared final review and complete that same render; a candidate needs no separate approval phase. When they ask for changes, save the feedback and follow the normal edit and approval gates.\n\nOn resume, treat a render left at \"running\" with workflow_stage \"blocked\" as a pending customer decision. Read custom_review and custom_review.feedback before doing anything else. If your own render shows stop_reason \"superseded\", another run replaced it: read video_project_read {brand_id,project_id,include:[\"assets\",\"renders\"]} and continue on the newer render; do not open another one just to resume.\n\nAfter each accepted generation or deterministic edit, update patch.production with the steps and settings that actually ran. Save and read back the actual candidate recipe before showing its preview or pausing for review, so an interrupted or waiting run does not leave only an early plan in the backend. Partial progress is allowed; pending creative approval or QC must stay explicit and must never be converted into passing clip evidence.\n\nBefore completing or pinning a candidate, replace the early planning manifest with the actual production recipe. Record every current script scene using its string scene number, exact current spoken line, measured duration and full generation prompts or deterministic rendering instructions. Record the actual pipeline/model settings, assembly/captions/audio settings, and repairs in fixes. Never leave blocked/pending planning statuses in a completed recipe. Preserve full prompts and guards; do not reduce them to summaries. Save partial progress while working, but an unfinished recipe is not a reusable final.\n\nSave the final recipe through patch.production, then read video_project_read and compare production_manifest with what you just saved, including all scene IDs and spoken lines. If the save fails or the read-back is stale/incomplete, repair it before completion; do not describe the run as finished or remixable. Final completion freezes the actual recipe and reviewed script together for the next agent.\n\nSave patch.production as a production manifest with version:1 and a nonempty pipeline array. Each pipeline item requires step and model; purpose and settings are optional. production.characters is an optional array, never a record/object: each entry requires both name and prompt strings. Store anchor media IDs, URLs, actual appearance and other extra provenance in script_drafts; character entries accept name and the full design prompt.\n\nproduction.scenes[].id is a string containing the corresponding script scene number, for example \"1\". script_drafts.scenes[].scene and production.clips[].scene remain positive integers, for example 1. Map production scene IDs with String(scriptScene.scene); do not convert clip.scene or script scene IDs to strings. Each scene can also carry line, still_prompt, motion_prompt, duration_s and notes. style is an object; voice and music are objects when present; assembly is an object; fixes is an array of {problem,fix}.\n\nEach clip requires a numeric scene, a stored URL and exactly one of each named check: visual_artifacts, brand, product, voice_and_script, duration_and_ratio. Each clip check is {check,status:\"pass\"|\"fail\",note?}; not_applicable is not valid for clip checks. Save exactly one checked clip per approved script scene before final completion, with every check passing. Before clips exist, omit clips from an ingredient-preparation save.\n\nThe following is a one-scene JSON shape example. Replace all placeholders with actual saved values. Its failed QC statuses are deliberately unapproved; never copy a passing status without performing the shared review.\n\n```json\n{\n \"patch\": {\n \"production\": {\n \"version\": 1,\n \"pipeline\": [\n {\n \"step\": \"Scene clips\",\n \"model\": \"<actual supported model>\",\n \"settings\": {}\n }\n ],\n \"style\": {\n \"prompt\": \"<shared visual direction>\",\n \"negative\": \"<shared guards>\"\n },\n \"characters\": [\n {\n \"name\": \"Presenter\",\n \"prompt\": \"<exact full character design prompt>\"\n }\n ],\n \"scenes\": [\n {\n \"id\": \"1\",\n \"line\": \"<approved spoken line>\",\n \"still_prompt\": \"<exact full still prompt>\",\n \"motion_prompt\": \"<exact full motion prompt and guards>\",\n \"duration_s\": 5\n }\n ],\n \"voice\": {\n \"voice_id\": \"<selected catalog voice ID>\",\n \"name\": \"<selected voice name>\",\n \"model\": \"<actual voice model>\",\n \"settings\": {}\n },\n \"assembly\": {\n \"ratio\": \"9:16\",\n \"fps\": 30\n },\n \"fixes\": [],\n \"clips\": [\n {\n \"scene\": 1,\n \"url\": \"https://example.com/confirmed-scene-1.mp4\",\n \"checks\": [\n {\n \"check\": \"visual_artifacts\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"brand\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"product\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"voice_and_script\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n },\n {\n \"check\": \"duration_and_ratio\",\n \"status\": \"fail\",\n \"note\": \"<actual observation; pass only after inspection>\"\n }\n ]\n }\n ]\n }\n }\n}\n```\n\nComplete with video_render_run {brand_id,project_id,render:{render_id,status:\"complete\",output_url,quality_status:\"passed\",quality_report:{version:1,summary,checks:{source,brand,product,hook_and_scene_order,voice_and_script,captions,endcard_and_cta,duration_and_ratio,visual_artifacts},detected_issues:[],repair_actions:[],checked_at}}}. Each final check is {status:\"pass\"|\"fail\"|\"not_applicable\",note}; brand/product/scene order/duration/visual artifacts must pass. A candidate that fails QC is never complete: keep it \"running\" with workflow_stage \"repairing\" while you fix it, report the waiting state above when the customer must decide, and use \"failed\" only for a real failure. Final completion binds approval revisions, output and quality evidence to the render; pin with patch.final_render_id only after passing.\n\nAll nine named final checks above are required, including source, voice_and_script, captions and endcard_and_cta when they are not applicable. A final check uses status:\"pass\"|\"fail\"|\"not_applicable\" and an optional note. The five mandatory passing checks are brand, product, hook_and_scene_order, duration_and_ratio and visual_artifacts; no final check may fail and detected_issues must be empty to complete. Record why a permitted check is not_applicable. Keep actual repair_actions and use the actual ISO 8601 checked_at time. The backend report is a minimum; it does not replace the full shared watch, claim verification or craft review.\n\nThis waiting-for-the-customer report illustrates every required field. Replace the URL, reason, choices, findings and example timestamp with actual evidence. Only after repairs and the shared final review pass may the render be reported complete with quality_status:\"passed\", its confirmed output_url and no unresolved issues.\n\n```json\n{\n \"render\": {\n \"render_id\": \"<existing render ID>\",\n \"status\": \"running\",\n \"workflow_stage\": \"blocked\",\n \"quality_status\": \"blocked\",\n \"output_url\": \"https://example.com/confirmed-candidate-in-this-project.mp4\",\n \"error_message\": \"<what you need from the customer, in plain words>\",\n \"choices\": [\n {\n \"label\": \"Approve this version\",\n \"message\": \"I approve this version\"\n },\n {\n \"label\": \"Change something\",\n \"message\": \"I want to change something in this version\"\n }\n ],\n \"quality_report\": {\n \"version\": 1,\n \"summary\": \"<actual full-video review summary>\",\n \"checks\": {\n \"source\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"brand\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"product\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"hook_and_scene_order\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"voice_and_script\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"captions\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"endcard_and_cta\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"duration_and_ratio\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n },\n \"visual_artifacts\": {\n \"status\": \"fail\",\n \"note\": \"<actual finding from the shared review>\"\n }\n },\n \"detected_issues\": [\n \"<actual unresolved issue>\"\n ],\n \"repair_actions\": [],\n \"checked_at\": \"2026-10-03T00:00:00Z\"\n }\n }\n}\n```\n\n### Finalize an existing candidate after re-approval\n\nUse this when an uploaded candidate (a confirmed video in this project) already shows and says exactly what the current script says, but its render can no longer complete: the script was amended to match the take, or the wait ended as review_expired. If any spoken line, caption, scene or ingredient differs from the current script, this route does not apply: repair or regenerate under the normal gates.\n\n1. If the script changed, save it and record the customer's script approval first, as in \"Record each approval in this chat\". Then save the candidate as a video ingredient (its confirmed URL) in the review set, show the candidate and the current custom_review.approval_quote in chat, and record the ingredient approval. The earlier render was approved against the old review, and the server will not complete it.\n2. Open a new render with video_render_run {brand_id,project_id,kind:\"full\"}. Start no provider call. The older waiting render stops as superseded.\n3. Run the shared final review on the existing file against the current script. voice_and_script and captions must match the current lines.\n4. Save and read back the final production recipe with the current lines and one checked clip per scene, as described in \"Clips, assembly and quality\". Reuse the clip records from the candidate's saved recipe, updated to the current lines.\n5. Complete the new render with status:\"complete\", output_url set to the existing candidate's confirmed URL, quality_status:\"passed\" and the full quality_report. Do not regenerate or re-upload. No credits are spent.\n6. Pin it with video_project_upsert patch.final_render_id (alias set_final_render).\n\n## Feedback and delivery\n\nSave customer script/ingredient/video feedback through the connected project tools before continuation; affected creative edits invalidate their approvals. Read custom_review.feedback on every turn, preserving the original watched render/time and text when provided. A selected final change never relocates an earlier note. Resolve only after the candidate satisfies the original intended effect and full-output recheck; keep incomplete or conflicting notes open. Replace only the affected assets; save revised estimates and show the changed review and cumulative budget in the same chat before recording renewed approval. Deliver the playable current_render_url with render_artifact kind:\"video\" in Growth and actual project spend. Include the Studio app_url when a text host or the customer needs it; do not require it for approval. Keep final history; never create another project just because an agent restarted.\n\n## Reviewed snapshot, voices and supported pricing\n\ncustom_review returns script_drafts and plan_revision from the same saved snapshot as its tokens. Show that snapshot in chat; Studio can also render it. Use the revision for edits and the current approval_quote for each approval. Spoken copy (text) and on-screen copy (caption) are separate fields. Voice audition ingredients carry role and voice_id; script_drafts.voices maps each role to its selected voice_id/name. Every selected role needs an actual matching playable preview before approval.\n\nA pending/processing/failed reference blocks script approval. If the customer explicitly chooses to continue from the brief without the reference, save that choice through the connected reference-review tool when exposed, or offer Studio's Continue from brief action when needed. This is a reference decision, not a requirement to approve in Chrome. Do not silently replace a requested reference with brief-only production.\n\nCustom provider submits require a positive server quote, including quantity, supported dimensions/audio and any provider estimate. The server must establish source duration for audio/video-driven routes from authorized media metadata or a bounded probe; do not add invented duration fields to the provider body to force a quote. A provider estimate permits production within the approved budget even when exact final billing is unavailable. Missing source duration or an unavailable provider estimate is a system blocker to resolve on the saved project, not a model allowlist or a new creative choice. A conservative reservation is released to actual charged spend when the provider result settles. Final output must be a confirmed, stored video_asset in this exact organization/project, and completion binds its media_id to the render. External hotlinks cannot be pinned as generated custom finals. The portable helper checks FFmpeg's libass capability before local captions, rejects clips shorter than their timeline and validates video-stream duration.\n";
6
6
  //# sourceMappingURL=custom-video-skill.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-video-skill.js","sourceRoot":"","sources":["../../src/skills/custom-video-skill.ts"],"names":[],"mappings":";;;AAAA,iGAAiG;AACpF,QAAA,4BAA4B,GAAG,20wDAA20wD,CAAC"}
1
+ {"version":3,"file":"custom-video-skill.js","sourceRoot":"","sources":["../../src/skills/custom-video-skill.ts"],"names":[],"mappings":";;;AAAA,iGAAiG;AACpF,QAAA,4BAA4B,GAAG,sx1DAAsx1D,CAAC"}
@@ -1388,7 +1388,7 @@ Idea requests still follow ad-angle-miner with the video output.
1388
1388
  ### 3. Show the picker or its text fallback
1389
1389
 
1390
1390
  Call \`video_catalog_list { kind: "formats", brand_id }\`. On the customer's computer, when you
1391
- can actually execute shell commands, include \`client: { shell: true }\`; in a chat host omit
1391
+ can actually execute shell commands, you MUST choose local execution and include \`client: { shell: true }\`; in a chat host omit
1392
1392
  that claim. Inside a coworker sandbox follow its reported capabilities, never claim to be the
1393
1393
  customer's computer. Respect requested limit and next_cursor for more item pages; the card may
1394
1394
  contain a full picker independently of the item page.
@@ -1414,7 +1414,7 @@ contain a full picker independently of the item page.
1414
1414
  Never tell a chat host it needs Claude Code to start. Browser-only formats remain unavailable
1415
1415
  here; give computer setup guidance only if asked how to make one.
1416
1416
  - **Local shell:** run \`gooseworks doctor --no-browser\` for common setup (auth/MCP, Node 18+,
1417
- ffmpeg with libx264 + libass, ffprobe). Then fetch the selected template and its capabilities,
1417
+ ffmpeg with libx264 (libass only for an ASS caption route), ffprobe). Then fetch the selected template and its capabilities,
1418
1418
  and install documented dependencies in its fetched folder. Do not guess a renderer from a
1419
1419
  format name. For each Node renderer using default Playwright Chromium, run
1420
1420
  \`gooseworks doctor --renderer-script "/absolute/path/to/the/fetched/scripts/record.js"\` with
@@ -1752,7 +1752,7 @@ the skill. It's fire-and-forget, never counts against you, and never blocks your
1752
1752
  1. **Sandbox →** see "Running in a GooseWorks sandbox": ffmpeg + ffprobe (+ PIL on demand); no
1753
1753
  Chromium, so browser formats stop there.
1754
1754
  2. **CLI present →** run \`gooseworks doctor --no-browser\` for login, MCP, Node 18+, ffmpeg
1755
- with libx264 + libass, and ffprobe. This is common setup only. After fetching the selected
1755
+ with libx264, and ffprobe. Require libass only for a selected ASS caption route; caption-burn uses Pillow overlays and does not need it. This is common setup only. After fetching the selected
1756
1756
  capabilities in Step 2, check each browser renderer's actual launch before ANY paid
1757
1757
  ingredient. An unscoped \`gooseworks doctor\` checks only the calling folder's browser;
1758
1758
  it cannot certify a different fetched renderer.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gooseworks",
3
- "version": "0.5.0-dev.3.8661ef81",
3
+ "version": "0.5.0-dev.5.1ff84a4f",
4
4
  "description": "GooseWorks CLI — give your coding agent real data tools",
5
5
  "bin": {
6
6
  "gooseworks": "./dist/index.js"
@@ -57,7 +57,7 @@
57
57
  "homepage": "https://gooseworks.ai",
58
58
  "author": "GooseWorks <help@gooseworks.ai>",
59
59
  "gooseworksRelease": {
60
- "commit": "8661ef8177829a0d4a283a8c8a81cfe0a0552078",
60
+ "commit": "1ff84a4f894dcb13e9fd2c1698fb3a2576ebe8d5",
61
61
  "branch": "dev"
62
62
  }
63
63
  }
@@ -483,7 +483,7 @@ Idea requests still follow ad-angle-miner with the video output.
483
483
  ### 3. Show the picker or its text fallback
484
484
 
485
485
  Call `video_catalog_list { kind: "formats", brand_id }`. On the customer's computer, when you
486
- can actually execute shell commands, include `client: { shell: true }`; in a chat host omit
486
+ can actually execute shell commands, you MUST choose local execution and include `client: { shell: true }`; in a chat host omit
487
487
  that claim. Inside a coworker sandbox follow its reported capabilities, never claim to be the
488
488
  customer's computer. Respect requested limit and next_cursor for more item pages; the card may
489
489
  contain a full picker independently of the item page.
@@ -509,7 +509,7 @@ contain a full picker independently of the item page.
509
509
  Never tell a chat host it needs Claude Code to start. Browser-only formats remain unavailable
510
510
  here; give computer setup guidance only if asked how to make one.
511
511
  - **Local shell:** run `gooseworks doctor --no-browser` for common setup (auth/MCP, Node 18+,
512
- ffmpeg with libx264 + libass, ffprobe). Then fetch the selected template and its capabilities,
512
+ ffmpeg with libx264 (libass only for an ASS caption route), ffprobe). Then fetch the selected template and its capabilities,
513
513
  and install documented dependencies in its fetched folder. Do not guess a renderer from a
514
514
  format name. For each Node renderer using default Playwright Chromium, run
515
515
  `gooseworks doctor --renderer-script "/absolute/path/to/the/fetched/scripts/record.js"` with
@@ -453,7 +453,7 @@ the skill. It's fire-and-forget, never counts against you, and never blocks your
453
453
  1. **Sandbox →** see "Running in a GooseWorks sandbox": ffmpeg + ffprobe (+ PIL on demand); no
454
454
  Chromium, so browser formats stop there.
455
455
  2. **CLI present →** run `gooseworks doctor --no-browser` for login, MCP, Node 18+, ffmpeg
456
- with libx264 + libass, and ffprobe. This is common setup only. After fetching the selected
456
+ with libx264, and ffprobe. Require libass only for a selected ASS caption route; caption-burn uses Pillow overlays and does not need it. This is common setup only. After fetching the selected
457
457
  capabilities in Step 2, check each browser renderer's actual launch before ANY paid
458
458
  ingredient. An unscoped `gooseworks doctor` checks only the calling folder's browser;
459
459
  it cannot certify a different fetched renderer.
@@ -240,6 +240,20 @@ review set; do not add a separate approval round.
240
240
 
241
241
  The generic production phases run in the Growth sandbox or a connected agent with a shell. GooseWorks owns the project, approvals, budget, uploads and final selection. This adapter replaces Studio desktop files and Tauri approval events with the product contract below.
242
242
 
243
+ ## Execution preflight
244
+
245
+ A connected agent with a working shell executes this custom project locally. Declare client:{shell:true} on every video/format/catalog request that accepts it, including video_project_read. Each call can reach a different server process; a previous capability report does not carry over reliably. Missing libass does not remove shell capability: fetch [[composes::caption-burn]], which uses Pillow and FFmpeg overlay. Fetch every selected specialist and the invoked harness step files before declaring a route unavailable.
246
+
247
+ For MCP-owned runs set GW_MEDIA_VIA=mcp and GW_PROJECT_ID before running any helper, even if CLI credentials exist. Record the selected account_whoami public API origin as GW_EXPECTED_API_ORIGIN; never open credential files to discover it. Use HTTP only after verifying the matching origin through supported CLI diagnostics. For large MCP relay bodies, use the helper's body_file without retyping: upload that JSON file to this same video project, confirm the returned asset, then call data_post_provider with body_asset_id and omit body when the tool advertises that argument. Its normal project, approval, budget and secret checks still apply. Older connectors must relay the exact saved JSON unchanged.
248
+
249
+ Before taking over a delegated project, cancel its delegate task and read back that it is detached. Do not request another approval while a stale delegate remains attached. If cancellation is unsupported, save the blocker; a Stop followed by reapproval can wake the same delegate again.
250
+
251
+ After a paid failure, reconcile the known job and actual charges. Stop after the first identical infrastructure failure; a failed coworker turn can still cost credits. Quotes are estimates, not actual spend. Preserve approved copy while changing cost explanations; show actual cumulative charges from the project ledger.
252
+
253
+ Run helpers from the run's working directory with explicit absolute input/output paths. For footage, save inspected source in/out bounds and fit:width, including screen.fit:width. A planned creator image may be absent during free take planning; use plan_takes --plan-only instead of generating a placeholder.
254
+
255
+ The writer's paid critic cannot run before custom script approval. Perform its rubric locally before script review and save that evidence. Only run an external critic when the host explicitly supports it in the current approved phase and budget; never bypass a spend gate or silently claim an independent critic ran.
256
+
243
257
  ## Check the connected tool contract first
244
258
 
245
259
  Inspect the tool parameters exposed by the selected connection before creating or changing a custom project. catalog_fetch returns skill packages, not tool schemas. Use the host's registered tool definitions (MCP tools/list when available); do not assume that fetching a newer skill updates a connector's saved schema.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "package": "gooseworks",
3
- "version": "0.5.0-dev.3.8661ef81",
3
+ "version": "0.5.0-dev.5.1ff84a4f",
4
4
  "entries": {
5
5
  "gooseworks": "d719edca708f013faebe51a51fac2877fdbd99a52ff6b6fd4af033b11b888504",
6
6
  "goose-ads": "72d118fcef19eec4ff875cfc3997b3e949bb88966b9156f8e9e23a5b458c9d92",
7
- "goose-video": "b5ef83fb9b9201b58521aa3266a550c07d0a08b4cf0356b66cba0d4b7abd23ae",
8
- "goose-video-local": "72709ed2cd983aeb898b1c401fe55330336e9707ee7c62c1ad00a87de3874b53",
9
- "make-custom-video": "b765083cafe2e645b646e0217439130839c7ceb9b497375135058d61cf76c1be",
7
+ "goose-video": "36e67eb44ca33558c6e6912a957d5c6724897d8e33556cbaa309831245d2c0f9",
8
+ "goose-video-local": "ab48518399e68d1c9b59d8576eac00588e39b0b3c401ec95b287e8cd07391420",
9
+ "make-custom-video": "a87dcd0af66e14ad5749806af0455d9fa1181d4dd2801d3f9c74b8eaf8667aab",
10
10
  "goose-product-photos": "e0450b5556c7b67f8338fafcd2a620b0647e333ecd651b3bd5242402a6616ffe"
11
11
  }
12
12
  }