A simulated market

The running jobjob_7Hq2 · waiting · on approval · $49.00 held

Seed simulated members in every Pool, set how hard work is to fill, and watch the market run through the real gate before anyone joins. Every act they take is labeled simulated.

How do you see your marketplace work before anyone has joined it?

dev takes two flags. --members N seeds N simulated members in each Pool, from the Pool's own join shape. --market sets how hard work is to fill:

--marketThe members it seeds
tightask more than Tasks post at, so the fill ladder climbs before a claim
normal, the defaultask what Tasks post at, and pass, decline, send back and contest at set rates
flushask less than Tasks post at, so a Task fills at the first rung
Run
npx services.dev dev --members 12 --market tight --no-try
magic values: client.email = signs@example.test
  attorneys           http://localhost:8787/attorneys · join at /attorneys/join, or npx services.dev signers add attorneys <email>
  verifier            vt_test_7Hq2 · the only writer of verified facts, at POST /<network>/signers/:id/verify
  market              tight · 12 simulated signers in attorneys, each act labeled simulated · the fill ladder climbs before a review is claimed

Simulated members claim, pass, send back, decline and contest through the same gate a person's act goes through, so every branch your Service has runs without a person. Each act they take is labeled simulated: true on the record, in its events and on every answer. Every roll is fixed by the member, the Task and the act, so a market writes the same record, act for act, every run, and a captured walk never drifts.

One job from the legal example, ordered into each market, then six hours on the clock. tight climbs two rungs before a member claims it:

Call
→ POST /matters {"service":"contract-review","contract":"lease.pdf","client":{"name":"Ada Lovelace","email":"signs@example.test"},"client_region":"US-CA","max_usd":99,"key":"tight"}, then six hours
magic values: client.email = signs@example.test
  14:02 · task.posted · tsk_7Hq2 · $50.00 · dispatch cascade
  16:02 · task.raised · tsk_7Hq2 · $55.00 · raise 10% 2h · funded by the brand
  16:02 · task.offered · tsk_7Hq2 · mbr_7Hq3 · cascade
  18:02 · task.widened · tsk_7Hq2 · opened reviewer · widen 4h
  18:02 · task.offered · tsk_7Hq2 · mbr_7Hq4 · cascade
  18:02 · task.claimed · tsk_7Hq2 · mbr_7Hq4 · simulated
  18:02 · step.committed · advise · person · bar admission · US-CA · mbr_7Hq4 · simulated
  18:02 · pay.accrued · mbr_7Hq4 · attest · $55.00 · $5.00 of it the brand's raise · simulated
← job_7Hq2 · delivered · flags.pdf · memo.pdf · $99.00 held

normal raises once, then widens:

Call
→ POST /matters {"service":"contract-review","contract":"lease.pdf","client":{"name":"Ada Lovelace","email":"signs@example.test"},"client_region":"US-CA","max_usd":99,"key":"normal"}, then six hours
magic values: client.email = signs@example.test
  14:02 · task.posted · tsk_7Hq2 · $50.00 · dispatch cascade
  14:02 · task.offered · tsk_7Hq2 · mbr_7Hq2 · cascade
  16:02 · task.raised · tsk_7Hq2 · $55.00 · raise 10% 2h · funded by the brand
  16:02 · task.offered · tsk_7Hq2 · mbr_7Hq2 · cascade
  18:02 · task.widened · tsk_7Hq2 · opened signer · widen 4h
  18:02 · task.offered · tsk_7Hq2 · mbr_7Hq3 · cascade
  18:02 · task.claimed · tsk_7Hq2 · mbr_7Hq3 · simulated
  18:02 · step.committed · advise · person · bar admission · US-CA · mbr_7Hq3 · simulated
  18:02 · pay.accrued · mbr_7Hq3 · attest · $55.00 · $5.00 of it the brand's raise · simulated
← job_7Hq2 · delivered · flags.pdf · memo.pdf · $99.00 held

flush fills at the posted fee:

Call
→ POST /matters {"service":"contract-review","contract":"lease.pdf","client":{"name":"Ada Lovelace","email":"signs@example.test"},"client_region":"US-CA","max_usd":99,"key":"flush"}, then six hours
magic values: client.email = signs@example.test
  14:02 · task.posted · tsk_7Hq2 · $50.00 · dispatch cascade
  14:02 · task.offered · tsk_7Hq2 · mbr_7Hq2 · cascade
  14:02 · task.claimed · tsk_7Hq2 · mbr_7Hq2 · simulated
  14:02 · step.committed · advise · person · bar admission · US-CA · mbr_7Hq2 · simulated
  14:02 · pay.accrued · mbr_7Hq2 · attest · $50.00 · simulated
← job_7Hq2 · delivered · flags.pdf · memo.pdf · $99.00 held

Beside the seeded market, every Pool on localhost has the sandbox's four magic members: one eligible for every Task, and three that each fail one predicate. Eligibility lists them, and the magic values list every branch the sandbox can run.

A test clock moves every job, Task, hold and rung on it in order. POST /test_clocks/:id/advance fires each rung as it falls due, so a ladder that takes twelve hours runs in one call, as When no one claims shows.