EXIT GATE, Not Prose: Why AI Codegen Needs Structural Enforcement
I put 'CRITICAL: always update Punk Records after shipping' in my agent skill. The agent shipped 4 times in a week without updating Punk Records. Here's the mechanism fix.
The short version
Prose rules in agent skill files get ignored under context pressure — measured at ~30% skip rate even with CRITICAL / MUST / NEVER framing. The fix isn't bolder prose. It's making the skill's output schema require structured evidence that the rule was followed. Skip rates dropped from ~35% to ~2%.
I put CRITICAL: always update Punk Records after shipping in my agent skill. The agent shipped 4 times in a week without updating Punk Records.
The problem
Prose rules in system prompts and skill files get ignored under context pressure. Not always, not deterministically, but often enough that any rule you care about will be skipped within a week of real usage.
This isn’t a model-capability complaint. It’s a mechanism problem. An agent’s primary loss function is “complete the user’s ask.” Every additional instruction — “also update this log,” “also check server-side validation,” “also verify the migration ran” — reads as an accessory to the primary task. Under token pressure, time pressure, or just a long context window, accessories get dropped.
I knew this theoretically. I watched Stella Protocol — my AI-PM methodology, the framework behind every post on this site — prove it empirically over four versions.
Evidence from Stella v0.5 through v0.8
Stella has a phase flow: DEFINE → DESIGN → BUILD → REVIEW → CLOSE. Each phase has a skill (stella-define, oda-design, etc.). Each phase’s skill file ended with something like:
Before transitioning to the next phase:
- Update brain/log-pose.md with current phase
- Append rationale to brain/vivre-cards.md
- Confirm all PRD items are marked
brain/vivre-cards.md is the append-only decision log — every significant choice gets a timestamped entry there.
Session logs across a dozen projects showed:
- 14 out of 40 BUILD-to-REVIEW transitions skipped the
brain/vivre-cards.mdupdate. Not always the same agent, not always the same project. Just skipped. - 9 out of 40 went directly from BUILD to CLOSE, bypassing REVIEW entirely. The skill file said “REVIEW is required.” The agent agreed it was required. It moved on anyway.
- 3 out of 40 skipped ODA design checks because the PRD had design notes inline and the agent inferred (wrongly) that those notes substituted for a design pass.
I caught most of these in after-the-fact log review. By “after the fact” I mean after the feature had shipped to production. The governance trail I was supposed to be able to trust had holes in it.
Why
Agents optimize for finishing. A skill file that says “update the log before proceeding” reads as:
- Primary: ship the feature the PM asked for
- Secondary: update the log
Secondary instructions compete with everything else in context — the user’s most recent message, the test output, the file being edited. Sometimes secondary wins. Often it doesn’t. And “often it doesn’t” is not an acceptable failure mode for governance.
Making the prose bolder doesn’t help. Neither does repeating it. I A/B’d. CRITICAL: prefixes, ALL CAPS, “MUST,” “NEVER SKIP” — skip rates moved from ~30% to ~25%. Not nothing, not a fix.
The breakthrough: EXIT GATE
Stop making the rule advisory. Make the skill’s output schema require a confirmation that the rule was followed. If the agent cannot produce the required output structure, it cannot exit the skill.
Before
stella-review.md skill file, v0.7:
When reviewing, make sure to check:
- Server-side input validation
- RLS policies on any new tables
- Environment variables not logged
- Error handling covers user-facing failures
Provide a review summary.
Output: a free-form “review summary.” Sometimes comprehensive. Sometimes “Looks good, ready to ship.”
After
stella-review.md skill file, v0.9:
Final output MUST match this schema exactly. Empty or
generic fields cause the gate to refuse.
## Security Checklist
- [ ] Server-side input validation: <specific endpoint + validation lib / approach>
- [ ] RLS policies confirmed: <specific table names, or "N/A — no new tables">
- [ ] Secrets not logged: <grep result for log statements in auth paths>
- [ ] Error handling: <specific user-facing failure modes covered>
## Scope Drift Log
- Written to: brain/scope-changes.md
- Entries appended this session: <count + line refs>
## Vivre Card Update
- brain/vivre-cards.md entry appended: <YES + timestamp, or BLOCK>
The agent now physically cannot hand back a “looks good, ready to ship.” It has to name tables. It has to name endpoints. It has to paste a grep result. If the fields are empty or generic (“validation is handled”), the gate refuses and the agent loops until it produces concrete findings.
Skip rate for the vivre-cards.md update dropped from ~35% to ~2% across the next 50 sessions. The 2% were cases where the agent filled in the field incorrectly — a different failure mode, one I can catch in CI.
Why this works
It mirrors how type systems beat documentation. A comment that says “this param should be a string” is advisory. A type signature that requires a string is structural. The compiler doesn’t need good intentions.
EXIT GATEs turn “please do X before proceeding” into “the output you must produce to proceed requires evidence that X was done.” The agent’s incentive to finish now aligns with doing X, instead of competing with it.
The caveat
EXIT GATE can become another prose rule if nothing actually validates the output. A skill file that says “output must include a Security Checklist” but has no parser checking that the checklist is present and non-empty is just longer prose.
Stella v0.9 uses markdown schema validation in CI: each skill declares its exit schema, a linter parses every brain/*.md file that a skill wrote, and fails the session log if required sections are missing or contain placeholder text. It’s not foolproof — the agent could paste plausible-looking garbage — but it catches the skip-class failures that dominated the v0.5-v0.8 data.
The evolution will keep going. Next up: EXIT GATEs that take structured input (JSON schema, not markdown) so the validator can check types, not just presence. The direction is the same: push every important rule from “prose the agent should respect” to “structure the agent cannot bypass.”
Lesson
Don’t trust agent discipline. Structure the tool so discipline is structural.
Every rule in your skill files that you actually care about enforcing needs an EXIT GATE. If you can’t write one — if the rule is too vague to require structured evidence — the rule is probably too vague to enforce at all, and you should sharpen the rule before you sharpen the enforcement.
Key Takeaways
- Prose rules are advisory no matter how loud. CRITICAL, MUST, and ALL CAPS moved skip rates from 30% to 25% — measurable, but not a fix. If the rule matters, it needs structure, not volume.
- Put the rule in the output schema, not the instructions. An EXIT GATE requires the agent to produce specific evidence (endpoint names, table names, grep results, timestamps) before it can finish. Finishing and complying become the same action.
- A gate with no validator is still prose. Schema requirements need a parser that fails the session when fields are empty or generic. Otherwise you’ve just written longer instructions the agent can skim.
Satellite: Morgans (this post) · Pipeline: AUDIT — Lilith Red findings → Morgans