Skip to content

GUIDES

AI Coding Workflow: 273 Rules, 36 Gates, 0 Automatic

An ai coding workflow is what runs, not what is written down. This project states 273 rules, backs 36 of them with a check, and fires none of them automatically.

Every published ai coding workflow is a list of rules: put your conventions in a context file, plan before editing, review the diff, run the checks. None of it is wrong, and none of it is a workflow. A workflow is the subset that executes whether or not anybody remembered it. npm run check:gates counts all three quantities on this repository — rules written, instruments that can fail, and triggers that fire without being asked — and the third number is zero. If you are still choosing the tool this workflow would run on, the assistants pillar is the decision above this one.

Key takeaways

  • 273 normative rules across 491.5 kB of governing documents. 18 of them (7%) are in the 8.0 kB the agent holds without being asked.
  • 36 committed checks, 0 automated triggers. No CI, no git hooks, no npm lifecycle scripts, no check inside npm run build.
  • One "check" could not fail. It printed a warning about silently truncated context and exited zero, so every listing counted it as a gate. Found by this audit and fixed the same day.
  • The instruments are lopsided: 23 of 36 read scripts/, 10 read content/, and only 6 read app/.
  • 7.6 rules per gate is the ratio the project actually runs on, and it is generous — most of the 273 have no instrument at all.

The short answer

Write fewer rules and wire more triggers. The failure mode of an ai development workflow is not that the rules are bad — the rules here are specific, tested and mostly correct. It is that a rule with no gate behind it is a rule that holds exactly as long as attention does, and attention is the resource an agent session consumes fastest.

Three moves, in order of return: put the rules that must never break into the always-loaded context file, give each one an instrument that exits non-zero, then attach those instruments to something that runs on its own. This project has done the first two and not the third, which is why it can report the ratio honestly.

Terminal
npm run check:gates
# → 273 written rules across 491.5 kB
# → 36 instruments that can fail
# → 0 that fire on their own

The three numbers an ai coding workflow runs on

The script reads the governing documents, every scripts/check-*.mjs, and everything that could plausibly invoke one.

DocumentSizeTokensRulesLoading
CLAUDE.md8.0 kB~2k18always loaded
content-rules.md45.5 kB~12k87on demand
roadmap.md438.0 kB~112k168on demand
total491.5 kB~126k273

A rule is counted as a sentence carrying a normative modal — never, always, must, must not, do not, required, mandatory, non-negotiable. That is a keyword test over prose and not an inventory; a rule spread across three sentences counts once, and a sentence that merely mentions "never" counts as a rule. The report leans on the ratio between the columns rather than the absolute count, and the ratio is robust to the miscounts.

7% of the rules are in the context the agent always holds

CLAUDE.md is loaded into every session in full — Anthropic's memory documentation is explicit that it has no truncation limit, which is why keeping it small is a design decision rather than tidiness. At 8.0 kB it costs roughly 2,000 tokens per session and carries 18 rules.

The other 255 rules live in 483.5 kB that has to be opened. In practice it is opened when a task obviously touches it, which means the rules governing rare situations are the ones least likely to be in context when a rare situation arrives.

That is not hypothetical here. Two of this project's worst self-inflicted failures were both rules that existed, in writing, in a document nobody had open:

  • A standards section instructed authors to mark deferred links with a bare <!-- --> HTML comment. MDX does not parse HTML comments, three articles followed the instruction, and the build aborted on all routes. The correct form was already documented in a different article on this same site.
  • A stale permission line survived six days past the decision that revoked it and cost nine articles their cover images, because the line said covers could be added later and the rule said they could not.

Both are the same shape: a written rule, correct at the time, in a file that is not in context, contradicted by a newer written rule in a different file that is also not in context. Why an agent appears to ignore its own configuration is usually this, before it is anything about the model.

A check that cannot fail is not a gate

The instrument audit classifies each check-*.mjs by whether any exit path is non-zero. A script whose only exit is process.exit(0) reports a problem and returns success — it can tell you something is wrong and cannot stop you.

On its first run this found one:

check:gates, first run
1 problem(s):
  - scripts/check-context-weight.mjs: no non-zero exit path — it reports,
    and a listing of "checks" counts it as a gate

check:context-weight measures the per-session context floor and prints a warning when the auto-memory index exceeds the documented 200-line / 25 kB read limit, past which content is silently dropped on the next load. It printed WARN and exited clean. For its whole life it had been listed among this project's checks, cited as one, and could not fail. It now exits non-zero on both of its warning conditions, and that change is in the same commit as this article.

This is the failure mode to look for in your own repository, because it is invisible from the outside. Every check:* in a package.json looks identical in a listing. The difference between a gate and a report is one integer, and nothing surfaces it.

What the instruments actually read

Each check is scanned for the path literals it opens, which gives a rough map of what the project has an automated opinion about.

TreeInstruments that read it
scripts/23
content/10
components/7
lib/7
app/6
.claude/6
public/3
db/2

Twenty-three of thirty-six instruments read scripts/ — mostly their own committed fixtures, which is how a measurement stays reproducible after the thing it measured changed. That is legitimate and it also means the majority of this project's checking apparatus is pointed at its own evidence rather than at its running code.

app/ is read by 6 and db/ by 2. The article route — the one module that needs all five side conditions and the highest-traffic page on the site — is covered by checks that assert on its rendered output, and by nothing that asserts on its logic. That is a defensible position and it should be a chosen one.

Nothing here runs without being asked

TriggerCountWhere it would live
CI workflows0.github/workflows
git hooks (non-sample)0.git/hooks
husky hooks0.husky
npm lifecycle scripts0pre*/post* in package.json
lint-staged0package.json
checks inside npm run build0package.json build

Zero. Thirty-six instruments, every one of which runs when a person types its name.

The fixes are not exotic. npm's lifecycle scripts would run a check before every build with one line; a pre-commit hook would run it before every commit. Neither is here, and the reason is the ordinary one: each was going to be added after the current article shipped, eighteen batches in a row.

This is the concrete version of a pattern this site keeps measuring in itself. A single prompt on this project has produced 236 tool calls and 75 file edits with nobody watching, and the run-length distribution has an empty middle — sessions are either short or very long, with almost nothing between. A long unattended run is precisely the condition under which "the operator remembers to run the check" stops being a mechanism.

The workflow that survived contact with the work

Stripped of everything unenforced, what this project actually runs is four steps, and they are worth stating because they are the honest version:

Best practices

  • Cap the always-loaded file and treat the cap as the budget. Anything that will not fit is a rule you are choosing not to enforce; decide that deliberately rather than by accretion.
  • Give every rule that matters an exit code. If you cannot describe the command that fails when the rule is broken, the rule is advice. Writing the guard alongside the rule is what keeps the two from drifting.
  • Audit your checks for exit paths, once. It takes a regex over process.exit and it found a real one here on the first run.
  • Attach one trigger before you write the next check. Thirty-six manual gates are worth less than three automatic ones, and this project is the evidence.
  • Date every rule and delete the ones it contradicts. Both of the failures above were a live rule and a stale rule coexisting. The stale one wins whenever it is the one in context.
  • Point at least one instrument at each tree you care about. Two trees here are read by fewer than three checks, and neither gap was a decision anybody made.

Common mistakes we made

  • We counted instruments and called it enforcement. The whole point of this measurement is the third column, and the first draft of the script did not have one — it reported 36 checks and would have let the article claim a workflow that does not run.
  • We assumed every check could fail. One could not, and it had been cited in this project's own documentation as a check for weeks. The audit that found it took twenty lines.
  • We put the rules where they were easiest to write. 168 of 273 rules live in the planning document because that is where the decision was being made at the time. It is a 438 kB file and the least likely of the three to be open.
  • We deferred the trigger eighteen times. Every batch added instruments and none added automation, which is the same compounding-deferral pattern this project has recorded against its own deploy for nine weeks. Writing the check is the enjoyable part; wiring it is not.

What we are not claiming

Unenforced rules are not worthless. CLAUDE.md demonstrably changes what the agent does, and none of its 18 rules has an exit code. Persuasion is a real mechanism. It is a different mechanism from a gate, and the mistake is counting them together.

"Normative sentence" is a scale, not an inventory. The keyword test miscounts in both directions. It is used for the ratio between rules and gates, which survives the noise; no single count above should be quoted as an exact number of rules.

One repository, one operator, one agent. A team workflow has review, approval and shared CI, and every one of those is a trigger this measurement would score above zero. What changes when more than one person is involved is a different article and a different set of constraints.

The instruments include this one. check:gates is one of the 36 it counts, and it has no automated trigger either.

Conclusion

Audit your own three numbers before adopting anyone's ai coding workflow: rules written, rules with an exit code, and triggers that fire on their own. If the third is zero, the workflow is a set of intentions with good documentation, which is what this project's was until the audit that produced this article. Fix it in the cheapest order — cap the always-loaded file, give the rules that matter an exit code, then wire one trigger. The wiring is the step everybody defers, and it is the only one that survives a long session. It is also the step that decides whether the throughput is worth anything: the same repository produced 183,788 words in 33 days and has delivered none of them.

Frequently asked questions

What is a good AI coding workflow?
One where the rules that matter most are enforced by something that runs on its own. Written conventions change what an agent does — that is a real mechanism and it is not a gate. This project states 273 normative rules across 491 kB of standards, backs 36 of them with a runnable check, and has zero automated triggers, so every one of those 36 runs only when a person types its name.
Where should AI coding rules actually live?
In the file the agent loads without being asked, kept small enough that it is loaded in full. Here that is CLAUDE.md at 8.0 kB and roughly 2,000 tokens, holding 18 of the project's 273 rules. The remaining 483.5 kB across two documents has to be opened deliberately, and in practice is opened only when a task obviously touches it.
Why does the AI ignore my instructions in long sessions?
Often because the instruction was never in the always-loaded context to begin with. A rule sitting in a 438 kB planning document is not competing for attention with your prompt — it is absent from it. Before treating non-adherence as a model problem, check whether the rule is in the file that loads by default, and whether anything would fail if it were broken.
Do I need CI to have an AI coding workflow?
You need something that runs without being asked, and CI is the usual something. This repository has 0 CI workflows, 0 git hooks, 0 npm lifecycle scripts and no checks inside the build, which makes 36 well-written gates a memory exercise. The gap between a check existing and a check firing is the single largest weakness this measurement found.
How do I know if a check is really enforcing anything?
Read its exit paths. A script whose only exit is process.exit(0) reports a problem and returns success, so a listing of checks counts it as a gate and it is not one. One of the 36 here was exactly that until this audit found it: it printed a warning about a truncated memory index and exited clean. It now exits non-zero.

Muhammad Kashif

Founder and editor of Devventa, covering AI coding assistants, Next.js and the modern AI development stack.