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.

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.

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 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.

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.

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

5 QA Patterns for Multi-Agent AI
No review, self-critique, supervisor review, human approval and double review, with the latency and token cost of each, and a decision matrix that picks by stakes and speed.

Why Your LangGraph Agent Loses Its Memory
Pydantic AI tool calls inside a LangGraph node do not emit to astream_events. Capture state from the node's return value via on_chain_end instead, in about ten lines.

We Added 3 Lines of Code. AI Costs Dropped 57%.
A first-hand account of enabling Anthropic prompt caching: the trace that found the bottleneck, the three settings that fixed it, and the before-and-after cost and latency numbers.
See if your brand sounds like itself.
Run the free 90-second Brand Genome audit. No card, just your score.