diff --git a/.claude/skills/ai-diataxis-scaffold/SKILL.md b/.claude/skills/ai-diataxis-scaffold/SKILL.md index e542c35..1c05706 100644 --- a/.claude/skills/ai-diataxis-scaffold/SKILL.md +++ b/.claude/skills/ai-diataxis-scaffold/SKILL.md @@ -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 — + +(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 @@ -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 @@ -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. @@ -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: @@ -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 @@ -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 diff --git a/.claude/skills/ai-diataxis-scaffold/references/seeds.md b/.claude/skills/ai-diataxis-scaffold/references/seeds.md index 42faca4..cde5c7f 100644 --- a/.claude/skills/ai-diataxis-scaffold/references/seeds.md +++ b/.claude/skills/ai-diataxis-scaffold/references/seeds.md @@ -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 `` 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. @@ -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 `/index.md`. A shape to fill rather than a block to copy: +`` is the label the builder gave, and `` 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: "" +sidebar_label: "" +sidebar_position: 1 +--- + +# documentation + +For readers working on . 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 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 ``.** A finished page contains no `` 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 @@ -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 `- /` line per audience root from the interview answer. + +```markdown +# / + +Documentation content, partitioned first by **audience** and then by +[Diátaxis](https://diataxis.fr) mode — one directory per audience, four per audience. + +- / — for readers working on +- / — for readers working on + +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 `` 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. diff --git a/.claude/skills/ai-diataxis/SKILL.md b/.claude/skills/ai-diataxis/SKILL.md index 6572a8a..5727fb0 100644 --- a/.claude/skills/ai-diataxis/SKILL.md +++ b/.claude/skills/ai-diataxis/SKILL.md @@ -69,8 +69,21 @@ Read `.context/README.md` and resolve `docs_path` from its frontmatter: the Edit tool, and report that the interview will not repeat. Do not block if the user declines — proceed with the detected value for this run only. +**Read the placement convention unconditionally.** Separately from resolving +`docs_path`, read `dirname(docs_path)/CLAUDE.md` **by path** — and the project +root's `CLAUDE.md` when that is a different file. This is rank 3 of the audience +resolution ladder (reference §12.3), and it is **not** conditional on `docs_path` +being absent: a project can carry `docs_path` in its context file and record where +a new page goes only in prose, so a read that fires only on a missing `docs_path` +never consults the top-ranked signal. +`.claude/skills/ai-skills-reference/framework-detection.md` ranks this signal +first for that reason. Do not rely on either file being in ambient context. + Also read the project's Voice, Key Terms, Principles, and Constraints from -`.context/README.md` — CREATE applies them to every page it writes. +`.context/README.md` — CREATE applies them to every page it writes. Read its +`## Audiences` section too, if it has one (reference §12.2). **Absence is the +normal case and is not a warning** — a project that declares no audiences has one, +and the axis selects nothing there. ### The walk exclusion rule @@ -153,6 +166,37 @@ also wrong" the compass warns about. The gate always stops and asks. The request describes content that does not exist yet. Produce exactly one page, in exactly one mode directory. +### Step C0: Check which root the request belongs to + +**Run this before C1.** A request that should never become a published page must +not be classified either — classifying it assigns a mode, and a mode assignment is +what sends it into the tree. + +Reference §13 lists four documentation roots. This skill writes to exactly one of +them, the published docs tree. If the request names an artifact belonging to one +of the other three, **write no page** and report which skill owns it: + +| The request names | Owner | Root | +|---|---|---| +| how a feature, subsystem, or module was actually built | `/ai-as-built` | the working root | +| an architectural decision, or a record of one | `/ai-adr` | the decision log | +| agent context for a source directory — a `CLAUDE.md`, or a directory's own `README.md` | `/ai-context` | agent context, by proximity | +| research, a plan, a design, an outline, or a draft | the working-root pipeline — `/ai-research`, `/ai-architect`, `/ai-plan`, `/ai-outline`, `/ai-draft` | the working root | + +"Document how we built the release pipeline" is the case this step exists for. It +reads as a documentation request, resolves to no existing path, and therefore +reaches CREATE — where Mode Detection has already branched on path resolution +alone and nothing has yet asked which root it belongs to. Name `/ai-as-built` and +stop. + +**One test, so this step does not swallow legitimate work.** A request for a page +*about* one of these things is still a page request: "explain why we keep a +decision log" is an explanation page, not a decision record. The discriminator is +whether the request asks for **the artifact itself** or for **a page addressed to +a reader who came to the site.** When it reads as both, ask with +`AskUserQuestion`, offering the two readings — the same posture Mode Detection +takes on an ambiguous argument. + ### Step C1: Classify the request Run **Shared: Classify** on the request text. @@ -164,13 +208,53 @@ caching works and show me how to configure it" (cognition/acquisition + action/application) — stops here and proposes two cross-linked pages. Write nothing until the user confirms. +### Step C2b: Resolve the audience + +**After the gate and before placement.** It cannot live in Mode Detection, which +resolves `$ARGUMENTS` against `docs_path` first and would then be reading the same +argument twice for two different purposes. + +1. Work down the **five-rank ladder** in reference §12.3, stopping at the first + rank that decides: the request's own words (matched by *position* — `for the +