19 review comments, one mistake, zero memory: giving Claude Code a guilty conscience
Claude Code writes code that works. Builds, tests pass, CI green. Then a human reads it. IList on a Kafka message. Compiles, serializes, consumer can't deserialize an interface. Kafka has no opinion on your abstractions. List . Variable named result . In a codebase where even the loop variables hav

Claude Code writes code that works. Builds, tests pass, CI green. Then a human reads it.
None of it in CLAUDE.md. All of it known to every human on the team, including the one who joined last week. That's the gap: tacit knowledge. The reviewer has it, the model doesn't, and nothing moves it across except the reviewer, again, by hand, with a slightly shorter comment each time.
Each comment gets fixed. Next PR, same class, different file. Fixing the comment removes today's symptom. Capturing why is the only part that changes the next PR.
lessons.md, hand-written, imported from CLAUDE.md. Rule for Claude: reviewer catches something, add a line.
Three months in: 99 lines, 312 captures logged, top line hit 19 times. Not 19 reviewers. One class, "after a rename, search the whole repo, not your diff", caught 19 times, each with a new wrinkle, by reviewers of steadily declining patience. Second line at 10. Third at 8. The file had become a leaderboard.
Claude had every line in context every session. Didn't matter. 60k tokens into a change, the line is somewhere behind three file reads and a test run. Memory wasn't the problem. Timing was. Nobody re-reads the safety briefing mid-flight.
Then four bash hooks and jq. Every script: command -v jq || exit 0. No jq → silently dead, no signal. Found out weeks later. The system had achieved perfect silence, which is the one thing it was built to prevent.
github.com/N1XUS/tacit. Claude Code plugin. Stores papercuts: small, repeatable, they add up. Three parts.
Hook fires after gh pr view --comments / gh api …/comments. Points at a skill: triage each comment, fix the valid ones, then answer one question per fix:
Why did I write it that way? What class of mistake is this an instance of?
"Forgot to remove the enum" is not a root cause. "Scoped the removal to files I was already editing" is. The first one gets you a sticky note. The second one gets you a grep.
Global: "Message types cross a serialization boundary: concrete collections, never interfaces." Local: "Kafka payloads: List<T> not IList<T>, grep -rn 'IList' src/Messages/."
One file can't hold both "every line generic" and "on second hit, rewrite as a concrete command". Concrete commands are stack-specific. So two files. Took me embarrassingly long to stop fighting that.
Scoped variant:.claude/papercuts/sql.md with paths: frontmatter, injected only when a matching file is written. Same schema as native.claude/rules/, so promotion is a file move.
Every global line ends [hits: N, last: YYYY-MM]. Same class caught again → increment, sharpen wording, no near-duplicate. hits >= 2 → lint fails: rewrite as a check, put the command in the local store, mark escalated.
Hits are self-reported by a model. Asking a model to count its own mistakes is asking a cat to log its own vase incidents. Cheapest way to satisfy "increment, don't duplicate" is to duplicate anyway and report a clean conscience. So every capture appends a line to papercuts-log.jsonl, and tacit audit diffs log against counters. Logged > claimed: near-duplicates added quietly. Claimed > logged: capture without log line. Evidence, not a hunch.
Hard cap 30 per tier. Line 31 is where checklists go to become decoration. An unread checklist is worse than none: looks like coverage.
Correction detection: "you did it wrong, here's how". No finite grammar. Tried:
Shipped: one-line reminder, 1st prompt then every 10th, names which skill handles reviews / PR comments / corrections. Main model judges. It already holds the prompt, it's the smartest thing in the room, and it works for free. Any language. ~60 tokens per 10 prompts. Re-arms after compaction. The dumbest option, after a full day of clever ones.
All three classifiers removed from the tree. Not flagged off. Removed. Dead code behind an opt-in is dead code with a nicer funeral.
Checked against Claude Code 2.1.278. Auto memory records corrections ( type: feedback ), per repo, on by default. Project-root CLAUDE.md survives compaction. Path-scoped rules load on read/write, summarised away on compaction.
Nothing native: root-cause capture, recurrence counters, counter audit, generic/local split, checklist at write or push time. Those are why this exists. Day the host ships them, I delete it, gladly. I have other papercuts.
claude plugin marketplace add N1XUS/tacit claude plugin install tacit@tacit Enter fullscreen mode Exit fullscreen mode Store files: plain markdown, yours, outside the plugin dir. Disable the plugin, papercuts stay. Like real ones.
tacit list · tacit audit · tacit doctor · tacit config local <path>