AI security · Trace

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. Now a session with a prompt behind it wrote the line and a person pressed merge. RepoOps rebuilds the missing half of that record, so a finding resolves to the developer, the session, the prompt cycle and what the run cost, with the confidence stated rather than implied.

Runs on your machine · the prompt text stays there · every answer arrives wearing its confidence band

What it does

The parts, and the module behind each one.

Four kinds of signal walk the same chain, and each leg differs exactly where the evidence differs.

A stamp on the commit, from day one

A prepare-commit-msg hook writes a Session-Id trailer onto each commit, and a second trailer carries the agent and human line counts. It goes in at setup, because a trailer that starts appearing in month three cannot attribute month one. If another hook already sits there, the installer refuses rather than overwriting it.

lib/attribution/install-trailer-hook.mjslib/causal/session-trailer.mjs

A security finding, with no clock involved

A secret committed six months ago is detected today, so closeness in time is not evidence here at all. This leg correlates by commit trailer or by blame, with no deploy hop, and it takes the developer from the commit rather than from whoever owns the machine.

lib/causal/security-attribute.mjs

A production error, back through the deploy

The error names a culprit file, the nearest preceding deploy names a commit, the commit names a session, and the prompt cycle that touched that file names the turn. A slow route walks a shorter version of the same road, correlated on three axes with the purely temporal one banded as the weakest.

lib/causal/prod-attribute.mjslib/causal/prod-correlate.mjs

Four bands, and only two of them are proof

Exact means the line sits inside a hunk of a commit carrying a session id and that session is the only candidate. Strong means blame traces the line to a commit whose window overlaps one session that touched the same file. Weak reads as possibly and never counts. None is not written down at all.

lib/causal-link.mjs

The dollars on the same row

The session that wrote the line has a metered cost, so the answer carries it. A model with no price on file reports as unpriced rather than borrowing a similar model's rate, because a wrong number is worse here than a missing one.

lib/security-cost-fusion.mjs

A configuration change that explains a symptom

Four symptoms are watched, cost up, quality down, refusals up and latency up, against five kinds of change that can explain one: a model swapped, a prompt changed, a tool added or removed, a parameter changed. No coincident change is recorded as unexplained rather than pinned on the nearest edit.

lib/model-drift.mjs

Where it lands

What the platform gets, and what you get.

How it helps the platform

Trace is the join that makes the other four acts one product rather than four tools.

  • It turns a detection into a case with an ownerA finding with a developer, a session and a band can be routed, disputed and closed. A finding without one can only be listed. The incident surfaces, the approval queue and the leaderboard all read the same chain.
  • It aims the lesson at the real causeThe guard that blocks a recurrence is written against the thing that actually caused the defect, which is possible because the chain resolved a session and a prompt rather than only a file. A lesson aimed at a filename stops nothing.
  • It is the leg an observability vendor cannot buildWalking an incident back to a prompt needs the coding-agent record and the git history in the same place. A runtime tool holds one and a code host holds the other, which is why this hop is where the local record earns its keep.

How it helps you

You get an answer you can take to a review, including the cases where the honest answer is that nobody knows.

  • A name you can defendThe developer comes from the commit, never from the git identity configured on the machine that ran the scan. When only that identity is available, the answer bands weak and says out loud that it is describing who usually commits on this box.
  • A refusal instead of a plausible guessNo introducing deploy means the chain reads none rather than reaching for a session anyway. A config symptom with no coincident change is recorded as unexplained rather than pinned on the nearest edit.
  • The prompt stays yoursAn incident case keeps the pointer to the prompt cycle, not the prompt text. Moving a transcript to anyone else runs through a per-incident consent record with its own clocks, and no hosted code path can grant that consent to itself.

In practice

Three days this changes.

Each one runs on the modules above. The situation, what RepoOps does with it, and what you are left holding.

  1. 01

    The secret nobody remembers committing

    The situation
    A scan turns up a credential in a config file that has been in the repository for months, and three people have touched the file since.
    What RepoOps does
    The security leg ignores the clock entirely, correlates through the commit trailer or blame, and reports the developer from the commit with a band on the answer.
    What you get
    A rotation conversation with the person who actually introduced it, or an honest weak band that tells you the evidence does not support naming anyone.
  2. 02

    A 3am error in code nobody wrote by hand

    The situation
    Production throws in a file that was generated during an agent session two weeks ago, and the pull request that carried it was reviewed in four minutes.
    What RepoOps does
    The chain runs incident to deploy to commit to session to prompt, and returns the prompt cycle that touched that file along with what the run cost.
    What you get
    You can read the instruction that produced the bug. That is the difference between fixing this error and preventing the next twenty like it.
  3. 03

    The bill went up and nothing obvious changed

    The situation
    Spend on a workflow climbs, quality feels worse, and the only candidate explanations are a model swap and a prompt edit made in the same week.
    What RepoOps does
    Four symptoms are watched against five kinds of configuration change, and the symptom is linked to the change that coincided with it under the same band rules as every other leg.
    What you get
    A named change to roll back, or an explicit unexplained verdict that stops the team blaming the last edit somebody happened to notice.

The limits

What this does not do.

Stated here rather than found out later. The long version, with the module behind each boundary, is on the proof page.

A trailer cannot attribute the past

The hook stamps commits made after it is installed. History written before setup is reachable only through blame, which bands weaker, so the earlier you install it the more of your repository the chain can reach.

Weak is not proof, and the product treats it that way

More than one candidate session, a blame walk that crossed a squash with no recovered trailer, or a rename inside the window all band weak. Weak reads as possibly and is never counted as an attribution.

No attribution rate is claimed anywhere

How much of a repository the chain reaches depends on when the hook went in and how the team commits. Any percentage printed on a marketing page would be a claim about your repository that we are in no position to make.

File-level overlap alone is weak evidence

Matching a prompt cycle to a line through file-level overlap is banded weak on purpose. The strong answers come from the trailer and from a sole-candidate blame match, not from proximity.

Read further

Where this is documented in full.

Find out which prompt wrote the line.

One developer, no account, nothing leaving the machine. Arm a control when you want one.