Catalog
affaan-m/delivery-gate

affaan-m

delivery-gate

Stop hook that blocks Claude from finishing until quality checks pass. Detects rationalization patterns (surface text heuristics), stale learning logs (filesystem mtime), and low disk space. Complements self-audit by mechanically enforcing learning capture habits. Use when Claude should be mechanically blocked from declaring work finished before quality checks and learning capture actually pass.

NewUpdated Sep 9, 2026

Delivery Gate — Mechanical Quality Gate for Claude Code

A Stop hook that checks three things before Claude can finish a session, using only deterministic checks — file modification timestamps, disk usage, and regex patterns on the transcript text. No AI inference.

This is distinct from reasoning gates (like self-audit): delivery-gate checks machine-verifiable facts; self-audit checks output quality across four reasoning dimensions. Together they form defense in depth:

  • delivery-gate: "Was the learning library touched today? Is disk space safe?"
  • self-audit: "Is the file content correct, complete, and honest?"

This is the same pattern as CI pipeline gates — automated, deterministic checks that verify machine-readable facts rather than trusting self-reported status.

What It Checks

Check Mechanism On Hit
Rationalization patterns Regex on transcript tail Warning only (never blocks)
Stale learning libraries mtime on 5 configurable paths Warning if some stale; Block if >=3 stale OR growth-log stale + complex task
Disk space < 50GB shutil.disk_usage Warning
Disk space < 15GB shutil.disk_usage Block (exit 2)

Rationalization detection warns about patterns like "skip tests for now" and "pre-existing bug" — surface signals that thinking may have been cut short. It never blocks on its own, because regex heuristics can false-positive. The blocking conditions are: disk critical, >=3 learning libs stale, OR growth-log specifically stale (all require complex task >=3 edits).

Why

Claude Code's built-in checks cover code quality (build → type → lint → test). But there's a different failure mode: the agent produces working code while the session hygiene was neglected — learning not captured, rationalized shortcuts, disk running out silently.

Over many sessions of "ship and forget," the human hasn't grown. This hook enforces the habit: complex task → must touch learning libraries.

Install

cp quality-gate.py ~/.claude/scripts/

Add to ~/.claude/settings.json:

{
  "hooks": {
    "Stop": [{
      "hooks": [{
        "type": "command",
        "command": "python3 ~/.claude/scripts/quality-gate.py",
        "timeout": 5000
      }]
    }]
  }
}

Learning Libraries

Create these files in your project's memory directory. The hook checks if at least one was updated today:

memory/
├── growth-log/          # Daily learning entries (directory)
├── decisions/log.md     # Decision log
├── output-index.md      # Index of session outputs
├── ratings-tracker.md   # Skill ratings over time
└── tooling_capabilities.md  # Known tools inventory

Customize the LIBS dict to match your own file structure.

Configuration

Edit quality-gate.py:

Variable Default Purpose
RATIONALIZE 4 patterns Regex patterns for rationalization detection
LIBS 5 libraries Files/dirs to check for today's updates
COMPLEX_THRESHOLD 3 Edit/Write calls to classify as complex
DISK_WARN_GB 50 Warn below this
DISK_CRIT_GB 15 Block below this

Examples

Simple session — allowed:

edit_count=1 (< 3, not complex) → exit 0

Complex task, learning captured — allowed:

edit_count=5 (complex) → checks LIBS → growth-log updated today → exit 0

Complex task, no learning — BLOCKED:

edit_count=4 (complex) → checks LIBS → all 5 stale → exit 2
stderr: "Blocked: complex task completed but no learning captured today."

Low disk space — BLOCKED:

disk_free=12GB < 15GB critical → exit 2
stderr: "Blocked: disk space at 12GB (threshold: 15GB)."

Limitations

The hook enforces the habit of touching learning libraries, not the quality of what was recorded. If output-index.md is updated but growth-log is skipped, the hook passes (1 of 5 libraries touched). This is by design: mechanical gates check machine-verifiable facts. For content quality verification, pair with self-audit.

Compatibility

  • Python 3.8+ (uses from __future__ import annotations)
  • Cross-platform: Windows, macOS, Linux
  • Zero dependencies beyond stdlib

Quality

This code went through 4 rounds of automated code review (CodeRabbit + Greptile) with 9 real bugs found and fixed.

See Also

  • self-audit — Reasoning quality gate (completeness/consistency/groundedness/honesty)
  • verification-loop — Code quality checks (build/type/lint/test)
  • gateguard — PreToolUse safety gate
Files2
2 files · 8.7 KB

Select a file to preview

Overall Score

82/100

Grade

B

Good

Grades are signals, not a certification. Always review a skill yourself before use.

Safety

78

Quality

84

Clarity

86

Completeness

81

Summary

A deterministic Stop hook that blocks Claude from declaring work finished until quality checks pass. It verifies three machine-readable facts: learning library modification timestamps (via filesystem mtime), disk space availability (via shutil.disk_usage), and transcript patterns (via regex). Unlike reasoning-based gates, this enforces *mechanical* verification of session hygiene habits without AI inference.

Detected Capabilities

stdin read (transcript)filesystem access (memory directory scanning, file mtime checks)disk usage checks (shutil)regex pattern matching (transcript tail analysis)process exit code signaling (exit 0 = allow, exit 2 = block)stderr output (hook response logging)

Trigger Keywords

Phrases that agents use to match this skill to user intent.

enforce learning capturequality gate deliveryblock incomplete sessionslearning library checksession hygiene gatedisk space monitortranscript rationalizationmechanical exit block

Risk Signals

INFO

Reads full transcript from stdin or transcript_path, processes entire session history

main() -> raw = sys.stdin.read()
INFO

Scans project memory directory recursively (growth-log/) looking for today's file modifications

check_stale_libs() -> os.walk(full)
INFO

Accesses home directory to check disk space (cross-platform)

check_disk() -> shutil.disk_usage(home)
INFO

Exits with code 2 (blocking) based on machine-verifiable facts: stale learning libs or critical disk space

main() -> sys.exit(2)
INFO

Per-file error handling: individual unreadable files skipped, scan continues

check_stale_libs() -> except OSError

Use Cases

  • /home/user/code: After a complex coding session (3+ edits), hook blocks exit unless at least one learning library (growth-log, decisions, output-index, etc.) was updated that day
  • Prevent Claude from silently finishing sessions when free disk space drops below safety thresholds (15GB critical, 30GB warning)
  • Detect and warn about rationalization patterns in the transcript tail (e.g., 'skip tests for now', 'pre-existing bug') without blocking, to complement deeper self-audit reasoning
  • Enforce session hygiene habits: blocking exit when complex tasks complete but growth-log specifically remains untouched enforces learning capture discipline
  • Run as a deterministic pre-exit gate in Claude Code settings, paired with self-audit for defense-in-depth (mechanical facts + reasoning quality)

Quality Notes

  • Installation and configuration instructions are clear and explicit (LIBS dict customization, settings.json hook registration)
  • Three-level disk check strategy (remind 50GB, warn 30GB, block 15GB) is well-reasoned for different response levels
  • Rationalizing patterns (4 regexes) are realistic session anti-patterns (skip tests, pre-existing bug, won't fix)
  • Complexity threshold (3 edits) is clearly justified and customizable
  • Error handling is defensive: missing memory directory logs warning but does NOT deadlock new users; individual file OSErrors are caught and logged
  • Blocking conditions are explicit and unambiguous: (1) >=3 stale libs OR (2) growth-log stale for complex tasks
  • Code went through 4 rounds of code review; 9 bugs found and fixed (adds credibility)
  • Limitations section explicitly notes that the gate checks *habit*, not *quality* — content verification is deferred to self-audit
  • Paired integration with self-audit and verification-loop is documented, showing this is designed as part of a defense-in-depth pattern
  • Regex patterns include negative lookaheads to reduce false positives (e.g., pre-existing that/which)
  • MIN_CHARS threshold (40) prevents blocking trivial sessions
  • Logging is informative: each check produces diagnostic output (edit counts, stale libs, disk space)
Model: claude-haiku-4-5-20251001Analyzed: Sep 9, 2026

Reviews

Add this skill to your library to leave a review.

No reviews yet

Be the first to share your experience.

Version History

  1. v2.0

    Contract changed: description

    ✦ AIDescription clarified to emphasize mechanical blocking and gate enforcement conditions.

    triggering2026-09-09

    LATEST
  2. v1.0

    2026-06-30

    View This VersionInitial version

Use affaan-m/delivery-gate in your dev environment

Command Palette

Search for a command to run...