Skip to content
Open
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
161 changes: 154 additions & 7 deletions .claude/skills/ai-diataxis-scaffold/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ before you run.**
cannot adopt a structure they have never seen, and that every directory here
ships with a page in it.

**The same disclaimer covers the second axis.** When step 2's audience question is
answered with anything but its default, this skill builds a tree partitioned by
reader as well as by mode. The one upstream page that raises that shape —
<https://web.archive.org/web/20260802004758/https://diataxis.fr/complex-hierarchies/>
(snapshot captured 2026-08-02, retrieved 2026-08-24; the live URL returns 404 as of
2026-08-24, so the guidance is published-but-withdrawn) — **presents it only as a
question it declines to answer**: "Which better? There seems to be a lot of
repetition in either cases." So claim no source support for the two-axis shape
either. State that Diátaxis does not endorse it, name that page as raising and
declining it, and say the argument for offering it is this project's own.

**So: never create a directory you do not also seed.** That is not a stylistic
preference. Git does not track empty directories, so four empty directories
produce zero commits and there is nothing to hand over; and an autogenerated
Expand Down Expand Up @@ -95,6 +106,40 @@ On confirmation, write `docs_path` into `.context/README.md` frontmatter with th
Edit tool and report that the interview will not repeat. If the user declines, use
the value for this run only.

### Step 2b: Ask the audience question — once, before anything is created

**Ask this in step 2 and not later.** Step 5 creates directories, and the above-mode
shape cannot be adopted after that: once `docs_path/how-to/` holds six pages, moving
to `user-docs/how-to/` relocates every page and breaks every cross-mode index link.
The one moment the choice costs nothing is before the tree exists.

Use `AskUserQuestion` with three options:

- **No audiences** *(recommended)* — the four mode directories go directly under
`docs_path`. One readership, which is the ordinary case.
- **A user tree and a developer tree** — two audience roots, each holding its own
four mode directories.
- **Something else** — the builder names their audiences.

Write the question to the same standard step 2 already sets for the docs root: say
that **the answer determines where the four mode directories go**, name what will be
created under each option, and say that **changing it later moves every page.**

**The options are examples of a shape, not a vocabulary.** `user` and `developer` are
offered because they are the common pair; a project that picks "something else" names
its own labels with no suggestion from this skill. An audience has a **label** — the
project's own word — and an **object**, the thing that audience's readers act on
(*the released command-line tool*, *this repository's source tree*). **The object is
never a person**, and it is what the landing page seed needs. The rule in full is
reference §12 in
`.claude/skills/ai-skills-reference/diataxis-classification.md`.

**Do not write the answer into `.context/README.md`.** `/ai-init` is the sole writer
of that file's body, and `## Audiences` is never interviewed for there. Instead, when
the answer is anything but the default, **print the `## Audiences` section for the
user to paste**, one bullet per audience carrying its label and the object its readers
act on.

## Step 3: Detect the static-site generator

Run the detection table in `framework-detection.md` again, this time for the
Expand Down Expand Up @@ -133,6 +178,32 @@ generator: Docusaurus (docs/docusaurus.config.ts)
Creating 2 directories, 2 index pages, 5 template files. Writing 0 existing files.
```

**When step 2b returned audiences, report the whole shape in the same form**, and
report it **before writing anything** — the count is the number most worth seeing
early, because it is more than double the default:

```text
docs_path: docs/docs (from .context/README.md)
generator: Docusaurus (docs/docusaurus.config.ts)
audiences: user, developer (from the step 2b answer)

user-docs/ missing — will create + seed index.md
user-docs/tutorial/ missing — will create + seed index.md
user-docs/how-to/ missing — will create + seed index.md
user-docs/reference/ missing — will create + seed index.md
user-docs/explanation/ missing — will create + seed index.md
developer-docs/ missing — will create + seed index.md
developer-docs/tutorial/ missing — will create + seed index.md
developer-docs/how-to/ missing — will create + seed index.md
developer-docs/reference/ missing — will create + seed index.md
developer-docs/explanation/ missing — will create + seed index.md
_templates/ missing — will copy 5 templates
../CLAUDE.md missing — will write

Creating 10 directories, 10 index pages, 5 template files. Writing 0 existing files.
Against 4 directories and 4 pages for the no-audiences answer.
```

**Never overwrite.** Where a target file already exists, warn and ask whether to
overwrite or skip; default to skip. An existing page must be byte-identical after
the run.
Expand All @@ -148,10 +219,58 @@ say plainly that moving existing pages into modes is not this skill's job:

## Step 5: Create the missing directories and seed each one

For each of the four modes that is missing, create the directory **and** write its
`index.md`. The four seed shapes are in `references/seeds.md` — read it and use
them; they carry the frontmatter keys, the reader-facing paragraph, the fenced
worked example, and the cross-mode links.
Branch on step 2b's answer. The two branches share every non-negotiable below.

### 5a. The default answer — no audiences

Create the four mode directories directly under `docs_path`, seed each one, and
**change nothing else.** This path must be **byte-identical to a run of this skill
before the audience question existed**: four directories, four index pages, and **no
output line naming an audience, a readership, a shape, or a second axis.** Not even
to say the question was asked and declined.

That is the point rather than a nicety. A builder who answered "no audiences" has one
readership, and a scaffold that then tells them about a distinction selecting nothing
has reintroduced exactly the noise the axis was designed to avoid.

### 5b. Any other answer — one root per audience

Create **one audience root per declared audience**, each holding the four seeded mode
directories, plus **one landing page per root**. For two audiences that is ten
directories and ten pages, reported in step 4's form before any of it is written.

Then **print the registration lines and stop there**:

- **Docusaurus** — one sidebar entry and one navbar item per root:

```text
// sidebars.ts — one per audience root
userDocsSidebar: [{type: 'autogenerated', dirName: 'user-docs'}],
developerDocsSidebar: [{type: 'autogenerated', dirName: 'developer-docs'}],

// docusaurus.config.ts — navbar.items, one per audience root
{ type: 'docSidebar', sidebarId: 'userDocsSidebar', position: 'left', label: 'User docs' },
{ type: 'docSidebar', sidebarId: 'developerDocsSidebar', position: 'left', label: 'Developer docs' },
```

- **Another generator, or none detected** — name what it registers a top-level tree
with, or say that no generator was detected and the tree will not render at all.

**Edit no configuration file, and say the tree is unreachable from the site's
navigation until those lines are added.** This is the failure most easily produced by
being helpful: pages that exist, build, and no reader can reach. Reference §12 states
the rule — a skill never creates an audience root it cannot register, so a skill that
creates one hands over the registration.

**Repeat the no-endorsement disclaimer here**, in one line, naming the withdrawn
upstream page as raising the two-axis shape and declining to recommend it.

### Seeding, both branches

The four mode seed shapes are in `references/seeds.md` — read it and use them; they
carry the frontmatter keys, the reader-facing paragraph, the fenced worked example,
and the cross-mode links. The **audience landing page** is the fifth shape in that
same file, used only in 5b.

Non-negotiables, all checked in step 8:

Expand Down Expand Up @@ -198,9 +317,21 @@ else:
directory becomes a page, so the agent-context file would publish as
documentation.

The content is in `references/seeds.md`. Then **print the `AGENTS.md` snippet
rather than writing it** — no skill in this collection writes that file; `/ai-init`
prints one too.
The content is in `references/seeds.md`, and **which variant you use follows step
2b**:

- **Default answer (no audiences)** → use the docs-tree `CLAUDE.md` seed **exactly as
written, byte for byte.** It gains nothing about audiences, shapes, or thresholds.
- **Any other answer** → use the audience variant in the same file. It adds the
audience paths filled in from the interview answer, plus the two lines a two-axis
tree needs that a flat one does not: **a page's home is its mode**, and **a mode
index gets grouped only once its list passes seven items.**

Both lines are conditional for the same reason 5a is byte-identical: the default path
must not acquire prose about an axis the builder declined.

Then **print the `AGENTS.md` snippet rather than writing it** — no skill in this
collection writes that file; `/ai-init` prints one too.

## Step 8: Self-audit

Expand All @@ -215,6 +346,22 @@ build: `onBrokenMarkdownLinks` defaults to `warn`, so a page carrying an unfille
failure this skill's whole justification rests on not happening.
- **Every file you did not intend to touch is unchanged.**

When step 2b returned audiences, also check:

- **Every audience root holds at least one landing page and four seeded mode
directories.** A root with modes and no landing page has no entry point; a root with
a landing page and no modes is an empty structure by another name.
- **Every cross-mode link inside a root resolves within that root.** `../how-to/` from
`user-docs/tutorial/index.md` must reach `user-docs/how-to/`, never
`docs_path/how-to/`. A link that escapes its root sends a reader to the other
audience's tree, and the site build will not catch it because the target exists.
- **No landing page contains a `{`.** The registration lines you printed do contain
braces; they are printed output, not an emitted page, so the rule does not reach
them — but it does reach every landing page, and that is the one seed shape written
from the interview answer rather than copied.
- **No configuration file was modified.** `sidebars.ts`, `docusaurus.config.ts`, and
their equivalents must be byte-identical after the run.

Fix anything that fails before reporting completion.

## Report
Expand Down
124 changes: 117 additions & 7 deletions .claude/skills/ai-diataxis-scaffold/references/seeds.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
# Mode Index Seed Shapes

The four index pages the scaffold skill writes, one per Diátaxis mode. Each is a
complete page, not a fragment: a reader who opens a freshly scaffolded tree finds
prose that tells them what the mode is for and one example of a page in it.

Every seed below is **generic by design**. It describes its mode in reader terms
and carries a fenced example with no project specifics, because the scaffold runs
before any page exists to be specific about. Project-specific pages come from
The pages the scaffold skill writes: **four mode index pages**, one per Diátaxis
mode, and — only when the audience question returned audiences — **one landing page
per audience root**. Each is a complete page, not a fragment: a reader who opens a
freshly scaffolded tree finds prose that tells them what the mode is for and one
example of a page in it.

The four mode seeds are **generic by design**. Each describes its mode in reader
terms and carries a fenced example with no project specifics, because the scaffold
runs before any page exists to be specific about. Project-specific pages come from
`ai-diataxis` CREATE afterwards.

**The audience landing seed is the one exception, and it is a shape rather than a
copyable block.** Its content is *this* project's audience label and the object that
audience's readers act on, both of which come from the interview answer, so there is
nothing generic to copy. It uses `<angle-bracket>` slots and every one of them is
filled before the page is written — the no-`{` rule below covers braces, and an
emitted page carries no unfilled angle brackets either.

This file is shared byte-identically by both runtimes, so it names skills without
a leading slash and cites no path that only one runtime has.

Expand Down Expand Up @@ -162,6 +171,59 @@ For the steps to do something, see [how-to](../how-to/). For what a setting
does, see [reference](../reference/).
````

## Seed: the audience landing page

**Used only when the audience question returned audiences.** One per audience root,
written at `<audience-root>/index.md`. A shape to fill rather than a block to copy:
`<audience>` is the label the builder gave, and `<object>` is the thing that
audience's readers act on — *the released command-line tool*, *this repository's
source tree*. **The object is never a person.**

````markdown
---
title: "<Audience label, capitalised>"
sidebar_label: "<Audience label, capitalised>"
sidebar_position: 1
---

# <Audience label, capitalised> documentation

For readers working on <object>. Everything in this section is written for that
work; documentation for a different reader lives in its own section.

The four kinds of page here answer four different questions:

- [Tutorial](tutorial/) — teach me to use <object> for the first time
- [How-to guides](how-to/) — I already know what I want to do; show me the steps
- [Reference](reference/) — tell me exactly what this option does
- [Explanation](explanation/) — help me understand why it works this way

A page belongs to one of those four and to no other. Which one it belongs to
depends on what the reader needs at that moment, not on what the page is about.
````

**Filling it:**

- **Replace every `<slot>`.** A finished page contains no `<slot>` placeholder and
no `{` character. Both are checked at skill step 8.
- **The mode links are relative to the root** — `tutorial/`, not `../tutorial/`.
This page sits one level *above* the mode directories, where a mode index sits
inside one. Getting this wrong sends every link to the other audience's tree, or
out of the docs root entirely.
- **Name the object in the builder's own words from the interview, never a job
title:** "the released command-line tool", not "end users". A label names the
audience; the object names what they act on, and the two are not
interchangeable.
- **Add a cross-link to the other roots only if there is more than one, and only to
roots this run created.** A link to a tree that does not exist fails the build
under `onBrokenLinks: 'throw'`.
- **Expect the modes to sort alphabetically in the sidebar, not in Diátaxis
order.** All four mode index pages carry `sidebar_position: 1`, so inside one
audience root they tie and an autogenerated sidebar falls back to alphabetical —
explanation, how-to, reference, tutorial. Say so when handing over the
registration lines. Renumbering them is not available here: the four mode seeds
are shared with the no-audiences answer, which must stay byte-identical.

## The docs-tree `CLAUDE.md`

Written to the **parent** of `docs_path` when that parent is inside the docs site
Expand Down Expand Up @@ -192,6 +254,54 @@ implicit "About". Tutorial and reference titles carry no pattern.
name begins with `_` are excluded from the build by convention.
```

### The audience variant

**Used only when the audience question returned audiences**, in place of the block
above — never in addition to it. On the default answer the block above is written
exactly as it stands, so that path acquires no prose about an axis the builder
declined.

Fill one `- <root>/` line per audience root from the interview answer.

```markdown
# <docs directory name>/

Documentation content, partitioned first by **audience** and then by
[Diátaxis](https://diataxis.fr) mode — one directory per audience, four per audience.

- <root>/ — for readers working on <object>
- <root>/ — for readers working on <object>

Inside each audience directory:

- `tutorial/` — learning-oriented: one guided path, no choices
- `how-to/` — task-oriented: the reader brings the goal
- `reference/` — information-oriented: mirrors the product
- `explanation/` — understanding-oriented: why, not how

A page's home is its **mode**. The audience directory says who the page is for; the
mode directory inside it says what kind of page it is, and it is the mode that
decides which of the four directories a page goes in. A page serves exactly one
mode. When a page starts serving two, split it rather than adding a section — the
mode a reader is in determines what they can absorb.

Put a new page in the audience whose readers act on the thing it describes, then in
the directory matching what those readers need — not what the content is about.

A mode index lists its pages flatly and gets grouped only once that list passes
seven items. Below that, grouping costs a reader more than the flat list does.

A how-to title begins "How to". An explanation title reads naturally after an
implicit "About". Tutorial and reference titles carry no pattern.

`_templates/` holds the page templates and is not published. Directories whose
name begins with `_` are excluded from the build by convention.
```

Replace every `<slot>` before writing. This file is agent context rather than a
published page, so the no-`{` rule does not reach it — but an unfilled slot here
misinforms every agent that reads it, which is worse than a broken build.

## The `AGENTS.md` snippet

Always printed, never written — no skill in this collection writes that file.
Expand Down
Loading
Loading