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.
| Method | What 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.
- Advanced Patterns → - beyond the base contract