The cron exited clean. There were no drafts.

The cron fired at 07:00 UTC on Monday, 29 June. Day 1 of a fresh 14-day cadence clock, and the first on-schedule weekday firing in a while. Triage completed. Ground stage ran. One cluster survived all the way to candidate stage. Zero drafts emerged.

Three days later, 2 July, 08:22 BST. Triage completed again. 150 clusters ranked, top candidate mortgage at a calculator score of 20. Candidates fetched, ground ran, zero drafts.

Both mornings the cron exited clean. The 14-day structure assumes the pipeline fires and produces drafts on weekday mornings. On two of those mornings, one week apart, it fired, reported success, and produced nothing.

What “clean exit” means here

The pipeline stages before a draft materialises: triage ranks candidate clusters by calculator relevance score, ground fetches and assembles source material against each candidate, claim extraction runs the assembled ground through Haiku to pull verifiable claim blocks, and draft runs only if extraction produces enough claims to meet the threshold. Each stage signals success independently; only the stage that fails produces an error.

When extraction underfires, meaning Haiku returns too few claims from the assembled ground, the draft stage doesn’t start. No error fires and no downstream warning surfaces. The stage simply doesn’t run. Every prior stage exits cleanly, and draft never runs. The cron reports success.

This is B-076. As of 29 June it was still open.

Four days

The pattern across 29 June to 2 July:

  • 29 June: zero drafts. Haiku underfire on the one cluster that survived ground. Two articles published via the operator path instead: T-006 (the 60% tax trap) and T-029 (Mortgage Guarantee Scheme 2025).
  • 30 June: one draft. mortgage-abandoned-about-above, slug still mangled because the title-normalisation step was mid-fix. Ten of thirteen sentences passed claim verification. Structurally nearly complete; rescued and published after operator edits.
  • 1 July: one draft. Same mortgage rate-spike cluster as the previous day: same BBC, Zoopla, Moneyfacts, and Bank of England sources, same US-Iran geopolitical framing, same £232 and £66 regional figures. Redundant. Published operator-written content instead: Personal Savings Allowance and the High-Income Child Benefit Charge, both single-source gov.uk drafts.
  • 2 July: zero drafts. 150 clusters ranked, candidates fetched, ground ran. Nothing.

Useful pipeline output across four days: one partial draft, published after edits.

The 1 July duplicate is a separate problem. Triage ranked the mortgage cluster first again, and the pipeline built a second draft from the same assembled sources. Extraction underfire and duplicate cluster selection produce the same outcome: a cron firing that contributes nothing publishable.

Why it doesn’t announce itself

Triage produces a ranked list. Ground fetches source pages. Both stages leave auditable artefacts. You can count rows, count bytes, verify the stage ran.

Claim extraction’s output is internal to draft stage’s input. Haiku runs, the result lands, and if the count falls below threshold, draft skips. Nowhere in the current log does a line appear reading “extraction returned N claims, threshold is M, skipping.” The cron exits 0 regardless of whether Haiku returned 0 claims or 14.

The monitoring model was built around stage completion, not output quality. Triage is monitored by whether it produced a ranked list; ground, by whether it fetched pages. Both are binary states, run or didn’t. Claim extraction breaks that pattern. It can run, exit cleanly, and return a result that is technically valid but practically empty. Binary completion monitoring misses this entirely.

A stage failure produces a non-zero exit and something in the log. An underfire produces a zero exit and silence. On a morning where you expect a draft, absence isn’t obviously a failure. It could be a quiet news day. It could mean no cluster scored above the triage threshold. Without an explicit extraction-count log line, there is no way to distinguish “extraction returned 2 claims” from “extraction returned 0” from “genuinely nothing worth extracting.”

The gap is observable in aggregate. A single zero-draft morning is unremarkable. Two in four, with a third producing a duplicate, is a pattern. But the operator has to count manually to see it. The pipeline provides no signal. The corrective pass doesn’t just add a re-ground step; it adds an observable count that makes the pattern visible without manual inspection.

The corrective pass

The fix is a step between ground and draft that makes the extraction count explicit and acts on it.

Minimum viable: after extraction runs, write a log line with the claim count and the threshold. If count ≥ threshold, proceed. If not, two routes.

Re-ground with wider sources. If the initial ground was narrow, fetch additional sources for the same cluster and re-run extraction. Haiku gets more material; the claim count has room to improve. Keeps the cluster in play without relaxing quality standards.

Threshold relaxation with explicit flag. When no additional sources exist for the cluster: lower the minimum by one level, re-run Haiku against the same ground, flag the draft as threshold-relaxed. The downstream verifier applies tighter scrutiny.

If both routes return below threshold: drop the cluster for the current cycle and write the reason to the log explicitly. Not a silent skip. A visible drop record. The operator can see the count, the threshold, the gap, and decide whether to commission an operator-path article on the same topic.

Any of these shapes makes the failure observable. A zero-draft morning because no cluster survived genuinely looks different in the log from a zero-draft morning because Haiku underfired on a live cluster. Currently they look the same.

The operator gap

While the pipeline underdelivered, content shipped. On Day 1 the operator path put out two: T-006 (the 60% tax trap) and T-029 (Mortgage Guarantee Scheme 2025). Day 3 added Personal Savings Allowance plus the High-Income Child Benefit Charge, both single-source gov.uk articles. Day 4 covered CGT annual exemption, then Dividend Allowance. Day 5 brought ISA allowance: 754 words, 15 hand-curated claim blocks across three gov.uk pages, published before the morning cron fired.

The operator path is not a substitute for a working pipeline. It is the right track for policy-reference pillars: stable gov.uk sources, tax-year thresholds, entitlement rules. These benefit from hand-curation and don’t depend on today’s news ground. News-grounded content is what the pipeline was built to produce: current rate movements, Budget follow-up, regulatory changes with fresh commentary. The operator’s time should not be filling that gap.

Two zero-draft mornings in four, both with a clean cron exit. The corrective pass makes that visible and actionable rather than invisible and ambiguous. B-076 is still open.

All writing