And correct the previous commit's closing claim, which was wrong.
c378bc0 said the Hiring activity chart "still renders empty ... the fault is
further down in that component, not in the data." That was a retraction of a
correct diagnosis, made from a screenshot taken before the rebase had reached
the browser. The chart was empty BECAUSE the data was stale, exactly as first
diagnosed, and rebasing fixed it. Checked properly this time: the area path
carries real values, and the rendered chart shows applications peaking at 16
around 8/18 with the screening and interview series drawn over it.
What was genuinely still missing was Hires. Staff was not rebased, so
hire_date stayed 35 days old with nothing inside the 30-day window and that
series drew nothing. It is rebased now, anchored on hire_date rather than
created_date, because the hire is the event the chart plots.
Leaving it behind had also introduced an inconsistency of my own making: once
applications moved, a candidate was hired last week according to their
application and five weeks ago according to their staff record. Rebasing them
together removes that.
All four series now render. Full suite green.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJvibeSc1JYXjatankqM1g
ShiftRecord is generated against now (shifts.go); everything else stayed on the
fixed calendar in seed.js while the calendar moved on. Twenty-three days after
that file was written the activity agent truthfully reported zero events in the
last seven days, and applications were sixteen days stale. Nothing was broken —
the data had simply aged out of every window the product reports over, and it
gets worse every day nobody reseeds.
RebaseToNow moves a set of records so the newest sits at now, keeping every gap
exactly as authored. The SHAPE is what every reader of this data is looking at:
three hires on one day, a screening the day after, a quiet fortnight before it.
Shifting the whole set by one delta preserves all of it. Scaling into a window
or scattering events across recent days would invent a rhythm nobody wrote.
Applied per entity — UserActivity, JobApplication, AIInterview — because each
anchors on its own newest record. One shared anchor would drag the quieter
entities by another entity's delta and invent relationships between them.
Reference data is untouched: a course's date is a fact about the course, not a
position in a window.
Rebasing rather than generating, so seed.json stays the single authored source,
still deterministic and still comparable byte-for-byte by the drift check. The
alternative — excluding these from the fixture the way ShiftRecord is — means a
second generator to keep in step with the frontend's copy.
The existing TestSeedPreservesSourceValues caught a real bug in the first
attempt, and its comment is why: "Applications carry updated_date in the
source, and the gap from created_date is what buildHires reads as
time-to-hire." I had shifted created_date alone, which turned five-day hires
into three-week ones. EVERY timestamp on a record now moves by the same delta,
and there is a test on that specifically.
That test now asserts the GAP rather than the absolute dates, because for a
rebased entity the dates are deliberately different — which is the one reason
it is supposed to allow. Its real subject was always the interval.
Verified against the database: before, activity was 23 days old with 0 events
in the last 7; after, all three entities are current, with 24 applications
spread across the last 30 days and 15 activity events inside 30.
Not fixed here: the Hiring activity chart on Control Center still renders
empty, and it was equally empty before this change. Its bucketing is correct —
replaying it in the browser against live data matched all 24 applications into
the right days — so the fault is further down in that component, not in the
data. Naming it rather than leaving it implied by a chart that still looks
wrong.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJvibeSc1JYXjatankqM1g