AGENTS.md ยท diff
git:20260730.d0a15c3 to git:20260730.678e432
3 added, 2 removed. Audit A to A.
# AGENTS.md - Instructions for LLMs Working in This Repo
## Project Purpose
The Writing Style Library is a composable catalog of writing instructions organized along four orthogonal axes: Voice, Tone, Style/Mode/Genre, and Format/Output Structure. The goal is to allow any combination of axis values to be assembled into a structured prompt prefix that shapes LLM writing output toward a specific register, rhetorical pattern, and layout. The library is packaged as a Claude Code plugin with three skills today - `writing-instruction-builder` (compose a prompt from axis values you already know you want), `style-profile` (capture a personal default style once, for reuse), and `entry-recommender` (recommend a combination for a described situation, composing the prompt in the same step) - plus any further skill a maintainer-approved spec adds; check `docs/internal/` for in-flight proposals. A TypeScript/Python SDK and a Composer SPA were considered and deliberately deferred indefinitely (see `ROADMAP.md` - "Deliberately deferred").
---
## The Four-Axis Taxonomy Model
Four axes, one directory each, one selection each. Composition applies them in the precedence
order below (ADR 0016). Named "four-axis" per ADR 0018; earlier docs called this a three-axis
model and grouped Voice with Tone, so treat any surviving "Axis 1/2/3" numbering as stale.
**Axis 1 - Voice** (`taxonomy/voices/`): The persistent identity of the writer. Voice captures worldview, characteristic concerns, and professional archetype. It is stable across contexts. Example seed entries: `pragmatic-architect`, `product-thinker`, `operator`.
**Axis 2 - Tone** (`taxonomy/tones/`): Situational register layered on top of voice. Tone is orthogonal to voice and can be mixed freely. Example seed entries: `candid`, `encouraging`, `confident`.
> Voice and Tone are the most confusable pair in the catalog. The rule: **voice is what does
> not change; tone is what changes per piece.** They have separate directories, separate
> schemas with different required fields, and separate composer parameters. When triaging
> which directory a new entry belongs in, ask whether a writer could hold it constant across
> a year of writing.
**Axis 3 - Style** (`taxonomy/styles/`): The cognitive and rhetorical pattern of the writing. How ideas are sequenced and structured. Example seed entries: `problem-solution`, `layered-disclosure`, `decision-log`.
**Axis 4 - Format** (`taxonomy/formats/`): The visual and structural container. Defines headings, bullet depth, table layouts, section templates. Example seed entries: `adr`, `daily-standup`, `slack-message`.
---
## Key Conventions
### Atomic-Folder Pattern
Each taxonomy entry lives in its own folder: `taxonomy/<axis>/<entry-id>/`. The folder contains `ENTRY.md` (the entry body and frontmatter) and nothing else. Worked examples do not live inside the entry folder: they are separate files under the top-level `examples/` tree (`examples/vertical-slices/<topic-slug>/<axis>-<entry-id>.md` - see `examples/README.md` and CONTRIBUTING.md Path 2).
### Frontmatter-First
Every entry file must begin with a YAML frontmatter block. The block must include at minimum: `id`, `axis`, `name`, `version`, `review_status`, `tags`, `created`, `author`. Validate against the axis-specific schema in `schemas/` before committing.
### No Em-Dashes, No En-Dashes
This is a hard rule with no exceptions. Do not use U+2014 (em-dash) or U+2013 (en-dash) anywhere in any file you create or modify - including entry bodies, documentation, commit messages, and comments. Use " - " (space-hyphen-space) as the substitute. A pre-commit hook enforces this rule; do not attempt to disable it.
### Review Status Progression
New entries must start at `draft`. The progression is: `draft` -> `reviewed` -> `stable` -> `reference-quality`. Do not set a new entry to `stable` or `reference-quality` without maintainer approval.
The 60 entries shipped in v0.1.0 are the maintainer-curated seed set: they were reviewed and set to `stable` as the initial baseline. This rule governs every contribution since - the catalog currently carries 20 `draft` Format entries (the Hold-20, staged for a future audience-expansion release) alongside 97 `stable` entries, and any new entry starts at `draft` the same way.
---
## How to Add an Entry
1. Create a new folder: `taxonomy/<axis>/<kebab-case-id>/`
2. Create `ENTRY.md` inside that folder
3. Add the required frontmatter fields (see CONTRIBUTING.md for the full list)
4. Write the entry body: definition sentence, "When to use" bullets, "Instruction block" section, optional "Do not use when" section
5. Add at least one example file (vertical slice preferred)
6. Run `python tools/validate.py` and confirm it passes
7. Commit with a Conventional Commits message: `feat(taxonomy): add <entry-id> <axis> entry`
---
## Generating and Promoting Content at Scale (the Agentic Factory)
The steps above add ONE entry by hand. To generate or promote content at scale - new
candidate entries, whole-corpus de-duplication, or rendering and promoting drafts to
stable - use the **agentic generation factory** in `tools/agentic/`. It is the
catalog's production engine: isolated subagents do the writing, layered gates do the
checking, and it all runs free in-session (no paid CI).
Key rules when operating it:
- **New entries always start `review_status: draft`.** Promotion to `stable` is a
maintainer decision (and earns a hard cost: rendering on all 12 anchor topics).
- **Gate 2 is atomic.** A stable entry must render on all 12 anchor topics
(`tools/anchor_topics.py`). Render while still draft (drafts are exempt), then flip
with `python tools/promote.py` - it is guarded and will refuse to leave the build red.
- **Gate every batch.** New entries get a cross-vendor distinguishability gate; the
corpus gets a family-cluster de-dup audit; dated samples get a calendar gate.
Start at [`tools/agentic/README.md`](tools/agentic/README.md). The design and contracts
are in [`docs/internal/agentic-generation-spec.md`](docs/internal/agentic-generation-spec.md);
the step-by-step promotion and release steps are in
[`docs/internal/release-plans/promotion-and-release-runbook.md`](docs/internal/release-plans/promotion-and-release-runbook.md).
---
## Validation
Always run validation before committing:
```bash
python tools/validate.py
```
This checks frontmatter completeness, schema conformance, no em-dash/en-dash characters, valid `review_status` values, and resolving cross-references.
---
## Schema Safety
The six contributor-facing schemas (`entry.universal`, `voice`, `tone`, `style`, `format`,
`example`) are **frozen** as of
- [ADR 0019](docs/internal/adr/0019-schema-freeze-and-change-policy.md). `diff-pair.schema.json`
- is not frozen, but the classes below still govern it.
+ [ADR 0019](docs/internal/adr/0019-schema-freeze-and-change-policy.md). `experimental/diff-pair.schema.json`
+ is not frozen and is served from `/schemas/experimental/` so its URL says so, but the
+ classes below still govern it.
The test: **would this edit change the verdict on any conceivable document, not just the
files in this repo?** Checking only the current corpus is the trap this policy exists to
avoid, because `additionalProperties: false` or a narrowed `$ref` can leave every entry here
passing while rejecting documents the published schema used to accept.
| Class | What it covers | Requires |
| ------ | --------------- | --------- |
| **A - Annotation** | An allowlist, nothing else: `title`, `description`, `$comment`, `examples`, plus unobservable reordering | Normal PR. No ADR, no version bump, no entry migration. Say "annotation-only, class A" in the PR body. |
| **B - Additive optional** | New **optional** property; widened `enum`, `pattern`, or bound | Minor version bump + `CHANGELOG.md` note |
| **C - Breaking, or unclear** | New required property, removal, rename, narrowing, optional -> required, **and every keyword not listed in A or B** - including `$id`, `$schema`, `$ref`, `$defs`, `additionalProperties`, `unevaluatedProperties`, `format`, and the combinators | ADR + **major** version bump + migrate every affected file in the same change + `validate.py` green before merge |
**The default is C.** Anything not on the class A allowlist or squarely class B is class C;
unclear resolves to the most expensive class, not to a fourth one. A change to
`entry.universal` or a shared `$def` is class C for every schema that `$ref`s it.
ADR 0019 is the authority; this table is a summary. If still unsure, open a draft PR and ask
rather than committing directly.
---
## Skill Frontmatter Convention
Each `skills/*/SKILL.md` includes a `metadata: version:` block in its YAML frontmatter:
```yaml
metadata:
version: "0.3.0"
```
This is a project-private convention - it is not part of the Claude Code skills specification. The value must be a SemVer `X.Y.Z` string and must match the `version` field for that skill in `library.json` under `components.skills`. The validator at `scripts/validate-plugin-manifest.mjs` enforces this agreement: it will fail if the SKILL.md version and the library.json version drift. When bumping a skill version, update both `SKILL.md` and `library.json` in the same commit.
---
## Paths to Know
| Path | What it contains |
| ------ | --------------- |
| `taxonomy/` | All axis entries |
| `examples/` | Worked output examples |
| `schemas/` | JSON Schema definitions for entry types |
| `skills/writing-instruction-builder/` | Compose a prompt from axis values you already know you want |
| `skills/style-profile/` | Capture a personal default style once, for reuse |
| `skills/entry-recommender/` | Recommend a combination for a described situation |
| `tools/validate.py` | Validation script |
| `tools/agentic/` | The agentic generation factory (generate, audit, remediate, render harnesses) |
| `tools/promote.py` | Guarded, atomic draft -> stable promotion |
| `site/` | The Astro Starlight documentation site (authored pages in `src/content/docs/`; catalog pages generated at build time) |
| `docs/` | Internal governance only (see the two rows below) - not built by Astro; the site lives in `site/` |
| `docs/internal/` | Living planning docs - ADRs, release-plan trackers, specs, the backlog - maintained under direct maintainer direction as work proceeds. Demonstrated by this repo's own history: `agentic-generation-spec.md`, the promotion-and-release runbook, and every `stream-b-*` tracker were all produced and merged here. |
| `docs/internal/_working/` | Frozen historical planning snapshots - read-only, do not modify |
| `_LOCAL/` | Source research - read-only, do not modify |