One engineer wearing every hat, with a producer keeping them coherent. firm is the engineering operating system that handles the work around the code: the roles, skills, workflows, gates, and contracts that turn an idea into shipped, defensible software. It exists to stop three recurring failures: repeating work already done, repeating mistakes already made, and forgetting steps under pressure.
A Claude Code plugin that turns a feature idea into shipped, defensible software — without skipping any discipline. Twenty skills and six agents, each owning one seam of the engineering process, orchestrated by a producer that keeps them coherent.
scripts/firm-plugins.sh sync --rails # 1. install (or update) firm's core + Rails tiers — restart Claude Code to apply- Onboard the repo — run the
firm-onboardskill (in the Rails tier); it writes.firm/profile.ymlso every portable reviewer is grounded on your codebase. - Drive a feature —
/grill-with-docs(shape it) →/break-down(decompose into a GitHub Epic) →/epic-autopilot(ship it, one PR per issue).
New to firm? Read on. In a hurry? The three lines above are the whole path.
A fresh machine installs firm from this repo, onboards a real Rails app, and the gate catches
five planted convention violations — then a reasoned waiver, the config-driven PR-reference
check, and the pluggable external-tools seam, ending with an empty git status (leaves no
trace). Distilled from a real recorded acceptance run (11/11 claims passed):
And act 2 — the judgement layer. Same repo, but Claude Code drives: the convention-reviewer agent (seam A6) reads the Profile, grades its findings beyond what the deterministic cops catch — including a failing test masquerading as coverage, an honest false-positive call on a stock Rails route, and a blind spot in firm's own gate, escalated as a firm issue:
And act 3 — the full arc. A product-owner request ("a coffee shop selling one subscription") driven end to end in a single session: the grill shapes six decisions, the break-down sequences five sub-issues with a safe stop, the build lands red→green on real modular engines (generated by seams — which surfaced a real gem bug, fixed and filed upstream on camera), firm's gate then reviews the session's own code, and the proof is a live server creating an active subscription with no payment keys at all:
Adopting firm from scratch? Start with the self-serve guide — five short documents that take a newcomer from install to a first shipped feature: install · concepts & the seam model · configure your ecosystem · extend firm · the disciplines & why.
A feature moves through five stations. Not every station fires on every feature — the right ones fire based on what the feature touches. The producer routes cross-seam work.
STATION 1 — Shape the work (before a line of code is written)
strategy (B9) At cycle start or on a direction shift. Write/refresh STRATEGY.md:
product goals, success metrics, tracks and personas in scope.
The upstream anchor brainstorm and plan read.
story-writer (B6) Always. Turn the idea into a well-formed GitHub issue:
one goal, Given/When/Then criteria, non-goals, test expectation.
architecture-advisor (B7) If the feature crosses an architectural boundary or needs
a design decision. Options analysis + draft ADR.
decompose-change (B1) If the scope contains multiple concerns. Split first.
producer (B4) If the feature touches two or more seams. Sequence the
hand-offs and name the build order.
STATION 2 — Review the design (before code)
skeptic (B3) Any design doc, plan, or ADR. Independent adversarial review:
surfaces assumptions, blind spots, and known-unknowns.
STATION 3 — Build (during implementation, on the diff)
decisions-from-diff (B2) Every PR. Reads the diff and drafts ADRs for decisions
worth a reviewer's attention.
perf-reviewer (A3) If queries, serializers, or migrations are touched.
security-reviewer (A4) If auth, PII, or gem dependencies are touched.
integration-resilience (C1) If a new outbound HTTP call or third-party client is added.
boundary-reviewer (C2) If the diff crosses an engine boundary.
accessibility-review If the UI changes.
observability-check (A5) If a new operation is added. Is it observable?
test-strategist (A1) Confirm the test coverage strategy is right for the change.
mutation-testing Kill alive mutations in the touched paths.
STATION 4 — Ship
communicator (B5) Write the PR description in house format and the operator's voice.
release-gatekeeper (B8) Three-gate pre-deploy: developer DoD, QA quality gate,
operational readiness (SHIP / CONDITIONAL / HOLD).
STATION 5 — After
compound At cycle end. "What did this teach, and where does each lesson belong?"
Routes by scope: reusable patterns to docs/solutions/, conventions to
AGENTS.md/CLAUDE.md, terms to CONTEXT.md, the rest by hand-off. Silence
("nothing worth compounding") is a valid output.
retrospective If something went wrong, harvest the lesson into a gate or memory.
firm-gap-check At session end, check if firm has a gap worth recording.
Quick rule: if you're not sure which station applies, ask the producer. It reads
SEAMS.md, finds the seam(s) the task crosses, and sequences the hand-offs.
Slash commands you invoke directly (from engineering-core, available in every repo). Type /<name>; in a headless or background session use the fully-qualified /engineering-core:<name>.
| Command | What it does |
|---|---|
/grill-me |
Interviews you relentlessly about a plan or decision until it is sound, recommending an answer to every question. |
/grill-with-docs |
The same grilling, but writes the proposal as it crystallises — maintains CONTEXT.md, records decisions inline, mirrors to the docs vault. For work that deserves a permanent record. |
/break-down |
Turns an accepted proposal into a GitHub Epic + structurally-linked sub-issues (the real Sub-issues API), after grilling delivery: phases, dependencies, effort, safe stopping points. |
/epic-autopilot |
Drives an Epic to completion, one sub-issue per fresh self-chaining session: works the next unblocked issue test-first, opens a documented PR, merges only when green, then launches the next session. --once = one hop; --no-merge = stop before merge. Never merges red; halts and escalates on a genuine block. |
/note-break-point |
Quickly logs a break-point (a place your process slipped) to the ledger, to become a hook later. |
/firm-self-improve |
On-demand, scans the session for what you did by hand and, where a reusable tool would remove that toil, builds it to firm's bar (a Why + a self-test) — plan-first and human-gated, routing each tool to firm / your repo / the backlog. Silent when there is nothing worth automating. |
The delivery arc: /grill-with-docs (shape it) → /break-down (decompose it) → /epic-autopilot (ship it).
firm is a set of Claude Code plugins, published through its own marketplace. A Rails repo needs two tiers; onboard the repo once they are enabled.
-
Add the marketplace (once per machine):
/plugin marketplace add davidslv/firm-os -
Install the tiers you need:
/plugin install engineering-core@firm # universal disciplines — everywhere /plugin install engineering-rails@firm # Rails tier: firm-onboard + reviewers + flag detection + ux-auditengineering-railsdepends onengineering-core. -
Onboard the target repo — run the
firm-onboardskill in the repo. It detects the stack, writes.firm/profile.yml, builds the catalogue, and grounds every portable reviewer against this repo. Nothing else works until the Profile exists, so this is the first step in any new repo.
One command (shell) — fresh machine or one that already has firm:
scripts/firm-plugins.sh sync # add marketplace + install if missing + update if present
scripts/firm-plugins.sh sync --rails # also handle the engineering-rails tierfirm plugins are versioned, so a machine only sees changes after an update, and a plugin update applies on the next Claude Code session (the CLI prints "restart to apply"). Either run the script, or update by hand:
scripts/firm-plugins.sh update# interactively, inside a session:
/plugin marketplace update firm
/plugin update engineering-core@firm # and engineering-rails@firm if installed
scripts/firm-plugins.sh sync is the safe default: it installs if missing and updates if present, whichever the machine needs. (The full curated toolset and the declarative settings.json live in SETUP.md.)
Skills (procedures invoked in the current context):
| Skill | Seam | What it does | Eval |
|---|---|---|---|
| strategy | B9 Strategic anchoring | Creates/updates STRATEGY.md: product goals, success metrics, tracks and personas in scope. The loop's upstream anchor for brainstorm and plan | gate ◇ |
| story-writer | B6 Requirements quality | Well-formed GitHub issue: one goal, testable ACs, non-goals, escalation policy | 3/3 ‡ |
| architecture-advisor | B7 Architecture guidance | Options analysis + draft ADR before code is written. Companion to decisions-from-diff (reactive) and skeptic (adversarial) | 3/3 ‡ |
| release-gatekeeper | B8 Release readiness | Three-gate pre-deploy: DoD, QA quality gate, operational readiness. SHIP / CONDITIONAL / HOLD | 2/3 ‡ |
| decisions-from-diff | B2 Decision capture | Reads a diff, surfaces architectural decisions, drafts MADR ADRs | 3/3 ‡ |
| decompose-change | B1 Decomposition | Splits a large or mixed-concern change into stacked, revertable PRs | 2/3 ‡ |
| test-strategist | A1 Testing | Picks the right test level and finds adversarial edges the happy path misses | 3/3 ‡ |
| observability-check | A5 Observability | "Is this change observable?" — detect signal, diagnose context, acceptance criteria | 3/3 ‡ |
| communicator | B5 Communication | PR descriptions, commit messages, Slack updates in the operator's voice and house format | 3/4 ‡ |
| producer | B4 Delivery planning | Orchestrates multi-seam work: routes hand-offs, holds build order, runs integration gate | 3/4 ‡ |
| ticket-sync | B10 Ticket currency | Mid-work: keeps the ticket the source of truth at three triggers — progress snapshots, open decisions (never pre-assigned), and decisions that supersede stale criteria. Silence is a valid output | eval added; not yet 3-vote scored |
| firm-gap-check | meta | Post-session: surfaces a gap firm should fill (missing skill, check, or automation) | 1/3 ‡ |
| retrospective | meta | After a bug or incident: routes the lesson to a gate/hook or personal memory | 2/3 ‡ |
| compound | compounding | Cycle-end router: routes each learning to its home by scope (docs/solutions/, AGENTS.md, CONTEXT.md, or a hand-off). Silence is a valid output | gate ◇ + regression-guard ¶ |
| blast-radius | blast-radius | Change-time forcing function: scores a change's blast radius, decides with the human whether a feature toggle is warranted, and governs the flag's whole life via the .firm/flags.yml ledger (mandatory expiry) until removal | gate ◇ |
Agents (independent workers in a fresh context):
| Agent | Seam | What it does | Eval |
|---|---|---|---|
| skeptic | B3 Epistemic honesty | Adversarial design reviewer: surfaces assumptions, blind spots, known-unknowns, BLOCK/CAUTION/PROCEED | 1/3 ‡ |
The portable Rails and Ruby-gem reviewers. Each reads a per-repo Profile
(.firm/profile.yml, see plugins/engineering-rails/docs/profile-schema.md) for the
stack, engines, asset layout, test command, and integrations, so the same reviewer is
correct on any repo instead of one hard-coded codebase. The seams move here from the core
and domain tiers; the seam-ownership gate keeps exactly one owner each.
Skills:
| Skill | Seam | What it does | Eval |
|---|---|---|---|
| integration-resilience | C1 Integration resilience | Checklist for any new outbound HTTP call: timeout, retry, idempotency, DLQ, observability. Reads the Profile's integrations |
2/3 ‡ (re-verified 2026-06-22; case 1 delta +) |
| mutation-testing | C-A1 Mutation testing | Decides what an alive Ruby mutation means: add test, simplify, or accept as unkillable. Grounded on the Profile's test_framework |
3/4 ‡ |
| accessibility-review | ux-audit | Audits Rails/Hotwire/Tailwind UI against WCAG 2.2 AA. Reports file:line, SC, impact, fix | 3/3 ‡ |
| ux-audit | runtime-ux | Runtime, browser-driven UX audit when a runnable URL exists: delegates to an external UX-audit tool (a11y/perf/journeys/copy/visual), surfaces verdict.json in firm's five house buckets graded verified, degrades to the static accessibility-review when tool/URL absent | 2/2 ‡ (case 1 delta+, first real lift) + gate ◇ |
| firm-onboard | onboarding | The entry-point that makes firm productive on a fresh repo: a deterministic detector writes the per-repo Profile (stack, versions, engines, asset pipeline, test command, integrations), then a grill fills intent (criticality, ownership, constraints) into a per-engine catalogue and augments AGENTS.md/CLAUDE.md non-destructively. Has an optional external-tool signal seam for churn/hotspot evidence | gate ◇ |
Agents:
| Agent | Seam | What it does | Eval |
|---|---|---|---|
| migration-safety-reviewer | A2 Data safety | Reviews DB migrations: lock risk, concurrent index, reversibility, backfill safety against live data | 3/3 ‡ |
| perf-reviewer | A3 Performance | N+1 reads, missing FK indexes, query-cost regressions. Runs FK scanner pre-check | 2/3 ‡ |
| security-reviewer | A4 Security | Dependency PRs (safe to merge?) + diff review: secrets, tenant scoping, auth, injection | 3/4 ‡ (re-verified 2026-06-22 post-relocation; cases 2,3 delta +) |
| boundary-reviewer | C2 Engine boundary | Cross-engine model/scope/service reach + asset-manifest footgun. Runs cross-association scanner; reads engines and asset layout from the Profile | 3/4 ‡ (2026-06-22; case 1 over-flags engine↔host assoc, delta −) |
| convention-reviewer | A6 Convention conformance | Judges the Rails-way residue no cop catches: resource-vs-verb, logic placement, association modelling, tautology / wrong-seam tests. Reads the Profile; emits a deviation dossier | eval added (#404 pattern); not yet 3-vote scored |
‡ Verified (3-vote), 2026-06-20 — full roster. All nineteen skills and agents were re-scored
with EVAL_JUDGE_VOTES=3 … --save-outputs and committed under evals/outputs/ (eight dated run
dirs, …T014006 through …T124931). What the runs showed:
- Single-judge lows were mostly understated. communicator 1/3→3/4, security-reviewer 2/3→4/4, retrospective 0/3→2/3, engine-boundary-reviewer 2/4→4/4 (its "regression" was judge noise), decompose-change 1/3→2/3, decisions-from-diff 2/3→3/3, migration-safety-reviewer 2/3→3/3.
- Some held, some fell — genuine, not noise. Clean 3/3s confirmed: story-writer, architecture-advisor, test-strategist, observability-check. Held weak: skeptic 1/3 (fabricates findings), release-gatekeeper 2/3 (no lift), integration-resilience 2/3 (over-flags a clean integration). Fell on pressure-testing: firm-gap-check ~2/3→1/3 (no silence / no autonomous write), perf-reviewer 3/3→2/3 (grades a deterministic FK-index catch "likely" not "verified"). The old "use 3 votes and skeptic/release-gatekeeper pass" note is retired.
Nine skill/eval follow-ups remain open: producer, communicator, mutation-testing, skeptic, release-gatekeeper, decompose-change, firm-gap-check, integration-resilience, perf-reviewer.
§ Re-scored 2026-06-22 (Phase 4, #31). The boundary-reviewer is the relocated, Profile-driven
form of the old engine-boundary-reviewer (which scored 4/4 ‡ under its domain-named, hard-coded
form). Its eval was re-grounded onto a neutral Profile fixture
(evals/fixtures/boundary-reviewer/profile.yml) and renamed to evals/boundary-reviewer.json;
the four cases and their assertions are unchanged in shape. The 3-vote re-score (resolver fixed so
the WITH arm actually loads the role) gives 3/4: cases 2, 3, 4 pass, and case 1 regresses (delta −)
because the reviewer over-flags a legitimate engine↔host association, the known pre-existing weak spot.
The engineering-rails tier is not only reviewers; it governs the Rails way with a self-contained toolchain that installs under a gitignored .firm/ and leaves no trace in the target repo (proposal 0008). firm install lays down the sidecar — its own bundle, config, an exceptions ledger, tool pins, and a native git pre-push hook — and firm update refreshes the pinned tool versions. The gate blocks a deviation locally, overridable only with a recorded reason: FIRM_OVERRIDE="rule@path: reason".
- Deterministic cops (in
.firm/hooks/checks.d/, each with a self-test, all ledger-aware):hatch-lock(escape hatches from Rails' own walls),rest-shape(non-resourceful routes),herb-view(ActiveRecord in ERB), and the TDD-quality pairtdd-private-probe/tdd-internal-mock. A test-presence check blocks a behaviour-bearing change with no matching test. - Orchestrated tools:
brakeman(static, from the sidecar) andbullet(runtime, injected into the host's own test run) — never into the host's committed bundle — plus any deterministic analysis tools a repo registers in.firm/tools.yml(optional, plural). The one deterministic RuboCop cop firm turns on isRails/UniqueValidationWithoutIndex. - The A6
convention-reviewerjudges the residue no cop catches (resource-vs-verb, logic placement, tautology / wrong-seam tests) and emits a deviation dossier. Its rubrics:plugins/engineering-rails/docs/rails-conventions-rubric.md(state modelling) andplugins/engineering-rails/docs/tdd-good-bad-rubric.md(test quality). - Generators (
.firm/generators/) scaffold convention-correct, test-first, unbranded Rails; a reusable capability made while working is harvested upstream intoengineering-rails, a host-tool gap becomes a suggested PR (e.g.firm-suggest-strong-migrations.sh), never a silent edit.
Default is local-only (binds your machine, no committed trace, proposal 0007); a shared mode that commits the gate for a whole team is an explicit, off-by-default opt-in. Full design in proposal 0008.
All 19 scores are verified (3-vote), 2026-06-20. Every fraction in the roster (the ‡ rows)
is a committed EVAL_JUDGE_VOTES=3 run saved under evals/outputs/ — a reproducible record, not
a single-judge estimate. See the ‡ note above for what each run found. scripts/check-roster.sh
guards eval presence; the numbers trace to the dated artifacts.
Each case is rated by whether the WITH arm passes and whether the skill helps vs. the baseline (delta +/0/−).
| Notation | Meaning (verified 3-vote) |
|---|---|
| n/m | of m cases, n passed under a 3-judge majority |
| delta + | the skill's WITH arm passed where the bare baseline failed — it helped |
| delta 0 | WITH and WITHOUT agreed — the skill matched the baseline on that case |
| delta − | regression — WITH failed where the baseline passed |
| gate ◇ | not a judge eval: proof is a deterministic gate (proposal D9). strategy is gate-checked by scripts/check-strategy.sh (present-and-complete STRATEGY.md), which ships a self-test over a valid and an invalid fixture |
| gate ◇ + regression-guard ¶ | compound is a forcing function, so per proposal D9 + D12 its proof is the procedural release-gatekeeper "did this cycle compound and decide correctly, including silence?" gate (#29), not eval lift. evals/compound.json (rich / barren / routing cases) is kept as a REGRESSION GUARD only: at 3 votes it scores 3/3 with every delta 0, meaning the WITH arm matches the bare baseline and never does worse. It is not evidence of lift; a one-shot WITH-vs-WITHOUT prompt cannot measure a skill whose value is that it runs every cycle. See D12 for the full finding (including a fixed regression and an eval-harness side-effect on real memory) |
To re-score any skill: EVAL_JUDGE_VOTES=3 bash scripts/run-evals.sh --save-outputs evals/<skill-name>.json
| Doc | What it contains |
|---|---|
docs/architecture.md |
How firm is put together and why: the tiers, the seam model, the .firm/ sidecar, the gate, and the pluggable external-tools + ecosystem seams |
docs/guide/ |
The self-serve guide: install, concepts, configure-your-ecosystem, extend-firm, the disciplines |
proposals/ |
Numbered design proposals; 0008 decides firm's Rails convention + TDD governance (the .firm/ gate), 0007 the leaves-no-trace overlay |
SETUP.md |
The full curated toolset + declarative settings.json; install and update paths |
docs/sdlc-role-profiles.md |
Evidence-grounded SDLC role profiles (8 roles, boundary table, RACI) |
plugins/engineering-core/SEAMS.md |
The 8 core seams (B1–B8, A1–A5) and house rules |
docs/skill-authoring.md |
How to author a skill/agent: the seam: key, dispatch tier, WHEN NOT clause, the CI gates |
Five checks run in CI (.github/workflows/) and the pre-commit hook, so firm holds its own
standards automatically rather than by reminder:
- Why-section gate (
scripts/check-why-sections.sh) — every authored file declares a Why. - Roster gate (
scripts/check-roster.sh) — README counts, roster membership, one-owner-per-seam (theseam:frontmatter key), and the ≤1024-char description limit all match what is on disk. - Self-test suite (
scripts/run-self-tests.sh) — runs every*.self-test.sh/test-*.shacross the plugins as one command (over a Ruby matrix in CI): the cops, the.firm/gate, the sidecar installer, the generators, the validators, and the plugin install/update script. A regression fails the build. - Eval suite (
scripts/run-evals.sh) — each judgment skill ships an eval proving it beats the baseline; scores are single-judge and indicative until a committed 3-vote--save-outputsrun (seeevals/README.md). - Strategy gate (
scripts/check-strategy.sh) — a deterministic check that a STRATEGY.md is present and carries its four required sections (proposal D9: a mechanical skill is gated, not judged). Ships a self-test over a valid and an invalid fixture (--self-test).
See docs/skill-authoring.md to add a new skill or agent to firm's standard.
firm/
├── plugins/
│ ├── engineering-core/ # 15 skills + 1 agents + hooks + commands
│ │ ├── SEAMS.md
│ │ ├── skills/ # strategy, story-writer, architecture-advisor, release-gatekeeper,
│ │ │ # decisions-from-diff, decompose-change, test-strategist,
│ │ │ # observability-check, communicator, producer,
│ │ │ # firm-gap-check, retrospective, compound, blast-radius, ticket-sync
│ │ ├── agents/ # skeptic
│ │ ├── commands/ # break-down, grill-me, grill-with-docs, note-break-point,
│ │ │ # epic-autopilot, firm-self-improve (+ its harvest/route/gen-cop toolkit)
│ │ ├── scripts/ # external-tool-evidence.sh (generic multi-provider adapter) + self-test
│ │ ├── docs/ # ecosystem-schema.md, tools-registry.md
│ │ ├── examples/ # ecosystem.example.yml, tools.example.yml
│ │ └── hooks/ # verify-gate.sh
│ └── engineering-rails/ # 5 skills + 5 agents (Profile-driven; install in any Ruby/Rails repo)
│ ├── SEAMS.rails.md
│ ├── docs/ # profile-schema.md, tdd-good-bad-rubric.md,
│ │ # rails-conventions-rubric.md, generators-and-harvest.md
│ ├── examples/ # profile.example.yml
│ ├── scripts/ # validate-profile.sh + validate-pins.sh (+ self-tests), firm-update.sh (+ test),
│ │ # runtime-ux-tool.sh (shared runtime UX-audit helper) + self-test + fixtures/runtime-ux/,
│ │ # ux-boot.sh (optional local boot for the runtime audit) + self-test
│ ├── skills/ # integration-resilience, mutation-testing, accessibility-review,
│ │ # ux-audit (runtime UX audit; delegate to an external UX-audit tool + surface + grade; gate-checked),
│ │ # firm-onboard (detector + Profile + grill/catalogue + knowledge merge; gate-checked)
│ │ # → the .firm/ gate (proposal 0008): firm-install/firm-gate/firm-suggest-strong-migrations,
│ │ # cops/ (hatch-lock, rest-shape, herb-view, tdd-private-probe, tdd-internal-mock),
│ │ # generators/ (firm-generate-model), config/rubocop.yml
│ └── agents/ # migration-safety-reviewer, perf-reviewer, security-reviewer,
│ # boundary-reviewer, convention-reviewer
├── evals/ # 24 eval files: one per judgment skill/agent, plus the firm-self-improve command
├── proposals/ # numbered design proposals (0001–0008)
├── scripts/
│ ├── firm-plugins.sh # atomic install/update of firm's own plugins (+ self-test)
│ ├── run-self-tests.sh # runs every *.self-test.sh / test-*.sh as one suite (CI matrix)
│ ├── run-evals.sh # the eval runner (--save-outputs writes a score artifact)
│ ├── check-why-sections.sh # the Why-section gate
│ ├── check-roster.sh # the roster / seam-ownership / description gate
│ └── check-strategy.sh # the STRATEGY.md gate (D9; --self-test over valid/invalid fixtures)
├── statusline/ # operator statusline
└── docs/ # design records, backlog, glossary, role profiles


