qvib.pro
RU

~7 min read · everyone · Updated: 2 Jul 2026 · Читать по-русски

ENFORCED vs ADVISORY: Real AI Guardrails

ENFORCED vs ADVISORY: Where the Guarantee Is Real and Where It's Just an Instruction

In short

The most common lie in this market is passing an instruction off as a guarantee. We split rules into two levels and label each one right in the package: ENFORCED means a violation is blocked by an exit code (a git hook or CI fails with a non-zero exit code and physically won't let the commit through); ADVISORY means the rule is strict and literal, but there's no blocking process — it's an instruction to the model. Full enforcement inside someone else's runtime is impossible, since some targets are executed by a model we don't control, so the INSTALL note for every target states the enforcement level honestly for each class of rule. Honest labeling isn't weakness — it's protection against a false sense of security in production.

What it is

The most common lie in this market is passing an instruction off as a guarantee. "The engine WILL NOT allow a secret to leak" sounds like enforcement, but if all there is under the hood is text in a system prompt, that's hope, not a barrier. We separate two levels and label each one right in the package:

ENFORCEDguard-hook: блок ДО запуска командыpre-commit + CI: красный = стопADVISORY±Правила и workflow-проза±Модель следует, но код не блокирует
Where the guarantee is real (an exit code blocks it) and where it's an instruction
  • ENFORCED — a violation is blocked by an exit code. There's a process (a hook or CI) that fails with a non-zero exit code and physically stops the action or commit. That's a guarantee.
  • ADVISORY — the rule exists, it's strict and literal, the model follows it, but there is NO process that blocks a violation. That's an instruction.

Why honesty here is a feature, not a weakness

Full enforcement inside someone else's runtime is impossible: some targets are executed by a target model we don't control. Pretending "everything is enforced" means setting the user up for a fall in production. So the INSTALL note for every target honestly states the enforcement level for each class of rule.

What is genuinely ENFORCED today

1. The guard hook against catastrophe — Claude Code and Cursor. The base engine bakes in guard-dangerous.sh as a PreToolUse hook: it denys with exit 2 before the tool runs on rm -rf against root or home, DROP/TRUNCATE, git push --force, curl | bash. That's an exit code, not text — a hard guarantee at the model's boundary. Claude Code and Cursor support hooks at the tool boundary, so this layer is ENFORCED on both; targets without such a runtime (a bare AGENTS.md in an editor with no hooks, say) read the same rule as ADVISORY text.

2. The Portable Safety Floor — on ALL targets. This is already built (exporters/safetyFloor.ts, wired into the export through applySafetyFloor for every target). The package carries:

  • .engine/hooks/pre-commit — a self-contained POSIX hook (plain sh + grep, no Node or husky): it scans staged files for secrets (GitHub/OpenAI/Slack/AWS tokens, private keys) and for destructive or BLOCKED-DO-NOT-COMMIT markers, and exits with code 1 on a match;
  • .github/workflows/engine-guard.yml — the same scan on every push and PR, enforced whether or not the local hook is armed.

The scan body is identical in the hook and in CI (SCAN_SH verbatim), so "green locally" equals "green in CI." That converts part of ADVISORY into ENFORCED beyond Claude too.

What is honestly ADVISORY

  • Logic-level invariants (a tenancy filter in every query, i18n sync, reversible migrations) — the engine demands them literally, but compliance is checked by a prism verdict or the model, not by an exit code. The floor will catch a secret and an obviously destructive command; "forgot the org filter in a new query" it won't.
  • Prism verdicts and vetoes — the model is instructed to obey, but the verdict itself produces no exit code: on a target without the corresponding hook this isn't a blocking runtime.
  • Verify-green / doneCriteria — ADVISORY until you wire them into your own pre-commit or CI. (A reminder: the 10/10 doneCriteria layer isn't in the flagship Quest seed yet — it's a builder layer in development.)

Example: input → what the engine does → result

Input. The same engine is installed in two projects: on a target with hooks at the tool boundary (Claude Code / Cursor) and in an editor via a bare AGENTS.md with no hooks. In both, someone accidentally commits a file with the literal sk-abc123... in the code, and elsewhere tries to run rm -rf ~/.

Claude Code / Cursor (hooks at the tool boundary):

  • rm -rf ~/ → the PreToolUse guard hook fires BEFORE execution: BLOCKED by guard-hook: rm -rf against root/home directory, exit 2. The command never ran. ENFORCED.
  • a commit with sk-... → the portable pre-commit catches the secret: ENGINE GUARD: possible secret in ..., exit 1. The commit is blocked. ENFORCED.
  • The INSTALL note says it honestly: "Claude Code / Cursor: PreToolUse hook — ENFORCED at the model boundary; this git hook + CI are an additional ENFORCED layer."

An editor with a bare AGENTS.md (no hooks):

  • There's no hook at the tool boundary, so on this target the model reads the rule "don't run destructive commands" as ADVISORY text. If the model complies, great; there's no guarantee at the tool boundary.
  • BUT: a commit with a secret is still caught by the portable pre-commit (after git config core.hooksPath .engine/hooks) and — more importantly — CI engine-guard.yml fails the push or PR even if the local hook isn't armed. ENFORCED through CI.
  • The INSTALL note says it honestly: "Bare AGENTS.md: git hook (ENFORCED once armed) + CI (ENFORCED always). The rule text the model reads is ADVISORY."

Result. One class of protection (secrets and catastrophe) is hard on every target through the floor plus CI. Another class (logical invariants) is honestly labeled ADVISORY. The user KNOWS where the wall is and where the instruction is — and doesn't build production on an illusion.

Enforcement level by protection class on two targets
Claude Code / CursorBare AGENTS.md
Destructive commands (rm -rf, DROP, push --force)ENFORCED · exit 2ADVISORY
Secret in a commit (pre-commit hook)ENFORCED · exit 1ENFORCED once armed
Secret in a push/PR (CI engine-guard.yml)ENFORCEDENFORCED always
Logical invariants (tenancy, i18n, migrations)ADVISORYADVISORY
ENFORCED — a violation is blocked by an exit code; ADVISORY — the model reads the rule, no blocking process exists

The design principle

The point of the base engine is to make ADVISORY so literal and checkable that even a weak model executes it (behavior as a recipe, not "figure it out"), while in parallel pushing as many rules as possible into the ENFORCED floor. What's hard is labeled ENFORCED and provable by an exit code. What's an instruction is labeled ADVISORY. No "100% protected" where that isn't true.