Entry 05Developer tooling · Go2026

A guard that went stale in the session that wrote it

RunEcho watches what a coding agent is about to change and objects before the change lands. The most useful thing it produced was evidence against one of its own designs.

false positives removed91%
guard overhead0.36 ms
was9.5 ms
languages parsed5

The contract that expired before the day did

An edit-scope contract declares what a piece of work is allowed to touch, so a guard can object when an agent wanders outside it. The obvious next step was to bind a contract automatically when a session starts. Dogfooding the guard on the day it merged killed that idea: the contract describing the work went stale within the same session, at the moment the work it described was merged.

A session routinely spans several unrelated pieces of work. A contract belongs to a task, not to a session, and between tasks the correct state is no active contract at all — the free, silent, abstaining default. Automatic session binding would have produced a guard that was confidently wrong most of the time, which is worse than no guard.

Choosing a parser by what a shortcut would get wrong

Each language gets a parser engine chosen on one question: are there constructs a cheap length-preserving masker cannot disambiguate without actually parsing? If yes, it earns a real grammar. If no, a grammar is overkill.

LanguageEngineWhy
Rusttree-sitter grammarlifetimes vs char literals; nested block comments
Shellregex + maskerquoting and heredocs resolve in one stateful pass

The asymmetry is what makes ambiguity the right test. A masker that guesses wrong fails silently and loses every symbol after the mistake — indistinguishable from a file with no symbols in it, which is the worst possible failure for a guard. In Rust, 'a is a lifetime in one line and a character literal in the next, and nothing short of parsing tells them apart.

Visibility follows the same principle rather than a house convention. Go extracts only exported names, because an unexported Go name cannot be referenced from outside its package. Rust extracts everything, because a same-crate reference to a private function is completely ordinary — filtering it out would produce false negatives on the common case.

Guards have to be cheap or they get turned off

Duplicate-symbol warningsBuild-constraint pairs — the same function defined once per platform — produced 91% false positives. Suppressing only when both files are constrained removed all of them, without a toolchain shell-out. A constrained-versus-unconstrained pair still asks.
Store accessChecking the contract meant opening the store a second time, measured at +9.5 ms per edit. Sharing the handle with the symbol lookup already running brought it to +0.36 ms.
Threat modelLocal execution behind a firewall, so no web attack surface — but the binaries are distributed publicly, which puts the release pipeline in scope even though authentication and rate limiting are not.
Developer ToolingGo Tree-sitterAgent Safety

Questions about the approach? Email is best — [email protected] · Back to portfolio