- A run can no longer spend more time than it has. osha.gov's CloudFront
answered 503/504 for two days (2026-09-06 and 09-07) and this actor's retry
ladder had no ceiling: five attempts at a 90-second request timeout plus 53
seconds of backoff meant a single stubborn page could cost 503 seconds, and
both the office sweep and the detail pass looped over that with nothing
watching the clock. Fifteen Texas offices at three at a time is five waves of
that — past the run's own hour-long timeout with not one row pushed. Four of
the last thirty runs ended that way and the Store flagged the actor as under
maintenance.
- Every fetch now plans against the time that is actually left rather than
booking its worst case up front: the request timeout is clamped to what
remains, a backoff that would outlive the run is not slept, and no single URL
may spend more than 90 seconds (a search page), 30 seconds (a detail page) or
20 seconds (the office dropdown, which has a shipped fallback anyway).
- The run reserves the last 90 seconds to charge and push what it collected, so
a run that runs long now delivers a partial answer instead of nothing.
- It also says so. Two new statuses: a partial delivery states it is partial and
how many matching inspections it left behind, and a run that delivered nothing
because the clock beat it says exactly that. Neither may claim OSHA had no
inspections, that your filters dropped them all, or that monitor mode found
nothing new — a run cut short did not measure any of those. Offices the clock
cut short or never reached are named, the same as offices that refused.
- Inspections skipped for time are kept out of the monitor-mode baseline, so the
next run picks them up instead of treating them as already reported.
- Every run now ends with a status message you can read straight from the run
list. It used to end with a bare exit and no message at all, so a run that
swept twelve offices and delivered nothing looked identical to one that
delivered four hundred. The three different ways to reach zero rows are now
three different sentences: OSHA reported no inspections in your window (with
the date its data is actually current through), OSHA returned inspections but
none passed your filters, or monitor mode found nothing new since the last
run. An office whose search OSHA refused is named, and can never be folded
into "no inspections" — it told us nothing about what it holds.
- The wording lives in one pure, unit-tested function (
src/status.js).
- README now states the prices ($0.005 per run start, $0.005 per inspection,
$0.03 per webhook digest); it had no pricing section at all.
New OSHA inspection leads, built on OSHA's public establishment search. One row
per inspection with the establishment, site and mailing address, NAICS industry,
inspection type and scope, the OSHA office running it, case status, and the
violation counts and penalties once OSHA publishes them.
Covers federal OSHA and every state-plan agency, 55 states and territories, with
no API key. Filter by state, by OSHA office, by industry (NAICS prefix), by
inspection type or by keyword, and choose open cases, closed cases or both.
Monitor mode remembers what it has already reported, so a scheduled run returns
and charges for only inspections that are new since the last one, with an
optional Slack digest.