Getting started
First green suite in minutes.
The loop is spec → generate → implement → run, with
feat verify locked around it. This page walks it once,
end to end.
1 · Install and init
$ npm i -D @mmmnt/feature
$ npx feat init
✓ feat.config.json written · adapters: handler, fs
feat.config.json names your services and binds each to an
adapter. Service keys are yours — the spec references them, and an unknown key is a
validation error.
{
"response": { "adapter": "@mmmnt/feat-adapter-handler" },
"services": {
"database": { "adapter": "@mmmnt/feat-adapter-fs", "consistency": "acid" }
}
}
2 · Write a spec
A minimal .feat file needs a header, one construct
directive, one enforce directive, one contract reference, and one scenario with a
prediction. No escape hatches. See the
language guide for the
full grammar.
3 · Generate, fail, implement, pass
$ npx feat generate
✓ 1 suite derived · inputs sha256 in the header · commit it
$ npx feat run
✕ 2 failed — hand the construct block to your agent, implement, re-run
$ npx feat run
✓ 2 passed · standard Vitest — coverage and reporters work unchanged
Generated suites are committed and versioned like any other code. They are never
hand-edited — the header says so, and feat verify
enforces it.
4 · Lock it in CI
# ci.yml — the whole integration
- run: npx feat verify # drift is a build failure
- run: npx feat run --reporter junit
The CLI surface
feat parse Parse and validate specs; errors carry hints and spec coordinates.
feat generate Derive complete Vitest suites. Deterministic — same spec, same bytes.
feat verify Re-derive and byte-compare committed suites. The CI drift gate.
feat run Execute suites via Vitest; JUnit report with --reporter junit.
feat audit Cross-check specs, suites, and config for closure.
feat lint Semantic checks — unused declarations, two-way rejection lint.
feat fmt Conservative canonical formatting; --check for CI.
feat watch Regenerate on spec change during authoring.
feat diff IR-level spec diff against a git ref — what changed, semantically.
Language guide
Two zones. One file.
A .feat file is indentation-sensitive, comments start
with #, and every block belongs to one of two zones. The
in-repo docs/grammar-reference.md and the nine-exemplar
corpus are the source of truth; this page is the map.
Agent zone — freeform
construct: and enforce:.
Natural-language directives for the implementing agent. The parser captures them; the
compiler skips them. Any unmatched line is a valid freeform directive.
Compiler zone — strict
contract:, scenario,
predict. Typed grammar; malformation is a parse error
with a hint, never a silent failure.
The header and the agent contract
spec, context,
aggregate, and type
(command, query, policy, projection, saga, infrastructure, integration, scaffold). Three
header lines carry the agent contract:
Agent-zone keywords
Inside construct: —
handler at, imports … from,
register … in, emit to.
Inside enforce: — behavioral directives, plus one
structured form with a compiler-side shadow:
rejects DUPLICATE_EMAIL when a user with that email already exists
Two-way lint: every predict rejection ID must have a
matching rejects, and vice versa. When a spec is
ambiguous, the agent contract says: halt and ask — never guess.
Compiler-zone grammar
contract: Declares the closed schema space — input, event, error, response, record, stream. Every schema a scenario references must be declared here; from is optional.
scenario "name": Unique names, required — failure reports anchor to spec › "scenario" › surface[i] coordinates, not stack traces.
given: / when: Precondition (freeform) and stimulus. Actors: when (as admin): with reserved anonymous. Pin time with clock at "2026-07-01T00:00:00Z". Event-triggered specs use deliver <Event> {} to <service>.
predict Three types, fixed grammar: success, rejection <ID> (asserts zero side effects everywhere), error <CODE>. Surfaces: response <status> <Schema>, <service> has […], <service> contains […], equals fixture "path" for golden comparisons.
scenario outline Parameterized scenarios with an examples: table. Placeholders are valid in payloads, value blocks, rejection-ID and matching-argument positions.
The four closed spaces
Schemas, service keys, commands, actors. A reference outside its declared space dies at
parse time, with a hint — type safety in the spec. And the query guarantee: a spec of
type query grammatically cannot express a write.
Token classes — KEYWORD, IDENT, LITERAL, FREEFORM — are normative; the editor grammar at
editor/feat.tmLanguage.json realizes them. Try the
playground to see parse errors live.
Architecture
A pipeline you can replay.
Every stage is deterministic. The parser is hand-rolled recursive descent; the IR is a
language-neutral JSON Schema; emission carries no timestamps — only an inputs
sha256. That is what makes
feat verify a byte compare instead of a judgment call.
02
build
AST → BuiltSpec IR
The lock
feat verify
byte compare · CI
Packages
@mmmnt/feature The CLI. Owns the feat bin.
@mmmnt/feat-types · feat-core Shared types, parser, IR, validation.
@mmmnt/feat-derive · feat-emit-ts Test derivation and TypeScript emission.
@mmmnt/feat-runtime · feat-runner The harness generated suites import; capture, matching, reports.
@mmmnt/feat-adapter-handler · -fs · -http First-party adapters. Community adapters are plain npm packages.
Adapters and the capture window
An adapter is one exported function — createAdapter(config)
— loaded by config-driven dynamic import. No plugin registry. Each service declares a
consistency model (acid, strong,
eventual) that determines capture timing; each test shares a
single absence-proof window, and adapter instances are per-file for parallel runs.
Generated tests are location-independent: config resolves relative to the file, payload
paths from the project root.
The record
Fourteen ADRs govern the design (ADR-0001…0014); the nine-exemplar corpus with IR goldens
is the conformance suite; three JSON Schemas define the contract surface
(builtspec, .contract.json,
feat.config.json). The evidence chain — spec → suite → config
→ CI run → JUnit — is a development byproduct fit for regulated environments.