What a Third Grammar Validator and a Dormant Feature Taught About Navigating a Build

A companion to Project Navigation & Triangulation, What Four Real Features Taught About Navigating a Build, and What Building a Code-Synthesis Engine Taught About Any Software Project, grounded in Act XIV of the PatLang journey: a PEG grammar validator built deliberately scoped down before being scoped up, a language feature that had sat undesigned for months finally given real semantics, and an honest benchmark regression that turned directly into a measured performance fix within the same session. None of what follows depends on the subject matter being a compiler — the same shape of lesson applies to any project with more than one implementation of the same logic, more than one stakeholder's framing to reconcile, or a performance claim worth actually measuring rather than assuming.

Prove the architecture at the smallest possible scope before investing in full coverage

The grammar validator's first pass covered only what an existing test generator already produced — not the language's full syntax. That narrow scope existed to answer one question cheaply: would one shared grammar file, interpreted identically by two independent engines, actually hold together at all? It did, on the first attempt at each engine, which is what made expanding it to full coverage afterward a controlled, well-understood expansion rather than a second unknown stacked on top of the first. Had the proof-of-concept instead started at full scope, a fundamental architectural problem would have been indistinguishable from a coverage gap — exactly the kind of ambiguity a narrow first pass exists to remove.

The hardest bug in a new subsystem is often completely unrelated to the subsystem's own subject matter

The single hardest bug in building the grammar engine had nothing to do with PEG semantics, ordered choice, or backtracking — it was a pre-existing, orthogonal API confusion (two similarly-shaped but structurally distinct collection types, one accessor silently returning a wrong-but-plausible value instead of erroring on the other). No amount of expertise in the new subsystem's actual domain would have anticipated it; only close, patient isolation testing against a known-working comparison case found it. When a new piece of infrastructure behaves mysteriously, the bug is not obligated to live in the interesting new code — check the boring, load-bearing utility calls first.

A stakeholder's reframing of a question is more valuable than an answer to the question as asked

Offered a choice between two ways to shape a feature's dependency syntax, the answer wasn't a pick — it was a correction of the premise underneath both options ("everything is a function, everything is an object... dependencies only need a way of letting us know if they have been met"). That single reframing collapsed what looked like a real design fork into one uniform mechanism, cheaper and more general than either original option. When a question posed as a choice between A and B gets answered with neither, that's not evasion — it's usually a sign both options were narrower instances of an assumption worth checking directly, and worth treating as a gift, not a non-answer.

A one-line correction can invalidate an entire execution model, not just a detail

A planner's dispatch design implicitly assumed that once a valid plan was found, running it would always succeed. One sentence — "a function dependency might not always result in it being true, the function might fail for some reason" — didn't tweak that assumption, it replaced it: the whole execution loop had to stop-and-report on first failure instead of running unconditionally to completion. The lesson isn't "listen to feedback" in the abstract; it's that a short correction phrased as an aside can be doing structural work far beyond its length, and deserves being traced all the way through a design, not patched at the surface where it was mentioned.

Hitting a real architectural wall doesn't always mean inventing a new primitive

Implementing "call each planned step's registered behaviour" ran straight into a hard constraint: the low-level execution layer could not call back into the higher-level system that would need to invoke it. The instinct is to add a new capability to remove the wall. The alternative that worked instead: generate ordinary, already-supported constructs at the point where source code becomes runnable instructions, and let the existing machinery run them exactly as if a person had hand-written that control flow. Before adding a new primitive to work around an architectural constraint, check whether the same effect is reachable by generating more of what the system already knows how to run — a bigger but purely mechanical change across fewer new concepts is often the safer fix.

A flagged gap closes fast specifically because it was flagged honestly, not buried

A second implementation of the same feature was deliberately left un-updated at the point a first implementation landed, with the gap named explicitly rather than silently left implicit. When the moment came to close it ("catch up... slowcoach!"), the work was straightforward specifically because the exact shape of what was missing had already been written down — nothing had to be rediscovered first. The value of flagging debt honestly isn't just honesty for its own sake; it's that it converts a future "where do we even start" into a future "here's exactly what's left," which is a much shorter distance to travel.

A benchmark's methodology is as much a deliverable as its number

An early performance comparison produced a result that looked meaningful and was actually backwards — the more permissive of two systems appeared to accept more input than the stricter one, because neither side had been run through the same preprocessing the real pipeline actually applies first. The number wasn't wrong because the measurement was sloppy; it was wrong because the two things being compared weren't actually facing the same input. Before trusting any comparison between two systems, confirm both are actually being exercised the same way a real caller would exercise them — a benchmark that skips this can produce a confident, wrong number faster than no benchmark at all.

A named, unproven suspicion is a place to go looking, not a place to stop

Re-measuring an existing benchmark found a real, reproducible regression against an earlier baseline. The likely cause was named directly and just as directly labelled unverified — no bisection had actually been run to confirm it. That honest half-answer turned out to be exactly the lead needed: asked afterward whether an optimisation existed, reading the specific code path the earlier suspicion had already implicated found a concrete, fixable inefficiency almost immediately. Stating "probably X, not confirmed" costs nothing and loses nothing — and when someone later asks what to do about it, that specific, honestly-hedged claim is a far better starting point than either silence or a false certainty in either direction.

A fix in duplicated logic isn't done until every copy is done

The same performance fix needed a second, independently-adapted implementation in a second, structurally different copy of the same logic before every real way of running a program actually benefited from it. Skipping that second copy wouldn't have been a smaller fix — it would have been a fix that silently only worked half the time, arguably worse than not fixing it at all, since it creates a new, invisible divergence between two things that are supposed to behave identically. When logic is genuinely duplicated across more than one implementation of the same system, budget for touching all of them as part of the same piece of work, not as a follow-up.

Naming a bigger opportunity precisely is real progress, even when you don't build it yet

The smaller performance fix surfaced a larger, structural one sitting right behind it — the same problem's real root cause, more expensive to fix, touching more of the system. Rather than either building it immediately or letting it disappear, it was named specifically enough to pick up later: what it would touch, roughly how large a change it would be, and why it wasn't being done now. Deferring a bigger idea isn't the same as dropping it, as long as the deferral is specific enough that someone (including a future you) can actually act on it without having to rediscover it from scratch.

See also

Act XIV of the PatLang journey for the full narrative these lessons are drawn from. The PEG grammar validator and the published grammar file for the technical detail behind the grammar-validation lessons above. The goal/pursue/activate demo for the worked example the design-quote lessons refer to. Debugging Strategy and its companion below apply the same benchmark-and-optimisation material from a software-engineering angle rather than a project-navigation one.