Reconstructing Run Journals from Git History
Rebuild the missing timelines of old runs from commit times so they replay as first-class timed runs
Gantry records each run as a journal: an event-by-event timeline of what happened and when. The replay and screencast tools read that journal to animate a finished run back as a moving picture. But the oldest completed runs have no usable timeline. Some carry no journal at all; others carry a journal whose events never recorded a timestamp. Those runs could not be replayed as real animated timelines or filmed, and the episode manifest treated them as journal-less, handing them an invented timing profile rather than a real one.
This job rebuilds the missing timelines from what git already knows. A run's ledger records which commit finished each sprint, and every commit carries a real wall-clock time. Anchoring a timeline on those commit times turns an absent or untimed journal into a real one. The reconstruction stays honest about what it did: it stamps every rebuilt journal with a marker recording that the journal was reconstructed, when, by which version, and which instants are real commit-anchored boundaries versus interpolated spacing — so a rebuilt timeline is never mistaken for one that was measured while the run actually happened.
Build
The work split into a pure reconstruction engine and the layer that surfaces it, and the engine itself into an input reader, an honesty-and-classification mechanism, two separate rebuild strategies, and an orchestration entry point — an order where each piece was provable before the next depended on it.
The outer boundary is between an engine that reconstructs a journal and the command-line and pipeline work that lets an operator invoke it. The first milestone builds the engine as a self-contained module with no verb, no replay change, and no manifest change; the second puts a by-hand verb on top and wires the rebuilt output into replay and the episode scan. That ordering let the whole engine be tested against on-disk fixtures before any of it was exposed, so the CLI milestone consumed a module that was already proven rather than growing logic and surface at once.
Inside the engine the cut turns on what a run has left on disk. A run whose journal is complete but missing only timestamps needs a timestamp overlay: keep every recorded event and field exactly, add a monotonic `ts` to each, anchoring every sprint-finished event on its commit's real time. A run with no journal at all needs synthesis: emit one started/finished pair per done ledger row from the sprint files and commit times, and leave metrics absent because none were ever measured. The briefs make these two rebuilds pure functions from their inputs to a timestamped event list, keeping file writing and classification out of them, so each strategy could be exercised on a fixture without touching disk. A classifier ahead of them decides which of four cases a run is — genuine, already-backfilled, overlay, or synthesis — and the orchestration entry point wires classify, dispatch, mark, and atomic write into one call.
The run stayed green apart from a single stress point, and it landed on the foundation. The ground-truth-readers sprint — the input layer that resolves a commit sha to a time and reads a ledger's ordered rows, the layer every later sprint consumes — is the one the gate sent back after review; a fix landed it and it went green. That the failure sat at the base and not in the harder overlay or synthesis sprints is the point: those reconstructions were built on already-typed ground truth the first sprint had established, and they passed clean. No review forced a re-plan, and the two-milestone cut held from the engine through the verb, the replay note, the scan promotion, and the docs.
Feature
Before this job, old runs without a timestamped journal were second-class downstream — journal-less in the manifest, degraded in replay, unfilmable. It left a reconstruction engine that rebuilds their timelines from git, two by-hand verbs, and honest handling across replay and the scan, all still standing at HEAD.
The problem this answers is that a finished run without a real per-event timeline had nowhere good to go. Replay fell back to a degraded path warning that nothing would animate; the manifest scan flagged the run journal-less and gave it an invented timing profile; and the screencast pipeline had no way to promote such a run before filming. The old cohort — runs that predate the journal, and runs whose journal never carried timestamps — were stuck that way.
The engine that answers it lives in one module. It classifies a run into four cases, then either overlays timestamps onto an otherwise-complete journal or synthesizes a coarse chunk-level timeline from the ledger and commit times, prepends a provenance marker, and writes the result atomically so a failure mid-write leaves the prior state intact. The marker uses a deliberately novel record type that rides untouched through Gantry's existing journal reader, which is what lets a rebuilt journal be read back as ordinary events while still being recognisable as reconstructed — and lets a re-run detect its own prior output and skip it. Two bare-first-argument verbs drive it: one reconstructs a single named run in place, one sweeps a whole registry and skips every run already timed or already backfilled. Downstream, replay surfaces an honest note that the timeline was reconstructed from git commit times instead of the degraded warning, and the scan promotes a backfilled run to the real timing profile.
Standing in the tree today, all of this is present. The engine module is the largest thing the job left and nearly all of it survives; the verbs are registered and documented in the command listings; the replay note and the scan promotion are in place, tested at their unit boundaries; and the screencast README documents backfill as a step in the by-hand pipeline — curate the manifest, backfill the old journals, re-scan, render. Nothing later folded the capability into a larger design or replaced it; the actual mutation of the real registry remains the documented by-hand follow-up the plan left outside the gate.