Context
AgentWorkforce/burn#224 (merged) lands a vendor-neutral tool-call-pattern detector in burn hotspots. Burn surfaces five categories of vanilla call patterns with consolidatable overhead, but it deliberately does not name a specific replacement tool — that mapping belongs here.
This issue covers building the wash-side consumer that closes the loop: take burn's findings, map each category to the matching relaywash__* tool, and produce an "install relaywash to save N tokens" advisory the way the original burn PR did before we split it.
Status of upstream prerequisites (all landed)
- ✅ burn#218 —
@relayburn/sdk programmatic surface published
- ✅ burn#219 —
_meta.replaces / _meta.collapsedCalls annotations recognized on ingest
- ✅ burn#224 —
tool-call-pattern detector merged, exposed via hotspots() in the SDK
So this issue is now fully unblocked — no more --json shelling required.
Status on the wash side
src/burn/sdk.js is still a local stub of relayburn/sdk with a header comment claiming it is "blocked on burn#218." That blocker is gone — we should swap the stub for the real @relayburn/sdk npm dep as part of this work (or in a small precursor PR).
scripts/relaywash-savings/run.js (the /relaywash-savings slash command) already calls summary({ session }) from the SDK. That is the post-install ledger report (how much you saved with relaywash already running). This issue is the complementary pre-install advisory (how much you would save if you installed relaywash) — different command, same SDK.
- The relaywash tools (
src/tools/{search,edit,git-state,test-run,gh-pr}.js) already emit _meta.replaces / _meta.collapsedCalls via src/burn/meta.js, so once the advise command re-prices, it can pull tool-specific footprints from those annotations directly.
Burn's output (what we consume)
hotspots({ patterns: ['tool-call-pattern'] }) returns an array of findings, each shaped roughly like:
{
source: 'claude-code' | 'opencode' | 'codex',
sessionId: string,
category:
| 'search-sequence' // Glob → Grep → Read in one turn (≥3 per session)
| 'edit-cluster' // ≥3 edits to same file in 5-turn window
| 'bash-git-state' // git status/diff/log
| 'bash-test-run' // pnpm test, pytest, jest, etc.
| 'bash-gh-pr', // gh pr <verb>, gh api
occurrenceCount: number,
estimatedTokensSaved: number, // burn's conservative per-occurrence estimate
estimatedUsdSaved: number, // priced at session's dominant model rate
sampleTurnIndexes: number[],
evidence: string[],
}
patterns also accepts tool-output-bloat and ghost-surface if we later want to layer recommendations on those.
Mapping table
| Burn category |
relaywash tool |
search-sequence |
relaywash__Search |
edit-cluster |
relaywash__Edit (batched) |
bash-git-state |
relaywash__GitState |
bash-test-run |
relaywash__TestRun |
bash-gh-pr |
relaywash__GhPR |
All five replacement tools exist today under src/tools/.
Proposed shape
A relaywash advise command (likely a new slash command alongside /relaywash-savings) that:
- Imports
hotspots from @relayburn/sdk (replacing the local stub) and calls it with { patterns: ['tool-call-pattern'] }. No more burn hotspots --json shell-out.
- Joins each finding to its
relaywash__* mapping.
- Re-prices the savings using the relaywash tool's actual per-call token footprint instead of burn's conservative flat rates. The
_meta.replaces / _meta.collapsedCalls annotations the tools already emit are the source of truth here (now that burn#219 is in).
- Emits a per-session "you'd save $N by installing/enabling these tools" report. Markdown PR-comment /
CLAUDE.md snippet output mode would let CI surface it on PRs the way burn-compare already does.
Why split it this way
Burn's value prop is observability — it should report the pattern and the overhead estimate without picking a vendor. wash's value prop is the consolidated tools — it owns the recommendation layer and the marketing copy ("install relaywash to save $X"). This keeps burn vendor-neutral and lets multiple consolidation libraries layer on top of the same burn signal.
Acceptance
Context
AgentWorkforce/burn#224(merged) lands a vendor-neutraltool-call-patterndetector inburn hotspots. Burn surfaces five categories of vanilla call patterns with consolidatable overhead, but it deliberately does not name a specific replacement tool — that mapping belongs here.This issue covers building the wash-side consumer that closes the loop: take burn's findings, map each category to the matching
relaywash__*tool, and produce an "install relaywash to save N tokens" advisory the way the original burn PR did before we split it.Status of upstream prerequisites (all landed)
@relayburn/sdkprogrammatic surface published_meta.replaces/_meta.collapsedCallsannotations recognized on ingesttool-call-patterndetector merged, exposed viahotspots()in the SDKSo this issue is now fully unblocked — no more
--jsonshelling required.Status on the wash side
src/burn/sdk.jsis still a local stub ofrelayburn/sdkwith a header comment claiming it is "blocked on burn#218." That blocker is gone — we should swap the stub for the real@relayburn/sdknpm dep as part of this work (or in a small precursor PR).scripts/relaywash-savings/run.js(the/relaywash-savingsslash command) already callssummary({ session })from the SDK. That is the post-install ledger report (how much you saved with relaywash already running). This issue is the complementary pre-install advisory (how much you would save if you installed relaywash) — different command, same SDK.src/tools/{search,edit,git-state,test-run,gh-pr}.js) already emit_meta.replaces/_meta.collapsedCallsviasrc/burn/meta.js, so once the advise command re-prices, it can pull tool-specific footprints from those annotations directly.Burn's output (what we consume)
hotspots({ patterns: ['tool-call-pattern'] })returns an array of findings, each shaped roughly like:patternsalso acceptstool-output-bloatandghost-surfaceif we later want to layer recommendations on those.Mapping table
search-sequencerelaywash__Searchedit-clusterrelaywash__Edit(batched)bash-git-staterelaywash__GitStatebash-test-runrelaywash__TestRunbash-gh-prrelaywash__GhPRAll five replacement tools exist today under
src/tools/.Proposed shape
A
relaywash advisecommand (likely a new slash command alongside/relaywash-savings) that:hotspotsfrom@relayburn/sdk(replacing the local stub) and calls it with{ patterns: ['tool-call-pattern'] }. No moreburn hotspots --jsonshell-out.relaywash__*mapping._meta.replaces/_meta.collapsedCallsannotations the tools already emit are the source of truth here (now that burn#219 is in).CLAUDE.mdsnippet output mode would let CI surface it on PRs the wayburn-comparealready does.Why split it this way
Burn's value prop is observability — it should report the pattern and the overhead estimate without picking a vendor. wash's value prop is the consolidated tools — it owns the recommendation layer and the marketing copy ("install relaywash to save $X"). This keeps burn vendor-neutral and lets multiple consolidation libraries layer on top of the same burn signal.
Acceptance
src/burn/sdk.jsstub replaced with a real@relayburn/sdkdependency (or the stub explicitly kept as a tested-fallback with a clear reason).hotspots({ patterns: ['tool-call-pattern'] })output and emits per-session recommendations._meta.replaces/_meta.collapsedCalls, not burn's flat estimates.fixtures/corpus/setup used byburn-compareis a good starting point).