AI Coding Harness
What it is
An AI coding harness is the enforcement and verification scaffolding you build around a coding agent so it can run autonomously without breaking things. Where a guardrail is a habit you have to remember (run the tests, read the diff), a harness is a machine that remembers for you: it sits between the agent's intent and the real world, and at every dangerous step it records, warns, or blocks. dancinlab/harness is a project-agnostic reference engine — a shared TypeScript core where each repo differs only by a harness.config.json plus a few .harness/*.json data files.
Strengths
- Turns your guardrails from optional habits into rules enforced by code — the agent can't skip them.
- Gates the whole tool lifecycle: before a command runs, before a file is written, on the prompt, on commit, and on push.
- Append-only JSONL ledgers give a tamper-evident record of everything the agent did — cheap to write, trivial to audit.
- Drops into any repo: behavior is config and data, not forked code.
- Designed to stay quiet when things are fine, so warnings still mean something.
Trade-offs
- It is plumbing, not magic: a harness makes mistakes cheap to catch, it does not make the AI correct.
- Needs initial setup and a config tuned to your project's danger zones.
- Over-strict rules create friction; the "bitter-gate" discipline (retire a dormant rule before adding a new one) exists precisely to fight this.
- Most valuable on real projects with real users — overkill for a throwaway prototype.
Best for
Serious vibe coding where you let an agent make multi-file changes and run commands largely unsupervised, and you need the cost of a bad action to stay near zero.
The five principles (H1–H5)
- H1 Success quiet, failure loud — no noise you'll learn to ignore.
- H2 Never auto-fix — propose, block, or warn; a human or the informed agent decides.
- H3 Bitter-gate — retire a dormant rule before adding a new one.
- H4 Config-driven — one engine, per-project
harness.config.json. - H5 AI-native — append-only JSONL ledgers, impossible to silently rewrite.
What it looks like
A minimal config sketch:
// harness.config.json
{
"lockedPaths": ["src/auth/**", "infra/**", ".github/**"],
"blockCommands": ["rm -rf", "git push --force", "curl * | sh"],
"verify": ["npm run lint", "npm run typecheck", "npm test"],
"ledger": ".harness/ledger.jsonl"
}
And the pre/post hook flow around a single agent action:
agent intends an action
│
┌────▼─────────────┐
│ pre (PreToolUse) │ block dangerous? warn? → else allow
└────┬─────────────┘
│ command runs / file is written
┌────▼──────────────┐
│ post (PostToolUse) │ record to JSONL · warn if a locked file was touched
└────┬──────────────┘
│ at commit / push
┌────▼─────┐
│ verify │ lint · typecheck · tests (parallel) → green or stop
└──────────┘
The agent never gets to bypass the gate — that's the whole point.