Skip to main content
TruStacks
← All posts

The interesting part of a decision is what you turned down

TruStacks5 min read

A changelog tells you what a company built. It cannot tell you whether the shape was reasoned about or arrived at by accident, because both produce the same list of features. The useful record is the one that says what was decided against — reselling inference, auto-applying low-risk fixes, flattening the policy layers, exempting ourselves from our own gate. Four decisions, each with the tempting alternative we rejected.

Here is a problem with evaluating a young product: a well-designed one and an accidental one produce the same feature list.

Both have a policy engine. Both have agents. Both have a page describing an architecture. The list tells you what exists, and it is silent on the only question that predicts anything — whether the shape was reasoned about or whether it accumulated.

There is one artifact that separates them, and it is not the changelog. It is the record of what was turned down.

Why rejections carry the information

A decision to build something has many causes. It might be conviction, or a loud customer, or the fact that a competitor shipped it, or that it was simply the next obvious thing. You cannot tell which from the outcome.

A decision not to build something almost always costs money, and that is what makes it informative. Somebody wanted it. It was on a roadmap. It had a business case. Declining it means a principle outranked a benefit — and the principle it outranked for is the thing that will still be there when the pressure arrives.

So here are four of ours, with the tempting alternative in each case. All four are on the decision record with dates.

Before them, one decision that was not a rejection but sets up the rest. The project brief in this repository's first commit — before any code — says policy is Rego, evaluated by OPA. The gate was running against agent output the next day, with five rules behind it. Signed policy bundles landed the day after that.

Five rules is not an impressive gate. Building it first anyway is the point: every feature since has had to arrive through it. A mandatory gate retrofitted onto a system that already works without one is a migration nobody ever finds time for.

We turned down reselling inference

The obvious commercial move for a product built on large language models is to sit in the middle of the token bill. You buy inference wholesale, you sell it with the product, and the margin is clean and recurring. Plenty of good companies do this.

We decided in May that customers bring their own key and pay the provider directly.

The reason is that a token margin quietly inverts an incentive. The moment we make money per token, we benefit from agents that deliberate longer, retry more, and produce more output than you needed — and we would be the ones tuning them. There is no amount of good intent that survives that arrangement indefinitely.

It costs us a revenue line. It buys a sentence we can say without qualifying it: we do not make more money when your agents do more work.

We turned down auto-applying low-risk fixes

This one was genuinely tempting, and it came back more than once.

If an agent finds a vulnerable dependency and the patch is a version bump with a green build, why make a human look at it? Call that class "low risk" and apply it automatically. The time saved across a year is enormous, and the demo is fantastic.

We tried repeatedly to write down what "low risk" meant. Every definition we produced was a judgement call wearing the costume of a threshold — patch versions only, unless the project does not use semantic versioning; green build, unless the tests do not cover the changed path; no API change, unless you count behaviour.

Each qualifier was a judgement, and every one of them was our judgement being applied inside your repository. That is precisely the thing this product exists to prevent an AI from doing. It would have been incoherent to sell a gate and then ship a bypass for the cases we felt confident about.

So the remediation loop closes right up to the merge and stops there.

We turned down flattening the policy layers

This one is not commercial; it is the kind of decision that only shows up later.

Our rules arrive in layers — the constitution we author, specialist packs, and the overlay your architects write. The simplest implementation merges them at build time into one flat bundle. Faster to evaluate, less code, easier to reason about.

We chose to keep the layers separate and aggregate them at evaluation time, in a decision recorded on 30 April.

The reason only matters in hindsight, which is why writing it down mattered: once the layers are flattened, you cannot tell which layer a rule came from. And if you cannot tell that, you cannot prove that a customer's rule only tightened ours rather than replacing it. The entire ratchet-only property — the one that lets us say your architects can tighten our constitution and nobody can loosen it, with a linter proving it at compile time — depends on a directory layout decision made before any of the rules existed.

That is what a good architectural decision looks like from the outside: boring at the time, load-bearing later.

We turned down exempting ourselves

We have a naming standard for policy rules. The easy way to enforce a house convention is in the tooling — the CLI rejects a bad name, and the standard is a thing we impose on rules we did not write.

Instead the naming standard is enforced by a rule in the constitution, the same mechanism a customer's rules are subject to. Our conventions go through our own gate.

This is a small decision that answers a large question. A governance product that carves out a special case for its own output is telling you exactly how much it believes in the gate it is selling you. If the constitution is non-waivable, it has to be non-waivable for us too, or the word means nothing.

What to do with this

You are probably not evaluating us today. But you are likely evaluating somebody, and the pattern generalises.

Ask a vendor what they decided against, and when. Not what is on the roadmap — what was on the roadmap and got taken off, and why. Anyone can recite what they built. The ones who can name the alternative they rejected, and tell you what it cost them, are showing you how they will behave the next time revenue and principle point in different directions.

If they cannot answer, it is not necessarily that they are hiding something. More often it means nobody wrote it down, which means the shape of the product is the accumulated residue of a hundred local decisions nobody revisited. That is worth knowing before you build on it.

Ours are at /decisions, with dates, including the ones that have not aged especially well.

Agents propose. Policy decides. Humans approve.

One caveat this post owes you: the decision records themselves live in a repository that is not open to the public yet, so the decisions page carries our summary of them rather than the documents. That is a weaker offer than the real thing and we would rather name the gap than paper over it.

  • AI delivery governance
  • engineering decisions
  • policy as code

See it open a pull request.

Run the agent crew locally in about two minutes. No signup, no credit card. It reads a real repository and proposes a policy-checked pull request you review yourself.