The workflow /

Where the time actually went, measured honestly enough to hurt.

A portfolio of projects generates a comforting amount of activity. Counting it naively produces a number that feels like progress, and the main thing that number measures is how much of the work was done by a robot on a timer.

From ~/dev/METRICS.md · A definitions file with a machine-readable block, plus three reporters · Verified 2026-09-11

Definitions live in one file, before any reporter.

Windows, signals and filters are declared once, in a fenced block a program can read: what counts as active, how far back to look, which authors to exclude, where the project mapping lives.

Every reporter reads that file. Each falls back to its own prior default when a definition is missing and prints a warning naming the key, so an undefined metric is visible rather than silently assumed.

  • Active window: 21 days.
  • Bot commits excluded by default.
  • A missing definition produces a warning per key, never a silent default.

Most of the activity was a daemon.

A nightly job committed to one repository on a schedule. Counted naively it read as the most active project by a wide margin — a thirty-day window of 582 commits, of which 574 were the daemon's own.

Filtering by author identity fixed that case. It did not fix the general one, and the general one is more interesting.

The obvious fix was wrong, and was rejected.

A second project's commits were all authored under a human name, but most carried an assistant co-author trailer. Filtering on that trailer produced the right answer for that project and a badly wrong one elsewhere: a repository with a full day of real work and a passing test suite dropped to zero, because its single commit was co-authored too.

Assistance is not automation. A trailer cannot tell an unattended job apart from a person working with a tool, and treating them the same produces a lie in the opposite direction. The filter was implemented, measured, and left switched off rather than shipped.

The fix was to emit the signal at the source.

Rather than infer intent from a message after the fact, the automation now declares itself: a commit hook stamps a marker only when a job runs unattended. Interactive work carries no marker, so nothing has to be guessed from a trailer.

Pattern matching after the fact was replaced by a declaration at the moment of the commit — the only point where the answer is actually known.

The ledger exists to make a choice, not a chart.

The output is not a dashboard. It answers which ventures received attention this period, which received almost none, and where work is happening that no plan accounts for — and it is only useful if it can deliver bad news.

A measurement system that cannot report that a favourite project got no attention this month is decoration.