v0.8.0 — requirements approval gate

Train your AI coders like you'd train a vine.

An espalier trains a fruit tree to grow flat along a wall — pruned, wired, productive, impossible to mistake for a wild one. Espalier does the same for your AI coding agents: discover the patterns already in your codebase, encode them as constraints, get code that lands inside your conventions on the first try, not the fifth.

claude code
$/plugin marketplace add Junhanliu-dev/espalier-engineering
$/plugin install espalier-engineering@espalier-engineering
$/espalier-init
PLATE I · ESPALIER EN GOBLET Vitis methodicus ․ trained 2026 50 40 30 20 10 0 CM harvest tier training ii training i wiki/ on-demand hooks/ programmatic agents/ delegated skills/ phase-loaded rules/ always loaded /ESPALIER-INIT ․ ROOTSTOCK Fig. 1a — Pattern discovery & encoding
02 The problem

Plausible code that doesn't fit.

AI coders write plausible-looking code that doesn't match your codebase. It's not a model intelligence problem. It's an unwritten rules problem — patterns every experienced developer on the team knows but nobody documented. The model can't read your team's Slack history.

// invented

It writes a new formatDate() helper when you already have one three folders away.

// split

It carves a component into four files when the team keeps colocated views in one.

// picked

It reaches for winston when the project standardised on pino two years ago.

// threw

It handles errors with throw when your repo committed to Result<T> in 2022.

The model can't read your team's Slack history.

03 The solution

Train the vine, then let it grow.

Espalier reads your code, extracts those rules, and writes them down as machine-enforceable constraints. The next time the AI codes, it loads your project's rules automatically and follows them. A reviewer agent — different agent, different tool set — checks against the same rules before any commit lands.

Rework cycles
3–5 typically 1
The first attempt lands inside your conventions because the conventions are loaded with the prompt and enforced by the reviewer. The middle four rounds vanish.
i. Discover

Read your code first.

Ten concurrent scouts inspect architecture, coding patterns, testing posture, CI, unwritten rules, and per-layer specs. An oracle pulls vendor docs in parallel. No templates from other projects.

ii. Encode

Write the rules down.

Patterns become rules/ always-loaded into Claude Code, skills/ loaded per phase, wiki/ on demand. Every rule cites the observed pattern that justifies it.

iii. Enforce

Gate every stage.

A separate reviewer agent (Read/Grep only — no Write) checks each output. Pre-push hooks block layer-boundary violations. Failed gates roll back; rollback counters escalate to humans.

04 What it generates

Inside the espalier/ directory.

After /espalier-init, a single per-project directory wires into Claude Code via symlinks. Hover any path to see what it does and when it loads.

espalier/
├── rules/ # structure, coding, security, production standards ├── skills/ # coding, review, testing, /espalier-fix, /espalier-ask, /espalier-audit… ├── agents/ # harness-coder, harness-reviewer, harness-security ├── wiki/ # architecture, data models, critical paths ├── hooks/ # layer boundary, pre-push, post-merge drift ├── pipeline.md # 10-stage workflow with gates & rollback └── changes/ # feat/, fix/, refactor/, docs/ — one dir per req
05 The two pipelines

One full lane, one bug lane.

After init, your repo exposes two orchestrators. Each stage has a programmatic gate, each gate either passes deterministically or rolls back. Brass dots are gates; failed gates accumulate into a counter that triggers human escalation.

/espalier <requirement>
Full 10-stage pipeline
For features, refactors, and large fixes. Requirement → reqs review → coding (sub-agent) → code review (different sub-agent) → tests → test review → push → CI verify → deploy verify → user confirmation.
01 requirement 02 reqs review 03 coding sub-agent 04 code review different agent 05 tests 06 test review 07 push 08 CI verify 09 deploy verify 10 confirm
/espalier-fix <bug>
5-stage bug-fix lane
Slimmer than the full pipeline. Stage 0 auto-link discovery walks git blame + reverse-lookup cache + squash-merge mapping to bind the fix back to the feature change that caused it.
00 auto-link causal binding 01 reproduce 02 fix sub-agent 03 regression test 04 push + CI 05 confirm
Prefix Type Output directory
feat: (or no prefix) Feature espalier/changes/feat/<slug>/
refactor: Refactor espalier/changes/refactor/<slug>/
docs: Docs espalier/changes/docs/<slug>/
fix: Bug fix use /espalier-fix instead
06 v0.8.0 · requirements approval gate

Sign off the requirement before a line of code is written.

Stage 1 → Stage 2 → Stage 3 used to chain automatically — coding began the moment the requirement doc existed. Now both pipelines stop after the requirement is written and reviewed, and wait for your explicit go-ahead. A Stage 2 PASS no longer authorizes coding on its own.

i
write — Stage 1 produces the requirement, grilled into requirements.md.
ii
review — Stage 2 checks it for completeness and scope.
iii
gate — the pipeline halts on Approve / Edit / Abort. The full pipeline gates between review and coding; the fix lane gates after Stage 1, downstream of its escalation gate.
iv
then code — only an explicit Approve lets Stage 3 begin.
Interactive-only — an unattended (no-TTY) run auto-approves so the pipeline never hangs. No new skill, no new stage.

v0.11.0 — the push gate actually blocks now. Claude Code hooks block only on exit code 2 with the message on stderr — the old gates’ exit 1 was a silent no-op. Every gate script and wrapper speaks the real contract (the wrapper fails closed without python and matches git -C … push and multi-line commands), the Stage 4/6 gates read the verdict word — closing the FAIL-with-P1-only and ESCALATION_REQUIRED-as-PASS holes — the reviewer/security agents get a record-file-scoped Write tool, and .claude/ symlinks go relative so a moved repo keeps working. Existing users run /espalier-migrate.

v0.9.1 — the review-round and rollback hard stops are now configurable. How many coder↔reviewer rounds run before the pipeline stops and asks a human used to be hardcoded prose (Max 2 P0 rounds) in the pipeline templates. It now lives in a tracked espalier/.espalier-configmax-req-rounds, max-code-rounds, max-test-rounds, max-rollbacks — that the orchestrator reads at runtime, falling back to 3 when a key is absent so a missing file never blocks. Defaults unify to 3 (code and test caps rise 2→3). Existing users run /espalier-migrate.

v0.9.0 — Stage 4 now runs a two-agent panel. Alongside the correctness reviewer, a new harness-security auditor checks the change's trust boundary on one rule — never trust data the frontend sent. It hard-blocks any sensitive field (price, userId, role, orderId, status) the backend fails to re-derive, re-authorize, or recompute, and requires an abuse test proving the tampered value is rejected and never persisted. The coder reads the same taxonomy while writing, so security shifts left. /espalier-audit runs the same auditor repo-wide over your existing code, dispatchable to /espalier-fix. The release also adds an always-loaded production-standards bar — resilience, observability, data-safety — the coder writes to and the reviewer enforces at tiered severity, plus a fail-closed push gate and a programmatic build/lint gate.

v0.8.2 — code review is now a fixpoint loop. When the reviewer files a P0 and the coder fixes it, the fix is re-reviewed — the only way out is a fresh review of the current code returning zero P0, so a new bug introduced by the fix can't slip through unreviewed. A push-gate certificate binds the verdict to a fingerprint of the reviewed source, so a fix that skips re-review fails closed at push time.

v0.8.1 — the coder and reviewer sub-agents now reason about every surface a change touches — admin / CRUD UIs, API validation, client forms, persisted data, other callers — not just the happy path. Closes a class of fix-round where a now system-derived value left "required" on a UI blocks the user before the server-side hook ever runs.

Existing users run /espalier-migrate — it auto-detects your version and applies the chain (… v0.9.4 → v0.10.0 → v0.11.0) in order.

New pipeline runs get the loop; in-flight changes are unaffected. Non-breaking.

07 v0.7.0 · read-only ask lane

Ask the codebase. Answered from your docs, checked against the code.

/espalier-ask <question> answers "how does this work / where is it / why is it built this way / what changed recently" — reading the espalier/ docs you already paid to build, instead of crawling the whole codebase from scratch every time.

i
classify — where / how / why / what-changed, so the question hits the right source: the wiki for how/where, the change history for why.
ii
read the docs first — wiki, rules, and changes/ records, before any from-scratch codebase search.
iii
verify against code — every doc claim is confirmed by reading the cited file before it lands in the answer. The wiki is the map; the code is the truth.
iv
answer with sources — doc path and file:line on every claim; fall back to a code search when the docs come up short.
Strictly read-only — never edits a doc, never opens a changes/ folder. No stages, no gates.

Two notify-only byproducts: a stale wiki it trips over while answering gets flagged (the same signal /espalier-doctor produces, pointing you at /espalier-prune), and a question the docs can't answer is logged to a git-tracked .ask-gaps.tsv — a backlog of what the wiki should cover next.

Existing users run /espalier-migrate — it auto-detects your version and applies the chain (… v0.6 → v0.7) in order.

Purely additive — no pipeline change. Non-breaking.

08 v0.6.0 · Stage 1 grilling

Interrogate the spec before the code.

A vague requirement — or an unconfirmed bug diagnosis — that passes Stage 1 is trusted by every later stage, and no later gate audits it. /espalier now grills that input first, turning an under-specified ask into one a coding agent can execute without guessing.

i
score the ambiguity — count concrete signals: undefined terms, unstated actors, missing failure behaviour, hidden quantifiers, unscoped edge cases.
ii
choose a depth — the signal count maps to a tier, so a crisp spec gets waved through and a fuzzy one gets pressed.
iii
ask, adaptively — a short sequential interrogation, only as many questions as the vagueness warrants. Each answer lands in requirements.md.
iv
two modesspec for /espalier requirements, diagnosis for /espalier-fix root causes — so the lane never patches a symptom on an unconfirmed theory.
On by default. --no-grill skips one invocation; an unattended (no-TTY) run auto-skips so the pipeline never hangs.

Change folders are now date-prefixed — changes/feat/2026-06-02-add-login/ — so a directory listing sorts chronologically.

Existing users run /espalier-migrate — it auto-detects your version and applies the chain (… v0.5 → v0.6) in order.

Stage 1 grilling is additive and interactive-only. Non-breaking.

09 v0.5.0 · doc-drift detection

Keep the guardrails honest.

The artifacts /espalier-init generates describe your codebase on init day. As code evolves, v0.5.0 keeps them in sync — without ever silently overwriting anything you wrote.

i
post-merge hook detects drift in generated docs and writes a gitignored sidecar — your tree stays clean.
ii
reviewer agent captures convention shifts a file diff can't see and adds them to a cross-PR convention index.
iii
Stage 0 pre-flight on every pipeline run surfaces all drift in one place before any new work begins.
iv
/espalier-prune <path> refreshes a flagged artifact via a single scout and a gated diff.
v
/espalier-doctor runs a periodic scan, re-scouting a handful of artifacts to catch drift no diff caught.
Nothing is ever auto-overwritten. Every refresh is gated by you.

Existing users on v0.4.x or earlier run /espalier-migrate — it auto-detects your installed version and applies the migration chain (v0.1 → v0.2 → v0.4 → v0.5) in order.

Drift detection is additive. Non-breaking for v0.4 installs.

10 Cost, honestly

Once-per-repo vs. every-request-forever.

/espalier-init is a heavy one-time tax — typically 10–15 minutes on a medium codebase (~150 source files). Every subsequent /espalier and /espalier-fix reuses what's generated.

Without Espalier

Re-discovery every request Agent re-reads source files into context each time. Same exploration, same tokens, every time.
3–5 review rounds Code doesn't fit, reviewer flags it, agent retries — across the full conversation per request.
Human re-explains You catch "this doesn't match our patterns" and re-articulate them by hand each round.
Silent drift Implicit rules forgotten across the codebase as the model picks whatever-it-felt-like-today.

With Espalier

Conventions loaded once ~3K tokens from rules/, always cached, no re-discovery.
Typically 1 round Code lands inside conventions on the first attempt because the conventions are in the prompt.
Reviewer agent enforces You review business logic only. Pattern adherence is automatic.
Drift detected, not silent Post-merge hook + reviewer + /espalier-doctor flag artifacts as they age.

Per /espalier-init in USD

Medium repo, ~150 source files. Across ~5–10 features you earn this back via dropped rework rounds.

Setup Per run
Opus everywhere (no cache)$10–20
Opus main + Sonnet scouts (no cache)$4–8
Opus main + Sonnet scouts + cache hits (typical)$2–5
Sonnet everywhere + cache$1–3
11 Philosophy

Five principles.

When an agent makes an error, engineer its elimination — not with prompt tweaks, but with files, rules, automated checks, and system structure.

i.

Discover,
don't prescribe.

Read the actual code, extract patterns. Never impose templates from other projects.

ii.

Gates are programmatic.

ci_status == 'success' AND tests_passed == total, not "check if CI passes".

iii.

Separate execution from judgment.

Coder and reviewer are different invocations with different tool sets. Reviewer gets Read/Grep only.

iv.

Context in layers.

Rules always loaded. Skills per phase. Agents see only their scope. Wiki on demand.

v.

Every rule has a reason.

Either reflects an observed pattern, or prevents a known failure mode. Nothing arbitrary.

An espalier is a tree that hasn't forgotten what shape it's meant to hold.

Anonymous · 1839
12 Install

Three ways in.

Marketplace install is the standard path. Manual clone is for hacking on Espalier itself. Project-scoped drops a single skill into one repo without going global.

Recommended. Updates flow in via /plugin update espalier-engineering.

claude code · marketplace
$/plugin marketplace add Junhanliu-dev/espalier-engineering
$/plugin install espalier-engineering@espalier-engineering
$# in any project:
$/espalier-init

For users not on the plugin path, or while iterating on Espalier itself.

shell · manual
$git clone https://github.com/Junhanliu-dev/espalier-engineering ~/repos/espalier-engineering
$ln -sfn ~/repos/espalier-engineering/skills/espalier-init \
~/.claude/skills/espalier-init
$# restart Claude Code, then in any project:
$/espalier-init

Update with cd ~/repos/espalier-engineering && git pull.

Drop the skill inside a single project rather than installing globally.

shell · project-scoped
$mkdir -p .claude/skills
$ln -sfn /path/to/espalier-engineering/skills/espalier-init \
.claude/skills/espalier-init