Hook Enforcement Reference
12 scripts | 11 active in settings.json | 6 enforcement layers | ZERO standalone execution
The ADLC framework enforces constitutional governance through 12 shell scripts that fire automatically at different points in the agent lifecycle. Together they form a defense-in-depth chain where every agent action passes through multiple validation gates.
Coverage Matrix
Every tool call passes through at least one enforcement layer. The matrix below shows which hooks fire for each event type.
| Event | Hook(s) | Exit Codes | What Gets Blocked |
|---|---|---|---|
| UserPromptSubmit | remind-coordination.sh | 0/1 | All prompts when PO+CA logs missing |
| UserPromptSubmit | detect-nato-violation.sh | 0/2 | Completion claims without evidence |
| PreToolUse Bash | validate-bash.sh | 0/2 | Destructive commands, git mutations, IaC mutations |
| PreToolUse Bash | enforce-container-first.sh | 0/2 | Bare-metal terraform/tflint/checkov/infracost |
| PreToolUse Edit/Write | block-sensitive-files.sh | 0/2 | Access to .env, .pem, .key, .tfstate, credentials |
| PreToolUse Edit/Write | enforce-coordination.sh | 0/1 | Code changes without PO+CA coordination logs |
| PreToolUse Edit/Write | enforce-specialist-delegation.sh | 0/2 | Raw Edit/Write on domain files without specialist lock |
| PreToolUse Task | enforce-coordination.sh | 0/1 | Agent dispatch without PO+CA coordination logs |
| PreToolUse Task | write-specialist-lock.sh | 0 | (writes lock file, never blocks) |
| PostToolUse Task | log-coordination-wrapper.sh | 0 | (logs evidence, never blocks) |
| PostToolUse Task | enforce-pdca-cycle.sh | 0 | (tracks cycles, escalates at limit) |
| SessionStart | load-project-context.sh | 0 | (initialization, never blocks) |
Manual utility: log-coordination.sh is not wired into settings.json hooks. It is called by agents directly to create structured coordination logs with --scope and --scope-keywords flags.
Layer 1: Prompt-Level Enforcement (UserPromptSubmit)
These hooks fire before Claude processes the user's prompt. They cannot be bypassed by plan mode, permission overrides, or accept-all-edits settings.
remind-coordination.sh v4.3.0
Purpose: Block all prompts until product-owner and cloud-architect coordination logs exist for today.
Smart Bypass Architecture (solves the chicken-and-egg problem from v1.0.0-v3.0.0):
| Prompt Type | Detection Pattern | Action |
|---|---|---|
| Coordination-invoking | invoke|run|launch + product.owner|cloud.architect | Allow through (exit 0) |
| Informational | help|status|continue|what.*should|/help|/clear | Allow with reminder (exit 0) |
| Work prompt (no logs) | Anything else | BLOCK (exit 1) |
Validation chain when logs exist:
- File existence check (
product-owner-YYYY-MM-DD.json,cloud-architect-YYYY-MM-DD.json) - JSON syntax validation (
jq empty) - Required fields check (
timestamp,agent,status) - Status must be
"success" - Session scope (v4.2.0): If
ADLC_SESSION_SCOPE_STRICT=true, logs from a different session are rejected - HITL report scope drift (v4.3.0): Detects when prompt requests a HITL/manager report but coordination logs lack matching
scope_keywords(anti-pattern #19)
Version history:
- v1.0.0: BLOCKING — caused chicken-and-egg (can't invoke agents when blocked)
- v2.0.0: BLOCKING + JSON validation — same problem
- v3.0.0: ADVISORY (exit 0) — too weak (Claude ignores stderr guidance)
- v4.0.0: BLOCKING + smart bypass — reads prompt from stdin JSON
- v4.2.0: Requires action verbs in patterns (bare
@agent-product-ownerno longer passes) - v4.3.0: HITL report scope drift detection
detect-nato-violation.sh v3.0.0
Purpose: Block completion claims that lack evidence paths.
Detection:
- 9 completion keywords:
complete,done,finished,implemented,resolved,fixed,delivered,shipped,ready for review - Evidence path patterns required:
tmp/,evidence/,artifacts/,coordination-logs/,test-results/,.json,screenshot - Strict mode (
ADLC_STRICT_EVIDENCE=true): Evidence paths must resolve to actual files on disk
Layer 2: Tool-Level Enforcement (PreToolUse)
These hooks fire before a tool executes. They inspect the tool input and block if the action violates governance rules.
Bash Tool: Dual-Hook Chain
When Claude calls the Bash tool, two hooks fire sequentially:
validate-bash.sh v2.1.0
Blocks dangerous shell commands across 7 categories:
| Category | Blocked Patterns | Principle |
|---|---|---|
| Destructive | rm -rf /, sudo rm, chmod 777, mkfs, dd if= | I |
| Sudo | sudo without explicit HITL context | I |
| Path traversal | ../../.. patterns | II |
| Credentials | cat .env, cat .pem, curl password= | II |
| Git mutations | git add/commit/push/merge/rebase/reset/revert/checkout/stash/cherry-pick/tag | I |
| IaC mutations | terraform apply/destroy/import/taint, terraform state rm/mv, cdk deploy/destroy/bootstrap, tofu apply/destroy | I |
| Publishing | npm publish, docker push, kubectl delete, helm delete/uninstall | I |
v2.1.0 addition (GITHUB_API_TREE_CORRUPTION incident):
Blocks gh api calls targeting git object mutation endpoints (repos/.../git/blobs, /trees, /commits, /refs). This closes the HOOK_BYPASS_VIA_API vector where agents used the GitHub API to circumvent git mutation blocks.
Allowed read-only operations: terraform state list/show, terraform output/show/graph/version/providers, all git read commands.
enforce-container-first.sh v1.0.0
Blocks bare-metal tool invocations that must route through container-first task commands:
| Blocked Command | Correct Alternative |
|---|---|
terraform fmt | task build:validate |
terraform validate | task build:validate |
terraform init | task build:validate |
terraform test | task test:tier1 |
terraform plan | task plan:cost |
tflint | task build:lint |
checkov | task build:lint |
infracost | task plan:cost |
trivy | task security:trivy |
Always allowed: task:* commands, docker exec/run/compose, DOCKER_HOST=* prefixed commands, _exec helper calls.
Bypass: ADLC_CONTAINER_FIRST_BYPASS=true in settings.local.json.
Edit/Write Tool: Triple-Hook Chain
When Claude calls Edit or Write, three hooks fire sequentially:
block-sensitive-files.sh v2.0.0
Blocks access to 22 sensitive file patterns:
.env, .env.*, .env.local, secrets/, credentials, .pem, .key,
.p12, .pfx, id_rsa, id_ed25519, .aws/credentials, .ssh/,
terraform.tfstate, .tfvars, .secret, .secrets.*, kubeconfig,
token.json, oauth*.json, service[-_]account*.json
All blocked attempts are logged to tmp/audit/sensitive-access-YYYY-MM-DD.jsonl for audit trail.
enforce-coordination.sh v4.0.0
Validates that product-owner + cloud-architect coordination has occurred:
- Checks for coordination log files (
coordination-logs/product-owner-YYYY-MM-DD.jsonandcloud-architect-YYYY-MM-DD.json) - Validates JSON syntax (
jq empty) - Checks required fields:
timestamp,agent,status - Verifies
statusis"success" - Validates agent agreement >= threshold (default 95%, configurable via
ADLC_AGENT_AGREEMENT_THRESHOLD)
No escape hatch: ADLC_AUTONOMOUS_MODE was removed entirely in v4.0.0. Zero standalone execution.
enforce-specialist-delegation.sh v2.0.0
Blocks raw Edit/Write on domain-specific files unless a specialist agent is active:
Delegation rules (16 patterns):
| File Pattern | Required Specialist |
|---|---|
*.tf, *.tftest.hcl, modules/** | infrastructure-engineer |
.github/workflows/*.yml | infrastructure-engineer or qa-engineer |
scripts/*.sh | infrastructure-engineer or qa-engineer |
tests/**, *_test.go, *_test.py, *.test.ts | qa-engineer |
security/**, *.policy.json, CODEOWNERS | security-compliance-engineer |
.claude/agents/**, .claude/commands/**, .claude/skills/**, .claude/hooks/** | meta-engineering-expert |
Detection mechanism (file-based lock, not env var):
write-specialist-lock.shwrites a lock file before the specialist Task starts- This hook reads the lock file and checks age < 300 seconds (TTL)
log-coordination-wrapper.shremoves the lock when the Task completes
See File-Lock Mechanism below for details.
Task Tool: Dual-Hook Chain
When Claude dispatches a specialist agent via the Task tool:
enforce-coordination.sh v4.0.0
Same coordination validation as Edit/Write (described above).
write-specialist-lock.sh v1.0.0
Writes a time-stamped lock file before the specialist agent executes. Only fires for known specialist agents (not coordination agents like product-owner or cloud-architect).
Specialist agents recognized: infrastructure-engineer, kubernetes-engineer, qa-engineer, security-compliance-engineer, observability-engineer, frontend-docs-engineer, meta-engineering-expert.
Lock file path: tmp/<project>/specialist-lock/<agent>-active.lock
Lock file content:
{
"agent": "infrastructure-engineer",
"started_at": "2026-03-08T10:00:00Z",
"epoch": 1772996400,
"session_id": "abc123",
"lock_file": "tmp/terraform-aws/specialist-lock/infrastructure-engineer-active.lock",
"ttl_seconds": 300,
"written_by": "write-specialist-lock.sh v1.0.0"
}
Layer 3: Post-Execution Audit (PostToolUse)
These hooks fire after a tool completes. PostToolUse hooks must never block (exit 0 always).
log-coordination-wrapper.sh v2.1.0
Purpose: Auto-log evidence for ALL agent completions (coordination + specialist).
- Classifies agents into
agent_class: "coordination"(product-owner, cloud-architect) oragent_class: "specialist"(all others) - Writes structured JSON log to
coordination-logs/<agent>-YYYY-MM-DD.json - Coordination agents get
agreement: 97(design-level); specialists getagreement: 100(binary done/not-done) - v2.1.0: Removes the specialist lock file on Task completion, immediately closing the delegation window
Log schema:
{
"timestamp": "2026-03-08T10:05:00Z",
"agent": "infrastructure-engineer",
"agent_class": "specialist",
"status": "success",
"agreement": 100,
"session_id": "abc123",
"description": "Implement ECS module",
"source": "log-coordination-wrapper.sh v2.0.0",
"project": "terraform-aws"
}
enforce-pdca-cycle.sh v1.0.0
Purpose: Track Plan-Do-Check-Act cycles per specialist per day. Escalates to HITL when a specialist exceeds the cycle limit.
- State file:
tmp/<project>/pdca-cycles/<agent>-YYYY-MM-DD.json - Default limit: 7 cycles (
ADLC_MAX_PDCA_CYCLES) - When
cycle_count >= max_cycles: emits HITL escalation warning via stderr - Status transitions:
active->escalated - Specialists only (coordination agents are excluded from PDCA tracking)
Layer 4: Session Initialization (SessionStart)
load-project-context.sh v2.1.0
Fires once at session start. Never blocks (exit 0 always).
Actions:
- Auto-creates evidence directories (8 directories + 3 test-result tiers):
coordination-logs/
test-results/ (+ tier1-static/, tier2-unit/, tier3-integration/)
evidence/
screenshots/
cross-validation/
architecture-decisions/
cost-reports/
pdca-cycles/ - Version drift detection: Compares
VERSIONfile against 7 config files (settings.json, MANIFEST.json, package.json variants, docker-compose.yml, devcontainer.json) - Prerequisite checks: docker, node, jq, terraform
- Memory loading: Detects
.claude/memory/MEMORY.mdand project-specific memory from.adlc/projects/<project>/MEMORY.md - Coordination status: Reports whether PO+CA logs exist for today
Layer 5: Permission-Based Blocking (settings.json)
The settings.json permission model is the second line of defense (hooks are first). Permissions are enforced by Claude Code itself before hooks even fire.
3-Tier Permission Model
| Tier | Count | Behavior | Examples |
|---|---|---|---|
| allow | 34 | Auto-approved, no user prompt | Read(*), Glob(*), Grep(*), git status/log/diff, task:*, terraform state list/show |
| ask | 4 | User prompted for approval | terraform plan, tofu plan, Write(*), Edit(*) |
| deny | 30 | Permanently blocked | terraform apply/destroy, git add/commit/push, rm -rf, sudo, npm publish, Read(.env/.pem/.key) |
Environment Variables (16)
| Variable | Value | Purpose |
|---|---|---|
ADLC_ENFORCEMENT_MODE | BLOCKING | All hooks enforce (not advisory) |
ADLC_AGENT_AGREEMENT_THRESHOLD | 95 | Minimum PO+CA agreement percentage |
ADLC_STRICT_EVIDENCE | true | Evidence paths must resolve to real files |
ADLC_MAX_PDCA_CYCLES | 7 | HITL escalation trigger per specialist |
ADLC_NO_NATO | true | Completion claims require evidence |
ADLC_MANDATORY_AGENTS | product-owner,cloud-architect | Required coordination agents |
ADLC_CONSTITUTION_VERSION | 2.1.0 | Active constitution version |
ADLC_EVIDENCE_DIR | tmp/ | Root evidence directory |
Layer 6: Rules-Layer Mitigation (CLAUDE.md + adlc-governance.md)
Some attack surfaces cannot be covered by hooks. The rules layer provides behavioral constraints enforced by Claude's instruction-following.
Ungated Surface: Text Response
| Hook Event | Fires On | Can Block |
|---|---|---|
| UserPromptSubmit | User's incoming prompt | Yes |
| PreToolUse | Tool calls (Edit/Write/Bash/Task) | Yes |
| PostToolUse | Tool completion | No (audit only) |
| Text response | NOT HOOKABLE | No |
Mitigation: adlc-governance.md Content Classification requires PO+CA coordination logs before Claude produces implementation content (code blocks, architecture decisions, design comparisons, technology selection) in text output.
Content Classification
| Classification | Examples |
|---|---|
| REQUIRES PO+CA | Architecture decisions, design comparisons, technology selection, business value analysis, implementation recommendations, HITL deliverables |
| EXEMPT | Factual lookups, CLI output interpretation, reading/summarising existing files, status checks, error debugging |
| Boundary default | When ambiguous, requires coordination |
Anti-Pattern Tracking
The governance rules document 23 anti-patterns with root causes, hooks/prevention mechanisms, and fix descriptions. See Governance Rules for the complete table.
File-Lock Mechanism (Specialist Delegation)
The file-lock mechanism solves the ENV_VAR_DETECTION_DEAD_ZONE problem discovered in v1.x of enforce-specialist-delegation.sh.
The Problem
Claude Code's Task tool does not export custom environment variables when spawning subagents. ADLC_ACTIVE_AGENT is never set in the Claude Code runtime, making env-var-based specialist detection permanently inert.
The Solution
Three hooks cooperate to create a file-based lock lifecycle:
PreToolUse Task Specialist Executing PostToolUse Task
| | |
write-specialist-lock.sh enforce-specialist-delegation.sh log-coordination-wrapper.sh
| | |
Writes lock file ──────────────> Reads lock file (age < 300s?) ──> Removes lock file
(JSON with epoch, agent, If valid: ALLOW Edit/Write (immediate cleanup)
TTL=300s) If stale/missing: BLOCK
Lock File Details
| Property | Value |
|---|---|
| Path | tmp/<project>/specialist-lock/<agent>-active.lock |
| Format | JSON: {agent, started_at, epoch, session_id, ttl_seconds: 300} |
| TTL | 300 seconds (5 minutes) |
| Created by | write-specialist-lock.sh (PreToolUse Task) |
| Read by | enforce-specialist-delegation.sh (PreToolUse Edit/Write) |
| Removed by | log-coordination-wrapper.sh (PostToolUse Task) |
| Stale cleanup | Locks older than TTL are silently deleted during read |
| HITL bypass | ADLC_DELEGATION_BYPASS=true in settings.local.json |
Detection Priority
- File-based lock (primary) - works in all Claude Code contexts
- ADLC_ACTIVE_AGENT env var (fallback) - useful for CI/scripted invocations
- ADLC_ACTIVE_SPECIALIST env var (alias fallback)
Evidence Requirements (NATO Prevention)
Required Directory Structure
Created automatically by load-project-context.sh at session start:
tmp/<project>/
coordination-logs/ # PO, CA, and specialist agent logs
test-results/ # Test output
tier1-static/
tier2-unit/
tier3-integration/
evidence/ # Feature validation, deployment proof
screenshots/ # Visual verification
cross-validation/ # Multi-source accuracy checks
architecture-decisions/ # ADR evidence
cost-reports/ # FinOps evidence
pdca-cycles/ # PDCA state per specialist
Coordination Log Schema
{
"timestamp": "ISO8601",
"agent": "product-owner|cloud-architect|infrastructure-engineer|...",
"agent_class": "coordination|specialist",
"status": "success|failed",
"agreement": 97,
"session_id": "optional",
"description": "task description",
"source": "log-coordination-wrapper.sh v2.0.0",
"project": "terraform-aws"
}
NATO Detection Chain
detect-nato-violation.shscans prompt for 9 completion keywords- If found, checks for evidence path patterns in the prompt text
- If
ADLC_STRICT_EVIDENCE=true, validates that referenced paths resolve to actual files on disk - Blocks (exit 2) if completion is claimed without evidence
Related Pages
- Governance Rules - Anti-patterns and content classification
- Permissions - 3-tier permission model and environment variables
- Components - All 7 component types
- Principle I: Acceptable Agency - HITL approval boundaries
- Principle VI: Governance & Compliance - Certification and audit
- Principle V: Observability & Resilience - PDCA tracking