Dates at risk
Every date that needs your hand, in one list on the owner console. A clock no one answers for, a seat of record left vacant, a rung held at the gate, a missed acknowledgement, a job at risk or late. Each one comes with why it is there and the control that settles it, and the next 30 days follow.
Most dates keep themselves. A clock's rungs give notice, ask for the day's acknowledgement and run the step that moves the date, and the gate decides each one. Dates at risk, at /console/dates, lists only the dates that don't keep themselves, each with why it is there and the control that settles it.
After a year on the test clock, the tax example has nothing that needs its owner, and its next 30 days in a table:
Its year stays off the list because each clock says how it closes and what runs before it's missed:
| The clock declares | What happens, with no one acting | In the tax example |
|---|---|---|
a step of the same name, or satisfied_by | the step commits and the clock closes | pay: { satisfied_by: ['pay', 'file'] }: a balance paid with the return closes it |
rungs: ['run <step> <span>'] | the step proposes through the gate that far ahead | file: run tentative 3d figures the tax and files the extension |
moves: { <step>: <span> } | that step moves the date, and the portals say from when | file: extend moves it six months |
rungs: ['notice <span>', 'ack daily <span>'] | whoever answers for it hears, then acknowledges each day | file: notice 30d, ack daily 7d |
| Listed when | The control |
|---|---|
| no one answers for it | Assign who answers for it |
| it's the brand's own, due within 14 days | Mark it done, on a receipt the job holds |
| it came due unsatisfied | the brand's own: one button per option. Anyone else's waits on its owner |
| a run rung is held at the gate | none: it says why, and when it proposes again |
| a day's acknowledgement was missed, or it escalated | none: its owner acts, and acknowledges or marks it done |
| its date couldn't be read, so it never opened | none: fix the definition, clock_due_unreadable |
| a hard date is 30 days out or less, whoever answers for it | the brand's own: Mark it done. Anyone else's: who answers, and their last acknowledgement |
| a job is at risk or late | its escalated step, in your staff's inbox with the time it has left |
check already refuses a clock that no one could ever own (clock_unowned). A vacancy is what the world does after you deploy.
A clock falls vacant when the person who answered for it no longer can: here, a member of record whose coverage lapsed. The console raises the alarm, and assigning a member who holds the role's credential settles it:
→ GET /clocks?owner=none clk_7Hq2 · renew · due 2026-12-24 · no one · open · on the subject
→ GET /console # the owner console's alarms
alarm · vacant · clk_7Hq2 · mark renew · due 2026-12-24 · no one answers for it
→ POST /owner/clocks/clk_7Hq2/assign {"member":"mbr_eligible"}
← 200 · clk_7Hq2 · renew · due 2026-12-24 · mbr_eligible · open · on the subject
→ GET /clocks?owner=none
← 200 · EMPTY · 0 clocksThe same lapse on a subject's seat raises its own alarm. The custodian ladder covers the seat until a member takes it:
open http://localhost:8787/console # the owner consolealarm · vacant · sbj_7Hq2 · patent family rcp_7Hq2 · practitioner mbr_7Hq3: coverage lapsed on 2026-10-01 · covered by brandA rung whose step needs a grant the client let lapse is held at the gate. It proposes again each day, and the console says why:
→ GET /console # the owner console alarm · held · clk_7Hq2 · appeal deadline · extend refused:needs_grant · due 2026-11-24 · proposes again 2026-11-23A job's deadline counts only while the work is the brand's. At three quarters it fires job.at_risk and at the end job.late, and the console lists the job as at risk, then late. A step that escalates at risk waits in your staff's inbox:
npx services.dev tick 4htc_7Hq2 · 2026-10-28 19:00:00 → 2026-10-28 23:00:00 · 2 fired
2026-10-28 19:30:00 job_7Hq2 job.at_risk · 7.5h of 10h, counted only while the work is the brand's
2026-10-28 22:00:00 job_7Hq2 job.late · 10h of 10h, counted only while the work is the brand'sEach alarm is also an event: clock.vacant, clock.escalated, clock.ack_missed, job.at_risk and job.late. A watch carries them to wherever you'll see them.
Every kind of time and what each one fires: Keeping time. Every screen of a year, in order: the tax example's console.
| Call (CLI) | API | Event | On the console | Plan |
|---|---|---|---|---|
clocks assign <clock> <member> | POST /owner/clocks/:id/assign | clock.assigned | /console/dates | every plan |
clocks satisfy <clock> | POST /clocks/:id/satisfy | clock.satisfied | /console/dates | every plan |
clocks choose <clock> <option> | POST /clocks/:id/choose | clock.chosen | /console/dates | every plan |
clocks ack <clock> | POST /clocks/:id/ack | clock.acked | /console/dates | every plan |