Lossless Changelog
product

Most of what we write isn't code

The ledger counted every line as code. Two thirds of them aren't — and the chart now says so, day by day, project by project.

Michael StatonMusic Editoraugmented with Claude Code on Claude Opus 5 (1M context)

Most of what we write isn't code

Why Care?

This site opened with a number: 5.9M lines. It read as a code metric, and it wasn't one. Every line anyone had ever committed — specs, ship notes, prose corpora, a lockfile, an accidentally-committed node_modules — landed in one undifferentiated pile and got filed under "code."

In this tree that is badly wrong in a specific direction. astro-knots carries 71,000 lines of context-v/ against 13,000 of actual code. lossless-ai-labs carries 166,000 against 38,000. The documentation is the work, and the headline was quietly crediting all of it to the compiler.

The fix is not a smaller number. It is four numbers.

What's New?

Lines are counted by kind. Code, context-v/, changelog/, and content each get their own counter and their own segment of a stacked bar:

Lines
Code2,731,61562%
Context757,77117%
Changelog294,6457%
Content649,83415%

The chart shows focus days. 317 days in this record had a commit. 124 of them carried more than ten, and those 124 days account for 76% of every commit ever made here. The busiest was 129 commits in a single day. That is what a solo operator's output actually looks like — not a steady rate, a handful of days a month given over to it entirely.

The changelog surface finally exists. The site that publishes everyone else's ship log had no page for its own. /changelog now renders it through @lossless-group/lfm, pinned to 0.5.1.

Filter by project. Four chips — AI Labs, Astro Knots, Content Farm, Misc — each wearing its project's own favicon, pulled out of the project's own repo. No client JavaScript; the whole thing is a radio group and :has().

How it Works

There is no API for this

GitHub's /stats/contributors is the only series behind the old number, and it returns weekly additions per repo with no path attribution whatsoever. There is no endpoint that buckets lines by directory. Getting it from the API would mean walking all 4,300 commits one at a time.

The local clones already hold the answer. scripts/sync-line-classes.mjs walks every manifest repo, runs git log --no-merges --no-renames --numstat, and classifies each added line by its path.

--no-renames is deliberate. Git's default rename detection reports a moved file as 0/0, which would erase every large reorganization from the record.

A hybrid, and why

Two sources, each doing what it is good at:

_commits.json   GitHub's per-repo additions   →  the DENOMINATOR
_lines.json     local git, split by path      →  the RATIOS

They disagree, and not by a little — GitHub credits astro-knots with 158k additions where the repo, verified in sync with origin, carries 122k. We do not try to reconcile them. GitHub's cached figure decides how big the pie is; the local history decides how it is sliced. Every number is an estimate with an exact shape.

The clamp that had to exist

We removed node_modules from this repo's history the same day. Local additions dropped from 1,075,860 to 80,635 while GitHub's cached stats still reported 2,151,718 — a 26.7× scale factor that inflated the fleet's code total from 2.8M to 4.7M in one rebuild.

Every other repo sits between 1.0× and 2.6×. So the band is empirical:

TS
const SCALE_MIN = 0.5;
const SCALE_MAX = 3;
// Out of band means the two sources disagree about what history IS,
// most likely because it was rewritten. Trust the measurement.

Rejected factors fall back to the measured local count and are exposed via unscaled rather than swallowed. A silent fallback that moves a headline is exactly the kind of thing the next person should be able to find.

Under the Hood

The chart was lying about its own resolution

The ledger strip square-rooted entry counts against a 27-entry outlier. The result:

entries/day   # days   rendered height
     1          50          19%
     2          24          27%
     3          13          33%
    27           1         100%

69% of days rendered between 19% and 33% height. The chart spent its entire vertical range on twelve outlier days while the other 114 were visually identical. Now it is linear, clipped at the 95th percentile — 1→13%, 2→25%, 3→38% — with the four days past the cap drawn full height and dashed so a capped mark is not mistaken for an exact reading.

Commits went daily, not weekly. A weekly bucket averages away the difference between an ordinary Tuesday and a day of total focus, which is the one distinction this record is about.

Hue means when, so the bar means value

The brand ramp is mapped onto the corpus's time axis — teal is early 2025, amber is now — and colouring anything else with it would break the one thing a reader is being taught to read. So the line-kind bar separates by value alone: code at full text colour, the three prose kinds stepping down from it. The floor is 0.24, because below roughly a fifth a white segment stops separating from the track behind it.

What gets dropped, and why it is not a rounding detail

Lockfiles and vendored trees are excluded outright — nobody authored them. Also reports/, which everywhere in this tree holds machine output: lossless-content keeps eight evaluation-output dumps totalling 183k lines inside changelog--content/reports/. Left in, those alone would have overstated the fleet's changelog volume by half.

Files Touched

  • scripts/sync-line-classes.mjs — path classification, per-repo and per-day series

  • scripts/sync-icons.mjs — each project's favicon out of its own repo

  • scripts/lib/clones.mjs — repo→clone resolution by origin remote, shared

  • src/lib/lines.ts — the hybrid, and the scale clamp

  • src/lib/daily.ts — per-day commits and lines, merged per subtree

  • src/lib/groups.ts — the four filter buckets

  • src/lib/ownChangelog.ts — this repo's own entries, kept out of the aggregate

  • src/components/LedgerStrip.astro — daily commits, linear clipped scale, month ticks, interactive key

  • src/components/LineBar.astro — the stacked bar

  • src/pages/changelog/ — the surface that was missing

What's Next

  • The ledger row counts still flip meaning by depth — a root shows its subtree, a child shows only itself, so MemoPop AI reads 5 while its own child reads 71.

  • context-v/ files are counted nowhere. astro-knots has 103 of them against 12 changelog entries, and by the only number on its row it looks like one of the quieter projects.

  • Hue and horizontal position carry identical information. Colour could encode line kind or project instead, and do real work.

  • design-system/ is still a generated export at the repo root rather than src/pages/design-system/ where the convention puts it.