Structural Ratchet
A committed baseline holds each file’s structural high-water mark. A file you touch may improve or stay equal, never regress. Untouched legacy is never punished.

For the person who signs off on the merge · v4.7.0 · Apache 2.0
Your AI writes faster than you can review it. A prompt asks for your architecture rules and forgets them by the tenth file. This refuses the write instead, and the same rules run in your editor, in your pipeline, and in the criteria your reviewer reads.
⚙ craftsman:pre-write: 4 levels
✗ PHP001 Class must be declared final
✗ SEC001 Credential in source
✗ LAYER001 Domain imports infrastructure
✗ 3 violations: write refused
✓ fix applied · 3/3 passed
✓ File written to disk.The drift
01
No memory of yesterday’s decision. Today final class, tomorrow mutable state.
02
It writes code that works and quietly dissolves your layer boundaries.
03
The last hour of a session is never as good as the first. Six months of that, and your codebase carries a design nobody chose and you signed off on all of it.
Where this sits
BMAD, spec-kit and Superpowers decide what to build and in what order. They are good at it, and this plugin does not replace any of them. It answers the question they leave open: what happens when the model writes something the architecture cannot carry.
| Axis | Methodology plugins | Craftsman |
|---|---|---|
| What it is | A method. Prompts, templates, a workflow | A control. Hooks that run whether or not the model cooperates |
| How it acts | It asks the model to comply | It refuses the write before the file exists |
| When the context fills | Compliance decays with attention | Unchanged. It is bash and Python, not a paragraph |
| Where it reaches | The session it was invoked in | The session, your CI, and a baseline committed to git |
| What it knows | Software delivery, generally | SOLID, hexagonal, DDD, and taming inherited code |
Run both. The plugin detects Superpowers at session start and arms its gates on its workflows. Plan with the method you already trust, and let this one hold the line while the plan gets written.
The quality gate
A pre-write hook runs before the edit reaches your disk. What a regex can decide never reaches a model, so the expensive checks rarely run.
Forbidden patterns, naming, secrets. SEC001 catches a committed key before the file exists. Under 50ms.
LSP-backed, live, and only when the language server is already on your machine. The plugin orchestrates your tooling, it does not replace it.
PHPStan, ESLint, deptrac. Running a project’s analysers runs its code, so you allow it in your own global config. A repository can never grant it to itself.
Layer boundaries and DDD invariants. LAYER001 refuses a domain that imports infrastructure.
One rule set, two runtimes. What the hook refuses locally, the pipeline refuses on the branch, so nobody negotiates with the gate by pushing.
Inherited code
A quality gate that fails four hundred files the moment it is installed gets uninstalled the same afternoon. This one measures each file against its own recorded mark. Debt you inherited is not a violation. It becomes one the day somebody makes it worse.
And when you do decide to go in, there is a method for it, with an agent that works in its own git worktree so a rescue in progress never leaks into your branch.
/craftsman:legacy audit
Hotspots ranked by churn times complexity, from your existing tooling rather than a second opinion invented on the spot. Plus a contra section: what looks alarming and is fine.
/craftsman:legacy cover
Characterization tests pin the behaviour that exists, bugs included, before a line changes. Golden master, scrubbers, printers.
/craftsman:legacy untangle
Break the hard dependency that makes the class untestable. Subclass and override, wrap and sprout. Behaviour does not move.
/craftsman:legacy migrate
Strangler fig, branch by abstraction, anti-corruption layer. The old component retires when the new one carries the load, not before.
“The safety net comes before the refactor. No net, no change.”
Iron law 4, /craftsman:legacy
Receipts
A tool that enforces standards has to be held to them. v4.2.0 was an audit release. Every finding was reproduced before it was fixed, and each carries a test that fails when the fix is removed.
Level 2 and 3 could not run and said they were clean. Every analyser was capped at 2 seconds, below the cold start of all of them, and || true flattened the timeout into success.
CI reported a pass on a pipeline that inspected nothing. The default scan path was src/, so a Laravel app/ matched nothing and the run exited 0 with files_scanned: 0.
The test suite trained the learning loop on its own fixtures. 3704 of 15588 violations sat on a path this repository does not have.
The recurring shape is one defect wearing different clothes: a control that reports success when it did not run.
Correction learning
When you override the gate or rewrite what Claude produced, that correction is recorded and weighted. A fix that recurs becomes a candidate, and a candidate becomes a rule only when you say so.
No embeddings. No vector index. No external service. Knowledge is plain Markdown with YAML frontmatter, versioned in git, resolved through a deterministic rule-to-concept lookup, so the same input always yields the same rule.
ADR-0020 · promotion is human-gated
What is recorded
Every gate run is an event in a local SQLite database. The schema is deliberately boring, which is exactly what makes it short to audit.
rule id
LAYER001
severity
block · warn · ignore
path pattern
src/Domain/**/*.php
outcome
blocked · warned · fixed
timestamp
UTC
project hash
sha-256 of the repo root
never recorded
No telemetry, no analytics, no phone-home. With agent_hooks: falseand no Sentry configured, the plugin makes zero network calls.
Agent fleet
Mechanical work runs on the cheapest model that can do it. You do not choose, and you do not pay Opus rates to format a commit message.
Core · always available
Pack · when their pack is enabled
Opus is assigned to no agent: that tier is used by skills that need judgment spanning files. About $0.15 to $0.30 per session, and the core gate needs no API key. Read each agent’s frontmatter rather than its role name: two that sound like reviewers hold Edit.
The mechanisms
Ten of them. You need to understand two: the ratchet, which is why your codebase cannot get worse, and correction learning, which is why you stop repeating yourself. The other eight run without being asked.
A committed baseline holds each file’s structural high-water mark. A file you touch may improve or stay equal, never regress. Untouched legacy is never punished.
Three contradictors attack a design before any code exists. Every objection lands in a retained or dismissed table.
“Done” requires proof. A failing test run revokes a verification that already exists.
A fix that recurs three times across three files becomes a candidate you approve.
Every scaffold loads the canonical example before it writes a line.
Catches acceleration, scope creep and over-optimisation in your prompts, not the model’s.
15 core rules plus everything your pack adds, inherited global to project to directory. Legacy coexists with strict new code.
Opening a repository is not consenting to run it. A project file can never grant itself permission.
One rule set, four providers, identical to the hooks.
adapters/hermes refuses a conclusion rather than a write, because blocking a write assumes somebody can break the loop, and an autonomous agent has nobody.
Packs
A pack is a manifest, a rule set, and optional agents./craftsman:setup reads your repository and enables the ones that match.
filled = ships with the plugin · dashed = a skeleton to fork
pack.yml
name: symfony
version: 2.3.0
extends: [php-core]
rules:
- PHP001 # final by default
- LAYER001 # domain imports nothing
- SEC001 # no secrets in source
agents:
- symfony-reviewer (sonnet)Three steps
STEP 01
/plugin marketplace add
BULDEE/ai-craftsman-superpowersSTEP 02
/plugin install
craftsman@ai-craftsman-superpowersSTEP 03
/craftsman:setup
→ reads your repositoryRequires Claude Code 2.1.218 or later, python3 3.9+, and bash, grep, jq, sqlite3. GNU coreutils is not required: the plugin runs on a stock macOS.

Free & open source
The core gate runs entirely on your machine and costs nothing. Agent hooks are optional and cost cents per session. Two commands, one restart, and the next write is checked.
Install it now