On this page
A customer ran reword on what looked like a single page. It took eight minutes and twenty six seconds. The terminal showed nothing the whole time. They had no way to tell whether Wire was working, stuck, or quietly dead, so they asked the only question you can ask a black box: "is this correct?"
That question is the bug. Not the eight minutes. A run that does real work can take real time. The failure was that Wire never said what it was doing, so the only signal left was the clock, and the clock cannot tell you the difference between progress and a hang.
This release fixes the signal.
A heartbeat for every batch
Every per-page content command, news, refine, enrich, reword, consolidate, and crosslink among them, now logs a heartbeat as it goes. Each item announces itself when it starts and reports how long it took when it finishes:
[1/12] risk-analytics: starting
[1/12] risk-analytics: done in 41s
[2/12] bootstrapping: starting
[2/12] bootstrapping: done in 38s
[3/12] cash-flow-forecasting: starting
The counter answers "how far along am I." The timing answers "is this page slow, or is the whole run slow." And when a single item blows up, it says so without taking the batch down with it:
[4/12] tax-strategy: exception after 6s - <reason>
The batch keeps going. The failed page is logged, not silently marked done, so the next run picks it up again instead of skipping it.
Watching it live
The heartbeat goes to both the terminal and wire.log. To follow a long run as it happens, tail the log:
tail -f wire.log
One sharp edge worth knowing: tail -40 wire.log is not the same thing. The plain form buffers and only flushes when the file ends, so during a live run it can look frozen even though Wire is writing steadily. Use -f to follow. The workflow guide covers this and the rest of the command set.
Slow is not stuck, and failed is not done
The heartbeat is half of a larger correction. The other half is that Wire used to confuse two very different outcomes.
When a news run hit a transient API error, Wire could mistake the failure for "no news found" and write a tracker file, which marks the topic checked and skips it for the full refresh window, by default twenty one days. One blip on day one meant three weeks of missed coverage, and the article evaluations Wire had already paid for were thrown away. Now Wire separates "genuinely nothing to report," which writes the tracker, from "a step actually failed," which raises loud and leaves the topic to be retried on the next run. A missed window is expensive: the average page-one result gets refreshed roughly every two years, per Siege Media's content decay research, and Wire's whole point is to beat that cadence, not silently fall behind it.
The same instinct runs through the rest of the batch. Source diversity analysis that fails now logs a warning instead of quietly degrading the search. An article that comes back without a usable verdict now logs what the model actually returned. A page Wire cannot parse is logged and skipped, never fed blindly into an edit. This continues the work from the honest errors release and the earlier pipeline refactor: loud where it matters, quiet where it does not.
What you do
Upgrade and rebuild. Your content and config are untouched.
python -m wire.chief update
The next time a run takes eight minutes, you will know exactly which page it is on, how long each one took, and that it is working rather than wedged. For the full list of changes see the news index.