Savra

We Track 136 Known Issues in One Markdown File

A 136-entry bug ledger with no ticket system: what every entry carries, the eight buckets a census found, and the four-verdict triage that keeps it honest.

Kash · FounderUpdated Sep 6, 20266 min read
Poster: "four verdicts" over a soft pastel sky and the number 136 known issues (We Track 136 Known Issues in One Markdown File)
On this page

An issue list you never re-read drifts into fiction. Entries describe code that has since been rewritten, bugs that got fixed in passing, decisions someone made and forgot to record. The list grows, trust in it shrinks, and one day the team declares backlog bankruptcy and deletes the lot, along with the six real bugs buried in it.

We counted the open findings in ours this week: 136, the oldest from early June. No Jira, no Linear, no GitHub Issues. The whole ledger is one markdown file in the repo, next to the code it describes.

One file, in git, next to the code

The ledger lives in the repository as a markdown file with a section called Known Issues. Anyone who finds a problem mid-task appends an entry the moment they see it, whether or not it relates to what they were doing. Recording a finding costs about thirty seconds. Rediscovering it three months later costs an hour.

How a finding travels from discovery through the ledger to a triage verdict

Most of the code in question is written by AI coding agents, and an agent starts every session with no memory of the last one. The file is the memory. A finding written down on Tuesday is read by a different session on Thursday with full context: where it lives, how severe it is, who owns it. The same property helps humans, since the reader of a six-month-old entry has forgotten the details even when the reader is you.

Git turns out to be a good issue database. Every entry has an author, a timestamp and a diff. Review covers the bug reports because the bug reports ride in pull requests. And the ledger is greppable from the terminal where the work happens, which is the difference between a list that gets consulted and a list that gets ignored.

An entry is a claim, so it carries evidence

The format is one line per finding, and the line has a shape. Date and session first, then a category and severity, then the claim itself in bold, then the evidence, the shape of the fix if it is visible, and an owner.

The anatomy of a known-issues entry, annotated field by field

The evidence field carries the weight. A file path and a line number make the claim checkable by anyone, months later, in seconds. Without them an entry is a rumor, and the next reader pays an hour to re-derive what the writer knew and did not write down.

Two rules keep the section trustworthy. Entries are append-only: when a finding is resolved it keeps its original text and gains a dated stamp naming the fix, so the record shows what was believed and when the belief changed. And a status needs proof. "Resolved" with no commit reference or verification note does not count, because unverified good news is how a ledger starts lying.

What a census of 136 findings looks like

After three months of this we ran a census: read every entry, sort it into a bucket, count.

136 open findings sorted into eight buckets, plus five resolved entries awaiting archive

The shape taught us three things.

The biggest bucket is barely bugs at all. Forty entries are recorded decisions and small code debt: a timeout that looks wrong and is deliberate, a duplicated helper kept because merging it would change behavior, dead files awaiting deletion. Writing decisions into the ledger stops the team from re-litigating them, which makes this bucket a feature.

The dangerous entries are the quiet ones. One finding noted that a feature with no usage meter accounted for nearly half of what a heavy user costs us to serve. Another documented a sync to our email CRM that catches its own failure, logs a warning, writes the local row anyway and reports success, which is why nobody noticed it failing for months. Neither throws an error. Both surfaced because someone was reading code for an unrelated reason and wrote the observation down.

And fifteen entries were never issues. They are working habits and environment quirks, useful knowledge filed in the wrong drawer, and the census is what exposed them. Those move to the docs where they belong.

Triage day: every entry gets one of four verdicts

A census tells you what you have. Triage decides what is still true. The pass runs oldest first with the code open, and every entry leaves with exactly one verdict.

The four triage verdicts and what happens to an entry after each

Closed with evidence. The claim no longer holds, and the entry gains a dated stamp proving it: the commit that fixed it, or the code showing the described behavior is gone. Belief is not proof, so a verdict of closed without a stamp is not allowed.

Still open, reaffirmed. The claim holds. The entry gets a fresh verification date, and its severity or owner gets sharpened while the code is in front of you. A reaffirmed entry is worth more than a new one, because two people at two times have now confirmed it.

Promoted to a task. Real, and too large to sit in a list. It moves to the backlog with a scope, joining the queue that our QA patterns run against.

Routed to a decision. Some findings are product questions wearing a bug costume. How long to retain audit records, whether a free feature gets a quota, whether a vendor plan is worth upgrading. These get batched for the human who owns the call, instead of blocking the pass.

One discipline makes the day work: fix nothing larger than the verdict. Deleting an unused import while you are looking at it is fine. Starting a refactor is how triage turns into a rabbit hole and the remaining hundred entries stay unread.

The contract that keeps the file alive

A ledger that only grows eventually cannot be read, so ours has a rotation contract. Open entries never leave the live file, whatever their age. Closed matter moves verbatim to an archive file in the same repo, so a grep still finds every finding ever recorded. A size tripwire warns when the live file outgrows what one session can read comfortably.

The census pass alone, before any code was opened, closed nine entries on evidence that already existed in the file. That is the argument for the whole system in one number: the list got shorter by getting read, and a list that rewards reading is one people keep writing to.

Key takeaways

  • A bug report is a claim. A date, a path, a line number and an owner make it checkable; without evidence it is a rumor with a timestamp.
  • Triage is a verdict pass, and reading oldest-first with the code open shrinks a backlog faster than a fix-everything sprint. Four verdicts cover every case.
  • Keep the ledger where the work happens. Ours is a markdown file in git because our coding agents read it at the start of every session, and what they read, they act on.

What's next

The full triage pass is scheduled, and the follow-up post will report what 136 entries became: how many closed, how many were promoted, and what the decision batch looked like. If the census shape holds, the list comes out of it half the size and twice as trusted.

Keep reading

See if your brand sounds like itself.

Run the free 90-second Brand Genome audit. No card, just your score.