Skip to content
Conduit

skill

ef-harness

Spec-driven development harness for AI coding agents. Grill the decisions, write the RFC/PRD, check every spec claim against the real code, build against named proofs, then pass one adversarial audit.

micaelcf/ef-harnesscommunitylistedunreviewed

Set up

Skills are installed by placing their folder where your agent loads skills.

The download comes from github.com/micaelcf/ef-harness itself, not from our server, so what you get is exactly what its author published.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 17, 2026

EF Harness

Take a feature from raw intent to a code-verified contract — with an AI agent that has to prove what it built.

Release License: MIT Claude Code plugin omp plugin Repo-agnostic


Why this exists

Coding agents are very good at producing code and very bad at knowing whether it was the right code. In practice a feature built with an agent fails in a handful of predictable ways:

What goes wrongWhy it happens
The agent builds a confident implementation of an undecided requirementNobody forced the decision; the agent filled the gap with something plausible
The spec is wrong about the code and nobody notices until reviewSpecs are written at product altitude, often before the code exists, by someone who could not see the repo
"All tests pass" — and the feature is still brokenThe tests were written by reading the implementation, so they assert what the code does, not what it should do
The agent says it's done, and verifies itselfThe author of a change has the same blind spots as the change
The second repository builds against the design, not what shippedNobody wrote down where the implementation diverged

EF is a set of commands and skills that turns those failure modes into gates. It does not make the agent smarter. It makes the agent's mistakes surface early, cheaply, and in writing.

What you get

  • 🔨 Decisions before code. Stage 1 is a relentless, one-question-at-a-time interview. Every decision is recorded with its evidence, the option that lost, the riskiest assumption, and the exact condition that would reopen it.
  • 🔍 Docs are claims, not truth. Before a line is written, every code anchor the docs mention is checked against the real repository — VERIFIED, MOVED, CHANGED or FICTION.
  • ♻️ Self-correcting decisions. A false anchor that matches a decision's Would reopen if condition reopens that decision by its own stated terms — no debate about whether it matters.
  • ✅ Named proofs. Every implementation check names the specific test whose exit code settles it. "The suite is green" is not a proof.
  • 🧑‍⚖️ One adversarial audit gate. A fresh reviewer, dispatched over the whole feature range, assumes the work is wrong until the code says otherwise. Builders never verify themselves.
  • 📜 Living documents. The RFC and PRD are amended in place by Stages 3, 4 and 5, so the next repository reads what actually shipped.
  • 🧩 Any stack. No language, test runner or directory layout is assumed. Your repository declares its own gates once; the harness never invents a command.
  • 🔌 Two tools, one tree. The same files are a Claude Code plugin and an omp plugin.
  • ⚖️ Priced shortcuts. Small features skip steps — and each shortcut names exactly which class of failure it stops catching.

Quick start

Claude Code

/plugin marketplace add micaelcf/ef-harness
/plugin install ef@ef-harness

omp

omp plugin marketplace add micaelcf/ef-harness
omp plugin install ef@ef-harness                  # every project
omp plugin install --scope project ef@ef-harness  # or just this one

Your first feature

/ef:grilling  "Users can export their audit log as CSV"

Answer the questions. When the decisions are closed, the grill tells you the next command — and so does every stage after it.


How it works

flowchart LR
    idea(["💡 Feature idea"]) --> S1

    subgraph product ["Once per feature"]
        S1["<b>1 · Grill</b><br/>/ef:grilling<br/><i>grill-decisions.md</i>"]
        P["Prototype<br/>/ef:prototype<br/><i>optional</i>"]
        S2["<b>2 · Feature docs</b><br/>/ef:feature-docs<br/><i>RFC · PRD · INDEX</i>"]
        S1 -. "new UI with no<br/>known pattern" .-> P -.-> S1
        S1 --> S2
    end

    subgraph repo ["Once per target repository"]
        D["Spec drift<br/>/ef:spec-drift<br/><i>cheap pre-check</i>"]
        S3["<b>3 · Discovery</b><br/>/ef:perspective-discovery<br/><i>the contract</i>"]
        S4["<b>4 · Implement</b><br/>/ef:implement<br/><i>.ef/&lt;feature&gt;/checks.md</i>"]
        S5["<b>5 · Audit</b><br/>/ef:audit<br/><i>handoff doc</i>"]
        D -.-> S3 --> S4 --> S5
    end

    S2 --> D
    S3 -. amend .-> S2
    S4 -. amend .-> S2
    S5 -. amend .-> S2
    S5 --> ship(["🚀 Shipped + contract<br/>for the next repo"])
StageCommandRunsProducesWhy it is a separate stage
1/ef:grillingonce per featuregrill-decisions-<date>-<feature>.mdAn undecided requirement is the most expensive bug there is, and it is invisible in code review
2/ef:feature-docsonce per featureRFC · PRD · INDEXWritten from the decisions, never beside them, so the documents cannot drift from what was agreed
3/ef:perspective-discoveryper target repothe contractThe docs were written without seeing this repo; this is where they meet it
4/ef:implementper target repo.ef/<feature>/checks.mdChecks and proofs are fixed before code, so they are a bar to build under, not a rationalisation
5/ef:auditper target repothe handoff docThe only gate. A fresh agent, the whole feature, every requirement

Stage 1 — Grill: close the decisions

The grill asks one question at a time — batching produces worse answers, because the human optimises for getting through the list. Every question is grounded in something it read, carries an evidence grade, offers 2–4 real options with their costs, and makes a recommendation.

It also guards its own reasoning — sycophancy, anchoring, sunk cost, confirmation bias — because the failure mode of an agent interview is not disagreement, it is agreement.

Every closed decision takes the same shape, and every field is consumed downstream:

Decision · Why (ranked) · Evidence grade · Dissent · Riskiest assumption · Test · Would reopen if · Supersedes
  • Dissent becomes the RFC's rejected-options row — invented later, it would be a fake comparison written by someone who already knows the answer.
  • Riskiest assumption + Test + Would reopen if become the RFC's assumptions table.
  • Would reopen if is what makes Stage 3 self-correcting:

A question nobody in the room can answer yet is recorded as still open, with what it is blocked on. A coerced decision gets written into an RFC, built into a contract, and discovered to be hollow three stages later; an honest open question costs one line.

Stage 2 — Feature docs: transcribe, don't re-decide

grill-decisions  →  RFC  →  PRD  →  INDEX

Each document is written from the one before it. Nothing mandatory is ever filled with invented content — missing values are asked for, and anything unresolved goes to ## Open questions with an owner. A placeholder that looks like content is the one failure this stage must not produce.

Stage 3 — Discovery: the docs meet the code

flowchart TD
    A["Step 1 · Anchor check<br/><i>always runs</i>"] --> B{"Can you name the files<br/>this feature changes?"}
    B -- yes --> T
    B -- no --> F["Step 2 · Scout fan-out<br/>parallel read-only agents,<br/>one area and one lens each"]
    F --> T["Step 3 · Triage<br/>resolved · self-answerable from code · a genuine decision"]
    T --> G["Step 4 · Grill<br/>repo altitude, weakest evidence first"]
    G --> C["Step 5 · Write the contract<br/>interfaces · data shapes · boundaries · naming"]
    A -. "FICTION / CHANGED<br/>on a load-bearing claim" .-> R["Reopen the decision<br/>+ amend the RFC"]

Scouts get different critical lenses — assumption-surfacing, pre-mortem, red-team, evidence-audit, second-order — because parallel readers using the same method produce correlated reports, and the fan-out buys nothing.

The contract is written by the agent that holds the whole feature, into a file. Parallel slices cannot read a conversation, and anything left for them to negotiate will diverge.

Stage 4 — Implement: proofs first, then build

flowchart LR
    X["Extract<br/>checks + named proofs<br/>+ the sweep"] --> Bld
    subgraph Bld ["Build — parallel slices, one owner per file set"]
        direction TB
        s1["slice A"] ~~~ s2["slice B"] ~~~ s3["slice C"]
    end
    Bld --> Gt["Gates from your repo<br/>run once, by the owner"] --> V["Stage 5"]
  • Refuse rather than guess. Every check needs a nameable proof, a concrete value, and a stated boundary. A vague check becomes a vague assertion that passes.
  • The sweep walks thirteen requirements nobody writes down — authorization, idempotency, concurrency, the error contract, data lifecycle, schema provenance and more — and forces an answer for each. "Already covered by X" is an answer. Silence is not.
  • Tests assert the check, never the implementation. No weakening assertions, no skipping, no deleting to go green.

Stage 5 — Audit: the single gate

sequenceDiagram
    participant O as Feature owner
    participant R as Fresh reviewer
    participant C as Code
    O->>O: run the repo's gates
    O->>R: audit base..HEAD, every requirement, gates already green
    R->>C: walk each requirement id, hunt defect classes
    R-->>O: findings with path:line + evidence grade
    O->>O: triage, then remediate as a separate step
    O->>R: verify — assume one fix is incomplete and one regressed
    R-->>O: clean
    O->>O: contract mode → handoff doc, amend the RFC

The auditor hunts the defects that survive a green suite: tests that would still pass if the behaviour reverted, destructive defaults on omitted fields, nil-versus-empty, signals that mean two things. A finding graded C or D is reported as a question, never a blocker.

The handoff document is written from the code, not from the design, and lists its divergences from the spec first — it is the only section a consumer cannot afford to skim.


Scale: pay only for what you need

flowchart TD
    Q{"More than one repo?<br/>A one-way door?<br/>Auth, money or deletion?<br/>Can't name the files?"}
    Q -- "any yes" --> M{"More than one repo?"}
    Q -- "all no" --> S["<b>single</b><br/>grill → checks → build → audit"]
    M -- yes --> MU["<b>multi</b><br/>all five stages per repo,<br/>handoff docs, per-repo status"]
    M -- no --> ST["<b>standard</b><br/>all five stages, one repo"]
ScaleWhat you skipWhat it can no longer catch
singleRFC + PRD collapse into one DECISIONS_<feature>.md; no fan-outa convention of this repo you do not know about; anything a second reader would have seen
standardcross-repo apparatuscross-repo contract drift — there is no second repo to drift from
multinothingnothing structural; this is the complete pipeline

Stage 1 declares the scale once and every stage inherits it; a repo may raise it for itself, never lower it. The audit never collapses — it runs at every scale.

Two optional steps are decided by the same question — can you name the thing you are copying?

Optional stepRuns when
/ef:prototypethe feature introduces a screen that is not a variation of an existing one or a well-known pattern. Produces 4–5 genuinely different variants in one HTML file, one of them the boring baseline. Forms, tables, modals and wizards are built, not prototyped
Scout fan-out (Stage 3)you cannot name the files the feature changes

Bindings — the only place your stack appears

Nothing in the harness hardcodes a command, an identifier rule or a convention. Each repository declares its own, once, in CLAUDE.md / AGENTS.md:

## ef-harness

gates:         <commands that must pass before Stage 5, in order>
generated:     <command that regenerates code; state that the tree must be clean after>
identifier:    <which identifier may cross the API boundary, and everywhere the rule applies>
authorization: <the policy mechanism every new surface must pass>
tests:         <runner; how ONE test is named and invoked; known incompatibilities>
migrations:    <how a schema migration must be created>
audit:         <where side-effect/audit entries are catalogued, if the repo has one>
commits:       <commit message convention>

Where the block is absent, Stage 4 derives the gates from your task runner and CI workflows, proposes them, and offers to write the block. It never invents a command: a proof that cannot run is worse than no proof.


Artifacts

ArtifactWritten byLives in
knowledge/ topic notesStage 1 groundingfeature docs folder
grill-decisions-<date>-<feature>.mdStage 1feature docs folder
prototypes/<screen>.html/ef:prototypefeature docs folder
RFC_*.md, PRD_*.md, INDEX.mdStage 2feature docs folder
DECISIONS_<feature>.md (single scale)Stage 2feature docs folder
amendments to the RFC/PRDStages 3, 4, 5in place, next to what they change
the contractStage 3.ef/<feature>/checks.md, in the repo that builds it
checks, slices, ownership, Landing, CoverageStage 4.ef/<feature>/checks.md
handoff doc (API_HANDOFF*, FRONTEND_HANDOFF*, API_CHANGE_REQUEST_*)Stage 5feature docs folder

Product documents are cross-repo and live with the feature. Build artifacts are per repo and live in the repo. Nothing is written twice. grill-decisions outranks the RFC and PRD wherever they disagree, and the RFC header is the only home for cross-repo delivery status.


Installing in depth

Claude Code

/plugin marketplace add micaelcf/ef-harness
/plugin install ef@ef-harness

To give a whole team the same harness, commit this to the repository's .claude/settings.json; Claude Code offers the install to everyone who opens the project:

{
  "extraKnownMarketplaces": {
    "ef-harness": { "source": { "source": "github", "repo": "micaelcf/ef-harness" } }
  },
  "enabledPlugins": { "ef@ef-harness": true }
}

omp

omp plugin marketplace add micaelcf/ef-harness
omp plugin install --scope project ef@ef-harness     # or omit --scope for every project

omp reads .omp-plugin/, and falls back to .claude-plugin/. The install is persisted in <repo>/.omp/plugins/ (project scope) or ~/.omp/plugins/ (user scope). The project registry holds absolute cache paths, so each developer runs the install once rather than committing it.

If you previously hand-copied EF files into ~/.omp/agent/commands/ or ~/.omp/agent/managed-skills/, remove them so each skill exists once — same-named skills from different sources resolve by provider priority, not by recency.

Names and updates

Commands run as /ef:grilling, /ef:implement, … and skills appear as ef:ef-grilling, etc. Update with /plugin update (Claude Code) or omp plugin upgrade ef@ef-harness.

Manual copy (offline / air-gapped)

<repo>/.claude/commands/ef/*.md      ← commands/*.md
<repo>/.claude/skills/ef-*/**         ← skills/ef-*/

Copy into each target repo — both tools read .claude/ from the current working directory. In Claude Code the ef/ folder only labels the commands, so they run as /grilling, /implement, …; omp registers both /grilling and /ef:grilling.


Repository layout

.claude-plugin/{plugin,marketplace}.json   Claude Code manifest + marketplace catalog
.omp-plugin/{plugin,marketplace}.json      omp manifest + catalog — identical to the Claude pair

commands/                        thin shims; the plugin is named `ef`, so each runs as /ef:<name>
├── grilling.md                  Stage 1 — holds the canonical stage map
├── feature-docs.md              Stage 2
├── spec-drift.md                Stage 3 pre-check — anchor verification only
├── perspective-discovery.md     Stage 3
├── implement.md                 Stage 4
├── audit.md                     Stage 5
└── prototype.md                 optional

skills/                          the method — model-invoked, so it works without the command
├── ef-shared/                   evidence grades A–D + the five lenses; not user-invocable
├── ef-grilling/                 + references/{decision-record,deadlock}.md
├── ef-feature-docs/             + references/{rfc,prd,index}-template, amendments, anti-patterns
├── ef-prototype/
├── ef-perspective-discovery/
├── ef-implement/                + references/{checklist-format,sweep,orchestration}.md
└── ef-adversarial-audit/        + references/{defect-classes,contract-doc}.md

assets/                          README animations + social preview
.github/workflows/release.yml    version checks on every push; publishes the release on a tag
CHANGELOG.md                     every release, newest first

Commands are shims; skills hold the method. A teammate who says "implement this feature per the contract" gets the method without knowing a command exists. References load only at the step that needs them, never up front.


Design choices, and what we left out on purpose

  • No verification gate other than Stage 5. Convention inspectors and spec-completeness agents are not wired in; their value moved upstream into Stage 4's sweep, where acting on a finding is cheap.
  • No jury. Parallel readers are used where they decorrelate — scouts, deadlocked design questions — but the human stays the product decider.
  • No fault injection. Stage 5 asks whether a guard would fail if the behaviour reverted; it does not mutate code to prove it.
  • No enforcement of the amendment protocol. Stages 4 and 5 are instructed to amend the docs; nothing fails if they do not. The audit stays about code.
  • Markdown only. No hooks, no MCP servers, no executables. Everything the agent does runs under your tool's own permission model.

Contributing

Issues and pull requests are welcome — especially reports of a stage that let a real defect through, or a stack where the bindings block could not express a gate.

A few conventions keep the harness portable:

  1. Stay repo-agnostic. No command, framework or path specific to one stack in a skill. If it is concrete, it belongs in a repository's bindings block.
  2. Reference files so both tools resolve them. Inside a skill, write paths relative to that skill (references/deadlock.md). Across skills, name the skill (the ef-shared skill's references/lenses.md). In commands, say load the ef-grilling skill. Never write .claude/skills/… or ${CLAUDE_PLUGIN_ROOT}/… — the first does not exist after a plugin install, and omp does not substitute the second in skill text.
  3. One definition, one place. Shared vocabulary lives in ef-shared, not restated per stage.
  4. Validate before you push: claude plugin validate . --strict.

Versioning

EF follows Semantic Versioning 2.0.0. Every release is an immutable vX.Y.Z tag with a GitHub release, and every change is listed in CHANGELOG.md. Both Claude Code and omp keep installs on the manifest version, so users get nothing new until it changes.

What counts as the public API

A harness has no functions to call, so the contract is the set of names and shapes that users, their repositories and their saved artifacts depend on:

  1. The install identity: plugin ef, marketplace ef-harness.
  2. Command names (/ef:<name>) and skill names (ef-*).
  3. The bindings block keys and what each one means.
  4. Artifact names, locations and required sections: grill-decisions-*, RFC_*, PRD_*, INDEX.md, DECISIONS_*, .ef/<feature>/checks.md, and the handoff docs.
  5. Shared vocabulary: decision-record fields, scale values, anchor statuses, evidence grades A–D.
BumpWhenExamples
MAJORSomething in the public API is removed, renamed or changes meaning, so an existing install, bindings block or artifact stops working as beforerename /ef:audit; drop a decision-record field; move checks.md; remove a stage or gate
MINORSomething is added and everything that exists keeps workinga new command or skill; an optional bindings key; a new sweep item; a new defect class
PATCHThe behaviour gets clearer or more correct and no name or shape changeswording, clarified instructions, fixed references, docs

While the version is 0.y.z, a MINOR release may break things (SemVer §4). Every such change is marked BREAKING in the changelog, along with how to migrate. 1.0.0 will be released when the public API above is considered stable.

Releasing

  1. As you work, record changes under ## [Unreleased] in CHANGELOG.md.
  2. Rename that heading to ## [X.Y.Z] - YYYY-MM-DD, add an empty ## [Unreleased] above it, and update the compare links at the bottom.
  3. Set version in .claude-plugin/plugin.json and copy both manifests over their .omp-plugin/ twins.
  4. claude plugin validate . --strict
  5. Commit (:bookmark: chore(release): vX.Y.Z) and push main.
  6. git tag -a vX.Y.Z -m "vX.Y.Z" && git push origin vX.Y.Z

The release workflow runs on every push and pull request. It fails if the manifest pairs differ, if the version is not valid SemVer, or if the changelog has no entry for it. On a tag it also requires the tag to equal v + the manifest version, then publishes the GitHub release using that changelog section as the notes.

Published tags are never moved or deleted; a bad release is fixed with a new PATCH release. The repository backs this policy with a ruleset against updating or deleting v* tags, and with GitHub immutable releases for every release after v0.1.0.


License

MIT © Micael Fernandes. Security reports: see SECURITY.md.

↑↓ navigate openesc close