Fathym
Menu

Testing with Intents (IDD)

You built a Capability. You ran it. Now instead of writing a test, declare what it intends to do. An intent isn't a correctness check - it's a declaration of purpose that travels with the holon, version-controlled, machine-runnable, and readable by any AI that works in your codebase.

TDD says "prove this works." IDD says "this is what I built." Same mechanism - declare, run, verify - different purpose: holonic identity over regression coverage.

Declare an intent

import {
  CapabilityIntent,
  ExpectCapabilityResultEquals,
} from 'jsr:@fathym/steward/capabilities/testing';

CapabilityIntent('FormatText — title case', FormatText)
  .WithInput({ text: 'hello world', style: 'title' })
  .Expect(ExpectCapabilityResultEquals({ formatted: 'Hello World' }))
  .Run();

.Run() registers a Deno.test() internally - you don't write one.

MethodWhat it does
.WithInput(data)The input to test with
.Expect(expectation)What you intend the output to be
.Run()Registers as Deno.test() - no wrapper needed

Declare your full intent with a suite

CapabilityIntentSuite gathers every scenario you care about. .ExpectInput<T>() and .ExpectOutput<T>() are compile-time checks - if the holon's schema doesn't match T, the suite won't compile.

import {
  CapabilityIntentSuite,
  ExpectCapabilityResultEquals,
} from 'jsr:@fathym/steward/capabilities/testing';

CapabilityIntentSuite('FormatText', FormatText)
  .ExpectInput<{ text: string; style: 'upper' | 'lower' | 'title' }>()
  .ExpectOutput<{ formatted: string }>()
  .Intent('title case', (intent) =>
    intent.WithInput({ text: 'hello world', style: 'title' })
      .Expect(ExpectCapabilityResultEquals({ formatted: 'Hello World' })))
  .Intent('upper case', (intent) =>
    intent.WithInput({ text: 'hello', style: 'upper' })
      .Expect(ExpectCapabilityResultEquals({ formatted: 'HELLO' })))
  .Run();

(Each holon type has its matching suite - AgentIntentSuite, GovernancePolicyIntent, and so on.)

Intents as AI specs

The intent file is a design document an AI can read, act on, and verify against. An agent asked to modify a holon reads its intents first - they declare what it accepts, what it produces, and which scenarios matter - then writes code and runs the suite. If every intent passes, the work matches your declared purpose. No prompt explaining the holon needed; it's all in the intent file. That's why intents lead: they're executable specs, not documentation that goes stale.

Mock services

CapabilityIntentSuite('Greeter', Greeter)
  .WithServices({ prefix: 'Hi' })
  .Intent('uses mocked prefix', (intent) =>
    intent.WithInput({ name: 'World' })
      .Expect(ExpectCapabilityResultEquals({ greeting: 'Hi, World!' })))
  .Run();

.WithServices(mock) replaces the real service factory for the duration of the suite - scoped, so it doesn't affect other tests.

Verify the contract at compile time

function _contractTests() {
  // @ts-expect-error — 'invalid' is not in the style enum
  CapabilityRunner(FormatText).Execute({ text: 'hello', style: 'invalid' });
}
void _contractTests;

Wrap in a function + void fn so TypeScript checks the types without running it; @ts-expect-error suppresses the error on the next line only.

Run your intents

# All tests (including intents) via the barrel:
deno test -A tests/tests.ts --trace-leaks

# A specific holon's intents:
deno test -A intents/capabilities/format-text.intents.ts

Intent files live in intents/ parallel to tests/ - one .intents.ts per holon, named to match the holon file; the barrel wires them together.


On this page