Sentry Loop
Window: $ARGUMENTS (default: 7d)
Triage-then-investigate over the error tracker. The output is knowledge, not
fixes: every issue in the window ends the run classified, the few that matter
end it root-caused, and the findings live in the work tracker - separably from
human-authored work items.
Configuration
Read the current repo's AGENTS.md before filing anything:
- Tracker + label: the
Work-item tracking section names the tracker and
the label/team that marks loop-generated issues (default label:
sentry-loop). Create the label on first use if it doesn't exist.
- Sentry access: use the Sentry MCP (
find_organizations once, then
search_issues / search_events / get_sentry_resource). If the repo has
a docs/mcp-sentry.md, follow it.
No tracker configured → produce the report locally under ./tmp/ and stop
before the filing stage.
Stage 1 - Sweep
- Establish the window:
$ARGUMENTS if given, else 7d. Then find the
standing loop-report issue (search by the loop label); if its latest run
comment is newer than the window start, narrow the window to "since last
run" and note that in this run's comment.
- Pull the volume shape:
search_events grouped by project
(count(), count_unique(issue)) for the window.
- Pull the issue list:
search_issues per project, sorted by new, for the
window - capture id, title, culprit, first/last seen, event count, user
count, status.
Stage 2 - Classify
Tag every issue with one value per axis. This table IS the deliverable for
most issues - classification is cheap, so nothing is skipped.
- Age:
new (first seen in window) / recurring / regressed
(previously resolved, seen again).
- Impact:
user-impacting (users > 0) / zero-user.
- Nature:
real (a defect in our code) / env-noise (dev/staging
pollution, infra flakes, third-party outages) / external (browser
extensions, network, user-device).
- Cluster: issues sharing one probable root cause (same command, culprit,
error string, or release boundary) get one cluster id - a burst of distinct
Sentry issues is often one incident. Check event
extra data
(get_sentry_resource) when titles are generic; the real error string
usually lives there.
Stage 3 - Investigate (only what earns it)
Deep-dive a cluster only if it is new AND (user-impacting OR clearly a
defect). Everything else stays at classification depth.
Per cluster, hypothesis-first:
- Read the fullest event (
get_sentry_resource): stack, tags (release!),
and extra data.
- Form 2–3 ranked hypotheses before reading code.
- Trace the stack into the codebase; check
git log / git log -S around
the release tag and first-seen date - most new issues correlate with a
recent change.
- Conclude with: root cause, confidence, file:line references, introducing
change if found, affected users/orgs, and what a fix needs (not the fix).
Independent clusters may be investigated in parallel - dispatch one
investigator sub-agent per cluster (the Codex investigator role via the
codex skill, or an equivalent read-only agent), each fed the cluster's Sentry
ids and the classification context; the orchestrator keeps the table and
merges reports.
Stage 4 - File
All loop-generated tracker items carry the loop label. Before creating
anything, search the tracker for open loop-labeled issues covering the same
fix or the same recurring noise - update those instead of duplicating.
The unit of filing is one PR, not one incident. Every issue the loop
creates must be closable by a single PR; its title is the change, imperative
("Guard team deletion when a phone number is assigned"), not the symptom.
One issue per fix. If a root cause needs two changes (a revert now and
a redo later; a backend guard and a separate UI affordance), that is two
issues, cross-linked, each independently shippable. Never start the fix.
The body is the investigation, not just its verdict. A reader must be
able to follow the journey from Sentry to conclusion without re-deriving
it. Required sections, in order:
- Sentry evidence - what the event(s) actually showed: error string,
extra data, decisive tags (release, counts, first/last seen, users),
linked issue(s).
- Hypotheses - the ranked candidates formed before reading code.
- Trace - the path walked (file:line) and what confirmed the winner;
the introducing change if found.
- Ruled out - each discarded hypothesis with the evidence that killed
it. An issue with nothing ruled out is a smell (Stage 3 wasn't
hypothesis-first).
- Root cause + confidence - one sentence, and why that confidence.
- Fix shape - acceptance criteria and the suggested entry point
(
/create-brief <id> or straight /do for trivial ones).
Hygiene findings follow the same rule - each fixable noise source
(a dev cron writing to prod Sentry, a dead task type still queued) is its
own small PR-sized issue. Noise that isn't ours to fix (third-party,
browser extensions) does NOT become an issue; it's recorded in the run
report and ignored in Sentry with a reason.
One standing loop-report issue (create on first run, then reuse): each
run appends a comment with the window, volume shape, the full
classification table, links to the issues filed above, and what was left
un-investigated and why. The latest comment is the next run's "since"
marker. Runs never create per-run report issues - the tracker holds work,
not logs.
Stage 5 - Annotate Sentry
Make the triage stick in Sentry so next run's sweep is smaller:
- Root-caused and a fix is already deployed →
resolved with a reason
comment linking the fix and tracker issue.
- Root-caused but not fixed → leave unresolved; comment the root cause
and tracker issue link.
env-noise / external → ignored (untilEscalating) with a reason
comment.
Never resolve an issue whose fix has not shipped - it will re-alert as a
regression and poison the age axis.
Boundaries
- Report-only: no code changes, no fixes, no config edits. Fixes go through
/create-brief → /do.
- Don't investigate recurring known issues past confirming their tracker item
still reflects reality.
- If the window's volume is an order of magnitude above the norm, stop
classifying individual issues, say so, and triage the spike itself first.
1---2name: sentry-loop3description: On-demand Sentry triage loop - sweep every project's errors over a time window, classify each issue (new / recurring / regressed, user-impacting / zero-user, real / noise), root-cause only the clusters that matter, file findings into the work tracker under the loop's label, and annotate Sentry so the state sticks. Use when the user asks to run the sentry loop, triage Sentry, "what's new in Sentry", or wants a period's errors root-caused. Report-only - fixes go through /create-brief then /do.4---56# Sentry Loop78## Window: $ARGUMENTS (default: 7d)910Triage-then-investigate over the error tracker. The output is knowledge, not11fixes: every issue in the window ends the run classified, the few that matter12end it root-caused, and the findings live in the work tracker - separably from13human-authored work items.1415## Configuration1617Read the current repo's `AGENTS.md` before filing anything:1819- **Tracker + label**: the `Work-item tracking` section names the tracker and20 the label/team that marks loop-generated issues (default label:21 `sentry-loop`). Create the label on first use if it doesn't exist.22- **Sentry access**: use the Sentry MCP (`find_organizations` once, then23 `search_issues` / `search_events` / `get_sentry_resource`). If the repo has24 a `docs/mcp-sentry.md`, follow it.2526No tracker configured → produce the report locally under `./tmp/` and stop27before the filing stage.2829## Stage 1 - Sweep30311. Establish the window: `$ARGUMENTS` if given, else 7d. Then find the32 standing loop-report issue (search by the loop label); if its latest run33 comment is newer than the window start, narrow the window to "since last34 run" and note that in this run's comment.352. Pull the volume shape: `search_events` grouped by project36 (`count()`, `count_unique(issue)`) for the window.373. Pull the issue list: `search_issues` per project, sorted by `new`, for the38 window - capture id, title, culprit, first/last seen, event count, user39 count, status.4041## Stage 2 - Classify4243Tag every issue with one value per axis. This table IS the deliverable for44most issues - classification is cheap, so nothing is skipped.4546- **Age**: `new` (first seen in window) / `recurring` / `regressed`47 (previously resolved, seen again).48- **Impact**: `user-impacting` (users > 0) / `zero-user`.49- **Nature**: `real` (a defect in our code) / `env-noise` (dev/staging50 pollution, infra flakes, third-party outages) / `external` (browser51 extensions, network, user-device).52- **Cluster**: issues sharing one probable root cause (same command, culprit,53 error string, or release boundary) get one cluster id - a burst of distinct54 Sentry issues is often one incident. Check event `extra` data55 (`get_sentry_resource`) when titles are generic; the real error string56 usually lives there.5758## Stage 3 - Investigate (only what earns it)5960Deep-dive a cluster only if it is **new AND (user-impacting OR clearly a61defect)**. Everything else stays at classification depth.6263Per cluster, hypothesis-first:64651. Read the fullest event (`get_sentry_resource`): stack, tags (release!),66 and `extra` data.672. Form 2–3 ranked hypotheses before reading code.683. Trace the stack into the codebase; check `git log` / `git log -S` around69 the release tag and first-seen date - most new issues correlate with a70 recent change.714. Conclude with: root cause, confidence, file:line references, introducing72 change if found, affected users/orgs, and what a fix needs (not the fix).7374Independent clusters may be investigated in parallel - dispatch one75investigator sub-agent per cluster (the Codex `investigator` role via the76codex skill, or an equivalent read-only agent), each fed the cluster's Sentry77ids and the classification context; the orchestrator keeps the table and78merges reports.7980## Stage 4 - File8182All loop-generated tracker items carry the loop label. Before creating83anything, search the tracker for open loop-labeled issues covering the same84fix or the same recurring noise - update those instead of duplicating.8586**The unit of filing is one PR, not one incident.** Every issue the loop87creates must be closable by a single PR; its title is the change, imperative88("Guard team deletion when a phone number is assigned"), not the symptom.89901. **One issue per fix.** If a root cause needs two changes (a revert now and91 a redo later; a backend guard and a separate UI affordance), that is two92 issues, cross-linked, each independently shippable. Never start the fix.9394 **The body is the investigation, not just its verdict.** A reader must be95 able to follow the journey from Sentry to conclusion without re-deriving96 it. Required sections, in order:97 - **Sentry evidence** - what the event(s) actually showed: error string,98 `extra` data, decisive tags (release, counts, first/last seen, users),99 linked issue(s).100 - **Hypotheses** - the ranked candidates formed before reading code.101 - **Trace** - the path walked (file:line) and what confirmed the winner;102 the introducing change if found.103 - **Ruled out** - each discarded hypothesis with the evidence that killed104 it. An issue with nothing ruled out is a smell (Stage 3 wasn't105 hypothesis-first).106 - **Root cause + confidence** - one sentence, and why that confidence.107 - **Fix shape** - acceptance criteria and the suggested entry point108 (`/create-brief <id>` or straight `/do` for trivial ones).1092. **Hygiene findings follow the same rule** - each fixable noise source110 (a dev cron writing to prod Sentry, a dead task type still queued) is its111 own small PR-sized issue. Noise that isn't ours to fix (third-party,112 browser extensions) does NOT become an issue; it's recorded in the run113 report and ignored in Sentry with a reason.1143. **One standing loop-report issue** (create on first run, then reuse): each115 run appends a comment with the window, volume shape, the full116 classification table, links to the issues filed above, and what was left117 un-investigated and why. The latest comment is the next run's "since"118 marker. Runs never create per-run report issues - the tracker holds work,119 not logs.120121## Stage 5 - Annotate Sentry122123Make the triage stick in Sentry so next run's sweep is smaller:124125- Root-caused and a fix is **already deployed** → `resolved` with a reason126 comment linking the fix and tracker issue.127- Root-caused but **not fixed** → leave unresolved; comment the root cause128 and tracker issue link.129- `env-noise` / `external` → `ignored` (untilEscalating) with a reason130 comment.131132Never resolve an issue whose fix has not shipped - it will re-alert as a133regression and poison the age axis.134135## Boundaries136137- Report-only: no code changes, no fixes, no config edits. Fixes go through138 `/create-brief` → `/do`.139- Don't investigate recurring known issues past confirming their tracker item140 still reflects reality.141- If the window's volume is an order of magnitude above the norm, stop142 classifying individual issues, say so, and triage the spike itself first.