Generated report
Dev Log: 2026-07-15
The Hugo demo had become a liability. It looked fine, but it was welded to one renderer, it couldn't cleanly ingest the project's native artifacts, and every time I opened it I remembered that "demo" is not the same word as "example of what this tool is actually for." So the week turned into a reckoning: what does Timbers publish, what does it claim, and where has the story drifted from the code?
The biggest move was ripping Hugo out and standing up an Eleventy-based harness — Timbermill — in its place. The contract went first, on paper: platform-neutral Markdown collections, a materialization boundary, native-artifact semantics, route compatibility, and a responsive verification matrix. Only then did the rewrite happen. Public routes preserved, containment and output checks added, collection discovery generalized, and a light/dark layout that actually reads on a phone. A substantial chunk of plumbing, but boring in the good way.
While the site was being reshaped, a related question surfaced: what should Timbers publish for the user? The old answer — heuristically generated, numbered ADRs — had always been slightly embarrassing. They competed with the project's real ADRs. They implied lifecycle and authority they didn't have. So they're gone, replaced by decision digests: non-authoritative, source-citing, unnumbered. Native ADRs stay the authority. The digest is a reading aid, not a record.
Digests needed a repeatable shape, which meant a new report command with frontmatter profiles — scope, projection, format, quiet output. The tricky call was resisting the urge to build a second workflow engine. draft stays the low-level primitive; report is a thin, opinionated wrapper. Provenance metadata and best-effort Git enrichment come along, and the whole path is fail-closed: if the ledger has a corrupt entry, no partial artifact ships. That last part matters more than it sounds. Silent data loss in a tool whose entire job is durable rationale would be a special kind of failure.
Which led to a subtler decision about what "durable" means. Ledger entries used to lean on Git for their what — echoing commit subjects felt redundant to type. But history gets rewritten. Rebases, squash merges, force pushes. So what, when omitted, now snapshots the resolved commit subjects at capture time. Git enrichment stays as optional flavor at report time; the stored text is the fallback. Patch IDs came up and got deferred — they don't solve many-to-one squash merges, so they'd be theater.
And then the catchup command — the one that used an LLM to infer historical rationale — got retired. This one I'd been circling for a while. The output was low-confidence data stored in the same shape as authored reasoning, which is exactly the kind of contamination this tool exists to prevent. First-log baselines, batch logging, and ignore rules already cover the honest adoption cases. Keeping catchup around was a bet that convenience beat integrity. It doesn't.
The remainder was documentation reconciliation, which sounds tedious and mostly was. README, help text, agent guides, template syntax, storage guidance around destructive SHA rewrites, report-versus-draft distinctions. A drift regression test now guards against the specific stale claims most likely to recur. The plan document that inventoried all this drift is itself in the repo, which felt correct — the audit is part of the record.
The pattern underneath all of it: provenance beats convenience. Every decision this week came down to the same question — is this artifact the source of truth, or is it citing one? If it's citing, say so plainly. If it's authoritative, protect it fail-closed. And if a feature blurs that line, it probably shouldn't exist.
Where that leaves things: the demo site is honest about what it is, the report path has a shape you can actually use without hand-rolling conventions, corrupt entries can't hide, and the tool no longer generates rationale it didn't earn. Solid ground. Not finished ground — Timbermill still has to prove itself as a companion outside this repo, and the digest format will get poked at once real users run it — but the story the code tells now matches the story the docs tell, which hasn't been true for a while.
Written with AI assistance from session logs.