Trace the incident. Understand its origin.
Follow a production issue back through the release, the commit, the developer and the agent session that wrote the line. Every link keeps its source and says how sure it is.
Access is context, not proof of cause. An identity nobody resolved and a transcript nobody shared stay marked as such.
Blame names a commit. It does not name an actor.
When a person wrote every line, the commit was the actor: one author, one intent, one head to ask. It stops being enough when an agent writes most of the lines. The commit still carries a human name, and that name now means the person who accepted the change.
The session that produced the line, the prompt that asked for it, the model that answered and the money that turn spent are all recorded somewhere, and none of them are in the commit. So RepoOps writes the link while the evidence exists, then walks it back on demand.
Eight hops, and the evidence each one leaves.
The first three run while the work happens. The rest run when something goes wrong, over evidence that already exists.
- 01Capture
- 02Stamp
- 03Sign
- 04Sense
- 05Join
- 06Band
- 07Answer
- 08Learn
02 Stamp
A prepare-commit-msg hook writes a Session-Id trailer onto the commit, and a second trailer carries the agent and human line counts. It goes in at setup, because a trailer that starts in month three cannot attribute month one.
lib/attribution/install-trailer-hook.mjs05 Join
Walk it back. Each kind of signal has its own hops, and each hop is evidence rather than a guess: a trailer, a blame walk, a deploy record, a file overlap.
lib/causal/prod-attribute.mjs06 Band
Say how sure the join is, in one vocabulary every leg shares: exact, strong, weak or none. The rules live in the code that assigns them.
lib/causal-link.mjs08 Learn
The lesson, a guard that warns on the recurrence at the merge gate until a person promotes it to block, and a receipt an auditor can check.
lib/causal/prevention-receipt.mjsProduction, performance, security, configuration.
Each leg differs where the evidence differs, and each one says what it will not conclude.
A production error
incident, deploy, commit, session, promptThe error names a file. The nearest deploy before it names a commit, the commit names a session, and the prompt cycle that touched the file names the turn.
RefusesNo deploy that introduced it means the chain reads none. It does not reach for a session anyway.
A slow route
metric, deploy, commitA latency metric is matched to a recent deploy on three axes, strongest first: the commit reference, the tables the slow path touches, then timing alone.
RefusesA match on timing alone never reads as more than weak.
A security finding
finding, commit, developer, promptNo deploy hop and no clock: a secret committed six months ago is found today. The developer comes from the commit, not from whoever owns the machine.
RefusesThe machine's git identity bands weak and names itself as the source.
A configuration change
symptom, config changeFour symptoms (cost up, quality down, refusals up, latency up) and five kinds of change: a model swapped, a prompt changed, a tool added or removed, a parameter changed.
RefusesNo change at the same time is recorded as unexplained, not pinned on the nearest edit.
Four bands, and two of them count.
| Band | When it is assigned | Weight |
|---|---|---|
exact | The defect's file and line sit inside a hunk of a commit that carries a session id, and that session is the only candidate. | Counts as proof |
strong | Blame traces the line to a commit whose window overlaps a session that touched the same file. Sole match, no trailer. | Counts as proof |
weak | More than one session matched, or the blame walk crossed a squash with no trailer, or the file was renamed in the window. | Reads as possibly |
none | No session window overlapped at all. | Not written down |
The same agent, with and without the record.
The accountability benchmark runs one model and harness on the same cases twice, once with RepoOps memory and once without, and reports the paired difference with the unpaired reading printed beside it.
The three published figures, and how to reproduce them
| Figure | Value | What it counts |
|---|---|---|
| Defects attributed | 75% | 9 of 12 seeded defects traced to the session that caused them, at the proof-counting confidence bands. |
| Recurrences prevented | 100% | 12 of 12 known bugs blocked at the pre-merge gate, out of 20 review findings. The label is the benchmark's metric name; on a fixture built so the gate sees every seeded recurrence, it is a property of the fixture, not a rate to expect on a live repo. |
| Measured spend saved | $24.55 | The tracked session cost the blocked recurrences would have re-run: 6 priced, 2 unpriced (no cost signal), across 12 prevention events. Read from the committed results file, never estimated. |
A synthetic, reproducible fixture: 8 sessions, 12 seeded defects, 8 lessons and 20 review findings. The numbers come from running RepoOps's shipped code over that fixture inside a throwaway brain, not from a customer, and none of them is a real-world rate.
Attribution runs lib/causal-correlator.mjs and lib/causal-link.mjs over the fixture sessions and a constructed git blame, and a defect counts when it traces to the seeded session at the exact or strong band. Prevention runs lib/review/prevention-recorder.mjs over the review findings against the promoted lessons. Savings join each prevention event to its lesson's source session and that session's tracked cost (lib/continuity/cost-attribution.mjs); an event with no tracked cost counts as unpriced, never averaged.
$ npm run bench:accountability [bench] RepoOps accountability benchmark (fixture: accountability-v1) [bench] ---------------------------------------------------------- [bench] Attribution accuracy : 9/12 = 75% (bands: exact 3, strong 6, weak 1, none 2) [bench] Recurrence prevented : 12/12 = 100% (of 20 review findings) [bench] Measured $ saved : $24.55 (priced 6, unpriced 2, of 12 prevention events) [bench] ---------------------------------------------------------- [bench] wrote docs/benchmarks/accountability-results.json
Inside the repo, npm run bench:accountability prints that table and writes docs/benchmarks/accountability-results.json, and a parity check in CI holds the figures here to that file. Installed, repoops bench runs the same metrics over your own git history, telemetry and brain, locally and with nothing sent. Every command is listed in the CLI reference.
Start with one question: what happened in this change?
Follow a sample case from the instruction to the verified fix, then install RepoOps and open your own.