Once a report clears the noise filter, dedupe asks the next cheap question: have we seen this already. Each surviving report is compared against the corpus of what is already tracked, the other local tickets both open and closed, plus GitHub issues when a token is configured and a checked-in fixture when it is not, so the out-of-box demo still exercises the check. A reworded restatement of a bug that was fixed last week is caught here and linked to its original rather than diagnosed again from scratch.

Dedupe builds the memory. It assembles the corpus of what is already tracked and hands it to the gate, where a reworded old bug is matched and linked instead of diagnosed again.

This is the loop checking its own memory before it spends effort. The expensive step in triagepilot is the model call, and there is no point diagnosing a defect the system has already reasoned about. Dedupe is the second free screen, so by the time a report reaches the model it is both plausible and new.

Matching a duplicate is a terminal outcome for that report: it is linked to what it duplicates and closed, not passed on. The check does not decide what the underlying bug is; it decides only that this particular telling of it is not fresh.