--- name: plotpickle-fal-production description: Produce approved PlotPickle storyboard clips through the separately connected fal plugin, submitting on "Submit" and returning in-chat video when available; preserve source review, spend controls and 3–15-second editorial Motion Spans. --- # PlotPickle — fal Production (v0.8.27) fal is PlotPickle's sole recommended image-to-video provider connection. Use *actual connected fal tools* when available; an installed catalogue alone is not authentication. Do not require a local Windows application, another custom MCP server, GitHub or API-key paste. Exclude retired direct provider endpoints (including model IDs beginning `minimax/`) from PlotPickle's new-production recommendations. Model metadata and connection status must be verified from live provider tools; do not invent model support, credits or prices. ## The natural-language Submit action The desired UX is **Prepare → Review cost → Approve → Submit → Return video to chat**. Once the user explicitly approves the *specific* source image, endpoint, duration, resolution, audio mode and charge estimate, accept a simple subsequent **"Submit"**, **"Submit Shot 01"** or **"Generate approved clip"** as instruction to execute **one** previously approved job. Do not ask them to visit fal's website, copy the prompt or download the result by hand when connected upload/generation/result-display tools are available. Do not repeat the same approval question if approved terms have not changed. Do not interpret "why can't I submit?" or a hypothetical mention of the command as actual submission intent. On actual Submit: 1. Recheck the job specification against the previously approved source image, model, duration, resolution, audio choice, and price estimate. Reject stale or ambiguous approvals, changed payee, different clip, changed price, or a different model pending new cost approval. Record this as one *specific* paid request, not blanket authorization for a 25-shot batch. 2. Ensure first-frame **bytes** are genuinely available. Preferred: separate original shot media from the saved project/asset package, source identity+hash verified. For a creator explicitly using a user-uploaded contact sheet or storyboard composite in a noncanonical one-off test, crop only the relevant visual artwork, remove UI text/timecodes, and warn that thumbnail resolution may reduce quality. Mark as `experimental-preview`, not Save/Lock-verified or production accepted. Never upload the whole annotated 25-panel board as if it were shot one. 3. Upload the actual first-frame via fal upload tools: attached original user media via `upload_attachment`; for generated/prepared files in local sandbox, `upload_file` accepts complete base64 for up to 64KB; larger sandbox assets must become user attachments if no authorized upload path is available. Never pass a local filesystem path as a remote provider URL. If upload is impossible, explain this specific blocker and retain the approved job; do not pretend the job was submitted. 4. Use the connected fal's *actual endpoint* and precise schema; select an eligible compatible video model and get cost before asking approval. For the prior approved request, preserve the selected endpoint and settings. For long video generation, use `submit_job` with a stable submission key when journal availability permits, store the returned request ID and status/response URL. Do not create another request when a status call is uncertain; first reconcile the original request. A retry, enhancement, or other charge needs fresh approval. 5. Within the **same active chat turn**, use `check_job` until the job completes or the tool reports an unrecoverable state; fetch the result with `get_job_result` only if necessary. Show the returned video using `show_media` and present its original download/view URL if supported. If the job remains in progress beyond the current task, provide the real request ID and a user-initiated follow-up to resume checking; **do not claim it will continue asynchronously or post later without an actual automation**. No invisible continuous worker exists. 6. Once a fal result reports COMPLETED, **continue automatically** into the media-intake stage without demanding a second "convert", "register" or "send me the MP4" command. First present/retain the actual provider video. The agent should arrange its media URL, the real project source, shot address and unmodified completed fal result into the intake helper described below. Conversion and read-only registration require no new provider-generation approval and must never submit another fal job. 7. When media intake succeeds, publish the verified 24-fps MP4 and its draft receipt in the same active ChatGPT response. If ChatGPT Library/project-file tools are available and authorized, persist the draft MP4 and receipt under the story/shot; otherwise return actual files and clearly state persistence is pending. Do not silently revise the screenplay or native PPF. A native PPF asset registration requires a separate guarded write/readback with the actual import capability; a Library draft sidecar does not satisfy it. 8. If no host is able to read the provider MP4 bytes (including an HTTP download from its direct fal CDN URL), **stop at external-draft** and report a concrete transport limitation. Show the playable original file; never claim a 24 fps conform or verification was completed. Do not require user to download-and-reupload unless every host import path fails. Do not generate again or spend credits to solve a transport-only problem. ## Prepare, inspect and editorial truth Under **HOME → Storyboard → Produce**, offer **Prepare Motion**, **Check fal**, **Compare Model and Cost**, **Approve**, **Submit**, **Inspect Clip**, and **Continue Film**. No charge for browsing, preparing or displaying already generated media. Story/project sources remain authoritative; preserve project ID, revision, source SHA-256, screenplay passage IDs, shot address, first-frame artifact ID and hash. Production-ready native media requires separate Save/Lock validation; user-uploaded visual mockups can support clearly identified trial generations but never establish native Save/Lock. Never derive an unknown source-asset hash from a screenshot description. A Mini-Block uses 25 planned storyboard positions. Baseline = 3 seconds / 72 frames per position at 24fps. A Motion Span may group 1–5 consecutive positions in the same Mini-Block for a proposed 3–15-second editorial piece; a generated model duration need not equal edit duration. Do not multiply one approval into multiple billable jobs. For local still-animatics/draft assembly use `../plotpickle-animatic/SKILL.md`. Offline helper: `python3 scripts/fal-handoff.py --project story.ppf.json --block 1 --mini 1 --start-shot 1 --end-shot 1 --motion-cue "Gentle forward dolly" --out shot-01-fal-brief.json`. This never uploads, submits, spends, rewrites the PPF or claims production readiness. Run `python3 scripts/test-fal-handoff.py`; see `references/contract.md` and `references/motion-spans-v1.md`. ## Integrated no-spend clip intake and 24 fps conform (v0.8.27) After a successful fal job, prefer **same-turn fully automatic processing** using the accessible ChatGPT execution runtime. This is not a standing service: the execution environment must be able to retrieve the actual video bytes and have FFmpeg/ffprobe. Supply one *genuine* completed fal result (status, endpoint_id, request_id, result.video.url plus metadata) and the current saved PPF. Never invent a completed result or substitute a contact-sheet still for the registered PPF image. A current file/source revision must be verified again before intake. Keep approval status independent from draft registration. 1. Prepare `fal-completed.json` from the *actual connected fal result*. Do not include private job-account access fragments or authentication tokens in a public export. Keep the returned video URL intact. Use the saved PPF and exact source shot coordinates; the source image must already be selected for the approved generation. 2. For a direct-source download when permitted, call the helper with `--allow-fal-download`. It restricts the host to HTTPS fal media URLs and rejects redirects. When the host already has the actual video bytes, pass `--video path/to/source.mp4` instead. Do not fetch arbitrary URLs or use a guessed/made-up local filename. 3. Execute from this skill directory: `python3 scripts/fal-clip-intake.py --project /path/to/current-project.ppf.json --result /path/to/fal-completed.json --block 1 --mini 1 --shot 1 --expected-project-sha ORIGINAL_SHA256 --out /new/Shot01-draft --allow-fal-download` This helper validates the source PPF and screenplay passage mapping, checks the provider media URL and real byte length, probes and fully decodes original bytes, then creates an exact 72-frame 24fps 3-second H.264 MP4 without sound, verifies the full decode and writes `draft-receipt.json`. Inputs stay unchanged. It fails closed, refuses output overwrite and removes partial outputs. The source first-frame still is NOT automatically considered Save/Lock-verified or identical to the source PPF image. Use `--video` instead of `--allow-fal-download` if the host already obtained the MP4. 4. If intake succeeds, display/link `draft-24fps.mp4`, show the original video for comparison, and register both the video and receipt in the user's accessible story workspace/Library when the host offers a permitted writing tool. Keep the register status **verified draft sidecar, pending user review / native PPF import** until a native project writer independently verifies the import and reads it back. Don't write an extension into a PPF and claim it became native simply because the JSON was serialized. 5. If intake cannot run because bytes/HTTPS/FFmpeg are unavailable, show the actual fal result and preserve a truthful pending-intake record; never ask the user to confirm payment again or rerun a paid generation. Offer a user attachment only as a last resort and be clear that the limitation is the host's media transport, not the fal connection. The helper is standard-library Python plus installed FFmpeg and ffprobe, and does no fal calls or spending. Run `python3 scripts/test-fal-clip-intake.py` (synthetic offline video) and `python3 scripts/test-fal-handoff.py`. A passing synthetic test does not prove remote CDN download works in every ChatGPT sandbox. `references/clip-intake-contract.md` details verification states. ## Optional Windows editor intake (v0.8.28) If chat cannot fetch original MP4 bytes, do not regenerate video. Route to `../plotpickle-editor/SKILL.md` for a local-only Windows receiver that can fetch a completed fal CDN MP4, decode it and conform to 24 fps, then expose an editable draft timeline. This receiver is not automatically installed or MCP-connected; no public listener is permitted.