RunMirror
← All posts
TAB Forward — Chapter 5
Oct 14, 2026·9 min read

The Silent Seven Nights

What an assessment of my own repo got right, what a green status page got wrong, and the four practices I finally let into the pipeline.

TABForwardRunMirrorEngineeringPracticesDORABuildInPublicFundari

← TAB Forward — Chapter 4: The Founder, The Calibrator, and The Customer


The report I wrote about myself

In August I pointed Fundari, the engineering-practice assessment tool I have been building, at RunMirror, the running app I have also been building. It scores a repository the way DORA would if DORA were a careful colleague: every score has to cite a commit, a file and line, or an explicit absence, or it says INSUFFICIENT EVIDENCE and moves on. No blending. Every report ends with a section called What wasn't done, stated rather than hidden.

The August baseline said what you would expect of a solo repo built at AI speed: no CI, no automated tests, no dependency updates, no security policy, no error tracking. It summarised the whole thing in three words that I did not enjoy reading: process absent, reflex present.

I nodded, closed the report, and shipped thirty-five more commits.

Sixty days later

On October 12 the tool re-ran the same collectors and computed a trend. Here is the line that mattered:

Thirty-five commits, zero capability-score movement on the gaps.

And the one that stung:

"next": "latest" is still in package.json 67 days later. A finding in a Markdown report, however specific, is not a pull request.

Both true. I had built a lot of product in those sixty days. Signed sessions, webhook hardening, a seven-day retention purge to meet Strava's API policy, a whole editorial section. None of it moved the four gaps the report had named, because the report was a document and documents do not block merges.

The seven nights

Here is what the gap cost, concretely.

The retention purge is the one job in RunMirror that is compliance-critical. Strava's policy says API data lives at most seven days in my database, and the purge is what enforces that. It ran every night at 04:17 UTC. Every night it returned ok: true. Every night it deleted nothing from the two tables that mattered.

The cause was mundane. A single DELETE over ten thousand GPS stream rows took longer than the database's eight-second statement timeout. The database cancelled it, the API layer returned a 500, my code caught the error, wrote it into a results object, and the route still answered OK because nothing checked the results object. For seven nights the app was out of policy while every signal I had said it was fine.

I found it by accident, pulling a status report for a capacity request. The dry-run counter showed ten thousand rows waiting. Nothing had alerted, because there was nothing to alert. The August report had said error tracking: absent. It was right, and I had not done anything about it.

The fix took an afternoon: delete in batches of five hundred primary keys, return a real 500 when any table fails, log at error level. The backlog cleared in twenty-eight seconds. That part of the story is not interesting. The interesting part is why the fix came from an accident and not from the system.

What learning actually looks like

I used to think of learning as reading the finding and understanding it. I understood all four gaps in August. Understanding changed nothing.

The thing that changed something was the tool opening pull requests. Fundari's second pass did not stop at a report. It opened four PRs on RunMirror, each one tied to a specific finding and the capability score it should move:

  1. Pin the framework version and declare the Node runtime, so a build on Tuesday is the same build on Friday.
  2. Dependabot, weekly and grouped, so updates arrive as one reviewable PR per ecosystem instead of never.
  3. A security policy: where to report, what is in scope, what to expect back. One page.
  4. CI: npm run build on every push and pull request, on a machine that is not mine, with every third-party action pinned to a commit SHA.

Each PR was small enough to review in minutes. None of them changed product behaviour. I merged all four this morning. Dependabot opened its first two PRs within the hour and CI built both of them before I had finished my coffee. Sixty-seven days of inaction ended in a morning, because the finding had been converted into the one form I cannot ignore: a diff with a merge button.

That is the lesson, and it is not about AI. A finding becomes a practice at the moment it becomes a pull request, and a practice becomes a habit at the moment it becomes a required check.

The practices I am letting in

Writing them down so the next report can hold me to them.

Evidence or nothing. A score, a claim, a status line cites a SHA or a file and line, or it says it does not know. The purge route now follows this rule: it reports the counts it actually deleted, and a failure is a failure.

A finding is not done until it is a PR. Reports are for understanding. PRs are for change. If I write a finding about my own code and it is still a sentence a week later, that is the gap.

Propose, do not merge. The tool that assesses my repo opens PRs and never merges them. That boundary came from an incident on another project, where a dependency mismatch took production down behind a green CI run. The stance is versioned like code. I like that the thing judging me cannot also act for me.

Re-baseline on a clock. The same collectors, sixty days later, and I say what I expect the trend to be before the tool computes it. The August-to-October diff was the single most useful artefact of the quarter, precisely because it was unflattering.

Every PR names its finding. The commit message says which gap it closes. Failed attempts stay in the log, not smoothed over.

What is next in the pipeline

Making the CI job a required check, so the practice stops depending on my memory. Error tracking, so the next silent failure is loud. A test for the purge, because the one job that must run every night should have the one test I actually maintain. And a third baseline in December, where the expected trend is, for once, upward.

The reflex is still there. The process is finally arriving. It arrived as four small pull requests from a tool that refused to let a finding stay a finding.


RunMirror is a Strava-connected reflection tool for runners. Fundari is the assessment tool that scored it. I am building both, which is either a conflict of interest or the only honest way to test the second one.

Try RunMirror

See what your running data says about you.

Connect Strava. Get the 60-second story of who you really are as a runner.

Open RunMirror →