DEV Community

Cover image for Rules, Standards, and a Missing Line on My Chart
Athreya aka Maneshwar
Athreya aka Maneshwar

Posted on

Rules, Standards, and a Missing Line on My Chart

Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. Star git-lrc to help devs discover the project. Do give it a try and share your feedback.

A friend of mine sent over a blog post he'd been working on for a while, a genuinely deep dive into traffic law and, of all things, what it can teach us about governing LLMs.

I sat down to read it mostly out of curiosity. I was fighting a genuinely dumb bug at the time, and by the middle of the post my stomach did a little drop, because it was describing my bug back to me, just wearing a different costume.

The post's actual subject is speed limits, of all things, and how legal systems decide when to write a hard rule versus when to trust someone's judgment in the moment.

Turns out that's basically the entire job description of writing instructions for an LLM agent, except the "someone" making the judgment call is a language model instead of a driver, and the "speed limit" is whether your chart renders correctly or quietly draws nothing.

Let me walk you through how I got here.

I sit down to write some instructions for an LLM agent. The job sounds embarrassingly simple: look at a question like "is adoption increasing," pick the right chart, draw it. Bar chart, line chart, whatever. How hard can it be.

The instruction that seemed obviously fine

My first version of the rule was basically:

Draw a rolling average as a dashed line.

Reasonable, right? A human reads that and just does it.

So I fed it to the model along with a "here's roughly what the chart should look like" example, complete with a little placeholder in the JSON where the actual average number should go.

The model came back with a gorgeous chart spec.

Three layers, smooth interpolation, the works. Except the average line was invisible.

Not wrong, not off by a bit.

Just gone, like it had never been invited to the party.

Turns out the model had looked at my placeholder, something like "<period_avg>", and instead of computing the real number and putting it there, it copied the placeholder text itself, minus the angle brackets, as a literal string.

The chart library tried to plot the word "period_avg" on a number line and, understandably, drew nothing.

My "obviously fine" instruction was about as precise as telling someone to "drive safely."

That phrase should sound familiar to anyone who's read about Montana's old traffic law, which for a while genuinely told drivers to go at a speed that was "reasonable and prudent under the conditions."

It sounds wise.

It is also, as the Montana Supreme Court eventually found, a rule that doesn't actually tell a driver where the line is until after they've already crossed it.

My chart instruction had the exact same disease.

It told the model to be reasonable and prudent about the average line, and reasonable and prudent turned out to mean "make something up that looks like the right shape."

You cannot remove indeterminacy. You can only decide where it lives.

I'd already shipped the bug by the time I read that line.

Rules, standards, and why "just be sensible" always backfires

Here's the framing that clicked for me, borrowed straight from legal theory: every instruction you write has to live somewhere on a spectrum.

At one end you've got hard rules.

"The count query must return exactly one row and one column."

Cheap to write, cheap to check, boring, and completely unambiguous.

At the other end you've got standards.

"Pick whichever chart best communicates the trend."

Rich, contextual, and utterly useless if you need consistent behavior across ten thousand calls a day.

The economist Louis Kaplow has a paper about exactly this tradeoff in actual law, and the short version applies disturbingly well to prompt writing: a precise rule is expensive to write once and cheap to apply forever.

A vague standard is cheap to write and expensive every single time someone has to apply it, because now every application requires fresh judgment.

I had accidentally written a standard ("draw the average sensibly") in a place that desperately needed a rule.

The fix wasn't a longer, more eloquent paragraph explaining what a good average line looks like.

Eloquence is not the bottleneck here.

The fix was removing the judgment call entirely.

Instead of asking the model to compute a number and paste it into a placeholder, I pointed the average line straight at an aggregate function the charting library already understands: take the mean of a column that's already sitting right there in the data.

Zero values to invent.

Zero placeholders to mess up.

The rule became so boring there was nothing left to misinterpret, which, it turns out, is the entire point of a good rule.

The second bug was worse, because it looked like success

Once the average line worked, I hit a subtler problem.

The model would write a lovely SQL query, get back seven rows, correctly decide "this should be a chart," and then my own code would quietly downgrade it to a CSV download instead.

No error. No warning. Just... wrong output, delivered with total confidence.

The culprit: earlier in the pipeline, before the real query even ran, I'd asked the model to predict how many rows the answer would eventually have, so I could decide chart versus file export ahead of time.

Sometimes that prediction was garbage (an ungrouped total instead of a grouped count), and my code trusted the garbage prediction over the real, already-fetched data sitting three lines below it in the same function.

This is Kaplow's cost question showing up somewhere I didn't expect it.

Where is it cheapest to resolve the uncertainty: at prediction time, or at ground truth time? I'd resolved it at the worst possible moment, based on a guess, when the actual answer was one line of code away.

Moving that decision to after the real query ran didn't just fix a bug.

It deleted an entire category of bug, because the model's SQL-writing mistakes could no longer poison a decision that didn't need them anymore.

Frederick Schauer has this great point buried in his work on rules: sometimes you deliberately want a rule to be dumber than the smartest available judgment, because a dumb rule applied consistently beats a smart judgment applied inconsistently.

My "trust the actual fetched rows, not the earlier guess" rule is dumber than "let the model reason about it."

It is also unbreakable in a way the smarter version never was.

Where I finally put the "use your judgement" clause

Here's the thing though: I didn't purge every trace of contextual reasoning from the system.

That would just be Montana's problem wearing a different hat, except now instead of one vague rule you have zero rules and pure vibes.

What actually worked was a layered structure, and once I saw it laid out, it mapped almost cleanly onto the rules-standards-exceptions-principles ladder that shows up in legal theory:

  • Rules for the boring, high-frequency stuff. Every chart is one of a fixed list of shapes. Every count query returns exactly one number. No exceptions, no vibes, just mechanical compliance.
  • Standards for picking the actual chart family. "If the question is about a trend over time and the metric is noisy, layer a smoothing line over it." That's contextual, but it's contextual within a tightly bounded menu, not "do whatever seems right."
  • Exceptions for the cases where the standard would actively lie to you. One chart family exists purely because the default "smooth it with a rolling average" advice is wrong when the question is really about volatility, not trend, since averaging away the noise hides the exact thing being asked about.
  • A principle at the very bottom, for the question that matches nothing on the list: fall back to the smallest set of general obligations (state the time range, cite real numbers, never leave the reader with a bare figure and no context) and let the model actually think, instead of pretending every possible question was anticipated in advance.

Rules for scale. Standards for nuance. Exceptions for failure. Principles for the unknown.

The trick, and this is the part that took me embarrassingly long to internalize, is that the model should almost never reach that bottom layer.

If your "genuinely novel, use your best judgment" path is getting exercised on every third question, your rules and standards are doing a bad job and no amount of principled reasoning at the bottom is going to save you.

The escalation should be rare.

Cheap layer first, expensive layer only when the cheap one genuinely can't cope.

The genuinely surprising bit

The part I didn't expect going in: none of this made the model dumber to work with.

It's the opposite.

Once the boring 80% of decisions were nailed down as hard rules, the model's actual reasoning budget got spent entirely on the 20% that deserved it.

Before, it was burning effort re-deciding "should this be a bar chart" on every single call, the way you'd burn brainpower re-deriving whether 70mph is safe every time you pass a certain stretch of highway.

After, that question was already answered, permanently, and the model could focus on the part that actually needed a brain: does this specific question's phrasing match a known exception, or not.

If you're building anything with an LLM in the loop and you catch yourself writing an instruction that sounds like "use good judgment" or "do this sensibly," that's usually the tell.

Somewhere in your system, indeterminacy has to live.

The only real question is whether you're choosing where, on purpose, or whether you're finding out the hard way when an average line quietly vanishes from a chart and nobody notices for a week.


AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs — without telling you. You often find out in production.

git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.

Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.

⭐ Star it on GitHub:

GitHub logo HexmosTech / git-lrc

Free, Micro AI Code Reviews That Run on Git Commit




GenAI today is a race car without brakes. It accelerates fast -- you describe something, and large blocks of code appear instantly. But AI agents silently break things: they remove logic, relax constraints, introduce expensive cloud calls, leak credentials, and change behavior -- without telling you. You often find out in production.

git-lrc is your braking system. It hooks into git commit and runs an AI review on every diff before it lands. 60-second setup. Completely free.

In short, git-lrc helps Prevent Outages, Breaches, and Technical Debt Before They Happen

At a glance: 10 risk categories · 100+ failure patterns tracked · every commit…

Top comments (0)