Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,21 @@ using xUnit, using NSubstitute).
Migrating from AutoFixture? See the
[AutoFixture migration guide](https://layeredcraft.github.io/compono/migrating-from-autofixture/).

## AI Coding Agent Skill

Using Claude Code or another `npx skills`-compatible agent to write
Compono tests? Install the official skill so it knows Compono's actual
API and guardrails instead of guessing from AutoFixture-shaped habits:

```bash
npx skills add LayeredCraft/compono
```

See the
[AI Coding Agent Skill guide](https://layeredcraft.github.io/compono/getting-started/ai-agent-skill/)
for details, or the `skills/` directory in this repository for the
canonical source.

## Documentation

The full documentation site is at
Expand Down
223 changes: 223 additions & 0 deletions docs/adr/0035-compono-agent-skill-pack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
# [ADR-0035] Compono Agent Skill Pack

**Status:** Accepted

**Date:** 2026-08-07

**Decision Makers:** solo (Nick Cipollina), assisted by Claude

## Context

Compono's public preview shipped in Milestone 8: four packages on nuget.org,
a full documentation site, and a clean-room acceptance test proving the
learning path works without internal knowledge. The first post-MVP work
item is developer tooling, not a runtime feature: an AI-coding-agent
"skill" that teaches an agent (Claude Code, and other `npx skills`-
compatible hosts) how to write, modify, review, and troubleshoot unit
tests that use Compono in a *consumer's* test project.

This is necessary because Compono deliberately looks similar to, but
behaves differently from, AutoFixture β€” the library most agents already
"know" from pretraining. An agent working from general .NET knowledge
will reach for AutoFixture-shaped habits (`[Frozen]`, `ConfigureMembers`,
customization override, reflection fallback) that either don't exist in
Compono or actively conflict with its source-generated, deterministic
design. `docs/research/0001-autofixture-comparison.md` and
`docs/migrating-from-autofixture.md` already catalog this gap from real
migration evidence (Milestone 7); this ADR is about encoding that
hard-won knowledge into something an agent consults *before* writing
code, not just something a human reads.

This repo already installs skills itself via `npx skills` (see
`skills-lock.json`, `.agents/skills/`, `.claude/skills/`) and follows the
`.agents/skills/engineering-workflow` design process for exactly this
kind of decision.

## Decision Drivers

- The skill must reflect Compono's actual shipped public API β€” no
invented APIs, no forward-looking/roadmap content presented as current.
- Triggering accuracy: activate for genuine Compono test-authoring work,
never hijack ordinary non-Compono .NET test work.
- Context efficiency: an agent shouldn't have to load NSubstitute-specific
or Bogus-specific guidance for a project that doesn't reference those
packages.
- Maintainability: adding a future integration package (a new test
framework, mocking library, Verify, etc.) shouldn't require restructuring
the whole skill.
- Installability: must work via `npx skills add <owner>/compono` and the
`skills/` subpath form, per the `npx skills`/skills.sh convention this
repo already uses for its own tooling.
- Guardrail strength: the skill's primary value is stopping AutoFixture-
habit mistakes before they're written, not documenting the happy path.

## Considered Options

1. **One skill** (`skills/compono/`) β€” single `SKILL.md` with detection,
routing, default workflow, and guardrails in the body; deep material in
`references/`, loaded conditionally by which packages are detected.
2. **Router + focused workflow skills** (mirroring
[microsoft/aspire-skills](https://github.com/microsoft/aspire-skills)
more literally) β€” a top-level `compono` router skill plus separate
skills for, e.g., authoring vs. diagnostics vs. configuration.
3. **Core + per-integration skills** β€” `compono` (core) plus
`compono-xunit`/`compono-nsubstitute`/`compono-bogus` as independent
skills, split along package boundaries.

## Decision Outcome

Chosen option: **1, one skill** (`skills/compono/`), with progressive
disclosure through `references/`.

Compono is a single, coherent agent workflow β€” recognize the project uses
Compono β†’ inspect the type/collaborators β†’ decide whether/how to compose
β†’ act β†’ validate β€” regardless of which optional packages
(`Compono.XunitV3`/`Compono.NSubstitute`/`Compono.Bogus`) are installed.
A task like "compose a theory with a shared NSubstitute double and a
Bogus-generated email" touches all three integration surfaces *in one
decision*, not three sequential workflows. Aspire's multi-skill split is
justified there because its sub-skills are genuinely different
*operational domains* with different tools and blast radius β€” scaffolding
(`aspire-init`), process lifecycle/CLI safety (`aspire-orchestration`),
cloud/CI (`aspire-deployment`), observability tooling
(`aspire-monitoring`). Compono has no such domain split: everything is
"write or fix C# test code against one composition API." Splitting it
would force either constant cross-skill handoff mid-task, or duplicated
core-composition explanation copy-pasted into every sub-skill.

**Studied from [microsoft/aspire-skills](https://github.com/microsoft/aspire-skills)
and adopted, adapted to a single skill instead of six:**

- The `description` frontmatter as the actual triggering/boundary
mechanism: a bold skill-type tag, `USE FOR:` (concrete signals/phrases),
`DO NOT USE FOR: (use X)` redirects, and β€” since there's no sibling to
hand off to β€” a `SCOPES TO:` note on which reference files apply given
detected packages, replacing Aspire's `INVOKES:` (which names sibling
skills we don't have).
- A **Detection table** (signal β†’ how to detect β†’ confidence) gating
which `references/` files are relevant, adapted from the router
skill's pattern but living in the one `SKILL.md` instead of a separate
router file.
- **Guardrails separated by severity**: hard "never do this" rules
(no reflection fallback, no `Activator.CreateInstance` workaround, no
silent AutoFixture substitution) get a top-of-file refusal section like
`aspireify`'s `.aspire/modules/` rule; softer per-topic guardrails live
in `references/patterns-and-antipatterns.md` with the reasoning, not
just the rule.
- **Evals with a `skill-invocation`-equivalent check** β€” positive
activation (genuine Compono test work), negative activation (ordinary
xUnit/NSubstitute/Bogus work with no Compono involvement), and
correct-behavior scenarios (right API chosen, registration precedence
respected, no invented APIs) β€” scaled down from Aspire's 167-stimulus,
CI-gated suite to a handful of scenarios proportionate to one skill.

**Deliberately not adopted**: Aspire's self-deactivating one-time skill
pattern (`aspireify`'s SCAN→PROPOSE→EDIT→VALIDATE→DEACTIVATE) — Compono
has no one-time scaffolding phase distinct from ongoing authoring; adding
Compono to a project and writing a Compono test are the same kind of
"compose something" task, not two phases of one bigger job.

**Reference file set** (subject to renaming/consolidation during
implementation β€” see the escape-hatch principle below; this is a starting
shape, not a frozen list):

- `composition-model.md` β€” `Composer`, `Create<T>()`/`CreateMany<T>()`,
`[Composable]`, generated-plan discovery, determinism/seeding (folded in
rather than split out β€” seeding is inseparable from how a composition
path is derived, not a separate workflow)
- `registrations-profiles-and-scopes.md` β€” `Register<T>()`,
`For<T>().Use()`/`.Member()`, `ICompositionProfile`, `[Shared]`,
recursion detection
- `diagnostics.md` β€” the CMP0001–CMP0012 compile-time table, the runtime
`CompositionException`/tree-path/seed format, and the reproduce-a-
failure workflow
- `xunit-v3.md` β€” `[Compose]`/`[Compose<TProfile>]`/`[Shared]` in test
methods (only relevant if `Compono.XunitV3` is referenced)
- `nsubstitute.md` β€” `UseNSubstitute()`, substitutable-shape rules (only
relevant if `Compono.NSubstitute` is referenced)
- `bogus.md` β€” `UseBogus()`/`UseBogus<T>()`, conventions/aliases (only
relevant if `Compono.Bogus` is referenced)
- `patterns-and-antipatterns.md` β€” the guardrail/anti-pattern catalog,
including the AutoFixture concept-mapping table (folded in here rather
than a separate migration file β€” the migration guidance *is* the
antipattern catalog, framed from the AutoFixture-habit direction)

**Escape-hatch principle for future growth** (the actual reusable
decision this ADR records, per the user's explicit direction during
design review): start with one skill because Compono today represents a
single cohesive agent workflow. Split into additional skills only when a
future capability develops **distinct activation signals, workflows,
tooling requirements, or context needs** that make the single-skill model
inefficient or ambiguous β€” e.g. a future `Compono.Verify` or
`TUnit`/`NUnit` integration that introduces a genuinely different
operational mode, not just another `UseX()` call inside the same
authoring loop. **The existence of a new integration package alone is not
sufficient reason to split** β€” the test is whether it changes *how* an
agent works, not merely *what* API surface it adds. That split, if it
ever happens, is itself a new deep-dive design decision (a new ADR), not
something this ADR pre-commits to a shape for.

### Positive Consequences

- One `SKILL.md` to keep in sync with the API surface; no duplicated
core-composition explanation across sibling skills.
- Package-conditional loading keeps context lean without a router skill's
indirection overhead.
- Simple installation story: `npx skills add <owner>/compono` or the
`skills/compono` subpath, matching this repo's own tooling convention.

### Negative Consequences

- If Compono's package surface grows substantially (several new
integrations at once), `SKILL.md`'s Detection/Routing section could
grow unwieldy before a split is warranted β€” mitigated by the
escape-hatch principle above and by `references/` absorbing the actual
bulk of new content, not the routing table.
- A single skill can't express Aspire-style hard operational boundaries
between sub-domains, because Compono doesn't have any today β€” if that
changes, this ADR's Decision Outcome would need superseding, not
amending.

## Pros and Cons of the Options

### Option 1 β€” One skill

- Good, because it matches Compono's actual single-workflow shape.
- Good, because it avoids cross-skill handoff for tasks that legitimately
span two or three integration packages at once.
- Good, because `references/` already gives context-window efficiency
without needing a router.
- Bad, because it doesn't scale indefinitely β€” mitigated by the
escape-hatch principle.

### Option 2 β€” Router + focused workflow skills

- Good, because it directly mirrors the studied reference architecture.
- Bad, because Compono has no genuinely distinct operational domains to
route between today β€” the split would be along API-surface lines, not
workflow lines, which is exactly the "arbitrary API categories" split
the design brief warned against.
- Bad, because every real task (compose a test with a shared substitute
and semantic data) would still need multiple skills active at once,
producing router overhead with no triggering-accuracy benefit.

### Option 3 β€” Core + per-integration skills

- Good, because it's easy to reason about "does this skill apply" per
installed package.
- Bad, because it splits along package boundaries, not workflow
boundaries β€” the same "compose a test" decision (which value comes from
where: registration, rule, provider) gets fragmented across skills for
no navigational benefit, since `references/` already achieves the same
package-conditional loading inside one skill.
- Bad, because core composition-model knowledge (constructor selection,
`[Composable]`, diagnostics) would need restating or cross-referencing
in every integration skill.

## Links

- [Aspire skills repository](https://github.com/microsoft/aspire-skills) β€” architectural reference studied for this decision
- `docs/research/0001-autofixture-comparison.md` β€” source of the AutoFixture-habit gap evidence this skill encodes
- `docs/migrating-from-autofixture.md` β€” the human-facing counterpart this skill's `patterns-and-antipatterns.md` draws from
- `docs/mvp.md` Milestone 8 closeout β€” the public-preview release this skill pack follows
- `.agents/skills/engineering-workflow/references/design-decisions.md` β€” the process this ADR follows
1 change: 1 addition & 0 deletions docs/adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,4 @@ the mechanics: numbering, status, and the index.
| [0032](0032-api-reference-documentation-toolchain.md) | API Reference Documentation Toolchain | Accepted |
| [0033](0033-public-preview-samples-strategy.md) | Public Preview Samples Strategy | Accepted |
| [0034](0034-benchmark-suite-strategy-and-redesign.md) | Benchmark Suite Strategy and Redesign | Accepted |
| [0035](0035-compono-agent-skill-pack.md) | Compono Agent Skill Pack | Accepted |
18 changes: 15 additions & 3 deletions docs/documentation-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,10 @@ learning path.
## 1. Getting Started

**Audience:** someone who has never used Compono.
**Status:** real content (all 5 pages, written in
[PLAN-0008](plans/0008-milestone-8-public-preview.md) Phase 2).
**Status:** real content (5 pages written in
[PLAN-0008](plans/0008-milestone-8-public-preview.md) Phase 2, plus
`ai-agent-skill.md` added in
[PLAN-0035](plans/0035-compono-agent-skill-pack.md) β€” 6 pages total).
`docs/index.md` covers a subset of this today.
**Purpose:** answer "what is this, and can I get something working in the
next five minutes," and point every kind of newcomer toward the right next
Expand All @@ -221,9 +223,19 @@ step.
- `next-steps.md` β€” branches the reader outward: "want the mental model
next? β†’ Concepts. Have an immediate problem to solve? β†’ Cookbook. Want a
curated path instead of picking yourself? β†’ Learning Paths."
- `ai-agent-skill.md` β€” for a reader using an AI coding agent (Claude
Code or another `npx skills`-compatible host) to write Compono tests:
what the official `compono` agent skill is, how to install/update it,
which agents support it, and how it relates to (and stays independent
of) the NuGet packages. Tooling/workflow content, not part of the
Compono API itself β€” placed in Getting Started rather than its own
section because it's a one-time setup step for a specific class of
reader, the same shape as `installation.md`.
**Relates to:** assumes nothing. Hands off to Concepts (for the model),
Cookbook (for an immediate task), or Learning Paths (for a curated route
through everything else).
through everything else). `ai-agent-skill.md` additionally links back to
[ADR-0035](adr/0035-compono-agent-skill-pack.md) for the skill's own
design rationale.

## 2. Concepts

Expand Down
86 changes: 86 additions & 0 deletions docs/getting-started/ai-agent-skill.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# AI Coding Agent Skill

Compono ships an official agent skill β€” guidance an AI coding agent (like
Comment thread
ncipollina marked this conversation as resolved.
Claude Code) reads before writing, modifying, reviewing, or troubleshooting
Compono-based tests in your project. It's developer tooling, not a runtime
package: nothing here runs inside your test process, and it has no effect
on `dotnet build`/`dotnet test`.

## What it does

An agent without this skill knows Compono only from pretraining, and will
likely reach for AutoFixture-shaped habits that don't apply β€” `[Frozen]`
semantics, customization override, reflection-based construction. The
skill teaches the agent Compono's actual model: source-generated
composition, `[Composable]`'s narrow scope, registration/rule precedence,
`[Shared]`, deterministic seeding, the real `CMP0001`-`CMP0012` diagnostic
set, and the package-specific surface of `Compono.XunitV3`/
`Compono.NSubstitute`/`Compono.Bogus` β€” only recommending an integration's
API when that package is actually referenced in your project.

It also carries guardrails: it won't suggest reflection-based workarounds,
won't silently substitute AutoFixture, and won't add `[Composable]`
speculatively. And it stays out of the way for ordinary, non-Compono .NET
test work β€” it only activates on genuine Compono-related tasks.

## Install

The canonical source is the `skills/` directory of this repository. Add it
to a project via [`npx skills`](https://www.npmjs.com/package/skills)
(works with Claude Code and other `npx skills`-compatible agent hosts):

```bash
npx skills add LayeredCraft/compono
```

or, targeting the `skills/` directory explicitly:

```bash
npx skills add https://github.com/LayeredCraft/compono/tree/main/skills
```

This installs the `compono` skill into your project's agent-skill
directory (e.g. `.claude/skills/compono` for Claude Code). No NuGet
package, no `.csproj` change, no `dotnet` command β€” this is entirely
separate from installing the `Compono`/`Compono.XunitV3`/
`Compono.NSubstitute`/`Compono.Bogus` packages themselves (see
[Installation](installation.md) for those).

## Update

```bash
npx skills update compono
```

`npx skills` ships a dedicated `update` command for refreshing an
already-installed skill (`-g`/`--global` or `-p`/`--project` to scope it,
if you have the same skill installed at both levels) β€” use that rather
than re-running `add`. There's no separate version pin to manage for this
skill; an update always pulls whatever is currently on this repository's
default branch.

## Which agents support it

Any agent host compatible with the `npx skills`/skills.sh convention β€” the
skill is plain Markdown (a `SKILL.md` plus `references/`), with no
Claude-specific mechanics baked in. It's developed and verified primarily
against Claude Code.

## Relationship to the NuGet packages

The skill and the packages are independent, and neither requires the
other:

- Installing the skill doesn't add any package reference to your project,
and doesn't require Compono to already be in use β€” an agent with the
skill installed can also help you *adopt* Compono in a project that
doesn't have it yet, if you ask.
- Installing the packages without the skill works fine β€” the skill only
changes how well an AI agent assists you; Compono itself doesn't know or
care whether it's installed.
- The skill's guidance is checked against this repository's actual shipped
API on every change β€” it should never describe an API that doesn't
exist, or a roadmap item as if it were current.

See [ADR-0035](../adr/0035-compono-agent-skill-pack.md) for the design
decision behind the skill's structure.
3 changes: 3 additions & 0 deletions docs/getting-started/next-steps.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ on what you want to do now:
[Migrating from AutoFixture](../migrating-from-autofixture.md).
- **Something didn't work as expected?** β†’
[Troubleshooting](../troubleshooting/index.md).
- **Using an AI coding agent to write these tests?** β†’
[AI Coding Agent Skill](ai-agent-skill.md) β€” install Compono-specific
guidance for Claude Code and other `npx skills`-compatible agents.
Loading