Brain · Errors

Keep a fixed defect, and find the rule that keeps failing

The Errors tab renders one flat markdown file, .claude/brain/errors.md, and measures it. Each entry is a defect you fixed and the rule you wrote to stop it. RepoOps traces each entry back to the session that caused it, counts entries per week, and groups entries whose prevention rule is the same, which is the signal that the rule did not hold.

For: the engineer who writes the entry after a fix, and the person who reads the weekly trend

What it does, and why it helps

There is no page to build and nothing to regenerate. You write an entry under a ## YYYY-MM-DD heading in .claude/brain/errors.md, and the tab renders that file per request. The parser splits on that heading and skips a heading it cannot date rather than failing. The dashboard reaches it at /brain/<repoId>/errors.html. With the file absent the tab reads Nothing here yet and tells you to log the first error you fix.

Two readers then work on that file. The first is the trail: each heading is sent to /api/causal-link, and when a captured session window overlaps the commit that blame walks to, the tab appends a Caused by block carrying the commit, the session and a prompt excerpt. A multi-candidate match, or one whose blame walk crossed an unresolved squash, reads Possibly caused by and never counts toward attribution. A Save as lesson link carries the coordinates into the Lessons form. The second reader is lib/brain-metrics.mjs. It hashes the first Prevention rule. paragraph of each entry, falling back to the entry's title, and any fingerprint that appears on more than one entry is a recurring class. It also counts entries over four rolling weeks and calls the trend down, up or flat. Both readings surface on the Today tab, in the panel called Brain pulse.

The pain. A defect gets fixed and the reason evaporates with the branch. Six weeks later someone writes the same bug, and the only record that it happened before is in one person's head.

The point of view. An entry is worth writing only if something reads it back. So the file is measured rather than archived: the same rule written twice is evidence the rule failed, and every entry is traced to the session that introduced it before anyone argues about who wrote it.

What gets easier. Seeing the pattern. The recurring class names the rule and how many entries share it, the trend says whether this week sits above or below the prior three, and the caused-by block says which session and which prompt the defect came from.

When it helps. A repository with a .claude/brain/ directory, on a machine that captures sessions and has the git history the blame walk needs. The trail is strongest when commits carry a Session-Id trailer.

Its limits. An entry in errors.md never reaches CLAUDE.md on its own. The managed block renders active lessons only, and the nightly pass promotes a traced defect as an inactive lesson that a person has to activate. A recurring class has no time window: it is the same fingerprint anywhere in the file, however old. An entry with no Prevention rule paragraph is fingerprinted by its title, so two entries that share a rule but not a title do not group. And none of this prevents a repeat. It tells you the rule you already wrote did not hold.

Understand it in 30 seconds

30.1 s, captions on. Narration: Microsoft Zira Desktop (provisional voice; an approved narration source is pending).Transcript
Read the narration
  1. 0:00 A defect gets fixed.
  2. 0:02 The reason leaves with the branch.
  3. 0:06 RepoOps hashes the prevention rule you wrote.
  4. 0:09 Two entries, one hash, means the rule failed.
  5. 0:13 The tab traces each entry to the commit, the session and the prompt.
  6. 0:17 A weaker match says possibly, and never counts toward attribution.
  7. 0:23 Question the rule, not the person.
  8. 0:26 Nothing reaches the manual without you.

Synthetic example. Read the guide

Where to find it

Where to find it

  • Desktop: localhost:4000. It has no sidebar row: open it from the palette, or go straight to its address.
  • Hosted: repoops.ai/team/docs/errors.md. It has no sidebar row: open it from the search box, or go straight to its address.
  • Keyboard: ⌘ K, then type “Errors”.

When to use it

You fixed something and want the reason to survive

Situation. A lock with no timeout hung the preflight run. You found it, fixed it, and the branch is about to merge.

What you do. Add an entry to .claude/brain/errors.md under a dated h2 heading: what broke, the root cause, the fix, then a paragraph that leads with the words Prevention rule in bold. Open the Errors tab.

What you see. The entry renders at the top of the tab. Under its heading a Caused by block names the commit, the session and the prompt excerpt, with the band beside the label. Save as lesson opens the Lessons form with the trigger and the excerpt filled in.

What it establishes. The defect now has a written rule and a traced origin. The next session's briefing can carry it: the briefing reads up to three open entries, an entry counting as open when its heading starts with an hourglass, construction, warning or exclamation marker, or its body has a Status line reading open, unresolved, in progress or pending.

The same rule keeps coming back

Situation. The Today tab shows a recurring class line naming a rule and the number of entries that share its fingerprint.

What you do. Open the Errors tab and read the entries behind that fingerprint. Decide whether the rule was wrong, too vague to follow, or right but unenforced. Then rewrite it, or turn it into something mechanical: a lint rule, a CI check, a guard.

What you see. GET /api/brain/metrics returns the class with its fingerprint, occurrence count, first seen, last seen and the first three entry titles. The same numbers drive the Brain pulse line.

What it establishes. Recurrence is measured rather than assumed. The count is the number of entries sharing a fingerprint, which is a claim about what you wrote down, not a claim about how often the defect occurred.

The nightly pass proposed an entry you did not write

Situation. The 02:00 pass ran. The Brain reflection tab lists proposals under errors.md, and a lesson you did not create is sitting inactive on the Lessons tab.

What you do. Read each card. Accept appends the body to errors.md. Reject writes the full body into .claude/brain/proposed/rejected/ and records the proposal id. On the Lessons tab, refine the promoted lesson and activate it, or leave it inactive.

What you see. An accepted proposal appends to errors.md and its 12-character id lands in proposed/accepted/errors-ids.json; a rejection lands in proposed/rejected/errors-ids.json. An accept made over the local API is wrapped with an untrusted-source marker, so the origin of the prose stays visible in the file.

What it establishes. The file stays a reviewed record rather than a machine log. One caveat worth knowing: the auto-drain can accept a high-confidence proposal without you, up to 20 a run, and stamps each one auto with a reason.

Before you start

Supported versions
RepoOps desktop v0.3.1, the release this guide was read against. The tab needs .claude/brain/errors.md in the tracked repository. The caused-by trail needs captured sessions and the repository's git history. The nightly pass needs the app or the capture daemon running near 02:00 local, or within 48 hours of the last run.
Where it runs
Local: Memory, then Brain library, where errors.md is listed as a known error, rendered from the markdown per request. Hosted: repoops.ai/team/docs/errors.md renders the same file from your team's published brain snapshot, and repoops.ai/team/brain-metrics shows the pulse counts rolled up across bound devices. The hosted sidebar has no Errors row; the deep link and the command palette reach it.
Permissions
Locally, writing the file is writing a file in your repository. Accepting every high-confidence proposal in one press needs the repository id typed as a confirmation, because that bulk accept writes into files your agents read as instructions. Hosted reads are session authed, the team comes from your membership rather than a parameter, and the per-repo scope is resolved on the server.
Connections
ANTHROPIC_API_KEY on this machine for the nightly reflection that proposes entries, and for the model-drafted body on a promoted lesson. Without a key the deterministic half of the nightly pass still runs, correlation and promotion still happen, and the lesson gets a placeholder body. A bound device and the Brain snapshot publisher for the hosted page.
Plan
Free local. The pricing capability map lists the flat-markdown brain and the full accountability loop, the caused-by trail included, as free local rows. Reading either hosted page follows the hosted dashboard tiers, and the team brain metrics page checks the hosted tier and your seat.

Configure it

  1. Write the entry under a dated heading.

    An h2 of the form YYYY-MM-DD followed by what broke, newest first, in .claude/brain/errors.md. That heading is what every reader splits on: the metrics parser, the trail script, the nightly correlator and the ledger indexer all treat one h2 as one defect.

  2. Give it a Prevention rule paragraph.

    The fingerprint is a hash of the first paragraph that leads with the words Prevention rule in bold, lowercased and stripped of punctuation. With no such paragraph the title is hashed instead, and two entries that share a rule but not a title will not group. In this repository's own errors.md, 117 of 338 entries carry that paragraph, so most entries currently group by title.

  3. Read the trail under the heading.

    The tab asks /api/causal-link per heading and appends Caused by or Possibly caused by with the band. It then asks /api/prompt-for-line and, when that answers, adds the prompt that wrote the line. No block at all means the API answered none: no session window overlapped, and none is never stored.

  4. Backfill the trail after importing history.

    POST /api/causal-link/correlate scans every heading in errors.md, security.md and anti-patterns.md against the last 30 days of sessions and writes a link per hit. It is the same scan the nightly pass runs, so the button and the tick cannot drift.

  5. Review what the night proposed.

    The Brain reflection tab lists proposals per knowledge file and carries Reflect now for an on-demand run. Accepting appends to errors.md; rejecting writes the body to proposed/rejected/ and records the id. With no key it reads No proposals yet. and says reflection needs your ANTHROPIC_API_KEY.

  6. Activate a promoted lesson, or it stays out of the agent's instructions.

    The nightly pass turns exact and strong traced defects into lessons, at most 10 a run, and every one lands inactive. The managed CLAUDE.md block renders active lessons only, capped at 12 sections and a 1500-byte budget. Until you activate it on the Lessons tab, nothing about that defect reaches the next session through the block.

  7. Decide whether the team should read the file.

    Settings, then the section What this machine publishes to your team, then the Brain snapshot switch. It is off by default and also needs a bound device and cloud sync. Publishing runs on the hourly cycle, so the hosted page can take up to an hour to fill.

SettingWhereA sensible choiceWhy it matters
## YYYY-MM-DD - title.claude/brain/errors.mdone h2 per defect, newest firstEvery reader of this file splits on it. A heading it cannot date is skipped rather than treated as an error.
**Prevention rule.**the entry bodyone paragraph, in the words you would want quoted backIt is the fingerprint. Without it the title is hashed, so grouping follows your titles instead of your rules.
ANTHROPIC_API_KEYSettings, BYOK, or the data directory's .envyour own keyThe nightly reflection makes one call per knowledge file. Without a key the deterministic ticks still run and the promotion draft falls back to a placeholder.
REPOOPS_BRAIN_DREAMthe data directory's .envleave it unsetThe string 0 stops the 02:00 pass, which stops correlation, promotion and proposals together. It is named in the code and on the Brain reflection tab, not in .env.example.
REPOOPS_BRAIN_AUTO_LESSONSthe data directory's .envleave it unset (on)The string 0 disables the nightly correlate-and-promote pass. The tab still renders and the metrics still compute.
REPOOPS_BRAIN_AUTO_DRAIN_OFFthe data directory's .env1 if nothing may reach errors.md without youLeft off, the drain accepts high-confidence proposals into the knowledge files by itself and stamps each one auto with a reason.
REPOOPS_BRAIN_AUTO_DRAIN_CAPthe data directory's .env20 (the default)How many high-confidence proposals one drain may accept. Medium confidence drains at a separate cap of 8.
REPOOPS_BRAIN_STALE_PROPOSAL_DAYSthe data directory's .env14 (the default)How long a pending card waits before the machine rejects it unread, up to 40 a run. That rejection writes the full body to proposed/rejected/, so nothing is deleted.
Brain snapshotSettings, What this machine publishes to your teamoff unless the team should read the fileIt is the switch that puts errors.md on repoops.ai/team/docs/errors.md. It also needs a bound device and cloud sync.
ⓘ
To stop or undo
Four independent levers. Turn the Brain snapshot switch off to stop publishing the file. Set REPOOPS_BRAIN_AUTO_DRAIN_OFF=1 so nothing is appended without you. Set REPOOPS_BRAIN_AUTO_LESSONS=0 to stop the nightly promotion. Set REPOOPS_BRAIN_DREAM=0 to stop the 02:00 pass altogether. None of these removes an entry already written: errors.md is a file in your repository and you edit it the way you edit any other.

What you should see

A repository that captures sessions

Configuration. errors.md present, sessions captured, the nightly pass on, the Brain snapshot switch off.

Expect. The tab renders the file. Recent headings carry a Caused by or Possibly caused by block. Today shows an errors line for this week against the prior three-week mean, and a recurring class line whenever a fingerprint repeats.

Verify. GET /api/brain/metrics returns weekly counts for four weeks, the trend, the prior mean, and recurringClasses with fingerprint, occurrences, firstSeen, lastSeen and sample titles. The band on a Caused by block should match what BAND_RULES in lib/causal-link.mjs describes for it.

A repository with no captured sessions in the window

Configuration. errors.md present, no sessions inside the correlator's 30-day window.

Expect. The entries render and the counts still compute, because the metrics read the markdown alone. No Caused by block appears anywhere, and the nightly pass promotes nothing.

Verify. /api/causal-link answers with confidence none for each heading, and none is never written to disk. That is the honest null here: the trend and the recurring classes are still readable, attribution is not assessable until sessions land.

A brain larger than the snapshot cap

Configuration. The Brain snapshot switch on, a bound device, and an errors.md over 1 MB.

Expect. The publisher cuts the file to fit and appends a visible footer saying so. The hosted page leads with a Partial file. notice naming how many bytes were not published, and points you at the desktop app for the whole text.

Verify. Compare the byte size of .claude/brain/errors.md against the 1 MB per-file cap and the 5 MB snapshot cap. This repository's own file was 710,607 bytes over 338 headings when this guide was written, so it publishes whole.

Data and cost

What is captured
The entries you write, in .claude/brain/errors.md. Beside them, one CausalLink per traced heading in .claude/brain/causal-links/YYYY-MM.jsonl, append only, carrying the defect coordinates, the commit, the session, a prompt excerpt and the band. Proposals sit in .claude/brain/proposed/, and each accept or reject decision is a 12-character id with a timestamp in proposed/accepted/ or proposed/rejected/. Entries are also indexed into the local brain ledger so search can reach them.
Who can see it
Local by default. Two separate things can leave. The brain pulse runs whenever the device is bound: it sends aggregate counts and 8-character fingerprints, never the prose, which is why it carries no redaction pass. The brain snapshot is off by default and sends the text of errors.md, redacted at egress and re-redacted on the server.
How long it is kept
Not provided. No window trims errors.md, no cron expires it, and the file grows. Proposals are never deleted either: a rejection writes a copy and the original stays until a later reflection overwrites that day's file. Hosted, the retention crons cover events, telemetry, spans and cron history, and do not reach the published brain snapshot.
What leaves the machine
The pulse POSTs to /api/brain-pulse/ingest hourly over the device token, one upsert per device and repository. The snapshot POSTs the redacted files when brainpublish.enabled is 1, bounded at 1 MB a file, 5 MB a snapshot and 500 files; a republish deletes the older versions for that device and repository. The machine-data subtrees, causal-links included, and the forward-only session and pull-request logs are never published. The nightly reflection calls Anthropic on your key, one call per knowledge file; the promotion drafter is a separate short Haiku call per promoted lesson, capped at 10 a run.
What it costs
The fingerprinting, the trend, the correlation and the trail are local and make no model call. The model cost is the nightly reflection and the promotion drafts, both on your own key, and both stop when the key is absent or REPOOPS_BRAIN_DREAM is 0.

When the result differs

SymptomLikely causeNext action
The tab says Nothing here yet.The tracked repository has no .claude/brain/errors.md.Create the file and write one dated entry. It renders on the next request; there is nothing to rebuild.
No Caused by block on any heading.The API answered none: no captured session window overlapped the commit blame walked to.Check that sessions are being captured, then POST /api/causal-link/correlate to backfill the last 30 days.
Every block reads Possibly caused by.The weak band: several candidate sessions matched, or the blame walk crossed an unresolved squash or rebase, or the file was renamed inside the window.Nothing to fix on this tab. Weak is recorded and shown, and never counts toward attribution.
A recurring class groups entries that have nothing to do with each other.Neither entry carries a Prevention rule paragraph, so both were fingerprinted by their titles.Add a Prevention rule paragraph to each entry. The fingerprint is recomputed on the next read.
The Brain reflection tab reads No proposals yet.No ANTHROPIC_API_KEY on this machine, or the 02:00 pass has not run for this repository.Add the key in Settings, then press Reflect now rather than waiting for the night.
A promoted lesson is not in CLAUDE.md.It is working as written: promoted lessons land inactive, and the managed block renders active lessons only.Refine it on the Lessons tab and activate it. The block is capped at 12 sections and a 1500-byte budget, so a low-ranked lesson can still be left out.
The hosted page says No snapshot for this file yet.The Brain snapshot switch is off, the device is not bound, or no snapshot has been published since it was turned on.Turn the switch on in Settings and wait for the next hourly cycle.
Disable
Any of the four levers above, independently. Turning the Brain snapshot switch off stops the next publish. It does not withdraw the snapshot already in the store.
Roll back
Not provided as a product action. errors.md is a tracked markdown file, so an entry you regret is reverted in git like any other line. An accepted proposal leaves its id in proposed/accepted/errors-ids.json, so re-accepting the same body is recorded as already accepted rather than appended twice.
Revoke access
Hosted reads follow team membership and the server-resolved per-repo scope, so removing a member or narrowing their repository scope removes their access. Unbinding the device cascades the snapshot rows away, and deleting the team does the same.
Delete
Not provided. No route deletes an entry from .claude/brain/errors.md, and no user-facing control deletes an already-published snapshot of it. Publishing a newer version replaces the older versions for that device and repository. The proposal pruner only reports what could be pruned; it removes nothing.

Maintenance evidence

Feature id
errors (spine leaf errors)
Owner
The brain knowledge loop (the 02:00 dream pass and the proposal inbox) and Accountability Loop A1 and A2 (the caused-by trail and Save as lesson). Guide: LDG-0717.
Supported product version
RepoOps v0.3.1
Last verified
2026-09-15, read against origin/main at 52366bb6d; labels read from the served tab source. The Errors tab has no public/*.html, so its labels were read from lib/md-renderer.mjs (the page shell and the caused-by script) and lib/zero-states.mjs (the empty state); the proposal controls from public/brain-reflection.html and the publish switch from public/settings.html. The counts (338 headings, 117 of them carrying a Prevention rule paragraph, 710,607 bytes) were counted in this repository's own .claude/brain/errors.md on that date.
Example fixtures
lib/brain-metrics.test.mjs (34 cases over the parser, the weekly counts, the trend and the recurring classes), lib/defect-promotion.test.mjs (14 cases over the surface scan, the band filter, the cap and the inactive placeholder), lib/causal-link.test.mjs, lib/brain-acceptor.test.mjs, lib/routes/brain-proposals.test.mjs and lib/brain-pulse-streamer.test.mjs.
Source references
lib/canonical-tabs.mjs, lib/routes/mirror-files.mjs, lib/md-renderer.mjs, lib/zero-states.mjs, lib/causal-link.mjs, lib/brain-metrics.mjs, lib/today.mjs, lib/session-briefing.mjs, lib/brain-cron.mjs, lib/defect-promotion.mjs, lib/brain-acceptor.mjs, lib/brain-drain-policy.mjs, lib/agent-md-blocks.mjs, lib/brain-pulse-streamer.mjs, lib/brain-publisher.mjs, public/brain-reflection.html, public/settings.html
Documentation review
Independent review requested on the slice pull request; not yet recorded.
Video review
Narrated story rendered and published 2026-09-26 (render 9ae7137055d9, LDG-1012) with the breadcrumb Memory, checked against main at b0bb02812. Six frames, the captions and the transcript were reviewed by the authoring agent, not an independent reviewer; the audio was not listened to by a person. Narration is the provisional Windows voice until LDG-0721.

Last updated