Review steps

The running jobjob_7Hq2 · working · $49.00 held

A review step hardens the work before it, or extends it. Adversarial lenses attack it and flag it back; affirmative lenses propose additions and keep the ones that hold.

A review answers one question: did the work hold up before anyone saw it?

grow/review.ts
    translate: 'ai',
    harden: { review: 'adversarial', lenses: ['meaning', 'terms'], rounds: 2 },
Run
npx services.dev check
magic values: none
  steps   translate · ai → harden · ai · adversarial · 2 lenses

On the Service

KeyWrittenLeft outDoes
reviewReview'adversarial'How the AI checks every job before it ships: 'adversarial', or 'affirmative' for creative work.

On a review step

KeyWrittenLeft outDoes
reviewReviewrequired'adversarial' attacks the work and flags it back; 'affirmative' proposes additions and keeps the ones that hold.
of<step>the step beforeThe step reviewed.
lensesstring[]oneOne AI reviewer per lens, in parallel.
roundsnumber3Flag the work back and review again at most this many times, inside the AI budget.
byRoleWordnoneA person with this role reviews instead of AI.
exhausted<step> | <end>the job stops at $0Where still-flagged work goes once rounds run out: a step (a person, with review/<step>.json as their packet) or an end.

Leave reviews out, and the last AI step is reviewed once, adversarially: draft · ai → review · ai · adversarial. Write a review step to choose its lenses, its rounds and where it sits. review: 'affirmative' on the Service makes the default one extend instead.

Each lens is one AI reviewer, and the lenses run at once. A finding over the bar flags the work back to the step it reviews, the AI redoes it with the findings as feedback, and the review runs again, up to rounds times:

Call
→ POST /localization {"strings":"strings.json","listing":"listing.txt","to":"de","max_usd":49,"key":"flag-once","metadata":{"sandbox":{"review":"flag_once"}}}
magic values: metadata.sandbox.review = flag_once
  record  terms · ai | strings · ai | listing · ai | qa · ai · adversarial · 3 lenses · flagged | strings · ai · redo | qa · ai · adversarial · 3 lenses · pass

Each round writes review/<step>.json to the job: the findings, a signal per lens, and the verdict. The next person at the job reads it in their packet. Each lens keeps its own find rate across jobs, and an eval scores it against real outcomes before a change ships: Quality.

Run
curl http://localhost:8787/owner/jobs/job_7Hq6/export   # review/qa.json, round 0
magic values: metadata.sandbox.review = flag_once
{
  "step": "qa",
  "of": "strings",
  "kind": "adversarial",
  "round": 0,
  "lenses": [
    "placeholders",
    "length",
    "tone"
  ],
  "findings": [
    {
      "lens": "placeholders",
      "severity": "high",
      "says": "Simulated: placeholders found a problem in strings."
    }
  ],
  "signals": {
    "placeholders": true,
    "length": false,

"Yes, and." Each lens proposes an addition, an adversarial pass judges each one, and only the additions that survive are folded into the work:

services/store-copy.ts
    copy: 'ai',
    // Yes, and: each lens proposes an addition, and only the ones that survive an adversarial pass are folded in.
    extend: { review: 'affirmative', lenses: ['examples', 'keywords'] },
Call
→ POST /store-copy {"app":"a budgeting app for couples","to":"de","max_usd":29,"key":"yes-and","metadata":{"sandbox":{"review":"flag_once"}}}
magic values: metadata.sandbox.review = flag_once
  record  copy · ai | extend · ai · affirmative · 2 lenses · pass · 1 folded

Every round spends from the job's AI budget. With exhausted, work that's still flagged goes to a step you name, such as a person with the review as their packet, or to an end. Without it, the job stops and the buyer pays $0.

by: '<role>' makes a person the reviewer instead of AI. Put reviews before anyone signs: check fails review_after_attest when a person would attest work no review has passed.

No call of its own: it changes what the job carries, on every surface that reads one.

Events: review.done.

Operations has every column of every row.

check gateWhy
review_after_attestA person attests work no review has passed: the review runs after the signature.
WrittenWhat TypeScript says
review: 'none', price: 49Type '"none"' is not assignable to type 'Review | undefined'.
deliver: { draft: 'ai', examine: { review: 'adversarial', exhausted: 'nobody' } }, price: 49Type '"nobody"' is not assignable to type '"draft" | "examine" | undefined'.

The lines that use it in the example brands, as their files write them, and what check read aloud for each file.

legal · services/contract-review.ts · 16 lines
    attack: { review: 'adversarial' },
npx services.dev check · captured/legal-walk.txt
services/contract-review.ts · 16 lines · $99 per job, within 48 hours, charged on acceptance.
  steps   consent · client · consent → flag · ai → attack · ai · adversarial → advise · attorney · client · stamped · 2-item checklist → send · ai

The legal example runs every one of its files, captured.

tax · services/amended-return.ts · 22 lines
    check: { review: 'adversarial', lenses: ['what changed', 'numeric tie-out'] },
npx services.dev check · captured/tax-check.txt
services/amended-return.ts · 22 lines · $900 per job, within 30 days, charged when file or aar is accepted.
  steps   compute · code · cites depreciation and carryforward schedules → draft · ai · cites the workpapers and the records the organizer took → check · ai · adversarial · 2 lenses → prepare · preparer · * · 1-item checklist → sign · signer · * · stamped in the paid-preparer block → authorize · owner · sign → file · IRS and states, unless a partnership → aar · IRS · Form 8082, for a partnership · emits k1.adjusted

The tax example runs every one of its files, captured.