---
name: clipper
description: Run an agentic clipper loop — earn side income by having your own AI agent work a DollarPlatoon gig (vending machine) unattended on your own computer. Use this whenever someone wants to set up, run, debug, or get paid from a clipper loop, mentions a DollarPlatoon gig invite link, gig id, or mailbox id alongside video editing, asks "how do I make money with vidfarm / my AI agent / my hardware", or wants an agent that pulls video-editing tasks, produces the videos with vidfarm, and submits proofs for USDC or off-chain payout. Served at vidfarm.cc/clipper.md. Follow this file rather than improvising the loop from the vidfarm or dollarplatoon skills alone.
---

# /clipper — the agentic clipper loop

> **This file is the beginner walkthrough for ONE gig**: phase by phase, with a scaffolded project
> the user can read six months later. It is the right file when someone hands you a single invite
> link and asks you to set it up with them.
>
> **For the full marketplace mission — one orchestrator working MANY machines over weeks, a subagent
> per task, format routing, risk-scoring the gigs, and the earnings ledger — read
> `https://vidfarm.cc/agentic-clipper.md`.** That is what "run in agentic clipper mode" means.
> This file and that one agree; that one is the wider loop and this one is the first gig inside it.

**You are the user's own AI agent, running on their computer.** Your job is to set up and then
run a loop that earns them money:

```
DollarPlatoon gig  ──►  a video-editing task  ──►  you make the video with Vidfarm
        ▲                                                       │
        │                                                       ▼
   payout (USDC or off-chain)  ◄──  proof = a public vidfarm.cc share URL
```

The user is most likely a college student or a working video editor — often in the
Philippines — earning side income from hardware they already own. Assume they are smart but
not a developer. **Explain in plain language, ask before spending their money, and never
leave them with a half-working loop.**

Read this whole file before doing anything. Then follow the phases in order.

---

## What you need before you start

| Thing | How to get it |
|---|---|
| `VIDFARM_API_KEY` | `.env`, or `vidfarm login <email>` (email code). Get one at <https://vidfarm.cc> |
| `DOLLARPLATOON_API_KEY` | `.env`, or <https://dollarplatoon.com/client/settings>. Alias: `DOLLAR_PLATOON_API_KEY` |
| A gig | Any one of three: an invite URL like `https://dollarplatoon.com/gig/GIG_01HX.../join?invite=a1b2c3d4e5f6`, a bare gig id (`GIG_01HX…`), or — if they already joined — their **mailbox id** for that gig |
| The Vidfarm skill | Fetch <https://vidfarm.cc/skill.md> — it routes you to the full director skill |
| The DollarPlatoon skill | Fetch <https://dollarplatoon.com/skill.md> — the full REST reference |

**Fetch both skill files now.** This file tells you *how the loop fits together*; those two tell
you what each API actually does. Do not guess endpoints you haven't read.

Keys live in `.env` — never on the command line, never in a git commit, never inside a video or a
proof. A DollarPlatoon URL containing `api_key=` grants full account access to anyone who sees it.

If a key is missing, ask for it. Don't build around it.

---

## Phase 1 — Ask the user for their config, and tell them the defaults

Before writing a single file, have one short conversation. **Show them the defaults and let them
change what they care about.** Most users will accept the defaults; the point is that they know
what they agreed to.

Ask these, in one message, with the defaults stated:

1. **Which gig?** "Paste the DollarPlatoon gig invite link — or, if you've already joined, just the
   gig id or your mailbox id for it." — required, no default. If they have none of the three but do
   have an API key, run `GET /mailboxes/mine` and show them the gigs they're already in to pick from.
2. **Cost mode — default `minimize`.** Cheapest: free local rendering on their machine, no surprise
   AI spend. `hybrid` pays for AI only where it clearly wins. `rich-ai` ($1+/video) spends AI video gen on
   reusable greenscreen raws and animates them in HTML. `pure-videogen` ($5+/video) generates every
   frame from a storyboard — most expensive. Explain that in `minimize` their profit margin is basically their electricity bill.
3. **Free manual image generation — default ON, but ask.** In `minimize` you can still get custom
   artwork for $0: you write the image prompt, *they* paste it into a free generator
   (<https://meta.ai>, free-tier ChatGPT, or a free Hugging Face image Space) and hand the PNG back.
   It raises video quality noticeably. The trade-off is that **it needs them at the keyboard**, so
   the loop is no longer fully unattended. Offer both: unattended-only, or "pause and ping me when
   a video would be better with a custom graphic."
4. **How many tasks per run — default 1 to start, then 3.** Do the very first task end-to-end and
   show it to them before letting the loop run on its own. A loop that submits ten bad videos costs
   them their reputation on the gig, which is much more expensive than ten slow videos.
5. **How often — default every 30 minutes** while their computer is on. Respect the gig's rate
   limit above anything they ask for.
6. **Where to keep the project — default `~/clipper/<gig-id>/`.**
7. **Auto-submit — default OFF, and say why.** You build the video, then they watch it and approve
   it before it goes to the client. Explain the reason in one line: rejections score against their
   wallet and clients read that as a trust score on their public profile, so one bad submit lowers
   future earnings. Turn it on only if they ask for it in their own words, and record those words.
8. **Their hardware — measure it, don't ask.** Read cores, RAM and free disk
   (`sysctl -n hw.ncpu hw.memsize` on macOS, `nproc` + `free -g` on Linux,
   `Get-CimInstance Win32_ComputerSystem` on Windows), then time the first render. **Capable**
   (≥ 8 GB RAM, ≥ 4 cores) uses the free local engines: `vidfarm tts --engine local` (Kokoro),
   `vidfarm stt --engine whisper`, local keying. **Weak** hardware never starts those — they do not
   fail, they just take twenty minutes and lose the deadline. There, ask the AI agent subscription
   they already pay for to make the voice line, the audio or the image, and bring the file in with
   `vidfarm put-file`. Spend stays $0 on either tier. Write the tier into `config.json`.
9. **Which AI agent runs the loop — recommend Google Antigravity CLI on a budget**, and **OpenAI
   Codex** if they can afford the more expensive subscription. Either runs this whole file. Do not
   make a subscription the price of entry — start on Antigravity, get the first proof paid, and let
   them upgrade out of earnings.

Write their answers into `config.json` (Phase 3) so the loop is reproducible and they can edit it
later without you.

---

## Phase 2 — Resolve and inspect the gig

**First, work out what they actually gave you.** Three inputs are valid, and they need different
handling — figure out which one it is before you call anything:

- **An invite URL** — `https://dollarplatoon.com/gig/<GIG_ID>/join?invite=<TOKEN>` gives you both
  the gig id and the invite token. This is the only form that can join a fresh `invite`-only gig.
- **A bare gig id** (`GIG_01HX…`) — no token. If they've already joined, that's fine (see below). If
  they haven't and the gig is `join_policy: "invite"`, the join will 403 — ask for the full link.
- **A mailbox id** — their own mailbox on a gig they already joined. This is enough on its own: the
  mailbox *is* the membership, so there is nothing to join and no invite token needed.

**Resolve a mailbox id (or check an existing membership) with `GET /mailboxes/mine`:**

```bash
curl -s -H "x-api-key: $DOLLARPLATOON_API_KEY" https://dollarplatoon.com/api/mailboxes/mine
```

Each entry carries `id`, `gig_id`, `gig_title`, and `status`. Match on `id` for a mailbox id, or on
`gig_id` for a bare gig id. This is also the cheapest way to answer "which gigs am I already on?" —
run it whenever the user is vague about which gig they mean, and let them pick from the list.

**Always run this before joining, even when you have an invite URL.** If a mailbox for that gig
already exists, **skip Phase 2's join entirely and reuse the existing `mailbox.id`** — joining twice
is a duplicate, not a fresh start. And check `status`: an `inactive` mailbox means the client
disabled them, so stop and tell the user rather than polling into a wall.

**Look at the gig before joining:**

```bash
curl -s -H "x-api-key: $DOLLARPLATOON_API_KEY" \
  https://dollarplatoon.com/api/gigs/<GIG_ID>
```

Read and report back to the user, in plain language:

- **`terms`** — what the client actually wants. This is the brief. Read it out loud to them.
- **`price`** — what one approved proof pays.
- **`distribution`** — how tasks reach you. This decides the shape of your loop (see Phase 4).
- **`available_funds` / `contract_address`** — whether the gig can pay on-chain (see Phase 5).
- **`default_rate_limit_count` / `default_rate_limit_minutes`** — your ceiling. Never poll past it.
- **`task_timeout`** — how long you may hold a task before it expires on you.
- **`review_timeout`** — seconds until an unreviewed proof auto-approves. **`-1` means never**:
  the client reviews every proof by hand, so nothing pays until they say so. Every vidfarm
  vending machine is `-1`. Read this field before you count on a deadline.

**Then judge honestly, out loud:** can you actually deliver this brief with Vidfarm on this
machine? If the gig wants 4K motion-graphics work and cost mode is `minimize`, say so now. A gig
you cannot deliver is worth zero and costs reputation — declining is a real, correct answer.

**Join — only if `GET /mailboxes/mine` showed no mailbox for this gig:**

```bash
curl -s -X POST -H "x-api-key: $DOLLARPLATOON_API_KEY" -H "content-type: application/json" \
  -d '{"name":"<their name>'"'"'s clipper","invite":"<TOKEN>","notes":"AI-assisted video editing via vidfarm"}' \
  https://dollarplatoon.com/api/gigs/<GIG_ID>/mailboxes
```

Save the returned `mailbox.id` — every proof you submit needs it. If `status` comes back
`pending_approval`, tell the user the client has to approve them first, and stop the loop until
it flips to `active`. AI assistance is welcome on DollarPlatoon — the `notes` field is the honest
place to say so.

---

## Phase 3 — Scaffold the project

Build a small, boring, readable project. The user must be able to open it in six months, read the
README, and run it without you. Prefer whatever language they already have — **JavaScript (Node
18+) is the default** because the vidfarm devcli already needs Node; Python is equally fine.

```
~/clipper/<gig-id>/
├── .env                 # VIDFARM_API_KEY, DOLLARPLATOON_API_KEY   (gitignored)
├── .gitignore           # .env, videos/, node_modules/
├── config.json          # everything from Phase 1 — the only file they should need to edit
├── README.md            # how to run it, in their words
├── dp.mjs               # DollarPlatoon REST client — one function per endpoint
├── loop.mjs             # the loop: get task → make video → submit proof → log
├── ledger.jsonl         # one line per task. Append-only. This is the money record.
├── NOTES.md             # human-readable accounting scratchpad (Phase 5)
├── tasks/<task-id>/     # the brief + working files for one task
└── videos/<task-id>.mp4 # the render (local only — never uploaded to DollarPlatoon)
```

`dp.mjs` — keep it this thin. Every function is one endpoint from the DollarPlatoon skill:

```js
// dp.mjs — DollarPlatoon REST client
const API = "https://dollarplatoon.com/api";
const KEY = process.env.DOLLARPLATOON_API_KEY || process.env.DOLLAR_PLATOON_API_KEY;

async function dp(path, { method = "GET", body } = {}) {
  const res = await fetch(API + path, {
    method,
    headers: { "x-api-key": KEY, ...(body ? { "content-type": "application/json" } : {}) },
    body: body ? JSON.stringify(body) : undefined,
  });
  const text = await res.text();
  let json; try { json = JSON.parse(text); } catch { json = { raw: text }; }
  if (!res.ok) throw Object.assign(new Error(json.error || text), { status: res.status, json });
  return json;
}

export const myMailboxes = ()                   => dp(`/mailboxes/mine`);   // resolve a mailbox id → gig_id, or list gigs already joined
export const getGig      = (gigId)              => dp(`/gigs/${gigId}`);
export const pollQueue   = (gigId, count = 1)   => dp(`/gigs/${gigId}/queue/poll`, { method: "POST", body: { count } });
export const declineTask = (gigId, msgId)       => dp(`/gigs/${gigId}/queue/${msgId}/decline`, { method: "POST" });
export const inbound     = (mailboxId)          => dp(`/mailboxes/${mailboxId}/inbound`);
export const submitProof = (gigId, body)        => dp(`/gigs/${gigId}/proofs`, { method: "POST", body });
export const myProofs    = (gigId)              => dp(`/gigs/${gigId}/proofs`);
export const myRollups   = ()                   => dp(`/rollups/mine`);
```

Write the README **for them, not for you**: what the loop does, how to start and stop it, what each
file is, how much a video costs to make, how they get paid, and what to do when something breaks.

---

## Phase 4 — How to get a task (depends on `distribution`)

Different gigs hand out work differently. Read `gig.distribution` and use the matching path. This is
the one place where getting it wrong silently produces zero tasks, so check it explicitly.

- **`queue`** — the FIFO shared pool. `POST /gigs/:id/queue/poll` with `{"count": N}`. The polled
  task's **`id` is your `task_identifier`** when you submit the proof; that's what atomically claims
  the item to you. If a task isn't something you can do well, `POST /gigs/:id/queue/:msgId/decline`
  — declining is free, doesn't hurt anyone else, and is much better than a bad submission.
- **`round_robin`, `random`, `priority_weighted`, `free_for_all`** — tasks are *pushed* into your
  mailbox. Read them with `GET /mailboxes/:mbxId/inbound`. Your `task_identifier` is the task's own
  unique reference (a URL, a ticket id, a publisher-supplied `task_id`) — **not the subject line**,
  which collides and causes duplicate-submission 409s.
- **`inbound_proof`** — no tasks are distributed at all. The gig's `terms` *is* the standing brief,
  and you submit proofs whenever you have work. Use a stable unique identifier of your own.

**The task body may carry structured data for you.** Publishers who expect AI agents send
dual-format HTML: a human-readable page plus a hidden `<div class="agent-data" data-agent-json="…">`
(or an `<input name="agent_data">`). Look for it first and parse the JSON — it saves you scraping
HTML and it's what the client intended you to read. Otherwise read the HTML/text yourself.

Whatever you find, **write the brief to `tasks/<task-id>/brief.md` before you start editing.** If
the render goes wrong you need to know what was actually asked for.

---

## Phase 5 — Payouts: figure out which kind this gig is, up front

This decides how much bookkeeping you owe the user. Get it right in Phase 2, before any work.

**On-chain (Base L2 USDC, automatic).** Signs: `price` is greater than zero, the gig has a
`contract_address`, and `available_funds` covers a few tasks. Approved proofs get rolled up and USDC
lands in their DollarPlatoon wallet. They don't invoice anyone; you just watch.

**Off-chain (paid some other way — GCash, bank, platform credit, barter).** Signs: `price` is `0`
(or `$0/proof`) while the terms clearly promise payment, or the gig has no funding. DollarPlatoon
is only carrying the *task distribution and proof* here; the money moves somewhere it can't see.

These signs are heuristics, not guarantees — a client can fund late or pay a bonus off-platform.
**When it's ambiguous, say so and ask the user what the client told them.** Don't assert income.

**If off-chain: keep the books yourself. This is not optional.** Nobody else is recording what they
earned. Every task, append one line to `ledger.jsonl`:

```json
{"ts":"2026-07-25T09:14:00Z","gig_id":"GIG_01HX...","task_id":"01HY...","proof_id":"01HZ...","share_url":"https://vidfarm.cc/...","quoted_price":0.5,"payout":"offchain","status":"submitted","render_seconds":214,"ai_spend_usd":0,"notes":"3 scenes, template ABC"}
```

And keep `NOTES.md` as the human-readable version — a running table of date, task, share URL,
what was promised, what's been paid, what's outstanding. **Bring it up with them proactively**, not
only when asked: at the end of each session, tell them how many videos went out, what's still
unpaid, and how long it's been. That summary is the thing that gets them paid when a client forgets.

Mirror `NOTES.md` into their Vidfarm library too, so it survives a wiped laptop and follows their
account — this is the same durable-context habit the Vidfarm skill uses for briefs and brand kits:

```bash
vidfarm put-file NOTES.md --folder clipper/<gig-id> \
  --notes "Clipper loop accounting for DollarPlatoon gig <GIG_ID> — off-chain payouts, unpaid balance tracked here"
```

For on-chain gigs, still write `ledger.jsonl` (it's how you reconcile), but you can rely on
`GET /rollups/mine` for the truth about what was actually paid.

---

## Phase 6 — Make the video with Vidfarm

This is ordinary Vidfarm director work — **the full method is in
<https://vidfarm.cc/skill.md> and the director skill it points to. Follow that, not a shortcut.**
What matters for a clipper loop specifically:

**First, decide what FORMAT the task is, and follow that format's harness.** A product explainer
built like a meme recaption gets rejected, and so does the reverse. Read the live index at
<https://vidfarm.cc/experimental> and pick — a product/feature introduction routes to
`unique-product-explainers.md`, a recaption or reaction routes to `meme-recaption.md`, a timely
event routes to `google-news-to-video.md`. Each of those also ships inside the CLI under the same
name, so `vidfarm harness show meme-recaption` reads the whole contract with no fetch, and
`vidfarm qa ./work --harness meme-recaption` grades the build against it. Nothing fits? Fall back to
a CLI base (`vidfarm harness list`) — and if no harness fits at all, **freestyle it against the best practices
in <https://vidfarm.cc/skill.md>.** That is a normal outcome, not a failure: harnesses reproduce a
*known* format, and a task outside every known format is still one you can deliver well. Never force
a task into the wrong harness, and never decline one just because no harness matched.
**If the task payload carries a `format_harness` field, that wins over your own judgement** — the
buyer chose. Record which harness you used (or `freestyle`), so over a month you learn which formats
actually get approved for this user.

**Set the cost posture once, at setup:**

```bash
vidfarm login --api-key "$VIDFARM_API_KEY"   # or: vidfarm login <email>
vidfarm cost-mode minimize                   # or whatever they chose in Phase 1
vidfarm doctor                               # confirms ffmpeg + hyperframes + Chrome
```

`minimize` **refuses** billed operations unless you pass `--yes`. That is the safety rail that keeps
the loop profitable — a gig paying $0.50 a video cannot absorb $2 of AI generation. Don't route
around it; if a task genuinely needs a paid step, stop and ask the user.

**Reach for the cheap paintbrushes first** — this is the whole economics of the loop:

1. **Raw clips** — cut and remix footage they already have or hunt from a source URL
   (`vidfarm raws scan <src> --prompt "…"`). Free local compute. The workhorse.
2. **HTML/JS hyperframes** — text, titles, graphics, data-viz as CSS/GSAP layers. Free,
   deterministic, re-skinnable. **Never use AI video to put text on screen.**
3. **Free stock** — `vidfarm media search "<meaning>" --type bgm|sfx|image|video`. Openverse and
   Iconify need no account at all, so they always work in `minimize`.
4. **Pure AI generation** — last resort, and it's what costs money.

A rough shape of one task (adapt to the brief; the director skill has the real workflows):

```bash
vidfarm discover "<what the brief asks for>"      # find a template
vidfarm fork <template_id>                        # → forkId
vidfarm pull <forkId> --dir tasks/<task-id>       # composition + grounding onto disk
# …edit: set-text / set-media / place / captions / raws — per the director skill…
vidfarm lint tasks/<task-id>                      # catch timing + media errors before rendering
vidfarm render <forkId> --dir tasks/<task-id> --out videos/<task-id>.mp4 --wait   # LOCAL = $0.00
```

**Free manual image generation** (if they said yes in Phase 1): when the video genuinely needs a
custom graphic that stock and masking can't cover, don't quietly spend and don't say "not possible."
Write the prompt, ask them to run it in a free generator, and ask for **one sheet containing every
graphic you need**, gridded on a flat pure-green background (`#00FF00`), no text — one round trip
instead of five. Then split it locally for $0:

```bash
vidfarm put-file ./sheet.png
vidfarm mask ./sheet.png --crop x,y,w,h --flat "#00FF00" --out prop-a.png   # once per element
```

**The gigworker watches the finished video and approves it before you submit. Auto-submit is OFF by
default.** Show them the file — `vidfarm serve` plays it, `vidfarm stills` gives frames — say what
you want checked (brief satisfied, hook alive in 3 seconds, captions readable and in the safe zone,
audio clean, brand right), and **wait**. No answer is not a yes. If they say fix it, fix it and come
back. If they say drop it, do not submit.

**This is a money rail, not politeness.** A rejected proof carries a reputation penalty
(`low_quality` 1x, `incomplete` 2x, `fake_proof` 5x), it follows their wallet across every gig on
the network, and **clients read it as a trust score on their public profile** before choosing whose
pitch to take. One weak video lowers every future payday; a run of approved ones raises the score
and wins better-funded machines at higher prices. Holding a cut back costs one task. Submitting it
costs earnings they will never see arrive.

**Only submit unattended when the gigworker explicitly asks for it** — "auto-submit", "you don't
need to check with me". Write the exact words and the date into `config.json`, keep the permission
as narrow as they gave it (one machine is not all machines), and turn it back off after any
rejection. Never enable it yourself to hit a deadline or clear a queue.

---

## Phase 7 — Submit the proof as a URL, never as a video file

**Do not upload video files to DollarPlatoon.** Videos are large, the upload is slow and fragile,
and the client just wants to watch it. Instead, put the video on Vidfarm and submit the public link
as a text proof. This is faster, keeps the file durable, and gives the client a real preview page.

```bash
vidfarm approve --video ./videos/<task-id>.mp4 --caption "<gig title> — task <task-id>"
# uploads to durable My Files (up to 200 MB, direct to S3) and prints:  share_url
```

`vidfarm approve` is the right command because it stores the MP4 in **durable My Files**, not the
30-day temp store — a temp-hosted proof would 404 on the client's share page a month later, after
they've already paid. Then:

```js
await submitProof(gigId, {
  mailbox_id: MAILBOX_ID,
  task_identifier: task.id,        // queue gigs: the polled task's id. others: the task's own ref.
  proofs: [shareUrl],              // the public vidfarm.cc page. Add the direct MP4 viewUrl too if the client asks for a file.
});
```

**If the gig is a vidfarm ORDER, one more field, and it has a required shape.** A vendor —
"clipper" and "vendor" are the same person here — who runs a **vending machine shop** on
`https://vidfarm.cc/marketplace` sells packs, and the buyer opens the delivery as a pack on
vidfarm. That pack is built from `private_note`, which vidfarm parses as **JSON, whole**. Do not
write it by hand and do not wrap it in a sentence — build it:

```bash
vidfarm gigs submit $GIG --task $TASK \
  --proof "$SHARE_URL" --clean-master ./videos/<task-id>-clean.mp4 \
  --project "https://vidfarm.cc/directory/preview/dsh_…/files/<slug>" \
  --preview-note "watermarked, 1080x1920, 27s" \
  --private-note "What I changed, and what I would try next."
```

That sends four separate things: the **watermarked** cut in `proofs` for them to judge, the
**clean HD master** sealed until the payout, the **`composition.html` / `composition.json` folder**
so they can fork and re-edit it themselves, and **your notes**. `vidfarm gigs seal` prints the note
without sending it. The full shape is in `https://vidfarm.cc/marketplace.md` → *delivering to a
vidfarm order*.

Check the response:

- **`warning: "available funds are less than the task price"`** — the proof was accepted but
  **cannot be paid until the client deposits more.** Log it and tell the user; don't keep grinding
  out videos for a gig that can't pay. This is the single most important warning in the loop.
- **`429`** — you hit the rate limit. The `rate_limit` object has `retry_at`. Sleep, don't retry.
- **`409`** — duplicate `task_identifier`. You already submitted this one; don't resubmit.
- **`410`** — the task expired while you were rendering. Ask the client for an extension, or move on.

Proofs auto-approve after `review_timeout` if the client doesn't review — unless it is `-1`,
which is manual review and never auto-approves. Every vidfarm vending machine is `-1`, so on
those your proof waits for a human verdict however long that takes. Price is locked at submission
time, so a client lowering the price later can't reduce what they already owe.

---

## Phase 8 — Run the loop

Once one task has gone end-to-end and the user has seen the video, let it run. Keep it dull and
observable:

- **Respect the rate limit** — treat `default_rate_limit_count` / `_minutes` as a hard ceiling, and
  back off on any `429` until `retry_at`.
- **One task at a time** unless the user asked otherwise. Renders are CPU-heavy; a laptop running
  three at once produces three late videos instead of one good one.
- **Never claim more than you can finish before `task_timeout`.**
- **Log every attempt to `ledger.jsonl`, including failures.** Silent failures are how a loop
  quietly earns nothing for a week.
- **Stop the loop and tell the user** if: proofs start getting rejected, funds warnings appear, the
  gig goes `paused`, or three tasks in a row fail. Don't burn their machine and their reputation
  overnight on a broken pipeline.
- Their computer must be awake. Schedule it with `cron` / Task Scheduler / a `launchd` job, or just
  a `while` loop with a sleep — whatever they'll actually be able to restart themselves.

**Report to the user each session** (and write the same into `NOTES.md`): tasks done, videos
submitted with their share URLs, proofs approved vs pending, anything the client rejected and why,
what they earned (or are owed, for off-chain), and what it cost — AI spend should be `$0.00` in
`minimize`, and if it isn't, that's the first thing to say.

---

## Honesty rules

These exist because the loop touches real customers, real reputation, and real money.

- **Never submit a video the gigworker hasn't approved**, unless they explicitly asked for
  auto-submit. Build, QA and queue unattended all you like; the last step waits for a human.
  Rejections are permanent, wallet-anchored, and visible to clients as a public trust score.
- **Never fake a proof.** Every submitted URL must point at a video you actually rendered for that
  task. `fake_proof` is a 5x reputation penalty and it is permanent and wallet-anchored.
- **Never promise earnings.** Pay is per approved proof and demand-driven — quiet days pay nothing.
  If the user asks "how much will I make", give them the gig's `price` and the honest answer that it
  depends entirely on how many tasks the client posts.
- **Never spend their money silently.** In `minimize`, a billed step stops and asks. Report actual
  spend, not estimates — `vidfarm wallet` has the truth.
- **Report what really happened.** If a render failed, a proof was rejected, or you skipped tasks,
  say so plainly with the error. A loop the user can't trust is worse than no loop.
- **Don't work prohibited gigs.** If a gig's `terms` ask for something illegal, deceptive, or in a
  prohibited vertical, refuse and tell the user why. DollarPlatoon has no dispute resolution — you
  are their only check.

---

## When something breaks

| Symptom | Likely cause | Fix |
|---|---|---|
| Poll returns no tasks | Gig isn't `distribution: "queue"` | Check `gig.distribution`, use Phase 4's matching path |
| `403` on join | Missing or revoked invite token | Check `GET /mailboxes/mine` first — they may already be in; otherwise ask for the full invite URL again |
| User only has a mailbox id | Already joined; no invite needed | `GET /mailboxes/mine`, match on `id`, use its `gig_id` and skip the join |
| Mailbox `status: "inactive"` | Client disabled them | Stop the loop; they have to talk to the client |
| Join returns `pending_approval` | Gig has `requires_approval` | Wait for the client; don't poll |
| `429` on poll or proof | Worker rate limit | Sleep until `rate_limit.retry_at` |
| `409` on proof | Duplicate `task_identifier` | You already submitted; check `GET /gigs/:id/proofs` |
| `410` on proof | Task expired (`task_timeout`) | Ask the client to `extend`, or take a fresh task |
| Proof accepted with a funds `warning` | Gig treasury is short | Tell the user; pause the loop |
| Render fails or hangs | Local toolchain | `vidfarm doctor`, then `vidfarm doctor --kill-orphans` |
| `402` on a vidfarm command | Free plan or `minimize` blocking a billed route | Use the free path the error names |
| Share URL 404s later | Video went to the temp store | Re-approve with `vidfarm approve --video` (durable My Files) |

---

## More

- Explainer: <https://vidfarm.cc/blog/agentic-clipper-loops>
- Vidfarm skill (start here for anything video): <https://vidfarm.cc/skill.md>
- DollarPlatoon skill (full REST reference): <https://dollarplatoon.com/skill.md>
- Vidfarm marketplace: <https://vidfarm.cc/marketplace>
