Skip to content

plugin_token_savings: RTK operation rates are vendor claims that a paired A/B contradicts #2

Description

@javimosch

Summary

scripts/plugin_token_savings.py measures token volumes rigorously (real o200k_base
via tiktoken, deduplicated by call id — no complaints there). It then multiplies those
volumes by vendor-published compression rates to produce the operation_rate_scenario
savings that appear in assets/plugin-token-savings/report.md and summary.json.

For RTK specifically, there is now a controlled measurement that contradicts those rates,
and it points the other way.

Where

# scripts/plugin_token_savings.py
RTK_OPERATION_RATES = {
    "ls_tree": 0.80, "read": 0.70, "grep": 0.80, "git_status": 0.80,
    "git_diff": 0.75, "git_log": 0.80,  "git_write": 0.92,
    "cargo_npm_test": 0.90, "ruff_check": 0.80, "pytest": 0.90,
    "go_test": 0.90, "docker_ps": 0.80,
}

These track RTK's advertised "60–90% less token consumption". Applied to measured eligible
output they yield the published ~78.74% compression and 1,148,746 tokens / $5.74 of
scenario savings.

The contradicting evidence

JetBrains ran a paired A/B on rtk under Claude Code (writeup):

harness Harbor 0.18 sandboxes, paired A/B, agent pinned identically in both arms
benchmark SkillsBench, 86 tasks, auto-graded
model claude-sonnet-5, low and high reasoning effort
volume 425 billed trials
analysis Wilcoxon signed-rank on paired per-task deltas, pre-registered endpoints

Result: low effort +7.6 % more expensive (p=0.004); high effort +0.1 % (p=0.99).
Meanwhile rtk's own rtk gain reported "96.2 million tokens saved — 99.8 % of everything
it touched"
on the same run where the bill went up.

So the realized effect is zero-to-negative, while the scenario in this repo is a positive
1.15M tokens. That is a sign disagreement, not a magnitude quibble.

Why the rates don't transfer (the useful part)

Two independent gaps, both mechanical rather than statistical:

  1. Coverage. JetBrains found the hook "only ever sees about a fifth of the tool output",
    and that Claude Code already truncates pathological outputs before compression could
    help. count_rtk_payloads counts full observed stdout/stderr as eligible, so the base
    the rates multiply is roughly 5× the payload the plugin would actually touch.
  2. Boundary ≠ session. A per-operation compression ratio is measured at the tool
    boundary. Billing is a function of the context re-sent every turn; a smaller tool
    result still enters a growing transcript, and any detail lost can cost extra turns.
    Compressing an observation by 80 % does not remove 80 % of what you pay for.

Gap 1 alone is ~5×. Gap 2 is what turns a remainder into a wash.

Suggestion

The measured half of this analysis is good and worth keeping. It's the multiplication I'd
change. Options, roughly in order of how much I'd trust the outcome:

  1. Drop operation_rate_scenario for RTK and publish only the observed eligible volume
    ("this much output passed through commands rtk would touch"). That statement survives
    contact with the A/B.
  2. Keep it, adjacent to the contradicting measurement, in report.md and in
    summary.json as a field — not only in prose. A reader consuming the JSON currently
    gets estimated_saved_tokens with no machine-readable signal that a controlled
    experiment disagrees.
  3. Re-key the constants on provenance: {rate, source, kind: "vendor_claim" | "measured_ab", n, p}. Then a vendor claim can never be silently rendered the same way
    as a measured effect, for rtk or the next plugin.

I'm happy to open a PR for whichever you prefer — (3) is the one that keeps paying off.

Acknowledgement

The report does say these are "not causal measurements" and don't establish transferability.
That caveat is real and I don't want to imply it's missing. My concern is narrower: the
caveat is prose, the number is structured data, and the number is the thing that gets
indexed, charted, and cited.

Disclosure

I maintain token-optimizer-cli, which
Yu contacted us about — so I have an interest here and you should weigh this accordingly.
For what it's worth I applied the same standard to my own tool first: it estimated tokens
as chars/4, which I measured undercounting real o200k_base by 18.6 % and non-uniformly,
so I replaced it with exact BPE and it now publishes no "tokens saved" figure at all,
because it's a static analyzer that never sits in the agent's I/O path and therefore has no
honest way to claim one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions