Record recurring errors on the tracked issue instead of filing again - #11
Merged
Conversation
An error whose root cause already has an issue was filed as a brand new ticket every time it recurred, even when the investigation had correctly identified it as a duplicate and named the issue it belonged to. Nothing in the pipeline could stop it. The investigation returned only is_actionable and is_fixable; the dedup instruction told the agent to set is_fixable=false, which gates the fix stage, while the tracker stage is gated on is_actionable alone. A duplicate of a real, unfixed bug is still actionable, so the ticket was always filed and the "this is already tracked" reasoning survived only as prose in the issue body. Give the investigation somewhere to put that conclusion: is_duplicate and duplicate_of_url, deliberately independent of is_actionable. A duplicate now gets a recurrence note on the existing issue via tracker.comment(), skips the fix stage (the tracked issue owns that fix), and stays quiet on Slack. A duplicate claim with no issue URL is downgraded to a normal filing, since there would be nowhere to record the recurrence. Also: - add comment() to the IssueTracker protocol and both backends; GitHub's attach_pr now routes through it and picks up the --repo flag it was missing. - stop reading notion_page_url/linear_issue_url from the agent's output. Neither was in the documented output contract and both were overwritten by the pipeline. Overwriting linear_issue_url also broke the Slack already-reported check, which compared the just-created URL against earlier runs and so never fired; duplicates are now suppressed directly. - count an issue as created only when the tracker returns a URL.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed?
An error whose root cause is already tracked no longer opens a second ticket. The investigation now returns
is_duplicate+duplicate_of_url, and the pipeline posts a recurrence note on that issue instead of filing a new one — with the fingerprint, occurrence count, Datadog link, RCA doc link, and root cause.Duplicates also skip the fix stage (the tracked issue owns that fix) and stay quiet on Slack.
Why?
A real case: an investigation identified an error as a duplicate of an existing epic, named the tracked issues and the open PR that fixes it, and explicitly recommended not attempting a fix. A brand new ticket was filed anyway.
Nothing in the pipeline could stop it. The investigation returned only
is_actionableandis_fixable. The dedup instruction told the agent to setis_fixable=false— which gates the fix stage — while the tracker stage is gated onis_actionablealone. A duplicate of a real, unfixed bug is still actionable, so the ticket was always filed and the "already tracked" reasoning survived only as prose in the issue body.is_duplicateis therefore deliberately independent ofis_actionable; overloadingis_actionablewould have meant lying about whether the error matters. A duplicate claim with no issue URL is downgraded to a normal filing, since there would be nowhere to record the recurrence.Validation
pytest— 64 passed, including 15 new tests intests/test_duplicates.pycovering the output contract, DB round-trip and migration, recurrence-note content, and pipeline routing (tracked → comment only, untracked → issue only, non-actionable → neither)ruff check .CONTEXT.md,CHANGELOG.md)Risk and operations
investigations(is_duplicate,duplicate_of_url), applied by_migrate()on the next run. Verified against a copy of a live database; pre-existing rows default to0/''.comment()added to theIssueTrackerprotocol and both backends. Any third-party tracker implementation needs it. GitHub'sattach_prnow routes through it and picks up the--repoflag it was previously missing.notion_page_url/linear_issue_urloutput keys are no longer read. Neither was in the documented output contract and both were overwritten by the pipeline. That overwrite also broke the Slack already-reported check — it compared the just-created URL against earlier runs, so it never fired. Duplicates are now suppressed directly instead.