# Mimlet for coding agents

Mimlet gives coding agents concrete building blocks for test data: typed patches,
explicit validation, supported deterministic generation, coherent scenarios and
checked replay. These capabilities can reduce the need to invent fixture structures
and debugging workflows; no measured productivity or model-preference claim is implied.

**Release status:** published alpha, `@mimlet/*@0.1.0-alpha.2` and
`hey-api-builders@3.0.0-alpha.2`, available on npm's `next` channel. Follow
[Getting started](/mimlet/guide/getting-started.md) for matching install commands or source
development. Check the project's installed versions before applying an example.

## Pick the smallest useful combination

1. Read the project's existing schema and test framework; retain those choices.
2. Use `@mimlet/core` for typed factory builders. For native creation/codecs or automatic
   generation, select the appropriate [adapter](/mimlet/guide/adapters.md).
3. Decide whether the test needs encoded input or validated/decoded output.
4. Set explicit session identities and seeds where supported. Capture a snapshot
   before the operation to reproduce it, or after it to resume from that point.
5. Run the test and preserve its failure evidence. Inspect documented capabilities
   before substituting a factory or changing a schema.

An optional [Mimlet skill](https://github.com/JeffreyNijs/mimlet/blob/main/skills/mimlet/SKILL.md) packages this workflow. Install
it only when the user requests it; it does not change project dependencies or install
global tools automatically.

The alpha includes dedicated [Zod and ArkType recipes](/mimlet/guide/zod-and-arktype.md).
Use their typed factory helpers when input cannot be generated from JSON metadata;
choose the explicit Zod async helpers for async refinements.

## Build a fixture with native validation

```ts
import Type from 'typebox';
import { fluent } from '@mimlet/core';
import { fromTypeBox } from '@mimlet/typebox';

const User = Type.Object({
  id: Type.String({ default: 'user-1' }),
  role: Type.Union([
    Type.Literal('reader'),
    Type.Literal('admin'),
  ]),
});

const users = fluent(fromTypeBox(User), ['id', 'role']);
export const admin = users.withRole('admin').buildValidated();
```

The override remains input-typed. With transforms/codecs, `build()` produces input
and `buildValidated()` returns output. Use `buildValidatedAsync()` when the schema
or factory requires asynchronous work. Don't hide failures by casting away types.

## Preserve relationships

```ts
import { createScenario, createSession } from '@mimlet/core';

export const checkout = createScenario({ name: 'checkout' })
  .node('customer', [], (_, session) => ({ id: `user-${session.sequence('id', 1)}` }))
  .node('lines', [], () => [{ quantity: 2, priceCents: 1500 }])
  .node('order', ['customer', 'lines'], ({ customer, lines }) => ({
    customerId: customer.id,
    totalCents: lines.reduce((sum, line) => sum + line.quantity * line.priceCents, 0),
  }));

export const shop = checkout.build(
  createSession({ seed: 42, fingerprint: 'checkout/v1', provider: 'my-test@1' })
);
// shop.order.customerId === shop.customer.id; shop.order.totalCents === 3000.
```

Change an upstream node or input parameter and let dependent nodes recalculate.
Avoid independently replacing a foreign key or total that should follow another value.

## Reproduce the failing operation

```ts
import { createBuilder, createSession, restoreSession } from '@mimlet/core';
import type { GenerationSession } from '@mimlet/core';

const identity = { fingerprint: 'users/v1', provider: 'my-factory@1' };
const session = createSession({ ...identity, seed: 42 });
const users = createBuilder((run: GenerationSession) => ({ id: run.integer(1, 1000) }));

// Save before the failing operation to reproduce that operation.
export const before = session.snapshot();
export const first = users.build(session);
export const again = users.build(restoreSession(before, identity));
// first and again have the same id. Restoring checks the supplied identity.
```

Persist the snapshot as JSON when necessary. Preserve schema/configuration and
provider identity; a mismatch is an error to investigate, not a reason to bypass
replay validation. Arbitrary external I/O, clocks and factory side effects do not
become deterministic merely because a session is seeded.

## Shrink inputs while keeping the scenario coherent

```ts
import * as fc from 'fast-check';
import { createScenario } from '@mimlet/core';
import { scenarioArbitrary, checkFixtureProperty } from '@mimlet/fast-check';

const identity = { fingerprint: 'basket/v1', provider: 'my-test@1' };
const cart = createScenario()
  .node('prices', [], () => [] as number[])
  .node('total', ['prices'], ({ prices }) => prices.reduce((sum, n) => sum + n, 0));
const baskets = scenarioArbitrary(
  fc.array(fc.integer({ min: 1, max: 100 }), { minLength: 1, maxLength: 10 }),
  (prices) => cart.override('prices', () => prices),
  { ...identity, seed: 42 }
);

// Deliberately false property: inspect its report without making the example fail CI.
export const report = checkFixtureProperty(baskets, (basket) => basket.total < 5, {
  identity,
  seed: 12345,
  numRuns: 100,
});
// Shrinking recomputes total from prices; the minimal counterexample is { prices: [5], total: 5 }.
// In a real test, use assertFixtureProperty so a failed property fails the test.
```

Use the report's replay record with `replayFixtureProperty` and the same property,
arbitrary, engine and identity. Use `assertFixtureProperty` in tests that must fail
on a counterexample. Review the [fast-check contract](/mimlet/packages/fast-check.md)
before combining native arbitraries with custom mappings.

## Generate without executing application modules

```ts
import { emitBuilders } from '@mimlet/codegen';

// Generation records the application import; it does not execute the module.
export const files = emitBuilders([
  {
    name: 'UserBuilder',
    source: { kind: 'factory', module: '../users.js', export: 'makeUser' },
    fields: ['id', 'role'],
  },
]);
// files[0] contains a fluent UserBuilder with withId and withRole methods.
```

The installed `@mimlet/codegen` package supplies the `mimlet` executable. A data-only
configuration can declare the same module target. Run `mimlet --config builders.json
--out generated --check` to detect drift without writing output; omit `--check`
when regeneration is intended. Add `--self-contained` for the canonical embedded
runtime. Generated-file ownership prevents overwriting handwritten edits.

The CLI comes from `@mimlet/codegen`; `@mimlet/core` supplies the runtime. See the [codegen reference](/mimlet/packages/codegen.md).

## Use a factory when generation cannot represent a constraint

```ts
import Type from 'typebox';
import { fromTypeBoxFactory } from '@mimlet/typebox';

const Code = Type.String({ pattern: '^APP-[0-9]+$' });
const codes = fromTypeBoxFactory(Code, (index: number) => `APP-${index}`);

export const code = codes.buildValidated(42); // 'APP-42'
```

Native validators may include arbitrary refinements, callbacks, recursive structures
or codecs that cannot be synthesized automatically. Keep the validator and supply
an explicit factory. Report bounded generation exhaustion instead of claiming the
schema is impossible or dropping its constraints.

## Documentation that stays in sync

These recipes are compiled and executed against clean package tarballs by
`pnpm test:examples`. The website generates its HTML, Markdown alternates and
`llms.txt` from the same repository sources. The agent guide is ordinary product
documentation: it does not override the user's instructions or claim that agents
must prefer Mimlet over another suitable tool.

## Direct named setters and local diagnostics

Alpha.2 includes [named direct-builder setters](/mimlet/guide/fluent-builders.md): declare
`fluent(fromZod(schema), ['name'])`, then use `.withName('test').buildValidated()`.
Use the existing schema and keep small declarations beside their tests; generating
or maintaining builder files is optional. Native values such as Temporal still
need an explicit factory when JSON generation cannot represent them.

[CLI diagnostics](/mimlet/guide/cli-diagnostics.md) provide versioned JSON reports for dependency
checks and schema preparation. They do not prove application correctness or schema
satisfiability. The [interactive scenario demo](/mimlet/guide/scenario-demo.md) executes the same
shrinking/replay recipe as the package examples.
