---
title: "A date the world sets"
url: https://services.dev/docs/grow/clock
captured: [grow-clock-tabs.txt, grow-clock.txt]
---
# A date the world sets

URL: https://services.dev/docs/grow/clock

> Give the filing a date the registry sets and the buyer answers for. Three days out, a rung asks the registry for more time; at the date, unfiled, the buyer chooses what happens.

`within` is your deadline: how long the work may take. Some dates belong to the world: a registry takes a filing until the day it names. A clock holds that date, names who answers for it, acts before it comes, and at the date asks its owner what happens. This is Grow 5: Grow 4's filing gains a date.

## Add the clock

`check` counts 26 lines. `translators()` is [Grow 4's](https://services.dev/docs/grow/submit.md), unchanged:

```ts title="grow/clock.ts"
import { Pool, Rules, Service } from 'services.dev'

// Grow 5, a date the world sets: the registry takes the filing until a date the buyer names, and the buyer answers
// for it. Three days out, the clock asks the registry for two more weeks, and the extension moves the date. The clock
// is named for the filing, so the filing satisfies it; at the date, unfiled, the buyer chooses to file late or withdraw.
export default Service({
  name: 'Translation',
  description: 'A document, translated, signed and filed by its date.',
  input: { document: 'file', to: 'language: a BCP 47 tag, such as fr-CA', file_by: 'date: the registry deadline, such as 2026-11-04' },
  output: { document: 'file', filing: 'text', extension: 'text' },
  rules: rules(),
  roles: { translator: { pool: translators(), pay: 30 } },
  deliver: {
    glossary: { ask: 'buyer', to: 'answer', items: () => [{ id: 'terms', label: 'Which terms stay in English?' }] },
    translate: 'ai',
    harden: { review: 'adversarial', lenses: ['meaning', 'terms'], rounds: 2 },
    sign: { by: 'translator', stamp: true, est: '20min' },
    extend: { submit: 'https://registry.example.test/extensions', to: 'the registry', receipt: 'extension', routed: true },
    file: {
      submit: 'https://registry.example.test/filings',
      to: 'the registry',
      receipt: 'filing',
      rejected: { missing_certificate: 'sign', '*': 'translate' },
      perfect: '2d',
      fallback: 'hand_off',
    },
    hand_off: { ask: 'buyer', to: 'answer', routed: true },
  },
  clocks: {
    file: { due: job => job.input.file_by, owner: 'buyer', rungs: ['run extend 3d'], moves: { extend: '14d after due' }, lapse: ['file', 'withdraw, in writing'] },
  },
  price: 89,
})
```

Asking for more time is an act, so `rules()` gains one row:

```ts title="grow/clock.ts"
        extend: { open: true, position: 'Asking a registry for more time needs no credential.' },
```

`file_by` is the buyer's date. `extend` is routed: it runs only when the clock sends the job there.

| Key | What it does | Default |
|---|---|---|
| `due` | The date: a function of the job returning a civil date, which closes at the calendar's minute, or a span after a step, an input, an event or another clock, such as `'365d after file'`. A function that throws, or returns what isn't a date, fails `check` with [`clock_due_unreadable`](https://services.dev/docs/reference/check/clock_due_unreadable.md) | required |
| `owner` | Who answers for it: `'buyer'`, `'brand'`, a role, or `of_record`, the member of record on the subject. An owner that can never resolve fails `check` with [`clock_unowned`](https://services.dev/docs/reference/check/clock_unowned.md) | required |
| `rungs` | What happens before the date, in civil days back: `'notice 30d'` and `'escalate 3d'` tell the owner, `'ack daily 2d'` asks them to acknowledge each of the last two days, and `'run extend 3d'` proposes the routed step through the gate. A proposal the gate holds proposes again each day, and escalates | none |
| `moves` | Steps whose committed output moves the date, and to when: `'14d after due'`, or a function of the job. It moves this clock only, so two dates that move differently are two clocks | none |
| `lapse` | What the owner chooses at the date, unsatisfied, through `clock.choose`. A step's name runs that step through the gate; any other option closes the clock with the choice on the record | none |
| `satisfied_by` | Steps whose commit closes it | the step it's named for |

[Clocks](https://services.dev/docs/service/clocks.md) covers `every`, `each`, `lives_on`, `hard`, `exposure` and [the calendar](https://services.dev/docs/service/time.md#the-calendar).

## Check it

```bash
npx services.dev check
```

```txt title="magic values: none"
services/translation.ts · 26 lines · $89 per job, within 48 hours, charged on file's receipt.
  who     A translator signs every document before it is filed. (rules 2026-10) The buyer answers at glossary.
  roles   translator · sworn translator · from sworn-translators · $30 an act
  steps   glossary · buyer · answer → translate · ai → harden · ai · adversarial · 2 lenses → sign · translator · * · stamped → extend · the registry · routed → file · the registry → hand_off · buyer · answer · routed
  clocks  file · a date your code decides · the buyer
  bounds  reserved sign to sworn translator · open extend and file
  agent   order_translation · 30 of 30 words · job_7Hq2 waits on party
  ledger  +$89.00 · AI $1.26 (example) · translator $30.00 · you $57.74
  margin  at least $41.20 when the first translator signs ($89.00 − $30.00 translator − $17.80 AI cap) · $26.20 at the ladder's cap, the lower of 50% and what the floor leaves · $11.20 after a decline and a second translator
          a job that stops costs you at most $47.80
  apps    customer portal · delivery portal · owner console

mcp     13 buyer tools · 4,555 of 8,000 tokens · 9 more with ?toolset=sandbox
✓ ready to sell · 1 Service · it keeps at least 46% of every job
  next    npx services.dev dev

AI and money are simulated until you wire them. $0.42 a call is an example.
```

The `clocks` line names the date and its owner. The margin is Grow 4's.

## Run one job

No magic value is needed. The order opens the clock:

```txt
→ POST /translation {"document":"lease.pdf","to":"fr-CA","file_by":"2026-11-04","key":"grow","max_usd":89}
```

```txt title="magic values: none"
← job_7Hq2 · waiting · on party · $89.00 held
  clock   clk_7Hq2 · file · due 2026-11-04 · buyer · open
```

Every surface reads it alike, its rung armed, its lapse listed:

**CLI**

```bash title="CLI"
npx services.dev clocks get clk_7Hq2 --json
```

```json title="magic values: none"
{
  "id": "clk_7Hq2",
  "object": "clock",
  "livemode": false,
  "name": "file",
  "service": "translation",
  "job": "job_7Hq2",
  "subject": null,
  "lives_on": "job",
  "status": "open",
  "due_at": "2026-11-04T23:59:00.000Z",
  "due_on": "2026-11-04",
  "zone": "UTC",
  "original_due_at": "2026-11-04T23:59:00.000Z",
  "moves": [],
  "occurrence": 0,
  "owner": {
    "type": "buyer",
    "member": null
  },
  "rungs": [
    {
      "rung": "run extend 3d",
      "rings_at": "2026-11-01T00:00:00.000Z",
      "fired": false
    }
  ],
  "lapse": [
    "file",
    "withdraw, in writing"
  ],
  "choice": null,
  "satisfied_by": [
    "file"
  ],
  "created": "2026-10-25T14:02:11.000Z",
  "simulated": true
}
```

**API**

```bash title="API"
curl http://localhost:8787/clocks/clk_7Hq2
```

```json title="200 · magic values: none"
{
  "id": "clk_7Hq2",
  "object": "clock",
  "livemode": false,
  "name": "file",
  "service": "translation",
  "job": "job_7Hq2",
  "subject": null,
  "lives_on": "job",
  "status": "open",
  "due_at": "2026-11-04T23:59:00.000Z",
  "due_on": "2026-11-04",
  "zone": "UTC",
  "original_due_at": "2026-11-04T23:59:00.000Z",
  "moves": [],
  "occurrence": 0,
  "owner": {
    "type": "buyer",
    "member": null
  },
  "rungs": [
    {
      "rung": "run extend 3d",
      "rings_at": "2026-11-01T00:00:00.000Z",
      "fired": false
    }
  ],
  "lapse": [
    "file",
    "withdraw, in writing"
  ],
  "choice": null,
  "satisfied_by": [
    "file"
  ],
  "created": "2026-10-25T14:02:11.000Z",
  "simulated": true
}
```

**MCP**

```txt title="MCP"
→ tools/call get_clock {"id":"clk_7Hq2"}
```

```json title="magic values: none"
{
  "id": "clk_7Hq2",
  "object": "clock",
  "livemode": false,
  "name": "file",
  "service": "translation",
  "job": "job_7Hq2",
  "subject": null,
  "lives_on": "job",
  "status": "open",
  "due_at": "2026-11-04T23:59:00.000Z",
  "due_on": "2026-11-04",
  "zone": "UTC",
  "original_due_at": "2026-11-04T23:59:00.000Z",
  "moves": [],
  "occurrence": 0,
  "owner": {
    "type": "buyer",
    "member": null
  },
  "rungs": [
    {
      "rung": "run extend 3d",
      "rings_at": "2026-11-01T00:00:00.000Z",
      "fired": false
    }
  ],
  "lapse": [
    "file",
    "withdraw, in writing"
  ],
  "choice": null,
  "satisfied_by": [
    "file"
  ],
  "created": "2026-10-25T14:02:11.000Z",
  "simulated": true
}
```

**SDK**

```ts title="SDK"
await lingua.clocks.get("clk_7Hq2")
```

```json title="magic values: none"
{
  "id": "clk_7Hq2",
  "object": "clock",
  "livemode": false,
  "name": "file",
  "service": "translation",
  "job": "job_7Hq2",
  "subject": null,
  "lives_on": "job",
  "status": "open",
  "due_at": "2026-11-04T23:59:00.000Z",
  "due_on": "2026-11-04",
  "zone": "UTC",
  "original_due_at": "2026-11-04T23:59:00.000Z",
  "moves": [],
  "occurrence": 0,
  "owner": {
    "type": "buyer",
    "member": null
  },
  "rungs": [
    {
      "rung": "run extend 3d",
      "rings_at": "2026-11-01T00:00:00.000Z",
      "fired": false
    }
  ],
  "lapse": [
    "file",
    "withdraw, in writing"
  ],
  "choice": null,
  "satisfied_by": [
    "file"
  ],
  "created": "2026-10-25T14:02:11.000Z",
  "simulated": true
}
```

A test clock runs to 2 November, the glossary unanswered:

```txt
→ POST /test_clocks/default/advance {"to":"2026-11-02T00:00:00Z"}
```

```txt title="magic values: none"
  2026-10-31 14:02:11  ask.reminded · glossary · 1d before expiry
  2026-11-01 00:00:00  clock file · rung run extend 3d → extend proposed · committed
  2026-11-01 00:00:00  extend · rcp_7Hq2 accepted
  2026-11-01 00:00:00  clock file · moved 2026-11-04 → 2026-11-18
  2026-11-01 00:00:00  waits on party at glossary
  2026-11-01 14:02:11  ask.expired · glossary
  2026-11-01 14:02:11  ask glossary · buyer · 1 item · 1 open (terms)
```

Three days out, the rung proposed `extend`, the registry's receipt committed it, and `moves` carried the date to 18 November. The glossary's link expired and reopened as `ask_7Hq3`. The buyer answers, the translator signs, and the filing satisfies the clock:

```txt
→ POST /asks/ask_7Hq3?t=rE5VINsEvPPB93bDQLooDc {"items":{"terms":{"answer":"Lessee, Lessor, Premises"}}}
```

```txt title="magic values: none"

# 20 minutes later, mbr_7Hq2, the sworn translator, claims tsk_7Hq2 in the delivery portal and signs, in their own session
→ POST /tasks/tsk_7Hq2/claim · POST /tasks/tsk_7Hq2/clear · POST /tasks/tsk_7Hq2/attest

← job_7Hq2 · delivered · lease.fr-CA.pdf · $89.00 charged
  record  glossary · reminded 1d before expiry | file clock · run extend 3d · goto extend | extend · the registry · accepted · rcp_7Hq2 | file clock · moved 2026-11-04 → 2026-11-18 | glossary · expired | glossary.terms · answered | glossary · buyer · answer · clock paused 7d 9h | translate · ai | harden · ai · adversarial · 2 lenses · pass | sign · person · sworn translator · * · mbr_7Hq2 | file · the registry · accepted · rcp_7Hq3
  clock   clk_7Hq2 · file · due 2026-11-18 · buyer · satisfied · moved from 2026-11-04
  closed  file · satisfied when file committed
```

The glossary's wait paused the job's own deadline, `clock paused 7d 9h`; the registry's date kept running.

## At the date

Had the filing missed 18 November, the clock would turn `due` and wait for the buyer's `clock.choose`: `file` runs the filing late, through the gate, and `withdraw, in writing` closes the clock with that choice on the record, leaving the job for the buyer to cancel. [The clock calls](https://services.dev/docs/service/clocks.md#the-clock-calls) shows one.

## What changed

```bash
npx services.dev diff grow/submit.ts grow/clock.ts
```

```txt title="magic values: none"
grow/submit.ts (22 lines) → grow/clock.ts (26 lines)
Translation · changed description, input, output, deliver, rules, clocks · adds clocks: dates the world sets, who answers for each, its rungs and what moves it

API   ~ operation service.order.translation  POST /translation  item.description, item.requestBody.content.application/json.schema.properties.file_by, item.requestBody.content.application/json.schema.required  · breaking
      ~ operation service.quote.translation  GET /translation.json  answers.description, answers.input.properties.file_by, answers.input.required  · breaking
      + operation clock.list                 GET /clocks
      + operation clock.get                  GET /clocks/{id}
      + operation clock.ack                  POST /clocks/{id}/ack
      + operation clock.satisfy              POST /clocks/{id}/satisfy
      + operation clock.choose               POST /clocks/{id}/choose
      + operation clock.assign               POST /owner/clocks/{id}/assign
      ~ operation brand.manifest             GET /manifest.json  answers.services
      + object clk_                          clock
      + 15 events                            clock.opened, clock.noticed, clock.escalated, clock.ack_due, clock.ack_missed, clock.ran, clock.moved, clock.due, clock.satisfied, clock.rolled, clock.recurred, clock.acked, clock.chosen, clock.assigned, clock.outlived
      + 6 errors                             needs_the_owner, evidence_required, evidence_used, clock_closed, clock_not_due, clock_moved_on
CLI   ~ operation service.order.translation  services.dev translation document=… to=… file_by=…  input.properties.file_by, input.required  · breaking
      + operation clock.list                 services.dev clocks list
      + operation clock.get                  services.dev clocks get <clock>
      + operation clock.ack                  services.dev clocks ack <clock>
      + operation clock.satisfy              services.dev clocks satisfy <clock>
      + operation clock.choose               services.dev clocks choose <clock> <option>
      + operation clock.assign               services.dev clocks assign <clock> <member>
      + 15 events                            clock.opened, clock.noticed, clock.escalated, clock.ack_due, clock.ack_missed, clock.ran, clock.moved, clock.due, clock.satisfied, clock.rolled, clock.recurred, clock.acked, clock.chosen, clock.assigned, clock.outlived
      + 6 errors                             needs_the_owner, evidence_required, evidence_used, clock_closed, clock_not_due, clock_moved_on
MCP   ~ operation order_translation          order_translation  description, inputSchema.properties.file_by, inputSchema.required  · breaking
      + operation list_clocks                list_clocks
      + operation get_clock                  get_clock
      ~ prompt buy_translation               prompts/get buy_translation  arguments
SDK   + operation clock.list                 clocks.list()
      + operation clock.get                  clocks.get()
      + operation clock.ack                  clocks.ack()
      + operation clock.satisfy              clocks.satisfy()
      + operation clock.choose               clocks.choose()
      ~ object job_ (translation)            Job<"translation">  + input: { document: File; to: string; file_by: string }, + output: { document: File; filing: string; extension: string }
      + object clk_                          clock
      + 15 events                            clock.opened, clock.noticed, clock.escalated, clock.ack_due, clock.ack_missed, clock.ran, clock.moved, clock.due, clock.satisfied, clock.rolled, clock.recurred, clock.acked, clock.chosen, clock.assigned, clock.outlived
      + 6 errors                             needs_the_owner, evidence_required, evidence_used, clock_closed, clock_not_due, clock_moved_on
Site  ~ operation service.order.translation  /translation  + A document, translated, signed and filed by its date., + The boundarysign: reserved to sworn translator A registry accepts a translation a sworn tr
      ~ operation service.quote.translation  /translation.json  description, input.properties.file_by, input.required  · breaking
Docs  ~ operation service.order.translation  /llms.txt · Translation  + A document, translated, signed and filed by its date. $89 per job, within 48 hours, charge, + curl http://localhost:8787/jobs -H 'content-type: application/json' -d '{"service":"transl
      + operation clock.list                 /llms.txt · Operations
      + operation clock.get                  /llms.txt · Operations
      + operation clock.ack                  /llms.txt · Operations
      + operation clock.satisfy              /llms.txt · Operations
      + operation clock.choose               /llms.txt · Operations
      + 6 errors                             needs_the_owner, evidence_required, evidence_used, clock_closed, clock_not_due, clock_moved_on
App   no change
```

The input gains `file_by`, breaking for clients that type it. The clock brings its own calls, the `clk_` object, fifteen events and six errors; MCP only reads clocks.

In a brand, [the tax example](https://services.dev/docs/examples/tax/deadline.md) runs two clocks on one job, because its extension moves one date and never the other.

## Next

[Paid on the close](https://services.dev/docs/grow/outcome.md): a Service that charges only when its buyer's own customer pays.

---

- Up: [Your first paid job](https://services.dev/docs.md)
- Previous: [File it somewhere](https://services.dev/docs/grow/submit.md)
- Next: [Paid on the close](https://services.dev/docs/grow/outcome.md)
