A merged pair shares its history, and absence proves a delisting
10:14 pm AWST · 819857a
The convergence check's last two finds. The delist-integrity rule now
accepts a complete traversal on either side of an event: a merged pair's
runs justify each other's events (the mtfordmtbarker delisting whose
paperwork the merge orphaned), and a car that stays gone through subsequent
complete traversals is proven by absence — a fabricated delisting would be
relisted on sight by the first complete pass after it. Eight orphaned
events from the campaign week's killed crawls closed on that rule; a fresh
fabrication still alarms immediately. The family map is a hashed CTE — the
first draft's per-row union subquery turned a 760ms check into a timeout.
daily-rollup moves to 12:50: at 15:55 it collided with the 15:44 deep pass,
which is how 2026-08-23 became a day with no rollup row. It stays absent —
write_daily_rollup's own guard refuses to describe a past day with today's
snapshot, and that refusal is the product's discipline, not a bug.
Suite verdict after: 21 checks passed, two known work-queue warnings.
health.ts: zero alerts. DATA-QUALITY 48.
Every integrity check gets a shape that fits its question
11:23 am AWST · a33fb9e
Confirming "green" surfaced the rest of the outgrown-scan family, each
flapping — passing quiet, dying under crawl IO:
check_fields_empty_flag (0204): the gate now counts a partial index built on
the violating predicate — free to maintain, all history, microseconds — after
a windowed rewrite still measured 116s. Info counts sample 6 hours.
run_slow_integrity_checks died at exactly its 900s budget even in the 02:51
quiet window, so 0205's reschedule was necessary but not sufficient. 0206
splits it by what each check asks: the two regression gates window to where
a regression can appear (price-vs-identifier reads a second partial index
over all history plus a 48h external_id window; cross-view pairs watch 7
days of events), and the VIN work-queue count — the expensive half, which
must see the whole VIN-less population — moves to its own daily
quiet-window cron with the full budget to itself. check-integrity's VIN
freshness limit widens 12h -> 26h to match.
0205 also re-ran 0083's re-runnable merge for two returned mirror pairs
(mtfordmtbarker/mountbarkerford, hurstvilletoyota/fergusonstoyota — both
rebrands where discovery found the new domain before the old id retired):
zero live URLs held by two ids again.
Convergence is scheduled, not hoped for: index build 11:36 in today's quiet
window, VIN seed 11:55, windowed checks refresh 13:45. cross_view was seeded
by hand at 03:21 (n=0, clean).
The click is acknowledged in the beat before the skeleton
10:21 am AWST · a926d21
Route-level loading.tsx paints the destination once navigation is underway,
but the beat between click and skeleton still read as a dead click — and on
"View your yard" it literally was one: the dropdown closed on click,
unmounting the link and any feedback it could carry, while the force-dynamic
yard rendered for seconds. Kiel reported it verbatim: no loading animation.
Three fixes. NavPending — useLinkStatus inside the Link — pulses a dot on
the clicked link itself: the yard menu item and all six top-nav links carry
it. The dealer menu now closes when the destination ARRIVES (pathname
change), not when the link is clicked, so the pulse survives the
navigation. And the sign-in form gives way to a visible "Signed in —
opening your yard…" state after auth instead of a disabled button; a
dealer who is already signed in and clicks the footer's Dealer sign-in link
is recognised and taken straight through with the same status line.
Sold cars become facts, not scans — and every slow click gets a face
10:11 am AWST · 1360d6e
Four request-path functions re-derived the same sold-car set from the heavy
view on every call, and the corpus outgrew all four at once: recent_sales
115s (home), turn_filtered 53.7s (/moving), turn_by_model 53s (/market),
days_to_turn 2.2s (every valuation). These are the pages reported as "up to
ten seconds". One narrow facts table now holds a row per sold car, rebuilt
half-hourly off the request path — a sale is only detectable at crawl
cadence, so a 30-minute fact loses nothing — and the four read it in 3-46ms
with their filters preserved verbatim. catalogue_json's nine-pass 51s scan,
which survived as the value picker's fallback, now reads the existing board
on both paths. depth-boards moves to the two windows the crawl box is quiet:
at 18:25 and 00:25 refresh_live_snapshot was losing an IO race against the
deep pass and dying on timeout, which is how the catalogue and the dealer
snapshot quietly went 13h stale. New boards join board_spec so staleness
alerts instead of rotting.
0203 corrects 0202 measured mid-flight: the facts build skipped the view's
fields_empty fallback and lost HALF the days_old data — a delisted car's
final observation is so often an empty-fields probe that the fallback is
load-bearing for exactly this population. 8,109 of the view's 8,133 dated
cars after the fix; the 0201 boards now read facts too. DATA-QUALITY 46.
Loading states for moving, value, yard, market and dealer pages: grey
skeletons echoing each page's layout, one visible status line, reduced-motion
safe, no invented numbers. A slow render now shows work instead of a frozen
click.
tonylahood's collapse alert: investigated, not a break — their restructure
withdrew the Lidcombe yard's stock from the domain (verified: clean 3-page
pagination, sitemap agrees at 81 cars). Acknowledged with the finding;
tonylahoodmotorscroydon mirrors the same inventory, flagged for dedup.
Board discount_by_time_on_market and turn_segments too
09:39 am AWST · c42ba08
The pulse's two siblings on /market (DATA-QUALITY 44 named them) get the same
board treatment: a single-row jsonb board the read function expands back into
its table shape, refreshed every 6h by pg_cron, read in 0.6ms on the request
path instead of scanning the full delisted set live.
The refresh reads base tables, not listing_current. Lifting the original
`from listing_current where status='delisted'` into the refresh took 311s —
the view runs a price-change-count subquery and a double lateral per row for
all 257k listings before the delisted filter removes 87% of them. Reading
listing directly (listing_status_idx for the 34k delisted rows, then
observation_pick_current_idx per row) is ~107s, off the request path, inside
the cron budget. DATA-QUALITY 45 records the trap: a heavy view plus a WHERE
is not a filtered heavy view.
15%->83% by time on market; SUV/Ute/Wagon leading turn), read functions at
0.6ms, /market and /value back to ~0.3s.
The pulse bar reads a board, not the whole corpus — site restored
09:10 am AWST · 64de611
The site went slow-to-unresponsive: /value and /sign-in ~19s, /coverage
timing out, /market fine at 0.24s. The root layout renders the credibility
bar from market_pulse() on every page, so a slow pulse was a slow everything.
market_pulse was a live scan — sold_total counts every delisting ever, with a
correlated NOT EXISTS per row. Fine at its documented 104ms. Then today's own
backlog drain (recovering Westside and the dealer-studio/imotor cohorts wrote
hundreds of delistings and left dead tuples) tipped it past the Small
instance's cache: 30-100s, disk-bound. The in-app cache protects a warm
process but every cold Vercel instance pays full cost, so pages hung, more
instances span up, and ten concurrent disk scans became an unloadable site.
0200 gives the pulse the board treatment coverage (0154) and the depth boards
already use: a single row refreshed every 5 min by pg_cron, read in 0.75ms on
the request path. No live-scan fallback on an empty board — that is the
stampede returning. Applied as a DB function, so every cold instance was fixed
at once with no deploy. Verified: every page back to sub-2s.
DATA-QUALITY 44. The lesson: a fix that recovers a lot of data is a write
spike, and anything the root layout awaits is on the critical path for the
entire site.