agent-delivery-gates

Delivery gates for AI coding agents, because green tests are not proof.

Breaks your code on purpose and reports the breaks no test noticed.
Runs a change's new tests against the code from before it.
Induces the failure your report says is handled.
Git hook, CI step or MCP server. No API key, zero dependencies.

View on GitHub

A green run that proves nothing

A shopping cart with four passing tests. An agent is asked to add promo codes. It does, and it adds three tests for the new behaviour.

$ node --test tests/*.test.js
# tests 7
# pass 7
# fail 0

Four tests became seven. Nothing failed. The feature works. A customer whose cart comes to exactly 50 has just started paying for shipping, and the test that would have said so was edited, in the same commit, until it could no longer fail.

Every check a project normally runs got better here, which is the point. A green run and a green run over checks that cannot fail look the same from outside, and only one of them means anything.

Three questions a green run cannot answer

Each one is a command with an exit code, and each answers by running something and reporting what happened, never by reading a diff and forming an opinion about it.

adg mutate

Would your tests notice if the code broke?

It breaks the code in known ways, runs the suite against every break, and reports the breaks no test failed on.

killed 2, survived 3, timeout 0, skipped 0

adg census

Did your new test ever actually fail?

It runs the tests a change added against the code from before the change. One that passes there would have passed without the fix.

not-red-before-green: passing against the base source

adg induce

Does your error handling actually run?

It runs a failure you declare twice, once with the handling in place and once with it taken away, and fails the claim when the check passes both times.

proven 0, handler-did-not-fire 0, check-does-not-measure 1, could-not-run 0

A fourth question is what the agent then writes about the work. A rule system checks the code an agent wrote, and runtime guardrails check its inputs and tool calls while it works; neither checks the account of the work once the work is done. That is fourteen proof obligations for a delivery report, five of them checked by a hook on every commit, running the same way in Claude Code, Cursor, Codex, GitHub Copilot, CI, or a plain pre-commit hook with no agent at all, and an MCP server for an agent that would rather ask than be stopped.

Seven worked examples

Hardest first. Each one run for real, with the exact output it produced. They open in the repository on GitHub.

What the gates caught here

This repository ran its own gates while it was being built, and logged what they caught in the gate tally as the work went: 103 entries, dated 2026-09-07 to 2026-09-09. Each entry is dated and says where to see the result, so any row can be opened instead of taken on trust. It is a receipt, not a claim.

Gate rejections logged per rule, from docs/gate-tally.md
RuleEntries
induced-failure-required31
full-finding-list19
cross-cutting-audit14
named-spec-files-fail-loud11
filesystem-allowlist6
one-fail-loud-setup-script6
commit-before-mutation5
coverage-as-gap-finder3
test-diff-reported-apart3
expected-value-derived-apart2
standing-adversarial-self-review2
red-before-green1
artifact-inputs-reproducible0
builder-reviewer-separation0

A zero does not mean a rule was unnecessary. It means the work stayed clean on that rule for the life of this build, or nothing looked closely enough to catch anything on it yet, and the count alone cannot tell you which.

Install

npm install --save-dev agent-delivery-gates
npx adg init
git config core.hooksPath .githooks

init writes a git pre-commit hook, AGENTS.md, an empty gate tally log, a CI workflow, and the hook and MCP configs for the agents listed below, and only ever creates a file that does not already exist. --dry-run prints what would happen without writing anything, --force overwrites a file that already exists, and --dir PATH targets a directory other than the current one.

Every check is a command of its own, read here out of the command line entry point: validate-report, test-diff, mutate, census, induce, tally, scan-prose, check. Each is an ordinary program with an exit code, so it runs from any pre-commit hook or CI job. agent-delivery-gates mcp starts a local MCP server on stdio: a client starts it, writes to its stdin and reads its stdout, and nothing about a project's code or reports leaves the machine.

Node 22.18 or newer. No runtime dependencies. Licensed under Apache 2.0.

Where it runs

The wiring each agent uses
AgentWiring
Claude Codea plugin that wires its own hooks in with no init step needed, or the lines init prints for .claude/settings.json
Cursor.cursor/hooks.json, written by init
Codex.codex/hooks.json, written by init
GitHub Copilot.github/hooks/agent-delivery-gates.json, written by init
CI, no agent.github/workflows/agent-delivery-gates.yml, written by init
Command line, no agentvalidate-report, test-diff, mutate, census, induce, tally, scan-prose, check, run directly or from any pre-commit hook

The Codex, Cursor, and Copilot hook configs use each platform's tool names as best guesses. Only the Claude Code plugin has run against the real tool, so the other three configs have not been loaded and confirmed by the coding tool they target.

The fourteen rules

All fourteen are recorded in the rules directory, one JSON file per rule. Everything below is read out of those files at build time, so this page cannot describe a rule the records do not carry. Grouped by each record's own enforcement field.

Enforced by a hook (5)

Checked mechanically on a relevant tool call or on every commit.

  • commit-before-mutation

    Commit before mutation

    A claim that a deliverable is finished and safe to hand to a reviewer for mutation testing.

    severity: critical tally entries: 5 the commit-before-mutation record

    Emits missing-commit-line

  • filesystem-allowlist

    Filesystem allowlist

    A claim that a build agent's filesystem access stayed within its intended scope.

    severity: critical tally entries: 6 the filesystem-allowlist record

    Emits path-allowlist-confinement

  • full-finding-list

    Full finding list

    A deliverable that runs an automated or human reviewer over the work and then reports on the review.

    severity: high tally entries: 19 the full-finding-list record

    Emits finding-list-incomplete, open-finding-not-carried

  • induced-failure-required

    Induced failure required

    Robustness, safety, and correctness claims: a report that says something is handled, isolated, recovered, prevented, rejected, or validated.

    severity: critical tally entries: 31 the induced-failure-required record

    Emits unproven-robustness-claim, evidence-not-durable

  • test-diff-reported-apart

    Test changes reported apart from source changes

    A claim that a fix works, resting on a test run that came back green.

    severity: high tally entries: 3 the test-diff-reported-apart record

    Emits assertion-removed, assertion-weakened, test-case-removed, test-file-declassified, skip-added, tolerance-widened, timeout-raised

Carried by prompt instructions (7)

No mechanical check today. These depend on the agent following the instruction and on a person reading the report afterward.

  • artifact-inputs-reproducible

    Artifact inputs reproducible

    A claim that a step produced an artifact whose content depends on specific inputs, such as a generated image with a prompt and a seed, a scaffold built from a template, or a dataset pulled from a query.

    severity: medium tally entries: 0 the artifact-inputs-reproducible record

  • coverage-as-gap-finder

    Coverage as gap finder

    A claim that test coverage supports confidence in a phase or step.

    severity: medium tally entries: 3 the coverage-as-gap-finder record

  • expected-value-derived-apart

    Expected value derived apart

    A claim that something was checked: a test, an assertion, a gate, or a report stating that a page, a document, or a count agrees with the record behind it.

    severity: high tally entries: 2 the expected-value-derived-apart record

  • named-spec-files-fail-loud

    Named spec files fail loud

    A claim that a prompt needing specification or reference files used the right ones.

    severity: medium tally entries: 11 the named-spec-files-fail-loud record

  • one-fail-loud-setup-script

    One fail-loud setup script

    A claim that a deliverable's manual setup steps are ready for a human to run.

    severity: medium tally entries: 6 the one-fail-loud-setup-script record

  • red-before-green

    Red before green

    A claim that a bug fix actually fixed something.

    severity: high tally entries: 1 the red-before-green record

  • standing-adversarial-self-review

    Standing adversarial self-review

    A claim that a build step is finished and ready to hand off, before any reviewer has looked at it.

    severity: high tally entries: 2 the standing-adversarial-self-review record

Needs a human gate (2)

No script can confirm these from the outside. They can be arranged for and then checked.

  • builder-reviewer-separation

    Builder reviewer separation

    A claim that independent review happened during a build.

    severity: high tally entries: 0 the builder-reviewer-separation record

  • cross-cutting-audit

    Cross-cutting audit at phase boundaries

    A claim that a multi-step build is internally consistent across steps, not just correct step by step.

    severity: high tally entries: 14 the cross-cutting-audit record

Questions

Does this need an AI agent to run?

No. The command line tools are ordinary programs with exit codes. The same checks run from a git pre-commit hook, from CI, or by hand, with no agent involved.

Does anything leave the machine?

No. The MCP server is a local subprocess on stdio, not a hosted service. Nothing about a project's code or reports leaves the machine, and there is no analytics or telemetry.

How many of the fourteen rules are checked mechanically?

Five of the fourteen are enforced by a hook that runs on a tool call or a commit. Two commands go further than that grouping suggests: census runs a change's new tests against the code from before the change, which is the mechanical half of red-before-green, and induce runs a declared failure with the handling in place and again with it taken away, which is what induced-failure-required asks for. The rest are carried by prompt instructions or need a person, and the catalog says which is which.

What does a rule with zero tally entries mean?

A zero does not mean a rule was unnecessary. Two of the rules sit at zero. It means the work stayed clean on that rule for the life of this build, or nothing looked closely enough to catch anything on it yet, and the count alone cannot tell you which.