# The feedback loop

# The feedback loop

inline gets quieter and sharper the more your team uses it. It watches how you respond to its findings — resolve a thread, react with a 👎, change the flagged code, or merge without touching it — and turns those signals into outcomes, an acceptance rate, and proposed suppression rules. Reading these signals is deterministic and free: no model runs to read reactions.

## The signals

Three signals, all read straight from GitHub:

- **Thread state** — was the review conversation resolved or left open?
- **Reactions** — 👍 / ❤️ / 🎉 on a finding's comment count as up; 👎 / 😕 count as down. Bot reactions are ignored.
- **Code change** — did a later push touch the exact lines the finding flagged?

## Live, during the PR

On each incremental review, prior open findings whose lines the new push touched are marked **addressed** — they stop counting against the [merge gate](./merge-gate.html), because changing the code is evidence the point landed. If a later review re-confirms the same issue, it's reopened.

## On PR close: the harvest

When a PR closes, inline runs a feedback pass. It syncs thread resolutions, computes one diff per distinct reviewed commit, and resolves each finding to a single outcome:

| Outcome | Condition |
| --- | --- |
| Rejected | 👎 present and ≥ the 👍 count. |
| Fixed | The flagged code changed — the fix is the proof. |
| Accepted | 👍 present, no code change. |
| Dismissed | Thread resolved, no code change. |
| Ignored | PR merged, finding untouched and unresolved. |
| None | Closed unmerged, no signals. |

Line matching uses a small fuzz against the base-side line map; file-level findings match on any change to their file. These outcomes power the acceptance-rate metric on the dashboard.

## Dismissal patterns → proposed learnings

The loop's most useful output: when the **same finding pattern is dismissed or rejected across at least 3 distinct PRs within 90 days**, inline drafts a suppression rule.

- Findings are grouped by category and a normalized title — the same normalization the [dedup fingerprint](./review-noise.html#dedup-fingerprints) uses, so a proposed rule covers exactly the findings that share an identity.
- A single cheap model call drafts the rule, stored as a **proposed, inactive** [learning](./learnings.html) with the evidence attached.
- One proposal per pattern, ever.

Crucially, **inline never silences a class of finding on its own.** A proposed learning sits inactive until an admin approves it in the portal (which activates it) or deletes it. inline surfaces the pattern; a human decides.

> This is the whole philosophy in one mechanism: the agent notices what you keep rejecting and offers to stop — but you stay in control of what it stops saying.

## Tuning

The thresholds (3 distinct dismissals, a 90-day window) are built in. What you control is what happens next: review proposed learnings under **Learnings** in the portal and approve the ones that match your team's taste.
