NAOMS Devlog

Building a sovereign, local-first memory & identity system โ€” in the open, honestly.

Deleting 8,300 Lines: When AGENTS.md Became Policy

Why moving an agent's rules out of code and into readable data is a governance decision, not just a refactor

Technology Architect free May 17, 2026ยท5 min readยทgovernance
TL;DR We deleted ~8,300 lines of bespoke rule code and lost nothing โ€” because 142 rules an agent must follow stopped being little programs and became readable definitions a single engine reads. The line count is just how you notice the rules became something you can audit.

The most satisfying commit of this week deletes more than it adds. On 2026-05-17, a change landed whose subject line reads, in effect: "migrate 142 rules from custom code to closed-form phrases ... delete ~8,300 lines of legacy machinery." One hundred and forty-two rules moved from bespoke code to declarative data, and roughly eight thousand three hundred lines of the machinery that used to back them went away.

That number โ€” 8,300 lines deleted โ€” is the headline, but it's the least interesting thing about the change. The interesting thing is what kind of change it was. It wasn't a refactor for tidiness. It was the moment the rules a NAOMS agent must follow stopped being programs and became definitions.

The "before": every rule was a little program

NAOMS agents operate under a policy engine. Before any work, an agent asks the engine to check what it's about to do against a set of rules. The rules encode the discipline that lives in AGENTS.md โ€” the Zero Rule (work in a worktree), the back-off ladder, the "don't capitulate, don't endlessly ask" balance, and dozens more.

In the old design, each of those rules was its own small piece of imperative code โ€” a custom evaluator. A rule that says "the agent should not capitulate to pressure" was a function someone wrote, with its own parsing, its own matching, its own edge cases. Multiply that by 142 rules and you get what the commit calls "legacy machinery": thousands of lines of one-off evaluators, each subtly different, each a place a bug could hide, each something a human had to read code to understand.

There's a deeper problem than line count. When a rule is code, the rule and its enforcement are tangled together. You cannot read what the rule is without reading how it's checked. For a governance system โ€” where the whole point is that the rules are legible, auditable, and trustworthy โ€” that's backwards. The rule should be the readable artifact; the enforcement should be a single, shared, boring engine you trust once.

The "after": rules as closed-form phrases

The work introduces a declarative representation called closed-form phrases. Instead of writing a function to detect a violation, you declare the phrases โ€” the closed set of forms โ€” that constitute the rule, and a single shared evaluator matches against them. The pieces landed in two parts on the same day:

  • Part 1: the engine side โ€” a closed-form-phrases evaluation arm, one evaluator that handles all such rules, and a delta-comparator so you can diff what the new declarative rules match against what the old custom code matched. The delta-comparator is the safety net: it lets you prove the migration is behavior-preserving rule by rule, instead of hoping.
  • Part 2: the migration itself โ€” 142 rules rewritten from custom evaluators to phrase definitions, the old machinery deleted, and one rule split into two (capitulation vs. ask โ€” they'd been conflated; 142 became 143).

That split is worth pausing on, because it's the kind of clarity you only get after you stop writing rules as code. "Don't capitulate" and "don't endlessly ask for confirmation" had been living in one tangled evaluator. They are genuinely different failures โ€” one is giving up under pressure, the other is refusing to act on an unambiguous path. Once the rules are declarative, the seam between them is obvious, and you split them so each can be matched, reported, and reasoned about on its own. The refactor revealed a modeling error that the code form had hidden.

Why moving rules to data is a governance decision

You could describe all of this as "we replaced custom code with a config-driven evaluator," shrug, and move on. We want to argue it's more than that, because the thing being moved is governance.

When rules are code:

  • Auditing them means reading code. The set of people who can verify "do the agents actually follow the discipline we wrote down?" is the set of people who can read the evaluators. That's a small, expensive set.
  • Changing a rule means a code change, with all the risk that carries โ€” you might break the engine while editing the rule.
  • The rule and its enforcement can drift: the prose in AGENTS.md says one thing, the evaluator does another, and nobody notices because they're different artifacts.

When rules are closed-form phrases:

  • Auditing them means reading definitions. The phrases are the rule. Someone who can read AGENTS.md can read the rule set, because they're converging toward the same shape.
  • Changing a rule is editing data, evaluated by an engine you've already trusted once. The blast radius shrinks to the rule.
  • The delta-comparator makes drift visible: you can mechanically diff old-behavior against new-behavior and catch any rule that changed meaning in the move.

This is the same instinct that makes us prefer signed declarative artifacts everywhere in NAOMS โ€” chains over mutable state, credentials over permission flags. A rule you can read and verify beats a rule you have to execute to understand. Governance that can't be audited cheaply isn't really governance; it's a hope that the code does what the docs say.

The honest scope

Two honesty notes. First: the ~8,300 figure is the commit author's own count in the change's subject line; we cite it as stated, and the direction (a large net deletion) is the verifiable point, not a line-exact audit. Second: this was a large effort with many milestones, and the 2026-05-17 transcripts carry little human-typed voice โ€” so the framing of why (governance legibility) is our reading of the design, grounded in the commit subjects (the hardening, the delta-comparator, the capitulation/ask split), not a quoted decision from that day. The dated, verified facts are the commits behind it.


The lesson we'd hand to anyone building an agent-governance layer: write your rules so they can be deleted as code and kept as data. The day you can delete 8,300 lines of evaluators and lose nothing โ€” because a single engine now reads declarations the old code used to hard-bake โ€” is the day your rules became legible. That legibility is the product. The line count is just how you notice.


Written by AI agents from real project logs; owned and edited by Mujo.

โ† more in Technology   home โœฆ   all โ†’