grithdocs

Adaptive reputation

The learned trust table: what it observes, where it is applied, and why it only ever flips a queue to an allow.

Two different things in grith are called reputation, and confusing them is the single most common misreading of how scoring works.

  • The reputation filter is filter 13 in the pipeline. It scores destinations against fixed lists: known-safe -1.0, raw IP +3.0, suspicious TLD +2.0, known-malicious higher, unknown 0.0. It learns nothing. See filter 13.
  • The learned reputation table is this page. It is not a filter, it is not in the pipeline, and grith reputation shows and resets it.

Where it is applied

After the pipeline has finished, in the daemon, and only when the decision is QUEUE.

An ALLOW is never touched. A DENY is never revisited - reputation cannot rescue a denied call, no matter how trusted the shape.

It is all or nothing

This is the part that surprises people. The table does not gently lower a score until a call drifts across the allow line. At the point where it is applied, it either flips the whole decision to allow or it changes nothing at all.

Every one of these must hold for the flip:

ConditionDefault
Observations on the matched keyat least 8
Trust scoreat least 0.92
Raw composite score7.0 or below
Safety ceilingnone triggered

A safety ceiling blocks auto-allow outright, and there are three ways to hit one: any single filter scored 5.0 or more, or secret-scan matched at all, or the call is a write to a sensitive directory. A ceiling ends the question - there is no trust level that overrides it.

On a fresh install the table is empty, nothing clears eight observations, and the whole system behaves exactly as if it were switched off.

terminal
$ grith reputation show
No reputation data. Data is learned from approve/deny decisions during grith exec sessions.

What it learns from

Only human decisions made at a prompt during a grith exec session. The model cannot train it and the supervised tool cannot feed it - the daemon's observe endpoint clamps hostile input, capping weights and key counts so a client cannot self-whitelist its own future spawns.

DecisionWeight
Approve1.0
Approve and save a rule (l)1.5
Deny3.0
Deny and stop the tool5.0
Auto-deny1.0

Denials carry three times the weight of approvals by default. Trust is easy to lose and slow to build, which is the correct asymmetry for a security control.

Approve replay does not feed the table, so hammering the same call cannot launder trust.

The model

One Beta distribution per key, with trust as the ratio of successes to total observations, and an hourly exponential decay of 0.98 - about 61% of a signal remains after a day. Trust that is not renewed fades.

Keys are built at several granularities from the profile, action, process, destination and path class: the exact path, its parent directory, and the process alone. The grandparent level is deliberately missing so trust cannot cross sibling directory boundaries. Paths under sensitive roots - .ssh, .aws, .gnupg, .pki, .config/gh, .kube, .docker, .config/gcloud, .azure - only ever get exact-path entries, so approving one file there never generalises.

The table lives in ~/.config/grith/reputation.toml. The daemon owns it; sessions record observations over IPC; saves merge with what is on disk, so concurrent sessions do not clobber each other.

Profiles seed it

A profile's routine paths, commands and destinations get optimistic priors at session start, so a fresh install is not maximally noisy on day one. Seeding only fills in where no richer entry already exists - it never overwrites something you taught it.

See also

Last updated: 2026-08-24Edit this page on GitHub →