Dates at risk

The running jobjob_7Hq2 · accepted · document.fr-CA.pdf · $49.00 final

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:

Owner console/consoleafter the tick 1y walk

Its year stays off the list because each clock says how it closes and what runs before it's missed:

The clock declaresWhat happens, with no one actingIn the tax example
a step of the same name, or satisfied_bythe step commits and the clock closespay: { satisfied_by: ['pay', 'file'] }: a balance paid with the return closes it
rungs: ['run <step> <span>']the step proposes through the gate that far aheadfile: run tentative 3d figures the tax and files the extension
moves: { <step>: <span> }that step moves the date, and the portals say from whenfile: extend moves it six months
rungs: ['notice <span>', 'ack daily <span>']whoever answers for it hears, then acknowledges each dayfile: notice 30d, ack daily 7d
Listed whenThe control
no one answers for itAssign who answers for it
it's the brand's own, due within 14 daysMark it done, on a receipt the job holds
it came due unsatisfiedthe brand's own: one button per option. Anyone else's waits on its owner
a run rung is held at the gatenone: it says why, and when it proposes again
a day's acknowledgement was missed, or it escalatednone: its owner acts, and acknowledges or marks it done
its date couldn't be read, so it never openednone: fix the definition, clock_due_unreadable
a hard date is 30 days out or less, whoever answers for itthe brand's own: Mark it done. Anyone else's: who answers, and their last acknowledgement
a job is at risk or lateits 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:

Call
→ GET /clocks?owner=none
200 · OK · 1 clock · magic values: member = mbr_eligible
  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 clocks

The same lapse on a subject's seat raises its own alarm. The custodian ladder covers the seat until a member takes it:

Run
open http://localhost:8787/console   # the owner console
magic values: applicant.email = signs@example.test
alarm · vacant · sbj_7Hq2 · patent family rcp_7Hq2 · practitioner mbr_7Hq3: coverage lapsed on 2026-10-01 · covered by brand

A 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:

Call
→ GET /console   # the owner console
magic values: none
  alarm · held · clk_7Hq2 · appeal deadline · extend refused:needs_grant · due 2026-11-24 · proposes again 2026-11-23

A 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:

Run
npx services.dev tick 4h
magic values: client.email = silent@example.test
tc_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's

Each 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)APIEventOn the consolePlan
clocks assign <clock> <member>POST /owner/clocks/:id/assignclock.assigned/console/datesevery plan
clocks satisfy <clock>POST /clocks/:id/satisfyclock.satisfied/console/datesevery plan
clocks choose <clock> <option>POST /clocks/:id/chooseclock.chosen/console/datesevery plan
clocks ack <clock>POST /clocks/:id/ackclock.acked/console/datesevery plan