How-to / A guided look at how we build

How-to template — a timer pipeline

Side post for "How to use analyst-server" (pua-4-side-posts, criterion pua-4-how-to-templates). This is a template: the six stops from part 2, filled in for one use case so you can copy it. Swap the words in ‹angle brackets› for your own. The screens are the same ones part 2 describes. Kind of work: Apparatus-build (extend the machine). Drafted 2026-10-08.

Why use the path for a timer pipeline? A job that runs on a timer fails quietly. Nobody is watching at 3 a.m. Running it as an initiative means its reach test asks "did it run, and did it produce something", and the briefing reports last run and last output, so a stopped timer shows up as red instead of as silence.

① say it ──► ② read it back ──► ③ place it ──► ④ watch it build ──► ⑤ judge it ──► ⑥ change it
  "every ‹hour›,  "does it say       under            lane "timer-‹name›"  "did it run, and   "also alert me
   do ‹thing›"     when and why?"     Capabilities                         was it useful?"    when it fails"

1 · Builder session — state the intent

Intent text to copy:

"Every ‹weekday at 07:00›, I want ‹the treasury auction results› pulled and saved, so that ‹my morning report› always has yesterday's numbers. If a run fails or comes back empty, I want to see that in the briefing the same morning."

Width check. Ask the session: is there already a scheduled job that collects this? Does it belong in an existing data pipeline as one more source, or does it need its own? The usual answer is to extend what exists. On this box, scheduled work is a record in the scheduler's _schedules collection that the 15-minute tick fires. You do not add a new server process for each timer.

The tree you accept:

big-init-timer-‹name›          "‹thing› runs every ‹cadence› and its output is always fresh"
├── 1 · The job        the script that does one run, testable by hand
├── 2 · The schedule   the _schedules record: cadence, what it serves, who reads it
├── 3 · Output         where a run's result lands and how fresh it must be
├── 4 · Failure        what an empty or failed run looks like, and who is told
└── 9 · Operations     derived: what is owed, by whom, in what order

Example criterion, 3 · Output: "Each run leaves a dated result — REACH-TEST: schedule-ctl.mjs last-run ‹slug› --max-age-h 26 passes and the output file it names has today's date."

Briefing you describe: "Daily. First line: did the last run succeed, when, and how many rows. Then the last seven runs as a row of ✓ and ✗, and anything that needs me."

2 · Briefing draft — read it back

What the draft should say, first two lines:

Intent: ‹treasury auction results› collected every ‹weekday 07:00› and fresh by ‹07:15›. Verdict: Started — job written, not yet scheduled; 1 of 4 branches met.

A draft that opens with the cron expression is describing the machine. The first line should say what you get and when.

3 · Workbench — place it and give it a lane

Open the workbench at the parent (Capabilities, or the data pipeline it extends) and check:

  • no sibling already collects the same source;
  • The schedule branch names a subject (the node the job serves) and an audience (who reads it), so the job is not an orphan on the schedule list;
  • the cadence is no faster than the scheduler's 15-minute tick. Faster than that is a design conversation, not a setting.

Lane: timer-‹name›.

4 · Lane activity — watch it build

Filtered to timer-‹name›, expect: the job run once by hand, then the schedule record set and switched on, then the first fired run. When you switch a schedule on, set its last-fired time to now, unless you want it to fire on the next tick. A lane that goes quiet after "schedule set" with no "first run" entry means the record is not active.

5 · Initiative briefing report — is the intent fulfilled?

What the filled-in report should show:

Branch Evidence a stranger can check
1 · The job a hand run and its output
2 · The schedule the record's cadence, subject and audience (schedule-ctl.mjs show ‹slug›)
3 · Output last run time, row count, and age against the freshness bar
4 · Failure the last failure, if any, and where it was reported

The judge's question: on the mornings you needed the numbers, were they there? Seven green runs that each saved zero rows is a true report on the wrong intent.

6 · Builder session — request changes

Typical ask to copy:

"Two Mondays in a row the source was late and the run saved nothing. Retry at 07:30 when the first run is empty, and only show red if the retry is empty too."

The session files it verbatim as an upgrade proposal. The amended 4 · Failure criterion appears on the workbench, and the loop runs again from stop ③.


Back to the side-posts list: 04-side-posts.md · The six stops in general: 02-screen-path.md