The bug
Sentry shows: "Hydration failed because the initial UI
does not match what was rendered on the server", frequency
~30 events/hour, mostly on the
/dashboard/manager/[districtId] route. You have no
idea where to start. The agent has even less.
Step 1 — context_packet with the error verbatim
{
"tool": "context_packet",
"args": {
"request": "Hydration failed on /dashboard/manager/[districtId]",
"includeInstructions": true,
"includeRisks": true,
"includeLiveHints": true,
"freshnessPolicy": "prefer_fresh",
"budgetTokens": 4000
}
} The packet returns:
- primaryContext: the layout file
app/dashboard/manager/[districtId]/layout.tsx, the loading state, and the data fetcher. - activeFindings: a Reef finding from a
prior session — "client-only date formatting in
DistrictHeaderuses Date.now() inline". - risks: "this layout reads from
manager_district; RLS-sensitive." - recommendedHarnessPattern: "read primary
→ call
file_findingson layout.tsx → check freshness."
The activeFindings line is gold — someone already looked at this file and noted a likely client/server mismatch culprit. Skip ahead to verifying it instead of re-deriving from scratch.
Step 2 — verify the finding is current
The Reef finding might be from three weeks ago and already fixed. Check:
{
"tool": "evidence_confidence",
"args": {
"subjectKind": "finding",
"subjectId": "<finding id from step 1>"
}
} Returns a freshness label. If it's contradicted,
the file changed and the finding may be obsolete — re-run
lint_files on the layout. If it's
fresh_indexed, the suspicion is still valid.
Step 3 — trace_error if you need broader context
If context_packet didn't surface the right file:
{
"tool": "trace_error",
"args": {
"term": "Hydration failed",
"limit": 30
}
} Returns throw sites, catch handlers, and PL/pgSQL bodies that match. For a runtime error this usually surfaces the React/Next boundary that's emitting it (and any custom error handlers in your app).
Step 4 — live_text_search after edits
You make a fix in DistrictHeader — wrap the
time-sensitive render in a useEffect so it only
runs on the client. Now you want to confirm there are no other
instances of the same pattern. Indexed
cross_search would be stale (you just edited).
Use live_text_search:
{
"tool": "live_text_search",
"args": {
"query": "new Date(",
"pathGlob": "app/**/*.tsx",
"fixedStrings": true,
"maxMatches": 100
}
} Now you have a fresh ground-truth list of every
new Date( in your app components. Audit them, fix
any other inline-date-during-render cases.
Step 5 — record the finding (optional)
If you discovered a real pattern, record it via
finding_ack — but only if the finding is reviewed
and intentional. Don't ack noise.
Why this is faster than grep loops
The agent went from "vague bug report" to "fix shipped" in roughly 5 tool calls and ~2,000 tokens of context. The vanilla path would have looked like 12 grep calls, 6 file reads, 8,000+ tokens, and the agent missing the prior Reef finding entirely.
The Reef finding from a prior session is the key win. Every bug you debug becomes durable knowledge — the next person (or agent) gets a head start.
Tools used in this recipe
context_packet— vague request → ranked context.reef_scout— broader scout packet of facts/findings/rules.reef_inspect— full evidence trail for one file/subject.trace_error— find throw/catch sites for an error term.live_text_search— exact current text on disk.evidence_confidence— freshness label for one piece of evidence.file_findings— durable findings on a file.lint_files— Mako rule-pack diagnostics.