@officexapp/vidfarm-devcli 0.21.58 → 0.21.60

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.
package/marketplace.md CHANGED
@@ -52,6 +52,12 @@ in this order, and report back with what you found. Each one is spelled out in
52
52
  > join command on each row — then lists the work already waiting in machines you joined. Start
53
53
  > there, then use the table above when you want a move on its own.
54
54
 
55
+ > **Those four moves are the FIRST session. A loop that runs for weeks is paced**, and the pacing is
56
+ > three rules: fill your subagent slots by walking your machines one at a time and stopping when they
57
+ > are full, never ask the same machine again inside **12 hours**, and sweep the notifications
58
+ > **twice a day** for new bells and new machines to join. See *Keep the bench full* under
59
+ > **Gigworker Instructions**, and § 4 ①–② of `https://vidfarm.cc/agentic-clipper.md`.
60
+
55
61
  > **Then ask ONE question before you build anything: how much of the gigworker's attention does each
56
62
  > task get?** That is the **run mode**, and there are four — full interactive, quick interactive, full
57
63
  > auto with batch review, and full auto with auto-submit. They change which stages stop for the human
@@ -263,7 +269,7 @@ Read `private_note` on its own and you know where you stand:
263
269
 
264
270
  **Use `not_selected` for a pass on an inbound offer.** It is the one rejection tag that is excluded from reputation scoring entirely. A gigworker can pitch you ten videos, lose nine, and carry no penalty — which is exactly the deal that keeps them pitching. Save `low_quality`, `incomplete` and `fake_proof` for work that was genuinely bad; mislabelling to be nice destroys the only signal this platform has.
265
271
 
266
- **Review promptly. Silence is approval.** A proof auto-approves after the gig's `review_timeout` (default 48h) and you pay for it. If you disappear for a week you will pay for everything that arrived.
272
+ **Review promptly. Silence is NOT approval here.** Both vidfarm vending machines run at `review_timeout: -1`, manual review: no proof auto-approves, and nothing is paid until you approve it. A countdown that pays for you exists on Dollar Platoon generally, but not on these two. The cost of silence is the other one — a gigworker who is never answered is left holding finished work and stops sending it.
267
273
 
268
274
  In the browser the same job is one swipe deck: `https://vidfarm.cc/marketplace/inbound/swipe`. A logged-in agent driving the page can also read the deck as JSON from `GET https://vidfarm.cc/marketplace/buyer/proofs?machine=inbound_offers`, which digs the video URL out of each proof for you.
269
275
 
@@ -321,6 +327,24 @@ reference is the intended outcome, not a defect.** Your creative variety comes f
321
327
  small model improvising, which is something nobody controls. Want seven different bets this week?
322
328
  Name seven different reference templates.
323
329
 
330
+ **If you want a SERIES, say so in the task — otherwise you will get seven different things.**
331
+ Clippers are instructed never to send one buyer two videos that repeat the same hook, clip, template
332
+ or joke, because unasked-for repetition reads as batch output. That default is right most of the
333
+ time and wrong when you are deliberately running variants. So make it explicit in the brief:
334
+
335
+ ```jsonc
336
+ {
337
+ "task": "5 cuts of ONE hook for acme.com — this is a deliberate A/B set",
338
+ "series": true,
339
+ "series_note": "hold the hook and the template. vary only the opening clip and the b-roll",
340
+ "reference_template_id": "template_019fd6b0…"
341
+ }
342
+ ```
343
+
344
+ The same words work in the gig terms, in the bell, or in the `feedback` on a proof you kept —
345
+ `"Great hook. More like this one."` is read as a request for the series. Say nothing and you get
346
+ variety, which is the safer default for a buyer who is still finding out what works.
347
+
324
348
  The body **is** the task payload, so everything about the task rides on the query string: `price=` (or `price=tbd`), `tags=`, `priority=` (lower is polled sooner), `assign_to=` to hand it to one named worker. Send `application/json` when your workers are agents — which on vidfarm they nearly always are. Do not write HTML you do not need.
325
349
 
326
350
  Confirm it landed with `GET /gigs/$CUSTOM_GIG/queue`. **Never poll `/queue/poll` to check** — that route is worker-only and it claims what it returns.
@@ -562,6 +586,26 @@ vidfarm clipper-run mode quick-interactive # save the answer into CLIPPER/run
562
586
  **Quick interactive and full auto + batch review are the two that get used.** Full interactive is the
563
587
  rescue mode for a weak model on an unfamiliar buyer; auto-submit is the narrow opt-in.
564
588
 
589
+ ### Then ask the second question: the clipper dashboard (recommended)
590
+
591
+ **Three of the four modes stop to make a human WATCH A VIDEO, and a terminal cannot play one.** So
592
+ offer the clipper dashboard in the same breath as the run mode, and expect a yes:
593
+
594
+ ```bash
595
+ vidfarm dashboard # a localhost page over the same CLIPPER/ folder — no key, no network
596
+ ```
597
+
598
+ It is the review queue as one page: the cut **playing** and seekable, the buyer's brief rendered
599
+ beside it, the checks as tickable boxes whose unticked items pre-fill the rejection note, the
600
+ shortlist candidates playing side by side (`1`/`2`/`3` to pick), `A`/`C`/`D` to answer, and what is
601
+ submitted and still owed. Every button calls the same `clipper-run` verb, so the page and the
602
+ terminal can never disagree — use both in one session if you like.
603
+
604
+ Record the answer in `MISSION.md` as `dashboard: yes | no`, and never make it a dependency: a
605
+ gigworker who says no, closes the tab or works over SSH loses nothing. `REVIEW_QUEUE.md`,
606
+ `vidfarm clipper-run review` and the `gate` rail are unchanged. Full section:
607
+ `https://vidfarm.cc/agentic-clipper.md` § 3⅘.
608
+
565
609
  **The template pick is the highest-leverage human moment in the whole loop, which is why three of the
566
610
  four modes put a stop there.** A weak model told to author a format from prose hands back something a
567
611
  buyer rejects; the same model handed a *decomposed template to adapt* hands back something they keep
@@ -601,6 +645,8 @@ vidfarm clipper-run start $TASK --gig $GIG --price 0.50 \
601
645
  ```bash
602
646
  vidfarm fork <template_id> && vidfarm pull <forkId> --dir ./work
603
647
  vidfarm harness derive <forkId> --out ./work/HARNESS.md # viral DNA + visual DNA
648
+ # …write ./work/ADAPTATION.md: one row per element, KEEP / REPLACE / CUT + why (see the
649
+ # element audit below). Every REPLACE row is a line on the procurement list.
604
650
  # …write ./work/STORYBOARD.md: the beats, the words, the shot per beat, the audio per beat
605
651
  vidfarm clipper-run plan $TASK --file ./work/STORYBOARD.md
606
652
  ```
@@ -688,7 +734,7 @@ the stage lives on disk under `CLIPPER/`, and **`vidfarm clipper-run` is the onl
688
734
  and writes it**:
689
735
 
690
736
  ```bash
691
- vidfarm clipper-run init # MISSION.md · MACHINES.md · LEDGER.jsonl · EARNINGS.md · REVIEW_QUEUE.md · tasks/
737
+ vidfarm clipper-run init # MISSION.md · MACHINES.md · LEDGER.jsonl · DELIVERED.tsv · EARNINGS.md · REVIEW_QUEUE.md · tasks/
692
738
  vidfarm clipper-run next # WHAT DO I DO RIGHT NOW — per open task, and what is waiting on the human
693
739
  vidfarm clipper-run status # every task, its stage, who it is waiting on
694
740
  vidfarm clipper-run review # the human's list (also written to CLIPPER/REVIEW_QUEUE.md)
@@ -722,6 +768,9 @@ The short version of that file, so you know what you are opting into:
722
768
 
723
769
  1. `vidfarm discover --query "<the client's problem, in their words>" --json` — shortlist three
724
770
  templates. A row carrying `summary`, `keywords` and `promotions` is **already decomposed**.
771
+ **First check what you already sent this buyer** and drop any template, clip or hook that repeats
772
+ it — see [never send one client the same video twice](#never-send-one-client-the-same-video-twice).
773
+ Repetition caught here costs a `jq` call; caught at submit it costs the whole build.
725
774
  2. `vidfarm fork <template_id>` → `vidfarm pull <forkId> --dir ./work`. Not decomposed?
726
775
  `vidfarm decompose <forkId>` on a paid plan, `vidfarm decompose <forkId> --local` on free.
727
776
  Prefer a template that is already decomposed over one you have to decompose yourself.
@@ -731,12 +780,58 @@ The short version of that file, so you know what you are opting into:
731
780
  the client's shared folder → the client's website (`vidfarm capture`) → public raws → free stock
732
781
  → IconScout → your own subscription's generator → billed, last. Same ladder for the voiceover
733
782
  and the music.
734
- 5. Transplant: keep the beat count, the timings, the cut rhythm and the caption identity; replace
735
- every word, every image, every voice line and the track. **Check that every audio `data-src` is
736
- now yours** shipping the source brand's voiceover under your client's captions is the failure
737
- this format is most prone to, and it passes every automated check.
783
+ 5. **Audit every element in the fork before you transplant, and write the verdicts down.** Keep the
784
+ beat count, the timings, the cut rhythm and the caption identity; question everything else, one
785
+ element at a time. See the audit below it is what separates a customized video from a
786
+ re-captioned one.
738
787
  6. `vidfarm qa`, render, read the contact sheet, then the review gate below.
739
788
 
789
+ #### The element audit — the difference between a customized video and a re-captioned one
790
+
791
+ **A decomposed template you forked is somebody else's FINISHED video.** Every element in it was
792
+ chosen for their product, their customer, their face, their joke. Anything you do not deliberately
793
+ re-decide stays theirs, and the buyer watches it. **A cut whose captions changed and nothing else is
794
+ the most common rejected proof on this marketplace** — the buyer is paying for a video about *their*
795
+ thing, and they can tell in three seconds when it is not.
796
+
797
+ So list every element and give each one a verdict: **KEEP** (it is DNA, or it is generic enough to
798
+ be true in the buyer's world too), **REPLACE** (it says something about the source's world), or
799
+ **CUT** (the buyer's story does not have this beat). Write them into `./work/ADAPTATION.md`, one row
800
+ per element.
801
+
802
+ > **KEEP is the verdict that needs a reason. REPLACE is the default.** An element nobody looked at
803
+ > and an element you deliberately kept produce byte-identical HTML — the written ledger is the only
804
+ > thing that tells them apart, and no automated check ever will.
805
+
806
+ ```bash
807
+ vidfarm pull <forkId> --dir ./work --json \
808
+ | jq -r '.layers[] | [.key,(.kind//"?"),(.start|tostring),(.src//"—")] | @tsv' # the inventory
809
+ grep -o 'data-src="[^"]*"' ./work/composition.html | sort -u # every asset the video still loads
810
+ vidfarm captions list ./work # every caption cue, with its words
811
+ ```
812
+
813
+ A `text` layer has no `src`, so it shows as `—` in the inventory. That is not "nothing to decide" —
814
+ it is the words on screen, and it gets a row like everything else.
815
+
816
+ | Element | Default | The catch |
817
+ |---|---|---|
818
+ | **voiceover / TTS, every line** | REPLACE | a fork ships with the source brand's narration. Shipping it under your buyer's captions passes every automated check |
819
+ | **music bed / SFX** | REPLACE | part of the source's identity, and the licence is not yours |
820
+ | **caption words** | REPLACE, every cue | they are the script |
821
+ | **caption identity** — font, size, placement, background | KEEP | this is the visual DNA you forked the template for |
822
+ | **on-screen text that is not a caption** — titles, kickers, labels, prices, stats, end cards | REPLACE or CUT | these are the source's claims. A stale price is worse than no price |
823
+ | **talking-head / actor clips** | REPLACE | a face is a brand. The wrong person recommending the buyer's product is the loudest defect there is |
824
+ | **b-roll** | REPLACE unless generic **and** still true | "a keyboard" survives a subject change; "a barista" does not survive a move to fintech |
825
+ | **product shots, screenshots, UI, mockups** | REPLACE, always | this is literally another company's product on screen |
826
+ | **stickers, icons, cutouts, emoji** | REPLACE when they name a thing, KEEP when purely decorative | a burger sticker in a payroll video is a rejection |
827
+ | **backgrounds and plates** | KEEP the treatment, REPLACE the picture | the grade and the stage are DNA; the photo behind them is content |
828
+ | **logos, wordmarks, @handles, URLs, watermarks** | REPLACE or CUT — **never KEEP** | a competitor's handle on the end card costs the payout and the trust score |
829
+ | **`start`, `duration`, transitions, beat order** | KEEP | the rhythm is the DNA. Retiming is how a weak model flattens a format |
830
+
831
+ Every REPLACE row becomes a line on your procurement list, so the audit runs **before** the sourcing
832
+ pass, not after the build. Report the three counts — kept / replaced / cut — in the proof. The full
833
+ version, with the three tie-break tests, is §3½ of `https://vidfarm.cc/flash-harness.md`.
834
+
740
835
  **Routing a task to a format.** Whichever tier you are, decide what kind of video the task is, then
741
836
  follow the matching format harness from the live index at `https://vidfarm.cc/experimental`. A weak
742
837
  model reads that harness as a **grading rubric** and reaches it by the six steps above; a frontier
@@ -913,6 +1008,86 @@ Add `--json` to any of them for structured output.
913
1008
  client, the invite link, what it wants, its `available_funds`, and today's date. you will revisit
914
1009
  these every loop, and re-deriving gig ids every session is wasted work.
915
1010
 
1011
+ ### Keep the bench full — how a long-horizon loop paces itself
1012
+
1013
+ **The first session finds work. A long-horizon loop has to keep finding it for weeks without burning
1014
+ its rate limit or its buyers' patience.** That is a different problem, and it has three rules. The
1015
+ full apparatus — the algorithm, the state columns, the four cooldown-clearing signals — is § 4 ① and
1016
+ § 4 ② of `https://vidfarm.cc/agentic-clipper.md`. The short version:
1017
+
1018
+ **① Fill your subagent bandwidth, gig by gig, then stop.** Two numbers in `CLIPPER/MISSION.md` bound
1019
+ it: `max_subagents` (build slots — how many task subagents run at once) and `max_tasks_in_flight`
1020
+ (total open tasks, including cuts parked at the human review gate, whose subagent is already dead).
1021
+ Both start at `1`. Then:
1022
+
1023
+ 1. **one** call for the map — `vidfarm gigs work` — never one call per machine;
1024
+ 2. walk only the machines it lit up, best-payer-first, **one at a time**, claiming with
1025
+ `vidfarm gigs claim <gig> --count N` until the slots are full;
1026
+ 3. **stop the walk the moment they are**, and write down which machine you stopped on;
1027
+ 4. when a slot opens — a proof sent, a cut dropped, a task declined — **resume the walk from that
1028
+ machine**, not from the top. Otherwise machines 5 through 20 are never reached.
1029
+
1030
+ > **"do not poll each vending machine one by one" and "walk your machines one at a time" answer
1031
+ > different questions.** *Where is there work?* is one call, `GET /work/available`. *Give me that
1032
+ > work* is `POST /gigs/:id/queue/poll`, which only exists per machine. Read the map once, then walk
1033
+ > what it lit up.
1034
+
1035
+ A polled task is **not exclusively yours until your proof lands** — the atomic claim happens at
1036
+ submit. So keep the bench short and build the oldest task on it first.
1037
+
1038
+ **② Never ask the same machine twice inside 12 hours.** Stamp `last_polled` and
1039
+ `next_poll_after = last_polled + 12h` on every machine you poll, whatever it returned, and let the
1040
+ walk skip anything still inside it. A queue poll is a write against your rate limit, and buyers post
1041
+ in batches — the machine that had nothing an hour ago has nothing now. Four things clear it early:
1042
+ **a new bell for that machine**, **a `/work/available` row with `tasks_in_mailbox: true`** (work
1043
+ handed to you personally — `poll_in_gig: true` does *not* count, it only reports a shared queue's
1044
+ depth), **a proof of yours there approved or paid**, or **the gigworker asking by name**. An empty
1045
+ bench is not one of them.
1046
+ The cooldown governs the *ask*, never the *work*: three tasks claimed today are three tasks built
1047
+ today.
1048
+
1049
+ **③ Sweep the notifications twice a day — that is where new machines come from.** Not every cycle;
1050
+ between sweeps you build. A sweep reads the bells (`vidfarm gigs earn`), clears the cooldown on any
1051
+ machine whose bell is newer than your last poll, **checks the funds on machines you have not joined
1052
+ and joins the ones you can actually serve** (`vidfarm gigs join <url> --wallet 0x…`), and reads
1053
+ `https://gigdesk.cc/api/feeds/vidfarm_clients` for new client projects. A machine you just joined has
1054
+ no cooldown, so it enters the very next walk — that is the whole path from *a bell rang* to *I am
1055
+ building*. A third sweep in a day happens only when the gigworker asks for one.
1056
+
1057
+ ### Use your specialties, and skip what you cannot deliver
1058
+
1059
+ **Most gigworkers carry a few formats they have already tuned** — a prompt file, a template they keep
1060
+ re-adapting, a look they land every time. Write them into `CLIPPER/SPECIALTIES.md` next to a second
1061
+ list: **what you cannot deliver at all** (a named real person on camera, music licensed by id, a
1062
+ language you cannot proof-read, a 3-minute multi-scene render on a weak laptop).
1063
+
1064
+ - **A task that names no format hands the choice to you** — no `format_harness`, no `format`, no
1065
+ `reference_template_id`. Use a specialty. It is the cheapest quality you own, and **Inbound Offers
1066
+ is where it pays best**: no brief, nothing to claim, and a `not_selected` pass costs no reputation.
1067
+ - **A task that names a format beats your specialty, always.** Substituting yours is a rejection, not
1068
+ a service. Reusing a *format* is craft; the element audit still runs and every asset is still
1069
+ sourced for this buyer.
1070
+ - **A task on your CANNOT list gets skipped, and you take the next one.** Never claim it to try,
1071
+ never build a substitute, never stall the cycle over it.
1072
+
1073
+ **On a queue machine, `decline` is the skip button — use it, because almost nobody does:**
1074
+
1075
+ ```bash
1076
+ curl -s -X POST -H "x-api-key: $DOLLARPLATOON_API_KEY" \
1077
+ "https://dollarplatoon.com/api/gigs/$GIG/queue/$TASK_ID/decline" # → {"success": true}
1078
+ ```
1079
+
1080
+ it hides that task from **your** future polls only — other workers still see it, so the buyer loses
1081
+ nothing, and the `declined_count` they see is how they learn a brief is unworkable. it is free,
1082
+ idempotent, and costs no reputation. **without it the same unsuitable task sits at the head of your
1083
+ FIFO and comes back on every future poll of that machine, forever** — which is the most common reason
1084
+ a clipper loop stops finding work in a gig that has plenty. there is no devcli wrapper for it yet.
1085
+
1086
+ then tell the gigworker what you skipped and why: they are the only channel back to the buyer. and
1087
+ if one machine sends two briefs you cannot serve, mark it `skip` in `MACHINES.md` and stop polling
1088
+ it — claiming and abandoning is the expensive way to learn one fact about a buyer. holding a task you
1089
+ never finish scores `unresponsive` at 2×; declining scores nothing.
1090
+
916
1091
  ### Step 1 — join the vidfarm feed
917
1092
 
918
1093
  the feed is the single place where every vidfarm client's vending machine is advertised. join it once and you can see all of them. this is the link:
@@ -1053,8 +1228,12 @@ vidfarm clients run two standing machines and they want different things from yo
1053
1228
 
1054
1229
  **inbound offers is the one worth understanding.** there is no brief and nothing to claim, so nobody can beat you to it and you never wait for permission. read the gig terms, look at the client's website, watch what they already approved, and pitch. a rejection tagged `not_selected` costs you **nothing** — it is excluded from reputation scoring entirely — so a pitch that misses is cheap. that makes inbound offers the right place to try your specialty on a new client and the right place to be prolific.
1055
1230
 
1231
+ **prolific means many distinct bets, never one bet in five costumes.** every pitch you send this buyer sits in the same deck, so a second video that reuses the first one's hook, clip, template or joke reads as one idea sent twice and burns the attention the first one earned. see [never send one client the same video twice](#never-send-one-client-the-same-video-twice) — the only exception is a buyer who asked for a series, in writing.
1232
+
1056
1233
  **custom requests is a commitment.** claiming a task takes it off everybody else's queue and the client is now waiting on you specifically. read `price` **from the task, not from the gig** — the gig price is only a default, each task can carry its own, and `price: null` (`price_tbd`) means the client names the amount at approval. claim what you will actually finish; `unresponsive` is a 2× reputation hit.
1057
1234
 
1235
+ **a polled task you cannot serve gets DECLINED, not held.** `POST /gigs/$GIG/queue/$TASK_ID/decline` hides it from **your** future polls only — other workers still see it, the client keeps the item, and you pay nothing in reputation. it is free and idempotent. **skip it without declining and the same task sits at the head of your fifo and comes back on every future poll of that machine**, which is how a loop concludes a busy gig is empty. see [Use your specialties, and skip what you cannot deliver](#use-your-specialties-and-skip-what-you-cannot-deliver) above.
1236
+
1058
1237
  **before you submit, the gigworker watches the cut and approves it.** this call is the point of no
1059
1238
  return: you cannot unsend a proof, and a `low_quality` rejection is scored on the wallet and shown to
1060
1239
  buyers as a trust score on the public profile. so an agent running a clipper loop builds, QAs and
@@ -1066,6 +1245,11 @@ name. make the stop mechanical rather than remembered: `vidfarm clipper-run gate
1066
1245
  gigs submit …` cannot send an unreviewed cut, because the gate exits non-zero while a human gate is
1067
1246
  open. see **The four run modes** above.
1068
1247
 
1248
+ **there are two pre-submit gates and they answer different questions.** `clipper-run gate` asks *did
1249
+ a human watch this*. `gigs verify-proof` asks *can the buyer actually open it* — see
1250
+ [the sanity check before you send](#the-sanity-check-before-you-send--run-it-every-single-time). run
1251
+ both. a cut the gigworker loved, behind a link that 403s, is still a lost payout.
1252
+
1069
1253
  **when you submit, `task_identifier` is the field people get wrong.** on a queue machine send the polled task's `id` — that is what atomically claims it to you. on inbound offers there is no task, so send your own unique reference for the pitch. **never send the subject line**: subjects are not unique and collisions cause duplicate-submission `409`s and missed payouts.
1070
1254
 
1071
1255
  ```bash
@@ -1077,6 +1261,175 @@ curl -s -X POST "https://dollarplatoon.com/api/gigs/$GIG/proofs" \
1077
1261
 
1078
1262
  put a **playable public MP4 url** in `proofs`. the buyer swipes these in a deck on vidfarm.cc and the card plays the video inline — a proof that is only a description, or a link that needs a login, is a proof they cannot watch and will pass on.
1079
1263
 
1264
+ ### never send one client the same video twice
1265
+
1266
+ **a buyer's deck is one stream, and they swipe it in a sitting.** your second proof does not arrive
1267
+ in a vacuum — it arrives directly under your first one, on a card the same size, from the same name.
1268
+ two videos that share a hook, a template, a source clip, a joke shape or a stock actor do not read as
1269
+ two pitches. they read as **one idea sent twice**, and the cost is worse than a pass: it tells the
1270
+ buyer you are generating rather than making, and it prices every future proof from you accordingly.
1271
+
1272
+ > **the rule, for both machines: no two proofs to the same client repeat the same creative unit,
1273
+ > unless that client asked for repetition. across clients it is softer — reuse what is proven, and
1274
+ > retire what is not.**
1275
+
1276
+ per **client**, not per task and not per day. the unit is the idea, and these are the ways it repeats:
1277
+
1278
+ | what repeated | what the buyer sees |
1279
+ |---|---|
1280
+ | the **source clip / meme / actor** — the same `slugId`, the same face, the same stock shot | "I have seen this exact video" — the loudest repeat there is, and the easiest to avoid |
1281
+ | the **reference template** — the same `reference_template_id` twice | the same beats, the same rhythm, the same reveal, with new words on top |
1282
+ | the **hook** — the same first line, reworded | they only ever read the first line. rewording it does not make it a second hook |
1283
+ | the **joke shape** — same caption frame, same punchline mechanism | funny once |
1284
+ | the **pain named** — the same complaint, restaged | you sent one insight and charged for three |
1285
+ | the **b-roll set** — the same three stock shots recut | the tell that one folder made every video |
1286
+
1287
+ **your STYLE is allowed to repeat. your IDEA is not.** caption identity, colour, pacing, typography,
1288
+ your keyer, your grade — that is the specialty the buyer is hiring, and consistency there is an asset.
1289
+ a gigworker who reads this rule as "vary everything" produces five unrelated videos and no signature.
1290
+ vary the *unit of content*; hold the craft.
1291
+
1292
+ **the exception is real and it must be in writing.** a client who asked for a series, a variant set,
1293
+ an A/B pair, or "five cuts of this one hook" is asking for controlled repetition — then repeating is
1294
+ the deliverable, and varying is the defect. three things count as asking, and nothing else does:
1295
+
1296
+ - the task payload says so — a `series`, `variants`, `batch` or `ab_test` note in the brief
1297
+ - the gig terms or the bell say so
1298
+ - **the buyer's `feedback` on a proof they kept says so.** `"Great hook. More like this one."` is a
1299
+ written request for the series. read every verdict's `feedback`; it is the only channel a buyer has
1300
+ to steer you, and it is where permission to repeat comes from
1301
+
1302
+ **never infer the exception from a payout.** an approval means that video worked, not that a second
1303
+ copy of it will. absent a written ask, ship one, and let their feedback ask for the next.
1304
+
1305
+ #### across clients it is softer — a great raw is an asset, a mid one is a tell
1306
+
1307
+ same client is a hard rule. **across clients it is a preference, and the thing that decides it is not
1308
+ novelty, it is quality.** a raw that reliably lands is exactly the kind of thing you should reuse —
1309
+ that is what a proven raw *is*, and refusing to reuse it in the name of variety is you throwing away
1310
+ the only edge you have. reuse it across five buyers who each see it once and it is five good videos.
1311
+
1312
+ **what is not fine is running a mid raw into the ground.** the failure is specific and it always
1313
+ looks the same from the outside: one clip appears in most of your recent deliveries, it was never
1314
+ better than okay, and now your whole book has the same face in it. **diversity across clients is the
1315
+ default; reuse is the exception you earn.**
1316
+
1317
+ > **the reuse budget is set by the verdicts a raw has already collected, not by how good it felt to
1318
+ > you when you cast it.**
1319
+
1320
+ `DELIVERED.tsv` carries a `verdict` column for exactly this, so the budget is readable:
1321
+
1322
+ | what the raw has collected | budget |
1323
+ |---|---|
1324
+ | **nothing yet** — never delivered | **one use.** ship it and find out. it is unproven, whatever you think of it |
1325
+ | **an approval, no passes** | **reuse it freely.** it is proven. carry it to other buyers, one use each |
1326
+ | **passed on twice, no approval** | **retire it.** two buyers said no. it is mid, and the third will say no too |
1327
+ | **mixed** | it is a fit question, not a quality one. reuse it only where the pain genuinely matches, never to fill a slot |
1328
+
1329
+ **the raws catalog is public and shared, which makes this sharper than it looks.** you cast from
1330
+ `vidfarm public-raws` and so does every other clipper on this marketplace, so a popular clip is not
1331
+ only repeated by *you* — the buyer may have already seen it this week from somebody else. a raw
1332
+ nobody has worn out is worth more than a raw you happen to like.
1333
+
1334
+ **one number, checked with a `cut`:** if the same `source_clip` is in more than about **3 of your
1335
+ last 20 deliveries**, that is a signature you did not choose. either it has the approvals to justify
1336
+ it, or you are reaching for the same folder because it is nearby.
1337
+
1338
+ ```bash
1339
+ cut -f5 CLIPPER/DELIVERED.tsv | tail -20 | sort | uniq -c | sort -rn | head # your recent look
1340
+ awk -F'\t' '$5=="hangover-dog"{print $1, $8}' CLIPPER/DELIVERED.tsv # who got it, and how it went
1341
+ ```
1342
+
1343
+ **when the shelf feels exhausted, change the PAIN, not the clip.** that feeling is almost always the
1344
+ 🟢 rights tier biting — the safe shelf is smaller than the full one, and a clipper working one niche
1345
+ hits its edge in a month. the way out is a different complaint cast fresh, never a third outing for a
1346
+ clip that has already done its work.
1347
+
1348
+ **make it mechanical, because a long loop forgets what it already sent.** `LEDGER.jsonl` already
1349
+ records `gig_id`, `template_id` and `harness` on every submit, so the template repeat is one line:
1350
+
1351
+ ```bash
1352
+ GIG=GIG_01M…
1353
+ jq -r 'select(.gig_id=="'"$GIG"'" and .status=="submitted")
1354
+ | [.ts, .harness, .template_id] | @tsv' CLIPPER/LEDGER.jsonl
1355
+ ```
1356
+
1357
+ the ledger does not hold the creative key — the clip, the hook, the pain — so keep one append-only
1358
+ row per delivery beside it, and **grep it before you plan, not before you submit**. a repeat caught
1359
+ at submit time is a whole build wasted:
1360
+
1361
+ ```bash
1362
+ # CLIPPER/DELIVERED.tsv — one row per proof, tab separated
1363
+ # gig_id proof_id harness template_id source_clip hook pain verdict
1364
+ printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
1365
+ "$GIG" "$PROOF_ID" meme-recaption template_019fd… hangover-dog \
1366
+ "10 tabs since 7pm" "cannot pick a restaurant" pending >> CLIPPER/DELIVERED.tsv
1367
+
1368
+ grep -c "^$GIG" CLIPPER/DELIVERED.tsv # how many you have sent this buyer
1369
+ cut -f1,5,6,7 CLIPPER/DELIVERED.tsv | grep "^$GIG" # what you already used on them
1370
+ ```
1371
+
1372
+ **stamp the verdict back when the buyer rules, or the file only ever answers half the question.** a
1373
+ row written at submit says `pending`, and a log that is all `pending` says every raw you own is
1374
+ unproven forever — which is exactly the state in which a mid clip gets reused. use the buyer's own
1375
+ tag: `approved`, `not_selected`, `low_quality`. `not_selected` is a **fit** verdict, not a quality
1376
+ one, so one of them retires nothing; two on the same clip with no approval anywhere does.
1377
+
1378
+ **on inbound offers this rule decides whether prolific pays.** that machine rewards volume — a
1379
+ `not_selected` costs nothing, so pitching often is correct. volume of *distinct bets* is the thing
1380
+ that works. volume of one bet in five costumes reads as spam from the second card onward, and the
1381
+ buyer stops opening your cards, which is the only outcome on this marketplace you cannot recover from
1382
+ by making a better video.
1383
+
1384
+ **on custom requests, the brief is the boundary.** two tasks from the same buyer that ask for
1385
+ similar things are still two videos that land next to each other. deliver each brief exactly, and
1386
+ take the variety out of the elements the brief left free.
1387
+
1388
+ ### the sanity check before you send — run it every single time
1389
+
1390
+ **one command, no api key, and it is the last thing you do before `gigs submit`:**
1391
+
1392
+ ```bash
1393
+ vidfarm gigs verify-proof \
1394
+ --proof https://…/final-watermarked.mp4 \
1395
+ --clean-master ./final-clean.mp4
1396
+ ```
1397
+
1398
+ it exits non-zero on any failure, so write the submit as a chain and a broken proof cannot physically be sent:
1399
+
1400
+ ```bash
1401
+ vidfarm clipper-run gate $TASK \
1402
+ && vidfarm gigs verify-proof --proof $PROOF_URL --clean-master ./final-clean.mp4 \
1403
+ && vidfarm gigs submit $GIG --task $TASK --proof $PROOF_URL --clean-master ./final-clean.mp4
1404
+ ```
1405
+
1406
+ `gigs submit` **runs the same check itself and refuses to send a proof that fails it** (`--skip-verify` overrides, at your own risk). the standalone command exists so you can check *before* you claim the moment is right, and so a share-link worker with no account can check too.
1407
+
1408
+ **why this is not optional.** you cannot unsend a proof, and the buyer opens it days later, on their machine, with none of your sessions. the two ways a finished video still loses the payout are both mechanical:
1409
+
1410
+ **① the link does not load for them.** the check fetches every url in `proofs` the way a stranger's browser would — no key, no cookie, follow redirects — and fails on:
1411
+
1412
+ | what it catches | why it kills the payout |
1413
+ |---|---|
1414
+ | `403` on the object | you uploaded it, the bucket never made it public. your own browser has the session; theirs does not |
1415
+ | `404` | the upload did not land at the key you think it did |
1416
+ | **an expiring presigned url** | `X-Amz-Signature=…`, a CloudFront `Signature`+`Expires` pair, an Azure SAS. **a presigned url is for the UPLOAD, never for the proof** — read access dies on a clock and the buyer reviews later |
1417
+ | a `200` whose body is XML or HTML | the classic s3 `AccessDenied` body served with a `video/mp4` header. it looks fine in a `curl -I` and plays nothing |
1418
+ | `localhost`, `192.168.…`, `http://` | only reachable from your own desk, or blocked as mixed content in the deck |
1419
+ | Drive / Dropbox / WeTransfer / Notion links | they serve a sign-in page to a stranger, and half of them expire |
1420
+ | 0 bytes, or a few hundred | the export or the upload stopped early |
1421
+
1422
+ it reads the **first bytes**, not just the headers, so a file that claims `video/mp4` and is really an error page still fails. **a durable public url passes** — which is exactly what `vidfarm gigs upload <file>` hands you.
1423
+
1424
+ **② the two halves are the wrong way round.** it also checks how you split `proofs` against `private_note`, and this half is a **recommendation, not a law**:
1425
+
1426
+ - **the recommended shape:** the **watermarked** cut in `--proof`, the **clean master** in `--clean-master` (sealed into `private_note`). see the next section.
1427
+ - **submitting the unwatermarked final in `proofs` itself is allowed** — some workers and some briefs want it — but it has to be a decision, not an accident. with no note at all you get a warning; pass `--clean-in-proof` to say you meant it and the warning becomes an OK line.
1428
+ - **two things do fail**, because neither can be intentional: a `--clean-master` file that is missing or 0 bytes on disk (caught *before* anything uploads), and a private note that points at a url you also published in `proofs` — the sealed half then hands the buyer nothing they did not already have.
1429
+ - it warns when a proof url is *named* like the master (`final-clean.mp4`, `no-watermark.mp4`) while you are also sealing one. that is usually the two files swapped at the last step.
1430
+
1431
+ `--strict` makes the warnings fail too. `--json` gives your agent `{ok, may_submit, failures, warnings, checks, probes}`.
1432
+
1080
1433
  ### watermark the proof, hold the clean master
1081
1434
 
1082
1435
  **the devcli does this whole four-step dance in one call:**
@@ -1090,7 +1443,8 @@ vidfarm gigs submit $GIG --task $TASK \
1090
1443
 
1091
1444
  `--clean-master` presigns, uploads the file to dollarplatoon's own s3, and puts that url at the top
1092
1445
  of the private note. It then **verifies `private_note_locked` came back** and warns loudly if it did
1093
- not — because you cannot patch a note onto a proof afterwards. `vidfarm gigs upload <file>` does the
1446
+ not — because a note cannot be patched onto a proof once it is submitted (withdraw it and edit the
1447
+ draft, which works only until the buyer rules). `vidfarm gigs upload <file>` does the
1094
1448
  upload on its own if you want the url first. The manual version follows.
1095
1449
 
1096
1450
  **submit the watermarked cut in `proofs`. put the clean master in `private_note`.** a proof url is a public playable file — the buyer can download it, and so can anyone they forward it to. a buyer who already holds your clean master has nothing left to buy. `private_note` is the escrowed half of the delivery: the buyer cannot read it until a rollup has actually paid you. that is what makes the vending machine pay.
@@ -1154,7 +1508,7 @@ curl -s -X POST "https://dollarplatoon.com/api/gigs/$GIG/proofs" \
1154
1508
  "private_note_locked": true } }
1155
1509
  ```
1156
1510
 
1157
- `private_note_locked: true` in the response is your confirmation that the note was stored and is being withheld. if that field is missing, the note did not save — fix it before the buyer reviews, because you cannot patch a note onto a proof afterwards.
1511
+ `private_note_locked: true` in the response is your confirmation that the note was stored and is being withheld. if that field is missing, the note did not save — fix it before the buyer reviews. a submitted proof's note cannot be patched, so the repair is `vidfarm gigs withdraw`, then `edit-draft`, then `send`. that route closes the moment they rule on it.
1158
1512
 
1159
1513
  **keep `proofs` playable and watermarked.** the buyer swipes a deck on vidfarm.cc and the card plays the first url inline. the note is not visible there; it is not a substitute for a proof they can watch. a proof whose only watchable asset is locked reads as no proof at all.
1160
1514
 
@@ -1174,6 +1528,54 @@ that `GET` returns the proof **flat** — read `.paid_out_at`, not `.proof.paid_
1174
1528
 
1175
1529
  **never put the clean master in the task's `upload_link` folder.** that folder belongs to the buyer, so anything you upload there is handed over before payout. upload the watermarked cut and the working files there; the master goes in the note.
1176
1530
 
1531
+ ### drafts, and the undo — a submitted proof is not one-way
1532
+
1533
+ a proof has two halves, and for a long time this document only described the second one. the first
1534
+ one is a **draft**: a proof that is saved, holds its task, and has been delivered to nobody.
1535
+
1536
+ ```
1537
+ draft ──send──▶ pending ──the buyer rules──▶ approved / rejected
1538
+ ▲ │
1539
+ └───withdraw───────┘ only while it is pending, and never once a rollup carries it
1540
+ ```
1541
+
1542
+ ```bash
1543
+ vidfarm gigs draft $GIG --task $TASK --proof https://…/wip.mp4 # save, send nothing
1544
+ vidfarm gigs drafts $GIG # what is still unsent
1545
+ vidfarm gigs edit-draft $GIG $PROOF --proof https://…/final.mp4 --private-note "…"
1546
+ vidfarm gigs send $GIG $PROOF # now the buyer sees it
1547
+ vidfarm gigs withdraw $GIG $PROOF # THE UNDO — take it back
1548
+ vidfarm gigs discard $GIG $PROOF # delete a draft, free its task
1549
+ ```
1550
+
1551
+ **a draft is invisible.** no review clock, no `proof_webhook`, no auto-approval, and it is not
1552
+ counted in `proofs_submitted`. the buyer's dashboard filters it out and their `GET` on it answers
1553
+ `404`. nothing about it reaches your reputation until you send it.
1554
+
1555
+ **a draft still claims its task.** that is deliberate — two workers cannot both draft the same task
1556
+ and then both try to send it — so a draft counts against your `max_open_tasks` cap and your rate
1557
+ limit while it sits there. an abandoned draft blocks its own task until you `discard` it.
1558
+
1559
+ **withdraw is the undo, and it stops where the buyer's judgment starts.** a `pending` proof goes back
1560
+ to draft, the review clock stops, and the buyer can no longer see it. an `approved` or `rejected`
1561
+ proof answers `409`: the verdict is theirs, and withdrawing a rejection would erase it from the
1562
+ record it belongs to. anything already inside a rollup, or carrying `paid_out_at`, is final.
1563
+
1564
+ **the price is snapshotted at `send`, not at `draft`.** a draft can sit for days while the buyer
1565
+ reprices the task, so the number that pays is the one showing when you send. re-sending after a
1566
+ withdrawal restarts the review clock from zero and fires the webhook again with
1567
+ `"resubmitted": true` — but `proofs_submitted` and your reputation are credited once, on the first
1568
+ send.
1569
+
1570
+ **what this does and does not change.** a note cannot be patched onto a **submitted** proof — that
1571
+ much was always true — but you are not stuck with a bad one: withdraw it, `edit-draft` it, send it
1572
+ again. the undo is a repair for the wrong file or a missing note. it is not a licence to submit work
1573
+ nobody looked at, because the buyer may open it within the minute and their verdict closes the door.
1574
+
1575
+ **the one place this genuinely is one-way:** a share-link submission
1576
+ (`POST /public/submit-proof`). there is no account behind it, so there is nothing to authenticate a
1577
+ withdrawal with. check that one before you send it.
1578
+
1177
1579
  ### the fast path for an agent — `vidfarm gigs`, with your own key
1178
1580
 
1179
1581
  you do **not** need a vidfarm account for any of this. install the devcli, export your own dollarplatoon key, and the whole worker loop is one command to start and eight to run:
@@ -1190,8 +1592,13 @@ vidfarm gigs check <gig-id|join-url> # CAN THIS ONE PAY ME? do it before you c
1190
1592
  vidfarm gigs join <invite-url> --wallet 0x… # the url from the feed entry carries the token
1191
1593
  vidfarm gigs work # work waiting across every machine you joined (paged)
1192
1594
  vidfarm gigs claim <gig-id> # claim ONE off the FIFO queue — keep the task id
1595
+ vidfarm gigs verify-proof --proof <url> --clean-master ./final-clean.mp4
1596
+ # LAST STEP BEFORE SUBMIT — does the link even load for them?
1193
1597
  vidfarm gigs submit <gig-id> --task <task-id> \
1194
1598
  --proof https://…/final-watermarked.mp4 --clean-master ./final-clean.mp4
1599
+ vidfarm gigs draft <gig-id> --task <task-id> --proof <url> # save it, send nothing
1600
+ vidfarm gigs send <gig-id> <proof-id> # send the draft — the price is snapshotted HERE
1601
+ vidfarm gigs withdraw <gig-id> <proof-id> # THE UNDO — pending only, never after their verdict
1195
1602
  vidfarm gigs proof <gig-id> <proof-id> # did it save the note? have i been PAID?
1196
1603
  vidfarm gigs earnings # your rollups + totals
1197
1604
  vidfarm gigs mine # every gig you have a mailbox in
@@ -1211,10 +1618,15 @@ vidfarm clipper-run gate <task-id> # may i submit? non-zero exit while a hum
1211
1618
  `vidfarm gigs` talks to the network; `vidfarm clipper-run` writes files under `CLIPPER/`. keep them
1212
1619
  straight: the first one is money, the second one is memory.
1213
1620
 
1214
- **four rules the CLI now enforces or surfaces for you, and they still apply:**
1621
+ **five rules the CLI now enforces or surfaces for you, and they still apply:**
1215
1622
 
1216
1623
  - `--task` is the **polled task's id**, never the subject line, and the proof must be a playable
1217
1624
  public url.
1625
+ - `gigs submit` **runs `gigs verify-proof` first and refuses to send a proof that fails it** — a dead
1626
+ link, a 403 bucket, an error page served as `video/mp4`, an expiring presigned url, a clean-master
1627
+ file that is not on disk. It also warns when the public half and the sealed half look swapped. Run
1628
+ the check on its own whenever you like; it needs no key. `--skip-verify` overrides it, and the only
1629
+ good reason to reach for that is a host the checker cannot reach but the buyer can.
1218
1630
  - `gigs claim` claims **one** task by default. Claiming takes a task off everybody else's queue and
1219
1631
  the client is now waiting on you specifically; `unresponsive` is a 2× reputation hit. Pass
1220
1632
  `--count N` only when you mean it.
@@ -1223,9 +1635,10 @@ straight: the first one is money, the second one is memory.
1223
1635
  was created, so adding one later does not redirect a payout already in flight.
1224
1636
  - `gigs submit --clean-master <file>` uploads that file to dollarplatoon's own s3 and seals the url
1225
1637
  in the proof's `private_note`, then **checks `private_note_locked` came back in the response** and
1226
- says so loudly if it did not. You cannot patch a note onto a proof afterwards, so a silent miss
1227
- there means you handed over nothing. Submitting with no note at all gets a warning too — if the
1228
- url in `--proof` is your clean master, the buyer has it before paying.
1638
+ says so loudly if it did not. A note cannot be patched onto a proof once it is submitted, so a
1639
+ silent miss there means you handed over nothing `gigs withdraw` is how you repair it, and it
1640
+ works only while the buyer has not ruled. Submitting with no note at all gets a warning too — if
1641
+ the url in `--proof` is your clean master, the buyer has it before paying.
1229
1642
 
1230
1643
  ### the task gave you a folder link — work it from the terminal
1231
1644
 
@@ -1281,6 +1694,8 @@ dollarplatoon rejects a Bearer-only request with `401 {"error":"Missing x-api-ke
1281
1694
 
1282
1695
  when the gigworker says **"check available work"**, **"check the vending machines for tasks"**, **"any work today?"** or anything similar, the ai agent must call `GET /work/available`. do not poll each vending machine one by one. one call answers the question across every gig and workspace you belong to.
1283
1696
 
1697
+ **this is the MAP, not the claim, and the difference matters for a long-horizon loop.** `/work/available` answers *where is there work* for every machine at once. *give me that work* is `POST /gigs/:id/queue/poll`, and that route only exists per machine — so you read the map once, then walk **only** the machines it lit up, one at a time, until your build slots are full. that walk, its 12-hour per-machine cooldown, and where to resume it are in [Keep the bench full](#keep-the-bench-full--how-a-long-horizon-loop-paces-itself) above.
1698
+
1284
1699
  ```bash
1285
1700
  # all gigs / all workspaces at once
1286
1701
  curl -H "Authorization: Bearer $GIGDESK_API_KEY" \
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@officexapp/vidfarm-devcli",
3
- "version": "0.21.58",
3
+ "version": "0.21.60",
4
4
  "description": "Local bridge for the Vidfarm Trackpad Editor. `vidfarm serve <template_id>` boots the FULL editor on localhost (disk-backed records/storage, free in-process render); edit composition.html on disk (Claude Code, Codex, etc.) and the browser live-morphs it.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,6 +16,7 @@
16
16
  "dist/src/devcli/captions.js",
17
17
  "dist/src/devcli/clip-store.js",
18
18
  "dist/src/devcli/clips.js",
19
+ "dist/src/devcli/clipper-panel.js",
19
20
  "dist/src/devcli/clipper-run.js",
20
21
  "dist/src/devcli/composition-edit.js",
21
22
  "dist/src/devcli/consult.js",
@@ -34,6 +35,7 @@
34
35
  "dist/src/devcli/plate-key.js",
35
36
  "dist/src/devcli/port-utils.js",
36
37
  "dist/src/devcli/process-scan.js",
38
+ "dist/src/devcli/proof-verify.js",
37
39
  "dist/src/devcli/qa-check.js",
38
40
  "dist/src/devcli/harness.js",
39
41
  "dist/src/devcli/sequence.js",
@@ -115,6 +117,9 @@
115
117
  "test:qa": "node --import tsx --test test/qa-check.test.ts",
116
118
  "test:engine-globals": "node --import tsx --test test/engine-globals.test.ts",
117
119
  "test:clipper-run": "node --import tsx --test test/clipper-run.test.ts",
120
+ "test:clipper-panel": "node --import tsx --test test/clipper-panel.test.ts",
121
+ "test:proof-verify": "node --import tsx --test test/proof-verify.test.ts",
122
+ "test:gigs-lifecycle": "node --import tsx --test test/gigs-proof-lifecycle.test.ts",
118
123
  "test:update-check": "node --import tsx --test test/update-check.test.ts",
119
124
  "test:studio-brand": "node --import tsx --test test/studio-brand.test.ts",
120
125
  "test:stickers": "node --import tsx --test test/sticker-pack.test.ts test/plate-key.test.ts",