Skip to content

Convert every plan row into a hook-enforced contract so the system — not the builder — decides when a task is done.

Guide

How to Enforce Plan Execution

The Core Problem

Self-certifying agents produce phantom completions

Without enforcementPHANTOM DONE

1Builder runs task

2Builder marks itself DONE

3Orchestrator trusts the status

4Pipeline continues — no check

Result: declared files may never have been written. The orchestrator has no way to know.

With enforcementHOOK IS JUDGE

1Builder runs task

2Stop hook fires automatically

3filesExpected checked against disk

4Task closes only if files exist

Result: the hook is the judge, not the builder. Completion is a verified fact, not a self-report.

Without enforcement, agents can declare victory and move on. The hook removes the builder's authority to self-certify.

The Three-Layer Pipeline

Each layer does exactly one thing

1

Skills — Orchestrators

Declare tasks, set expectations

/product-spec/planning-products

Reads TDD File Manifest rows and converts each into a task record with filesExpected populated.

2

CLI Tools — State Mutators

Read and write task-list.json

task_create.pytask_update.pytask_get.py

Pure state operations. They never decide whether a task passes — they only persist what they are told.

3

Hooks — Enforcers

Fire on tool events, cannot be reasoned around

Stop hookPostToolUse

Intercept every tool call. Cannot be skipped by agent reasoning — they run in the harness, outside the model.

Mixing layers breaks the guarantee. If a skill tries to do state mutation, or a CLI tool tries to enforce — the separation collapses and agents can route around the checks.

Three layers, three jobs. Separation is what makes the guarantee hold.

Reading Path

Six nodes — traverse them in order

01 — Start here\ \ Task\ \ The atomic unit of work. Holds filesExpected, status, and agent context — the record the hook reads at enforcement time.\ ↗ 02 — The mechanism\ \ Hook-Enforced Contract\ \ How a task declaration becomes an ironclad contract: the hook intercepts, checks, and either closes or blocks — no agent vote required.\ ↗ 03 — The principle\ \ Trust But Verify\ \ Why accepting agent output at face value is structurally unsafe and how independent verification at each boundary breaks the self-certification loop.\ ↗ 04 — The source\ \ The Plan is the Prompt\ \ The TDD File Manifest is not documentation — it is the executable spec that populates every filesExpected list in every task.\ ↗ 05 — The agents\ \ Builder-Validator Pair\ \ After the hook passes file presence, the validator reads the TDD and selfAudit independently — adding semantic correctness on top of structural enforcement.\ ↗ 06 — The architecture\ \ Layered Enforcement\ \ How Skills, CLI tools, and Hooks stack into a defense-in-depth system where each layer's guarantee is independent of the others.\ ↗

Each card is a standalone page. Read linearly for depth, or jump directly to the node you need.

The Enforcement Moment

What happens when the Stop hook fires

stop-hook — task enforcement sequenceHOOK FIRE

1readtask.filesExpected←task-list.json

["src/api/routes.ts", "src/api/schema.ts", "build-summary.md"]


2readwrite_ledger←tool-use-log(files builder touched)


3stateachfilesExpected[*]on disk


4aifANY file missing→ emit FAIL+ block task close

task.status remains IN_PROGRESS — pipeline halts


4bifALL files present→ emit PASS+ close task

task.status→COMPLETE — validator may proceed

The hook runs outside the model — it cannot be argued with, prompted around, or skipped. This is the moment "done" becomes a verified fact.

The guarantee

A task that says COMPLETE has the files on disk.

Not because the builder said so — because the hook checked. Convert every plan row into a task with filesExpected and the hook does the rest.