One submission per element

The running jobjob_7Hq2 · working · $49.00 held

each sends one submission per element of a list and keeps one receipt for each. The lead goes first, and the linked ones wait for its acceptance.

each answers one question: how do several filings that belong together go out?

services/linked-filing.ts
    file: {
      submit: 'http://localhost:8787/registry',
      to: 'the registry',
      receipt: 'receipts',
      each: { of: 'filings', lead: filing => (filing as { name: string }).name === 'parent.pdf' },
    },

On a submit step

KeyWrittenLeft outDoes
each{ of: <list input> | <list output>; lead?: (element) => boolean }noneFan out: one submission and one receipt per element of a list. lead goes first; the rest wait for its acceptance.
receipt<text output>requiredThe output field the receipt fills: its number, or the receipt's id; a list with each. price.release can name this step, or <step>.accepted.

of names a list, an input or an output. Each element is one submission with its own receipt. lead picks the element that goes first, and the rest wait until the outside system accepts it, the way linked filings must:

Call
→ POST /linked-filing {"filings":["schedule-a.pdf","parent.pdf","schedule-b.pdf"],"max_usd":90,"key":"linked"}
magic values: none
← job_7Hq2 · delivered · $90.00 charged
  record  prepare · ai | review · ai · pass | file · the registry · 3 accepted
  receipts ["rcp_7Hq3","rcp_7Hq2","rcp_7Hq4"]
  1 · rcp_7Hq2 · accepted · at 2026-10-25T14:02:11.000Z
  0 · rcp_7Hq3 · accepted · at 2026-10-25T14:02:11.000Z · lead rcp_7Hq2
  2 · rcp_7Hq4 · accepted · at 2026-10-25T14:02:11.000Z · lead rcp_7Hq2

The parent is element 1, so its receipt, rcp_7Hq2, comes first in time. The receipts list in the output keeps the order of the elements, and every linked receipt names its lead.

A submit step sends its whole batch. A rejection in one element never holds back the others: they file on time, and the rejection routes the job once the batch is out, by its code, the way a single submission's does (Sending to outside systems). Each element counts its own rejections. A route written { to, items } narrows the repair's ask to what that element's code names: items is (job, element) => AskItem[].

The charge waits for the step's receipts. With price.release set to '<step>.accepted', it waits until every one of them is accepted.

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

Objects: rcp_. Events: submission.sent, receipt.accepted, receipt.rejected, receipt.timed_out.

Operations has every column of every row.

check gateWhy
release_unprovenprice.release names no step that runs.

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

tax · services/annual-return.ts · 45 lines
    file: {
      submit: efile, to: 'IRS and states', receipt: 'receipts', each: { of: 'jurisdictions', lead: j => j === 'US' },
      rejected: { ein_mismatch: { to: 'organizer', items: reask.ein_mismatch }, schedule_missing: { to: 'organizer', items: reask.schedule_missing }, math: 'draft', '*': 'prepare' }, perfect: '10d',
    },
    extend: { routed: true, submit: extension, to: 'IRS and states', receipt: 'extensions', each: { of: 'jurisdictions', lead: j => j === 'US' } },
npx services.dev check · captured/tax-check.txt
services/annual-return.ts · 45 lines · $1,800 per job, filed 5 days before its deadline, 20% off if late, or we pay the penalty and its interest, up to $5,000, after we ask the IRS to take it off, charged when file is accepted.
  steps   consent · owner · consent · §7216, may disclose to a preparer outside the US and a lender you name → organizer · owner · upload → compute · code · cites depreciation and carryforward schedules → draft · ai · cites the workpapers and the records the organizer took → check · ai · adversarial · 3 lenses → sign · signer · * · stamped in the paid-preparer block · 3-item checklist → authorize · owner · sign · Form 8879-CORP or 8879-PE → file · IRS and states → prepare · preparer · * · 1-item checklist · routed → tentative · code · cites the year as the ledger stands, less the estimates paid · routed → pay · Treasury and states · routed → extend · IRS and states · routed

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

The return routes each state's rejection on its own. In the example's year, New York rejects the return for its account number. The federal return, California and New Jersey stay filed, the organizer asks for New York's number alone, and the refiled return keeps its first filing time inside perfect. What each branch does runs two states rejecting at once:

captured/tax-years.txt · magic values: owner.email = signs@example.test, metadata.sandbox.asks = {"organizer.books":"after 160d","organizer.assets":"waive","organizer #2":"after 2d","w9":"after 19d"}, metadata.sandbox.outside = {"reject":{"file.US-NY":["ein_mismatch"]}}, metadata.sandbox.events = { notice.received: { at: 2027-11-14T15:00:00Z, data: { notice, reply_by, tax_years } } }
$ npx services.dev tick 1y --test-clock tc_7Hq4 --market normal
  2027-07-11 14:00:00  job_4Tx3  file · US 1120 accepted → US-CA 100 accepted, US-NJ CBT-100 accepted, US-NY CT-3 rejected ein_mismatch → organizer
  2027-07-11 14:00:00  job_4Tx3  ask organizer · signs@example.test · 1 item · 1 open (ny_account)
  2027-07-13 14:00:00  job_4Tx3  ask organizer · ny_account answered · done
  2027-07-13 14:00:00  job_4Tx3  file · US-NY CT-3 accepted (keeps 2027-07-11)