Three hotfix tags went out on one day. On that same day we rewrote the global rules for rtk, the output compressor we put in front of shell commands to save tokens, because its git log filter had misled release verification.

The filter that looked free

rtk sits between the agent and the shell and shrinks command output before the model reads it. For git log the rewrite was simple. It dropped merge commits, since they are noise in most histories, and kept the one-line subjects. On a repo where every ticket lands as a feature commit, the output got much shorter and we saw no downside.

Where it broke

Our release lane is gitflow. Hotfixes are cut from master, and the runbook computes the next hotfix version from two sources at once. One is the merge trail on the branch. The other is git ls-remote --tags origin. It takes the higher of the two and never trusts a single source. That rule exists because a single-source grep once tagged the same version twice.

The merge trail is merge commits. Once the filter stripped them, the log no longer answered the question the verification step was asking: is the hotfix merge the tip of the branch, and is the tag the agent expects the one that exists? What came back was a clean list of feature commits. The fix commit we were looking for was in it, so the check passed. Nothing in the output said that the merge above it, the one that makes it live, was missing or was somewhere other than where we assumed.

This happened twice. Both times we read the compressed log, saw the commit we expected, and treated the release as verified. Both times the raw history had to be re-read to find what the filtered version had hidden.

The fix that rebuilt the hole

Our first repair made things worse. We decided the filter was too blunt and narrowed it. We kept merge commits only when the subject matched a ticket id pattern, on the theory that the merges that mattered were the ones named after tickets.

That is a heuristic stacked on a heuristic. The merge that matters for release verification is the one whose subject is Merge branch 'master' into ... or a tag merge, and those match no ticket pattern. We had rebuilt the same hole with a more elaborate rule. It cost a second false pass, and the second one was the more expensive because we now trusted the filter more, having tuned it.

Any transformation between the repo and the reader has a rule for what counts as noise, and the reader can no longer see what the rule removed. For a status log that is fine. For a check that feeds a go/no-go decision, the removed part is the evidence.

Raw for decisions, compressed for skimming

The rewritten global rules for rtk are short:

  • Compression is allowed for output that a human or agent skims. That covers build logs, test output and directory listings.
  • Compression is banned for any command whose output feeds a release or merge decision. That covers git log and git tag used for version math, git ls-remote, git status before a push, and branch-tip checks.
  • Those commands run raw, every time, even when the output is long. The token cost is the price of the check.

Release verification also reads the tip directly instead of inferring it from a log. The check is git rev-parse origin/master compared against the tag’s commit, plus the higher-of-both version rule the runbook already had. A one-line answer to a precise question is small enough that nothing needs compressing.

What it cost

The tokens saved on those calls were a few hundred a day. The false passes cost two re-verifications and a day of not trusting our own release log. So before a command goes behind a filter, ask what the reader does with the result. If the answer is “decides whether to ship”, leave that command out and run it raw.