Appearance
Skills carry intent, CLI tools mutate state, hooks enforce contracts — three layers, one job each, no bleed, and advisory prompting never substitutes for a hook that blocks.
Pattern
Layered Enforcement
The shape
Three layers. Each reads from below, enforces on above.
Layer 1
Skills
intent
- Orchestrate workflows
- Spawn agents
- Read spec, write briefing
Does NOT
write code
enforce contracts
Layer 2
CLI Tools
state mutation
- task_create / update / get
- ADWState
- Mutate task record + pipeline
Does NOT
make decisions
enforce contracts
Layer 3
Hooks
enforcement
- Fire at tool boundaries
- Read state from L2
- Block or allow L1 actions
Does NOT
produce artifacts
mutate state directly
Layers read downward and enforce upward. Jobs don't overlap — and can't be swapped.
The anti-pattern
Advisory enforcement is a suggestion. The agent can override it.
Enforcement in the promptadvisory
lives in: L1 skill / agent prompt
"Before writing, make sure you've read every file listed in requiredReads."
Agent reads instruction ✓Agent intends to comply ✓Context pressure mounts…Write fires without all reads
The instruction was followed sometimes. It can be forgotten, misinterpreted, or skipped under pressure — no mechanism catches the miss.
Enforcement in a hookstructural
lives in: L3 hook (PreToolUse:Write)
context-gate.sh reads ledger. If requiredReads incomplete → exit 2.
Agent calls WriteHook fires, checks ledgerReads missing → BLOCKEDAgent reads, retries → ALLOWED
The rule can't be skipped. It's not about trusting the agent — it's about the reliability of the system. Structural enforcement doesn't depend on the agent remembering.
The invariants
Each hook enforces one cross-layer contract.
context-gate.sh
requiredReads were read before any Write
builder-product
planner-task-create-gate.sh
task created with --files-expected, --layer, --required-reads
/planning-products
product-spec-stop-verify.sh
filesExpected satisfied on disk + ledger at Stop
any builder task
subagent-context-check.sh
spawn prompt has all 5 required sections
any agent spawn
active-task-recorder.sh
active-task.json written on in_progress call
ledger precondition
Reliability comes from the structure — not from any individual agent doing the right thing.
Which layer?
Every new requirement maps to exactly one.
need
"Enforce that agents don't write to protected files."
↳Layer 3 · PreToolUse:Write hook
need
" Track which phase each task belongs to."
↳Layer 2 · CLI tool field
need
" Orchestrate a new 3-phase workflow."
↳Layer 1 · Skill
need
"Enforce that new workflows follow the 3-phase structure."
↳Layer 3 · Stop-event hook on the skill
Category errors are silent. Enforcement in L1 becomes advisory. State tracking in L3 becomes brittle and unqueryable. Classify first — the layer decides the mechanism.
The discipline
Advisory enforcement is not enforcement.
A hook that blocks a tool call cannot be overridden. A sentence in a prompt can. When you catch yourself writing "make sure you check X before Y," stop — that's a hook, not a paragraph. Pick the layer before you pick the mechanism.